first row

This commit is contained in:
2025-10-02 17:27:06 +00:00
parent 9409de9103
commit eefa562cb1
29 changed files with 779 additions and 739 deletions

57
.vscode/settings.json vendored
View File

@@ -4,9 +4,6 @@
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.formatOnPaste": true, "editor.formatOnPaste": true,
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "esbenp.prettier-vscode",
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": { "[markdown]": {
"editor.wordWrap": "on", "editor.wordWrap": "on",
"editor.defaultFormatter": "vscode.markdown-language-features" "editor.defaultFormatter": "vscode.markdown-language-features"
@@ -16,11 +13,12 @@
}, },
"liveServer.settings.root": "/dist", "liveServer.settings.root": "/dist",
"liveServer.settings.file": "spa.html", "liveServer.settings.file": "spa.html",
"liveServer.settings.port": 5502, "liveServer.settings.port": 5501,
"liveServer.settings.proxy": { "liveServer.settings.proxy": {
"enable": true, "enable": true,
"baseUri": "/api", "baseUri": "/api",
"proxyUri": "https://login.tibicms.de/api/v1" "proxyUri": "http://localhost:8080/api/v1/_/renz_shop_2024"
//"proxyUri": "https://dev.renzshop.testversion.online/api"
}, },
"extensions.ignoreRecommendations": true, "extensions.ignoreRecommendations": true,
"files.autoSave": "off", "files.autoSave": "off",
@@ -28,6 +26,21 @@
"npm.autoDetect": "off", "npm.autoDetect": "off",
"debug.allowBreakpointsEverywhere": true, "debug.allowBreakpointsEverywhere": true,
"html.autoClosingTags": false, "html.autoClosingTags": false,
"[django-html]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "batisteo.vscode-django"
},
"saveAndRun": {
"commands": [
{
"match": "/api/.*(\\.ya?ml|js|env)$",
"cmd": "echo \"\" > ../../cms/tibi-server/tmp.html",
"silent": true
}
]
},
"i18n-ally.sourceLanguage": "de",
"i18n-ally.keystyle": "nested",
"yaml.schemas": { "yaml.schemas": {
"./../../cms/tibi-types/schemas/api-config/config.json": "api/config.y*ml", "./../../cms/tibi-types/schemas/api-config/config.json": "api/config.y*ml",
"./../../cms/tibi-types/schemas/api-config/collection.json": "api/collections/*.y*ml", "./../../cms/tibi-types/schemas/api-config/collection.json": "api/collections/*.y*ml",
@@ -43,27 +56,35 @@
} }
], ],
"workbench.colorCustomizations": { "workbench.colorCustomizations": {
"activityBar.activeBorder": "#00879f", "activityBar.activeBackground": "#ec1b3c",
"activityBar.activeBackground": "#43546e", "activityBar.background": "#ec1b3c",
"activityBar.background": "#43546e",
"activityBar.foreground": "#e7e7e7", "activityBar.foreground": "#e7e7e7",
"activityBar.inactiveForeground": "#e7e7e799", "activityBar.inactiveForeground": "#e7e7e799",
"activityBarBadge.background": "#ab748a", "activityBarBadge.background": "#2fce11",
"activityBarBadge.foreground": "#15202b", "activityBarBadge.foreground": "#15202b",
"commandCenter.border": "#e7e7e799", "commandCenter.border": "#e7e7e799",
"sash.hoverBorder": "#43546e", "sash.hoverBorder": "#ec1b3c",
"statusBar.background": "#303c4e", "statusBar.background": "#c4102d",
"statusBar.foreground": "#e7e7e7", "statusBar.foreground": "#e7e7e7",
"statusBarItem.hoverBackground": "#43546e", "statusBarItem.hoverBackground": "#ec1b3c",
"statusBarItem.remoteBackground": "#303c4e", "statusBarItem.remoteBackground": "#c4102d",
"statusBarItem.remoteForeground": "#e7e7e7", "statusBarItem.remoteForeground": "#e7e7e7",
"titleBar.activeBackground": "#303c4e", "titleBar.activeBackground": "#c4102d",
"titleBar.activeForeground": "#e7e7e7", "titleBar.activeForeground": "#e7e7e7",
"titleBar.inactiveBackground": "#303c4e99", "titleBar.inactiveBackground": "#c4102d99",
"titleBar.inactiveForeground": "#e7e7e799" "titleBar.inactiveForeground": "#e7e7e799",
"editorGroup.border": "#ec1b3c",
"panel.border": "#ec1b3c",
"sideBar.border": "#ec1b3c",
"statusBar.border": "#c4102d",
"tab.activeBorder": "#ec1b3c",
"titleBar.border": "#c4102d"
}, },
"peacock.remoteColor": "#303C4E", "peacock.remoteColor": "#C4102D",
"editor.tabCompletion": "on", "editor.tabCompletion": "on",
"diffEditor.codeLens": true, "diffEditor.codeLens": true,
"i18n-ally.localesPaths": ["public/ContentBuilder/public/contentbuilder/lang"] "i18n-ally.localesPaths": ["frontend/locales"],
"[svelte]": {
"editor.defaultFormatter": "svelte.svelte-vscode"
}
} }

View File

@@ -1,8 +1,8 @@
DOCKER_COMPOSE=docker compose -f docker-compose-local.yml DOCKER_COMPOSE=docker compose -f docker-compose-local.yml
DOCKER_COMPOSE_PLAYWRIGHT = docker-compose -f docker-compose-playwright.yml
.DEFAULT_GOAL := help .DEFAULT_GOAL := help
.PHONY: docker-up docker-up-tibi-dev docker-start docker-start-tibi-dev docker-down docker-ps docker-logs yarn-upgrade fix-permissions .PHONY: docker-up docker-up-tibi-dev docker-start docker-start-tibi-dev docker-down docker-ps docker-logs yarn-upgrade fix-permissions mongo-sync-dev-to-local mongo-sync-master-to-local
include ./.env include ./.env
@@ -10,19 +10,21 @@ help: ## show this help
@echo MAKE TARGETS @echo MAKE TARGETS
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' @grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
docker-up: ## bring docker compose stack up in background docker-up: ## bring docker compose stack up in background
$(DOCKER_COMPOSE) --profile tibi up -d $(DOCKER_COMPOSE) --profile tibi up -d
docker-up-tibi-dev: ## bring docker compose stack up in background with tibi-dev docker-up-tibi-dev: ## bring docker compose stack up in background with tibi-dev
$(DOCKER_COMPOSE) --profile tibi-dev up -d $(DOCKER_COMPOSE) --profile tibi-dev up -d
docker-up-admin-dev: ## bring docker compose stack up in background with tibi-dev
$(DOCKER_COMPOSE) --profile admin-dev up -d
docker-up-chisel: ## bring up chisel tunnel docker-up-chisel: ## bring up chisel tunnel
$(DOCKER_COMPOSE) --profile chisel up -d $(DOCKER_COMPOSE) --profile chisel up -d
docker-down: ## take docker compose stack down docker-down: ## take docker compose stack down
$(DOCKER_COMPOSE) --profile tibi-dev --profile tibi --profile chisel down $(DOCKER_COMPOSE) --profile admin-dev --profile tibi-dev --profile tibi --profile chisel down
docker-start: ## start docker compose stack in foreground and take it down after CTRL-C docker-start: ## start docker compose stack in foreground and take it down after CTRL-C
$(DOCKER_COMPOSE) --profile tibi up; $(DOCKER_COMPOSE) --profile tibi-dev --profile tibi --profile chisel down $(DOCKER_COMPOSE) --profile tibi up; $(DOCKER_COMPOSE) --profile tibi-dev --profile tibi --profile chisel down
@@ -42,37 +44,42 @@ docker-pull: ## pull docker images
docker-%: docker-%:
$(DOCKER_COMPOSE) $* $(DOCKER_COMPOSE) $*
yarn-upgrade: ## interactive yarn upgrade yarn-upgrade: # interactive yarn upgrade
$(DOCKER_COMPOSE) run --rm yarnstart yarn upgrade-interactive $(DOCKER_COMPOSE) run --rm yarnstart yarn upgrade-interactive
$(DOCKER_COMPOSE) restart yarnstart $(DOCKER_COMPOSE) restart yarnstart
fix-permissions: ## set files/directories owner to UID:GID from .env fix-permissions: # set files/directories owner to UID:GID from .env
sudo chown -R $(CODER_UID):$(CODER_GID) ./ sudo chown -R $(CODER_UID):$(CODER_GID) ./
mongo-sync-dev-to-local: ## sync mongo from dev to local
$(DOCKER_COMPOSE) up mongo -d
playwright-run-ui: ## run playwright tests in cli read -s -p "Enter chisel password: " CHISEL_PASSWORD; \
BROWSER=chromium CURRENT_UID=$(CODER_UID):$(CODER_GID) PY_MODE='' PY_SPECFLAG='tests/ui/**/*.spec.js' $(DOCKER_COMPOSE_PLAYWRIGHT) up --exit-code-from=playwright; $(DOCKER_COMPOSE_PLAYWRIGHT) down chisel client --auth coder:$$CHISEL_PASSWORD http://dock8.basehosts.de:10987 27017:mongo:27017 &
sleep 3
playwright-open-ui: ## open playwright tests via remote X mongodump --archive --gzip --db=wmbasic_renz_shop_dev | $(DOCKER_COMPOSE) exec -T mongo mongorestore --archive --gzip --nsFrom='wmbasic_renz_shop_dev.*' --nsTo='wmbasic_renz_shop.*' --nsInclude='wmbasic_renz_shop_dev.*' --drop
BROWSER=chromium CURRENT_UID=$(CODER_UID):$(CODER_GID) PY_MODE='--ui' PY_SPECFLAG='' $(DOCKER_COMPOSE_PLAYWRIGHT) --profile vnc up --exit-code-from=playwright; $(DOCKER_COMPOSE_PLAYWRIGHT) --profile vnc down sleep 3
killall chisel
playwright-run-api: ## run playwright tests in cli
BROWSER=chromium CURRENT_UID=$(CODER_UID):$(CODER_GID) PY_MODE='' PY_SPECFLAG='tests/api/**/*.spec.js' $(DOCKER_COMPOSE_PLAYWRIGHT) up --exit-code-from=playwright; $(DOCKER_COMPOSE_PLAYWRIGHT) down
playwright-open-api: ## open playwright tests via remote X
BROWSER=chromium CURRENT_UID=$(CODER_UID):$(CODER_GID) PY_MODE='--ui' PY_SPECFLAG='' $(DOCKER_COMPOSE_PLAYWRIGHT) --profile vnc up --exit-code-from=playwright; $(DOCKER_COMPOSE_PLAYWRIGHT) --profile vnc down
docker-down-playwright: ## take docker compose stack down
$(DOCKER_COMPOSE_PLAYWRIGHT) --profile tibi-dev --profile tibi --profile chisel down
mongo-sync-master-to-local: ## sync mongo from master to local mongo-sync-master-to-local: ## sync mongo from master to local
$(DOCKER_COMPOSE) up mongo -d $(DOCKER_COMPOSE) up mongo -d
read -s -p "Enter chisel password: " CHISEL_PASSWORD; \ read -s -p "Enter chisel password: " CHISEL_PASSWORD; \
chisel client --auth coder:$$CHISEL_PASSWORD http://dock4.basehosts.de:10987 27017:mongo:27017 & chisel client --auth coder:$$CHISEL_PASSWORD http://dock8.basehosts.de:10987 27017:mongo:27017 &
sleep 3 sleep 3
mongodump --archive --gzip --db=wmbasic_bkdf_tibi_2024 | $(DOCKER_COMPOSE) exec -T mongo mongorestore --archive --gzip --nsFrom='wmbasic_bkdf_tibi_2024.*' --nsTo='bkdf_tibi_2024_bkdf_tibi_2024.*' --nsInclude='wmbasic_bkdf_tibi_2024.*' --drop mongodump --archive --gzip --db=wmbasic_renz_shop | $(DOCKER_COMPOSE) exec -T mongo mongorestore --archive --gzip --nsFrom='wmbasic_renz_shop.*' --nsTo='wmbasic_renz_shop.*' --nsInclude='wmbasic_renz_shop.*' --drop
sleep 3 sleep 3
killall chisel killall chisel
media-sync-master-to-local: ## sync media from master to local
rsync -v -e "ssh -p 22222" -az --info=progress2 --exclude=contact_form renz_shop_media_master@dock1.basehosts.de:/ media/
mongo-sync-local-to-early: ## sync mongo from local to early
$(DOCKER_COMPOSE) up mongo -d
read -s -p "Enter chisel password: " CHISEL_PASSWORD; \
chisel client --auth coder:$$CHISEL_PASSWORD http://dock8.basehosts.de:10987 27017:mongo:27017 &
sleep 3
$(DOCKER_COMPOSE) exec -T mongo mongodump --archive --gzip --db=wmbasic_renz_shop | mongorestore --archive --gzip --nsFrom='wmbasic_renz_shop.*' --nsTo='wmbasic_renz_shop_early.*' --nsInclude='wmbasic_renz_shop.*' --drop
sleep 3
killall chisel
media-sync-local-to-early: ## sync media from local to early
rsync -v -e "ssh -p 22222" -az --info=progress2 --exclude=contact_form media/ renz_shop_media_early@dock1.basehosts.de:/

