diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..edbf375 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +# Gebruik een multi-architecture versie van Node +FROM --platform=linux/amd64 node:22.0.0 as build + +WORKDIR /app + +COPY package*.json ./ + +RUN npm install + +RUN npm install -g @angular/cli + +COPY . . + +RUN ng build --configuration=production + +# Gebruik een multi-architecture versie van Nginx +FROM --platform=linux/amd64 nginx:latest + +# Kopieer de gecompileerde bestanden van Angular naar de Nginx-webserver +COPY --from=build app/dist/job-findr-frontend/browser /usr/share/nginx/html + +EXPOSE 80 diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..18e3dc3 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,79 @@ +pipeline { + agent any + tools { + jdk 'jdk-21' + maven 'mvn 3.9.9' + } + environment { + SSH_CREDENTIALS_ID = 'ssh-true-nas' // ID van de SSH-sleutel in Jenkins + TRUENAS_HOST = '192.168.2.31' // IP-adres of hostname van TrueNAS + SSH_USER = 'jenkins' // SSH-gebruiker voor TrueNAS + IMAGE_REPO = 'veenm' // Naam van de Docker-image + IMAGE_NAME = 'jobfindr' // Naam van de Docker-image + IMAGE_TAG = 'latest' + } + + stages { + stage('Checkout Code') { + steps { + checkout scm + } + } + + stage('Build Angular Project') { + steps { + script { + // Bouw het Quarkus-project (assumeert Maven als build tool) + sh 'ng build' + } + } + } + + stage('Build Docker Image') { + steps { + script { + + // Maak een Docker-image gebaseerd op de Dockerfile + sh 'ls' + } + } + } + + stage('Push Docker Image') { + steps { + script { + // Push de Docker-image naar een Docker Registry + sh """ + docker push ${IMAGE_REPO}/${IMAGE_NAME}:${IMAGE_TAG} + """ + } + } + } + + stage('Deploy Docker Image to TrueNAS') { + steps { + script { + // Verbind via SSH met TrueNAS en voer Docker-installatiecommando's uit + sshagent([SSH_CREDENTIALS_ID]) { + sh """ + ssh -o StrictHostKeyChecking=no ${SSH_USER}@${TRUENAS_HOST} << EOF + sudo docker stop ${IMAGE_NAME} || true + sudo docker rm ${IMAGE_NAME} || true + sudo docker pull ${IMAGE_REPO}/${IMAGE_NAME}:${IMAGE_TAG} || echo "Local image will be used" + sudo docker run -d --name ${IMAGE_NAME} -p 8080:8080 \ + ${IMAGE_REPO}/${IMAGE_NAME}:${IMAGE_TAG} + """ + } + } + } + } + } + + post { + always { + script { + echo "Pipeline execution completed." + } + } + } +} diff --git a/src/app/app.component.css b/src/app/app.component.css index e69de29..bef4fa4 100644 --- a/src/app/app.component.css +++ b/src/app/app.component.css @@ -0,0 +1,94 @@ +.vacatures-container { + max-width: 1200px; + margin: 0 auto; + padding: 20px; + background-color: #f7f8fa; /* Lichtgrijze achtergrond */ + border-radius: 8px; +} + +h1 { + text-align: center; + font-size: 3em; + color: #3498db; /* Blauwe kleur voor een frisse uitstraling */ + margin-bottom: 40px; + font-family: 'Roboto', sans-serif; +} + +.vacature-card { + background-color: #ffffff; + border-radius: 12px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); + margin: 20px 0; + padding: 20px; + transition: all 0.3s ease-in-out; + border: 2px solid #ecf0f1; /* Lichte rand om de cards */ + display: flex; + flex-direction: column; + justify-content: space-between; +} + +.vacature-card:hover { + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2); + transform: translateY(-5px); /* Card tilt effect */ +} + +.vacature-card h2 { + font-size: 1.6em; + color: #2ecc71; /* Groene kleur voor de titel */ + font-family: 'Poppins', sans-serif; + font-weight: bold; +} + +.vacature-card p { + color: #7f8c8d; /* Donkergrijze tekstkleur voor locatie en datum */ + font-size: 1em; + margin: 5px 0; +} + +.vacature-card a { + text-decoration: none; + color: inherit; /* Kleur van de tekst erft van de titel */ +} + +.vacature-card a:hover h2 { + color: #e74c3c; /* Rood voor de hover-effect op de titel */ +} + +.vacature-card .location { + font-size: 1.1em; + color: #95a5a6; /* Grijze kleur voor de locatie */ + margin-top: 10px; +} + +.vacature-card .date { + font-size: 0.9em; + color: #bdc3c7; /* Lichte grijze kleur voor de datum */ + margin-top: 10px; +} + +.vacature-card button { + background-color: #3498db; /* Blauwe knop */ + color: white; + border: none; + padding: 10px 20px; + font-size: 1em; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s ease; + align-self: flex-start; + margin-top: 15px; +} + +.vacature-card button:hover { + background-color: #2980b9; /* Donkerder blauw bij hover */ +} + +.vacature-card button:focus { + outline: none; + box-shadow: 0 0 5px rgba(52, 152, 219, 0.7); +} + +.row{ + display: flex; + text-align: center; +} diff --git a/src/app/app.component.html b/src/app/app.component.html index 36093e1..ab81b4a 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,336 +1,19 @@ - - - - - - - - +
+

