diff --git a/.github/workflows/build-and-push-docker.yml b/.github/workflows/build-and-push-docker.yml deleted file mode 100644 index a42d7d85..00000000 --- a/.github/workflows/build-and-push-docker.yml +++ /dev/null @@ -1,88 +0,0 @@ -name: Build and Push Docker Images - -on: - pull_request: - paths-ignore: - - 'README.md' - - 'CODE_OF_CONDUCT.md' - - 'CONTRIBUTING.md' - - 'LICENSE' - - 'SECURITY.md' - - 'docs/**' - - 'keycloakify/**' - - '.github/**' - - '!.github/workflows/build-and-push-docker-image.yml' - - '!.github/workflows/dev.yml' - push: - branches: - - develop - -jobs: - build: - name: ${{ matrix.path }} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - include: - - dockerfile: ./webapp/Dockerfile - image: ls1intum/Hephaestus/webapp - context: ./webapp - path: webapp - - dockerfile: ./server/intelligence-service/Dockerfile - image: ls1intum/Hephaestus/intelligence-service - context: ./server/intelligence-service - path: intelligence-service - - dockerfile: ./server/webhook-ingest/Dockerfile - image: ls1intum/Hephaestus/webhook-ingest - context: ./server/webhook-ingest - path: webhook-ingest - - dockerfile: ./server/application-server/Dockerfile - image: ls1intum/Hephaestus/application-server - context: ./server/application-server - path: application-server - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - platforms: all - - - name: Install Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to the Container registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v5 - with: - images: ghcr.io/${{ matrix.image }} - tags: | - type=raw,value=latest,enable={{is_default_branch}} - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=sha,prefix=,format=long - - - name: Build and push Docker Image - uses: docker/build-push-action@v6 - with: - context: ${{ matrix.context }} - file: ${{ matrix.dockerfile }} - platforms: linux/amd64,linux/arm64 - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - push: true - cache-from: type=gha,scope=${{ matrix.image }} - cache-to: type=gha,scope=${{ matrix.image }},mode=max diff --git a/build_images.sh b/build_images.sh new file mode 100644 index 00000000..d9fd3383 --- /dev/null +++ b/build_images.sh @@ -0,0 +1 @@ +nixpacks build -n hephaestus-application-server server/application-server \ No newline at end of file diff --git a/compose.yaml b/compose.yaml index 1d5295aa..33a4baef 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,31 +1,6 @@ services: - webapp: - build: - context: ./webapp - ports: - - '80' - environment: - - APPLICATION_CLIENT_URL - - APPLICATION_SERVER_URL - - SENTRY_DNS - - KEYCLOAK_URL - - KEYCLOAK_REALM - - KEYCLOAK_CLIENT_ID - - KEYCLOAK_SKIP_LOGIN - - LEGAL_IMPRINT_HTML - - LEGAL_PRIVACY_HTML - - UMAMI_ENABLED - - UMAMI_SCRIPT_URL - - UMAMI_WEBSITE_ID - - UMAMI_DOMAINS - depends_on: - - application-server - networks: - - app-network - application-server: - build: - context: ./server/application-server + image: hephaestus-application-server ports: - '8080' environment: @@ -91,7 +66,4 @@ services: networks: app-network: - driver: bridge - -volumes: - postgresql-data: \ No newline at end of file + driver: bridge` \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b5cc70c7..dc061d43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,10 @@ { "name": "hephaestus", - "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "hephaestus", - "version": "0.0.1", "workspaces": [ "webapp/*" ], diff --git a/package.json b/package.json index 10200163..7ae0df07 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,4 @@ { - "version": "0.0.1", "name": "hephaestus", "workspaces": [ "webapp/*" diff --git a/server/application-server/Dockerfile b/server/application-server/Dockerfile deleted file mode 100644 index 19dcd62b..00000000 --- a/server/application-server/Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -FROM maven:3.9.8-eclipse-temurin-21 AS build - -WORKDIR /app - -COPY pom.xml . - -# This step is to cache dependencies, avoiding re-downloading them every time -RUN mvn dependency:go-offline - -COPY src ./src - -RUN mvn clean package -DskipTests - -FROM eclipse-temurin:21 - -WORKDIR /app - -COPY --from=build /app/target/*.jar /app/server.jar - -RUN addgroup --system spring && adduser --system spring --ingroup spring - -USER spring:spring - -EXPOSE 8080 - -ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/server.jar"] \ No newline at end of file diff --git a/server/application-server/nixpacks.toml b/server/application-server/nixpacks.toml new file mode 100644 index 00000000..c7cd6ac8 --- /dev/null +++ b/server/application-server/nixpacks.toml @@ -0,0 +1,8 @@ +[variables] +NIXPACKS_JDK_VERSION = '21' + +[phases.setup] +aptPkgs = ["...", "wget"] + +[phases.build] +cmds = ["chmod +x ./mvnw", "./mvnw -DskipTests clean package"] \ No newline at end of file diff --git a/server/application-server/src/main/resources/application-prod.yml b/server/application-server/src/main/resources/application-prod.yml index a5bdbcb1..37fdd15c 100644 --- a/server/application-server/src/main/resources/application-prod.yml +++ b/server/application-server/src/main/resources/application-prod.yml @@ -14,7 +14,7 @@ spring: issuer-uri: ${KEYCLOAK_URL}/realms/${KEYCLOAK_REALM} hephaestus: - host-url: ${APPLICATION_CLIENT_URL} + host-url: ${APPLICATION_HOST_URL} leaderboard: schedule: @@ -33,8 +33,8 @@ hephaestus: keycloak: url: ${KEYCLOAK_URL} realm: ${KEYCLOAK_REALM} - client-id: ${KEYCLOAK_CONFIDENTIAL_CLIENT_ID} - client-secret: ${KEYCLOAK_CONFIDENTIAL_CLIENT_SECRET} + client-id: ${KEYCLOAK_CLIENT_ID} + client-secret: ${KEYCLOAK_CLIENT_SECRET} nats: enabled: ${NATS_ENABLED:false} diff --git a/webapp/Dockerfile b/webapp/Dockerfile index 6e6c6088..7cab5188 100644 --- a/webapp/Dockerfile +++ b/webapp/Dockerfile @@ -1,46 +1,60 @@ -FROM node:22 AS build +FROM node:latest as build WORKDIR /app -COPY package.json package-lock.json ./ +COPY ./ /app/ + +# Ensure .env file exists +RUN mv .env* .env || true +RUN touch .env +RUN cat .env + +# Fix buggy replacement of COOLIFY_URL in .env +RUN COOLIFY_URL_VALUE=$(grep '^COOLIFY_URL=' .env | cut -d '=' -f2) && \ + sed -i "s|\$COOLIFY_URL|$COOLIFY_URL_VALUE|g" .env + +# Export environment variables from .env +# This assumes that .env contains lines like VARIABLE=value +# and does not contain spaces around the '=' +RUN set -a && \ + . /app/.env && \ + set +a && \ + echo "Generating environment.prod.ts" && \ + cat > src/environments/environment.prod.ts < /app/version.txt - -FROM nginx:stable-alpine - -ENV APPLICATION_CLIENT_URL=https://default-client.url -ENV APPLICATION_SERVER_URL=https://default-server.url - -ENV SENTRY_DNS=https://289f1f62feeb4f70a8878dc0101825cd@sentry.ase.in.tum.de/3 - -ENV KEYCLOAK_URL=https://default-keycloak.url -ENV KEYCLOAK_REALM=default-realm -ENV KEYCLOAK_CLIENT_ID=default-client-id -ENV KEYCLOAK_SKIP_LOGIN=false - -ENV LEGAL_IMPRINT_HTML="

Default Imprint

" -ENV LEGAL_PRIVACY_HTML="

Default Privacy

" - -ENV UMAMI_ENABLED=false -ENV UMAMI_SCRIPT_URL="" -ENV UMAMI_WEBSITE_ID="" -ENV UMAMI_DOMAINS="" +FROM nginx:latest COPY --from=build /app/dist/webapp/browser /usr/share/nginx/html -COPY generate_config.sh /usr/local/bin/generate_config.sh -RUN chmod +x /usr/local/bin/generate_config.sh - COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 - -ENTRYPOINT ["/usr/local/bin/generate_config.sh"] -CMD ["nginx", "-g", "daemon off;"] diff --git a/webapp/angular.json b/webapp/angular.json index e58e11c3..a2a9e259 100644 --- a/webapp/angular.json +++ b/webapp/angular.json @@ -60,6 +60,12 @@ }, "configurations": { "production": { + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" + } + ], "budgets": [ { "type": "initial", diff --git a/webapp/generate_config.sh b/webapp/generate_config.sh deleted file mode 100644 index c7f63c48..00000000 --- a/webapp/generate_config.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -# This script generates the environment.json file for the webapp based on the environment variables during the docker container startup. - -APP_VERSION=$(cat /version.txt) - -cat < /usr/share/nginx/html/environment.json -{ - "version": "{$APP_VERSION}", - "clientUrl": "${APPLICATION_CLIENT_URL}", - "serverUrl": "${APPLICATION_SERVER_URL}", - "sentry": { - "dsn": "${SENTRY_DNS}", - "environment": "prod" - }, - "keycloak": { - "url": "${KEYCLOAK_URL}", - "realm": "${KEYCLOAK_REALM}", - "clientId": "${KEYCLOAK_CLIENT_ID}", - "skipLoginPage": ${KEYCLOAK_SKIP_LOGIN} - }, - "umami": { - "enabled": ${UMAMI_ENABLED}, - "scriptUrl": "${UMAMI_SCRIPT_URL}", - "websiteId": "${UMAMI_WEBSITE_ID}", - "domains": "${UMAMI_DOMAINS}" - }, - "legal": { - "imprintHtml": "$(echo "${LEGAL_IMPRINT_HTML}" | sed 's/"/\\"/g')", - "privacyHtml": "$(echo "${LEGAL_PRIVACY_HTML}" | sed 's/"/\\"/g')" - } -} -EOF - -exec "$@" diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 37b1cc60..8496898b 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -81,7 +81,6 @@ "@storybook/test": "8.3.4", "@tailwindcss/typography": "0.5.15", "@types/jasmine": "5.1.4", - "@types/node": "22.10.1", "@typescript-eslint/eslint-plugin": "8.2.0", "@typescript-eslint/parser": "8.2.0", "chromatic": "11.7.1", @@ -8472,13 +8471,12 @@ } }, "node_modules/@types/node": { - "version": "22.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", - "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==", + "version": "22.7.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", + "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", "devOptional": true, - "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.19.2" } }, "node_modules/@types/node-forge": { @@ -22096,11 +22094,10 @@ } }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "devOptional": true, - "license": "MIT" + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "devOptional": true }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", diff --git a/webapp/package.json b/webapp/package.json index c36b61d1..9180289e 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -93,7 +93,6 @@ "@storybook/test": "8.3.4", "@tailwindcss/typography": "0.5.15", "@types/jasmine": "5.1.4", - "@types/node": "22.10.1", "@typescript-eslint/eslint-plugin": "8.2.0", "@typescript-eslint/parser": "8.2.0", "chromatic": "11.7.1", diff --git a/webapp/public/environment.json b/webapp/public/environment.json deleted file mode 100644 index 6cea134c..00000000 --- a/webapp/public/environment.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "version": "dev", - "clientUrl": "http://localhost:4200", - "serverUrl": "http://localhost:8080", - "sentry": { - "dsn": "https://289f1f62feeb4f70a8878dc0101825cd@sentry.ase.in.tum.de/3", - "environment": "prod" - }, - "keycloak": { - "url": "http://localhost:8081", - "realm": "hephaestus", - "clientId": "hephaestus", - "skipLoginPage": false - }, - "umami": { - "enabled": false, - "scriptUrl": "", - "websiteId": "", - "domains": "" - }, - "legal": { - "imprintHtml": "

This is the imprint.

", - "privacyHtml": "

This is the privacy policy.

" - } -} diff --git a/webapp/src/app/analytics.service.ts b/webapp/src/app/analytics.service.ts index b4194805..b74d050e 100644 --- a/webapp/src/app/analytics.service.ts +++ b/webapp/src/app/analytics.service.ts @@ -1,16 +1,14 @@ -import { inject, Injectable } from '@angular/core'; -import { EnvironmentService } from './environment.service'; +import { Injectable } from '@angular/core'; +import { environment } from 'environments/environment'; @Injectable({ providedIn: 'root' }) export class AnalyticsService { - private environmentService = inject(EnvironmentService); - private scriptLoaded = false; initialize(): void { - if (this.environmentService.env.umami.enabled) { + if (environment.umami.enabled) { this.loadUmamiScript(); } } @@ -22,9 +20,9 @@ export class AnalyticsService { const script = document.createElement('script'); script.defer = true; - script.src = this.environmentService.env.umami.scriptUrl; - script.setAttribute('data-website-id', this.environmentService.env.umami.websiteId); - script.setAttribute('data-domains', this.environmentService.env.umami.domains); + script.src = environment.umami.scriptUrl; + script.setAttribute('data-website-id', environment.umami.websiteId); + script.setAttribute('data-domains', environment.umami.domains); script.onload = () => { console.log('Umami analytics script loaded successfully.'); diff --git a/webapp/src/app/app.config.ts b/webapp/src/app/app.config.ts index 29cc314e..3da5f04e 100644 --- a/webapp/src/app/app.config.ts +++ b/webapp/src/app/app.config.ts @@ -3,17 +3,16 @@ import { provideRouter, Router } from '@angular/router'; import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; import { provideHttpClient, withInterceptors } from '@angular/common/http'; import { provideAngularQuery, QueryClient } from '@tanstack/angular-query-experimental'; +import { environment } from 'environments/environment'; import { BASE_PATH } from 'app/core/modules/openapi'; import { routes } from 'app/app.routes'; import { AnalyticsService } from './analytics.service'; import { securityInterceptor } from './core/security/security-interceptor'; -import { EnvironmentService } from './environment.service'; import { TraceService } from '@sentry/angular'; import { SentryErrorHandler } from './core/sentry/sentry.error-handler'; -function initializeApp(environmentService: EnvironmentService, analyticsService: AnalyticsService) { +function initializeAnalytics(analyticsService: AnalyticsService): () => void { return () => { - environmentService.loadEnv(); analyticsService.initialize(); }; } @@ -25,12 +24,8 @@ export const appConfig: ApplicationConfig = { provideAngularQuery(new QueryClient()), provideHttpClient(withInterceptors([securityInterceptor])), provideAnimationsAsync(), - { provide: APP_INITIALIZER, useFactory: initializeApp, multi: true, deps: [EnvironmentService, AnalyticsService] }, - { - provide: BASE_PATH, - useFactory: (environmentService: EnvironmentService) => environmentService.env.serverUrl, - deps: [EnvironmentService] - }, + { provide: BASE_PATH, useValue: environment.serverUrl }, + { provide: APP_INITIALIZER, useFactory: initializeAnalytics, multi: true, deps: [AnalyticsService] }, { provide: ErrorHandler, useClass: SentryErrorHandler }, { provide: TraceService, deps: [Router] }, { diff --git a/webapp/src/app/core/header/header.component.html b/webapp/src/app/core/header/header.component.html index b47af1c0..955d44af 100644 --- a/webapp/src/app/core/header/header.component.html +++ b/webapp/src/app/core/header/header.component.html @@ -3,7 +3,6 @@ - {{ appVersion }} @if (user()?.roles?.includes('admin')) { Workspace diff --git a/webapp/src/app/core/header/header.component.ts b/webapp/src/app/core/header/header.component.ts index 28e8d3bc..59a6dfb7 100644 --- a/webapp/src/app/core/header/header.component.ts +++ b/webapp/src/app/core/header/header.component.ts @@ -9,9 +9,9 @@ import { BrnMenuTriggerDirective } from '@spartan-ng/ui-menu-brain'; import { SecurityStore } from '@app/core/security/security-store.service'; import { ThemeSwitcherComponent } from '@app/core/theme/theme-switcher.component'; import { RequestFeatureComponent } from './request-feature/request-feature.component'; +import { environment } from 'environments/environment'; import { lucideUser, lucideLogOut, lucideSettings } from '@ng-icons/lucide'; import { provideIcons } from '@ng-icons/core'; -import { EnvironmentService } from '@app/environment.service'; import { AiMentorComponent } from './ai-mentor/ai-mentor.component'; @Component({ @@ -40,8 +40,6 @@ import { AiMentorComponent } from './ai-mentor/ai-mentor.component'; ] }) export class HeaderComponent { - private environmentService = inject(EnvironmentService); - protected Hammer = Hammer; securityStore = inject(SecurityStore); @@ -52,16 +50,12 @@ export class HeaderComponent { this.securityStore.signOut(); } - protected get appVersion() { - return this.environmentService.env.version; - } - protected signIn() { - if (this.environmentService.env.keycloak.skipLoginPage) { + if (environment.keycloak.skipLoginPage) { const authUrl = - `${this.environmentService.env.keycloak.url}/realms/${this.environmentService.env.keycloak.realm}/protocol/openid-connect/auth` + - `?client_id=${encodeURIComponent(this.environmentService.env.keycloak.clientId)}` + - `&redirect_uri=${encodeURIComponent(this.environmentService.env.clientUrl)}` + + `${environment.keycloak.url}/realms/${environment.keycloak.realm}/protocol/openid-connect/auth` + + `?client_id=${encodeURIComponent(environment.keycloak.clientId)}` + + `&redirect_uri=${encodeURIComponent(environment.clientUrl)}` + `&response_type=code` + `&scope=openid` + `&kc_idp_hint=${encodeURIComponent('github')}`; diff --git a/webapp/src/app/core/security/keycloak.service.ts b/webapp/src/app/core/security/keycloak.service.ts index c7082b73..168f3984 100644 --- a/webapp/src/app/core/security/keycloak.service.ts +++ b/webapp/src/app/core/security/keycloak.service.ts @@ -1,5 +1,5 @@ -import { inject, Injectable } from '@angular/core'; -import { EnvironmentService } from '@app/environment.service'; +import { Injectable } from '@angular/core'; +import { environment } from 'environments/environment'; import Keycloak from 'keycloak-js'; export interface UserProfile { @@ -17,17 +17,15 @@ export interface UserProfile { @Injectable({ providedIn: 'root' }) export class KeycloakService { - private environmentService = inject(EnvironmentService); - _keycloak: Keycloak | undefined; profile: UserProfile | undefined; get keycloak() { if (!this._keycloak) { this._keycloak = new Keycloak({ - url: this.environmentService.env.keycloak.url, - realm: this.environmentService.env.keycloak.realm, - clientId: this.environmentService.env.keycloak.clientId + url: environment.keycloak.url, + realm: environment.keycloak.realm, + clientId: environment.keycloak.clientId }); } return this._keycloak; @@ -80,6 +78,6 @@ export class KeycloakService { } logout() { - return this.keycloak.logout({ redirectUri: this.environmentService.env.clientUrl }); + return this.keycloak.logout({ redirectUri: environment.clientUrl }); } } diff --git a/webapp/src/app/core/sentry/sentry.error-handler.ts b/webapp/src/app/core/sentry/sentry.error-handler.ts index 357e88e7..2bde1073 100644 --- a/webapp/src/app/core/sentry/sentry.error-handler.ts +++ b/webapp/src/app/core/sentry/sentry.error-handler.ts @@ -1,10 +1,10 @@ -import { ErrorHandler, inject, Injectable } from '@angular/core'; -import { EnvironmentService } from '@app/environment.service'; +import { ErrorHandler, Injectable } from '@angular/core'; +import { environment } from 'environments/environment'; import * as Sentry from '@sentry/angular'; @Injectable({ providedIn: 'root' }) export class SentryErrorHandler extends ErrorHandler { - private environmentService = inject(EnvironmentService); + private environment = environment; constructor() { super(); @@ -14,7 +14,7 @@ export class SentryErrorHandler extends ErrorHandler { * Initialize Sentry with environment. */ async init() { - const env = this.environmentService.env; + const env = this.environment; if (!env || !env.version || !env.sentry?.dsn) { return; } @@ -38,7 +38,7 @@ export class SentryErrorHandler extends ErrorHandler { super.handleError(error); return; } - if (this.environmentService.env.sentry.environment !== 'local') { + if (this.environment.sentry.environment !== 'local') { const exception = error.error || error.message || error.originalError || error; Sentry.captureException(exception); } diff --git a/webapp/src/app/environment.service.ts b/webapp/src/app/environment.service.ts deleted file mode 100644 index 64081ca0..00000000 --- a/webapp/src/app/environment.service.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Injectable, isDevMode } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { lastValueFrom } from 'rxjs'; - -export interface Environment { - version: string; - clientUrl: string; - serverUrl: string; - sentry: { - dsn: string; - environment: string; - }; - keycloak: { - url: string; - realm: string; - clientId: string; - skipLoginPage: boolean; - }; - umami: { - enabled: boolean; - scriptUrl: string; - websiteId: string; - domains: string; - }; - legal: { - imprintHtml: string; - privacyHtml: string; - }; -} - -@Injectable({ - providedIn: 'root' -}) -export class EnvironmentService { - private environment!: Environment; - - constructor(private http: HttpClient) {} - - loadEnv() { - if (isDevMode()) { - // eslint-disable-next-line @typescript-eslint/no-require-imports - const environment = require('../../public/environment.json') as Environment; - this.environment = environment; - return Promise.resolve(); - } else { - return lastValueFrom(this.http.get('/environment.json')) - .then((environment) => { - this.environment = environment; - console.log('Environment loaded successfully.', this.environment); - }) - .catch((error) => { - console.error('Error loading environment.', error); - }); - } - } - - get env(): Environment { - return this.environment; - } -} diff --git a/webapp/src/app/home/home.component.ts b/webapp/src/app/home/home.component.ts index eee831f9..8a884ab1 100644 --- a/webapp/src/app/home/home.component.ts +++ b/webapp/src/app/home/home.component.ts @@ -1,5 +1,5 @@ -import dayjs from 'dayjs/esm'; -import isoWeek from 'dayjs/esm/plugin/isoWeek'; +import dayjs from 'dayjs'; +import isoWeek from 'dayjs/plugin/isoWeek'; import { lastValueFrom } from 'rxjs'; import { Component, computed, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; diff --git a/webapp/src/app/home/leaderboard/filter/timeframe/timeframe.component.ts b/webapp/src/app/home/leaderboard/filter/timeframe/timeframe.component.ts index fe74151e..39f7ba44 100644 --- a/webapp/src/app/home/leaderboard/filter/timeframe/timeframe.component.ts +++ b/webapp/src/app/home/leaderboard/filter/timeframe/timeframe.component.ts @@ -1,8 +1,8 @@ import { Component, computed, effect, inject, signal } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; -import dayjs from 'dayjs/esm'; -import isoWeek from 'dayjs/esm/plugin/isoWeek'; +import dayjs from 'dayjs'; +import isoWeek from 'dayjs/plugin/isoWeek'; import { BrnSelectModule } from '@spartan-ng/ui-select-brain'; import { HlmSelectModule } from '@spartan-ng/ui-select-helm'; import { HlmLabelModule } from '@spartan-ng/ui-label-helm'; diff --git a/webapp/src/app/legal/imprint.component.ts b/webapp/src/app/legal/imprint.component.ts index a07d84f8..1337b3d7 100644 --- a/webapp/src/app/legal/imprint.component.ts +++ b/webapp/src/app/legal/imprint.component.ts @@ -1,5 +1,5 @@ -import { Component, inject } from '@angular/core'; -import { EnvironmentService } from '@app/environment.service'; +import { Component } from '@angular/core'; +import { environment } from 'environments/environment'; @Component({ selector: 'app-imprint', @@ -12,6 +12,5 @@ import { EnvironmentService } from '@app/environment.service'; ` }) export class ImprintComponent { - private environmentService = inject(EnvironmentService); - imprintHtml = this.environmentService.env.legal.imprintHtml; + imprintHtml = environment.legal.imprintHtml; } diff --git a/webapp/src/app/legal/privacy.component.ts b/webapp/src/app/legal/privacy.component.ts index 1b1128c5..18a1d61b 100644 --- a/webapp/src/app/legal/privacy.component.ts +++ b/webapp/src/app/legal/privacy.component.ts @@ -1,5 +1,5 @@ -import { Component, inject } from '@angular/core'; -import { EnvironmentService } from '@app/environment.service'; +import { Component } from '@angular/core'; +import { environment } from 'environments/environment'; @Component({ selector: 'app-privacy', @@ -12,6 +12,5 @@ import { EnvironmentService } from '@app/environment.service'; ` }) export class PrivacyComponent { - private environmentService = inject(EnvironmentService); - imprintHtml = this.environmentService.env.legal.privacyHtml; + imprintHtml = environment.legal.privacyHtml; } diff --git a/webapp/src/app/user/header/header.component.ts b/webapp/src/app/user/header/header.component.ts index 07243d27..f232a8a5 100644 --- a/webapp/src/app/user/header/header.component.ts +++ b/webapp/src/app/user/header/header.component.ts @@ -7,8 +7,8 @@ import { HlmIconModule } from 'libs/ui/ui-icon-helm/src/index'; import { BrnTooltipContentDirective } from '@spartan-ng/ui-tooltip-brain'; import { HlmTooltipComponent, HlmTooltipTriggerDirective } from '@spartan-ng/ui-tooltip-helm'; import { HlmButtonModule } from '@spartan-ng/ui-button-helm'; -import dayjs from 'dayjs/esm'; -import advancedFormat from 'dayjs/esm/plugin/advancedFormat'; +import dayjs from 'dayjs'; +import advancedFormat from 'dayjs/plugin/advancedFormat'; import { RepositoryInfo, UserInfo } from '@app/core/modules/openapi'; dayjs.extend(advancedFormat); diff --git a/webapp/src/app/user/header/header.stories.ts b/webapp/src/app/user/header/header.stories.ts index 660b1315..31656f02 100644 --- a/webapp/src/app/user/header/header.stories.ts +++ b/webapp/src/app/user/header/header.stories.ts @@ -1,5 +1,5 @@ import { argsToTemplate, Meta, StoryObj } from '@storybook/angular'; -import dayjs from 'dayjs/esm'; +import dayjs from 'dayjs'; import { UserHeaderComponent } from './header.component'; type FlatArgs = { diff --git a/webapp/src/app/user/issue-card/issue-card.component.ts b/webapp/src/app/user/issue-card/issue-card.component.ts index 3d200831..a4b93fbb 100644 --- a/webapp/src/app/user/issue-card/issue-card.component.ts +++ b/webapp/src/app/user/issue-card/issue-card.component.ts @@ -5,7 +5,7 @@ import { octCheck, octComment, octFileDiff, octGitPullRequest, octGitPullRequest import { HlmCardModule } from '@spartan-ng/ui-card-helm'; import { HlmSkeletonComponent } from '@spartan-ng/ui-skeleton-helm'; import { GithubLabelComponent } from '@app/ui/github-label/github-label.component'; -import dayjs from 'dayjs/esm'; +import dayjs from 'dayjs'; import { cn } from '@app/utils'; @Component({ diff --git a/webapp/src/app/user/review-activity-card/review-activity-card.component.ts b/webapp/src/app/user/review-activity-card/review-activity-card.component.ts index abe52943..241e5c90 100644 --- a/webapp/src/app/user/review-activity-card/review-activity-card.component.ts +++ b/webapp/src/app/user/review-activity-card/review-activity-card.component.ts @@ -7,8 +7,8 @@ import { HlmSkeletonComponent } from '@spartan-ng/ui-skeleton-helm'; import { HlmIconComponent } from '@spartan-ng/ui-icon-helm'; import { HlmTooltipTriggerDirective } from '@spartan-ng/ui-tooltip-helm'; import { HlmButtonModule } from '@spartan-ng/ui-button-helm'; -import dayjs from 'dayjs/esm'; -import relativeTime from 'dayjs/esm/plugin/relativeTime'; +import dayjs from 'dayjs'; +import relativeTime from 'dayjs/plugin/relativeTime'; import { lucideAward } from '@ng-icons/lucide'; dayjs.extend(relativeTime); diff --git a/webapp/src/app/user/review-activity-card/review-activity-card.stories.ts b/webapp/src/app/user/review-activity-card/review-activity-card.stories.ts index d7eb743c..93884e71 100644 --- a/webapp/src/app/user/review-activity-card/review-activity-card.stories.ts +++ b/webapp/src/app/user/review-activity-card/review-activity-card.stories.ts @@ -1,6 +1,6 @@ import { argsToTemplate, Meta, StoryObj } from '@storybook/angular'; import { ReviewActivityCardComponent } from './review-activity-card.component'; -import dayjs from 'dayjs/esm'; +import dayjs from 'dayjs'; type FlatArgs = { isLoading: boolean; diff --git a/webapp/src/environments/environment.prod.ts b/webapp/src/environments/environment.prod.ts new file mode 100644 index 00000000..a409952e --- /dev/null +++ b/webapp/src/environments/environment.prod.ts @@ -0,0 +1,25 @@ +export const environment = { + clientUrl: 'http://localhost:4200', + serverUrl: 'http://localhost:8080', + version: '0.0.1', + sentry: { + dsn: 'https://289f1f62feeb4f70a8878dc0101825cd@sentry.ase.in.tum.de/3', + environment: 'prod' + }, + keycloak: { + url: 'http://localhost:8081', + realm: 'hephaestus', + clientId: 'hephaestus', + skipLoginPage: false // If true, it will directly use github IDP for login + }, + umami: { + enabled: false, + scriptUrl: '', + websiteId: '', + domains: '' + }, + legal: { + imprintHtml: '

This is the imprint.

', + privacyHtml: '

This is the privacy policy.

' + } +}; diff --git a/webapp/src/environments/environment.ts b/webapp/src/environments/environment.ts new file mode 100644 index 00000000..a409952e --- /dev/null +++ b/webapp/src/environments/environment.ts @@ -0,0 +1,25 @@ +export const environment = { + clientUrl: 'http://localhost:4200', + serverUrl: 'http://localhost:8080', + version: '0.0.1', + sentry: { + dsn: 'https://289f1f62feeb4f70a8878dc0101825cd@sentry.ase.in.tum.de/3', + environment: 'prod' + }, + keycloak: { + url: 'http://localhost:8081', + realm: 'hephaestus', + clientId: 'hephaestus', + skipLoginPage: false // If true, it will directly use github IDP for login + }, + umami: { + enabled: false, + scriptUrl: '', + websiteId: '', + domains: '' + }, + legal: { + imprintHtml: '

This is the imprint.

', + privacyHtml: '

This is the privacy policy.

' + } +}; diff --git a/webapp/tsconfig.app.json b/webapp/tsconfig.app.json index e2722e2f..3775b37e 100644 --- a/webapp/tsconfig.app.json +++ b/webapp/tsconfig.app.json @@ -4,7 +4,7 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./out-tsc/app", - "types": ["node"] + "types": [] }, "files": [ "src/main.ts" diff --git a/webapp/tsconfig.json b/webapp/tsconfig.json index 4f92768e..90dcda75 100644 --- a/webapp/tsconfig.json +++ b/webapp/tsconfig.json @@ -2,7 +2,6 @@ "compileOnSave": false, "compilerOptions": { "outDir": "./dist/out-tsc", - "types": ["node"], "strict": true, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true,