diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c4756cf..25b00cbb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: uses: docker/metadata-action@v5 with: images: | - ghcr.io/${{ github.repository }}/web + ghcr.io/${{ github.repository }} tags: | type=ref,event=branch type=ref,event=pr @@ -49,8 +49,6 @@ jobs: uses: docker/build-push-action@v6 with: push: false - build-args: | - VITE_CLERK_PUBLISHABLE_KEY=${{ secrets.CLERK_PUBLISHABLE_KEY }} tags: ${{ steps.meta.outputs.tags }} cache-from: type=gha cache-to: type=gha,mode=max @@ -70,8 +68,6 @@ jobs: uses: docker/build-push-action@v6 with: push: false - build-args: | - VITE_CLERK_PUBLISHABLE_KEY=${{ secrets.CLERK_PUBLISHABLE_KEY }} tags: ${{ needs.build.outputs.tags }} load: true cache-from: type=gha @@ -80,7 +76,12 @@ jobs: env: REPOSITORY: '${{ github.repository }}' run: | - docker run -d -p 5173:80 ghcr.io/${REPOSITORY,,}/web:sha-${{ github.sha }} + docker run -d -p 5173:80 ghcr.io/${REPOSITORY,,}:sha-${{ github.sha }} + - name: Setup Firefox + if: matrix.browser == 'firefox' + uses: browser-actions/setup-firefox@v1 + with: + firefox-version: "140.0" - name: Cypress run uses: cypress-io/github-action@v6 with: @@ -93,29 +94,3 @@ jobs: name: cypress-screenshots-${{ matrix.browser }} path: cypress/screenshots/ retention-days: 7 - - push: - name: Push - runs-on: ubuntu-latest - needs: [build, test] - if: success() - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: Setup buildx - uses: docker/setup-buildx-action@v3 - - name: Login to GHCR - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Build and Push Docker image - uses: docker/build-push-action@v6 - with: - push: true - build-args: | - VITE_CLERK_PUBLISHABLE_KEY=${{ secrets.CLERK_PROD_PUBLISHABLE_KEY }} - tags: ${{ needs.build.outputs.tags }} - cache-from: type=gha - cache-to: type=gha,mode=max diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..3593bae1 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,46 @@ +name: CI +on: + push: + branches: + - main + tags: + - '*' + +jobs: + push: + name: Push + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + attestations: write + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Setup buildx + uses: docker/setup-buildx-action@v3 + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha,format=long + - name: Build and Push Docker image + uses: docker/build-push-action@v6 + with: + push: true + tags: ${{ needs.build.outputs.tags }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile index 1e432913..00bc1499 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,4 @@ FROM node:22.14.0-alpine AS build-stage -ARG VITE_CLERK_PUBLISHABLE_KEY -ENV VITE_CLERK_PUBLISHABLE_KEY=$VITE_CLERK_PUBLISHABLE_KEY WORKDIR /app diff --git a/README.md b/README.md index a52f048f..87de9112 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,6 @@ Check the [open issues](https://github.com/lost-university/web/issues) to see wh ## Project setup -A [Clerk](https://clerk.com/) publishable key is needed to run the project in combination with the backend. Copy the `example.env` file to `.env` and set the variable. -> You don't have to set it up if you only want to run the frontend without the backend. - ``` npm install ``` @@ -67,11 +64,3 @@ npm run test:dev ``` npm run test ``` - -## Pipeline - -The pipeline is configured to set the `CLERK_PUBLISHABLE_KEY` environment variable which is stored inside a github secret. The token will be compiled into the docker container. If the publishable key has changed, a new image must be built. This is because the application is compiled into static files so there is no node server when running in production which could set the token dynamically. -> As the name publishable key suggests, it is not a secret. It is only used to identify the application and to allow Clerk to serve the correct configuration. It is limited to the url configured for this application. - - - diff --git a/cypress/e2e/graph/graphView.cy.ts b/cypress/e2e/graph/graphView.cy.ts index 4246caaf..87e24194 100644 --- a/cypress/e2e/graph/graphView.cy.ts +++ b/cypress/e2e/graph/graphView.cy.ts @@ -1,13 +1,13 @@ /* eslint-disable max-len */ describe("Graph View E2E Tests", () => { beforeEach(() => { - cy.intercept("GET", "https://raw.githubusercontent.com/Janooski/data/main/data/modules.json", { + cy.intercept("GET", "https://raw.githubusercontent.com/lost-university/data/main/data/modules.json", { fixture: "modules.json", }).as("modules"); cy.intercept( "GET", - "https://raw.githubusercontent.com/Janooski/data/main/data2I/categories.json", + "https://raw.githubusercontent.com/lost-university/data/main/data2I/categories.json", { fixture: "categories.json" } ).as("categories"); diff --git a/example.env b/example.env deleted file mode 100644 index a32bad29..00000000 --- a/example.env +++ /dev/null @@ -1 +0,0 @@ -VITE_CLERK_PUBLISHABLE_KEY= \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c4d07297..45041c90 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3777,20 +3777,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "optional": true, - "peer": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", @@ -4150,16 +4136,6 @@ "tweetnacl": "^0.14.3" } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/blob-util": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", @@ -4398,34 +4374,6 @@ "node": ">= 0.8.0" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "optional": true, - "peer": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, "node_modules/ci-info": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.2.0.tgz", @@ -6612,13 +6560,6 @@ "node": ">= 4" } }, - "node_modules/immutable": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", - "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", - "optional": true, - "peer": true - }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -6736,19 +6677,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "optional": true, - "peer": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -7884,16 +7812,6 @@ "dev": true, "license": "MIT" }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/normalize-range": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", @@ -8428,19 +8346,6 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "optional": true, - "peer": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -8739,24 +8644,6 @@ "dev": true, "license": "MIT" }, - "node_modules/sass": { - "version": "1.62.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.62.1.tgz", - "integrity": "sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A==", - "optional": true, - "peer": true, - "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/semver": { "version": "7.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", diff --git a/src/api/config.ts b/src/api/config.ts new file mode 100644 index 00000000..c63390c7 --- /dev/null +++ b/src/api/config.ts @@ -0,0 +1,14 @@ +const fetchConfig = async (): Promise => { + try { + const response = await fetch('/api/config'); + const data = await response.json(); + + return data.clerkPublishableKey + } catch (error) { + return ''; + } +} + +export { + fetchConfig +} diff --git a/src/components/GraphModule.vue b/src/components/GraphModule.vue index 01bd6e36..d63143d3 100644 --- a/src/components/GraphModule.vue +++ b/src/components/GraphModule.vue @@ -109,7 +109,7 @@ export default defineComponent({ required: true }, id: { - type: Number, + type: String, required: true } }, diff --git a/src/components/GraphModuleHightlight.vue b/src/components/GraphModuleHightlight.vue index 03aaab45..9a3d1f53 100644 --- a/src/components/GraphModuleHightlight.vue +++ b/src/components/GraphModuleHightlight.vue @@ -9,7 +9,7 @@ @mouseleave="handleMouseLeave" > diff --git a/src/components/GraphModuleList.vue b/src/components/GraphModuleList.vue index 827a9ac2..996ae67c 100644 --- a/src/components/GraphModuleList.vue +++ b/src/components/GraphModuleList.vue @@ -16,7 +16,7 @@ > @@ -114,4 +114,4 @@ export default defineComponent({ }, }, }); - \ No newline at end of file + diff --git a/src/components/Module.vue b/src/components/Module.vue index 0fd6740d..7235a1ea 100644 --- a/src/components/Module.vue +++ b/src/components/Module.vue @@ -30,7 +30,7 @@ export default defineComponent({ components: { ModuleCard }, props: { module: { type: Object as () => Module, required: true }, - id: { type: Number, required: true } + id: { type: String, required: true } }, emits: ['on-delete'] }) diff --git a/src/components/ModuleCard.vue b/src/components/ModuleCard.vue index 4da474bb..dffc2f75 100644 --- a/src/components/ModuleCard.vue +++ b/src/components/ModuleCard.vue @@ -55,7 +55,7 @@ export default defineComponent({ required: true }, id: { - type: Number, + type: String, required: true }, showValidation: { diff --git a/src/components/ModuleSearch.vue b/src/components/ModuleSearch.vue index 6b73ec22..297d26ff 100644 --- a/src/components/ModuleSearch.vue +++ b/src/components/ModuleSearch.vue @@ -21,10 +21,10 @@
-
+
-
+
-
+
diff --git a/style.css b/style.css index 03d6a803..e07603df 100644 --- a/style.css +++ b/style.css @@ -4,6 +4,11 @@ @import '@vue-flow/core/dist/theme-default.css'; @import '@vue-flow/core/dist/style.css'; +@custom-variant touch-only (@media (hover: none) or (pointer: coarse)); + +/* This media query applies styles only to devices that do not support hover, + such as touchscreens. It ensures that elements with a title attribute + display a tooltip when focused. */ @media (hover: none) { [title] { position: relative; diff --git a/tailwind.config.mjs b/tailwind.config.mjs index a06b26e9..545b3d80 100644 --- a/tailwind.config.mjs +++ b/tailwind.config.mjs @@ -6,7 +6,7 @@ export default { "./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}", ], - darkMode: 'class', + darkMode: 'class', theme: { extend: { screens: { @@ -20,7 +20,6 @@ export default { }, plugins: [ plugin(function({ addVariant }) { - addVariant('touch-only', '@media (hover:none)') addVariant('not-first', '&:not(:first-child)'); }) ]