1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-11-20 12:02:22 +03:00

Bootstrap the frontend

This commit is contained in:
Quentin Gliech
2022-11-09 18:59:39 +01:00
parent 7123b51e80
commit 815afb4535
17 changed files with 12253 additions and 0 deletions

26
frontend/.eslintrc.cjs Normal file
View File

@@ -0,0 +1,26 @@
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/** @type {import('eslint').Linter.Config} */
module.exports = {
extends: [
"react-app",
"react-app/jest",
"prettier",
"plugin:prettier/recommended",
"plugin:jsx-a11y/recommended",
],
plugins: ["jsx-a11y"],
};

2
frontend/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/node_modules
/dist

32
frontend/index.html Normal file
View File

@@ -0,0 +1,32 @@
<!--
Copyright 2022 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/src/index.css" />
<title>matrix-authentication-service</title>
</head>
<body class="bg-white text-black-900 dark:bg-black-800 dark:text-white flex flex-col min-h-screen">
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

11730
frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

40
frontend/package.json Normal file
View File

@@ -0,0 +1,40 @@
{
"name": "mas-frontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"lint": "eslint src/ .eslintrc.cjs tailwind.config.cjs vite.config.ts",
"relay": "relay-compiler",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-relay": "^14.1.0",
"relay-runtime": "^14.1.0"
},
"devDependencies": {
"@types/node": "^18.11.9",
"@types/react": "^18.0.25",
"@types/react-dom": "^18.0.8",
"@types/react-relay": "^14.1.2",
"@types/relay-runtime": "^14.1.4",
"@vitejs/plugin-react": "^2.2.0",
"autoprefixer": "^10.4.13",
"eslint": "^8.27.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-prettier": "^4.2.1",
"postcss": "^8.4.18",
"prettier": "^2.7.1",
"relay-compiler": "^14.1.0",
"tailwindcss": "^3.2.2",
"typescript": "^4.6.4",
"vite": "^3.2.3",
"vite-plugin-eslint": "^1.8.1",
"vite-plugin-relay": "^2.0.0"
}
}

View File

@@ -0,0 +1,19 @@
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/** @type {import('postcss-load-config').Config */
module.exports = {
plugins: [require("tailwindcss"), require("autoprefixer")],
};

View File

@@ -0,0 +1,11 @@
{
"src": "./src",
"schema": "../crates/graphql/schema.graphql",
"language": "typescript",
"eagerEsModules": true,
"exclude": [
"**/node_modules/**",
"**/__mocks__/**",
"**/__generated__/**"
]
}

39
frontend/src/App.tsx Normal file
View File

@@ -0,0 +1,39 @@
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import React from "react";
import { graphql, useLazyLoadQuery } from "react-relay";
import type { AppQuery } from "./__generated__/AppQuery.graphql";
export const App: React.FC = () => {
const data = useLazyLoadQuery<AppQuery>(
graphql`
query AppQuery {
currentUser {
username
}
}
`,
{}
);
if (data.currentUser) {
return (
<h1 className="font-bold text-2xl">Hello {data.currentUser.username}!</h1>
);
} else {
return <div className="font-bold text-alert">You're not logged in.</div>;
}
};

View File

@@ -0,0 +1,72 @@
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {
Environment,
Network,
RecordSource,
Store,
Variables,
RequestParameters,
CacheConfig,
} from "relay-runtime";
async function fetchRelay(
params: RequestParameters,
variables: Variables,
_cacheConfig: CacheConfig
) {
const response = await fetch("/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query: params.text,
variables,
}),
});
// Get the response as JSON
const json = await response.json();
// GraphQL returns exceptions (for example, a missing required variable) in the "errors"
// property of the response. If any exceptions occurred when processing the request,
// throw an error to indicate to the developer what went wrong.
if (Array.isArray(json.errors)) {
console.log(json.errors);
throw new Error(
`Error fetching GraphQL query '${
params.name
}' with variables '${JSON.stringify(variables)}': ${JSON.stringify(
json.errors
)}`
);
}
// Otherwise, return the full payload.
return json;
}
// Export a singleton instance of Relay Environment configured with our network layer:
export default new Environment({
network: Network.create(fetchRelay),
store: new Store(new RecordSource(), {
// This property tells Relay to not immediately clear its cache when the user
// navigates around the app. Relay will hold onto the specified number of
// query results, allowing the user to return to recently visited pages
// and reusing cached data if its available/fresh.
gcReleaseBufferSize: 10,
}),
});