View File

@@ -152,16 +152,6 @@ permissions:
put: true put: true
delete: true delete: true
hooks:
post:
return:
type: javascript
file: hooks/clear_cache.js
put:
return:
type: javascript
file: hooks/clear_cache.js
projections: projections:
navigation: navigation:
select: select:

View File

@@ -454,7 +454,6 @@ subFields:
########################### Blöcke ############################ ########################### Blöcke ############################
############################################################### ###############################################################
- !include ./contentBlocks/columns.yml - !include ./contentBlocks/columns.yml
- !include ./contentBlocks/form.yml
- !include ./contentBlocks/predefined.yml - !include ./contentBlocks/predefined.yml
- !include ./contentBlocks/productSlider.yml - !include ./contentBlocks/productSlider.yml
- !include ./contentBlocks/MainHomepage.yml - !include ./contentBlocks/MainHomepage.yml

View File

@@ -1,7 +0,0 @@
name: form
type: object
meta:
widget: containerLessObject
dependsOn:
eval: $parent.type == 'form'
subFields: !include ../../fieldLists/formular/form.yml

View File

@@ -1,7 +0,0 @@
type: object
name: formular
meta:
label:
de: Formular
en: Form
widget: jsonField

View File

@@ -1,38 +0,0 @@
name: form
uploadPath: ../media/forms
meta:
label: Formular
muiIcon: web
backup:
active: true
collectionName: backups
views:
- type: table
columns:
- source: formular
permissions:
public:
methods:
get: true
post: true
put: false
delete: false
user:
methods:
get: true
post: true
put: true
delete: true
hooks:
post:
create:
type: javascript
file: hooks/forms/post_create.js
return:
type: javascript
file: hooks/forms/post_return.js
fields:
- !include fields/form.yml

View File

@@ -120,20 +120,6 @@ x-externalUrl: &externalUrl
de: Geben Sie hier die URL ein, zu der der Link führen soll. de: Geben Sie hier die URL ein, zu der der Link führen soll.
en: Enter the URL to which the link should lead. en: Enter the URL to which the link should lead.
hooks:
post:
return:
type: javascript
file: hooks/clear_cache.js
put:
return:
type: javascript
file: hooks/clear_cache.js
delete:
return:
type: javascript
file: hooks/clear_cache.js
fields: fields:
- name: tree - name: tree
type: number type: number

View File

@@ -1,4 +1,4 @@
namespace: kontextwerk namespace: kontextwerk
meta: meta:
openapi: openapi:
@@ -17,7 +17,7 @@ meta:
label: label:
de: Seiten de: Seiten
en: Pages en: Pages
collections: collections:
- !include collections/contact.yml - !include collections/contact.yml
- !include collections/banner.yml - !include collections/banner.yml
@@ -25,7 +25,6 @@ collections:
- !include collections/medialib.yml - !include collections/medialib.yml
- !include collections/navigation.yml - !include collections/navigation.yml
- !include collections/tag.yml - !include collections/tag.yml
- !include collections/webhook.yml
- !include collections/action.yml - !include collections/action.yml
- !include collections/module.yml - !include collections/module.yml
- !include collections/ssr.yml - !include collections/ssr.yml

View File

@@ -1,11 +1,7 @@
name: ${PROJECT_NAME} name: ${PROJECT_NAME}
version: "3.8"
services: services:
yarnstart: yarnstart:
profiles:
- tibi
- tibi-dev
image: node:20 image: node:20
volumes: volumes:
- ./:/data - ./:/data
@@ -25,8 +21,8 @@ services:
tibiserver: tibiserver:
profiles: profiles:
- tibi - tibi
- tibi-dev - admin-dev
image: gitbase.de/cms/tibi-server image: gitbase.de/cms/tibi-server:dev
volumes: volumes:
- ./:/data - ./:/data
environment: environment:
@@ -37,8 +33,6 @@ services:
SECURITY_ALLOWUPPERPATHS: "true" SECURITY_ALLOWUPPERPATHS: "true"
depends_on: depends_on:
- mongo - mongo
expose:
- 8080
labels: labels:
- traefik.enable=true - traefik.enable=true
- traefik.http.services.${PROJECT_NAME}-tibiserver.loadbalancer.server.port=8080 - traefik.http.services.${PROJECT_NAME}-tibiserver.loadbalancer.server.port=8080
@@ -47,10 +41,10 @@ services:
tibiserver-dev: tibiserver-dev:
hostname: tibiserver hostname: tibiserver
build: build:
context: ./ context: ./../../cms/tibi-server/
dockerfile: ./../../cms/tibi-server/Dockerfile.air dockerfile: ./../../cms/tibi-server/Dockerfile.air
profiles: profiles:
- tibiserver-dev - tibi-dev
volumes: volumes:
- ./:/data - ./:/data
- ./../../cms/tibi-server:/tibi-server - ./../../cms/tibi-server:/tibi-server
@@ -89,12 +83,11 @@ services:
labels: labels:
- traefik.enable=true - traefik.enable=true
- online.testversion.code.subdomain=${PROJECT_NAME}-tibiadmin - online.testversion.code.subdomain=${PROJECT_NAME}-tibiadmin
- traefik.http.routers.${PROJECT_NAME}-tibiadmin.middlewares=${PROJECT_NAME}-tibiadmin
- traefik.http.middlewares.${PROJECT_NAME}-tibiadmin.basicauth.usersfile=${PWD}/.basic-auth-code
tibiadmin-dev: tibiadmin-dev:
profiles: profiles:
- tibi-dev - tibi-dev
- admin-dev
image: node:20 image: node:20
volumes: volumes:
- ./../../cms/tibi-admin:/data - ./../../cms/tibi-admin:/data
@@ -105,30 +98,29 @@ services:
labels: labels:
- traefik.enable=true - traefik.enable=true
- online.testversion.code.subdomain=${PROJECT_NAME}-tibiadmin-dev - online.testversion.code.subdomain=${PROJECT_NAME}-tibiadmin-dev
- traefik.http.routers.${PROJECT_NAME}-tibiadmin-dev.middlewares=${PROJECT_NAME}-tibiadmin-dev
- traefik.http.middlewares.${PROJECT_NAME}-tibiadmin-dev.basicauth.usersfile=${PWD}/.basic-auth-code
user: ${CODER_UID}:${CODER_GID} user: ${CODER_UID}:${CODER_GID}
mongo: mongo:
profiles:
- tibi
- tibi-dev
image: gitbase.de/server/mongo:4.2 image: gitbase.de/server/mongo:4.2
volumes: volumes:
- ./tmp/mongo-data:/data/db - ./tmp/mongo-data:/data/db
user: ${CODER_UID}:${CODER_GID} user: ${CODER_UID}:${CODER_GID}
adminmongo: adminmongo:
profiles:
- tibi
- tibi-dev
image: gitbase.de/server/adminmongo image: gitbase.de/server/adminmongo
environment: environment:
CONN_NAME: mongo CONN_NAME: mongo
# DB_USERNAME: root
# DB_PASSWORD: root
DB_HOST: mongo DB_HOST: mongo
PORT: 1234 PORT: 1234
# ports:
# - ${ADMINMONGO_PORT:-3003}:1234
expose: expose:
- 1234 - 1234
#networks:
# - default
# - traefik_web
labels: labels:
- traefik.enable=true - traefik.enable=true
- online.testversion.code.subdomain=${PROJECT_NAME}-adminmongo - online.testversion.code.subdomain=${PROJECT_NAME}-adminmongo
@@ -136,19 +128,23 @@ services:
- traefik.http.middlewares.${PROJECT_NAME}-adminmongo.basicauth.usersfile=${PWD}/.basic-auth-code - traefik.http.middlewares.${PROJECT_NAME}-adminmongo.basicauth.usersfile=${PWD}/.basic-auth-code
maildev: maildev:
profiles:
- tibi
- tibi-dev
image: maildev/maildev image: maildev/maildev
# ports:
# - ${MAILDEV_PORT:-3004}:80
command: node bin/maildev --web 1080 --smtp 25 -v --hide-extensions=STARTTLS command: node bin/maildev --web 1080 --smtp 25 -v --hide-extensions=STARTTLS
expose: expose:
- 1080 - 1080
#networks:
# - default
# - traefik_web
labels: labels:
- traefik.enable=true - traefik.enable=true
- online.testversion.code.subdomain=${PROJECT_NAME}-maildev - online.testversion.code.subdomain=${PROJECT_NAME}-maildev
- traefik.http.services.${PROJECT_NAME}-maildev.loadbalancer.server.port=1080 - traefik.http.services.${PROJECT_NAME}-maildev.loadbalancer.server.port=1080
- traefik.http.routers.${PROJECT_NAME}-maildev.middlewares=${PROJECT_NAME}-maildev - traefik.http.routers.${PROJECT_NAME}-maildev.middlewares=${PROJECT_NAME}-maildev
- traefik.http.middlewares.${PROJECT_NAME}-maildev.basicauth.usersfile=${PWD}/.basic-auth-code - traefik.http.middlewares.${PROJECT_NAME}-maildev.basicauth.usersfile=${PWD}/.basic-auth-code
healthcheck:
test: ["NONE"]
chisel: chisel:
profiles: profiles:
@@ -160,3 +156,6 @@ services:
- traefik.enable=true - traefik.enable=true
- online.testversion.code.subdomain=${PROJECT_NAME}-chisel - online.testversion.code.subdomain=${PROJECT_NAME}-chisel
command: server --port 8080 --auth coder:coder command: server --port 8080 --auth coder:coder
#networks:
# traefik_web:
# external: true

