diff --git a/buildtime/client/logical-editor/.gitignore b/buildtime/client/logical-editor/.gitignore
deleted file mode 100644
index a547bf36d..000000000
--- a/buildtime/client/logical-editor/.gitignore
+++ /dev/null
@@ -1,24 +0,0 @@
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-lerna-debug.log*
-
-node_modules
-dist
-dist-ssr
-*.local
-
-# Editor directories and files
-.vscode/*
-!.vscode/extensions.json
-.idea
-.DS_Store
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?
diff --git a/buildtime/client/logical-editor/.oxlintrc.json b/buildtime/client/logical-editor/.oxlintrc.json
deleted file mode 100644
index 125507823..000000000
--- a/buildtime/client/logical-editor/.oxlintrc.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "$schema": "./node_modules/oxlint/configuration_schema.json",
- "plugins": ["react", "oxc"],
- "rules": {
- "react/rules-of-hooks": "error",
- "react/only-export-components": ["warn", { "allowConstantExport": true }]
- }
-}
diff --git a/buildtime/client/logical-editor/README.md b/buildtime/client/logical-editor/README.md
deleted file mode 100644
index d937833bd..000000000
--- a/buildtime/client/logical-editor/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# React + Vite
-
-This template provides a minimal setup to get React working in Vite with HMR and some Oxlint rules.
-
-Currently, two official plugins are available:
-
-- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
-- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
-
-## React Compiler
-
-The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
-
-## Expanding the Oxlint configuration
-
-If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and Oxlint's TypeScript related rules in your project.
diff --git a/buildtime/client/logical-editor/index.html b/buildtime/client/logical-editor/index.html
deleted file mode 100644
index 7832bfd36..000000000
--- a/buildtime/client/logical-editor/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
- logical-editor
-
-
-
-
-
-
diff --git a/buildtime/client/logical-editor/package-lock.json b/buildtime/client/logical-editor/package-lock.json
deleted file mode 100644
index 4c3653a28..000000000
--- a/buildtime/client/logical-editor/package-lock.json
+++ /dev/null
@@ -1,2174 +0,0 @@
-{
- "name": "logical-editor",
- "version": "0.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "logical-editor",
- "version": "0.0.0",
- "dependencies": {
- "@heroicons/react": "^2.2.0",
- "@tailwindcss/vite": "^4.3.3",
- "react": "^19.2.7",
- "react-arborist": "^3.16.0",
- "react-dom": "^19.2.7",
- "react-router": "^8.3.0",
- "tailwindcss": "^4.3.3"
- },
- "devDependencies": {
- "@types/react": "^19.2.17",
- "@types/react-dom": "^19.2.3",
- "@vitejs/plugin-react": "^6.0.3",
- "oxlint": "^1.71.0",
- "vite": "^8.1.1"
- }
- },
- "node_modules/@babel/runtime": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz",
- "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@emnapi/core": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz",
- "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/wasi-threads": "1.2.2",
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@emnapi/runtime": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz",
- "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@emnapi/wasi-threads": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz",
- "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@heroicons/react": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz",
- "integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==",
- "license": "MIT",
- "peerDependencies": {
- "react": ">= 16 || ^19.0.0-rc"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.13",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
- "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/remapping": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
- "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
- "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.31",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
- "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@napi-rs/wasm-runtime": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz",
- "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@tybys/wasm-util": "^0.10.3"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- },
- "peerDependencies": {
- "@emnapi/core": "^1.7.1",
- "@emnapi/runtime": "^1.7.1"
- }
- },
- "node_modules/@oxc-project/types": {
- "version": "0.139.0",
- "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz",
- "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/Boshen"
- }
- },
- "node_modules/@oxlint/binding-android-arm-eabi": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.76.0.tgz",
- "integrity": "sha512-ZHIE5Zt9AsPDcY4nOlofXt0YfneEeo+QrKMPcPzLf2Z6Q8VtV2W73d7SFJ920WUwyik783u/doKCs3KXdwG+7w==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-android-arm64": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.76.0.tgz",
- "integrity": "sha512-shm/ngQilHK6bs+ElJWa4oHfNj5vL1Gl/iVEJldTQjpr0/67oSgr0KUpbmcnLig5Fo0v/l6j2567A7TOL89ONA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-darwin-arm64": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.76.0.tgz",
- "integrity": "sha512-rvJmrAPKSQ9aWJ6wIS6CK2tJjwzfW0ApQH9qokq6sfDvmHwoyIHxHFMq7z7i7GiV6fdE6s8qvBqWKPTu8RmT6Q==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-darwin-x64": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.76.0.tgz",
- "integrity": "sha512-U/zYdb7VYKGY6pA9Vd2rYl9O/HlCylcOlb5PGPvVLtg+oLGsk6H3XGKEMHKyqD3nmmtmlmwb/8SwU2vfSAtvMw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-freebsd-x64": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.76.0.tgz",
- "integrity": "sha512-WvKG9CAriuo0XNiFzpXjDngUZcRGFNpaK2kLyMUsnJlShxkT96u+BpJQ3KqdQwGOrvI14L6V8bAwXwAYNNY6Jg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-linux-arm-gnueabihf": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.76.0.tgz",
- "integrity": "sha512-qJ5+RH99TqFRq3UCDxkW0zJJu9c+OAHFY72vGlxZLEpuO+MpKo3POgqb8sYipL9KYm8XY6ofb0HsOuvY6hQNqQ==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-linux-arm-musleabihf": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.76.0.tgz",
- "integrity": "sha512-PvPCVptkgVARsucgIqFQQcSmJ6xc6GtnVB5bRBekRahTc9eObMtjHfMjy5M+C2tHt5UCMttWM9RuSk/H9NqYeg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-linux-arm64-gnu": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.76.0.tgz",
- "integrity": "sha512-3KeFDx8Bu4HPAXbuHZOr/oHvN+QT+JQhMw/NYPz7Z071xLSsG27Jfh9PIQVEY7hk1I+jr43ExqRIeJ6VKk2yLw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-linux-arm64-musl": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.76.0.tgz",
- "integrity": "sha512-oPFkkKTgl0K/EIg9fQ8oA3IGcI05/Mq1en04iFa41mmNPT+6KEiByVazTOZZJiHMBBrbsns1YJ2e1Scqwzesjw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-linux-ppc64-gnu": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.76.0.tgz",
- "integrity": "sha512-gN7yZ0eqflA5Fhf1wvHxGUltIV3FsvmB1zhNMDEK9vSHhc7E6qg9CuPeBgPZab66Tjzq6w6kHAtNEvnTHf4cyw==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-linux-riscv64-gnu": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.76.0.tgz",
- "integrity": "sha512-S/HqMbn22mQrjtErUxEoS/a55u8kIeXvreIxiJu5G7Le3UecEd6SQZxrDIpuhtgaFnsY/nVra3ytP+pRljDilA==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-linux-riscv64-musl": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.76.0.tgz",
- "integrity": "sha512-ZIga3097VJZolGZk6SrIAUokIGfRkxRlhiHDUznZptGBfwrhD7pNfD1rzEzsCwvk/1DX0A1bLz+liuNh5QKIVQ==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-linux-s390x-gnu": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.76.0.tgz",
- "integrity": "sha512-ZGiiA7pFzMJSyMWYZTVlPgbTsx+Vl8ihLGMIujPwaslUF7kIPPWAbVmAlTc+9lWDV+DCiB8Ikixu+lSHeOIIWQ==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-linux-x64-gnu": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.76.0.tgz",
- "integrity": "sha512-JLiy5WuvEBFTT6ErIFV35SLzi0R7Iri6MKU6dZbTxfIx8pndbbPs3Mj780nMipBFcPkti+okAPOJ9POKkHFEgg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-linux-x64-musl": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.76.0.tgz",
- "integrity": "sha512-z7lgKQtbo/I1NIe8G5NHLesxJDv0tRSUWTpXKb9Pm3E9nKFKfO4IOSDtFroKgXtOYb0jQbcdH+0wzTyMXVes+A==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-openharmony-arm64": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.76.0.tgz",
- "integrity": "sha512-JOjKymIpb9QcYfEhZsN6h4V9Ivd474W38cNIBRv6bg2TbIvogbMTH0Mg6YWW9TiRDqfcX+/Hyfsbo5vcSE5guQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-win32-arm64-msvc": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.76.0.tgz",
- "integrity": "sha512-pqDWZiwcmByWUEm1NFUBNiT6aentCcaoMWJv0HbXEmuYermJ4sg8ppVrshubYP2MZ6SHccJJcpr6x469PuDFIw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-win32-ia32-msvc": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.76.0.tgz",
- "integrity": "sha512-Ba0O659kgMv6pwO3z9PdO+K3aMxQRaw9HnG+e6AtOfgwcKFvYilciQYBoUBmxfQvOCKZe1SwjMkuB542NkuDMQ==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@oxlint/binding-win32-x64-msvc": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.76.0.tgz",
- "integrity": "sha512-5qcirPHO8nKfkoowEVWtpAoVTcYDy6g0UT0NGic450Qv8J2NrOqg4uQ8QppRP4MDTC7Xx47lbZnmadTH03CGGA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@react-dnd/asap": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-4.0.1.tgz",
- "integrity": "sha512-kLy0PJDDwvwwTXxqTFNAAllPHD73AycE9ypWeln/IguoGBEbvFcPDbCV03G52bEcC5E+YgupBE0VzHGdC8SIXg==",
- "license": "MIT"
- },
- "node_modules/@react-dnd/invariant": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-2.0.0.tgz",
- "integrity": "sha512-xL4RCQBCBDJ+GRwKTFhGUW8GXa4yoDfJrPbLblc3U09ciS+9ZJXJ3Qrcs/x2IODOdIE5kQxvMmE2UKyqUictUw==",
- "license": "MIT"
- },
- "node_modules/@react-dnd/shallowequal": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz",
- "integrity": "sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==",
- "license": "MIT"
- },
- "node_modules/@rolldown/binding-android-arm64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz",
- "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-darwin-arm64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz",
- "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-darwin-x64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz",
- "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-freebsd-x64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz",
- "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz",
- "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-linux-arm64-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz",
- "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-linux-arm64-musl": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz",
- "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-linux-ppc64-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz",
- "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==",
- "cpu": [
- "ppc64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-linux-s390x-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz",
- "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==",
- "cpu": [
- "s390x"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-linux-x64-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz",
- "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-linux-x64-musl": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz",
- "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-openharmony-arm64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz",
- "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-wasm32-wasi": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz",
- "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==",
- "cpu": [
- "wasm32"
- ],
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/core": "1.11.1",
- "@emnapi/runtime": "1.11.1",
- "@napi-rs/wasm-runtime": "^1.1.6"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-win32-arm64-msvc": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz",
- "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/binding-win32-x64-msvc": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz",
- "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- }
- },
- "node_modules/@rolldown/pluginutils": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz",
- "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==",
- "license": "MIT"
- },
- "node_modules/@tailwindcss/node": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz",
- "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/remapping": "^2.3.5",
- "enhanced-resolve": "^5.24.1",
- "jiti": "^2.7.0",
- "lightningcss": "1.32.0",
- "magic-string": "^0.30.21",
- "source-map-js": "^1.2.1",
- "tailwindcss": "4.3.3"
- }
- },
- "node_modules/@tailwindcss/node/node_modules/lightningcss": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
- "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
- "license": "MPL-2.0",
- "dependencies": {
- "detect-libc": "^2.0.3"
- },
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- },
- "optionalDependencies": {
- "lightningcss-android-arm64": "1.32.0",
- "lightningcss-darwin-arm64": "1.32.0",
- "lightningcss-darwin-x64": "1.32.0",
- "lightningcss-freebsd-x64": "1.32.0",
- "lightningcss-linux-arm-gnueabihf": "1.32.0",
- "lightningcss-linux-arm64-gnu": "1.32.0",
- "lightningcss-linux-arm64-musl": "1.32.0",
- "lightningcss-linux-x64-gnu": "1.32.0",
- "lightningcss-linux-x64-musl": "1.32.0",
- "lightningcss-win32-arm64-msvc": "1.32.0",
- "lightningcss-win32-x64-msvc": "1.32.0"
- }
- },
- "node_modules/@tailwindcss/node/node_modules/lightningcss-android-arm64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz",
- "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@tailwindcss/node/node_modules/lightningcss-darwin-arm64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz",
- "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@tailwindcss/node/node_modules/lightningcss-darwin-x64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz",
- "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@tailwindcss/node/node_modules/lightningcss-freebsd-x64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz",
- "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@tailwindcss/node/node_modules/lightningcss-linux-arm-gnueabihf": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz",
- "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==",
- "cpu": [
- "arm"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@tailwindcss/node/node_modules/lightningcss-linux-arm64-gnu": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz",
- "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@tailwindcss/node/node_modules/lightningcss-linux-arm64-musl": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz",
- "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@tailwindcss/node/node_modules/lightningcss-linux-x64-gnu": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz",
- "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@tailwindcss/node/node_modules/lightningcss-linux-x64-musl": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz",
- "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@tailwindcss/node/node_modules/lightningcss-win32-arm64-msvc": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz",
- "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@tailwindcss/node/node_modules/lightningcss-win32-x64-msvc": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
- "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/@tailwindcss/oxide": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz",
- "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==",
- "license": "MIT",
- "engines": {
- "node": ">= 20"
- },
- "optionalDependencies": {
- "@tailwindcss/oxide-android-arm64": "4.3.3",
- "@tailwindcss/oxide-darwin-arm64": "4.3.3",
- "@tailwindcss/oxide-darwin-x64": "4.3.3",
- "@tailwindcss/oxide-freebsd-x64": "4.3.3",
- "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3",
- "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3",
- "@tailwindcss/oxide-linux-arm64-musl": "4.3.3",
- "@tailwindcss/oxide-linux-x64-gnu": "4.3.3",
- "@tailwindcss/oxide-linux-x64-musl": "4.3.3",
- "@tailwindcss/oxide-wasm32-wasi": "4.3.3",
- "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3",
- "@tailwindcss/oxide-win32-x64-msvc": "4.3.3"
- }
- },
- "node_modules/@tailwindcss/oxide-android-arm64": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz",
- "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-arm64": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz",
- "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-x64": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz",
- "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-freebsd-x64": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz",
- "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz",
- "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz",
- "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz",
- "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz",
- "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-x64-musl": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz",
- "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-wasm32-wasi": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz",
- "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==",
- "bundleDependencies": [
- "@napi-rs/wasm-runtime",
- "@emnapi/core",
- "@emnapi/runtime",
- "@tybys/wasm-util",
- "@emnapi/wasi-threads",
- "tslib"
- ],
- "cpu": [
- "wasm32"
- ],
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/core": "^1.11.1",
- "@emnapi/runtime": "^1.11.1",
- "@emnapi/wasi-threads": "^1.2.2",
- "@napi-rs/wasm-runtime": "^1.1.4",
- "@tybys/wasm-util": "^0.10.2",
- "tslib": "^2.8.1"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz",
- "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz",
- "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/vite": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.3.tgz",
- "integrity": "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==",
- "license": "MIT",
- "dependencies": {
- "@tailwindcss/node": "4.3.3",
- "@tailwindcss/oxide": "4.3.3",
- "tailwindcss": "4.3.3"
- },
- "peerDependencies": {
- "vite": "^5.2.0 || ^6 || ^7 || ^8"
- }
- },
- "node_modules/@tybys/wasm-util": {
- "version": "0.10.3",
- "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz",
- "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@types/react": {
- "version": "19.2.17",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz",
- "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "csstype": "^3.2.2"
- }
- },
- "node_modules/@types/react-dom": {
- "version": "19.2.3",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
- "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "^19.2.0"
- }
- },
- "node_modules/@vitejs/plugin-react": {
- "version": "6.0.4",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.4.tgz",
- "integrity": "sha512-XcCQz0TBpBgljhj0gMuuDj49i6Ytqh5q1osT/Gp5uAVJUCTWxyskk/l1jwYYiu2xcNHHipdMz40EGfM1VdamVg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@rolldown/pluginutils": "^1.0.1"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- },
- "peerDependencies": {
- "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0",
- "babel-plugin-react-compiler": "^1.0.0",
- "vite": "^8.0.0"
- },
- "peerDependenciesMeta": {
- "@rolldown/plugin-babel": {
- "optional": true
- },
- "babel-plugin-react-compiler": {
- "optional": true
- }
- }
- },
- "node_modules/cookie-es": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-3.1.1.tgz",
- "integrity": "sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==",
- "license": "MIT"
- },
- "node_modules/csstype": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
- "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/detect-libc": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
- "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/dnd-core": {
- "version": "14.0.1",
- "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-14.0.1.tgz",
- "integrity": "sha512-+PVS2VPTgKFPYWo3vAFEA8WPbTf7/xo43TifH9G8S1KqnrQu0o77A3unrF5yOugy4mIz7K5wAVFHUcha7wsz6A==",
- "license": "MIT",
- "dependencies": {
- "@react-dnd/asap": "^4.0.0",
- "@react-dnd/invariant": "^2.0.0",
- "redux": "^4.1.1"
- }
- },
- "node_modules/dnd-core/node_modules/redux": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
- "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.9.2"
- }
- },
- "node_modules/enhanced-resolve": {
- "version": "5.24.5",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz",
- "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.4",
- "tapable": "^2.3.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "license": "MIT"
- },
- "node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "license": "ISC"
- },
- "node_modules/hoist-non-react-statics": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
- "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "react-is": "^16.7.0"
- }
- },
- "node_modules/jiti": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
- "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
- "license": "MIT",
- "bin": {
- "jiti": "lib/jiti-cli.mjs"
- }
- },
- "node_modules/lightningcss": {
- "version": "1.33.0",
- "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz",
- "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==",
- "license": "MPL-2.0",
- "dependencies": {
- "detect-libc": "^2.0.3"
- },
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- },
- "optionalDependencies": {
- "lightningcss-android-arm64": "1.33.0",
- "lightningcss-darwin-arm64": "1.33.0",
- "lightningcss-darwin-x64": "1.33.0",
- "lightningcss-freebsd-x64": "1.33.0",
- "lightningcss-linux-arm-gnueabihf": "1.33.0",
- "lightningcss-linux-arm64-gnu": "1.33.0",
- "lightningcss-linux-arm64-musl": "1.33.0",
- "lightningcss-linux-x64-gnu": "1.33.0",
- "lightningcss-linux-x64-musl": "1.33.0",
- "lightningcss-win32-arm64-msvc": "1.33.0",
- "lightningcss-win32-x64-msvc": "1.33.0"
- }
- },
- "node_modules/lightningcss-android-arm64": {
- "version": "1.33.0",
- "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz",
- "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-darwin-arm64": {
- "version": "1.33.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz",
- "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-darwin-x64": {
- "version": "1.33.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz",
- "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-freebsd-x64": {
- "version": "1.33.0",
- "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz",
- "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm-gnueabihf": {
- "version": "1.33.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz",
- "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==",
- "cpu": [
- "arm"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm64-gnu": {
- "version": "1.33.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz",
- "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm64-musl": {
- "version": "1.33.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz",
- "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==",
- "cpu": [
- "arm64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-x64-gnu": {
- "version": "1.33.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz",
- "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "glibc"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-x64-musl": {
- "version": "1.33.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz",
- "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==",
- "cpu": [
- "x64"
- ],
- "libc": [
- "musl"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-win32-arm64-msvc": {
- "version": "1.33.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz",
- "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-win32-x64-msvc": {
- "version": "1.33.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz",
- "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/magic-string": {
- "version": "0.30.21",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
- "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.5"
- }
- },
- "node_modules/memoize-one": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
- "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
- "license": "MIT"
- },
- "node_modules/nanoid": {
- "version": "3.3.16",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz",
- "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/oxlint": {
- "version": "1.76.0",
- "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.76.0.tgz",
- "integrity": "sha512-6QoFioEU4fNdiUx/2Eo6TRd6NG7H7njnRCz8rhB66cZmMHDTqcm1Rjvl8Wry+ZTQMBAmyb4Mlf62Mk5X+eHSOw==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "oxlint": "bin/oxlint"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/Boshen"
- },
- "optionalDependencies": {
- "@oxlint/binding-android-arm-eabi": "1.76.0",
- "@oxlint/binding-android-arm64": "1.76.0",
- "@oxlint/binding-darwin-arm64": "1.76.0",
- "@oxlint/binding-darwin-x64": "1.76.0",
- "@oxlint/binding-freebsd-x64": "1.76.0",
- "@oxlint/binding-linux-arm-gnueabihf": "1.76.0",
- "@oxlint/binding-linux-arm-musleabihf": "1.76.0",
- "@oxlint/binding-linux-arm64-gnu": "1.76.0",
- "@oxlint/binding-linux-arm64-musl": "1.76.0",
- "@oxlint/binding-linux-ppc64-gnu": "1.76.0",
- "@oxlint/binding-linux-riscv64-gnu": "1.76.0",
- "@oxlint/binding-linux-riscv64-musl": "1.76.0",
- "@oxlint/binding-linux-s390x-gnu": "1.76.0",
- "@oxlint/binding-linux-x64-gnu": "1.76.0",
- "@oxlint/binding-linux-x64-musl": "1.76.0",
- "@oxlint/binding-openharmony-arm64": "1.76.0",
- "@oxlint/binding-win32-arm64-msvc": "1.76.0",
- "@oxlint/binding-win32-ia32-msvc": "1.76.0",
- "@oxlint/binding-win32-x64-msvc": "1.76.0"
- },
- "peerDependencies": {
- "oxlint-tsgolint": ">=7.0.2001",
- "vite-plus": "*"
- },
- "peerDependenciesMeta": {
- "oxlint-tsgolint": {
- "optional": true
- },
- "vite-plus": {
- "optional": true
- }
- }
- },
- "node_modules/picocolors": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "license": "ISC"
- },
- "node_modules/picomatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
- "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/postcss": {
- "version": "8.5.23",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz",
- "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "nanoid": "^3.3.16",
- "picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/react": {
- "version": "19.2.8",
- "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz",
- "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/react-arborist": {
- "version": "3.16.0",
- "resolved": "https://registry.npmjs.org/react-arborist/-/react-arborist-3.16.0.tgz",
- "integrity": "sha512-Pp1TQXETKMeg/0yAMGBFIwze7IfZaghDScX4vekJ4Ge8/t7uYifbDBhEGUSOYaDuahE1f8fyBIrlN2pLD4ysTA==",
- "license": "MIT",
- "dependencies": {
- "react-dnd": "^14.0.3",
- "react-dnd-html5-backend": "^14.0.3",
- "react-window": "^1.8.11",
- "redux": "^5.0.0",
- "use-sync-external-store": "^1.2.0"
- },
- "peerDependencies": {
- "react": ">= 16.14",
- "react-dom": ">= 16.14"
- }
- },
- "node_modules/react-dnd": {
- "version": "14.0.5",
- "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-14.0.5.tgz",
- "integrity": "sha512-9i1jSgbyVw0ELlEVt/NkCUkxy1hmhJOkePoCH713u75vzHGyXhPDm28oLfc2NMSBjZRM1Y+wRjHXJT3sPrTy+A==",
- "license": "MIT",
- "dependencies": {
- "@react-dnd/invariant": "^2.0.0",
- "@react-dnd/shallowequal": "^2.0.0",
- "dnd-core": "14.0.1",
- "fast-deep-equal": "^3.1.3",
- "hoist-non-react-statics": "^3.3.2"
- },
- "peerDependencies": {
- "@types/hoist-non-react-statics": ">= 3.3.1",
- "@types/node": ">= 12",
- "@types/react": ">= 16",
- "react": ">= 16.14"
- },
- "peerDependenciesMeta": {
- "@types/hoist-non-react-statics": {
- "optional": true
- },
- "@types/node": {
- "optional": true
- },
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/react-dnd-html5-backend": {
- "version": "14.1.0",
- "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-14.1.0.tgz",
- "integrity": "sha512-6ONeqEC3XKVf4eVmMTe0oPds+c5B9Foyj8p/ZKLb7kL2qh9COYxiBHv3szd6gztqi/efkmriywLUVlPotqoJyw==",
- "license": "MIT",
- "dependencies": {
- "dnd-core": "14.0.1"
- }
- },
- "node_modules/react-dom": {
- "version": "19.2.8",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz",
- "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==",
- "license": "MIT",
- "dependencies": {
- "scheduler": "^0.27.0"
- },
- "peerDependencies": {
- "react": "^19.2.8"
- }
- },
- "node_modules/react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "license": "MIT"
- },
- "node_modules/react-router": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/react-router/-/react-router-8.3.0.tgz",
- "integrity": "sha512-qyPMvW83jGIct3yiieisxdk9M745anqhpIMKN5m1t6yBMfgVPpt77aHOqs5fUlEJRMCGffg9BaQLH9oPVOL7xQ==",
- "license": "MIT",
- "dependencies": {
- "cookie-es": "^3.1.1"
- },
- "engines": {
- "node": ">=22.22.0"
- },
- "peerDependencies": {
- "react": ">=19.2.7",
- "react-dom": ">=19.2.7"
- },
- "peerDependenciesMeta": {
- "react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/react-window": {
- "version": "1.8.11",
- "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.11.tgz",
- "integrity": "sha512-+SRbUVT2scadgFSWx+R1P754xHPEqvcfSfVX10QYg6POOz+WNgkN48pS+BtZNIMGiL1HYrSEiCkwsMS15QogEQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.0.0",
- "memoize-one": ">=3.1.1 <6"
- },
- "engines": {
- "node": ">8.0.0"
- },
- "peerDependencies": {
- "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
- "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
- }
- },
- "node_modules/redux": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
- "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
- "license": "MIT"
- },
- "node_modules/rolldown": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz",
- "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==",
- "license": "MIT",
- "dependencies": {
- "@oxc-project/types": "=0.139.0",
- "@rolldown/pluginutils": "^1.0.0"
- },
- "bin": {
- "rolldown": "bin/cli.mjs"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- },
- "optionalDependencies": {
- "@rolldown/binding-android-arm64": "1.1.5",
- "@rolldown/binding-darwin-arm64": "1.1.5",
- "@rolldown/binding-darwin-x64": "1.1.5",
- "@rolldown/binding-freebsd-x64": "1.1.5",
- "@rolldown/binding-linux-arm-gnueabihf": "1.1.5",
- "@rolldown/binding-linux-arm64-gnu": "1.1.5",
- "@rolldown/binding-linux-arm64-musl": "1.1.5",
- "@rolldown/binding-linux-ppc64-gnu": "1.1.5",
- "@rolldown/binding-linux-s390x-gnu": "1.1.5",
- "@rolldown/binding-linux-x64-gnu": "1.1.5",
- "@rolldown/binding-linux-x64-musl": "1.1.5",
- "@rolldown/binding-openharmony-arm64": "1.1.5",
- "@rolldown/binding-wasm32-wasi": "1.1.5",
- "@rolldown/binding-win32-arm64-msvc": "1.1.5",
- "@rolldown/binding-win32-x64-msvc": "1.1.5"
- }
- },
- "node_modules/scheduler": {
- "version": "0.27.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
- "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
- "license": "MIT"
- },
- "node_modules/source-map-js": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
- "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/tailwindcss": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz",
- "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==",
- "license": "MIT"
- },
- "node_modules/tapable": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
- "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/webpack"
- }
- },
- "node_modules/tinyglobby": {
- "version": "0.2.17",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
- "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
- "license": "MIT",
- "dependencies": {
- "fdir": "^6.5.0",
- "picomatch": "^4.0.4"
- },
- "engines": {
- "node": ">=12.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/SuperchupuDev"
- }
- },
- "node_modules/tslib": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
- "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
- "license": "0BSD",
- "optional": true
- },
- "node_modules/use-sync-external-store": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
- "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
- "license": "MIT",
- "peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
- }
- },
- "node_modules/vite": {
- "version": "8.1.5",
- "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz",
- "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==",
- "license": "MIT",
- "dependencies": {
- "lightningcss": "^1.32.0",
- "picomatch": "^4.0.5",
- "postcss": "^8.5.17",
- "rolldown": "~1.1.5",
- "tinyglobby": "^0.2.17"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- },
- "peerDependencies": {
- "@types/node": "^20.19.0 || >=22.12.0",
- "@vitejs/devtools": "^0.3.0",
- "esbuild": "^0.27.0 || ^0.28.0",
- "jiti": ">=1.21.0",
- "less": "^4.0.0",
- "sass": "^1.70.0",
- "sass-embedded": "^1.70.0",
- "stylus": ">=0.54.8",
- "sugarss": "^5.0.0",
- "terser": "^5.16.0",
- "tsx": "^4.8.1",
- "yaml": "^2.4.2"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "@vitejs/devtools": {
- "optional": true
- },
- "esbuild": {
- "optional": true
- },
- "jiti": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "sass-embedded": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- },
- "tsx": {
- "optional": true
- },
- "yaml": {
- "optional": true
- }
- }
- }
- }
-}
diff --git a/buildtime/client/logical-editor/package.json b/buildtime/client/logical-editor/package.json
deleted file mode 100644
index 9dbe73527..000000000
--- a/buildtime/client/logical-editor/package.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "name": "logical-editor",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "dev": "vite",
- "build": "vite build",
- "lint": "oxlint",
- "preview": "vite preview"
- },
- "dependencies": {
- "@heroicons/react": "^2.2.0",
- "@tailwindcss/vite": "^4.3.3",
- "react": "^19.2.7",
- "react-arborist": "^3.16.0",
- "react-dom": "^19.2.7",
- "react-router": "^8.3.0",
- "tailwindcss": "^4.3.3"
- },
- "devDependencies": {
- "@types/react": "^19.2.17",
- "@types/react-dom": "^19.2.3",
- "@vitejs/plugin-react": "^6.0.3",
- "oxlint": "^1.71.0",
- "vite": "^8.1.1"
- }
-}
diff --git a/buildtime/client/logical-editor/public/SimplyCPQ_Logo.svg b/buildtime/client/logical-editor/public/SimplyCPQ_Logo.svg
deleted file mode 100644
index deca30faa..000000000
--- a/buildtime/client/logical-editor/public/SimplyCPQ_Logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/buildtime/client/logical-editor/public/favicon.svg b/buildtime/client/logical-editor/public/favicon.svg
deleted file mode 100644
index 6893eb132..000000000
--- a/buildtime/client/logical-editor/public/favicon.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/buildtime/client/logical-editor/public/icons.svg b/buildtime/client/logical-editor/public/icons.svg
deleted file mode 100644
index e9522193d..000000000
--- a/buildtime/client/logical-editor/public/icons.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/buildtime/client/logical-editor/src/99_Archive/App-orig.css b/buildtime/client/logical-editor/src/99_Archive/App-orig.css
deleted file mode 100644
index f90339d8f..000000000
--- a/buildtime/client/logical-editor/src/99_Archive/App-orig.css
+++ /dev/null
@@ -1,184 +0,0 @@
-.counter {
- font-size: 16px;
- padding: 5px 10px;
- border-radius: 5px;
- color: var(--accent);
- background: var(--accent-bg);
- border: 2px solid transparent;
- transition: border-color 0.3s;
- margin-bottom: 24px;
-
- &:hover {
- border-color: var(--accent-border);
- }
- &:focus-visible {
- outline: 2px solid var(--accent);
- outline-offset: 2px;
- }
-}
-
-.hero {
- position: relative;
-
- .base,
- .framework,
- .vite {
- inset-inline: 0;
- margin: 0 auto;
- }
-
- .base {
- width: 170px;
- position: relative;
- z-index: 0;
- }
-
- .framework,
- .vite {
- position: absolute;
- }
-
- .framework {
- z-index: 1;
- top: 34px;
- height: 28px;
- transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)
- scale(1.4);
- }
-
- .vite {
- z-index: 0;
- top: 107px;
- height: 26px;
- width: auto;
- transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)
- scale(0.8);
- }
-}
-
-#center {
- display: flex;
- flex-direction: column;
- gap: 25px;
- place-content: center;
- place-items: center;
- flex-grow: 1;
-
- @media (max-width: 1024px) {
- padding: 32px 20px 24px;
- gap: 18px;
- }
-}
-
-#next-steps {
- display: flex;
- border-top: 1px solid var(--border);
- text-align: left;
-
- & > div {
- flex: 1 1 0;
- padding: 32px;
- @media (max-width: 1024px) {
- padding: 24px 20px;
- }
- }
-
- .icon {
- margin-bottom: 16px;
- width: 22px;
- height: 22px;
- }
-
- @media (max-width: 1024px) {
- flex-direction: column;
- text-align: center;
- }
-}
-
-#docs {
- border-right: 1px solid var(--border);
-
- @media (max-width: 1024px) {
- border-right: none;
- border-bottom: 1px solid var(--border);
- }
-}
-
-#next-steps ul {
- list-style: none;
- padding: 0;
- display: flex;
- gap: 8px;
- margin: 32px 0 0;
-
- .logo {
- height: 18px;
- }
-
- a {
- color: var(--text-h);
- font-size: 16px;
- border-radius: 6px;
- background: var(--social-bg);
- display: flex;
- padding: 6px 12px;
- align-items: center;
- gap: 8px;
- text-decoration: none;
- transition: box-shadow 0.3s;
-
- &:hover {
- box-shadow: var(--shadow);
- }
- .button-icon {
- height: 18px;
- width: 18px;
- }
- }
-
- @media (max-width: 1024px) {
- margin-top: 20px;
- flex-wrap: wrap;
- justify-content: center;
-
- li {
- flex: 1 1 calc(50% - 8px);
- }
-
- a {
- width: 100%;
- justify-content: center;
- box-sizing: border-box;
- }
- }
-}
-
-#spacer {
- height: 88px;
- border-top: 1px solid var(--border);
- @media (max-width: 1024px) {
- height: 48px;
- }
-}
-
-.ticks {
- position: relative;
- width: 100%;
-
- &::before,
- &::after {
- content: '';
- position: absolute;
- top: -4.5px;
- border: 5px solid transparent;
- }
-
- &::before {
- left: 0;
- border-left-color: var(--border);
- }
- &::after {
- right: 0;
- border-right-color: var(--border);
- }
-}
diff --git a/buildtime/client/logical-editor/src/99_Archive/App-orig.jsx b/buildtime/client/logical-editor/src/99_Archive/App-orig.jsx
deleted file mode 100644
index e76cedf12..000000000
--- a/buildtime/client/logical-editor/src/99_Archive/App-orig.jsx
+++ /dev/null
@@ -1,122 +0,0 @@
-import { useState } from 'react'
-import reactLogo from './assets/react.svg'
-import viteLogo from './assets/vite.svg'
-import heroImg from './assets/hero.png'
-import './App.css'
-
-function App() {
- const [count, setCount] = useState(0)
-
- return (
- <>
-
-
-
-
Hello World
-
- Edit src/App.jsx and save to test HMR
-
-
- setCount((count) => count + 1)}
- >
- Count is {count}
-
-
-
-
-
-
-
-
-
-
-
Documentation
-
Your questions, answered
-
-
-
-
-
-
-
Connect with us
-
Join the Vite community
-
-
-
-
-
-
- >
- )
-}
-
-export default App
diff --git a/buildtime/client/logical-editor/src/99_Archive/hero.png b/buildtime/client/logical-editor/src/99_Archive/hero.png
deleted file mode 100644
index 02251f4b9..000000000
Binary files a/buildtime/client/logical-editor/src/99_Archive/hero.png and /dev/null differ
diff --git a/buildtime/client/logical-editor/src/99_Archive/react.svg b/buildtime/client/logical-editor/src/99_Archive/react.svg
deleted file mode 100644
index 6c87de9bb..000000000
--- a/buildtime/client/logical-editor/src/99_Archive/react.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/buildtime/client/logical-editor/src/99_Archive/vite.svg b/buildtime/client/logical-editor/src/99_Archive/vite.svg
deleted file mode 100644
index 5101b674d..000000000
--- a/buildtime/client/logical-editor/src/99_Archive/vite.svg
+++ /dev/null
@@ -1 +0,0 @@
-Vite
diff --git a/buildtime/client/logical-editor/src/App.css b/buildtime/client/logical-editor/src/App.css
deleted file mode 100644
index a5178b641..000000000
--- a/buildtime/client/logical-editor/src/App.css
+++ /dev/null
@@ -1,176 +0,0 @@
-
-
-.navbar {
- padding: 16px;
- color: gray;
- display: flex;
- flex-flow: row;
- background: var(--code-bg);
- box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
- height: 80px;
-}
-
-.navbar h1 {
- font-size: 32px;
- letter-spacing: -1.68px;
- margin: 4px 10px 0 0;
- @media (max-width: 1024px) {
- font-size: 20px;
- margin: 20px 0;
- }
-}
-
-.nav-links{
- display: flex;
- align-items: center;
- margin-left: auto;
- padding-right: 16px;
- padding-left: 16px;
-}
-
-.nav-links a {
- color: gray;
- text-decoration: none;
- margin-left: 16px;
- font-size: 20px;
- letter-spacing: -1px;
-}
-
-.logo {
- width: 55px;
- height: 55px;
- float: right;
- align-items: right;
- margin-right: 5px;
- margin-left: 5px;
- margin-top: -5px;
-}
-
-.sidebar {
- display: flex;
- flex-flow: column;
- padding: 16px;
- color: gray;
- background: var(--code-bg);
- box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
- width: 300px;
-}
-
-.sidebar h1 {
- font-size: 24px;
- letter-spacing: -1.68px;
- margin: 4px 10px 0 0;
- @media (max-width: 1024px) {
- font-size: 14px;
- margin: 20px 0;
- }
-}
-
-.treeElement p {
- font-size: 12px;
- margin: 8px 16px 0 0;
-}
-
-.treeElement {
- background: whitesmoke;
- border-inline: 1px solid var(--border);
- box-sizing: border-box;
- box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
-}
-
-.treeElement h2 {
- font-size: 14px;
- color: gray;
- letter-spacing: -1px;
- margin: 4px 16px 0 0;
-}
-
-.spacer {
- display: flex;
- flex-flow: column;
- height: 1vh;
-}
-
-.side-links {
- font-size: 12px;
- background: whitesmoke;
- overflow: auto;
- height: 70vh;
-}
-
-footer {
- padding: 16px;
- color: gray;
- display: flex;
- background: var(--code-bg);
- box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
- height: 40px;
-}
-
-
-.editor {
- display: flex;
- flex-flow: column;
- padding: 16px;
- margin: 16px;
- color: gray;
- background: whitesmoke;
- box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
- width: 100%;
-}
-
-.editor-title {
- font-size: 24px;
- letter-spacing: -1.68px;
- margin: 16px;
- @media (max-width: 1024px) {
- font-size: 14px;
- margin: 20px 0;
- }
-}
-
-input[type="text"] {
- width: 100%; /* Full width */
- padding: 2px; /* Inner spacing */
- margin: 8px 0; /* Space around */
- box-sizing: border-box; /* Include padding in width */
- border: 2px solid #000000; /* Green border */
- border-radius: 10px; /* Rounded corners */
- background-color: #ffffff; /* Light background */
- font-size: 16px; /* Text size */
-}
-
-input[type="text"]:focus {
- border-color: #45a049; /* Darker green on focus */
- outline: none; /* Remove default outline */
-}
-
-textarea {
- width: 100%; /* Full width */
- height: 150px;
- padding: 2px; /* Inner spacing */
- margin: 8px 0; /* Space around */
- box-sizing: border-box; /* Include padding in width */
- border: 2px solid #000000; /* Green border */
- border-radius: 10px; /* Rounded corners */
- background-color: #ffffff; /* Light background */
- font-size: 16px; /* Text size */
-}
-
-textarea:focus {
- border-color: #45a049; /* Darker green on focus */
- outline: none; /* Remove default outline */
-}
-
-.main {
- display: flex;
- flex-flow: column;
- padding: 16px;
- margin: 16px;
- color: gray;
- background: whitesmoke;
- box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
- width: 100%;
-}
-
-@import "tailwindcss";
diff --git a/buildtime/client/logical-editor/src/App.jsx b/buildtime/client/logical-editor/src/App.jsx
deleted file mode 100644
index ed09e1fad..000000000
--- a/buildtime/client/logical-editor/src/App.jsx
+++ /dev/null
@@ -1,29 +0,0 @@
-// Main App
-
-import { createBrowserRouter, RouterProvider } from 'react-router'
-import Layout from './Layout.jsx'
-import HomePage from './pages/HomePage.jsx'
-import LanguagePage from './pages/LanguagePage.jsx'
-import PropertyPage from './pages/PropertyPage.jsx'
-import NotFoundPage from './pages/NotFoundPage.jsx'
-
-import './App.css'
-
-const router = createBrowserRouter([
- {
- path: '/',
- element: ,
- children: [
- { index: true, element: },
- { path: 'language', element: },
- { path: 'propertypool', element: },
- { path: '*', element: },
- ],
- },
-])
-
-function App() {
- return
-}
-
-export default App
diff --git a/buildtime/client/logical-editor/src/Layout.jsx b/buildtime/client/logical-editor/src/Layout.jsx
deleted file mode 100644
index c9e2d07ac..000000000
--- a/buildtime/client/logical-editor/src/Layout.jsx
+++ /dev/null
@@ -1,19 +0,0 @@
-// Layouting Main Application
-
-import { Outlet, Link } from 'react-router'
-import NavBar from './components/NavBar.jsx'
-
-
-function Layout() {
- return (
-
- )
-}
-
-export default Layout
\ No newline at end of file
diff --git a/buildtime/client/logical-editor/src/assets/SimplyCPQ_Logo.svg b/buildtime/client/logical-editor/src/assets/SimplyCPQ_Logo.svg
deleted file mode 100644
index deca30faa..000000000
--- a/buildtime/client/logical-editor/src/assets/SimplyCPQ_Logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/buildtime/client/logical-editor/src/components/EditPropertyGroup.jsx b/buildtime/client/logical-editor/src/components/EditPropertyGroup.jsx
deleted file mode 100644
index 59ff45231..000000000
--- a/buildtime/client/logical-editor/src/components/EditPropertyGroup.jsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import React, { useState } from 'react';
-
-const EditPropertyGroup = ({ propertyGroup, onClose }) => {
- const [labelTranslation, setLabelTranslation] = useState(propertyGroup.labelTranslation);
- const [description, setDescription] = useState(propertyGroup.description);
-
- return (
-
-
Edit Property Group
-
-
-
- Name:
- setLabelTranslation(e.target.value)} />
-
-
-
-
- Description:
-
-
-
-
Save
-
- );
-};
-
-export default EditPropertyGroup;
diff --git a/buildtime/client/logical-editor/src/components/LangSideBar.jsx b/buildtime/client/logical-editor/src/components/LangSideBar.jsx
deleted file mode 100644
index c7292de15..000000000
--- a/buildtime/client/logical-editor/src/components/LangSideBar.jsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import React, { Component } from 'react';
-import { useState } from 'react'
-import LanguageElement from './LanguageElement';
-
-const LangSideBar = () => {
- return (
-
-
-
Available Languages:
-
-
-
-
-
-
- ...
-
- );
-};
-
-export default LangSideBar;
diff --git a/buildtime/client/logical-editor/src/components/LanguageElement.jsx b/buildtime/client/logical-editor/src/components/LanguageElement.jsx
deleted file mode 100644
index ea2617b44..000000000
--- a/buildtime/client/logical-editor/src/components/LanguageElement.jsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import { useState } from 'react'
-import UseFetch from './tools/UseFetch';
-
-const LanguageElement = ({ languageid }) => {
- const { data: lang, isLoading, error } = UseFetch(`http://localhost:8088/language/${languageid}`)
-
- if (isLoading) return Loading profile...
- if (error) return Error: {error}
-
- return (
-
-
Language: {lang.language}
-
Locale: {lang.locale}
-
- );
-}
-
-export default LanguageElement;
diff --git a/buildtime/client/logical-editor/src/components/NavBar.jsx b/buildtime/client/logical-editor/src/components/NavBar.jsx
deleted file mode 100644
index 6f162c5df..000000000
--- a/buildtime/client/logical-editor/src/components/NavBar.jsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import React from 'react';
-import { Link } from 'react-router';
-import scpqLogo from '../assets/SimplyCPQ_Logo.svg';
-
-const NavBar = () => {
- return (
-
-
-
- Home
- Property Pool
- Language
-
-
-
-
-
- );
-};
-
-export default NavBar;
-
-
\ No newline at end of file
diff --git a/buildtime/client/logical-editor/src/components/PropertyGroupContent.jsx b/buildtime/client/logical-editor/src/components/PropertyGroupContent.jsx
deleted file mode 100644
index 044619cb1..000000000
--- a/buildtime/client/logical-editor/src/components/PropertyGroupContent.jsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { useEffect } from "react";
-import ReactDOM from "react-dom";
-
-function PropertyGroupContent({ children, onClose }) {
-
- useEffect(() => {
- const handleEsc = (e) => e.key === "Escape" && onClose();
- window.addEventListener("keydown", handleEsc);
- return () => window.removeEventListener("keydown", handleEsc);
- }, [onClose]);
-
- return ReactDOM.createPortal(
-
-
e.stopPropagation()}>
- {children}
-
-
,
-
- document.getElementById("property-content")
-
- );
-}
-
-export default PropertyGroupContent;
diff --git a/buildtime/client/logical-editor/src/components/PropertySideBar.jsx b/buildtime/client/logical-editor/src/components/PropertySideBar.jsx
deleted file mode 100644
index 5bfd8f631..000000000
--- a/buildtime/client/logical-editor/src/components/PropertySideBar.jsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from 'react';
-import PropertyTreeView from './PropertyTreeView';
-
-const PropertySideBar = ({ properties }) => {
- return (
-
-
-
Property Pool:
-
-
-
- {properties.map((node) => (
-
- ))}
-
-
...
-
- );
-};
-
-export default PropertySideBar;
-
diff --git a/buildtime/client/logical-editor/src/components/PropertyTreeView.jsx b/buildtime/client/logical-editor/src/components/PropertyTreeView.jsx
deleted file mode 100644
index c6af93eb0..000000000
--- a/buildtime/client/logical-editor/src/components/PropertyTreeView.jsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import React, { useState } from 'react';
-import PropertyGroupContent from './PropertyGroupContent';
-import EditPropertyGroup from './EditPropertyGroup';
-import { ChevronRightIcon, DocumentIcon, FolderIcon, DocumentPlusIcon, FolderPlusIcon, PencilIcon } from '@heroicons/react/24/solid';
-
-const PropertyTreeView = ({ node, key }) => {
- const [expanded, setExpanded] = useState(true);
- const [open, setOpen] = useState(false);
- return (
-
-
- {node.subPropertygroups && node.subPropertygroups.length > 0 && (
- setExpanded(!expanded)} className="p-1 -m-1">
-
-
- )}
- {node.labelTranslation}
-
-
- setOpen(true)} className="p-1 -m-1">
-
- {open && (
- setOpen(false)}>
- setOpen(false)} />
-
- )}
-
-
-
-
-
-
-
-
- {expanded && (
-
- {node.subPropertygroups?.map((node) => (
-
- ))}
-
- )}
-
-
- );
-};
-
-export default PropertyTreeView;
-
-
diff --git a/buildtime/client/logical-editor/src/components/tools/UseFetch.jsx b/buildtime/client/logical-editor/src/components/tools/UseFetch.jsx
deleted file mode 100644
index 58c893311..000000000
--- a/buildtime/client/logical-editor/src/components/tools/UseFetch.jsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { useState, useEffect } from 'react'
-
-function UseFetch(url, options = {method: 'GET'}) {
- const [data, setData] = useState(null)
- const [isLoading, setIsLoading] = useState(true)
- const [error, setError] = useState(null)
-
- useEffect(() => {
- console.log('UseFetch: useEffect called with url =', url, 'options =', options)
- setIsLoading(true)
- setError(null)
- fetch(url, options)
- .then((response) => {
- if (!response.ok) {
- console.log('UseFetch: response not ok, status =', response.status)
- throw new Error(`HTTP error! status: ${response.status}`)
- }
- return response.json()
- })
- .then((json) => setData(json))
- .catch((err) => setError(err.message))
- .finally(() => setIsLoading(false))
- },[])
-
- return { data, isLoading, error }
-}
-
-export default UseFetch
diff --git a/buildtime/client/logical-editor/src/index.css b/buildtime/client/logical-editor/src/index.css
deleted file mode 100644
index cb61a2f99..000000000
--- a/buildtime/client/logical-editor/src/index.css
+++ /dev/null
@@ -1,109 +0,0 @@
-
-:root {
- --text: #6b6375;
- --text-h: #08060d;
- --bg: #fff;
- --border: #e5e4e7;
- --code-bg: #f4f3ec;
- --accent: #aa3bff;
- --accent-bg: rgba(170, 59, 255, 0.1);
- --accent-border: rgba(170, 59, 255, 0.5);
- --social-bg: rgba(244, 243, 236, 0.5);
- --shadow:
- rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;
-
- --sans: system-ui, 'Segoe UI', Roboto, sans-serif;
- --heading: system-ui, 'Segoe UI', Roboto, sans-serif;
- --mono: ui-monospace, Consolas, monospace;
-
- font: 18px/145% var(--sans);
- letter-spacing: 0.18px;
- color-scheme: light dark;
- color: var(--text);
- background: var(--bg);
- font-synthesis: none;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-
- @media (max-width: 1024px) {
- font-size: 16px;
- }
-}
-
-@media (prefers-color-scheme: dark) {
- :root {
- --text: #9ca3af;
- --text-h: #f3f4f6;
- --bg: #16171d;
- --border: #2e303a;
- --code-bg: #1f2028;
- --accent: #c084fc;
- --accent-bg: rgba(192, 132, 252, 0.15);
- --accent-border: rgba(192, 132, 252, 0.5);
- --social-bg: rgba(47, 48, 58, 0.5);
- --shadow:
- rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;
- }
-
- #social .button-icon {
- filter: invert(1) brightness(2);
- }
-}
-
-html, body {
- margin: 0;
- height: 100%;
-}
-
-#root {
- max-width: 90%;
- margin: 0 auto;
- text-align: left;
- border-inline: 1px solid var(--border);
- box-sizing: border-box;
-}
-
-h1,
-h2 {
- font-family: var(--heading);
- font-weight: 500;
- color: var(--text-h);
-}
-
-h1 {
- font-size: 56px;
- letter-spacing: -1.68px;
- margin: 32px 0;
- @media (max-width: 1024px) {
- font-size: 36px;
- margin: 20px 0;
- }
-}
-h2 {
- font-size: 24px;
- line-height: 118%;
- letter-spacing: -0.24px;
- margin: 0 0 8px;
- @media (max-width: 1024px) {
- font-size: 20px;
- }
-}
-p {
- margin: 0;
-}
-
-code,
-.counter {
- font-family: var(--mono);
- display: inline-flex;
- border-radius: 4px;
- color: var(--text-h);
-}
-
-code {
- font-size: 15px;
- line-height: 135%;
- padding: 4px 8px;
- background: var(--code-bg);
-}
diff --git a/buildtime/client/logical-editor/src/keycloak.ts b/buildtime/client/logical-editor/src/keycloak.ts
deleted file mode 100644
index 65719eceb..000000000
--- a/buildtime/client/logical-editor/src/keycloak.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Keycloak from 'keycloak-js';
- const keycloak = new Keycloak({
- url: 'https://barefacedlean.ddnss.de:9099',
- realm: 'simplycpq',
- clientId: 'simplycpq',
-});
-export default keycloak;
diff --git a/buildtime/client/logical-editor/src/main.jsx b/buildtime/client/logical-editor/src/main.jsx
deleted file mode 100644
index 6cc4f2f9d..000000000
--- a/buildtime/client/logical-editor/src/main.jsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { StrictMode } from 'react'
-import { createRoot } from 'react-dom/client'
-import keycloak from './keycloak';
-import './index.css'
-
-import App from './App.jsx'
-
-keycloak.init({ onLoad: 'login-required' }).then(() => {
- createRoot(document.getElementById('root')).render(
-
-
-
- ,
- )
-});
-
diff --git a/buildtime/client/logical-editor/src/pages/HomePage.jsx b/buildtime/client/logical-editor/src/pages/HomePage.jsx
deleted file mode 100644
index 6f88a0455..000000000
--- a/buildtime/client/logical-editor/src/pages/HomePage.jsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import React from 'react';
-import keycloak from './keycloak';
-
-const HomePage = () => {
- return (
-
-
Welcome to the Home Page
-
This is the main landing page of the application.
-
Angemeldet als: {keycloak.tokenParsed?.preferred_username}
-
- );
-};
-
-export default HomePage;
diff --git a/buildtime/client/logical-editor/src/pages/LanguagePage.jsx b/buildtime/client/logical-editor/src/pages/LanguagePage.jsx
deleted file mode 100644
index 63880f552..000000000
--- a/buildtime/client/logical-editor/src/pages/LanguagePage.jsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import React from 'react';
-import LangSideBar from '../components/LangSideBar';
-
-const LanguagePage = () => {
- return (
-
- );
-};
-
-export default LanguagePage;
-
diff --git a/buildtime/client/logical-editor/src/pages/NotFoundPage.jsx b/buildtime/client/logical-editor/src/pages/NotFoundPage.jsx
deleted file mode 100644
index 4ba08f87b..000000000
--- a/buildtime/client/logical-editor/src/pages/NotFoundPage.jsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import React from 'react';
-
-const NotFoundPage = () => {
- return (
-
-
404 - Page Not Found
-
The page you are looking for does not exist.
-
- );
-};
-
-export default NotFoundPage;
-
diff --git a/buildtime/client/logical-editor/src/pages/PropertyPage.jsx b/buildtime/client/logical-editor/src/pages/PropertyPage.jsx
deleted file mode 100644
index c802a7a8b..000000000
--- a/buildtime/client/logical-editor/src/pages/PropertyPage.jsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from 'react';
-import { useState } from 'react'
-import PropertySideBar from '../components/PropertySideBar';
-import UseFetch from '../components/tools/UseFetch';
-
-const PropertyPage = () => {
- const { data: properties, isLoading, error } = UseFetch(`http://localhost:8088/propertygroup/1/lang/1`)
-
- if (isLoading) return Loading profile...
- if (error) return Error: {error}
-
- return (
-
- );
-};
-
-export default PropertyPage;
-
diff --git a/buildtime/client/logical-editor/vite.config.js b/buildtime/client/logical-editor/vite.config.js
deleted file mode 100644
index c4069b770..000000000
--- a/buildtime/client/logical-editor/vite.config.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react'
-import tailwindcss from '@tailwindcss/vite'
-
-// https://vite.dev/config/
-export default defineConfig({
- plugins: [react(), tailwindcss()],
-})
diff --git a/buildtime/client/material-editor/src/App.tsx b/buildtime/client/material-editor/src/App.tsx
index 506566a43..152d901a1 100644
--- a/buildtime/client/material-editor/src/App.tsx
+++ b/buildtime/client/material-editor/src/App.tsx
@@ -1,22 +1,30 @@
+import { Suspense, lazy, type ComponentType } from 'react'
import { createBrowserRouter, RouterProvider } from 'react-router'
-import Layout from './Layout.tsx'
-import HomePage from './pages/HomePage.tsx'
-import LanguagesPage from './pages/LanguagesPage.tsx'
-import PropertyPage from './pages/PropertyPage.tsx'
-import NotFoundPage from './pages/NotFoundPage.tsx'
import './App.css'
+const Layout = lazy(() => import('./Layout.tsx'))
+const HomePage = lazy(() => import('./pages/HomePage.tsx'))
+const LanguagesPage = lazy(() => import('./pages/LanguagesPage.tsx'))
+const PropertyPage = lazy(() => import('./pages/PropertyPage.tsx'))
+const NotFoundPage = lazy(() => import('./pages/NotFoundPage.tsx'))
+
+const renderLazyRoute = (Component: ComponentType) => (
+ Loading...}>
+
+
+)
+
// routing configuration
const router = createBrowserRouter([
{
path: '/',
- element: ,
+ element: renderLazyRoute(Layout),
children: [
- { index: true, element: },
- { path: 'language', element: },
- { path: 'propertypool', element: },
- { path: '*', element: },
+ { index: true, element: renderLazyRoute(HomePage) },
+ { path: 'language', element: renderLazyRoute(LanguagesPage) },
+ { path: 'propertypool', element: renderLazyRoute(PropertyPage) },
+ { path: '*', element: renderLazyRoute(NotFoundPage) },
],
},
])
diff --git a/buildtime/client/material-editor/src/Layout.tsx b/buildtime/client/material-editor/src/Layout.tsx
index ad1167f09..3f5491e7e 100644
--- a/buildtime/client/material-editor/src/Layout.tsx
+++ b/buildtime/client/material-editor/src/Layout.tsx
@@ -1,6 +1,6 @@
// Layouting Main Application
-import { Outlet, Link } from 'react-router'
+import { Outlet } from 'react-router'
import NavBar from './components/NavBar'
import Footer from './components/Footer'
diff --git a/buildtime/client/material-editor/src/api/language/languages.api.ts b/buildtime/client/material-editor/src/api/language/languages.api.ts
index 4b681a188..5b0bbe221 100644
--- a/buildtime/client/material-editor/src/api/language/languages.api.ts
+++ b/buildtime/client/material-editor/src/api/language/languages.api.ts
@@ -13,10 +13,10 @@ export const createLanguage = async (language: Language): Promise => {
return ky.post(`http://localhost:8088/language`, { json: language }).json()
}
-export const updateLanguage = async (language: Language): Promise => {
- return ky.put(`http://localhost:8088/language`, { json: language }).json()
+export const updateLanguage = async (language: Language): Promise => {
+ await ky.put(`http://localhost:8088/language`, { json: language })
}
export const deleteLanguage = async (id: number): Promise => {
- return ky.delete(`http://localhost:8088/language/${id}`).json()
+ await ky.delete(`http://localhost:8088/language/${id}`)
}
diff --git a/buildtime/client/material-editor/src/api/language/propertyGroup.api.ts b/buildtime/client/material-editor/src/api/language/propertyGroup.api.ts
index b37a2034f..d26eb3f98 100644
--- a/buildtime/client/material-editor/src/api/language/propertyGroup.api.ts
+++ b/buildtime/client/material-editor/src/api/language/propertyGroup.api.ts
@@ -1,22 +1,22 @@
import ky from 'ky'
-import type { propertyGroup } from '../../data/propertyGroup'
+import type { PropertyGroup } from '../../data/propertyGroup'
-export const getPropertyGroups = async (): Promise => {
- return ky.get(`http://localhost:8088/propertygroups`).json()
+export const getPropertyGroups = async (): Promise => {
+ return ky.get(`http://localhost:8088/propertygroups`).json()
}
-export const getPropertyGroupById = async (id: number): Promise => {
- return ky.get(`http://localhost:8088/propertygroup/${id}`).json()
+export const getPropertyGroupById = async (id: number): Promise => {
+ return ky.get(`http://localhost:8088/propertygroup/${id}`).json()
}
-export const createPropertyGroup = async (propertyGroup: propertyGroup): Promise => {
- return ky.post(`http://localhost:8088/propertygroup`, { json: propertyGroup }).json()
+export const createPropertyGroup = async (propertyGroup: PropertyGroup): Promise => {
+ return ky.post(`http://localhost:8088/propertygroup`, { json: propertyGroup }).json()
}
-export const updatePropertyGroup = async (propertyGroup: propertyGroup): Promise => {
- return ky.put(`http://localhost:8088/propertygroup`, { json: propertyGroup }).json()
+export const updatePropertyGroup = async (propertyGroup: PropertyGroup): Promise => {
+ await ky.put(`http://localhost:8088/propertygroup`, { json: propertyGroup })
}
export const deletePropertyGroup = async (id: number): Promise => {
- return ky.delete(`http://localhost:8088/propertygroup/${id}`).json()
+ await ky.delete(`http://localhost:8088/propertygroup/${id}`)
}
diff --git a/buildtime/client/material-editor/src/api/language/propertyTypes.api.ts b/buildtime/client/material-editor/src/api/language/propertyTypes.api.ts
index 8050fa840..b8566152c 100644
--- a/buildtime/client/material-editor/src/api/language/propertyTypes.api.ts
+++ b/buildtime/client/material-editor/src/api/language/propertyTypes.api.ts
@@ -13,12 +13,12 @@ export const createPropertyType = async (propertyType: PropertyType): Promise()
}
-export const updatePropertyType = async (propertyType: PropertyType): Promise => {
- return ky.put(`http://localhost:8088/propertytype`, { json: propertyType }).json()
+export const updatePropertyType = async (propertyType: PropertyType): Promise => {
+ await ky.put(`http://localhost:8088/propertytype`, { json: propertyType })
}
export const deletePropertyType = async (id: number): Promise => {
- return ky.delete(`http://localhost:8088/propertytype/${id}`).json()
+ await ky.delete(`http://localhost:8088/propertytype/${id}`)
}
export const getPropertyTypesByPropertyGroupId = async (propertyGroupId: number): Promise => {
diff --git a/buildtime/client/material-editor/src/api/language/translations.api.ts b/buildtime/client/material-editor/src/api/language/translations.api.ts
index df7d7cefa..87e03f1ee 100644
--- a/buildtime/client/material-editor/src/api/language/translations.api.ts
+++ b/buildtime/client/material-editor/src/api/language/translations.api.ts
@@ -13,12 +13,12 @@ export const createTranslation = async (translation: Translation): Promise()
}
-export const updateTranslation = async (translation: Translation): Promise => {
- return ky.put(`http://localhost:8088/translation`, { json: translation }).json()
+export const updateTranslation = async (translation: Translation): Promise => {
+ await ky.put(`http://localhost:8088/translation`, { json: translation })
}
export const deleteTranslation = async (id: number): Promise => {
- return ky.delete(`http://localhost:8088/translation/${id}`).json()
+ await ky.delete(`http://localhost:8088/translation/${id}`)
}
export const getTranslationsByLanguageId = async (language_id: number): Promise => {
diff --git a/buildtime/client/material-editor/src/api/language/valueComplexities.api.ts b/buildtime/client/material-editor/src/api/language/valueComplexities.api.ts
new file mode 100644
index 000000000..587f188a3
--- /dev/null
+++ b/buildtime/client/material-editor/src/api/language/valueComplexities.api.ts
@@ -0,0 +1,7 @@
+import ky from 'ky'
+import type { ValueComplexity } from '../../data/valueComplexity'
+
+export const getValueComplexities = async (): Promise => {
+ return ky.get(`http://localhost:8088/valuecomplexities`).json()
+}
+
diff --git a/buildtime/client/material-editor/src/api/language/valueTypes.api.ts b/buildtime/client/material-editor/src/api/language/valueTypes.api.ts
new file mode 100644
index 000000000..8f4b528b0
--- /dev/null
+++ b/buildtime/client/material-editor/src/api/language/valueTypes.api.ts
@@ -0,0 +1,11 @@
+import ky from 'ky'
+import type { ValueType } from '../../data/valueType'
+
+export const getValueTypes = async (): Promise => {
+ return ky.get(`http://localhost:8088/valuetypes`).json()
+}
+
+export const getValueTypeById = async (id: number): Promise => {
+ return ky.get(`http://localhost:8088/valuetype/${id}`).json()
+}
+
diff --git a/buildtime/client/material-editor/src/components/CreateEntityDialog.tsx b/buildtime/client/material-editor/src/components/CreateEntityDialog.tsx
new file mode 100644
index 000000000..b1123577d
--- /dev/null
+++ b/buildtime/client/material-editor/src/components/CreateEntityDialog.tsx
@@ -0,0 +1,89 @@
+import * as React from 'react';
+
+import Alert from '@mui/material/Alert';
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogTitle from '@mui/material/DialogTitle';
+
+type CreateEntityDialogProps = {
+ open: boolean;
+ title: string;
+ initialState: TFormState;
+ onClose: () => void;
+ onCreated: (entity: TEntity) => void | Promise;
+ createEntity: (formState: TFormState) => Promise;
+ children: (props: {
+ formState: TFormState;
+ setFormState: React.Dispatch>;
+ isSubmitting: boolean;
+ }) => React.ReactNode;
+ validate?: (formState: TFormState) => string | null;
+ submitLabel?: string;
+ errorMessageText?: string;
+};
+
+const CreateEntityDialog = ({
+ open,
+ title,
+ initialState,
+ onClose,
+ onCreated,
+ createEntity,
+ children,
+ validate,
+ submitLabel = 'Create',
+ errorMessageText = 'Creating the entry failed.',
+}: CreateEntityDialogProps) => {
+ const [formState, setFormState] = React.useState(initialState);
+ const [errorMessage, setErrorMessage] = React.useState('');
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
+
+ React.useEffect(() => {
+ if (!open) {
+ setFormState(initialState);
+ setErrorMessage('');
+ setIsSubmitting(false);
+ }
+ }, [initialState, open]);
+
+ const handleSubmit = async (event: React.FormEvent) => {
+ event.preventDefault();
+
+ const validationError = validate?.(formState);
+ if (validationError != null) {
+ setErrorMessage(validationError);
+ return;
+ }
+
+ setIsSubmitting(true);
+ setErrorMessage('');
+
+ try {
+ const createdEntity = await createEntity(formState);
+ await onCreated(createdEntity);
+ } catch {
+ setErrorMessage(errorMessageText);
+ setIsSubmitting(false);
+ }
+ };
+
+ return (
+
+
+
+ );
+};
+
+export default CreateEntityDialog;
\ No newline at end of file
diff --git a/buildtime/client/material-editor/src/components/CrudDataGrid.tsx b/buildtime/client/material-editor/src/components/CrudDataGrid.tsx
new file mode 100644
index 000000000..1a4e862ea
--- /dev/null
+++ b/buildtime/client/material-editor/src/components/CrudDataGrid.tsx
@@ -0,0 +1,35 @@
+import Paper from '@mui/material/Paper';
+import { DataGrid } from '@mui/x-data-grid';
+import type { DataGridProps } from '@mui/x-data-grid';
+import type { SxProps, Theme } from '@mui/material/styles';
+
+type CrudDataGridProps = DataGridProps & {
+ paperSx?: SxProps;
+};
+
+const sharedGridSx: SxProps = {
+ border: 1,
+ borderRadius: 2,
+ boxShadow: 2,
+ borderColor: 'primary.main',
+ '& .MuiDataGrid-cell:hover': { color: 'primary.main' },
+ '& .even-row': { backgroundColor: 'rgba(0, 0, 1, 0.02)' },
+ '& .odd-row': { backgroundColor: 'rgba(0, 0, 20, 0.04)' },
+};
+
+const CrudDataGrid = ({ paperSx, sx, ...dataGridProps }: CrudDataGridProps) => {
+ return (
+
+
+
+ );
+};
+
+export default CrudDataGrid;
\ No newline at end of file
diff --git a/buildtime/client/material-editor/src/components/CrudTableToolbar.tsx b/buildtime/client/material-editor/src/components/CrudTableToolbar.tsx
new file mode 100644
index 000000000..715e4b6e1
--- /dev/null
+++ b/buildtime/client/material-editor/src/components/CrudTableToolbar.tsx
@@ -0,0 +1,38 @@
+import AddIcon from '@mui/icons-material/Add';
+import DeleteIcon from '@mui/icons-material/Delete';
+import FileDownloadIcon from '@mui/icons-material/FileDownload';
+import Tooltip from '@mui/material/Tooltip';
+import Typography from '@mui/material/Typography';
+import { ExportCsv } from '@mui/x-data-grid';
+import { Toolbar, ToolbarButton } from '@mui/x-data-grid';
+
+type CrudTableToolbarProps = {
+ title: string;
+ disableAdd?: boolean;
+ disableDelete?: boolean;
+ onAdd: () => void;
+ onDelete: () => void;
+};
+
+const CrudTableToolbar = ({ title, disableAdd = false, disableDelete = false, onAdd, onDelete }: CrudTableToolbarProps) => {
+ return (
+
+
+ {title}
+
+
+ }>
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default CrudTableToolbar;
\ No newline at end of file
diff --git a/buildtime/client/material-editor/src/components/Footer.tsx b/buildtime/client/material-editor/src/components/Footer.tsx
index 93626cb24..f577d63ae 100644
--- a/buildtime/client/material-editor/src/components/Footer.tsx
+++ b/buildtime/client/material-editor/src/components/Footer.tsx
@@ -8,7 +8,7 @@ function Footer() {
- SimplyCPQ Material Editor (c) 2026 Dr. Thomas Sindt
+ Simply CPQ Material Editor (c) 2026 Dr. Thomas Sindt
diff --git a/buildtime/client/material-editor/src/components/LanguageCreateDialog.tsx b/buildtime/client/material-editor/src/components/LanguageCreateDialog.tsx
new file mode 100644
index 000000000..5330eef2d
--- /dev/null
+++ b/buildtime/client/material-editor/src/components/LanguageCreateDialog.tsx
@@ -0,0 +1,56 @@
+import Stack from '@mui/material/Stack';
+import TextField from '@mui/material/TextField';
+
+import { createLanguage } from '../api/language/languages.api';
+import CreateEntityDialog from './CreateEntityDialog';
+import type { Language } from '../data/language';
+
+type LanguageCreateDialogProps = {
+ open: boolean;
+ onClose: () => void;
+ onCreated: (language: Language) => void | Promise;
+};
+
+type LanguageFormState = {
+ locale: string;
+ language: string;
+};
+
+const initialFormState: LanguageFormState = {
+ locale: '',
+ language: '',
+};
+
+const LanguageCreateDialog = ({ open, onClose, onCreated }: LanguageCreateDialogProps) => {
+ return (
+ createLanguage({ id: 0, locale: formState.locale, language: formState.language })}
+ errorMessageText="Creating the language failed."
+ >
+ {({ formState, setFormState }) => (
+
+ setFormState((currentState) => ({ ...currentState, locale: event.target.value }))}
+ />
+ setFormState((currentState) => ({ ...currentState, language: event.target.value }))}
+ />
+
+ )}
+
+ );
+};
+
+export default LanguageCreateDialog;
\ No newline at end of file
diff --git a/buildtime/client/material-editor/src/components/LanguagesTableView.tsx b/buildtime/client/material-editor/src/components/LanguagesTableView.tsx
index d49b389b5..8ee7184f5 100644
--- a/buildtime/client/material-editor/src/components/LanguagesTableView.tsx
+++ b/buildtime/client/material-editor/src/components/LanguagesTableView.tsx
@@ -1,56 +1,50 @@
-import Tooltip from '@mui/material/Tooltip';
-import { ExportCsv } from '@mui/x-data-grid';
+import * as React from 'react';
+
+import Alert from '@mui/material/Alert';
import type {Language} from '../data/language';
+import CrudDataGrid from './CrudDataGrid';
+import CrudTableToolbar from './CrudTableToolbar';
+import LanguageCreateDialog from './LanguageCreateDialog';
+import { alternatingRowClassName, createEmptyRowSelectionModel, getSelectedNumericRowId, isDeleteDisabled, isSelectedRowId } from './tableViewUtils';
-import { DataGrid, Toolbar, ToolbarButton} from '@mui/x-data-grid';
-import Paper from '@mui/material/Paper';
-import DeleteIcon from '@mui/icons-material/Delete';
-import AddIcon from '@mui/icons-material/Add';
-import FileDownloadIcon from '@mui/icons-material/FileDownload';
-import {updateLanguage} from '../api/language/languages.api';
-import type { GridSelectionModel } from '@mui/x-data-grid';
-import { Typography } from '@mui/material';
+import type { GridRowSelectionModel } from '@mui/x-data-grid';
+import {deleteLanguage, updateLanguage} from '../api/language/languages.api';
-const LanguagesTableView = ({ languages, setSelectedRow }: { languages: Language[]; setSelectedRow: (id: number) => void }) => {
- // const [languages, setLanguages] = useState([]);
+const LanguagesTableView = ({ languages, setSelectedRow, refreshLanguages }: { languages: Language[]; setSelectedRow: (id: number) => void; refreshLanguages: () => Promise }) => {
+ const [rowSelectionModel, setRowSelectionModel] = React.useState(createEmptyRowSelectionModel);
+ const [isCreateDialogOpen, setIsCreateDialogOpen] = React.useState(false);
+ const [errorMessage, setErrorMessage] = React.useState('');
- function CustomToolbar() {
- return (
-
-
- Here you see all your available languages for translations.
-
-
- }>
-
-
-
- console.log('Delete Row clicked')}>
-
-
- console.log('Add Row clicked')}>
-
-
-
- )
- }
+ const handleLanguageCreated = async () => {
+ setIsCreateDialogOpen(false);
+ setErrorMessage('');
+ await refreshLanguages();
+ };
+
+ const handleDeleteLanguage = async () => {
+ const selectedLanguageId = getSelectedNumericRowId(rowSelectionModel);
+ if (selectedLanguageId == null) {
+ setErrorMessage('Select a language before deleting it.');
+ return;
+ }
+
+ try {
+ await deleteLanguage(selectedLanguageId);
+ setRowSelectionModel(createEmptyRowSelectionModel());
+ setSelectedRow(0);
+ setErrorMessage('');
+ await refreshLanguages();
+ } catch {
+ setErrorMessage('Deleting the language failed.');
+ }
+ };
return (
-
- {errorMessage}}
+ (
+ setIsCreateDialogOpen(true)}
+ />
+ ),
}}
- processRowUpdate={(updatedRow, originalRow) => {
- updateLanguage({id: updatedRow.id, locale: updatedRow.locale, language: updatedRow.language});
+ processRowUpdate={async (updatedRow) => {
+ await updateLanguage({id: updatedRow.id, locale: updatedRow.locale, language: updatedRow.language});
+ setErrorMessage('');
+ await refreshLanguages();
return updatedRow;
}}
- getRowClassName={(params) =>
- params.indexRelativeToCurrentPage % 2 === 0 ? 'even-row' : 'odd-row'
- }
+ onProcessRowUpdateError={() => setErrorMessage('Saving the language failed.')}
+ getRowClassName={alternatingRowClassName}
onCellClick={(params) => {
- const selectedRowId = params.id as number;
- const selectedRow = languages.find((row) => row.id === selectedRowId);
+ const selectedRow = languages.find((row) => isSelectedRowId(params.id, row.id));
setSelectedRow(selectedRow ? selectedRow.id : 0);
}}
-
- showToolbar
+ rowSelectionModel={rowSelectionModel}
+ onRowSelectionModelChange={(newRowSelectionModel) => setRowSelectionModel(newRowSelectionModel)}
/>
-
+
setIsCreateDialogOpen(false)}
+ onCreated={handleLanguageCreated}
+ />
);
};
diff --git a/buildtime/client/material-editor/src/components/NavBar.tsx b/buildtime/client/material-editor/src/components/NavBar.tsx
index 6dc8e348f..76894da19 100644
--- a/buildtime/client/material-editor/src/components/NavBar.tsx
+++ b/buildtime/client/material-editor/src/components/NavBar.tsx
@@ -14,7 +14,7 @@ function NavBar() {
- SimplyCPQ Material Editor
+ Simply CPQ Material Editor
navigate('/propertypool')}>Property Pool
diff --git a/buildtime/client/material-editor/src/components/PropertyGroupCreateDialog.tsx b/buildtime/client/material-editor/src/components/PropertyGroupCreateDialog.tsx
new file mode 100644
index 000000000..17af82fdb
--- /dev/null
+++ b/buildtime/client/material-editor/src/components/PropertyGroupCreateDialog.tsx
@@ -0,0 +1,56 @@
+import Stack from '@mui/material/Stack';
+import TextField from '@mui/material/TextField';
+
+import { createPropertyGroup } from '../api/language/propertyGroup.api';
+import CreateEntityDialog from './CreateEntityDialog';
+import type { PropertyGroup } from '../data/propertyGroup';
+
+type PropertyGroupCreateDialogProps = {
+ open: boolean;
+ onClose: () => void;
+ onCreated: (propertyGroup: PropertyGroup) => void | Promise;
+};
+
+type PropertyGroupFormState = {
+ label: string;
+ description: string;
+};
+
+const initialFormState: PropertyGroupFormState = {
+ label: '',
+ description: '',
+};
+
+const PropertyGroupCreateDialog = ({ open, onClose, onCreated }: PropertyGroupCreateDialogProps) => {
+ return (
+ createPropertyGroup({ id: 0, label: formState.label, description: formState.description })}
+ errorMessageText="Creating the property group failed."
+ >
+ {({ formState, setFormState }) => (
+
+ setFormState((currentState) => ({ ...currentState, label: event.target.value }))}
+ />
+ setFormState((currentState) => ({ ...currentState, description: event.target.value }))}
+ />
+
+ )}
+
+ );
+};
+
+export default PropertyGroupCreateDialog;
\ No newline at end of file
diff --git a/buildtime/client/material-editor/src/components/PropertyGroupsTableView.tsx b/buildtime/client/material-editor/src/components/PropertyGroupsTableView.tsx
index 31186949b..88e6419c0 100644
--- a/buildtime/client/material-editor/src/components/PropertyGroupsTableView.tsx
+++ b/buildtime/client/material-editor/src/components/PropertyGroupsTableView.tsx
@@ -1,55 +1,50 @@
-import Tooltip from '@mui/material/Tooltip';
-import { ExportCsv } from '@mui/x-data-grid';
-import type {propertyGroup} from '../data/propertyGroup';
+import * as React from 'react';
-import { DataGrid, Toolbar, ToolbarButton} from '@mui/x-data-grid';
-import Paper from '@mui/material/Paper';
-import DeleteIcon from '@mui/icons-material/Delete';
-import AddIcon from '@mui/icons-material/Add';
-import FileDownloadIcon from '@mui/icons-material/FileDownload';
-import { updatePropertyGroup } from '../api/language/propertyGroup.api';
-import Typography from '@mui/material/Typography';
+import Alert from '@mui/material/Alert';
+import type { PropertyGroup } from '../data/propertyGroup';
+import CrudDataGrid from './CrudDataGrid';
+import CrudTableToolbar from './CrudTableToolbar';
+import PropertyGroupCreateDialog from './PropertyGroupCreateDialog';
+import { alternatingRowClassName, createEmptyRowSelectionModel, getSelectedNumericRowId, isDeleteDisabled, isSelectedRowId } from './tableViewUtils';
-const PropertyGroupsTableView = ({ propertyGroups, setSelectedRow }: { propertyGroups: propertyGroup[]; setSelectedRow: (id: number) => void }) => {
- // const [languages, setLanguages] = useState([]);
+import type { GridRowSelectionModel } from '@mui/x-data-grid';
+import { deletePropertyGroup, updatePropertyGroup } from '../api/language/propertyGroup.api';
- function CustomToolbar() {
- return (
-
-
- Available PropertyGroups.
-
-
- }>
-
-
-
- console.log('Delete Row clicked')}>
-
-
- console.log('Add Row clicked')}>
-
-
-
- )
- }
+const PropertyGroupsTableView = ({ propertyGroups, setSelectedRow, refreshPropertyGroups }: { propertyGroups: PropertyGroup[]; setSelectedRow: (id: number) => void; refreshPropertyGroups: () => Promise }) => {
+ const [rowSelectionModel, setRowSelectionModel] = React.useState(createEmptyRowSelectionModel);
+ const [isCreateDialogOpen, setIsCreateDialogOpen] = React.useState(false);
+ const [errorMessage, setErrorMessage] = React.useState('');
+
+ const handlePropertyGroupCreated = async () => {
+ setIsCreateDialogOpen(false);
+ setErrorMessage('');
+ await refreshPropertyGroups();
+ };
+
+ const handleDeletePropertyGroup = async () => {
+ const selectedPropertyGroupId = getSelectedNumericRowId(rowSelectionModel);
+ if (selectedPropertyGroupId == null) {
+ setErrorMessage('Select a property group before deleting it.');
+ return;
+ }
+
+ try {
+ await deletePropertyGroup(selectedPropertyGroupId);
+ setRowSelectionModel(createEmptyRowSelectionModel());
+ setSelectedRow(0);
+ setErrorMessage('');
+ await refreshPropertyGroups();
+ } catch {
+ setErrorMessage('Deleting the property group failed.');
+ }
+ };
return (
-
- {errorMessage}}
+ (
+ setIsCreateDialogOpen(true)}
+ />
+ ),
}}
- processRowUpdate={(updatedRow, originalRow) => {
- updatePropertyGroup({id: updatedRow.id, label: updatedRow.label, description: updatedRow.description});
+ processRowUpdate={async (updatedRow) => {
+ await updatePropertyGroup({id: updatedRow.id, label: updatedRow.label, description: updatedRow.description});
+ setErrorMessage('');
+ await refreshPropertyGroups();
return updatedRow;
}}
- getRowClassName={(params) =>
- params.indexRelativeToCurrentPage % 2 === 0 ? 'even-row' : 'odd-row'
- }
+ onProcessRowUpdateError={() => setErrorMessage('Saving the property group failed.')}
+ getRowClassName={alternatingRowClassName}
onCellClick={(params) => {
- const selectedRowId = params.id as number;
- const selectedRow = propertyGroups.find((row) => row.id === selectedRowId);
+ const selectedRow = propertyGroups.find((row) => isSelectedRowId(params.id, row.id));
setSelectedRow(selectedRow ? selectedRow.id : 0);
}}
-
- showToolbar
+ rowSelectionModel={rowSelectionModel}
+ onRowSelectionModelChange={(newRowSelectionModel) => setRowSelectionModel(newRowSelectionModel)}
/>
-
+
setIsCreateDialogOpen(false)}
+ onCreated={handlePropertyGroupCreated}
+ />
);
};
diff --git a/buildtime/client/material-editor/src/components/PropertyTypeCreateDialog.tsx b/buildtime/client/material-editor/src/components/PropertyTypeCreateDialog.tsx
new file mode 100644
index 000000000..48a798b53
--- /dev/null
+++ b/buildtime/client/material-editor/src/components/PropertyTypeCreateDialog.tsx
@@ -0,0 +1,121 @@
+import MenuItem from '@mui/material/MenuItem';
+import Stack from '@mui/material/Stack';
+import TextField from '@mui/material/TextField';
+
+import { createPropertyType } from '../api/language/propertyTypes.api';
+import CreateEntityDialog from './CreateEntityDialog';
+import type { PropertyType } from '../data/propertyType';
+import type { ValueComplexity } from '../data/valueComplexity';
+import type { ValueType } from '../data/valueType';
+
+type PropertyTypeCreateDialogProps = {
+ open: boolean;
+ propertyGroupId: number;
+ valueTypes: ValueType[];
+ valueComplexities: ValueComplexity[];
+ onClose: () => void;
+ onCreated: (propertyType: PropertyType) => void | Promise;
+};
+
+type PropertyTypeFormState = {
+ label: string;
+ valueTypeId: string;
+ valueComplexityId: string;
+ value: string;
+};
+
+const initialFormState: PropertyTypeFormState = {
+ label: '',
+ valueTypeId: '',
+ valueComplexityId: '',
+ value: '',
+};
+
+const PropertyTypeCreateDialog = ({
+ open,
+ propertyGroupId,
+ valueTypes,
+ valueComplexities,
+ onClose,
+ onCreated,
+}: PropertyTypeCreateDialogProps) => {
+ return (
+ {
+ if (propertyGroupId <= 0) {
+ return 'Select a property group before creating a property type.';
+ }
+
+ if (formState.valueTypeId === '') {
+ return 'Select a value type.';
+ }
+
+ if (formState.valueComplexityId === '') {
+ return 'Select a value complexity.';
+ }
+
+ return null;
+ }}
+ createEntity={(formState) => createPropertyType({
+ id: 0,
+ label: formState.label,
+ valueTypeId: Number(formState.valueTypeId),
+ propertyGroupId,
+ valueComplexityId: formState.valueComplexityId,
+ value: formState.value,
+ })}
+ errorMessageText="Creating the property type failed."
+ >
+ {({ formState, setFormState }) => (
+
+ setFormState((currentState) => ({ ...currentState, label: event.target.value }))}
+ />
+ setFormState((currentState) => ({ ...currentState, valueTypeId: event.target.value }))}
+ >
+ {valueTypes.map((valueType) => (
+
+ {valueType.label}
+
+ ))}
+
+ setFormState((currentState) => ({ ...currentState, valueComplexityId: event.target.value }))}
+ >
+ {valueComplexities.map((valueComplexity) => (
+
+ {valueComplexity.complexity}
+
+ ))}
+
+ setFormState((currentState) => ({ ...currentState, value: event.target.value }))}
+ />
+
+ )}
+
+ );
+};
+
+export default PropertyTypeCreateDialog;
\ No newline at end of file
diff --git a/buildtime/client/material-editor/src/components/PropertyTypesTableView.tsx b/buildtime/client/material-editor/src/components/PropertyTypesTableView.tsx
index bf6b6d075..07d31b4cf 100644
--- a/buildtime/client/material-editor/src/components/PropertyTypesTableView.tsx
+++ b/buildtime/client/material-editor/src/components/PropertyTypesTableView.tsx
@@ -1,106 +1,179 @@
import * as React from 'react';
-
-import type { propertyGroup } from '../data/propertyGroup';
+import type { PropertyGroup } from '../data/propertyGroup';
import type { PropertyType } from '../data/propertyType';
+import type { ValueType } from '../data/valueType';
+import type { ValueComplexity } from '../data/valueComplexity';
+import CrudDataGrid from './CrudDataGrid';
+import CrudTableToolbar from './CrudTableToolbar';
+import PropertyTypeCreateDialog from './PropertyTypeCreateDialog';
+import { alternatingRowClassName, createEmptyRowSelectionModel, getSelectedNumericRowId, isDeleteDisabled } from './tableViewUtils';
-import Paper from '@mui/material/Paper';
-import DeleteIcon from '@mui/icons-material/Delete';
-import AddIcon from '@mui/icons-material/Add';
-import Tooltip from '@mui/material/Tooltip';
-import FileDownloadIcon from '@mui/icons-material/FileDownload';
-
-import { Typography } from '@mui/material';
-import { DataGrid, Toolbar, ToolbarButton} from '@mui/x-data-grid';
-import { ExportCsv } from '@mui/x-data-grid';
+import Alert from '@mui/material/Alert';
+import type { GridColDef } from '@mui/x-data-grid';
+import type { GridRowSelectionModel } from '@mui/x-data-grid';
import { getPropertyGroupById } from '../api/language/propertyGroup.api';
-import { updatePropertyType } from '../api/language/propertyTypes.api';
+import { deletePropertyType, updatePropertyType } from '../api/language/propertyTypes.api';
import { getPropertyTypesByPropertyGroupId } from '../api/language/propertyTypes.api';
+import { getValueTypes } from '../api/language/valueTypes.api';
+import { getValueComplexities } from '../api/language/valueComplexities.api';
const PropertyTypesTableView = ({ selectedRow }: { selectedRow: number }) => {
const [propertyTypes, setPropertyTypes] = React.useState([]);
- const [propertyGroup, setPropertyGroup] = React.useState(null);
+ const [propertyGroup, setPropertyGroup] = React.useState(null);
+ const [valueTypes, setValueTypes] = React.useState([]);
+ const [valueComplexities, setValueComplexities] = React.useState([]);
+
+ const [isCreateDialogOpen, setIsCreateDialogOpen] = React.useState(false);
+ const [rowSelectionModel, setRowSelectionModel] = React.useState(createEmptyRowSelectionModel);
+ const [errorMessage, setErrorMessage] = React.useState('');
+
+ const valueTypeLabelById = React.useMemo(() => {
+ return new Map(valueTypes.map((valueType) => [valueType.id, valueType.label]));
+ }, [valueTypes]);
+
+ const valueComplexityById = React.useMemo(() => {
+ return new Map(valueComplexities.map((valueComplexity) => [String(valueComplexity.id), valueComplexity.complexity]));
+ }, [valueComplexities]);
+
+ const columns = React.useMemo[]>(() => [
+ { field: 'id', headerName: 'ID', width: 100, align: 'right', headerAlign: 'right', editable: false },
+ { field: 'label', headerName: 'Label', width: 200, editable: true },
+ { field: 'propertyGroupId', headerName: 'Property Group Id', width: 130, editable: true },
+ {
+ field: 'valueTypeId',
+ headerName: 'Value Type',
+ width: 180,
+ editable: true,
+ type: 'singleSelect',
+ valueOptions: valueTypes.map((valueType) => ({ value: valueType.id, label: valueType.label })),
+ valueFormatter: (value) => valueTypeLabelById.get(Number(value)) ?? String(value),
+ },
+ {
+ field: 'valueComplexityId',
+ headerName: 'Value Complexity',
+ width: 200,
+ editable: true,
+ type: 'singleSelect',
+ valueOptions: valueComplexities.map((valueComplexity) => ({
+ value: String(valueComplexity.id),
+ label: valueComplexity.complexity,
+ })),
+ valueFormatter: (value) => valueComplexityById.get(String(value)) ?? String(value),
+ },
+ { field: 'value', headerName: 'Value', width: 200, editable: true },
+ ], [valueComplexities, valueComplexityById, valueTypeLabelById, valueTypes]);
+
+ const loadPropertyTypes = () => {
+ if (selectedRow <= 0) {
+ setPropertyTypes([]);
+ setRowSelectionModel(createEmptyRowSelectionModel());
+ return;
+ }
+
+ getPropertyTypesByPropertyGroupId(selectedRow)
+ .then(setPropertyTypes)
+ .catch(() => setErrorMessage('Loading property types failed.'));
+ };
React.useEffect(() => {
- getPropertyTypesByPropertyGroupId(selectedRow).then(setPropertyTypes);
+ getValueTypes()
+ .then(setValueTypes)
+ .catch(() => setErrorMessage('Loading value types failed.'));
+ getValueComplexities()
+ .then(setValueComplexities)
+ .catch(() => setErrorMessage('Loading value complexities failed.'));
+ }, []);
+
+ React.useEffect(() => {
+ loadPropertyTypes();
}, [selectedRow]);
React.useEffect(() => {
+ if (selectedRow <= 0) {
+ setPropertyGroup(null);
+ return;
+ }
+
getPropertyGroupById(selectedRow).then(setPropertyGroup);
}, [selectedRow]);
+ const handleCreateDialogClose = () => {
+ setIsCreateDialogOpen(false);
+ };
- function CustomToolbar() {
- return (
-
-
- Property types for group {propertyGroup?.label}.
-
-
- }>
-
-
-
- console.log('Delete Row clicked')}>
-
-
- console.log('Add Row clicked')}>
-
-
-
- )
- }
+ const handlePropertyTypeCreated = () => {
+ setIsCreateDialogOpen(false);
+ setErrorMessage('');
+ loadPropertyTypes();
+ };
+
+ const handleDeletePropertyType = async () => {
+ const selectedPropertyTypeId = getSelectedNumericRowId(rowSelectionModel);
+ if (selectedPropertyTypeId == null) {
+ setErrorMessage('Select a property type before deleting it.');
+ return;
+ }
+
+ try {
+ await deletePropertyType(selectedPropertyTypeId);
+ setErrorMessage('');
+ setRowSelectionModel(createEmptyRowSelectionModel());
+ loadPropertyTypes();
+ } catch {
+ setErrorMessage('Deleting the property type failed.');
+ }
+ };
return (
-
- {errorMessage}}
+ (
+ setIsCreateDialogOpen(true)}
+ />
+ ),
}}
- processRowUpdate={(updatedRow, originalRow) => {
- updatePropertyType({
+ processRowUpdate={async (updatedRow) => {
+ await updatePropertyType({
id: updatedRow.id,
- valueTypeId: updatedRow.valueTypeId,
+ label: updatedRow.label,
+ valueTypeId: Number(updatedRow.valueTypeId),
propertyGroupId: updatedRow.propertyGroupId,
- valueComplexityId: updatedRow.valueComplexityId,
+ valueComplexityId: String(updatedRow.valueComplexityId),
value: updatedRow.value
- }
- )
+ });
+ setErrorMessage('');
return updatedRow;
}}
- getRowClassName={(params) =>
- params.indexRelativeToCurrentPage % 2 === 0 ? 'even-row' : 'odd-row'
- }
- showToolbar
+ onProcessRowUpdateError={() => setErrorMessage('Saving the property type failed.')}
+ getRowClassName={alternatingRowClassName}
+ rowSelectionModel={rowSelectionModel}
+ onRowSelectionModelChange={(newRowSelectionModel) => setRowSelectionModel(newRowSelectionModel)}
/>
-
+
);
};
diff --git a/buildtime/client/material-editor/src/components/TranslationCreateDialog.tsx b/buildtime/client/material-editor/src/components/TranslationCreateDialog.tsx
new file mode 100644
index 000000000..ed88ba325
--- /dev/null
+++ b/buildtime/client/material-editor/src/components/TranslationCreateDialog.tsx
@@ -0,0 +1,69 @@
+import Stack from '@mui/material/Stack';
+import TextField from '@mui/material/TextField';
+
+import { createTranslation } from '../api/language/translations.api';
+import CreateEntityDialog from './CreateEntityDialog';
+import type { Translation } from '../data/translation';
+
+type TranslationCreateDialogProps = {
+ open: boolean;
+ languageId: number;
+ onClose: () => void;
+ onCreated: (translation: Translation) => void | Promise;
+};
+
+type TranslationFormState = {
+ original: string;
+ translated: string;
+};
+
+const initialFormState: TranslationFormState = {
+ original: '',
+ translated: '',
+};
+
+const TranslationCreateDialog = ({ open, languageId, onClose, onCreated }: TranslationCreateDialogProps) => {
+ return (
+ {
+ if (languageId <= 0) {
+ return 'Select a language before creating a translation.';
+ }
+
+ return null;
+ }}
+ createEntity={(formState) => createTranslation({
+ id: 0,
+ language_id: languageId,
+ original: formState.original,
+ translated: formState.translated,
+ })}
+ errorMessageText="Creating the translation failed."
+ >
+ {({ formState, setFormState }) => (
+
+ setFormState((currentState) => ({ ...currentState, original: event.target.value }))}
+ />
+ setFormState((currentState) => ({ ...currentState, translated: event.target.value }))}
+ />
+
+ )}
+
+ );
+};
+
+export default TranslationCreateDialog;
\ No newline at end of file
diff --git a/buildtime/client/material-editor/src/components/TranslationsTableView.tsx b/buildtime/client/material-editor/src/components/TranslationsTableView.tsx
index 734cd99ac..d2200bdf2 100644
--- a/buildtime/client/material-editor/src/components/TranslationsTableView.tsx
+++ b/buildtime/client/material-editor/src/components/TranslationsTableView.tsx
@@ -1,67 +1,76 @@
-import Tooltip from '@mui/material/Tooltip';
-import { ExportCsv } from '@mui/x-data-grid';
import * as React from 'react';
-import { DataGrid, Toolbar, ToolbarButton} from '@mui/x-data-grid';
-import Paper from '@mui/material/Paper';
-import DeleteIcon from '@mui/icons-material/Delete';
-import AddIcon from '@mui/icons-material/Add';
-import FileDownloadIcon from '@mui/icons-material/FileDownload';
-import {getLanguageById, updateLanguage} from '../api/language/languages.api';
+import Alert from '@mui/material/Alert';
+import CrudDataGrid from './CrudDataGrid';
+import CrudTableToolbar from './CrudTableToolbar';
+import { alternatingRowClassName, createEmptyRowSelectionModel, getSelectedNumericRowId, isDeleteDisabled } from './tableViewUtils';
+import type { GridRowSelectionModel } from '@mui/x-data-grid';
+import {getLanguageById} from '../api/language/languages.api';
import type { Translation } from '../data/translation';
-import { Typography } from '@mui/material';
-import { getTranslationsByLanguageId, updateTranslation } from '../api/language/translations.api';
+import TranslationCreateDialog from './TranslationCreateDialog';
+import { deleteTranslation, getTranslationsByLanguageId, updateTranslation } from '../api/language/translations.api';
import type { Language } from '../data/language';
const TranslationsTableView = ({ selectedRow }: { selectedRow: number }) => {
const [translations, setTranslations] = React.useState([]);
const [language, setLanguage] = React.useState(null);
+ const [rowSelectionModel, setRowSelectionModel] = React.useState(createEmptyRowSelectionModel);
+ const [isCreateDialogOpen, setIsCreateDialogOpen] = React.useState(false);
+ const [errorMessage, setErrorMessage] = React.useState('');
+
+ const loadTranslations = () => {
+ if (selectedRow <= 0) {
+ setTranslations([]);
+ setRowSelectionModel(createEmptyRowSelectionModel());
+ return;
+ }
+
+ getTranslationsByLanguageId(selectedRow)
+ .then(setTranslations)
+ .catch(() => setErrorMessage('Loading translations failed.'));
+ };
React.useEffect(() => {
- getTranslationsByLanguageId(selectedRow).then(setTranslations);
+ loadTranslations();
}, [selectedRow]);
React.useEffect(() => {
+ if (selectedRow <= 0) {
+ setLanguage(null);
+ return;
+ }
+
getLanguageById(selectedRow).then(setLanguage);
}, [selectedRow]);
+ const handleTranslationCreated = () => {
+ setIsCreateDialogOpen(false);
+ setErrorMessage('');
+ loadTranslations();
+ };
- function CustomToolbar() {
- return (
-
-
- Translations for {language?.language}.
-
-
- }>
-
-
-
- console.log('Delete Row clicked')}>
-
-
- console.log('Add Row clicked')}>
-
-
-
- )
- }
+ const handleDeleteTranslation = async () => {
+ const selectedTranslationId = getSelectedNumericRowId(rowSelectionModel);
+ if (selectedTranslationId == null) {
+ setErrorMessage('Select a translation before deleting it.');
+ return;
+ }
+
+ try {
+ await deleteTranslation(selectedTranslationId);
+ setRowSelectionModel(createEmptyRowSelectionModel());
+ setErrorMessage('');
+ loadTranslations();
+ } catch {
+ setErrorMessage('Deleting the translation failed.');
+ }
+ };
return (
-
- {errorMessage}}
+ {
{ field: 'translated', headerName: 'Translated', width: 200 , editable: true},
]}
slots={{
- toolbar: CustomToolbar,
+ toolbar: () => (
+ setIsCreateDialogOpen(true)}
+ />
+ ),
}}
- processRowUpdate={(updatedRow, originalRow) => {
- updateTranslation({
+ processRowUpdate={async (updatedRow) => {
+ await updateTranslation({
id: updatedRow.id,
language_id: updatedRow.language_id,
translated: updatedRow.translated,
- original: updatedRow.original}
- )
+ original: updatedRow.original,
+ });
+ setErrorMessage('');
return updatedRow;
}}
- getRowClassName={(params) =>
- params.indexRelativeToCurrentPage % 2 === 0 ? 'even-row' : 'odd-row'
- }
- showToolbar
+ onProcessRowUpdateError={() => setErrorMessage('Saving the translation failed.')}
+ getRowClassName={alternatingRowClassName}
+ rowSelectionModel={rowSelectionModel}
+ onRowSelectionModelChange={(newRowSelectionModel) => setRowSelectionModel(newRowSelectionModel)}
/>
-
+
setIsCreateDialogOpen(false)}
+ onCreated={handleTranslationCreated}
+ />
);
};
diff --git a/buildtime/client/material-editor/src/components/tableViewUtils.ts b/buildtime/client/material-editor/src/components/tableViewUtils.ts
new file mode 100644
index 000000000..2cc8b96ae
--- /dev/null
+++ b/buildtime/client/material-editor/src/components/tableViewUtils.ts
@@ -0,0 +1,23 @@
+import type { GridRowClassNameParams, GridRowId, GridRowSelectionModel } from '@mui/x-data-grid';
+
+export const createEmptyRowSelectionModel = (): GridRowSelectionModel => ({
+ type: 'include',
+ ids: new Set(),
+});
+
+export const getSelectedNumericRowId = (rowSelectionModel: GridRowSelectionModel): number | null => {
+ const selectedRowId = Array.from(rowSelectionModel.ids)[0];
+ return typeof selectedRowId === 'number' ? selectedRowId : null;
+};
+
+export const isDeleteDisabled = (rowSelectionModel: GridRowSelectionModel): boolean => {
+ return rowSelectionModel.ids.size === 0;
+};
+
+export const alternatingRowClassName = (params: GridRowClassNameParams): string => {
+ return params.indexRelativeToCurrentPage % 2 === 0 ? 'even-row' : 'odd-row';
+};
+
+export const isSelectedRowId = (rowId: GridRowId, expectedId: number): boolean => {
+ return typeof rowId === 'number' && rowId === expectedId;
+};
\ No newline at end of file
diff --git a/buildtime/client/material-editor/src/data/propertyGroup.ts b/buildtime/client/material-editor/src/data/propertyGroup.ts
index fa28eedbe..709c2ec97 100644
--- a/buildtime/client/material-editor/src/data/propertyGroup.ts
+++ b/buildtime/client/material-editor/src/data/propertyGroup.ts
@@ -1,4 +1,4 @@
-export type propertyGroup = {
+export type PropertyGroup = {
id: number;
label: string;
description: string;
diff --git a/buildtime/client/material-editor/src/data/propertyType.ts b/buildtime/client/material-editor/src/data/propertyType.ts
index 284b28ecd..ac402b3ec 100644
--- a/buildtime/client/material-editor/src/data/propertyType.ts
+++ b/buildtime/client/material-editor/src/data/propertyType.ts
@@ -1,9 +1,9 @@
export type PropertyType = {
id: number;
label: string;
- valueTypeId: number;
propertyGroupId: number;
- valueComplexityId: number;
+ valueTypeId: number;
+ valueComplexityId: string;
value: string;
};
diff --git a/buildtime/client/material-editor/src/data/valueComplexity.ts b/buildtime/client/material-editor/src/data/valueComplexity.ts
new file mode 100644
index 000000000..3b851bbd0
--- /dev/null
+++ b/buildtime/client/material-editor/src/data/valueComplexity.ts
@@ -0,0 +1,6 @@
+export type ValueComplexity = {
+ id: number;
+ complexity: string;
+ valueDefinition: string;
+};
+
diff --git a/buildtime/client/material-editor/src/data/valueType.ts b/buildtime/client/material-editor/src/data/valueType.ts
new file mode 100644
index 000000000..e4ab33e48
--- /dev/null
+++ b/buildtime/client/material-editor/src/data/valueType.ts
@@ -0,0 +1,5 @@
+export type ValueType = {
+ id: number;
+ label: string;
+};
+
diff --git a/buildtime/client/material-editor/src/pages/LanguagesPage.tsx b/buildtime/client/material-editor/src/pages/LanguagesPage.tsx
index 5af920076..6bde4d043 100644
--- a/buildtime/client/material-editor/src/pages/LanguagesPage.tsx
+++ b/buildtime/client/material-editor/src/pages/LanguagesPage.tsx
@@ -9,9 +9,15 @@ import { getLanguages } from '../api/language/languages.api';
const LanguagesPage: React.FC = () => {
const [languages, setLanguages] = useState([]);
const [selectedRow, setSelectedRow] = useState(0);
+
+ const loadLanguages = React.useCallback(async () => {
+ const loadedLanguages = await getLanguages();
+ setLanguages(loadedLanguages);
+ }, []);
+
useEffect(() => {
- getLanguages().then(setLanguages);
- }, []);
+ loadLanguages();
+ }, [loadLanguages]);
return (
@@ -27,7 +33,7 @@ const LanguagesPage: React.FC = () => {
bgcolor: "#f5f5f5"
}}
>
-
+
diff --git a/buildtime/client/material-editor/src/pages/PropertyPage.tsx b/buildtime/client/material-editor/src/pages/PropertyPage.tsx
index ab3cf746a..052252560 100644
--- a/buildtime/client/material-editor/src/pages/PropertyPage.tsx
+++ b/buildtime/client/material-editor/src/pages/PropertyPage.tsx
@@ -3,15 +3,21 @@ import PropertyTypesTableView from '../components/PropertyTypesTableView';
import PropertyGroupsTableView from '../components/PropertyGroupsTableView';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
-import type { propertyGroup } from '../data/propertyGroup';
+import type { PropertyGroup } from '../data/propertyGroup';
import { getPropertyGroups } from '../api/language/propertyGroup.api';
const PropertyPage: React.FC = () => {
- const [propertyGroups, setPropertyGroups] = useState([]);
+ const [propertyGroups, setPropertyGroups] = useState([]);
const [selectedRow, setSelectedRow] = useState(0);
+
+ const loadPropertyGroups = React.useCallback(async () => {
+ const loadedPropertyGroups = await getPropertyGroups();
+ setPropertyGroups(loadedPropertyGroups);
+ }, []);
+
useEffect(() => {
- getPropertyGroups().then(setPropertyGroups);
- }, []);
+ loadPropertyGroups();
+ }, [loadPropertyGroups]);
return (
@@ -27,7 +33,7 @@ const PropertyPage: React.FC = () => {
bgcolor: "#f5f5f5"
}}
>
-
+
diff --git a/buildtime/client/material-editor/vite.config.ts b/buildtime/client/material-editor/vite.config.ts
index 8b0f57b91..8307bfe30 100644
--- a/buildtime/client/material-editor/vite.config.ts
+++ b/buildtime/client/material-editor/vite.config.ts
@@ -4,4 +4,41 @@ import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
+ build: {
+ rollupOptions: {
+ output: {
+ manualChunks(id) {
+ if (!id.includes('node_modules')) {
+ return undefined
+ }
+
+ if (id.includes('@mui/x-data-grid')) {
+ return 'mui-data-grid'
+ }
+
+ if (
+ id.includes('@mui/material') ||
+ id.includes('@mui/icons-material') ||
+ id.includes('@emotion')
+ ) {
+ return 'mui-core'
+ }
+
+ if (id.includes('react-router')) {
+ return 'react-router'
+ }
+
+ if (id.includes('react-dom') || id.match(/[\\/]node_modules[\\/]react[\\/]/)) {
+ return 'react-vendor'
+ }
+
+ if (id.includes('keycloak-js')) {
+ return 'keycloak'
+ }
+
+ return 'vendor'
+ },
+ },
+ },
+ },
})
diff --git a/buildtime/server/src/scpq-editor-server/config.toml b/buildtime/server/src/scpq-editor-server/config.toml
index f49905779..0d6464fa7 100644
--- a/buildtime/server/src/scpq-editor-server/config.toml
+++ b/buildtime/server/src/scpq-editor-server/config.toml
@@ -4,7 +4,7 @@
# password= dbname=
[database]
-connection_string = "host=barefaced.ddnss.de port=5432 user=tsindt password=XD14ko8d dbname=simply_cpq_master_data sslmode=disable"
+connection_string = "host=192.168.178.50 port=5432 user=tsindt password=XD14ko8d dbname=simply_cpq_master_data sslmode=disable"
driver_name = "postgres"
################################################################
diff --git a/buildtime/server/src/scpq-editor-server/repositories/propertyTypesRepository.go b/buildtime/server/src/scpq-editor-server/repositories/propertyTypesRepository.go
index 41c443237..10254da6b 100644
--- a/buildtime/server/src/scpq-editor-server/repositories/propertyTypesRepository.go
+++ b/buildtime/server/src/scpq-editor-server/repositories/propertyTypesRepository.go
@@ -271,6 +271,13 @@ func (rr PropertyTypesRepository) GetAllPropertyTypesByPropertyGroupId(propertyG
Status: http.StatusInternalServerError,
}
}
+ ValueTypeID, err = strconv.Atoi(value_type_id_str)
+ if err != nil {
+ return nil, &models.ResponseError{
+ Message: "ValueType id not int",
+ Status: http.StatusInternalServerError,
+ }
+ }
PropertyType := &models.PropertyType{
ID: PropertyTypeId,
Label: label,
diff --git a/documentation/presentations/Testpresentation b/documentation/presentations/Testpresentation
deleted file mode 100644
index 6b8611341..000000000
--- a/documentation/presentations/Testpresentation
+++ /dev/null
@@ -1,105 +0,0 @@
----
-marp: true
-
-title: Simply CPQ
-author: Dr. Thomas Sindt
-footer: 'Simply CPQ - (c) Dr. Ing. Thomas Sindt'
-
-theme: gaia
-_class: lead
-paginate: true
-transition: fade
-
----
-
-
-
-
-
-
-# Simply CPQ
-
-##### The easy way to configure, price and quote your products and services.
-
----
-
-
-
-# **über mich:**
-
-
-
-
-Dr. Ing. Thomas Sindt
-
-
-
-
-
-
-
-
- Lebenslauf:
-
-
- - Geb. vor zu langer Zeit
- - 1993 Datenverabeitungskaufmann
- - 2001 Diplom Informatik
- - 2001-2010 Softwareentwicklung CPQ
- - 2002-2008 Promotion Dr. Ing.
- - 2006-heute Projektleitung CPQ
- - 2018-heute Senior Consultant CPQ
- - 2026-Simply CPQ
-
-
-
-
----
-
-
-# **Agenda**
-
-1. Was ist CPQ
-2. Warum CPQ
-3. Wie funktioniert CPQ
-
----
-
-
-
-
-# Was ist CPQ?
-
----
-
-
-
-# **Megatrend Individualisierung**
-
-- Wir wollen individuelle Produkte
-- Die Industrie muss sich anpassen
-- Individuelle Produkte brauchen individuelle Angebote
-- Individuelle Angebote brauchen individuelle Konfigurationen
-- Individuelles Auslegen braucht Expertierse
diff --git a/documentation/presentations/Testpresentation.md b/documentation/presentations/Testpresentation.md
index 7416b91e1..df86cdd31 100644
--- a/documentation/presentations/Testpresentation.md
+++ b/documentation/presentations/Testpresentation.md
@@ -71,24 +71,33 @@ Dr. Ing. Thomas Sindt
----
+---

-# **Agenda**
-
-1. Einführung in CPQ
- - Was ist CPQ und warum CPQ?
- - Vorteile von CPQ
-2. Simply CPQ
- - Überblick über Simply CPQ
- - Funktionen und Features
-3. Abgrenzung zu anderen CPQ-Lösungen
----
-
+# **Über mich**
+Mein Name ist Dr. Thomas Sindt.
+Ich bin ein erfahrener Softwareentwickler, Projektleiter und Berater mit Schwerpunkt auf CPQ-Lösungen. Mit über 25 Jahren Erfahrung in der Branche habe ich zahlreiche Projekte erfolgreich umgesetzt und Unternehmen dabei geholfen, ihre Vertriebsprozesse zu optimieren.
+
+---
+
+

-# Hallo Welt
+# Was ist CPQ?
-Dieses ist ein kleiner Test, um zu sehen, wie die Präsentation in Marp aussieht.
\ No newline at end of file
+---
+
+
+
+# **Megatrend Individualisierung**
+
+- Wir wollen individuelle Produkte
+- Die Industrie muss sich anpassen
+- Individuelle Produkte brauchen individuelle Angebote
+- Individuelle Angebote brauchen individuelle Konfigurationen
+- Individuelles Auslegen braucht Expertierse
Connect with us
-Join the Vite community
---
-
-
- GitHub
-
-
- -
-
-
- Discord
-
-
- -
-
-
- X.com
-
-
- -
-
-
- Bluesky
-
-
-
-