From 6cbebd4781e420231fd070d1e12582a916effd98 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Wed, 8 Jul 2026 11:46:23 +0200 Subject: [PATCH 1/5] Move theme.ts to use JQuery Signed-off-by: Stefan Marr --- src/frontend/theme.ts | 47 +++++++++++++------------------------------ 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/src/frontend/theme.ts b/src/frontend/theme.ts index 65d276b8..cdff8e5c 100644 --- a/src/frontend/theme.ts +++ b/src/frontend/theme.ts @@ -29,44 +29,31 @@ function getPreferredTheme(): string { } function setTheme(theme: string) { - document.documentElement.setAttribute('data-bs-theme', theme); + $('html').attr('data-bs-theme', theme); } function showActiveTheme(theme: string) { - const themeSwitcher = document.querySelector('#theme-switcher'); - - if (!themeSwitcher) { - return; - } - - const themeIcons = document.querySelectorAll('.theme-icon'); - for (const themeIcon of themeIcons) { - themeIcon.classList.remove('active'); - } - - const iconToActivate = document.querySelector(`#theme-icon-${theme}`); - - if (!iconToActivate) { + const themeSwitcher = $('#theme-switcher'); + if (themeSwitcher.length === 0) { return; } - iconToActivate.classList.add('active'); + $('.theme-icon').removeClass('active'); + $(`#theme-icon-${theme}`).addClass('active'); } function toggleTheme() { - const themeIcons = document.querySelectorAll('.theme-icon'); + const themeIcons = $('.theme-icon'); let currentTheme = getPreferredTheme(); // that's the fallback // let's see what the current user setting is - for (const themeIcon of themeIcons) { - if (themeIcon.classList.contains('active')) { - if (themeIcon.id === 'theme-icon-light') { - currentTheme = 'light'; - } else { - currentTheme = 'dark'; - } - break; + const activeThemeIcon = themeIcons.filter('.active').first(); + if (activeThemeIcon.length > 0) { + if (activeThemeIcon.attr('id') === 'theme-icon-light') { + currentTheme = 'light'; + } else { + currentTheme = 'dark'; } } @@ -89,14 +76,8 @@ function toggleTheme() { showActiveTheme(newTheme); }); - window.addEventListener('DOMContentLoaded', () => { + $(() => { showActiveTheme(getPreferredTheme()); - - const themeSwitcher = document.querySelector('#theme-switcher'); - if (!themeSwitcher) { - return; - } - - themeSwitcher.addEventListener('click', toggleTheme); + $('#theme-switcher').on('click', toggleTheme); }); })(); From a6f7aaf6afa6fb0d123480cb8beb054dfbfe9f25 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Wed, 8 Jul 2026 12:00:56 +0200 Subject: [PATCH 2/5] Document a bit the frontend development guidelines Signed-off-by: Stefan Marr --- docs/development/frontend.md | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 docs/development/frontend.md diff --git a/docs/development/frontend.md b/docs/development/frontend.md new file mode 100644 index 00000000..576fe102 --- /dev/null +++ b/docs/development/frontend.md @@ -0,0 +1,51 @@ +# Frontend + +The frontend, i.e., the code that runs in the browser, is implemented with a +somewhat "classic" approach, trying to be in some sense of the word "low tech", +while using mature/boring libraries to make this approach a bit more convenient. + +## TypeScript + +The frontend is implemented in TypeScript. +During development, the builtin server will serve the JS files directly +from the `/dist` folder, and `npm run nodemon` in combination with +`npm run watch` works as one would expect. + +See `/src/index.ts` where `serveStaticResource` is used, which is implemented +under `/src/backend/dev-server/server.ts`. + +When testing with Docker, the Dockerfile triggers `npm run compile`, +which ensures all files are in the expected place. + +## JQuery + +For the interaction with the DOM, we are generally using JQuery. +Thus, instead of using `document.querySelectorAll('#id')` or similar, +we use `$('#id')`. + +JQuery allows for fairly concise code. + +## Serve-Side Page Generation + +For each page, we decide ad hoc, whether the data is queried and rendered +on the server, or whether we add a JSON-based API endpoint, and +render the page in the browser. + +I am not sure, that there is a consistently applied design principle right now. +But, when ever we can do it on the server, without obvious drawbacks, it means +we do not need to expose raw data via JSON, and have an endpoint less that +we have to worry about. So, in some ways, that's preferred. + +However, some database queries are known to take more time. For these cases, +requesting the data via an API endpoint as JSON is preferred. + +## API End Points + +The API end points are defined as routes in `/src/index.ts` and recognizable +by the `get*AsJson` function names. + +The `get*AsJson` functions wrap the HTTP aspect and the data retrieval is done +by a specific method, for instance `getProfileAsJson(.)` uses `getProfile(.)`. +The types for the data are defined in `/src/shared/view-types.ts`, which is +also used by the backend. Thus, types that are used to communicate between +frontend and backend should be defined only once in `view-types.ts`. From 508dd1867f22d4c82563c0d259ba19a954327a1a Mon Sep 17 00:00:00 2001 From: Thomas Bachner Date: Mon, 1 Jun 2026 20:38:49 +0200 Subject: [PATCH 3/5] Make sure that we have the static resources in Docker Only explude the subfolders of `/resources` we do not need. --- .dockerignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.dockerignore b/.dockerignore index 72de1f51..0680603e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,5 @@ **/node_modules /dist -/resources +/resources/exp-data +/resources/reports From acc0b119730e030ea8f6c65ddf0bda683fce5cf6 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Mon, 13 Jul 2026 15:28:05 +0200 Subject: [PATCH 4/5] Move standard-responses.ts one level up The `common` folder contained only one file, and the other things in `backend` seem to be as `common` as this one. Signed-off-by: Stefan Marr --- src/backend/project/project.ts | 2 +- src/backend/{common => }/standard-responses.ts | 0 src/backend/timeline/timeline.ts | 2 +- tests/backend/{common => }/standard-responses.test.ts | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename src/backend/{common => }/standard-responses.ts (100%) rename tests/backend/{common => }/standard-responses.test.ts (92%) diff --git a/src/backend/project/project.ts b/src/backend/project/project.ts index 080f7f43..2752f187 100644 --- a/src/backend/project/project.ts +++ b/src/backend/project/project.ts @@ -3,7 +3,7 @@ import { prepareTemplate } from '../templates.js'; import { respondProjectAndSourceNotFound, respondProjectNotFound -} from '../common/standard-responses.js'; +} from '../standard-responses.js'; import { completeRequestAndHandlePromise, startRequest diff --git a/src/backend/common/standard-responses.ts b/src/backend/standard-responses.ts similarity index 100% rename from src/backend/common/standard-responses.ts rename to src/backend/standard-responses.ts diff --git a/src/backend/timeline/timeline.ts b/src/backend/timeline/timeline.ts index 96db1669..e3a7bb47 100644 --- a/src/backend/timeline/timeline.ts +++ b/src/backend/timeline/timeline.ts @@ -1,5 +1,5 @@ import { ParameterizedContext } from 'koa'; -import { respondProjectNotFound } from '../common/standard-responses.js'; +import { respondProjectNotFound } from '../standard-responses.js'; import { prepareTemplate } from '../templates.js'; import { TimelineSuite } from '../../shared/api.js'; import { Database } from '../db/db.js'; diff --git a/tests/backend/common/standard-responses.test.ts b/tests/backend/standard-responses.test.ts similarity index 92% rename from tests/backend/common/standard-responses.test.ts rename to tests/backend/standard-responses.test.ts index 2e06788a..bf6ffc05 100644 --- a/tests/backend/common/standard-responses.test.ts +++ b/tests/backend/standard-responses.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from '@jest/globals'; import { respondProjectAndSourceNotFound, respondProjectNotFound -} from '../../../src/backend/common/standard-responses.js'; +} from '../../src/backend/standard-responses.js'; describe('respondProjectNotFound', () => { it('should set status to 404 and respond with text', () => { From 997de97bf797587822b752ae6f596c58bdd5b23e Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Mon, 13 Jul 2026 15:53:22 +0200 Subject: [PATCH 5/5] Document repo layout and backend a bit Signed-off-by: Stefan Marr --- docs/development/backend.md | 18 +++++++++++++++++ docs/development/repo-layout.md | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 docs/development/backend.md create mode 100644 docs/development/repo-layout.md diff --git a/docs/development/backend.md b/docs/development/backend.md new file mode 100644 index 00000000..d7cea522 --- /dev/null +++ b/docs/development/backend.md @@ -0,0 +1,18 @@ +# Backend + +Under `src/backend`, the code is separated a bit by the "pages" of the frontend, +so, end-user visible functionality, and by implementation concerns. + +Functionality that may be used by multiple parts of the backend, can be provided +by files directly in `backend`. + +The different features typically consist of some server-side TypeScript code +and one or more HTML fragments that use the EJS template engine. + +The `backend/db` feature groups the main interactions with the database, contains the +initial structure of the DB in `db.sql`, as well as SQL scripts that perform +schema updates. These scripts are run manually, and there's currently no +migration infrastructure. + +The `src/index.ts` file defines the routes to make the different features +accessible to the user. diff --git a/docs/development/repo-layout.md b/docs/development/repo-layout.md new file mode 100644 index 00000000..875ef4ac --- /dev/null +++ b/docs/development/repo-layout.md @@ -0,0 +1,34 @@ +# Repository Layout + +The implementation is in the `/src` folder. Tests are implemented in `/tests`. + +## 1. General Structure of Source under /src + +- `backend` TypeScript code running on the server +- `frontend` TypeScript code that runs on the client/browser +- `shared` helper functions and type definitions shared by frontend and backend +- `views` contains HTML fragments used by multiple features + + +## 2. Benchmarks + +The `src/benchmarks` folder provides a few integration-level benchmarks that +can be used to assess end-to-end performance. + +These are run in our CI setup using ReBench and the `/rebench.conf` +configuration file. Thus, ReBenchDB is benchmarking and tracking itself. + +## 3. Vendored + +The `src/vendored` folder contains upstream dependencies that had to be +integrated for practical purposes. + +## 4. Patches + +The `/patches` folder contains in-repo maintained customizations of NPM packages, +where the vendoring did not seem necessary. + +## 5. Resources + +The `/resources` folder contains the `style.css` file and is used to store +the compilation results and files that need to be accessible by the frontend.