Skip to content

Commit 3e7ee42

Browse files
authored
feat: open source main app (#2)
1 parent 95d9d6d commit 3e7ee42

38 files changed

Lines changed: 14731 additions & 4 deletions

.github/workflows/ci.yml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,18 @@ on:
88

99
jobs:
1010
test:
11-
name: Test and Lint
11+
name: Test and Build
1212
runs-on: ubuntu-latest
1313

1414
steps:
1515
- name: Checkout repository
1616
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
1717

18+
- name: Setup Node
19+
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
20+
with:
21+
node-version: 24.x
22+
1823
- name: Setup Bun
1924
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
2025
with:
@@ -26,8 +31,11 @@ jobs:
2631
- name: Lint code
2732
run: bun run lint
2833

29-
- name: Build userscript (test)
34+
- name: Run tests
35+
run: bun run test
36+
37+
- name: Build userscript
3038
run: bun run build:userscript
3139

32-
- name: Build apps (test)
40+
- name: Build apps
3341
run: bun run build:apps

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ dist/
44

55
.astro/
66
.wrangler/
7+
8+
.env

apps/icbe/README.md

Whitespace-only changes.

apps/icbe/astro.config.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import cloudflare from "@astrojs/cloudflare";
2+
import solid from "@astrojs/solid-js";
3+
import tailwindcss from "@tailwindcss/vite";
4+
import { defineConfig, envField } from "astro/config";
5+
6+
export default defineConfig({
7+
output: "server",
8+
adapter: cloudflare(),
9+
integrations: [solid()],
10+
vite: { plugins: [tailwindcss()] },
11+
site: "https://icbe.rman.dev",
12+
13+
env: {
14+
schema: {
15+
GITLAB_ACCESS_TOKEN: envField.string({
16+
context: "server",
17+
access: "secret",
18+
startsWith: "glpat",
19+
length: 26,
20+
}),
21+
GITLAB_PROJECT_ID: envField.number({
22+
context: "server",
23+
access: "secret",
24+
int: true,
25+
gt: 1,
26+
}),
27+
},
28+
},
29+
});

apps/icbe/package.json

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,28 @@
22
"name": "web-app",
33
"type": "module",
44
"private": true,
5+
"imports": {
6+
"#styles": "./src/styles/global.css",
7+
"#layout": "./src/layouts/Layout.astro",
8+
"#schemas": "./src/schemas/index.ts",
9+
"#utils/*": "./src/utils/*.ts",
10+
"#components/*": "./src/components/*.tsx"
11+
},
512
"scripts": {
13+
"typegen": "wrangler types ./src/worker-configuration.d.ts",
14+
"test": "bun test",
615
"build": "astro build",
716
"deploy": "wrangler deploy",
817
"dev": "astro dev"
918
},
1019
"dependencies": {
11-
"astro": "catalog:"
20+
"@astrojs/cloudflare": "^13.1.3",
21+
"@astrojs/solid-js": "^6.0.1",
22+
"@gitbeaker/rest": "^43.8.0",
23+
"@tailwindcss/vite": "catalog:",
24+
"astro": "catalog:",
25+
"solid-js": "^1.9.11",
26+
"tailwindcss": "catalog:"
1227
},
1328
"devDependencies": {
1429
"wrangler": "catalog:"

apps/icbe/public/.assetsignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_worker.js
2+
_routes.json

apps/icbe/src/actions/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import {
2+
submitDisprovenElements,
3+
submitProvenElements,
4+
} from "./submit-elements";
5+
6+
export const server = {
7+
elements: { submitDisprovenElements, submitProvenElements },
8+
};
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { ActionError, defineAction } from "astro:actions";
2+
import * as z from "astro/zod";
3+
import { DataProvenSchema } from "#schemas";
4+
import { saveToCloud } from "#utils/gitlab";
5+
import { getDisprovenToSave, getProvenToSave } from "#utils/submit-elements";
6+
7+
const submitDisprovenElements = defineAction({
8+
input: z.object({ elements: z.array(z.object({ name: z.string() })) }),
9+
async handler(input, context) {
10+
const role = null;
11+
12+
if (!role) {
13+
throw new ActionError({
14+
code: "UNAUTHORIZED",
15+
message: "Please login to use this feature.",
16+
});
17+
}
18+
19+
const canSubmitElements = false;
20+
21+
if (!canSubmitElements) {
22+
throw new ActionError({
23+
code: "FORBIDDEN",
24+
message: "You don't have permissions to use this feature.",
25+
});
26+
}
27+
28+
const elements = input.elements.map((element) => element.name);
29+
30+
const data = await getDisprovenToSave(elements);
31+
await saveToCloud(data);
32+
33+
return { success: true } as const;
34+
},
35+
});
36+
37+
const submitProvenElements = defineAction({
38+
input: z.object({ elements: DataProvenSchema }),
39+
handler: async (input, context) => {
40+
const role = null;
41+
42+
if (!role) {
43+
throw new ActionError({
44+
code: "UNAUTHORIZED",
45+
message: "Please login to use this feature.",
46+
});
47+
}
48+
49+
const canSubmitElements = false;
50+
51+
if (!canSubmitElements) {
52+
throw new ActionError({
53+
code: "FORBIDDEN",
54+
message: "You don't have permissions to use this feature.",
55+
});
56+
}
57+
58+
const data = await getProvenToSave(input.elements);
59+
await saveToCloud(data);
60+
61+
return { success: true } as const;
62+
},
63+
});
64+
65+
export { submitDisprovenElements, submitProvenElements };
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { JSX } from "solid-js";
2+
3+
export default function AdminDashboard(): JSX.Element {
4+
return (
5+
<div class="p-6 min-h-screen flex flex-col">
6+
<h2 class="text-2xl font-bold mb-6 text-neutral-800 dark:text-neutral-100">
7+
Admin Controls
8+
</h2>
9+
</div>
10+
);
11+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { type JSX, Show } from "solid-js";
2+
3+
import SubmitDisprovenElementsSection from "./dashboard/SubmitDisprovenElementsSection";
4+
import SubmitProvenElementsSection from "./dashboard/SubmitProvenElementsSection";
5+
import Divider from "./ui/Divider";
6+
import Link from "./ui/Link";
7+
8+
const TopBar = (): JSX.Element => (
9+
<div class="flex items-center justify-between pb-4">
10+
<h1 class="text-2xl font-bold text-neutral-800 dark:text-neutral-100">
11+
User Dashboard
12+
</h1>
13+
</div>
14+
);
15+
16+
export default function UserDashboard(props: {
17+
canSubmitElements: boolean;
18+
}): JSX.Element {
19+
const isAdmin = false;
20+
21+
return (
22+
<div class="p-6 min-h-screen flex flex-col">
23+
<TopBar />
24+
<Show when={isAdmin}>
25+
<Divider />
26+
<Link
27+
href="/admin/dashboard"
28+
color="blue"
29+
label="Open Admin Dashboard"
30+
/>
31+
</Show>
32+
<Show when={props.canSubmitElements}>
33+
<Divider />
34+
<SubmitDisprovenElementsSection />
35+
<Divider />
36+
<SubmitProvenElementsSection />
37+
</Show>
38+
</div>
39+
);
40+
}

0 commit comments

Comments
 (0)