Compare commits

...

1 Commits

Author SHA1 Message Date
ec31681b20 wip: archivist frontend 2025-07-29 15:49:42 +02:00
20 changed files with 373 additions and 176 deletions

View File

@@ -41,6 +41,7 @@
"@spectrum-web-components/tooltip": "^1.6.0",
"@spectrum-web-components/top-nav": "^1.7.0",
"@spectrum-web-components/underlay": "^1.6.0",
"@tailwindcss/vite": "^4.0.14",
"@turf/bezier-spline": "^7.2.0",
"@vaadin/login": "^24.8.0",
"lit": "^3.3.0",
@@ -51,6 +52,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-plotly.js": "^2.6.0",
"tailwindcss": "^4.0.14",
"vis-timeline": "^7.7.4",
},
"devDependencies": {
@@ -177,6 +179,8 @@
"@internationalized/number": ["@internationalized/number@3.6.3", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-p+Zh1sb6EfrfVaS86jlHGQ9HA66fJhV9x5LiE5vCbZtXEHAuhcmUZUdZ4WrFpUBfNalr2OkAJI5AcKEQF+Lebw=="],
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="],
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
@@ -521,6 +525,36 @@
"@szmarczak/http-timer": ["@szmarczak/http-timer@5.0.1", "", { "dependencies": { "defer-to-connect": "^2.0.1" } }, "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw=="],
"@tailwindcss/node": ["@tailwindcss/node@4.1.11", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.11" } }, "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q=="],
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.11", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.11", "@tailwindcss/oxide-darwin-arm64": "4.1.11", "@tailwindcss/oxide-darwin-x64": "4.1.11", "@tailwindcss/oxide-freebsd-x64": "4.1.11", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", "@tailwindcss/oxide-linux-x64-musl": "4.1.11", "@tailwindcss/oxide-wasm32-wasi": "4.1.11", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" } }, "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg=="],
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.11", "", { "os": "android", "cpu": "arm64" }, "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg=="],
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ=="],
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw=="],
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA=="],
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.11", "", { "os": "linux", "cpu": "arm" }, "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg=="],
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ=="],
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ=="],
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.11", "", { "os": "linux", "cpu": "x64" }, "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg=="],
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.11", "", { "os": "linux", "cpu": "x64" }, "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q=="],
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.11", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@emnapi/wasi-threads": "^1.0.2", "@napi-rs/wasm-runtime": "^0.2.11", "@tybys/wasm-util": "^0.9.0", "tslib": "^2.8.0" }, "cpu": "none" }, "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g=="],
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w=="],
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.11", "", { "os": "win32", "cpu": "x64" }, "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg=="],
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.11", "", { "dependencies": { "@tailwindcss/node": "4.1.11", "@tailwindcss/oxide": "4.1.11", "tailwindcss": "4.1.11" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw=="],
"@turf/area": ["@turf/area@7.2.0", "", { "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", "@types/geojson": "^7946.0.10", "tslib": "^2.8.1" } }, "sha512-zuTTdQ4eoTI9nSSjerIy4QwgvxqwJVciQJ8tOPuMHbXJ9N/dNjI7bU8tasjhxas/Cx3NE9NxVHtNpYHL0FSzoA=="],
"@turf/bbox": ["@turf/bbox@7.2.0", "", { "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", "@types/geojson": "^7946.0.10", "tslib": "^2.8.1" } }, "sha512-wzHEjCXlYZiDludDbXkpBSmv8Zu6tPGLmJ1sXQ6qDwpLE1Ew3mcWqt8AaxfTP5QwDNQa3sf2vvgTEzNbPQkCiA=="],
@@ -743,6 +777,8 @@
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
"chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
"chrome-trace-event": ["chrome-trace-event@1.0.4", "", {}, "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ=="],
"clamp": ["clamp@1.0.1", "", {}, "sha512-kgMuFyE78OC6Dyu3Dy7vcx4uy97EIbVxJB/B0eJ3bUNAkwdNcxYzgKltnyADiYwsR7SEqkkUPsEUT//OVS6XMA=="],
@@ -1227,6 +1263,8 @@
"jest-worker": ["jest-worker@27.5.1", "", { "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg=="],
"jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="],
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
@@ -1257,6 +1295,28 @@
"lerc": ["lerc@3.0.0", "", {}, "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww=="],
"lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="],
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="],
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="],
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="],
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="],
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="],
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="],
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="],
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="],
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="],
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="],
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
"lit": ["lit@3.3.0", "", { "dependencies": { "@lit/reactive-element": "^2.1.0", "lit-element": "^4.2.0", "lit-html": "^3.3.0" } }, "sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw=="],
@@ -1335,6 +1395,10 @@
"minipass": ["minipass@4.2.8", "", {}, "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ=="],
"minizlib": ["minizlib@3.0.2", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA=="],
"mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="],
"moment": ["moment@2.30.1", "", {}, "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how=="],
"mouse-change": ["mouse-change@1.4.0", "", { "dependencies": { "mouse-event": "^1.0.0" } }, "sha512-vpN0s+zLL2ykyyUDh+fayu9Xkor5v/zRD9jhSqjRS1cJTGS0+oakVZzNm5n19JvvEj0you+MXlYTpNxUDQUjkQ=="],
@@ -1701,8 +1765,12 @@
"tabbable": ["tabbable@6.2.0", "", {}, "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="],
"tailwindcss": ["tailwindcss@4.1.11", "", {}, "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA=="],
"tapable": ["tapable@2.2.2", "", {}, "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg=="],
"tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="],
"temp-dir": ["temp-dir@3.0.0", "", {}, "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw=="],
"tempy": ["tempy@3.1.0", "", { "dependencies": { "is-stream": "^3.0.0", "temp-dir": "^3.0.0", "type-fest": "^2.12.2", "unique-string": "^3.0.0" } }, "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g=="],
@@ -1835,7 +1903,7 @@
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
"yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
@@ -1853,6 +1921,8 @@
"@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"@isaacs/fs-minipass/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
"@maplibre/maplibre-gl-style-spec/@mapbox/unitbezier": ["@mapbox/unitbezier@0.0.1", "", {}, "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw=="],
"@maplibre/maplibre-gl-style-spec/quickselect": ["quickselect@2.0.0", "", {}, "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="],
@@ -1889,6 +1959,22 @@
"@sentry/cli/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="],
"@tailwindcss/node/magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],
"@tailwindcss/oxide/detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.4.5", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.4", "tslib": "^2.4.0" }, "bundled": true }, "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.4.5", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.0.4", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g=="],
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" }, "bundled": true }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.9.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="],
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"cacheable-request/get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="],
@@ -1941,6 +2027,8 @@
"jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
"lightningcss/detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
"load-json-file/parse-json": ["parse-json@4.0.0", "", { "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw=="],
"map-limit/once": ["once@1.3.3", "", { "dependencies": { "wrappy": "1" } }, "sha512-6vaNInhu+CHxtONf3zw3vq4SP2DOQhjBvIa3rNcG0+P7eKWlYH6Peu7rHizSloRU2EwMz6GraLieis9Ac9+p1w=="],
@@ -1967,6 +2055,8 @@
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"minizlib/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
"needle/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
"node-emoji/@sindresorhus/is": ["@sindresorhus/is@4.6.0", "", {}, "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="],
@@ -2369,6 +2459,8 @@
"svg-path-bounds/normalize-svg-path": ["normalize-svg-path@1.1.0", "", { "dependencies": { "svg-arc-to-cubic-bezier": "^3.0.0" } }, "sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg=="],
"tar/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
"tempy/is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="],
"tempy/type-fest": ["type-fest@2.19.0", "", {}, "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="],
@@ -2381,6 +2473,8 @@
"wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
"@semantic-release/github/aggregate-error/clean-stack": ["clean-stack@5.2.0", "", { "dependencies": { "escape-string-regexp": "5.0.0" } }, "sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ=="],
"@semantic-release/github/aggregate-error/indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="],
@@ -2411,6 +2505,8 @@
"@sentry/cli/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="],
"cacheable-request/get-stream/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="],
"cli-highlight/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],

