[web] Scaffold staff app (#1314)
This commit is contained in:
commit
2f5abb6318
26 changed files with 256 additions and 26 deletions
2
.github/workflows/web-deploy-accounts.yml
vendored
2
.github/workflows/web-deploy-accounts.yml
vendored
|
@ -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
|
||||
|
|
2
.github/workflows/web-deploy-auth.yml
vendored
2
.github/workflows/web-deploy-auth.yml
vendored
|
@ -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
|
||||
|
|
2
.github/workflows/web-deploy-cast.yml
vendored
2
.github/workflows/web-deploy-cast.yml
vendored
|
@ -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
|
||||
|
|
2
.github/workflows/web-deploy-payments.yml
vendored
2
.github/workflows/web-deploy-payments.yml
vendored
|
@ -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
|
||||
|
|
2
.github/workflows/web-deploy-photos.yml
vendored
2
.github/workflows/web-deploy-photos.yml
vendored
|
@ -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
48
.github/workflows/web-deploy-staff.yml
vendored
Normal 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"
|
2
.github/workflows/web-nightly.yml
vendored
2
.github/workflows/web-nightly.yml
vendored
|
@ -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
.github/workflows/web-preview.yml
vendored
2
.github/workflows/web-preview.yml
vendored
|
@ -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,3 +1,5 @@
|
|||
# Payments
|
||||
|
||||
Code that runs on `payments.ente.io`. It brokers between our services and
|
||||
Stripe's API for payments.
|
||||
|
||||
|
|
3
web/apps/staff/.eslintrc.cjs
Normal file
3
web/apps/staff/.eslintrc.cjs
Normal file
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
extends: ["@/build-config/eslintrc-vite"],
|
||||
};
|
8
web/apps/staff/README.md
Normal file
8
web/apps/staff/README.md
Normal 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
12
web/apps/staff/index.html
Normal 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>
|
22
web/apps/staff/package.json
Normal file
22
web/apps/staff/package.json
Normal 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"
|
||||
}
|
||||
}
|
11
web/apps/staff/src/App.tsx
Normal file
11
web/apps/staff/src/App.tsx
Normal 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>
|
||||
);
|
||||
};
|
5
web/apps/staff/src/components/Container.tsx
Normal file
5
web/apps/staff/src/components/Container.tsx
Normal file
|
@ -0,0 +1,5 @@
|
|||
import React from "react";
|
||||
|
||||
export const Container: React.FC<React.PropsWithChildren> = ({ children }) => (
|
||||
<div className="container">{children}</div>
|
||||
);
|
13
web/apps/staff/src/main.tsx
Normal file
13
web/apps/staff/src/main.tsx
Normal 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>,
|
||||
);
|
17
web/apps/staff/src/services/support-service.ts
Normal file
17
web/apps/staff/src/services/support-service.ts
Normal 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)}`);
|
||||
};
|
38
web/apps/staff/src/styles/globals.css
Normal file
38
web/apps/staff/src/styles/globals.css
Normal 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;
|
||||
}
|
||||
}
|
13
web/apps/staff/src/utils/strings.ts
Normal file
13
web/apps/staff/src/utils/strings.ts
Normal 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
18
web/apps/staff/src/vite-env.d.ts
vendored
Normal 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;
|
||||
}
|
5
web/apps/staff/tsconfig.json
Normal file
5
web/apps/staff/tsconfig.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"extends": "@/build-config/tsconfig-vite.json",
|
||||
"include": ["src"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
4
web/apps/staff/tsconfig.node.json
Normal file
4
web/apps/staff/tsconfig.node.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"extends": "@/build-config/tsconfig-vite.node.json",
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
7
web/apps/staff/vite.config.ts
Normal file
7
web/apps/staff/vite.config.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import react from "@vitejs/plugin-react";
|
||||
import { defineConfig } from "vite";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
});
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,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"],
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue