diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0133853 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,16 @@ +node_modules +.svelte-kit +build +out +.vite +.env +.env.* +*.dmg +*.zip +e2e +electron +forge.config.ts +forge.env.d.ts +vite.main.config.ts +vite.preload.config.ts +playwright.config.ts diff --git a/.github/workflows/build-and-publish.yaml b/.github/workflows/build-and-publish.yaml new file mode 100644 index 0000000..fa7baf3 --- /dev/null +++ b/.github/workflows/build-and-publish.yaml @@ -0,0 +1,133 @@ +name: Build and Publish + +on: + release: + types: [created] + +jobs: + build-server: + name: Build Server Image + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push the Docker image + uses: docker/build-push-action@v6 + with: + push: true + tags: | + ghcr.io/project-optima/ttscm-ui:latest + ghcr.io/project-optima/ttscm-ui:${{ github.event.release.tag_name }} + + build-desktop-macos: + name: Build Desktop (macOS) + runs-on: macos-latest + permissions: + contents: write + steps: + - name: Checkout source code + uses: actions/checkout@v4 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: latest + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build macOS distributables + run: pnpm run make:macos + + - name: Upload macOS artifacts to release + uses: softprops/action-gh-release@v2 + with: + files: | + out/make/**/*.dmg + out/make/**/*.zip + + build-desktop-windows: + name: Build Desktop (Windows) + runs-on: windows-latest + permissions: + contents: write + steps: + - name: Checkout source code + uses: actions/checkout@v4 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: latest + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build Windows distributables + run: pnpm run make -- --platform win32 + + - name: Upload Windows artifacts to release + uses: softprops/action-gh-release@v2 + with: + files: | + out/make/**/*.exe + out/make/**/*.nupkg + out/make/**/*.msi + + deploy: + name: Deploy + needs: [build-server] + runs-on: ubuntu-latest + steps: + - name: Set the Kubernetes context + uses: azure/k8s-set-context@v2 + with: + method: kubeconfig + kubeconfig: ${{ secrets.KUBECONFIG }} + + - name: Checkout source code + uses: actions/checkout@v4 + + - name: Lint Kubernetes manifests + uses: azure/k8s-lint@v3 + with: + lintType: dryrun + manifests: | + kubernetes/deployment.yaml + kubernetes/ingress.yaml + namespace: optima + + - name: Deploy to the Kubernetes cluster + uses: azure/k8s-deploy@v5 + with: + namespace: optima + force: true + skip-tls-verify: true + manifests: | + kubernetes/deployment.yaml + kubernetes/ingress.yaml + images: | + ghcr.io/project-optima/ttscm-ui:${{ github.event.release.tag_name }} diff --git a/.gitignore b/.gitignore index 6bc8809..d7883cb 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ vite.config.ts.timestamp-* .vite out +tailwindcss-*.log diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..58935ba --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +FROM node:22-alpine AS base + +RUN corepack enable && corepack prepare pnpm@latest --activate +WORKDIR /app + +# Install dependencies +COPY package.json pnpm-lock.yaml ./ +COPY patches ./patches +RUN pnpm install --frozen-lockfile + +# Build the SvelteKit app with adapter-node +COPY . . +RUN pnpm run build:server + +# Production image +FROM node:22-alpine AS production + +WORKDIR /app + +COPY --from=base /app/build ./build +COPY --from=base /app/package.json ./ + +ENV NODE_ENV=production +ENV PORT=3000 +ENV ORIGIN=https://optima.osdci.net + +EXPOSE 3000 + +CMD ["node", "build/index.js"] diff --git a/bun.lock b/bun.lock index 2d8c9e0..042211b 100644 --- a/bun.lock +++ b/bun.lock @@ -22,6 +22,7 @@ "@electron-forge/plugin-vite": "^7.11.1", "@electron/fuses": "^1.8.0", "@playwright/test": "^1.58.0", + "@sveltejs/adapter-node": "^5.5.3", "@sveltejs/adapter-static": "^3.0.10", "@sveltejs/kit": "^2.50.1", "@sveltejs/vite-plugin-svelte": "^5.1.1", @@ -238,6 +239,14 @@ "@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="], + "@rollup/plugin-commonjs": ["@rollup/plugin-commonjs@29.0.0", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", "fdir": "^6.2.0", "is-reference": "1.2.1", "magic-string": "^0.30.3", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^2.68.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-U2YHaxR2cU/yAiwKJtJRhnyLk7cifnQw0zUpISsocBDoHDJn+HTV74ABqnwr5bEgWUwFZC9oFL6wLe21lHu5eQ=="], + + "@rollup/plugin-json": ["@rollup/plugin-json@6.1.0", "", { "dependencies": { "@rollup/pluginutils": "^5.1.0" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA=="], + + "@rollup/plugin-node-resolve": ["@rollup/plugin-node-resolve@16.0.3", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", "is-module": "^1.0.0", "resolve": "^1.22.1" }, "peerDependencies": { "rollup": "^2.78.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg=="], + + "@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.41.0", "", { "os": "android", "cpu": "arm" }, "sha512-KxN+zCjOYHGwCl4UCtSfZ6jrq/qi88JDUtiEFk8LELEHq2Egfc/FgW+jItZiOLRuQfb/3xJSgFuNPC9jzggX+A=="], "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.41.0", "", { "os": "android", "cpu": "arm64" }, "sha512-yDvqx3lWlcugozax3DItKJI5j05B0d4Kvnjx+5mwiUpWramVvmAByYigMplaoAQ3pvdprGCTCE03eduqE/8mPQ=="], @@ -286,6 +295,8 @@ "@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.5", "", { "peerDependencies": { "acorn": "8.14.1" } }, "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ=="], + "@sveltejs/adapter-node": ["@sveltejs/adapter-node@5.5.3", "", { "dependencies": { "@rollup/plugin-commonjs": "^29.0.0", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.0", "rollup": "^4.9.5" }, "peerDependencies": { "@sveltejs/kit": "^2.4.0" } }, "sha512-yeWbKXBL9vqDb/7R8ebvRHeuBHN4cRYYBSquNJSMQtS6rIYkXxsVSveaMTUaLvHYQsb1zNa+nH2iLTOMawBohA=="], + "@sveltejs/adapter-static": ["@sveltejs/adapter-static@3.0.10", "", { "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-7D9lYFWJmB7zxZyTE/qxjksvMqzMuYrrsyh1f4AlZqeZeACPRySjbC3aFiY55wb1tWUaKOQG9PVbm74JcN2Iew=="], "@sveltejs/kit": ["@sveltejs/kit@2.50.1", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.6.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": "^5.3.3", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["@opentelemetry/api", "typescript"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-XRHD2i3zC4ukhz2iCQzO4mbsts081PAZnnMAQ7LNpWeYgeBmwMsalf0FGSwhFXBbtr2XViPKnFJBDCckWqrsLw=="], @@ -372,6 +383,8 @@ "@types/node": ["@types/node@22.19.7", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw=="], + "@types/resolve": ["@types/resolve@1.20.2", "", {}, "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="], + "@types/responselike": ["@types/responselike@1.0.3", "", { "dependencies": { "@types/node": "22.15.20" } }, "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw=="], "@types/wrap-ansi": ["@types/wrap-ansi@3.0.0", "", {}, "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g=="], @@ -554,6 +567,8 @@ "commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], + "commondir": ["commondir@1.0.1", "", {}, "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="], + "compare-version": ["compare-version@0.1.2", "", {}, "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A=="], "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], @@ -680,7 +695,7 @@ "estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], - "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "1.0.7" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], @@ -838,6 +853,8 @@ "is-lambda": ["is-lambda@1.0.1", "", {}, "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ=="], + "is-module": ["is-module@1.0.0", "", {}, "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="], + "is-my-ip-valid": ["is-my-ip-valid@1.0.1", "", {}, "sha512-jxc8cBcOWbNK2i2aTkCZP6i7wkHF1bqKFrwEHuN5Jtg5BSaZHUZQ/JTOJwoV41YvHnOaRyWWh72T/KvfNz9DJg=="], "is-my-json-valid": ["is-my-json-valid@2.20.6", "", { "dependencies": { "generate-function": "2.3.1", "generate-object-property": "1.2.0", "is-my-ip-valid": "1.0.1", "jsonpointer": "5.0.1", "xtend": "4.0.2" } }, "sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw=="], @@ -1452,6 +1469,18 @@ "@npmcli/move-file/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "7.2.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], + "@rollup/plugin-commonjs/fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "@rollup/plugin-commonjs/is-reference": ["is-reference@1.2.1", "", { "dependencies": { "@types/estree": "*" } }, "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ=="], + + "@rollup/plugin-commonjs/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "@rollup/plugin-commonjs/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "@rollup/pluginutils/@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@rollup/pluginutils/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + "@tailwindcss/node/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], @@ -1486,6 +1515,8 @@ "@types/yauzl/@types/node": ["@types/node@22.15.20", "", { "dependencies": { "undici-types": "6.21.0" } }, "sha512-A6BohGFRGHAscJsTslDCA9JG7qSJr/DWUvrvY8yi9IgnGtMxCyat7vvQ//MFa0DnLsyuS3wYTpLdw4Hf+Q5JXw=="], + "@vitest/mocker/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "1.0.7" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + "ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], "cacache/glob": ["glob@8.1.0", "", { "dependencies": { "fs.realpath": "1.0.0", "inflight": "1.0.6", "inherits": "2.0.4", "minimatch": "5.1.6", "once": "1.4.0" } }, "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ=="], @@ -1642,6 +1673,10 @@ "@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "8.0.0", "is-fullwidth-code-point": "3.0.0", "strip-ansi": "6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "@rollup/plugin-commonjs/is-reference/@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@rollup/plugin-commonjs/magic-string/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + "@tailwindcss/node/magic-string/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], "cacache/glob/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], diff --git a/electron/main.ts b/electron/main.ts index 0c13cf6..14e7602 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -7,29 +7,24 @@ if (started) { app.quit(); } +const PRODUCTION_URL = "https://optima.osdci.net"; + const createWindow = () => { - // Create the browser window. const mainWindow = new BrowserWindow({ - width: 800, - height: 600, + width: 1200, + height: 800, webPreferences: { preload: path.join(import.meta.dirname, "preload.js"), }, }); - // and load the index.html of the app. if (MAIN_WINDOW_VITE_DEV_SERVER_URL) { mainWindow.loadURL(`${MAIN_WINDOW_VITE_DEV_SERVER_URL}/login`); mainWindow.webContents.on("did-frame-finish-load", () => { mainWindow.webContents.openDevTools({ mode: "detach" }); }); } else { - mainWindow.loadFile( - path.join( - import.meta.dirname, - `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`, - ), - ); + mainWindow.loadURL(PRODUCTION_URL); } }; diff --git a/forge.config.ts b/forge.config.ts index 3b89373..a7e752f 100644 --- a/forge.config.ts +++ b/forge.config.ts @@ -1,6 +1,7 @@ import type { ForgeConfig } from "@electron-forge/shared-types"; import { MakerSquirrel } from "@electron-forge/maker-squirrel"; import { MakerZIP } from "@electron-forge/maker-zip"; +import { MakerDMG } from "@electron-forge/maker-dmg"; import { MakerDeb } from "@electron-forge/maker-deb"; import { MakerRpm } from "@electron-forge/maker-rpm"; import { VitePlugin } from "@electron-forge/plugin-vite"; @@ -15,6 +16,7 @@ const config: ForgeConfig = { makers: [ new MakerSquirrel({}), new MakerZIP({}, ["darwin"]), + new MakerDMG({}), new MakerRpm({}), new MakerDeb({}), ], diff --git a/kubernetes/deployment.yaml b/kubernetes/deployment.yaml new file mode 100644 index 0000000..70fcf48 --- /dev/null +++ b/kubernetes/deployment.yaml @@ -0,0 +1,30 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: optima-ui + namespace: optima +spec: + selector: + matchLabels: + app: optima-ui + replicas: 1 + template: + metadata: + labels: + app: optima-ui + spec: + containers: + - name: optima-ui + image: ghcr.io/project-optima/ttscm-ui:latest + imagePullPolicy: Always + env: + - name: PUBLIC_API_URL + value: "https://opt-api.osdci.net" + - name: ORIGIN + value: "https://optima.osdci.net" + - name: PORT + value: "3000" + ports: + - containerPort: 3000 + imagePullSecrets: + - name: github-container-registry diff --git a/kubernetes/ingress.yaml b/kubernetes/ingress.yaml new file mode 100644 index 0000000..a78b662 --- /dev/null +++ b/kubernetes/ingress.yaml @@ -0,0 +1,39 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: optima-ui-ingress + namespace: optima + annotations: + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.tls: "true" +spec: + tls: + - hosts: + - optima.osdci.net + secretName: osdci-net-cert + rules: + - host: optima.osdci.net + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: optima-ui + port: + number: 3000 +--- +apiVersion: v1 +kind: Service +metadata: + name: optima-ui + namespace: optima + labels: + app: optima-ui +spec: + type: ClusterIP + ports: + - port: 3000 + protocol: TCP + selector: + app: optima-ui diff --git a/package.json b/package.json index 2cd35c6..3bcdd7c 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,10 @@ "test": "npm run test:unit -- --run && npm run test:e2e", "test:e2e": "playwright test", "start": "electron-forge start", - "package": "vite build && electron-forge package", - "make": "vite build && electron-forge make", + "package": "electron-forge package", + "make": "electron-forge make", + "make:macos": "electron-forge make --platform darwin", + "build:server": "vite build", "publish": "electron-forge publish" }, "devDependencies": { @@ -34,6 +36,7 @@ "@electron-forge/plugin-vite": "^7.11.1", "@electron/fuses": "^1.8.0", "@playwright/test": "^1.58.0", + "@sveltejs/adapter-node": "^5.5.3", "@sveltejs/adapter-static": "^3.0.10", "@sveltejs/kit": "^2.50.1", "@sveltejs/vite-plugin-svelte": "^5.1.1", diff --git a/src/lib/index.ts b/src/lib/index.ts index ff0b6d0..80c4710 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,18 +1,25 @@ // place files you want to import through the `$lib` alias in this folder. +import { auth } from "./optima-api/modules/auth"; +import { company } from "./optima-api/modules/companies"; +import { credential } from "./optima-api/modules/credentials"; +import { credentialType } from "./optima-api/modules/credentialTypes"; +import { role } from "./optima-api/modules/roles"; +import { permission } from "./optima-api/modules/permissions"; import { user } from "./optima-api/modules/user"; +import { users } from "./optima-api/modules/users"; +import { unifi } from "./optima-api/modules/unifi"; export const optima = { - auth: (await import("./optima-api/modules/auth")).auth, - company: (await import("./optima-api/modules/companies")).company, - credential: (await import("./optima-api/modules/credentials")).credential, - credentialType: (await import("./optima-api/modules/credentialTypes")) - .credentialType, - role: (await import("./optima-api/modules/roles")).role, - permission: (await import("./optima-api/modules/permissions")).permission, + auth, + company, + credential, + credentialType, + role, + permission, user, - users: (await import("./optima-api/modules/users")).users, - unifi: (await import("./optima-api/modules/unifi")).unifi, + users, + unifi, }; /** * @TODO diff --git a/src/lib/optima-api/modules/user.ts b/src/lib/optima-api/modules/user.ts index 3a5f29b..067beba 100644 --- a/src/lib/optima-api/modules/user.ts +++ b/src/lib/optima-api/modules/user.ts @@ -79,6 +79,7 @@ export const user = { let settled = false; const socket = io(`${base}/auth_callback`, { transports: ["websocket"], + rejectUnauthorized: false, }); const timeout = setTimeout( () => { diff --git a/src/routes/(auth)/+layout.server.ts b/src/routes/(auth)/+layout.server.ts index 77ab0a0..e69de29 100644 --- a/src/routes/(auth)/+layout.server.ts +++ b/src/routes/(auth)/+layout.server.ts @@ -1 +0,0 @@ -export const ssr = true; diff --git a/src/routes/companies/[id]/components/UniFiTab.svelte b/src/routes/companies/[id]/components/UniFiTab.svelte index d928a23..5c30655 100644 --- a/src/routes/companies/[id]/components/UniFiTab.svelte +++ b/src/routes/companies/[id]/components/UniFiTab.svelte @@ -640,9 +640,10 @@ const updated = result?.data ?? wifiEditState; selectedWifi = { ...selectedWifi, ...updated } as UnifiWifiNetwork; // Preserve deviceMacs for "devices" mode since the API doesn't return it - const savedDeviceMacs = wifiEditState.apGroupMode === "devices" - ? (wifiEditState.deviceMacs as string[] ?? []) - : []; + const savedDeviceMacs = + wifiEditState.apGroupMode === "devices" + ? ((wifiEditState.deviceMacs as string[]) ?? []) + : []; wifiEditState = { ...updated, deviceMacs: savedDeviceMacs }; wifiOriginalState = { ...updated, deviceMacs: [...savedDeviceMacs] }; isWifiDirty = false; diff --git a/svelte.config.js b/svelte.config.js index 4f1806e..003bc6c 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -1,4 +1,4 @@ -import adapter from "@sveltejs/adapter-static"; +import adapter from "@sveltejs/adapter-node"; import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; const config = { @@ -9,9 +9,7 @@ const config = { }, }, kit: { - adapter: adapter({ - pages: ".vite/renderer/main_window", - }), + adapter: adapter(), router: { type: "pathname", },