Vacatures

+
+ +

{{ vacature.titel }}

+

{{ vacature.locatie }}

- - -
-
-
- -

Hello, {{ title }}

-

Congratulations! Your app is running. 🎉

-
- -
+

Geplaatst: {{ vacature.detail.geplaatst }}

+

Sluitingsdatum: {{ vacature.detail.sluitingsdatum }}

+

Aantal uren: {{ vacature.detail.aantalUren }}

+

Dienstverband: {{ vacature.detail.dienstverband }}

+

FTE: {{ vacature.detail.fte }}

+

Salaris: {{ vacature.detail.salaris }}

+

Startdatum: {{ vacature.detail.startdatum }}

+

Soort vacature: {{ vacature.detail.soortVacature }}

+

Zij-instromers: {{ vacature.detail.zijInstromers }}

+
-
- - - - - - - - - - - +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index c509bf4..59354ca 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,12 +1,38 @@ -import { Component } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; +import {Component, OnInit} from '@angular/core'; +import {HttpClient} from '@angular/common/http'; +import {Vacature} from './domain/vacature'; +import {NgForOf} from '@angular/common'; @Component({ selector: 'app-root', - imports: [RouterOutlet], + imports: [NgForOf], templateUrl: './app.component.html', styleUrl: './app.component.css' }) -export class AppComponent { - title = 'jobFindr-frontend'; +export class AppComponent implements OnInit{ + protected vacatures: Vacature[] = new Array(); + + constructor(private http: HttpClient) { + } + + toggleDarkMode() { + const currentTheme = document.documentElement.getAttribute('data-theme'); + const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; + document.documentElement.setAttribute('data-theme', newTheme); + } + + ngOnInit(): void { + this.http.get('https://jobfindr.melvanveen.nl/vacatures/all').subscribe( + (response: Vacature[]) => { + console.log(response) + this.vacatures = response + console.log(this.vacatures); + } + ) + } + title = 'JobFindr'; + + formatDate(date: string) { + return new Date(date).toLocaleDateString(); + } } diff --git a/src/app/app.config.ts b/src/app/app.config.ts index a1e7d6f..2ac860a 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -2,7 +2,8 @@ import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; +import {provideHttpClient, withInterceptorsFromDi} from '@angular/common/http'; export const appConfig: ApplicationConfig = { - providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes)] + providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideHttpClient(withInterceptorsFromDi())] }; diff --git a/src/app/domain/vacature-detail.ts b/src/app/domain/vacature-detail.ts new file mode 100644 index 0000000..b40157d --- /dev/null +++ b/src/app/domain/vacature-detail.ts @@ -0,0 +1,12 @@ +export interface VacatureDetail { + id: string; + geplaatst: string; + sluitingsdatum: string; + salaris: string; + aantalUren: string; + fte: string; + startdatum: string; + soortVacature: string; + dienstverband: string; + zijInstromers: string; +} diff --git a/src/app/domain/vacature.ts b/src/app/domain/vacature.ts new file mode 100644 index 0000000..facf801 --- /dev/null +++ b/src/app/domain/vacature.ts @@ -0,0 +1,10 @@ +import {VacatureDetail} from './vacature-detail'; + +export interface Vacature { + id: string; + titel: string; + locatie: string; + url: string; + datum: string; + detail: VacatureDetail; +} diff --git a/src/index.html b/src/index.html index 8bee0d4..468e2cf 100644 --- a/src/index.html +++ b/src/index.html @@ -2,12 +2,12 @@ - JobFindrFrontend + JobFindr - + diff --git a/src/styles.css b/src/styles.css index 90d4ee0..7376a42 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1 +1,12 @@ /* You can add global styles to this file, and also import other style files */ +body{ + font-family: sans-serif; +} + + +.title-card{ + text-align: center; + background-color: #2c3d50; + color: white; + width: 100%; +} diff --git a/tsconfig.json b/tsconfig.json index 5525117..268414f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,7 @@ "compileOnSave": false, "compilerOptions": { "outDir": "./dist/out-tsc", - "strict": true, + "strict": false, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true,