View File

@@ -0,0 +1,94 @@
/**
* @generated SignedSource<<85f26fc928e25f5adee1aa4bdb35943f>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest, Query } from 'relay-runtime';
export type AppQuery$variables = {};
export type AppQuery$data = {
readonly currentUser: {
readonly username: string;
} | null;
};
export type AppQuery = {
response: AppQuery$data;
variables: AppQuery$variables;
};
const node: ConcreteRequest = (function(){
var v0 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "username",
"storageKey": null
};
return {
"fragment": {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "AppQuery",
"selections": [
{
"alias": null,
"args": null,
"concreteType": "User",
"kind": "LinkedField",
"name": "currentUser",
"plural": false,
"selections": [
(v0/*: any*/)
],
"storageKey": null
}
],
"type": "RootQuery",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": [],
"kind": "Operation",
"name": "AppQuery",
"selections": [
{
"alias": null,
"args": null,
"concreteType": "User",
"kind": "LinkedField",
"name": "currentUser",
"plural": false,
"selections": [
(v0/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "84b2b5650a0c71cce7c40242b378e52f",
"id": null,
"metadata": {},
"name": "AppQuery",
"operationKind": "query",
"text": "query AppQuery {\n currentUser {\n username\n id\n }\n}\n"
}
};
})();
(node as any).hash = "fef45d7542db63ccb8b3d59ca5dc6afb";
export default node;

18
frontend/src/index.css Normal file
View File

@@ -0,0 +1,18 @@
/* Copyright 2022 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@tailwind base;
@tailwind components;
@tailwind utilities;

30
frontend/src/main.tsx Normal file
View File

@@ -0,0 +1,30 @@
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import React from "react";
import ReactDOM from "react-dom/client";
import { RelayEnvironmentProvider } from "react-relay";
import { App } from "./App";
import RelayEnvironment from "./RelayEnvironment";
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode>
<RelayEnvironmentProvider environment={RelayEnvironment}>
<React.Suspense fallback={"Loading..."}>
<App />
</React.Suspense>
</RelayEnvironmentProvider>
</React.StrictMode>
);

19
frontend/src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1,19 @@
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// <reference types="vite/client" />
declare module "babel-plugin-relay/macro" {
export { graphql as default } from "react-relay";
}

View File

@@ -0,0 +1,46 @@
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/** @type {import('tailwindcss').Config} */
module.exports = {
mode: "jit",
content: ["./src/**/*.tsx", "./index.html"],
theme: {
extend: {
colors: {
accent: "#0DBD8B",
alert: "#FF5B55",
links: "#0086E6",
"grey-25": "#F4F6FA",
"grey-50": "#E3E8F0",
"grey-100": "#C1C6CD",
"grey-150": "#8D97A5",
"grey-200": "#737D8C",
"grey-250": "#A9B2BC",
"grey-300": "#8E99A4",
"grey-400": "#6F7882",
"grey-450": "#394049",
"black-800": "#15191E",
"black-900": "#17191C",
"black-950": "#21262C",
ice: "#F4F9FD",
},
},
},
variants: {
extend: {},
},
plugins: [],
};

31
frontend/tsconfig.json Normal file
View File

@@ -0,0 +1,31 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": [
"DOM",
"DOM.Iterable",
"ESNext"
],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
],
"references": [
{
"path": "./tsconfig.node.json"
}
]
}

View File

@@ -0,0 +1,14 @@
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true,
"allowJs": true
},
"include": [
"vite.config.ts",
".eslintrc.cjs",
"tailwind.config.cjs"
]
}

30
frontend/vite.config.ts Normal file
View File

@@ -0,0 +1,30 @@
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { defineConfig } from "vite";
import eslint from "vite-plugin-eslint";
import react from "@vitejs/plugin-react";
import relay from "vite-plugin-relay";
export default defineConfig({
base: "/app/",
plugins: [react(), eslint(), relay],
server: {
proxy: {
// Routes mostly extracted from crates/router/src/endpoints.rs
"^/(|graphql.*|assets.*|\\.well-known.*|oauth2.*|login.*|logout.*|register.*|reauth.*|account.*|consent.*|_matrix.*|complete-compat-sso.*)$":
"http://127.0.0.1:8080",
},
},
});