[web] Scaffold staff app (#1314)

This commit is contained in:
Manav Rathi 2024-04-04 15:50:10 +05:30 committed by GitHub
commit 2f5abb6318
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 256 additions and 26 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
.github/workflows/web-deploy-staff.yml vendored Normal file
View file

@ -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"

View file

@ -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

View file

@ -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

View file

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

View file

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

8
web/apps/staff/README.md Normal file
View file

@ -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
web/apps/staff/index.html Normal file
View file

@ -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>

View file

@ -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"
}
}

View file

@ -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>
);
};

View file

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

View file

@ -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>,
);

View file

@ -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)}`);
};

View file

@ -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;
}
}

View file

@ -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
web/apps/staff/src/vite-env.d.ts vendored Normal file
View file

@ -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;
}

View file

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

View file

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

View file

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

View file

@ -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

View file

@ -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"

View file

@ -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"],
};