diff --git a/celements-admin-frontend/.dockerignore b/celements-admin-frontend/.dockerignore deleted file mode 100644 index ac9e20154..000000000 --- a/celements-admin-frontend/.dockerignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -dist -.git -.gitignore -.env -.env.* -*.log -public/config.js diff --git a/celements-admin-frontend/docker/Caddyfile b/celements-admin-frontend/docker/Caddyfile deleted file mode 100644 index 53f7a22df..000000000 --- a/celements-admin-frontend/docker/Caddyfile +++ /dev/null @@ -1,13 +0,0 @@ -:80 { - root * /srv - - handle /config.js { - header Cache-Control "no-store, no-cache, must-revalidate" - file_server - } - - handle { - try_files {path} /index.html - file_server - } -} diff --git a/celements-static/.dockerignore b/celements-static/.dockerignore new file mode 100644 index 000000000..6ebfe8118 --- /dev/null +++ b/celements-static/.dockerignore @@ -0,0 +1,8 @@ +**/node_modules +**/dist +**/.git +**/.gitignore +**/.env +**/.env.* +**/*.log +**/public/config.js diff --git a/celements-admin-frontend/Dockerfile b/celements-static/Dockerfile similarity index 53% rename from celements-admin-frontend/Dockerfile rename to celements-static/Dockerfile index 26d97926f..b0edc7ee3 100644 --- a/celements-admin-frontend/Dockerfile +++ b/celements-static/Dockerfile @@ -1,25 +1,25 @@ -# ____ _____ _ _ _ _ __ __ _ -# / __ \ / ____| | | | | /\ | | (_) \ \ / / | | /\ -# | | | |_ __ ___ _ __ ______| | ___| | ___ _ __ ___ ___ _ __ | |_ ___ / \ __| |_ __ ___ _ _ __ \ \ /\ / /__| |__ / \ _ __ _ __ -# | | | | '_ \ / _ \ '_ \______| | / _ \ |/ _ \ '_ ` _ \ / _ \ '_ \| __/ __| / /\ \ / _` | '_ ` _ \| | '_ \ \ \/ \/ / _ \ '_ \ / /\ \ | '_ \| '_ \ -# | |__| | |_) | __/ | | | | |___| __/ | __/ | | | | | __/ | | | |_\__ \ / ____ \ (_| | | | | | | | | | | \ /\ / __/ |_) / ____ \| |_) | |_) | -# \____/| .__/ \___|_| |_| \_____\___|_|\___|_| |_| |_|\___|_| |_|\__|___/ /_/ \_\__,_|_| |_| |_|_|_| |_| \/ \/ \___|_.__/_/ \_\ .__/| .__/ -# | | | | | | -# |_| |_| |_| # +# ____ _____ _ _ +# / __ \ / ____| | | | | +# | | | |_ __ ___ _ __ ______| | ___| | ___ _ __ ___ ___ _ __ | |_ ___ +# | | | | '_ \ / _ \ '_ \______| | / _ \ |/ _ \ '_ ` _ \ / _ \ '_ \| __/ __| +# | |__| | |_) | __/ | | | | |___| __/ | __/ | | | | | __/ | | | |_\__ \ +# \____/| .__/ \___|_| |_| \_____\___|_|\___|_| |_| |_|\___|_| |_|\__|___/ +# | | +# |_| # -# Open-Celements Admin WebApp Vue Frontend +# Celements static -## Stage: build -FROM node:lts AS build +## Stage: build admin frontend +FROM node:lts AS admin-frontend WORKDIR /app # Layer: dependencies -COPY package*.json ./ +COPY admin-frontend/package*.json ./ RUN npm ci # Layer: package -COPY . . +COPY admin-frontend/ . RUN npm run build ## Stage: execute @@ -29,13 +29,13 @@ ARG VERSION ARG REVISION LABEL org.opencontainers.image.source="https://github.com/celements/celements-web" \ - org.opencontainers.image.description="Celements admin frontend" \ + org.opencontainers.image.description="Celements static assets" \ org.opencontainers.image.version="${VERSION}" \ org.opencontainers.image.revision="${REVISION}" WORKDIR /srv -COPY --from=build /app/dist /srv +COPY --from=admin-frontend /app/dist /srv/admin COPY docker/Caddyfile /etc/caddy/Caddyfile COPY --chmod=755 docker/entrypoint.sh /usr/local/bin/start RUN caddy fmt /etc/caddy/Caddyfile --overwrite diff --git a/celements-admin-frontend/Jenkinsfile b/celements-static/Jenkinsfile similarity index 52% rename from celements-admin-frontend/Jenkinsfile rename to celements-static/Jenkinsfile index 8f801df84..3a73c8008 100644 --- a/celements-admin-frontend/Jenkinsfile +++ b/celements-static/Jenkinsfile @@ -2,7 +2,7 @@ dockerImagePipeline( org: 'celements', - image: 'celements-admin-frontend', - appDir: 'celements-admin-frontend', + image: 'celements-static', + appDir: 'celements-static', mode: 'node' ) diff --git a/celements-static/README.md b/celements-static/README.md new file mode 100644 index 000000000..bc52a760f --- /dev/null +++ b/celements-static/README.md @@ -0,0 +1,26 @@ +# Celements static + +This image serves the static Celements applications. `admin-frontend` is its first payload. +The local `package.json` versions the assembled image independently of its payloads. + +Build it from the repository root: + +```sh +docker build -t celements-static celements-static +``` + +## Potential improvements + +### Asset cache version + +The Celements webapp templates append an asset version as `?ver=`. A future +`$services.celementsweb.getAssetVersion()` helper should return the last startup timestamp in +production and the current timestamp in local development (cluster=local), so local changes always +bypass browser caching without disabling production cacheability. + +### Entrypoint extension + +The image currently has one entrypoint for its first static app. If additional apps need startup +configuration, each app can provide an entrypoint script that the aggregate image copies into +`entrypoint.d/`; a generic runner can execute those scripts in lexical order and fail startup if one +fails. diff --git a/celements-admin-frontend/.env.local.sample b/celements-static/admin-frontend/.env.local.sample similarity index 100% rename from celements-admin-frontend/.env.local.sample rename to celements-static/admin-frontend/.env.local.sample diff --git a/celements-admin-frontend/.prettierignore b/celements-static/admin-frontend/.prettierignore similarity index 100% rename from celements-admin-frontend/.prettierignore rename to celements-static/admin-frontend/.prettierignore diff --git a/celements-admin-frontend/.prettierrc.json b/celements-static/admin-frontend/.prettierrc.json similarity index 100% rename from celements-admin-frontend/.prettierrc.json rename to celements-static/admin-frontend/.prettierrc.json diff --git a/celements-admin-frontend/README.md b/celements-static/admin-frontend/README.md similarity index 92% rename from celements-admin-frontend/README.md rename to celements-static/admin-frontend/README.md index 15a0d9923..49535cdb7 100644 --- a/celements-admin-frontend/README.md +++ b/celements-static/admin-frontend/README.md @@ -63,7 +63,8 @@ The container generates `config.js` from its runtime environment. `.env.local` i | Command | Description | | -------------------- | ----------------------------------------------------------------- | -| `npm run dev` | Start dev server with concurrent type-checking and test watching | +| `npm run dev` | Build-watch into the local celements-webapp Tomcat target | +| `npm run dev:standalone` | Start the standalone Vite server with type-checking and test watching | | `npm run build` | Type-check + run tests + build production bundle | | `npm run preview` | Preview the production build locally | | `npm run test` | Run unit tests once with Vitest | @@ -103,14 +104,13 @@ The app exposes a `createCelementsAdminApp()` factory function from `bootstrap.t ## 🐳 Deployment -The project ships with a multi-stage `Dockerfile` that builds the static assets and serves them via [Caddy](https://caddyserver.com/). +The parent `celements-static` image builds and serves this frontend via [Caddy](https://caddyserver.com/). +Run these commands from the repository root: ```sh -# Build the Docker image (pass the active profile to select the correct .env file) -docker build --build-arg PROFILE_ACTIVE=prod -t celements-admin-frontend . +docker build -t celements-static celements-static -# Run the container -docker run -p 80:80 celements-admin-frontend +docker run -p 80:80 celements-static ``` --- diff --git a/celements-admin-frontend/env.d.ts b/celements-static/admin-frontend/env.d.ts similarity index 100% rename from celements-admin-frontend/env.d.ts rename to celements-static/admin-frontend/env.d.ts diff --git a/celements-admin-frontend/eslint.config.js b/celements-static/admin-frontend/eslint.config.js similarity index 100% rename from celements-admin-frontend/eslint.config.js rename to celements-static/admin-frontend/eslint.config.js diff --git a/celements-admin-frontend/index.html b/celements-static/admin-frontend/index.html similarity index 83% rename from celements-admin-frontend/index.html rename to celements-static/admin-frontend/index.html index 3beafdf24..d9b1ec06e 100644 --- a/celements-admin-frontend/index.html +++ b/celements-static/admin-frontend/index.html @@ -2,10 +2,9 @@ - Celements Admin - +
diff --git a/celements-admin-frontend/package-lock.json b/celements-static/admin-frontend/package-lock.json similarity index 100% rename from celements-admin-frontend/package-lock.json rename to celements-static/admin-frontend/package-lock.json diff --git a/celements-admin-frontend/package.json b/celements-static/admin-frontend/package.json similarity index 92% rename from celements-admin-frontend/package.json rename to celements-static/admin-frontend/package.json index a502f8e3c..76b30564b 100644 --- a/celements-admin-frontend/package.json +++ b/celements-static/admin-frontend/package.json @@ -7,7 +7,8 @@ "./src/*": "./src/*" }, "scripts": { - "dev": "concurrently \"vite\" \"npm:type-check-watch\" \"npm:test-watch\"", + "dev": "vite build --watch --outDir ../../celements-webapp/target/celements-web/static/admin", + "dev:standalone": "concurrently \"vite\" \"npm:type-check-watch\" \"npm:test-watch\"", "build": "npm run type-check && npm run test && vite build", "preview": "vite preview", "test": "vitest run", diff --git a/celements-admin-frontend/postcss.config.js b/celements-static/admin-frontend/postcss.config.js similarity index 100% rename from celements-admin-frontend/postcss.config.js rename to celements-static/admin-frontend/postcss.config.js diff --git a/celements-admin-frontend/public/config.sample.js b/celements-static/admin-frontend/public/config.sample.js similarity index 100% rename from celements-admin-frontend/public/config.sample.js rename to celements-static/admin-frontend/public/config.sample.js diff --git a/celements-admin-frontend/src/App.vue b/celements-static/admin-frontend/src/App.vue similarity index 100% rename from celements-admin-frontend/src/App.vue rename to celements-static/admin-frontend/src/App.vue diff --git a/celements-admin-frontend/src/assets/main.css b/celements-static/admin-frontend/src/assets/main.css similarity index 100% rename from celements-admin-frontend/src/assets/main.css rename to celements-static/admin-frontend/src/assets/main.css diff --git a/celements-admin-frontend/src/bootstrap.ts b/celements-static/admin-frontend/src/bootstrap.ts similarity index 100% rename from celements-admin-frontend/src/bootstrap.ts rename to celements-static/admin-frontend/src/bootstrap.ts diff --git a/celements-admin-frontend/src/conf/app.ts b/celements-static/admin-frontend/src/conf/app.ts similarity index 100% rename from celements-admin-frontend/src/conf/app.ts rename to celements-static/admin-frontend/src/conf/app.ts diff --git a/celements-admin-frontend/src/conf/locale/de/common.ts b/celements-static/admin-frontend/src/conf/locale/de/common.ts similarity index 100% rename from celements-admin-frontend/src/conf/locale/de/common.ts rename to celements-static/admin-frontend/src/conf/locale/de/common.ts diff --git a/celements-admin-frontend/src/conf/locale/de/index.ts b/celements-static/admin-frontend/src/conf/locale/de/index.ts similarity index 100% rename from celements-admin-frontend/src/conf/locale/de/index.ts rename to celements-static/admin-frontend/src/conf/locale/de/index.ts diff --git a/celements-admin-frontend/src/conf/locale/en/common.ts b/celements-static/admin-frontend/src/conf/locale/en/common.ts similarity index 100% rename from celements-admin-frontend/src/conf/locale/en/common.ts rename to celements-static/admin-frontend/src/conf/locale/en/common.ts diff --git a/celements-admin-frontend/src/conf/locale/en/index.ts b/celements-static/admin-frontend/src/conf/locale/en/index.ts similarity index 100% rename from celements-admin-frontend/src/conf/locale/en/index.ts rename to celements-static/admin-frontend/src/conf/locale/en/index.ts diff --git a/celements-admin-frontend/src/conf/locale/index.ts b/celements-static/admin-frontend/src/conf/locale/index.ts similarity index 100% rename from celements-admin-frontend/src/conf/locale/index.ts rename to celements-static/admin-frontend/src/conf/locale/index.ts diff --git a/celements-admin-frontend/src/conf/routes/index.ts b/celements-static/admin-frontend/src/conf/routes/index.ts similarity index 100% rename from celements-admin-frontend/src/conf/routes/index.ts rename to celements-static/admin-frontend/src/conf/routes/index.ts diff --git a/celements-admin-frontend/src/core/types/logger.d.ts b/celements-static/admin-frontend/src/core/types/logger.d.ts similarity index 100% rename from celements-admin-frontend/src/core/types/logger.d.ts rename to celements-static/admin-frontend/src/core/types/logger.d.ts diff --git a/celements-admin-frontend/src/embedded.ts b/celements-static/admin-frontend/src/embedded.ts similarity index 100% rename from celements-admin-frontend/src/embedded.ts rename to celements-static/admin-frontend/src/embedded.ts diff --git a/celements-admin-frontend/src/main.ts b/celements-static/admin-frontend/src/main.ts similarity index 100% rename from celements-admin-frontend/src/main.ts rename to celements-static/admin-frontend/src/main.ts diff --git a/celements-admin-frontend/src/medialib/api/tagApi.ts b/celements-static/admin-frontend/src/medialib/api/tagApi.ts similarity index 100% rename from celements-admin-frontend/src/medialib/api/tagApi.ts rename to celements-static/admin-frontend/src/medialib/api/tagApi.ts diff --git a/celements-admin-frontend/src/medialib/components/TagSidebar.vue b/celements-static/admin-frontend/src/medialib/components/TagSidebar.vue similarity index 100% rename from celements-admin-frontend/src/medialib/components/TagSidebar.vue rename to celements-static/admin-frontend/src/medialib/components/TagSidebar.vue diff --git a/celements-admin-frontend/src/medialib/components/TagStatusBar.vue b/celements-static/admin-frontend/src/medialib/components/TagStatusBar.vue similarity index 100% rename from celements-admin-frontend/src/medialib/components/TagStatusBar.vue rename to celements-static/admin-frontend/src/medialib/components/TagStatusBar.vue diff --git a/celements-admin-frontend/src/medialib/stores/tags.ts b/celements-static/admin-frontend/src/medialib/stores/tags.ts similarity index 100% rename from celements-admin-frontend/src/medialib/stores/tags.ts rename to celements-static/admin-frontend/src/medialib/stores/tags.ts diff --git a/celements-admin-frontend/src/medialib/utils/tagColors.ts b/celements-static/admin-frontend/src/medialib/utils/tagColors.ts similarity index 100% rename from celements-admin-frontend/src/medialib/utils/tagColors.ts rename to celements-static/admin-frontend/src/medialib/utils/tagColors.ts diff --git a/celements-admin-frontend/src/plugins/i18n.ts b/celements-static/admin-frontend/src/plugins/i18n.ts similarity index 100% rename from celements-admin-frontend/src/plugins/i18n.ts rename to celements-static/admin-frontend/src/plugins/i18n.ts diff --git a/celements-admin-frontend/src/plugins/plugin.pinia.ts b/celements-static/admin-frontend/src/plugins/plugin.pinia.ts similarity index 100% rename from celements-admin-frontend/src/plugins/plugin.pinia.ts rename to celements-static/admin-frontend/src/plugins/plugin.pinia.ts diff --git a/celements-admin-frontend/src/plugins/plugin.router.ts b/celements-static/admin-frontend/src/plugins/plugin.router.ts similarity index 100% rename from celements-admin-frontend/src/plugins/plugin.router.ts rename to celements-static/admin-frontend/src/plugins/plugin.router.ts diff --git a/celements-admin-frontend/src/types/global-components.d.ts b/celements-static/admin-frontend/src/types/global-components.d.ts similarity index 100% rename from celements-admin-frontend/src/types/global-components.d.ts rename to celements-static/admin-frontend/src/types/global-components.d.ts diff --git a/celements-admin-frontend/src/types/medialib.d.ts b/celements-static/admin-frontend/src/types/medialib.d.ts similarity index 100% rename from celements-admin-frontend/src/types/medialib.d.ts rename to celements-static/admin-frontend/src/types/medialib.d.ts diff --git a/celements-admin-frontend/src/types/vuefinder-locales.d.ts b/celements-static/admin-frontend/src/types/vuefinder-locales.d.ts similarity index 100% rename from celements-admin-frontend/src/types/vuefinder-locales.d.ts rename to celements-static/admin-frontend/src/types/vuefinder-locales.d.ts diff --git a/celements-admin-frontend/src/utils/dateutils.ts b/celements-static/admin-frontend/src/utils/dateutils.ts similarity index 100% rename from celements-admin-frontend/src/utils/dateutils.ts rename to celements-static/admin-frontend/src/utils/dateutils.ts diff --git a/celements-admin-frontend/src/utils/logger.ts b/celements-static/admin-frontend/src/utils/logger.ts similarity index 100% rename from celements-admin-frontend/src/utils/logger.ts rename to celements-static/admin-frontend/src/utils/logger.ts diff --git a/celements-admin-frontend/src/utils/utils.ts b/celements-static/admin-frontend/src/utils/utils.ts similarity index 100% rename from celements-admin-frontend/src/utils/utils.ts rename to celements-static/admin-frontend/src/utils/utils.ts diff --git a/celements-admin-frontend/src/views/MediaLib.vue b/celements-static/admin-frontend/src/views/MediaLib.vue similarity index 100% rename from celements-admin-frontend/src/views/MediaLib.vue rename to celements-static/admin-frontend/src/views/MediaLib.vue diff --git a/celements-admin-frontend/src/views/PageAttachments.vue b/celements-static/admin-frontend/src/views/PageAttachments.vue similarity index 100% rename from celements-admin-frontend/src/views/PageAttachments.vue rename to celements-static/admin-frontend/src/views/PageAttachments.vue diff --git a/celements-admin-frontend/tailwind.config.js b/celements-static/admin-frontend/tailwind.config.js similarity index 100% rename from celements-admin-frontend/tailwind.config.js rename to celements-static/admin-frontend/tailwind.config.js diff --git a/celements-admin-frontend/test/example.test.ts b/celements-static/admin-frontend/test/example.test.ts similarity index 100% rename from celements-admin-frontend/test/example.test.ts rename to celements-static/admin-frontend/test/example.test.ts diff --git a/celements-admin-frontend/tsconfig.app.json b/celements-static/admin-frontend/tsconfig.app.json similarity index 100% rename from celements-admin-frontend/tsconfig.app.json rename to celements-static/admin-frontend/tsconfig.app.json diff --git a/celements-admin-frontend/tsconfig.json b/celements-static/admin-frontend/tsconfig.json similarity index 100% rename from celements-admin-frontend/tsconfig.json rename to celements-static/admin-frontend/tsconfig.json diff --git a/celements-admin-frontend/tsconfig.vitest.json b/celements-static/admin-frontend/tsconfig.vitest.json similarity index 100% rename from celements-admin-frontend/tsconfig.vitest.json rename to celements-static/admin-frontend/tsconfig.vitest.json diff --git a/celements-admin-frontend/vite.config.ts b/celements-static/admin-frontend/vite.config.ts similarity index 96% rename from celements-admin-frontend/vite.config.ts rename to celements-static/admin-frontend/vite.config.ts index 4ec44fee8..22edade57 100644 --- a/celements-admin-frontend/vite.config.ts +++ b/celements-static/admin-frontend/vite.config.ts @@ -10,7 +10,7 @@ export default defineConfig(({ mode }) => getViteConfig(mode)); export const getViteConfig = (mode: string) => { const env = loadEnv(mode, process.cwd()); return defineConfig({ - base: mode === 'production' ? '/static/' : '/', + base: '/static/admin/', plugins: [ vue({ template: { @@ -22,6 +22,7 @@ export const getViteConfig = (mode: string) => { ], build: { manifest: true, + emptyOutDir: true, chunkSizeWarningLimit: 1500, rollupOptions: { input: { diff --git a/celements-admin-frontend/vitest.config.ts b/celements-static/admin-frontend/vitest.config.ts similarity index 100% rename from celements-admin-frontend/vitest.config.ts rename to celements-static/admin-frontend/vitest.config.ts diff --git a/celements-static/docker/Caddyfile b/celements-static/docker/Caddyfile new file mode 100644 index 000000000..3f3ddf802 --- /dev/null +++ b/celements-static/docker/Caddyfile @@ -0,0 +1,13 @@ +:80 { + root * /srv + + handle /health { + respond 200 + } + + handle { + @config path */config.js + header @config Cache-Control "no-store, no-cache, must-revalidate" + file_server + } +} diff --git a/celements-admin-frontend/docker/entrypoint.sh b/celements-static/docker/entrypoint.sh old mode 100755 new mode 100644 similarity index 87% rename from celements-admin-frontend/docker/entrypoint.sh rename to celements-static/docker/entrypoint.sh index cb0667427..7d5b299af --- a/celements-admin-frontend/docker/entrypoint.sh +++ b/celements-static/docker/entrypoint.sh @@ -7,7 +7,7 @@ escape_js_string() { -e "s/'/\\\\'/g" } -cat > /srv/config.js < /srv/admin/config.js < - -#else - - - -#end + + +
diff --git a/celements-webapp/src/main/webapp/templates/celAppScripts/cel/admin/PageAttachments++.vm b/celements-webapp/src/main/webapp/templates/celAppScripts/cel/admin/PageAttachments++.vm index 2bb6f9d03..e647d5a12 100644 --- a/celements-webapp/src/main/webapp/templates/celAppScripts/cel/admin/PageAttachments++.vm +++ b/celements-webapp/src/main/webapp/templates/celAppScripts/cel/admin/PageAttachments++.vm @@ -4,15 +4,9 @@ $!jsService.includeExtJsFile($extJsParamSync.setJsFile(':celJS/tailwind/tailwind.js')) $!jsService.includeExtJsFile($extJsParamSync.setJsFile(':celJS/tailwind/tailwind.config.js')) -#set($requestHost = "$!context.getRequest().getHeader('host')") -#if($requestHost.indexOf('localhost') != -1) - - -#else - - - -#end + + +
diff --git a/celements-webapp/vite.config.ts b/celements-webapp/vite.config.ts index c0fb5e0b1..bec8c4d9f 100644 --- a/celements-webapp/vite.config.ts +++ b/celements-webapp/vite.config.ts @@ -3,7 +3,9 @@ import { fileURLToPath, URL } from 'node:url'; import input from './src/main/frontend/celements/index.ts'; export default defineConfig({ + plugins: [], build: { + watch: process.argv.includes('--watch') ? { buildDelay: 2000 } : null, outDir: 'src/main/webapp/resources/dist', emptyOutDir: true, manifest: '.vite/manifest.celements.json', @@ -13,13 +15,13 @@ export default defineConfig({ // Use .mjs extension for celements module detection entryFileNames: '[name].[hash].mjs', chunkFileNames: '[name].[hash].mjs', - } + }, }, sourcemap: true, }, resolve: { alias: { - '@': fileURLToPath(new URL('./src/main/frontend', import.meta.url)) - } + '@': fileURLToPath(new URL('./src/main/frontend', import.meta.url)), + }, }, });