View File

@@ -22,6 +22,8 @@
"vite-plugin-mkcert": "^1.17.8"
},
"dependencies": {
"@tailwindcss/vite": "^4.0.14",
"tailwindcss": "^4.0.14",
"@fortawesome/fontawesome-free": "^6.7.2",
"@lit-labs/motion": "^1.0.8",
"@lit/context": "^1.1.5",

View File

@@ -18,26 +18,26 @@ let viteBundle = $"{vite} build --outDir {distPath}/public"
Target.create "Clean" (fun _ -> Shell.cleanDir distPath)
// Target.create "Bundle" (fun _ ->
// let vite = $"{viteBundle} -m production"
// run dotnet $"publish -c Release -o \"{distPath}\"" serverPath
// run dotnet $"fable -o build/client --run {vite}" clientPath
// )
// Target.create "BundleDebug" (fun _ ->
// let vite = $"{viteBundle} -m development --minify false"
// run dotnet $"publish -c Debug -o \"{distPath}\"" serverPath
// run dotnet $"fable -o build/client --run {vite}" clientPath
// )
Target.create "Bundle" (fun _ ->
let vite = $"{viteBundle} -m production"
run dotnet $"publish -c Release -o \"{distPath}\"" cliPath
run dotnet $"fable -o build/client --run {vite}" clientPath
)
Target.create "BundleDebug" (fun _ ->
let vite = $"{viteBundle} -m development --minify false"
run dotnet $"publish -c Debug -o \"{distPath}\"" cliPath
run dotnet $"fable -o build/client --run {vite}" clientPath
)
// Target.create "Bundle" (fun _ ->
// run dotnet $"publish -c Release -o \"{distPath}\"" cliPath
// )
// Target.create "BundleDebug" (fun _ ->
// run dotnet $"publish -c Debug -o \"{distPath}\"" cliPath
// )
Target.create "Format" (fun _ ->
run dotnet "fantomas . -r" "src"
)
@@ -64,4 +64,4 @@ let dependencies = [
]
[<EntryPoint>]
let main args = runOrDefault args
let main args = runOrDefault args

View File

@@ -8,7 +8,7 @@
},
}:
let
port = 9000;
port = 7000;
shell = pkgs.callPackage ./../../shell.nix { };
in
pkgs.mkShellNoCC {

View File

@@ -1,42 +1,66 @@
module App
open Archmaester
open Archmaester.Dto
open Browser
open Fable.Remoting.Client
open Lit
let archmaester =
[<Literal>]
let archmaesterUrl = "https://atlantis.local.oceanbox.io:8080"
let ModelArea =
Remoting.createApi ()
|> Remoting.withRouteBuilder Api.apiRouteBuilder
|> Remoting.buildProxy<Api.Inventory>
|> Remoting.withCredentials true
|> Remoting.withBaseUrl archmaesterUrl
|> Remoting.withRouteBuilder Archmaester.Api.authorizedRouteBuilder
|> Remoting.buildProxy<Archmaester.Api.ModelArea>
let fetchArchives modelAreaId callback =
let Archive =
Remoting.createApi ()
|> Remoting.withCredentials true
|> Remoting.withBaseUrl archmaesterUrl
|> Remoting.withRouteBuilder Archmaester.Api.authorizedRouteBuilder
|> Remoting.buildProxy<Archmaester.Api.Inventory>
let fetchModelAreaArchives modelAreaId callback =
async {
let! res = archmaester.getArchive modelAreaId
let! res = Archive.getModelAreaArchives (modelAreaId , ArchiveType.Fvcom (FvcomVariant.Any, FvcomFormat.Any))
match res with
| Error err -> console.error $"Fetch archives error: {err}"
| Ok archives -> Some [| archives |] |> callback
| Error err -> console.error $"Fetch archive error: %s{err}"
| Ok archives -> Some archives |> callback
}
|> Async.StartImmediate
let fetchModelAreas callback =
async {
let! res = archmaester.getModelAreaArchives (HelloWorld, ArchiveType.FromString "*:*:*")
async {
let! res = ModelArea.getModelArea HelloWorld
match res with
| None -> console.error $"Fetch modelArea error"
| Some areas -> Some [|areas|] |> callback
}
match res with
| Error err -> console.error $"Fetch model areas error: {err}"
| Ok modelAreas -> Some modelAreas |> callback
let fetchSubModelAreas callback =
async {
let! res = ModelArea.getSubModelAreas HelloWorld
Some res |> callback
}
[<LitElement("archive-listing")>]
let ArchiveListing () =
let _, _ = LitElement.init (fun init -> init.useShadowDom <- false)
let (modelAreas: ArchiveProps[] option), setModelAreas = Hook.useState None
let (modelAreas: ModelArea array option), setModelAreas = Hook.useState None
let (archives: ArchiveProps array option), setArchives = Hook.useState None
Hook.useEffectOnce (fun _ -> fetchModelAreas setModelAreas |> Async.StartImmediate)
Hook.useEffectOnce (fun _ ->
// fetchSubModelAreas setModelAreas |> Async.StartImmediate
fetchModelAreas setModelAreas |> Async.StartImmediate
fetchModelAreaArchives HelloWorld setArchives |> Async.StartImmediate
)
let modelAreaArchives archives =
archives
|> Array.groupBy _.modelArea
|> Map.ofArray
let archiveId (a: ArchiveProps) = a.archiveId.ToString ()
@@ -124,20 +148,27 @@ let ArchiveListing () =
{{archiveOwners item.acl}}
{{archiveUsers item.acl}}
{{archiveGroups item.acl}}
<h4>Start date: {item.startTime}</h4>
<h4>End date: {item.endTime}</h4>
</div>
</div>
"""
let archiveName archiveName =
let archiveName (archiveName: string) =
html
$"""
<p>{archiveName}</p>
"""
let modelAreaItem (item: ArchiveProps) =
// let archiveList = Array.map archiveName item.archives
let modelAreaItem (item: ModelArea) (archives: ArchiveProps array) =
// let archivesPerModelArea = modelAreaArchives archives
// let archiveList = Array.map archiveName item
let archivesForArea =
archives
|> Array.filter (fun a -> a.modelArea = item.modelAreaId)
|> Array.map _.name
|> Array.map archiveName
|> Lit.ofArray
html
$"""
@@ -146,19 +177,24 @@ let ArchiveListing () =
<h2 class="card-title">
{item.name}
</h2>
{item}
{archivesForArea}
</div>
</div>
"""
let modelAreaList =
match modelAreas with
| None -> html $"""<progress class="progress w-56"></progress>"""
| Some [||] -> html $"""<h1>No ModelAreas</h1>"""
| Some models ->
match modelAreas, archives with
| None, None-> html $"""<progress class="progress w-56"></progress>"""
| Some [||], Some [||] ->
html $"""<h1>Error no Model Areas available</h1>"""
| Some _, None ->
html $"""<h1>Error: Archives not loaded</h1>"""
| None, Some _ ->
html $"""<h1>Error: Model Areas not loaded</h1>"""
| Some modelAreas, Some archives ->
html
$"""
{models |> Lit.mapUnique (fun m -> m.name) modelAreaItem}
{modelAreas |> Lit.mapUnique _.name (fun a -> modelAreaItem a archives)}
"""
html

View File

@@ -4,16 +4,18 @@
<Version>7.1.0</Version>
</PropertyGroup>
<ItemGroup>
<Content Include="input.css"/>
<Content Include="index.html"/>
<Compile Include="App.fs"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Fable.Lit" Version="1.4.2"/>
<PackageReference Include="Fable.Remoting.Client" Version="7.32.0"/>
<PackageReference Include="Fable.Lit" Version="1.6.2-oceanbox" />
<PackageReference Include="Fable.Remoting.Client" Version="7.35.0"/>
<PackageReference Update="FSharp.Core" Version="9.0.201"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../../../Interfaces/Archmaester/Archmaester.Api.fsproj"/>
</ItemGroup>
<ItemGroup>
<Folder Include="public\" />
</ItemGroup>
</Project>

View File

@@ -4,7 +4,7 @@
<title>Fable</title>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="fable.ico" />
<link rel="shortcut icon" href="./public/fable.ico" />
<link href="./build/client/style.css" rel="stylesheet">
</head>
<body>

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env bash
dotnet fable watch -o build/client --run vite -c ../../vite.config.js
dotnet fable watch -o build/client --verbose --run bunx --bun vite serve -c ../../vite.config.js

View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -0,0 +1,69 @@
import mkcert from "vite-plugin-mkcert"
import tailwindcss from "@tailwindcss/vite"
import { defineConfig } from "vite"
import { resolve } from "path"
var clientPort = process.env.CLIENT_PORT == null ? 7080 : parseInt(process.env.CLIENT_PORT);
// var serverPort = process.env.SERVER_PORT == null ? 8085 : parseInt(process.env.SERVER_PORT);
// serverPort = process.env.SERVER_PROXY_PORT == null ? serverPort : parseInt(process.env.SERVER_PROXY_PORT);
var serverPort = 8085;
var certDir = `${process.env.HOME}/.vite-plugin-mkcert`;
var proxy = {
// target: `http://127.0.0.1:${serverPort}/`,
target: `https://atlantis.local.oceanbox.io:8080`,
changeOrigin: false,
secure: false,
ws: true
};
const plugins = [
tailwindcss(),
mkcert({
hosts: [
"localhost",
"*.local.oceanbox.io"
],
savePath: `${certDir}/certs`,
mkcertPath: `${certDir}/mkcert`
})
];
export default defineConfig({
plugins: plugins,
clearScreen: false,
emptyOutDir: true,
build: {
rollupOptions: {
input: {
main: resolve(__dirname, './src/Client/index.html'),
},
},
},
server: {
port: clientPort,
host: '0.0.0.0',
https: true,
cors: true,
proxy: {
'/api': proxy,
'/isAuthenticated': proxy,
'/signin-oidc': proxy,
'/signin': proxy,
'/signout': proxy,
'/token': proxy,
'/claims': proxy,
'/impersonate': proxy,
'/unimpersonate': proxy,
'/hub': proxy,
'/barentswatch-token': proxy,
'/socket': proxy,
},
watch: {
ignored: [
"**/*.fs" // Don't watch F# files
],
}
}
})

View File

@@ -1,115 +1,90 @@
module App
open Archmaester
open Archmaester.Dto
open Browser
open Fable.Core
open Fable.Remoting.Client
open Lit
let archmaester =
open Archmaester.Dto
[<Literal>]
let archmaesterUrl = "https://atlantis.local.oceanbox.io:8080"
let ModelArea =
Remoting.createApi ()
|> Remoting.withRouteBuilder Api.apiRouteBuilder
|> Remoting.buildProxy<Api.Inventory>
|> Remoting.withCredentials true
|> Remoting.withBaseUrl archmaesterUrl
|> Remoting.withRouteBuilder Archmaester.Api.apiRouteBuilder
|> Remoting.buildProxy<Archmaester.Api.ModelArea>
let fetchArchives modelAreaId callback =
async {
let! res = archmaester.getArchive modelAreaId
let Archive =
Remoting.createApi ()
|> Remoting.withCredentials true
|> Remoting.withBaseUrl archmaesterUrl
|> Remoting.withRouteBuilder Archmaester.Api.authorizedRouteBuilder
|> Remoting.buildProxy<Archmaester.Api.Inventory>
match res with
| Error err -> console.error $"Fetch archives error: {err}"
| Ok archives -> Some [| archives |] |> callback
}
|> Async.StartImmediate
let fetchModelAreas callback =
async {
let! res = archmaester.getModelAreaArchives (HelloWorld, ArchiveType.FromString "*:*:*")
match res with
| Error err -> console.error $"Fetch model areas error: {err}"
| Ok modelAreas -> Some modelAreas |> callback
}
type LoadingState<'T> =
| NotStarted
| Loading
| Success of 'T
| Error of string
[<LitElement("archive-listing")>]
let ArchiveListing () =
let _, _ = LitElement.init (fun init -> init.useShadowDom <- false)
let modelAreas, setModelAreas = Hook.useState<LoadingState<ModelArea array>> NotStarted
let archives, setArchives = Hook.useState<Map<System.Guid, LoadingState<ArchiveProps array>>> Map.empty
let archivesRef = Hook.useRef Map.empty<System.Guid, LoadingState<ArchiveProps array>>
let (modelAreas: ArchiveProps[] option), setModelAreas = Hook.useState None
// Update ref when archives state changes
Hook.useEffect(fun () -> archivesRef := archives)
Hook.useEffectOnce (fun _ -> fetchModelAreas setModelAreas |> Async.StartImmediate)
let archiveId (a: Archmaester.Dto.ArchiveProps) = a.archiveId.ToString ()
let archiveFiles files =
let fileEntry (fileName, _) = html $"""<li>{fileName}</li>"""
files |> Array.sortBy fst |> Lit.mapUnique fst fileEntry
let archiveOwners (acl: ArchiveAcl option) =
let owners =
match acl with
| Some x -> x.users
| None -> [||]
let userEntry name = html $"""<li>{name}</li>"""
let users' = owners |> Array.map userEntry |> Lit.ofArray
if Array.isEmpty owners then
Lit.nothing
else
html
$"""
<span>Owners:</span>
<div class="overflow-y-scroll">
<ul class="list-disc list-inside">
{users'}
</ul>
</div>
"""
let archiveUsers (acl: ArchiveAcl option) =
let users =
match acl with
| Some x -> x.users
| None -> [||]
let userEntry name = html $"""<li>{name}</li>"""
let users' = users |> Array.map userEntry |> Lit.ofArray
if Array.isEmpty users then
Lit.nothing
else
html
$"""
<span>Users:</span>
<div class="overflow-y-scroll">
<ul class="list-disc list-inside">
{users'}
</ul>
</div>
"""
let archiveGroups (acl: ArchiveAcl option) =
let groups =
match acl with
| Some x -> x.users
| None -> [||]
let groupEntry name = html $"""<li>{name}</li>"""
let groups' = groups |> Array.map groupEntry |> Lit.ofArray
if Array.isEmpty groups then
Lit.nothing
else
html
$"""
<span>Groups:</span>
<div class="overflow-y-scroll max-h-96">
<ul class="list-disc list-inside">
{groups'}
</ul>
</div>
"""
// Load model areas on mount
Hook.useEffectOnce (fun () ->
setModelAreas Loading
async {
try
let! areas = ModelArea.getSubModelAreas HelloWorld
setModelAreas (Success areas)
// Start loading archives for each model area
for area in areas do
let newArchives = Map.add area.modelAreaId Loading !archivesRef
archivesRef := newArchives
setArchives newArchives
async {
try
let! result = Archive.getModelAreaArchives (area.modelAreaId, ArchiveType.Fvcom (FvcomVariant.Any, FvcomFormat.Any))
match result with
| Ok archiveList ->
let newArchives = Map.add area.modelAreaId (Success archiveList) !archivesRef
archivesRef := newArchives
setArchives newArchives
| Result.Error err ->
let newArchives = Map.add area.modelAreaId (Error err) !archivesRef
archivesRef := newArchives
setArchives newArchives
with
| ex ->
let newArchives = Map.add area.modelAreaId (Error ex.Message) !archivesRef
archivesRef := newArchives
setArchives newArchives
}
|> Async.StartImmediate
with
| ex ->
setModelAreas (Error ex.Message)
}
|> Async.StartImmediate
)
let archiveItem (item: ArchiveProps) =
html
$"""
<div class="card w-full shadow-xl">
<div class="card w-full shadow-xl mb-4">
<div class="card-body">
<h2 class="card-title">
{item.name}
@@ -117,49 +92,54 @@ let ArchiveListing () =
</h2>
<h3>Start date: {item.startTime.ToShortDateString ()} {item.startTime.ToShortTimeString ()}</h3>
<span>Projection: {item.projection}</span>
{{archiveOwners item.acl}}
{{archiveUsers item.acl}}
{{archiveGroups item.acl}}
<h4>Start date: {item.startTime}</h4>
<h4>End date: {item.endTime}</h4>
</div>
</div>
"""
let archiveName archiveName =
html
$"""
<p>{archiveName}</p>
"""
let renderArchives modelAreaId =
match Map.tryFind modelAreaId archives with
| None -> html $"""<div class="loading loading-spinner loading-sm"></div>"""
| Some NotStarted -> html $"""<div class="loading loading-spinner loading-sm"></div>"""
| Some Loading -> html $"""<div class="loading loading-spinner loading-sm"></div>"""
| Some (Error err) -> html $"""<div class="alert alert-error"><span>Error: {err}</span></div>"""
| Some (Success [||]) -> html $"""<div class="alert alert-info"><span>No archives found</span></div>"""
| Some (Success archiveList) ->
archiveList
|> Array.map archiveItem
|> Lit.ofArray
let modelAreaItem (item: ArchiveProps) =
// let archiveList =
// Array.map archiveName item.archiveType
let modelAreaItem (area: ModelArea) =
html
$"""
<div class="card w-full shadow-xl">
<div class="card-body">
<h2 class="card-title">
{item.name}
</h2>
{item}
<h2 class="card-title">{area.name}</h2>
<div class="mt-4">
{renderArchives area.modelAreaId}
</div>
</div>
</div>
"""
let modelAreaList =
let content =
match modelAreas with
| None -> html $"""<progress class="progress w-56"></progress>"""
| Some [||] -> html $"""<h1>No ModelAreas</h1>"""
| Some models ->
| NotStarted -> html $"""<div class="flex justify-center"><div class="loading loading-spinner loading-lg"></div></div>"""
| Loading -> html $"""<div class="flex justify-center"><div class="loading loading-spinner loading-lg"></div></div>"""
| Error err -> html $"""<div class="alert alert-error"><span>Failed to load model areas: {err}</span></div>"""
| Success [||] -> html $"""<div class="alert alert-warning"><span>No model areas found</span></div>"""
| Success areas ->
html
$"""
{models |> Lit.mapUnique (fun m -> m.name) modelAreaItem}
"""
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{areas |> Array.map modelAreaItem |> Lit.ofArray}
</div>
"""
html
$"""
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
{modelAreaList}
<div class="container mx-auto p-4">
<h1 class="text-3xl font-bold mb-6">Archive Catalog</h1>
{content}
</div>
"""
"""

View File

@@ -2,19 +2,21 @@
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Version>6.20.0</Version>
<RootNamespace>Archivist</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Content Include="input.css" />
<Content Include="index.html" />
<Content Include="style.css" />
<Compile Include="App.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Fable.Lit" Version="1.4.2" />
<PackageReference Include="Fable.Remoting.Client" Version="7.32.0" />
<PackageReference Include="Fable.Lit" Version="1.6.2-oceanbox" />
<PackageReference Include="Fable.Remoting.Client" Version="7.35.0"/>
<PackageReference Update="FSharp.Core" Version="9.0.201" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\Interfaces\Archmaester\Archmaester.Api.fsproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="public\" />
</ItemGroup>
</Project>

View File

@@ -4,8 +4,8 @@
<title>Fable</title>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="fable.ico" />
<link href="./build/client/style.css" rel="stylesheet">
<link rel="shortcut icon" href="./fable.ico" />
<link href="./style.css" rel="stylesheet">
</head>
<body>
<!-- navbar -->
@@ -16,7 +16,7 @@
</label>
</div>
<div class="px-2 mx-2">
Archmeister
Archmaester
</div>
</div>
<div class="drawer drawer-mobile">
@@ -37,6 +37,6 @@
</ul>
</div>
</div>
<script type="module" src="./build/App.jsx"></script>
<script type="module" src="../build/Catalog/App.jsx"></script>
</body>
</html>

View File

@@ -1,4 +1,3 @@
#!/usr/bin/env bash
dotnet fable watch -o build/client --run vite -c ../../vite.config.js
dotnet fable watch -o build/client --verbose --run bunx --bun vite serve -c ../../vite.config.js

View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -23,5 +23,6 @@
<ItemGroup>
<ProjectReference Include="Atlas\Atlas.fsproj"/>
<ProjectReference Include="Mapster\Mapster.fsproj"/>
<ProjectReference Include="Catalog\Catalog.fsproj"/>
</ItemGroup>
</Project>

View File

@@ -61,6 +61,7 @@
"connString": "Username=postgres;Password=secret;Host=localhost;Port=5432;Database=app;Pooling=true;",
"sorcerer" : "https://<x>-sorcerer.ekman.oceanbox.io",
"allowedOrigins": [
"http://localhost:7080",
"https://atlantis.beta.oceanbox.io",
"https://<x>-atlantis.dev.oceanbox.io",
"https://atlantis.local.oceanbox.io:8080"

View File

@@ -3,6 +3,7 @@ import mkcert from "vite-plugin-mkcert"
import { sentryVitePlugin } from "@sentry/vite-plugin"
import { defineConfig } from "vite"
import { resolve } from "path"
import tailwindcss from "@tailwindcss/vite";
var clientPort = process.env.CLIENT_PORT == null ? 8080 : parseInt(process.env.CLIENT_PORT);
var serverPort = process.env.SERVER_PORT == null ? 8085 : parseInt(process.env.SERVER_PORT);
@@ -19,6 +20,7 @@ var proxy = {
const plugins = [
react({jsxRuntime: "automatic"}),
tailwindcss(),
mkcert({
hosts: [
"localhost",
@@ -62,6 +64,7 @@ export default defineConfig({
main: resolve(__dirname, './src/Client/index.html'),
atlas: resolve(__dirname, './src/Client/atlas.html'),
mapster: resolve(__dirname, './src/Client/map.html'),
catalog: resolve(__dirname, './src/Client/Catalog/catalog.html'),
},
},
},

View File

@@ -50,6 +50,7 @@
"sentryUrl": "https://5e6e3584098dc006de18038cf85d2cbe@o4509530141622272.ingest.de.sentry.io/4509547350065232",
"redis": "localhost:6379,user=default,password=secret",
"allowedOrigins": [
"http://localhost:7080",
"http://localhost:8085",
"http://localhost:8080",
"https://localhost:8080",