View File

@@ -1,14 +1,11 @@
const fs = require("fs") const fs = require("fs")
const { copy } = require("esbuild-plugin-copy")
const resolvePlugin = { const resolvePlugin = {
name: "resolvePlugin", name: "resolvePlugin",
setup(build) { setup(build) {
let path = require("path") let path = require("path")
// url in css does not resolve via esbuild-svelte correctly
build.onResolve({ filter: /.*/, namespace: "fakecss" }, (args) => { build.onResolve({ filter: /.*/, namespace: "fakecss" }, (args) => {
// console.log(args)
if (args.path.match(/^\./)) return { path: path.dirname(args.importer) + "/" + args.path } if (args.path.match(/^\./)) return { path: path.dirname(args.importer) + "/" + args.path }
// return { path: path.join(args.resolveDir, "public", args.path) }
}) })
}, },
} }
@@ -36,10 +33,11 @@ const esbuildSvelte = sveltePlugin({
dev: (process.argv?.length > 2 ? process.argv[2] : "build") !== "build", dev: (process.argv?.length > 2 ? process.argv[2] : "build") !== "build",
}, },
preprocess: svelteConfig.preprocess, preprocess: svelteConfig.preprocess,
cache: true, cache: false,
filterWarnings: (warning) => { filterWarnings: (warning) => {
// filter out a11y // filter out a11y
if (warning.code.match(/^a11y/)) return false if (warning.code.match(/^a11y/)) return false
if (warning.code === "element_invalid_self_closing_tag") return false
return true return true
}, },
}) })
@@ -54,7 +52,18 @@ const options = {
minify: process.argv[2] == "build", minify: process.argv[2] == "build",
bundle: true, bundle: true,
splitting: false, splitting: false,
plugins: [esbuildSvelte, resolvePlugin], plugins: [
esbuildSvelte,
resolvePlugin,
copy({
assets: {
from: "./frontend/serviceworker.js",
to: "service-worker.js",
},
}),
],
mainFields: ["svelte", "browser", "module", "main"],
conditions: ["svelte", "browser"],
loader: { loader: {
".woff2": "file", ".woff2": "file",
".woff": "file", ".woff": "file",
@@ -73,19 +82,6 @@ if (process.argv[2] == "start") {
const dotEnv = fs.readFileSync(__dirname + "/.env", "utf8") const dotEnv = fs.readFileSync(__dirname + "/.env", "utf8")
const TIBI_NAMESPACE = dotEnv.match(/TIBI_NAMESPACE=(.*)/)[1] const TIBI_NAMESPACE = dotEnv.match(/TIBI_NAMESPACE=(.*)/)[1]
const apiBase = process.env.API_BASE || "http://localhost:8080/api/v1/_/" + TIBI_NAMESPACE const apiBase = process.env.API_BASE || "http://localhost:8080/api/v1/_/" + TIBI_NAMESPACE
console.log("APIBASE;;", apiBase, "process", process.env.SSR)
bsMiddleware.push(
createProxyMiddleware({
pathFilter: "/_s",
target: "https://sentry.basehosts.de",
changeOrigin: true,
logLevel: "debug",
pathRewrite: (path, req) => {
return path.replace(/^\/_s(.*)$/, "/api/5/envelope/")
},
})
)
bsMiddleware.push( bsMiddleware.push(
createProxyMiddleware({ createProxyMiddleware({
pathFilter: "/api", pathFilter: "/api",
@@ -95,24 +91,6 @@ if (process.argv[2] == "start") {
logLevel: "debug", logLevel: "debug",
}) })
) )
if (process.env.SSR) {
bsMiddleware.push(
createProxyMiddleware({
pathFilter: function (path, req) {
console.log("filter", path)
return !path.match(/\./)
},
target: apiBase,
changeOrigin: true,
logLevel: "debug",
pathRewrite: function (path, req) {
console.log("rewirte")
console.log(path)
return "/ssr?url=" + encodeURIComponent(path)
},
})
)
}
} }
module.exports = { module.exports = {
@@ -121,7 +99,7 @@ module.exports = {
options: options, options: options,
distDir, distDir,
watch: { watch: {
path: [__dirname + "/" + frontendDir + "/src/**/*"], path: [__dirname + "/" + frontendDir + "/src"],
}, },
serve: { serve: {
onRequest(args) { onRequest(args) {
@@ -140,6 +118,7 @@ module.exports = {
}), }),
], ],
}, },
ghostMode: false,
open: false, open: false,
// logLevel: "debug", // logLevel: "debug",
}, },

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" zoomAndPan="magnify" preserveAspectRatio="xMidYMid meet" version="1.0" viewBox="165.78 159.11 49.59 56.44"><defs><clipPath id="bd9e6d0ed5"><path d="M 165 159.082031 L 215.691406 159.082031 L 215.691406 216 L 165 216 Z M 165 159.082031 " clip-rule="nonzero"/></clipPath><clipPath id="8bf626c89e"><path d="M 0.601562 0.0820312 L 50.519531 0.0820312 L 50.519531 56.761719 L 0.601562 56.761719 Z M 0.601562 0.0820312 " clip-rule="nonzero"/></clipPath><clipPath id="e48e3f235c"><rect x="0" width="51" y="0" height="57"/></clipPath></defs><g clip-path="url(#bd9e6d0ed5)"><g transform="matrix(1, 0, 0, 1, 165, 159)"><g clip-path="url(#e48e3f235c)"><g clip-path="url(#8bf626c89e)"><path fill="#741e20" d="M 32.6875 31.042969 C 40.058594 28.636719 47.421875 35.292969 45.523438 42.96875 C 43.078125 52.433594 32.925781 56.882812 22.929688 56.535156 L 22.929688 49.703125 C 39.636719 49.835938 45.316406 32.035156 32.6875 31.042969 M 29.917969 36.039062 C 30.808594 36.039062 31.53125 36.761719 31.53125 37.652344 C 31.53125 38.542969 30.808594 39.265625 29.917969 39.265625 C 29.027344 39.265625 28.304688 38.542969 28.304688 37.652344 C 28.304688 36.761719 29.027344 36.039062 29.917969 36.039062 Z M 24.203125 36.039062 C 25.09375 36.039062 25.816406 36.761719 25.816406 37.652344 C 25.816406 38.542969 25.09375 39.265625 24.203125 39.265625 C 23.3125 39.265625 22.589844 38.542969 22.589844 37.652344 C 22.589844 36.761719 23.3125 36.039062 24.203125 36.039062 Z M 18.484375 36.039062 C 19.378906 36.039062 20.097656 36.761719 20.097656 37.652344 C 20.097656 38.542969 19.378906 39.265625 18.484375 39.265625 C 17.59375 39.265625 16.871094 38.542969 16.871094 37.652344 C 16.871094 36.761719 17.59375 36.039062 18.484375 36.039062 Z M 28.578125 16.488281 C 36.304688 14.222656 46.632812 9.421875 49.421875 1.210938 C 50.289062 3.949219 50.550781 6.75 50.269531 9.457031 C 50.066406 11.445312 49.726562 13.175781 49.273438 14.691406 C 47.90625 18.25 45.480469 21.414062 42.160156 23.6875 C 42.496094 21.765625 42.253906 19.792969 41.460938 18.011719 C 36.949219 23.855469 21.6875 25.710938 14.578125 30.480469 C 11.671875 32.429688 9.898438 35.710938 9.898438 39.257812 C 9.898438 45.679688 18.644531 51.957031 22.769531 56.53125 C 13.492188 56.164062 4.390625 51.664062 1.753906 43.210938 C -5.558594 19.773438 30.507812 16.988281 42.691406 0.109375 C 42.144531 8.601562 36.023438 13.347656 28.578125 16.488281 Z M 28.578125 16.488281 " fill-opacity="1" fill-rule="evenodd"/></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1,30 +0,0 @@
<svg width="215" height="60" viewBox="0 0 215 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_221_1287)">
<path d="M192.538 33.9251H201.598L206.93 24.7218H183.334V47.8628H192.538V33.9251Z" fill="#2F4858"/>
<path d="M99.6896 21.4885L90.4856 28.7738V10.7841H99.6896V21.4885Z" fill="#2F4858"/>
<path d="M209.672 19.9874H171.21L171.623 21.2686C172.366 23.5657 172.742 26.2797 172.742 29.331C172.742 41.8056 166.678 47.8666 154.193 47.8666H138.436V24.7293H147.636V38.6671H154.193C160.307 38.6671 163.538 35.4375 163.538 29.331C163.538 23.2245 160.307 19.9912 154.193 19.9912H124.45L115.898 27.0719L127.844 47.8628H116.657L108.42 32.5984L88.8435 47.8666H55.4442L50.1084 38.6671H68.3307C69.7945 38.6671 70.7009 37.7573 70.7009 36.298C70.7009 34.8386 69.7907 33.9289 68.3307 33.9289H56.9005L51.5836 24.7293H68.3307C69.7945 24.7293 70.7009 23.8234 70.7009 22.3603C70.7009 20.8971 69.7907 19.9912 68.3307 19.9912H48.8417L43.5249 10.7916H68.3307C76.1164 10.7916 79.9049 14.5784 79.9049 22.3603C79.9049 24.9795 79.4688 27.1818 78.6117 28.8951L78.3918 29.331L78.6117 29.7669C79.4688 31.484 79.9049 33.6787 79.9049 36.298C79.9049 36.7718 79.8898 37.2191 79.8632 37.6285L79.795 38.6671H85.7717L120.79 10.8599L120.862 10.7916H214.996L209.668 19.9912L209.672 19.9874Z" fill="#2F4858"/>
<path d="M171.923 56.9146H174.634L176.053 54.917H169.928V59.9318H171.923V56.9146Z" fill="#2F4858"/>
<path d="M178.195 51.8997L176.781 53.8935H169.928V51.8997H178.195Z" fill="#2F4858"/>
<path d="M178.066 59.9356L179.545 57.9039H181.532C182.007 57.9039 182.56 57.9039 182.939 57.9267C182.727 57.6424 182.397 57.1572 182.135 56.7819L180.717 54.6896L177.004 59.9356H174.107L179.177 52.7867C179.507 52.3243 179.993 51.8997 180.763 51.8997C181.532 51.8997 181.98 52.2902 182.325 52.7867L187.267 59.9356H178.066Z" fill="#2F4858"/>
<path d="M195.314 55.1065C197.271 55.1065 198.329 55.8381 198.329 57.305C198.329 58.9501 197.331 59.9356 194.882 59.9356H187.395L188.992 57.8698H195.071C195.659 57.8698 195.924 57.703 195.924 57.2823C195.924 56.8615 195.659 56.7061 195.071 56.7061H190.699C188.632 56.7061 187.684 55.7812 187.684 54.4015C187.684 52.8891 188.692 51.9035 191.131 51.9035H198.113L196.516 53.9921H190.941C190.365 53.9921 190.088 54.1361 190.088 54.5455C190.088 54.9549 190.365 55.1103 190.941 55.1103H195.314V55.1065Z" fill="#2F4858"/>
<path d="M206.517 55.1065C208.473 55.1065 209.531 55.8381 209.531 57.305C209.531 58.9501 208.534 59.9356 206.084 59.9356H198.598L200.195 57.8698H206.274C206.862 57.8698 207.127 57.703 207.127 57.2823C207.127 56.8615 206.862 56.7061 206.274 56.7061H201.901C199.834 56.7061 198.886 55.7812 198.886 54.4015C198.886 52.8891 199.895 51.9035 202.334 51.9035H209.315L207.719 53.9921H202.144C201.568 53.9921 201.291 54.1361 201.291 54.5455C201.291 54.9549 201.568 55.1103 202.144 55.1103H206.517V55.1065Z" fill="#2F4858"/>
<path d="M55.7438 59.6854V51.6496H58.5198V59.6854H55.7438Z" fill="#2F4858"/>
<path d="M62.3312 55.3794V59.5376H59.9003V53.2871C59.9003 52.131 60.5829 51.6534 61.3603 51.6534C61.6865 51.6534 61.9974 51.733 62.426 52.1044L66.8175 55.9594V51.7898H69.2484V58.0517C69.2484 59.2078 68.5544 59.6854 67.777 59.6854C67.4395 59.6854 67.1399 59.5945 66.7113 59.223L62.3312 55.3794Z" fill="#2F4858"/>
<path d="M54.3672 54.1627C54.3672 54.1399 54.3672 54.121 54.3672 54.0982C54.3672 53.9883 54.3596 53.8822 54.352 53.7798L54.3445 53.6509H54.3407C54.1814 52.3091 53.366 51.6571 51.8605 51.6571H46.4829L47.6358 53.6509H51.8605C51.8984 53.6509 51.9363 53.6509 51.9742 53.6585C52.2245 53.7002 52.3762 53.886 52.3762 54.1627C52.3762 54.4773 52.179 54.6744 51.8605 54.6744H48.2312L49.3841 56.6682H51.8605C52.1752 56.6682 52.3724 56.8653 52.3762 57.1799C52.3762 57.4566 52.2245 57.6424 51.9742 57.6841C51.9401 57.6916 51.9022 57.6916 51.8605 57.6916H47.6434L48.8 59.6854H51.8643C53.3698 59.6854 54.1852 59.0335 54.3445 57.6954H54.3482L54.3558 57.5628C54.3634 57.4604 54.371 57.3543 54.371 57.2444C54.371 57.2216 54.371 57.2027 54.371 57.1799C54.371 56.6151 54.2762 56.1375 54.0904 55.7661L54.0449 55.6713L54.0904 55.5765C54.2762 55.2051 54.371 54.7312 54.371 54.1627H54.3672Z" fill="#2F4858"/>
<path d="M160.841 56.418C160.841 58.806 159.586 60.0001 156.298 60.0001C153.01 60.0001 151.982 58.806 151.982 56.418V51.9642H154.417V56.418C154.417 57.957 155.767 57.9646 156.412 57.9646C157.057 57.9646 158.384 57.9721 158.384 56.418V51.9642H160.841V56.418Z" fill="#2F4858"/>
<path d="M145.827 53.958H146.946C146.931 53.958 146.92 53.958 146.904 53.958H145.827Z" fill="#2F4858"/>
<path d="M150.924 55.9783C150.924 55.2619 150.833 54.6403 150.644 54.1172L150.591 53.9542H150.579C150.029 52.6161 148.812 51.9604 146.901 51.9604H143.488V53.9542H146.904C146.931 53.9542 146.961 53.9542 146.988 53.9542H146.946C148.243 53.9693 148.93 54.6668 148.93 55.9783C148.93 57.2898 148.243 57.9873 146.946 58.0025H146.988C146.961 58.0025 146.935 58.0025 146.904 58.0025C146.92 58.0025 146.931 58.0025 146.946 58.0025H145.482V54.9814L143.488 54.9776V59.9963H146.901C148.812 59.9963 150.029 59.3405 150.579 58.0025H150.591L150.644 57.8395C150.83 57.3164 150.924 56.6947 150.924 55.9783Z" fill="#2F4858"/>
<path d="M98.8971 59.9356H95.5674L93.7774 57.8091H89.9547V59.9356H87.4669V55.8267H94.46C95.2298 55.8267 95.829 55.478 95.829 54.9246C95.829 54.2991 95.3133 53.9883 94.46 53.9883H87.4669L90.0305 51.8997H94.2552C96.0831 51.8997 98.3889 52.4759 98.3889 54.7692C98.3889 56.02 97.6077 57.051 96.2841 57.3164C96.561 57.5211 96.8606 57.8091 97.4142 58.3739L98.8933 59.9356H98.8971Z" fill="#2F4858"/>
<path d="M102.792 59.9356L104.244 57.9342H106.197C106.664 57.9342 107.21 57.9342 107.582 57.957C107.373 57.6765 107.047 57.2027 106.789 56.8274L105.393 54.7692L101.741 59.9318H98.8895L103.88 52.8966C104.206 52.4418 104.684 52.0248 105.439 52.0248C106.194 52.0248 106.637 52.4077 106.975 52.8966L111.837 59.9318H102.784L102.792 59.9356Z" fill="#2F4858"/>
<path d="M119.812 55.1065C121.769 55.1065 122.827 55.8381 122.827 57.305C122.827 58.9501 121.829 59.9356 119.38 59.9356H111.893L113.49 57.8698H119.569C120.157 57.8698 120.422 57.703 120.422 57.2823C120.422 56.8615 120.157 56.7061 119.569 56.7061H115.197C113.13 56.7061 112.182 55.7812 112.182 54.4015C112.182 52.8891 113.19 51.9035 115.629 51.9035H122.611L121.014 53.9921H115.439C114.863 53.9921 114.586 54.1361 114.586 54.5455C114.586 54.9549 114.863 55.1103 115.439 55.1103H119.812V55.1065Z" fill="#2F4858"/>
<path d="M131.386 55.1065C133.343 55.1065 134.401 55.8381 134.401 57.305C134.401 58.9501 133.404 59.9356 130.954 59.9356H123.468L125.064 57.8698H131.143C131.731 57.8698 131.997 57.703 131.997 57.2823C131.997 56.8615 131.731 56.7061 131.143 56.7061H126.771C124.704 56.7061 123.756 55.7812 123.756 54.4015C123.756 52.8891 124.765 51.9035 127.203 51.9035H134.185L132.588 53.9921H127.014C126.437 53.9921 126.16 54.1361 126.16 54.5455C126.16 54.9549 126.437 55.1103 127.014 55.1103H131.386V55.1065Z" fill="#2F4858"/>
<path d="M80.3297 54.2195L78.3349 55.7964V51.8997H80.3297V54.2195Z" fill="#2F4858"/>
<path d="M88.104 51.8997H84.9184L84.9033 51.9149L78.3349 57.1306V59.6589L82.2145 56.5469L84.0083 59.9356H86.4316L83.7921 55.3415L88.104 51.8997Z" fill="#2F4858"/>
<path d="M44.033 54.1892L42.3113 51.2136L40.3696 47.859L47.6851 47.8779L47.6927 47.8628L47.7002 47.8779H48.1174H53.8932L54.0031 47.859L48.6749 38.6632H35.0414L32.2957 33.9251H55.448L50.1273 24.7255H26.6906L33.5851 12.8195L37.7301 19.976H47.3703L38.6403 4.90113L38.4052 4.49934L38.0184 3.83221L31.3704 0L20.0274 19.5818L14.7143 28.751L7.00069 42.0633L0 54.155L9.34816 59.5527H40.9347L44.033 54.1892ZM11.3467 51.2136L13.277 47.8779L16.6446 42.0633L20.9869 34.5695L22.007 32.8107L23.0272 34.5695L27.3694 42.0633L30.737 47.8779L32.6673 51.2136H11.3467Z" fill="#741E20"/>
</g>
<defs>
<clipPath id="clip0_221_1287">
<rect width="215" height="60" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -1,30 +0,0 @@
<svg width="215" height="60" viewBox="0 0 215 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_536_1683)">
<path d="M192.538 33.9251H201.598L206.93 24.7217H183.334V47.8628H192.538V33.9251Z" fill="#F3EED9"/>
<path d="M99.6896 21.4884L90.4856 28.7738V10.784H99.6896V21.4884Z" fill="#F3EED9"/>
<path d="M209.672 19.9874H171.21L171.623 21.2686C172.366 23.5656 172.742 26.2796 172.742 29.331C172.742 41.8055 166.678 47.8666 154.193 47.8666H138.436V24.7293H147.636V38.667H154.193C160.307 38.667 163.538 35.4375 163.538 29.331C163.538 23.2245 160.307 19.9912 154.193 19.9912H124.45L115.898 27.0718L127.844 47.8628H116.657L108.42 32.5984L88.8435 47.8666H55.4442L50.1084 38.667H68.3307C69.7945 38.667 70.7009 37.7573 70.7009 36.2979C70.7009 34.8386 69.7907 33.9289 68.3307 33.9289H56.9005L51.5836 24.7293H68.3307C69.7945 24.7293 70.7009 23.8234 70.7009 22.3602C70.7009 20.8971 69.7907 19.9912 68.3307 19.9912H48.8417L43.5249 10.7916H68.3307C76.1164 10.7916 79.9049 14.5783 79.9049 22.3602C79.9049 24.9795 79.4688 27.1818 78.6117 28.8951L78.3918 29.331L78.6117 29.7669C79.4688 31.484 79.9049 33.6787 79.9049 36.2979C79.9049 36.7717 79.8898 37.219 79.8632 37.6284L79.795 38.667H85.7717L120.79 10.8598L120.862 10.7916H214.996L209.668 19.9912L209.672 19.9874Z" fill="#F3EED9"/>
<path d="M171.923 56.9145H174.634L176.053 54.9169H169.928V59.9318H171.923V56.9145Z" fill="#F3EED9"/>
<path d="M178.195 51.8997L176.781 53.8935H169.928V51.8997H178.195Z" fill="#F3EED9"/>
<path d="M178.066 59.9356L179.545 57.9039H181.532C182.007 57.9039 182.56 57.9039 182.939 57.9266C182.727 57.6423 182.397 57.1571 182.135 56.7819L180.717 54.6895L177.004 59.9356H174.107L179.177 52.7867C179.507 52.3242 179.993 51.8997 180.763 51.8997C181.532 51.8997 181.98 52.2901 182.325 52.7867L187.267 59.9356H178.066Z" fill="#F3EED9"/>
<path d="M195.314 55.1065C197.271 55.1065 198.329 55.838 198.329 57.3049C198.329 58.95 197.331 59.9356 194.882 59.9356H187.395L188.992 57.8697H195.071C195.659 57.8697 195.924 57.7029 195.924 57.2822C195.924 56.8615 195.659 56.7061 195.071 56.7061H190.699C188.632 56.7061 187.684 55.7812 187.684 54.4014C187.684 52.889 188.692 51.9035 191.131 51.9035H198.113L196.516 53.992H190.941C190.365 53.992 190.088 54.1361 190.088 54.5455C190.088 54.9548 190.365 55.1102 190.941 55.1102H195.314V55.1065Z" fill="#F3EED9"/>
<path d="M206.517 55.1065C208.473 55.1065 209.531 55.838 209.531 57.3049C209.531 58.95 208.534 59.9356 206.084 59.9356H198.598L200.195 57.8697H206.274C206.862 57.8697 207.127 57.7029 207.127 57.2822C207.127 56.8615 206.862 56.7061 206.274 56.7061H201.901C199.834 56.7061 198.886 55.7812 198.886 54.4014C198.886 52.889 199.895 51.9035 202.334 51.9035H209.315L207.719 53.992H202.144C201.568 53.992 201.291 54.1361 201.291 54.5455C201.291 54.9548 201.568 55.1102 202.144 55.1102H206.517V55.1065Z" fill="#F3EED9"/>
<path d="M55.7438 59.6854V51.6495H58.5198V59.6854H55.7438Z" fill="#F3EED9"/>
<path d="M62.3312 55.3794V59.5376H59.9003V53.287C59.9003 52.1309 60.5829 51.6533 61.3603 51.6533C61.6865 51.6533 61.9974 51.7329 62.426 52.1044L66.8175 55.9593V51.7898H69.2484V58.0517C69.2484 59.2078 68.5544 59.6854 67.777 59.6854C67.4395 59.6854 67.1399 59.5944 66.7113 59.2229L62.3312 55.3794Z" fill="#F3EED9"/>
<path d="M54.3672 54.1626C54.3672 54.1399 54.3672 54.1209 54.3672 54.0982C54.3672 53.9883 54.3596 53.8821 54.352 53.7798L54.3445 53.6509H54.3407C54.1814 52.3091 53.366 51.6571 51.8605 51.6571H46.4829L47.6358 53.6509H51.8605C51.8984 53.6509 51.9363 53.6509 51.9742 53.6585C52.2245 53.7002 52.3762 53.8859 52.3762 54.1626C52.3762 54.4772 52.179 54.6743 51.8605 54.6743H48.2312L49.3841 56.6681H51.8605C52.1752 56.6681 52.3724 56.8652 52.3762 57.1799C52.3762 57.4566 52.2245 57.6423 51.9742 57.684C51.9401 57.6916 51.9022 57.6916 51.8605 57.6916H47.6434L48.8 59.6854H51.8643C53.3698 59.6854 54.1852 59.0334 54.3445 57.6954H54.3482L54.3558 57.5627C54.3634 57.4604 54.371 57.3542 54.371 57.2443C54.371 57.2216 54.371 57.2026 54.371 57.1799C54.371 56.6151 54.2762 56.1375 54.0904 55.766L54.0449 55.6712L54.0904 55.5765C54.2762 55.205 54.371 54.7312 54.371 54.1626H54.3672Z" fill="#F3EED9"/>
<path d="M160.841 56.418C160.841 58.806 159.586 60 156.298 60C153.01 60 151.982 58.806 151.982 56.418V51.9641H154.417V56.418C154.417 57.9569 155.767 57.9645 156.412 57.9645C157.057 57.9645 158.384 57.9721 158.384 56.418V51.9641H160.841V56.418Z" fill="#F3EED9"/>
<path d="M145.827 53.9579H146.946C146.931 53.9579 146.92 53.9579 146.904 53.9579H145.827Z" fill="#F3EED9"/>
<path d="M150.924 55.9783C150.924 55.2619 150.833 54.6402 150.644 54.1171L150.591 53.9541H150.579C150.029 52.6161 148.812 51.9603 146.901 51.9603H143.488V53.9541H146.904C146.931 53.9541 146.961 53.9541 146.988 53.9541H146.946C148.243 53.9693 148.93 54.6667 148.93 55.9783C148.93 57.2898 148.243 57.9872 146.946 58.0024H146.988C146.961 58.0024 146.935 58.0024 146.904 58.0024C146.92 58.0024 146.931 58.0024 146.946 58.0024H145.482V54.9814L143.488 54.9776V59.9962H146.901C148.812 59.9962 150.029 59.3405 150.579 58.0024H150.591L150.644 57.8394C150.83 57.3163 150.924 56.6947 150.924 55.9783Z" fill="#F3EED9"/>
<path d="M98.8971 59.9356H95.5674L93.7774 57.8091H89.9547V59.9356H87.4669V55.8266H94.46C95.2298 55.8266 95.829 55.4779 95.829 54.9245C95.829 54.2991 95.3133 53.9882 94.46 53.9882H87.4669L90.0305 51.8997H94.2552C96.0831 51.8997 98.3889 52.4758 98.3889 54.7691C98.3889 56.02 97.6077 57.051 96.2841 57.3163C96.561 57.521 96.8606 57.8091 97.4142 58.3739L98.8933 59.9356H98.8971Z" fill="#F3EED9"/>
<path d="M102.792 59.9356L104.244 57.9342H106.197C106.664 57.9342 107.21 57.9342 107.582 57.9569C107.373 57.6764 107.047 57.2026 106.789 56.8273L105.393 54.7691L101.741 59.9318H98.8895L103.88 52.8966C104.206 52.4417 104.684 52.0248 105.439 52.0248C106.194 52.0248 106.637 52.4076 106.975 52.8966L111.837 59.9318H102.784L102.792 59.9356Z" fill="#F3EED9"/>
<path d="M119.812 55.1065C121.769 55.1065 122.827 55.838 122.827 57.3049C122.827 58.95 121.829 59.9356 119.38 59.9356H111.893L113.49 57.8697H119.569C120.157 57.8697 120.422 57.7029 120.422 57.2822C120.422 56.8615 120.157 56.7061 119.569 56.7061H115.197C113.13 56.7061 112.182 55.7812 112.182 54.4014C112.182 52.889 113.19 51.9035 115.629 51.9035H122.611L121.014 53.992H115.439C114.863 53.992 114.586 54.1361 114.586 54.5455C114.586 54.9548 114.863 55.1102 115.439 55.1102H119.812V55.1065Z" fill="#F3EED9"/>
<path d="M131.386 55.1065C133.343 55.1065 134.401 55.838 134.401 57.3049C134.401 58.95 133.404 59.9356 130.954 59.9356H123.468L125.064 57.8697H131.143C131.731 57.8697 131.997 57.7029 131.997 57.2822C131.997 56.8615 131.731 56.7061 131.143 56.7061H126.771C124.704 56.7061 123.756 55.7812 123.756 54.4014C123.756 52.889 124.765 51.9035 127.203 51.9035H134.185L132.588 53.992H127.014C126.437 53.992 126.16 54.1361 126.16 54.5455C126.16 54.9548 126.437 55.1102 127.014 55.1102H131.386V55.1065Z" fill="#F3EED9"/>
<path d="M80.3297 54.2195L78.3349 55.7963V51.8997H80.3297V54.2195Z" fill="#F3EED9"/>
<path d="M88.104 51.8997H84.9184L84.9033 51.9148L78.3349 57.1306V59.6589L82.2145 56.5468L84.0083 59.9356H86.4316L83.7921 55.3415L88.104 51.8997Z" fill="#F3EED9"/>
<path d="M44.033 54.1892L42.3113 51.2136L40.3696 47.859L47.6851 47.8779L47.6927 47.8628L47.7002 47.8779H48.1174H53.8932L54.0031 47.859L48.6749 38.6632H35.0414L32.2957 33.9251H55.448L50.1273 24.7255H26.6906L33.5851 12.8195L37.7301 19.976H47.3703L38.6403 4.90113L38.4052 4.49934L38.0184 3.83221L31.3704 0L20.0274 19.5818L14.7143 28.751L7.00069 42.0633L0 54.155L9.34816 59.5527H40.9347L44.033 54.1892ZM11.3467 51.2136L13.277 47.8779L16.6446 42.0633L20.9869 34.5695L22.007 32.8107L23.0272 34.5695L27.3694 42.0633L30.737 47.8779L32.6673 51.2136H11.3467Z" fill="#741E20"/>
</g>
<defs>
<clipPath id="clip0_536_1683">
<rect width="215" height="60" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -1,5 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Symbol">
<path id="Vector" d="M18.5694 21.8385L17.8759 20.6393L17.0937 19.2874L20.0405 19.295L20.0435 19.2889L20.0466 19.295H20.2146H22.5411L22.5854 19.2874L20.4392 15.5814H14.9475L13.8415 13.6719H23.1674L21.0242 9.96448H11.5837L14.3609 5.16632L16.0305 8.05041H19.9137L16.3972 1.97518L16.3024 1.81325L16.1466 1.5444L13.4688 0L8.89973 7.89154L6.75958 11.5868L3.65245 16.9517L0.83252 21.8247L4.59803 24H17.3213L18.5694 21.8385ZM5.40308 20.6393L6.18062 19.295L7.53712 16.9517L9.28621 13.9316L9.69714 13.2228L10.1081 13.9316L11.8572 16.9517L13.2137 19.295L13.9912 20.6393H5.40308Z" fill="#2F4858"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 710 B

View File

@@ -57,22 +57,6 @@
rel="dns-prefetch" rel="dns-prefetch"
href="//analytics.google.com" href="//analytics.google.com"
/> />
<link
rel="dns-prefetch"
href="https://store-punbvyqteo.mybigcommerce.com"
/>
<link
rel="preconnect"
href="https://store-punbvyqteo.mybigcommerce.com"
/>
<link
rel="dns-prefetch"
href="//cdn.bigcommerce.com"
/>
<meta
name="apple-mobile-web-app-status-bar-style"
content="black-translucent"
/>
<!--HEAD--> <!--HEAD-->

View File

@@ -4,30 +4,15 @@
import Footer from "./lib/components/Footer.svelte" import Footer from "./lib/components/Footer.svelte"
import Notifications from "./lib/components/widgets/Notifications.svelte" import Notifications from "./lib/components/widgets/Notifications.svelte"
import SSRSkip from "./lib/components/SSRSkip.svelte" import SSRSkip from "./lib/components/SSRSkip.svelte"
import { baseURL } from "./config"
import { isMobile, location, openModal } from "./lib/store" import { isMobile, location, openModal } from "./lib/store"
import StaticHomepage from "./routes/StaticHomepage.svelte" import StaticHomepage from "./routes/StaticHomepage.svelte"
export let url = "" let innerWidth = $state(0)
$effect(() => {
$isMobile = innerWidth <= 1024
})
if (url) { let googleCookiesAllowed = $state(false)
const [rawPath, rawQuery = ""] = url.split("?")
const normalizedPath = rawPath.startsWith("/") ? rawPath : `/${rawPath}`
const query = rawQuery ? decodeURIComponent(`?${rawQuery}`) : ""
$location = {
path: normalizedPath,
search: query,
hash: "",
push: false,
pop: false,
url: `${baseURL}${normalizedPath}${rawQuery ? `?${rawQuery}` : ""}`,
}
}
let innerWidth = 0
$: $isMobile = innerWidth <= 1024
let googleCookiesAllowed = false
const googleCookieName = "googleAnalytics" const googleCookieName = "googleAnalytics"
const syncModalState = () => { const syncModalState = () => {
@@ -77,7 +62,7 @@
}) })
</script> </script>
<svelte:window bind:innerWidth={innerWidth} /> <svelte:window bind:innerWidth />
<svelte:head> <svelte:head>
{#if googleCookiesAllowed} {#if googleCookiesAllowed}
@@ -107,7 +92,10 @@
<Notifications /> <Notifications />
<SSRSkip /> <SSRSkip />
<style lang="less" global> <style
lang="less"
global
>
@import "./lib/assets/css/variables.less"; @import "./lib/assets/css/variables.less";
@import "./lib/assets/css/main.less"; @import "./lib/assets/css/main.less";
@import "../assets/fonts/fonts.css"; @import "../assets/fonts/fonts.css";
@@ -130,20 +118,18 @@
@media @min-tablet { @media @min-tablet {
font-size: 18px; font-size: 18px;
} }
} .app-shell {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.app-shell { main {
display: flex; flex: 1;
flex-direction: column; display: flex;
min-height: 100vh; flex-direction: column;
background-color: var(--neutral-white); align-items: center;
} width: 100%;
}
main {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
} }
</style> </style>

