瀏覽代碼

[web] Scaffold staff app (#1314)

Manav Rathi 1 年之前
父節點
當前提交
2f5abb6318

+ 1 - 1
.github/workflows/web-deploy-accounts.yml

@@ -24,7 +24,7 @@ jobs:
               with:
                   node-version: 20
                   cache: "yarn"
-                  cache-dependency-path: "docs/yarn.lock"
+                  cache-dependency-path: "web/yarn.lock"
 
             - name: Install dependencies
               run: yarn install

+ 1 - 1
.github/workflows/web-deploy-auth.yml

@@ -24,7 +24,7 @@ jobs:
               with:
                   node-version: 20
                   cache: "yarn"
-                  cache-dependency-path: "docs/yarn.lock"
+                  cache-dependency-path: "web/yarn.lock"
 
             - name: Install dependencies
               run: yarn install

+ 1 - 1
.github/workflows/web-deploy-cast.yml

@@ -24,7 +24,7 @@ jobs:
               with:
                   node-version: 20
                   cache: "yarn"
-                  cache-dependency-path: "docs/yarn.lock"
+                  cache-dependency-path: "web/yarn.lock"
 
             - name: Install dependencies
               run: yarn install

+ 1 - 1
.github/workflows/web-deploy-payments.yml

@@ -24,7 +24,7 @@ jobs:
               with:
                   node-version: 20
                   cache: "yarn"
-                  cache-dependency-path: "docs/yarn.lock"
+                  cache-dependency-path: "web/yarn.lock"
 
             - name: Install dependencies
               run: yarn install

+ 1 - 1
.github/workflows/web-deploy-photos.yml

@@ -24,7 +24,7 @@ jobs:
               with:
                   node-version: 20
                   cache: "yarn"
-                  cache-dependency-path: "docs/yarn.lock"
+                  cache-dependency-path: "web/yarn.lock"
 
             - name: Install dependencies
               run: yarn install

+ 48 - 0
.github/workflows/web-deploy-staff.yml

@@ -0,0 +1,48 @@
+name: "Deploy (staff)"
+
+on:
+    # Run on every push to main that changes web/apps/staff/
+    push:
+        branches: [main]
+        paths:
+            - "web/apps/staff/**"
+            - ".github/workflows/web-deploy-staff.yml"
+    # Also allow manually running the workflow
+    workflow_dispatch:
+
+jobs:
+    deploy:
+        runs-on: ubuntu-latest
+
+        defaults:
+            run:
+                working-directory: web
+
+        steps:
+            - name: Checkout code
+              uses: actions/checkout@v4
+              with:
+                  submodules: recursive
+
+            - name: Setup node and enable yarn caching
+              uses: actions/setup-node@v4
+              with:
+                  node-version: 20
+                  cache: "yarn"
+                  cache-dependency-path: "web/yarn.lock"
+
+            - name: Install dependencies
+              run: yarn install
+
+            - name: Build staff
+              run: yarn build:staff
+
+            - name: Publish staff
+              uses: cloudflare/pages-action@1
+              with:
+                  accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
+                  apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
+                  projectName: ente
+                  branch: deploy/staff
+                  directory: web/apps/staff/dist
+                  wranglerVersion: "3"

+ 1 - 1
.github/workflows/web-nightly.yml

@@ -34,7 +34,7 @@ jobs:
               with:
                   node-version: 20
                   cache: "yarn"
-                  cache-dependency-path: "docs/yarn.lock"
+                  cache-dependency-path: "web/yarn.lock"
 
             - name: Install dependencies
               run: yarn install

+ 1 - 1
.github/workflows/web-preview.yml

@@ -34,7 +34,7 @@ jobs:
               with:
                   node-version: 20
                   cache: "yarn"
-                  cache-dependency-path: "docs/yarn.lock"
+                  cache-dependency-path: "web/yarn.lock"
 
             - name: Install dependencies
               run: yarn install

+ 2 - 0
web/apps/payments/README.md

@@ -1,3 +1,5 @@
+# Payments
+
 Code that runs on `payments.ente.io`. It brokers between our services and
 Stripe's API for payments.
 

+ 3 - 0
web/apps/staff/.eslintrc.cjs

@@ -0,0 +1,3 @@
+module.exports = {
+    extends: ["@/build-config/eslintrc-vite"],
+};

+ 8 - 0
web/apps/staff/README.md

@@ -0,0 +1,8 @@
+## Staff dashboard
+
+Web app for staff members to help with support etc.
+
+### Deployment
+
+The app gets redeployed whenever a PR is merged into main. See
+[docs/deploy.md](../../docs/deploy.md) for more details.

+ 12 - 0
web/apps/staff/index.html

@@ -0,0 +1,12 @@
+<!doctype html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8" />
+        <meta name="viewport" content="width=device-width" />
+        <title>Staff | ente.io</title>
+    </head>
+    <body>
+        <div id="root"></div>
+        <script type="module" src="/src/main.tsx"></script>
+    </body>
+</html>

+ 22 - 0
web/apps/staff/package.json

@@ -0,0 +1,22 @@
+{
+    "name": "staff",
+    "version": "0.0.0",
+    "private": true,
+    "type": "module",
+    "scripts": {
+        "build": "tsc && vite build",
+        "dev": "vite",
+        "preview": "vite preview"
+    },
+    "dependencies": {
+        "react": "^18",
+        "react-dom": "^18"
+    },
+    "devDependencies": {
+        "@/build-config": "*",
+        "@types/react": "^18",
+        "@types/react-dom": "^18",
+        "@vitejs/plugin-react": "^4.2",
+        "vite": "^5.2"
+    }
+}

+ 11 - 0
web/apps/staff/src/App.tsx

@@ -0,0 +1,11 @@
+import React from "react";
+import S from "./utils/strings";
+
+export const App: React.FC = () => {
+    return (
+        <div>
+            <h1>{S.hello}</h1>
+            <a href="https://help.ente.io">help.ente.io</a>
+        </div>
+    );
+};

+ 5 - 0
web/apps/staff/src/components/Container.tsx

@@ -0,0 +1,5 @@
+import React from "react";
+
+export const Container: React.FC<React.PropsWithChildren> = ({ children }) => (
+    <div className="container">{children}</div>
+);

+ 13 - 0
web/apps/staff/src/main.tsx

@@ -0,0 +1,13 @@
+import React from "react";
+import ReactDOM from "react-dom/client";
+import { App } from "./App";
+import "./styles/globals.css";
+
+const root = document.getElementById("root");
+if (!root) throw new Error("Could not load root element to render onto");
+
+ReactDOM.createRoot(root).render(
+    <React.StrictMode>
+        <App />
+    </React.StrictMode>,
+);

+ 17 - 0
web/apps/staff/src/services/support-service.ts

@@ -0,0 +1,17 @@
+const apiOrigin = import.meta.env.VITE_ENTE_ENDPOINT ?? "https://api.ente.io";
+
+/** Fetch details of the user associated with the given {@link authToken}. */
+export const getUserDetails = async (authToken: string) => {
+    const url = `${apiOrigin}/users/details/v2`;
+    const res = await fetch(url, {
+        headers: {
+            "X-Auth-Token": authToken,
+        },
+    });
+    if (!res.ok) throw new Error(`Failed to fetch ${url}: HTTP ${res.status}`);
+    const json: unknown = await res.json();
+    if (json && typeof json === "object") {
+        return json;
+    }
+    throw new Error(`Unexpected response for ${url}: ${JSON.stringify(json)}`);
+};

+ 38 - 0
web/apps/staff/src/styles/globals.css

@@ -0,0 +1,38 @@
+:root {
+    color-scheme: light dark;
+    color: #213547;
+    background-color: #ffffff;
+}
+
+body {
+    font-family: system-ui, sans-serif;
+
+    margin: 0;
+    display: flex;
+    justify-content: center;
+    text-align: center;
+    min-height: 100svh;
+}
+
+a {
+    color: green;
+}
+
+a:hover {
+    color: darkgreen;
+}
+
+@media (prefers-color-scheme: dark) {
+    :root {
+        color: rgba(255, 255, 255, 0.87);
+        background-color: #242424;
+    }
+
+    a {
+        color: lightgreen;
+    }
+
+    a:hover {
+        color: chartreuse;
+    }
+}

+ 13 - 0
web/apps/staff/src/utils/strings.ts

@@ -0,0 +1,13 @@
+/**
+ * User facing strings in the app.
+ *
+ * By keeping them separate, we make our lives easier if/when we need to
+ * localize the corresponding pages. Right now, these are just the values in the
+ * default language, English.
+ */
+const S = {
+    hello: "Hello Ente!",
+    error_generic: "Oops, something went wrong.",
+};
+
+export default S;

+ 18 - 0
web/apps/staff/src/vite-env.d.ts

@@ -0,0 +1,18 @@
+/* Type shims provided by vite, e.g. for asset imports
+   https://vitejs.dev/guide/features.html#client-types */
+
+/// <reference types="vite/client" />
+
+/** Types for the vite injected environment variables */
+interface ImportMetaEnv {
+    /**
+     * Override the origin (scheme://host:port) of Ente's API to connect to.
+     *
+     * This is useful when testing or connecting to alternative installations.
+     */
+    readonly VITE_ENTE_ENDPOINT: string | undefined;
+}
+
+interface ImportMeta {
+    env: ImportMetaEnv;
+}

+ 5 - 0
web/apps/staff/tsconfig.json

@@ -0,0 +1,5 @@
+{
+    "extends": "@/build-config/tsconfig-vite.json",
+    "include": ["src"],
+    "references": [{ "path": "./tsconfig.node.json" }]
+}

+ 4 - 0
web/apps/staff/tsconfig.node.json

@@ -0,0 +1,4 @@
+{
+    "extends": "@/build-config/tsconfig-vite.node.json",
+    "include": ["vite.config.ts"]
+}

+ 7 - 0
web/apps/staff/vite.config.ts

@@ -0,0 +1,7 @@
+import react from "@vitejs/plugin-react";
+import { defineConfig } from "vite";
+
+// https://vitejs.dev/config/
+export default defineConfig({
+    plugins: [react()],
+});

+ 18 - 17
web/docs/deploy.md

@@ -29,21 +29,22 @@ and publish to [web.ente.io](https://web.ente.io).
 Here is a list of all the deployments, whether or not they are production
 deployments, and the action that triggers them:
 
-| URL                                          | Type       | Deployment action                           |
-| -------------------------------------------- | ---------- | ------------------------------------------- |
-| [web.ente.io](https://web.ente.io)           | Production | Push to `deploy/photos`                     |
-| [photos.ente.io](https://photos.ente.io)     | Production | Alias of [web.ente.io](https://web.ente.io) |
-| [auth.ente.io](https://auth.ente.io)         | Production | Push to `deploy/auth`                       |
-| [accounts.ente.io](https://accounts.ente.io) | Production | Push to `deploy/accounts`                   |
-| [cast.ente.io](https://cast.ente.io)         | Production | Push to `deploy/cast`                       |
-| [payments.ente.io](https://payments.ente.io) | Production | Push to `deploy/payments`                   |
-| [help.ente.io](https://help.ente.io)         | Production | Push to `main` + changes in `docs/`         |
-| [accounts.ente.sh](https://accounts.ente.sh) | Preview    | Nightly deploy of `main`                    |
-| [auth.ente.sh](https://auth.ente.sh)         | Preview    | Nightly deploy of `main`                    |
-| [cast.ente.sh](https://cast.ente.sh)         | Preview    | Nightly deploy of `main`                    |
-| [payments.ente.sh](https://payments.ente.sh) | Preview    | Nightly deploy of `main`                    |
-| [photos.ente.sh](https://photos.ente.sh)     | Preview    | Nightly deploy of `main`                    |
-| [preview.ente.sh](https://preview.ente.sh)   | Preview    | Manually triggered                          |
+| URL                                          | Type       | Deployment action                            |
+| -------------------------------------------- | ---------- | -------------------------------------------- |
+| [web.ente.io](https://web.ente.io)           | Production | Push to `deploy/photos`                      |
+| [photos.ente.io](https://photos.ente.io)     | Production | Alias of [web.ente.io](https://web.ente.io)  |
+| [auth.ente.io](https://auth.ente.io)         | Production | Push to `deploy/auth`                        |
+| [accounts.ente.io](https://accounts.ente.io) | Production | Push to `deploy/accounts`                    |
+| [cast.ente.io](https://cast.ente.io)         | Production | Push to `deploy/cast`                        |
+| [payments.ente.io](https://payments.ente.io) | Production | Push to `deploy/payments`                    |
+| [help.ente.io](https://help.ente.io)         | Production | Push to `main` + changes in `docs/`          |
+| [staff.ente.sh](https://staff.ente.sh)       | Production | Push to `main` + changes in `web/apps/staff` |
+| [accounts.ente.sh](https://accounts.ente.sh) | Preview    | Nightly deploy of `main`                     |
+| [auth.ente.sh](https://auth.ente.sh)         | Preview    | Nightly deploy of `main`                     |
+| [cast.ente.sh](https://cast.ente.sh)         | Preview    | Nightly deploy of `main`                     |
+| [payments.ente.sh](https://payments.ente.sh) | Preview    | Nightly deploy of `main`                     |
+| [photos.ente.sh](https://photos.ente.sh)     | Preview    | Nightly deploy of `main`                     |
+| [preview.ente.sh](https://preview.ente.sh)   | Preview    | Manually triggered                           |
 
 ### Other subdomains
 
@@ -54,8 +55,8 @@ Apart from this, there are also some other deployments:
     `albums.ente.io`, it redirects to the `/shared-albums` page (Enhancement:
     serve it as a separate app with a smaller bundle size).
 
--   `family.ente.io` is currently in a separate repositories (Enhancement: bring
-    them in here).
+-   `family.ente.io` is currently in a separate repository (Enhancement: bring
+    it in here).
 
 ### Preview deployments
 

+ 4 - 1
web/package.json

@@ -13,6 +13,7 @@
         "build:cast": "yarn workspace cast next build",
         "build:payments": "yarn workspace payments build",
         "build:photos": "yarn workspace photos next build",
+        "build:staff": "yarn workspace staff build",
         "deploy:accounts": "open 'https://github.com/ente-io/ente/compare/deploy/accounts...main?quick_pull=1&title=[web]+Deploy+accounts&body=Deploy+accounts.ente.io'",
         "deploy:auth": "open 'https://github.com/ente-io/ente/compare/deploy/auth...main?quick_pull=1&title=[web]+Deploy+auth&body=Deploy+auth.ente.io'",
         "deploy:cast": "open 'https://github.com/ente-io/ente/compare/deploy/cast...main?quick_pull=1&title=[web]+Deploy+cast&body=Deploy+cast.ente.io'",
@@ -25,6 +26,7 @@
         "dev:cast": "yarn workspace cast next dev -p 3001",
         "dev:payments": "yarn workspace payments dev",
         "dev:photos": "yarn workspace photos next dev",
+        "dev:staff": "yarn workspace staff dev",
         "lint": "yarn prettier --check . && yarn workspaces run eslint --report-unused-disable-directives",
         "lint-fix": "yarn prettier --write . && yarn workspaces run eslint --fix .",
         "preview": "yarn preview:photos",
@@ -32,7 +34,8 @@
         "preview:auth": "yarn build:auth && python3 -m http.server -d apps/auth/out 3000",
         "preview:cast": "yarn build:cast && python3 -m http.server -d apps/accounts/out 3001",
         "preview:payments": "yarn workspace payments preview",
-        "preview:photos": "yarn build:photos && python3 -m http.server -d apps/photos/out 3000"
+        "preview:photos": "yarn build:photos && python3 -m http.server -d apps/photos/out 3000",
+        "preview:staff": "yarn workspace staff preview"
     },
     "resolutions": {
         "libsodium": "0.7.9"

+ 1 - 1
web/packages/build-config/eslintrc-vite.js

@@ -1,5 +1,5 @@
 /* eslint-env node */
 module.exports = {
-    extends: ["./eslintrc-react.js"],
+    extends: ["./eslintrc-react.js", "plugin:react/jsx-runtime"],
     ignorePatterns: [".eslintrc.cjs", "vite.config.ts", "dist"],
 };