View File

@@ -89,10 +89,10 @@ export async function api<T>(endpoint: string, options: ApiOptions = {}, body?:
type EntryTypeSwitch<T> = T extends "medialib" type EntryTypeSwitch<T> = T extends "medialib"
? MedialibEntry ? MedialibEntry
: T extends "content" : T extends "content"
? ContentEntry ? ContentEntry
: T extends "navigation" : T extends "navigation"
? NavigationEntry ? NavigationEntry
: any : any
export async function getDBEntries<T extends CollectionName>( export async function getDBEntries<T extends CollectionName>(
collectionName: T, collectionName: T,

13
frontend/src/i18n.ts Normal file
View File

@@ -0,0 +1,13 @@
import { writable } from "svelte/store"
import { baseURL } from "./config"
const initLoc = {
path: (typeof window !== "undefined" && window.location?.pathname) || "/",
search: (typeof window !== "undefined" && window.location?.search) || "",
hash: (typeof window !== "undefined" && window.location?.hash) || "",
push: false,
pop: false,
url: `${baseURL}${(typeof window !== "undefined" && window.location?.pathname) || "/"}`,
}
export const location = writable<LocationStore>(initLoc)

View File

@@ -1,11 +1,82 @@
import "./i18n"
import App from "./App.svelte" import App from "./App.svelte"
import { baseURL } from "./config"
import { hydrate } from "svelte"
import { location } from "./i18n"
const publishLocation = (_p?: string) => {
let _s: string
let _h: string
if (_p) {
const parts = _p.split("#")
_p = parts.shift()
_h = parts.join()
if (_h) _h = "#" + _h
const parts2 = _p.split("?")
_p = parts2.shift()
_s = parts2.join()
if (_s) _s = "?" + _s
}
// make sure the path does not include the baseURL
if (_p && _p.startsWith(baseURL)) {
_p = _p.slice(baseURL.length)
} else if (!_p) {
_p = typeof window !== "undefined" && window.location?.pathname
}
const newLocation = {
path: _p,
search: _p ? _s : typeof window !== "undefined" && window.location?.search,
hash: _p ? _h : typeof window !== "undefined" && window.location?.hash,
push: !!_p,
pop: !_p,
url: "",
}
newLocation.url = `${baseURL}${newLocation.path}${newLocation.search ? "?" + newLocation.search : ""}`
location.set(newLocation)
}
if (typeof history !== "undefined") {
if (typeof Proxy !== "undefined") {
// modern browser
const historyApply = (target: any, thisArg: any, argumentsList: any[]) => {
publishLocation(argumentsList && argumentsList.length >= 2 && argumentsList[2])
Reflect.apply(target, thisArg, argumentsList)
}
history.pushState = new Proxy(history.pushState, {
apply: historyApply,
})
history.replaceState = new Proxy(history.replaceState, {
apply: historyApply,
})
} else {
// ie11
const pushStateFn = history.pushState
const replaceStateFn = history.replaceState
history.pushState = function (data: any, title: string, url?: string) {
publishLocation(url)
return pushStateFn.apply(history, [...arguments] as [any, string, string?])
}
history.replaceState = function (data: any, title: string, url?: string) {
publishLocation(url)
return replaceStateFn.apply(history, [...arguments] as [any, string, string?])
}
}
} // else ssr -> no history handling
typeof window !== "undefined" &&
window.addEventListener("popstate", (event) => {
publishLocation()
})
let appContainer = document?.getElementById("appContainer") let appContainer = document?.getElementById("appContainer")
const hydrate = true //import.meta?.env?.MODE !== "development" const app = hydrate(App, { target: appContainer })
const app = new App({
target: appContainer,
props: {},
hydrate,
})
export default app export default app

View File

@@ -40,8 +40,18 @@ ul {
} }
* { * {
transition: background-color 0.5s ease, max-height 0.5s, height 0.5s ease, width 0.5s ease, flex 0.5s ease, transition:
opacity 0.5s ease, top 0.5s ease, bottom 0.5s ease, left 0.5s ease, right 0.5s ease, transform 0.5s ease; background-color 0.5s ease,
max-height 0.5s,
height 0.5s ease,
width 0.5s ease,
flex 0.5s ease,
opacity 0.5s ease,
top 0.5s ease,
bottom 0.5s ease,
left 0.5s ease,
right 0.5s ease,
transform 0.5s ease;
} }
/* General scrollbar styles for all webkit browsers */ /* General scrollbar styles for all webkit browsers */
*::-webkit-scrollbar { *::-webkit-scrollbar {

View File

@@ -1,7 +1,8 @@
/* Figma Styles of your File */ /* Figma Styles of your File */
:root { :root {
/* Colors */ /* Colors */
--wire: linear-gradient(-77.29deg, rgba(0, 0, 0, 0) 0%, rgba(13, 12, 12, 1) 44.86416280269623%), --wire:
linear-gradient(-77.29deg, rgba(0, 0, 0, 0) 0%, rgba(13, 12, 12, 1) 44.86416280269623%),
linear-gradient(98.68deg, rgba(0, 0, 0, 0) 0%, rgba(13, 12, 12, 1) 44.86416280269623%), linear-gradient(98.68deg, rgba(0, 0, 0, 0) 0%, rgba(13, 12, 12, 1) 44.86416280269623%),
linear-gradient(180deg, rgba(51, 45, 44, 1) 0%, rgba(51, 45, 44, 0) 100%); linear-gradient(180deg, rgba(51, 45, 44, 1) 0%, rgba(51, 45, 44, 0) 100%);
--bg-grey-cultured: linear-gradient(to left, #0d0c0c, #0d0c0c); --bg-grey-cultured: linear-gradient(to left, #0d0c0c, #0d0c0c);
@@ -37,10 +38,6 @@
--text-300: #625755; --text-300: #625755;
--bg-300: #eceaea; --bg-300: #eceaea;
--text-invers-150: #6d97b0; --text-invers-150: #6d97b0;
--krass-kraft-primary: #eb5757;
--crazy-crave-control-primary: #c0f256;
--krass-kreativ-primary: #56f2f2;
--crazy-calm-primary: #56f2b0;
--vertical-default-margin: 3rem; --vertical-default-margin: 3rem;
--small-max-width: 1392px; --small-max-width: 1392px;

View File

@@ -1,219 +1,209 @@
<script lang="ts"> <script lang="ts">
import { onMount } from "svelte"
import { getDBEntries } from "../../api" import { getDBEntries } from "../../api"
import { socialIcons, companyName, email, streetAddress, zipCode, localityAddress } from "../../config"
import { spaLink } from "../actions" import { spaLink } from "../actions"
import { navigationCache } from "../store"
import CrinkledSection from "./CrinkledSection.svelte"
const NAVIGATION_TYPE = { let navigationEntries: NavigationEntry[] = []
Main: 0,
Service: 1,
Legal: 2,
} as const
let legalLinks: NavigationElement[] = [] function elementsToCache(elements: NavigationElement[]) {
let serviceLinks: NavigationElement[] = [] elements.forEach((el) => {
let loadingNavigation = true if (!el.external) {
if (!$navigationCache[el.page]) $navigationCache[el.page] = el
const resolveHref = (link: NavigationElement) => { if (el.elements?.length > 0) elementsToCache(el.elements)
const base = link.page || "/" }
const hash = link.hash ? (link.hash.startsWith("#") ? link.hash : `#${link.hash}`) : "" })
return `${base}${hash}`
} }
onMount(async () => { getDBEntries("navigation").then((navs) => {
try { navigationEntries = navs
const entries = await getDBEntries("navigation") navigationEntries.filter((nav) => "elements" in nav).forEach((nav) => elementsToCache(nav.elements))
legalLinks = entries.find((entry) => Number(entry.type) === NAVIGATION_TYPE.Legal)?.elements ?? []
serviceLinks = entries.find((entry) => Number(entry.type) === NAVIGATION_TYPE.Service)?.elements ?? []
} catch (error) {
console.error("Unable to load footer navigation", error)
} finally {
loadingNavigation = false
}
}) })
const currentYear = new Date().getFullYear()
</script> </script>
<footer class="site-footer"> <CrinkledSection>
<div class="footer-inner"> <footer class="footer">
<section class="footer-column"> <section id="legal-section">
<h2>{companyName}</h2> <div class="wrapper">
<p>{streetAddress}, {zipCode} {localityAddress}</p> <small class="">© 2025 | KontextWerk | Alle Rechte vorbehalten.</small>
<a <nav class="nav-points">
class="footer-link" <ul>
href={`mailto:${email}`} {#each navigationEntries.length ? navigationEntries[0].elements : [] as link}
> <li>
{email}
</a>
<ul class="footer-social">
{#each Object.entries(socialIcons) as [name, url]}
<li>
<a
href={url}
target="_blank"
rel="noopener noreferrer"
aria-label={`Öffne ${name} in einem neuen Tab`}
>
{name}
</a>
</li>
{/each}
</ul>
</section>
<section class="footer-column">
<h3>Service</h3>
{#if loadingNavigation}
<span class="footer-placeholder">Links werden geladen …</span>
{:else if serviceLinks.length}
<ul>
{#each serviceLinks as link (link.name)}
<li>
{#if link.external && link.externalUrl}
<a <a
href={link.externalUrl} class="footer-nav-point-bottom"
target="_blank"
rel="noopener noreferrer"
>
{link.name}
</a>
{:else}
<a
href={resolveHref(link)}
use:spaLink use:spaLink
href={link.page}
> >
{link.name} <small>{link.name}</small>
</a> </a>
{/if} </li>
</li> {/each}
{/each} </ul>
</ul> </nav>
{:else} </div>
<span class="footer-placeholder">Aktuell keine Service-Links</span>
{/if}
</section> </section>
<section class="footer-column"> </footer>
<h3>Rechtliches</h3> </CrinkledSection>
{#if loadingNavigation}
<span class="footer-placeholder">Links werden geladen …</span>
{:else if legalLinks.length}
<ul>
{#each legalLinks as link (link.name)}
<li>
{#if link.external && link.externalUrl}
<a
href={link.externalUrl}
target="_blank"
rel="noopener noreferrer"
>
{link.name}
</a>
{:else}
<a
href={resolveHref(link)}
use:spaLink
>
{link.name}
</a>
{/if}
</li>
{/each}
</ul>
{:else}
<span class="footer-placeholder">Aktuell keine rechtlichen Hinweise</span>
{/if}
</section>
</div>
<div class="footer-meta">© {currentYear} {companyName}. Alle Rechte vorbehalten.</div>
</footer>
<style lang="less"> <style lang="less">
@import "../../lib/assets/css/variables.less"; @import "../../lib/assets/css/variables.less";
.footer {
.site-footer { &,
background-color: var(--bg-200, #0d0d0d); & * {
color: var(--neutral-white); box-sizing: border-box;
padding: 3rem 1.5rem 1.5rem;
display: flex;
flex-direction: column;
gap: 2rem;
}
.footer-inner {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 2rem;
width: 100%;
max-width: var(--body-maxwidth);
margin: 0 auto;
}
.footer-column {
display: flex;
flex-direction: column;
gap: 0.75rem;
h2,
h3 {
margin: 0;
font-size: 1.2rem;
font-weight: 600;
} }
background: var(--neutral-white);
ul { display: flex;
list-style: none; flex-direction: column;
padding: 0; align-items: center;
margin: 0; justify-content: flex-start;
position: relative;
width: 100%;
gap: 1.5rem;
#content-section {
padding: 0px var(--horizontal-default-margin);
max-width: var(--small-max-width);
width: 100%;
display: flex;
flex-direction: row;
gap: 1.5rem;
align-items: flex-start;
justify-content: flex-start;
position: relative;
#content-link-section {
display: flex;
flex-direction: row;
gap: 1.5rem;
align-items: flex-start;
justify-content: flex-start;
flex: 1;
position: relative;
.content {
display: flex;
flex-direction: column;
gap: 1.125rem;
align-items: flex-start;
justify-content: flex-start;
width: 8rem;
position: relative;
}
}
@media @mobile {
flex-direction: column;
align-items: flex-start;
#content-link-section {
flex-direction: column;
}
}
}
#newsletter-section {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0.5rem; gap: 18px;
min-width: 300px;
form {
button {
width: fit-content;
}
}
} }
#icons-section {
li { padding: 0px var(--horizontal-default-margin);
max-width: var(--small-max-width);
width: 100%;
margin: 0 0 0 -0.0625rem;
display: flex; display: flex;
} gap: 0.625rem;
} align-items: flex-start;
justify-content: flex-start;
.footer-link, flex: 1;
.footer-column a { position: relative;
color: inherit; overflow: hidden;
text-decoration: none; .payments,
transition: opacity 0.2s ease; .social {
display: flex;
&:hover { gap: 0.75rem;
opacity: 0.75; figure {
} height: 1.2rem;
} img {
height: 100%;
.footer-social { width: auto;
flex-direction: row; }
gap: 0.75rem; }
}
a { .line {
text-transform: capitalize; padding: 0rem 1.5rem 0rem 1.5rem;
font-size: 0.9rem; display: flex;
font-weight: 500; flex-direction: row;
} gap: 1.5rem;
} align-items: center;
justify-content: flex-start;
.footer-placeholder { flex: 1;
font-size: 0.85rem; position: relative;
opacity: 0.7; overflow: hidden;
} .line-1,
.line-2 {
.footer-meta { border-style: solid;
text-align: center; border-color: var(--text-invers-100);
font-size: 0.85rem; border-width: 0.0625rem 0 0 0;
opacity: 0.6; flex: 1;
} height: 0rem;
position: relative;
@media (max-width: 640px) { }
.site-footer { }
padding: 2.4rem 1.2rem 1.2rem; @media @mobile {
flex-direction: column-reverse;
align-items: center;
gap: 2rem;
.line {
width: 100%;
padding: 0px;
}
}
} }
.footer-social { #legal-section {
flex-wrap: wrap; display: flex;
justify-content: center;
width: 100%;
background: var(--bg-100);
gap: 1.2rem;
.wrapper {
max-width: var(--small-max-width);
width: 100%;
a,
small {
color: var(--text-100);
}
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
flex-shrink: 0;
position: relative;
gap: 1.2rem;
padding: 1.5rem var(--horizontal-default-margin);
@media @mobile {
flex-direction: column;
align-items: flex-start;
}
.nav-points {
ul {
display: flex;
flex-wrap: wrap;
gap: 0.6rem;
align-items: center;
a {
font-weight: 400;
font-family: Outfit;
}
}
}
}
} }
} }
</style> </style>

View File

@@ -1,108 +1,49 @@
<script lang="ts"> <script lang="ts">
import { onMount } from "svelte" import { onMount } from "svelte"
import { getDBEntries } from "../../../api"
import { spaLink } from "../../actions" import { spaLink } from "../../actions"
import { location } from "../../store"
const NAVIGATION_TYPE = { let scrolled: boolean = false,
Main: 0, isHomepage: boolean = true
Service: 1,
Legal: 2,
} as const
let navigationEntries: NavigationEntry[] = [] function checkScroll() {
let isMenuOpen = false scrolled = window.scrollY >= 100
let loadingNavigation = true
const resolveHref = (item: NavigationElement) => {
const base = item.page || "/"
const hash = item.hash ? (item.hash.startsWith("#") ? item.hash : `#${item.hash}`) : ""
return `${base}${hash}`
} }
const isActive = (item: NavigationElement) => { onMount(() => {
const target = resolveHref(item) if (typeof window !== "undefined") {
const [path] = target.split("#") checkScroll()
return path === $location.path window.addEventListener("scroll", checkScroll)
} return () => {
window.removeEventListener("scroll", checkScroll)
const closeMenu = () => { }
isMenuOpen = false
}
const toggleMenu = () => {
isMenuOpen = !isMenuOpen
}
onMount(async () => {
try {
const entries = await getDBEntries("navigation")
navigationEntries = entries ?? []
} catch (error) {
console.error("Unable to load navigation", error)
} finally {
loadingNavigation = false
} }
}) })
$: mainNavigation = navigationEntries.find((entry) => Number(entry.type) === NAVIGATION_TYPE.Main) $: checkScroll()
$: darkBG = scrolled
</script> </script>
<header class="site-header" aria-label="Primäre Navigation"> <header
<div class="header-inner"> class="headercontainer"
<a id={"header-container"}
class="brand" class:scrolled={darkBG}
href="/" class:homepageHeader={isHomepage}
use:spaLink role="dialog"
on:click={closeMenu} aria-label="Hauptnavigation"
> >
Kontextwerk <div class="padding">
</a> <nav class="menu">
<button <a
class="menu-toggle" href="/"
aria-expanded={isMenuOpen} use:spaLink
aria-controls="primary-navigation" class="logo-container"
on:click={toggleMenu} aria-label="Go to homepage"
> >
<span class="sr-only">Navigation umschalten</span> <img
<span class="bar"></span> src="../../../../logo/KontextWerk.svg"
<span class="bar"></span> alt="logo"
<span class="bar"></span> />
</button> </a>
<nav
id="primary-navigation"
class:open={isMenuOpen}
>
{#if loadingNavigation}
<span class="nav-placeholder">Navigation wird geladen …</span>
{:else if mainNavigation?.elements?.length}
<ul>
{#each mainNavigation.elements as item (item.name)}
<li class:active={isActive(item)}>
{#if item.external && item.externalUrl}
<a
href={item.externalUrl}
target="_blank"
rel="noopener noreferrer"
on:click={closeMenu}
>
{item.name}
</a>
{:else}
<a
href={resolveHref(item)}
use:spaLink
on:click={closeMenu}
>
{item.name}
</a>
{/if}
</li>
{/each}
</ul>
{:else}
<span class="nav-placeholder">Keine Navigationspunkte verfügbar</span>
{/if}
</nav> </nav>
</div> </div>
</header> </header>
@@ -110,138 +51,55 @@
<style lang="less"> <style lang="less">
@import "../../assets/css/variables.less"; @import "../../assets/css/variables.less";
.site-header { @desktop: ~"only screen and (min-width: 1440px)";
position: sticky;
top: 0;
z-index: 1000;
background-color: var(--neutral-white);
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}
.header-inner { .headercontainer {
max-width: var(--body-maxwidth);
margin: 0 auto;
padding: 1.2rem 1.6rem;
display: flex; display: flex;
align-items: center;
justify-content: space-between;
gap: 1.2rem;
}
.brand {
font-size: 1.4rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-invers-100);
text-decoration: none;
}
.menu-toggle {
display: none;
flex-direction: column; flex-direction: column;
justify-content: center; @media @mobile {
overflow: hidden;
}
position: sticky;
z-index: 5500;
top: 0px;
justify-content: space-between;
background-color: #0d0c0c;
align-items: center; align-items: center;
gap: 0.3rem; width: 100%;
padding: 0.6rem; .padding {
border: none; width: 100%;
background: none; padding: 0px var(--horizontal-default-margin);
cursor: pointer; height: 100%;
.bar {
width: 1.6rem;
height: 2px;
background-color: var(--text-invers-100);
transition: transform 0.2s ease;
}
}
nav {
ul {
list-style: none;
display: flex; display: flex;
gap: 1.2rem; align-items: flex-end;
margin: 0; justify-content: center;
padding: 0; .menu {
} max-width: var(--normal-max-width);
li {
position: relative;
&.active a::after {
transform: scaleX(1);
}
}
a {
text-decoration: none;
font-weight: 500;
color: var(--text-100);
padding: 0.3rem 0;
position: relative;
display: inline-flex;
&::after {
content: "";
position: absolute;
left: 0;
bottom: -0.3rem;
width: 100%; width: 100%;
height: 2px; display: flex;
background-color: var(--accent-100, #c4102d); height: 86px;
transform: scaleX(0); align-items: center;
transform-origin: left; justify-content: space-between;
transition: transform 0.2s ease; .logo-container {
} height: 64px;
display: flex;
&:hover::after { align-items: flex-start;
transform: scaleX(1); img {
height: 60px;
width: auto;
object-fit: contain;
}
}
} }
} }
&.homepageHeader {
.nav-placeholder { background-color: transparent;
font-size: 0.875rem;
color: var(--text-60);
} }
} &.scrolled&.homepageHeader {
box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.2);
.sr-only { background-color: var(--bg-100);
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
@media (max-width: 960px) {
.menu-toggle {
display: flex;
}
nav {
position: absolute;
top: 100%;
left: 0;
right: 0;
background-color: var(--neutral-white);
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
transform: translateY(-110%);
transition: transform 0.2s ease;
padding: 1.2rem 1.6rem;
&.open {
transform: translateY(0);
}
ul {
flex-direction: column;
align-items: flex-start;
gap: 0.8rem;
}
} }
} }
</style> </style>

View File

@@ -0,0 +1,244 @@
<script lang="ts">
import { onMount } from "svelte"
let interval: NodeJS.Timeout
let selectedChapter = -1
let currentColor = "#741e20" // Initial color
setTimeout(() => {
// set width and height of placeholder to elements width and height
const placeholder = document.querySelector(".placeholder")
const elements = document.querySelector(".elements")
if (placeholder && elements) {
const { width, height } = elements.getBoundingClientRect()
placeholder.style.width = `${width}px`
placeholder.style.height = `${height}px`
}
}, 10)
function startInterval() {
interval = setInterval(() => {
selectedChapter = (selectedChapter + 1) % chapters.length
updateShadowColor(chapters[selectedChapter]?.color || "#000")
}, 3000)
}
function stopInterval() {
clearInterval(interval)
}
function updateShadowColor(newColor: string) {
const filter = document.getElementById("redShadow")
const feDropShadow = filter?.querySelector("feDropShadow")
if (feDropShadow) {
feDropShadow.style.transition = "flood-color 1s ease"
feDropShadow.setAttribute("flood-color", newColor)
currentColor = newColor
}
}
onMount(() => {
startInterval()
return () => clearInterval(interval)
})
const chapters = [
{
title: "Schneller",
alias: "Schneller",
shortDescription:
"Unser internes System sorgt für eine schnelle und effiziente Umsetzung Ihres Projekts. Dadurch ermöglichen wir, ihr Projekt in Wochen, statt Monaten zu realisieren!",
color: "#ffffff",
},
{
title: "Qualitativer",
alias: "Qualitativer",
shortDescription:
"Höhere Qualität durch spezialisierte Experten. Wir setzen auf ein Netzwerk aus erfahrenen Fachleuten, um Ihnen die bestmöglichen Lösungen mit State-of-the-Art-Technologien zu bieten.",
color: "#741e20",
},
{
title: "Entspannter",
alias: "Entspannter",
shortDescription:
"Wir bieten Ihnen einen Rundum-sorglos-Service. Von der Konzeption über die Umsetzung bis hin zur Nachbetreuung. Alles aus einer Hand.",
color: "#ffffff",
},
{
title: "Autonomer",
alias: "Autonomer",
shortDescription:
"Sie entscheiden wo die Software gehostet wird. Ob bei uns in unseren deutschen Rechenzentren oder bei Ihnen, wir bieten beides an.",
color: "#741e20",
},
]
</script>
<section
class="splittedHomepage"
style="--color: {currentColor}"
>
<div class="placeholder"></div>
<ul class="elements">
{#each chapters as chapter, i}
<li
class:selected={i == selectedChapter}
on:mouseenter={() => {
stopInterval()
selectedChapter = i
updateShadowColor(chapter.color)
}}
on:mouseleave={startInterval}
>
{#if i == selectedChapter}
<h2
class={i % 2 ? "" : "transparent-heading"}
style={i % 2 ? `color: ${chapter.color}` : `-webkit-text-stroke: 1px ${chapter.color}`}
>
{chapter.title}
</h2>
{:else}
<h2 class={i % 2 ? "white-heading" : "transparent-heading"}>{chapter.alias}</h2>
{/if}
<p style="color: {chapter.color} !important;">
{@html chapter.shortDescription}
</p>
</li>
{/each}
</ul>
<div class="media">
<svg
viewBox="0 0 51 57"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<filter
id="redShadow"
x="-20%"
y="-20%"
width="200%"
height="200%"
primitiveUnits="objectBoundingBox"
>
<feDropShadow
dx="-0.01"
dy="0"
stdDeviation="0.01"
flood-color="currentColor"
></feDropShadow>
</filter>
<clipPath id="bd9e6d0ed5"
><path
d="M 165 159.082031 L 215.691406 159.082031 L 215.691406 216 L 165 216 Z M 165 159.082031 "
clip-rule="nonzero"
></path></clipPath
><clipPath id="8bf626c89e"
><path
d="M 0.601562 0.0820312 L 50.519531 0.0820312 L 50.519531 56.761719 L 0.601562 56.761719 Z M 0.601562 0.0820312 "
clip-rule="nonzero"
></path></clipPath
><clipPath id="e48e3f235c"
><rect
x="0"
width="51"
y="0"
height="57"
></rect></clipPath
>
</defs>
<path
fill="black"
d="M 32.6875 31.042969 C 40.058594 28.636719 47.421875 35.292969 45.523438 42.96875 C 43.078125 52.433594 32.925781 56.882812 22.929688 56.535156 L 22.929688 49.703125 C 39.636719 49.835938 45.316406 32.035156 32.6875 31.042969 M 29.917969 36.039062 C 30.808594 36.039062 31.53125 36.761719 31.53125 37.652344 C 31.53125 38.542969 30.808594 39.265625 29.917969 39.265625 C 29.027344 39.265625 28.304688 38.542969 28.304688 37.652344 C 28.304688 36.761719 29.027344 36.039062 29.917969 36.039062 Z M 24.203125 36.039062 C 25.09375 36.039062 25.816406 36.761719 25.816406 37.652344 C 25.816406 38.542969 25.09375 39.265625 24.203125 39.265625 C 23.3125 39.265625 22.589844 38.542969 22.589844 37.652344 C 22.589844 36.761719 23.3125 36.039062 24.203125 36.039062 Z M 18.484375 36.039062 C 19.378906 36.039062 20.097656 36.761719 20.097656 37.652344 C 20.097656 38.542969 19.378906 39.265625 18.484375 39.265625 C 17.59375 39.265625 16.871094 38.542969 16.871094 37.652344 C 16.871094 36.761719 17.59375 36.039062 18.484375 36.039062 Z M 28.578125 16.488281 C 36.304688 14.222656 46.632812 9.421875 49.421875 1.210938 C 50.289062 3.949219 50.550781 6.75 50.269531 9.457031 C 50.066406 11.445312 49.726562 13.175781 49.273438 14.691406 C 47.90625 18.25 45.480469 21.414062 42.160156 23.6875 C 42.496094 21.765625 42.253906 19.792969 41.460938 18.011719 C 36.949219 23.855469 21.6875 25.710938 14.578125 30.480469 C 11.671875 32.429688 9.898438 35.710938 9.898438 39.257812 C 9.898438 45.679688 18.644531 51.957031 22.769531 56.53125 C 13.492188 56.164062 4.390625 51.664062 1.753906 43.210938 C -5.558594 19.773438 30.507812 16.988281 42.691406 0.109375 C 42.144531 8.601562 36.023438 13.347656 28.578125 16.488281 Z M 28.578125 16.488281 "
fill-opacity="1"
fill-rule="evenodd"
filter="url(#redShadow)"
></path>
</svg>
</div>
</section>
<style lang="less">
@import "../../assets/css/variables.less";
.splittedHomepage {
display: flex;
width: 100%;
position: relative;
height: 100%;
align-items: center;
justify-content: space-between;
transition: --color 1s ease;
max-width: var(--normal-max-width);
.elements {
display: flex;
flex-direction: column;
gap: 1.5rem;
position: absolute;
width: 100%;
@media @mobile {
gap: 0.5rem;
}
li {
transition: max-height 1.5s ease;
max-height: 5rem;
max-width: 900px;
h2 {
font-size: 4.5rem;
text-transform: uppercase;
font-weight: 700;
line-height: 4.5rem;
font-family: sans-serif;
@media @mobile {
font-size: 3rem;
line-height: 3rem;
}
&.transparent-heading {
@media @mobile {
font-size: 3rem;
}
font-weight: 700;
color: transparent;
position: relative;
display: inline-block;
-webkit-text-stroke: 1px white;
}
}
height: fit-content;
max-height: 10rem;
display: flex;
flex-direction: column;
p {
opacity: 0;
transition: opacity 1s;
}
&.selected {
p {
opacity: 1;
}
}
}
}
.media {
max-width: 600px;
width: 100%;
display: flex;
height: 100%;
align-items: center;
flex-grow: 1;
@media @mobile {
width: 100%;
}
overflow: visible;
svg {
width: 100%;
transition: fill 1s ease;
overflow: visible;
}
}
@media @mobile {
flex-direction: column;
}
}
</style>

View File

@@ -0,0 +1,5 @@
<script lang="ts">
import CoreSellingPoints from "../lib/components/staticPageRows/CoreSellingPoints.svelte"
</script>
<CoreSellingPoints />

View File

@@ -1,6 +1,7 @@
const esbuild = require("esbuild") const esbuild = require("esbuild")
const fs = require("fs") const fs = require("fs")
const path = require("path") const path = require("path")
const less = require("less")
const config = require(process.cwd() + (process.argv?.length > 3 ? "/" + process.argv[3] : "/esbuild.config.js")) const config = require(process.cwd() + (process.argv?.length > 3 ? "/" + process.argv[3] : "/esbuild.config.js"))
const { watch } = require("chokidar") const { watch } = require("chokidar")
@@ -16,6 +17,25 @@ function log(str, clear) {
let buildResults let buildResults
let ctx let ctx
// Funktion zum Transpilieren von LESS zu CSS mit manueller Promisifizierung
function transpileLessToCss(source, destination) {
return new Promise((resolve, reject) => {
fs.readFile(source, "utf8", (err, lessFile) => {
if (err) reject(err)
else {
less.render(lessFile, { filename: path.resolve(source) })
.then((output) => {
fs.writeFile(destination, output.css, (err) => {
if (err) reject(err)
else resolve()
})
})
.catch(reject)
}
})
})
}
async function build(catchError) { async function build(catchError) {
if (!ctx) ctx = await esbuild.context(config.options) if (!ctx) ctx = await esbuild.context(config.options)
log((buildResults ? "re" : "") + "building...") log((buildResults ? "re" : "") + "building...")

View File

@@ -1,16 +1,18 @@
{ {
"extends": "@tsconfig/svelte/tsconfig.json", "extends": "@tsconfig/svelte/tsconfig.json",
"include": [ "include": [
"frontend/src/**/*", "frontend/src/**/*",
"types/**/*", "types/**/*",
"./../../cms/tibi-types" "./../../cms/tibi-types",
"api/**/*",
"frontend/assets/service-worker.js",
"frontend/assets/service-worker.js"
], ],
"compilerOptions": { "compilerOptions": {
"module": "esnext", "module": "esnext",
"typeRoots": [ "typeRoots": ["./node_modules/@types", "./types"],
"./node_modules/@types",
"./types"
],
"target": "esnext", "target": "esnext",
"moduleResolution": "node", "moduleResolution": "node",
"jsx": "preserve", "jsx": "preserve",
@@ -21,14 +23,9 @@
"useDefineForClassFields": true, "useDefineForClassFields": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"verbatimModuleSyntax": true, "verbatimModuleSyntax": true,
"allowJs": true, "allowJs": true,
"checkJs": false, "checkJs": true,
"strictNullChecks": false, "strictNullChecks": false
"noUnusedLocals": true,
"paths": {
"cryptcha": [
"./types/cryptcha"
]
}
} }
} }