Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
936127aa09 |
@@ -4,7 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- main-debipogi
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-deploy:
|
build-and-deploy:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -19,7 +19,7 @@ jobs:
|
|||||||
mkdir -p ~/.ssh
|
mkdir -p ~/.ssh
|
||||||
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||||
chmod 600 ~/.ssh/id_rsa
|
chmod 600 ~/.ssh/id_rsa
|
||||||
git clone --branch debipogi ssh://gitea@gitea.takiguchi.ovh:12960/Codiki/codiki-properties.git --config core.sshCommand='ssh -o StrictHostKeyChecking=no'
|
git clone -b hexagonal-reforged ssh://gitea@gitea.takiguchi.ovh:12960/Codiki/codiki-properties.git --config core.sshCommand='ssh -o StrictHostKeyChecking=no'
|
||||||
|
|
||||||
- name: 📄 Edit configuration
|
- name: 📄 Edit configuration
|
||||||
run: |
|
run: |
|
||||||
@@ -45,11 +45,11 @@ jobs:
|
|||||||
|
|
||||||
- name: 📤 Transfer artifacts to remote server
|
- name: 📤 Transfer artifacts to remote server
|
||||||
env:
|
env:
|
||||||
SSH_PRIVATE_KEY: ${{ secrets.D_PROD_SSH_PRIVATE_KEY }}
|
SSH_PRIVATE_KEY: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
|
||||||
REMOTE_USER: ${{ secrets.D_PROD_REMOTE_USER }}
|
REMOTE_USER: ${{ secrets.PROD_REMOTE_USER }}
|
||||||
REMOTE_HOST: ${{ secrets.D_PROD_REMOTE_HOST }}
|
REMOTE_HOST: ${{ secrets.PROD_REMOTE_HOST }}
|
||||||
REMOTE_PORT: ${{ secrets.D_PROD_REMOTE_PORT }}
|
REMOTE_PORT: ${{ secrets.PROD_REMOTE_PORT }}
|
||||||
REMOTE_PATH: ${{ secrets.D_PROD_REMOTE_PATH }}
|
REMOTE_PATH: ${{ secrets.PROD_REMOTE_PATH }}
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ~/.ssh
|
mkdir -p ~/.ssh
|
||||||
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||||
@@ -61,15 +61,15 @@ jobs:
|
|||||||
- name: 🚀 Launch application onto remote server
|
- name: 🚀 Launch application onto remote server
|
||||||
env:
|
env:
|
||||||
SSH_PRIVATE_KEY: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
|
SSH_PRIVATE_KEY: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
|
||||||
REMOTE_USER: ${{ secrets.D_PROD_REMOTE_USER }}
|
REMOTE_USER: ${{ secrets.PROD_REMOTE_USER }}
|
||||||
REMOTE_HOST: ${{ secrets.D_PROD_REMOTE_HOST }}
|
REMOTE_HOST: ${{ secrets.PROD_REMOTE_HOST }}
|
||||||
REMOTE_PORT: ${{ secrets.D_PROD_REMOTE_PORT }}
|
REMOTE_PORT: ${{ secrets.PROD_REMOTE_PORT }}
|
||||||
REMOTE_PATH: ${{ secrets.D_PROD_REMOTE_PATH }}
|
REMOTE_PATH: ${{ secrets.PROD_REMOTE_PATH }}
|
||||||
run: |
|
run: |
|
||||||
ssh -o StrictHostKeyChecking=no $REMOTE_HOST -l $REMOTE_USER -p $REMOTE_PORT << EOC
|
ssh -o StrictHostKeyChecking=no $REMOTE_HOST -l $REMOTE_USER -p $REMOTE_PORT << EOC
|
||||||
cd $REMOTE_PATH
|
cd $REMOTE_PATH
|
||||||
sudo /usr/bin/docker load < $REMOTE_PATH/codiki-backend.tar
|
sudo /usr/bin/docker load < $REMOTE_PATH/codiki-backend.tar
|
||||||
sudo /usr/bin/docker load < $REMOTE_PATH/codiki-frontend.tar
|
sudo /usr/bin/docker load < $REMOTE_PATH/codiki-frontend.tar
|
||||||
sudo /usr/bin/docker compose --file /home/codiki/docker-compose.yml down
|
sudo /usr/bin/docker compose down
|
||||||
sudo /usr/bin/docker compose --file /home/codiki/docker-compose.yml up --detach
|
sudo /usr/bin/docker compose up --detach
|
||||||
EOC
|
EOC
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
application:
|
application:
|
||||||
pictures:
|
pictures:
|
||||||
path: /Users/fthierry/Documents/Developpement/codiki-hexagonal/backend/pictures-folder
|
path: /home/florian/Developpement/codiki-hexagonal/backend/pictures-folder/
|
||||||
temp-path: /Users/fthierry/Documents/Developpement/codiki-hexagonal/backend/pictures-folder/temp
|
temp-path : /home/florian/Developpement/codiki-hexagonal/backend/pictures-folder/temp/
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
level:
|
level:
|
||||||
|
|||||||
+4
-4
@@ -16,9 +16,9 @@
|
|||||||
<maven.compiler.source>21</maven.compiler.source>
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
<maven.compiler.target>21</maven.compiler.target>
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
<jakarta.servlet-api.version>6.1.0</jakarta.servlet-api.version>
|
<jakarta.servlet-api.version>6.1.0</jakarta.servlet-api.version>
|
||||||
<java-jwt.version>4.5.1</java-jwt.version>
|
<java-jwt.version>4.5.0</java-jwt.version>
|
||||||
<postgresql.version>42.7.10</postgresql.version>
|
<postgresql.version>42.7.8</postgresql.version>
|
||||||
<tika-core.version>3.3.0</tika-core.version>
|
<tika-core.version>3.2.3</tika-core.version>
|
||||||
<commons-lang3.version>3.20.0</commons-lang3.version>
|
<commons-lang3.version>3.20.0</commons-lang3.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-dependencies</artifactId>
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
<version>4.0.5</version>
|
<version>4.0.1</version>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|||||||
+2
-2
@@ -12,7 +12,7 @@ services:
|
|||||||
POSTGRES_PASSWORD: <POSTGRES_PASSWORD>
|
POSTGRES_PASSWORD: <POSTGRES_PASSWORD>
|
||||||
PGDATA: /var/lib/postgresql/data/pgdata
|
PGDATA: /var/lib/postgresql/data/pgdata
|
||||||
volumes:
|
volumes:
|
||||||
- "/home/codiki/database:/var/lib/postgresql/data/pgdata"
|
- "./docker/postgresql/pgdata:/var/lib/postgresql/data/pgdata"
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
codiki-backend:
|
codiki-backend:
|
||||||
@@ -23,7 +23,7 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "50011:8080"
|
- "50011:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- "/home/codiki/pictures:/opt/codiki/pictures"
|
- "/opt/codiki/pictures:/opt/codiki/pictures"
|
||||||
networks:
|
networks:
|
||||||
- "codiki-network"
|
- "codiki-network"
|
||||||
restart: always
|
restart: always
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ http {
|
|||||||
}
|
}
|
||||||
|
|
||||||
location ~ ^/api {
|
location ~ ^/api {
|
||||||
proxy_pass http://192.168.1.154:50011;
|
proxy_pass http://192.168.1.153:50011;
|
||||||
proxy_set_header Host $host:$server_port;
|
proxy_set_header Host $host:$server_port;
|
||||||
proxy_set_header X-Forwarded-Host $server_name;
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
|||||||
Generated
+3548
-2731
File diff suppressed because it is too large
Load Diff
+19
-19
@@ -17,26 +17,26 @@
|
|||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "21.2.10",
|
"@angular/animations": "^21.1.2",
|
||||||
"@angular/cdk": "21.2.8",
|
"@angular/cdk": "^21.1.2",
|
||||||
"@angular/common": "21.2.10",
|
"@angular/common": "^21.1.2",
|
||||||
"@angular/compiler": "21.2.10",
|
"@angular/compiler": "^21.1.2",
|
||||||
"@angular/core": "21.2.10",
|
"@angular/core": "^21.1.2",
|
||||||
"@angular/forms": "21.2.10",
|
"@angular/forms": "^21.1.2",
|
||||||
"@angular/material": "21.2.8",
|
"@angular/material": "^21.1.2",
|
||||||
"@angular/platform-browser": "21.2.10",
|
"@angular/platform-browser": "^21.1.2",
|
||||||
"@angular/platform-browser-dynamic": "21.2.10",
|
"@angular/platform-browser-dynamic": "^21.1.2",
|
||||||
"@angular/router": "21.2.10",
|
"@angular/router": "^21.1.2",
|
||||||
"rxjs": "7.8.2",
|
"rxjs": "~7.8.2",
|
||||||
"tslib": "2.8.1"
|
"tslib": "^2.8.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular/build": "21.2.8",
|
"@angular/build": "^21.1.2",
|
||||||
"@angular/cli": "21.2.8",
|
"@angular/cli": "^21.1.2",
|
||||||
"@angular/compiler-cli": "21.2.10",
|
"@angular/compiler-cli": "^21.1.2",
|
||||||
"@angular/localize": "21.2.10",
|
"@angular/localize": "^21.1.2",
|
||||||
"@types/jasmine": "6.0.0",
|
"@types/jasmine": "~5.1.15",
|
||||||
"jasmine-core": "6.2.0",
|
"jasmine-core": "~5.13.0",
|
||||||
"typescript": "5.9.3"
|
"typescript": "~5.9.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
@for (category of categories(); track category.id) {
|
@for (category of categories$ | async; track category) {
|
||||||
<div class="category {{category.isOpenned ? 'openned' : ''}}">
|
<div class="category {{category.isOpenned ? 'openned' : ''}}">
|
||||||
<div id="category-{{category.id}}" class="category-header" (click)="setOpened(category)">
|
<div id="category-{{category.id}}" class="category-header" (click)="setOpenned(category)">
|
||||||
{{ category.name }}
|
{{ category.name }}
|
||||||
<mat-icon>chevron_right</mat-icon>
|
<mat-icon>chevron_right</mat-icon>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+15
-13
@@ -1,7 +1,8 @@
|
|||||||
import {CommonModule} from "@angular/common";
|
import {CommonModule} from "@angular/common";
|
||||||
import {Component, inject, OnInit, output, Signal} from "@angular/core";
|
import {Component, EventEmitter, inject, OnInit, Output} from "@angular/core";
|
||||||
import {MatIconModule} from "@angular/material/icon";
|
import {MatIconModule} from "@angular/material/icon";
|
||||||
import {DisplayableCategory, SideMenuService} from "../side-menu.service";
|
import {DisplayableCategory, SideMenuService} from "../side-menu.service";
|
||||||
|
import {Observable} from "rxjs";
|
||||||
import {RouterModule} from "@angular/router";
|
import {RouterModule} from "@angular/router";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -15,44 +16,45 @@ import {RouterModule} from "@angular/router";
|
|||||||
styleUrl: './categories-menu.component.scss'
|
styleUrl: './categories-menu.component.scss'
|
||||||
})
|
})
|
||||||
export class CategoriesMenuComponent implements OnInit {
|
export class CategoriesMenuComponent implements OnInit {
|
||||||
readonly #sideMenuService = inject(SideMenuService);
|
private sideMenuService = inject(SideMenuService);
|
||||||
categoryClicked = output<void>();
|
@Output()
|
||||||
|
categoryClicked = new EventEmitter<void>();
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.#sideMenuService.loadCategories();
|
this.sideMenuService.loadCategories();
|
||||||
}
|
}
|
||||||
|
|
||||||
get categories(): Signal<DisplayableCategory[]> {
|
get categories$(): Observable<DisplayableCategory[]> {
|
||||||
return this.#sideMenuService.categories;
|
return this.sideMenuService.categories$;
|
||||||
}
|
}
|
||||||
|
|
||||||
setOpened(category: DisplayableCategory): void {
|
setOpenned(category: DisplayableCategory): void {
|
||||||
if (category.isOpenned) {
|
if (category.isOpenned) {
|
||||||
const categoryDiv = document.getElementById(`category-${category.id}`);
|
const categoryDiv = document.getElementById(`category-${category.id}`);
|
||||||
if (categoryDiv) {
|
if (categoryDiv) {
|
||||||
this.#closeAccordion(categoryDiv);
|
this.closeAccordion(categoryDiv);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const categoriesDivs = document.getElementsByClassName('category-header');
|
const categoriesDivs = document.getElementsByClassName('category-header');
|
||||||
Array.from(categoriesDivs)
|
Array.from(categoriesDivs)
|
||||||
.map(category => category as HTMLElement)
|
.map(category => category as HTMLElement)
|
||||||
.forEach(categoryDiv => this.#closeAccordion(categoryDiv));
|
.forEach(categoryDiv => this.closeAccordion(categoryDiv));
|
||||||
|
|
||||||
const categoryDiv = document.getElementById(`category-${category.id}`);
|
const categoryDiv = document.getElementById(`category-${category.id}`);
|
||||||
if (categoryDiv) {
|
if (categoryDiv) {
|
||||||
this.#openAccordion(categoryDiv);
|
this.openAccordion(categoryDiv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#sideMenuService.setOpened(category);
|
this.sideMenuService.setOpenned(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
#closeAccordion(categoryDiv: HTMLElement): void {
|
private closeAccordion(categoryDiv: HTMLElement): void {
|
||||||
const divContent = categoryDiv?.nextElementSibling as HTMLElement;
|
const divContent = categoryDiv?.nextElementSibling as HTMLElement;
|
||||||
divContent.style.maxHeight = '0';
|
divContent.style.maxHeight = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
#openAccordion(categoryDiv: HTMLElement): void {
|
private openAccordion(categoryDiv: HTMLElement): void {
|
||||||
const divContent = categoryDiv?.nextElementSibling as HTMLElement;
|
const divContent = categoryDiv?.nextElementSibling as HTMLElement;
|
||||||
divContent.style.maxHeight = `${divContent.scrollHeight}px`;
|
divContent.style.maxHeight = `${divContent.scrollHeight}px`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,6 @@
|
|||||||
</button>
|
</button>
|
||||||
</h1>
|
</h1>
|
||||||
<h2 i18n>Categories</h2>
|
<h2 i18n>Categories</h2>
|
||||||
<app-categories-menu (categoryClicked)="close()"/>
|
<app-categories-menu (categoryClicked)="close()"></app-categories-menu>
|
||||||
</div>
|
</div>
|
||||||
<div class="overlay {{ isOpened() ? 'displayed' : ''}}" (click)="close()"></div>
|
<div class="overlay {{ isOpened() ? 'displayed' : ''}}" (click)="close()"></div>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {inject, Injectable, Signal, signal} from '@angular/core';
|
import {inject, Injectable} from '@angular/core';
|
||||||
import {MatSnackBar} from '@angular/material/snack-bar';
|
import {MatSnackBar} from '@angular/material/snack-bar';
|
||||||
|
import {BehaviorSubject, Observable} from 'rxjs';
|
||||||
import {CategoryRestService} from '../../core/rest-services/category/category.rest-service';
|
import {CategoryRestService} from '../../core/rest-services/category/category.rest-service';
|
||||||
import {Category} from '../../core/rest-services/category/model/category';
|
import {Category} from '../../core/rest-services/category/model/category';
|
||||||
|
|
||||||
@@ -19,60 +20,68 @@ export interface DisplayableSubCategory {
|
|||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class SideMenuService {
|
export class SideMenuService {
|
||||||
readonly #categoryRestService = inject(CategoryRestService);
|
private categoryRestService = inject(CategoryRestService);
|
||||||
readonly #snackBar = inject(MatSnackBar);
|
private snackBar = inject(MatSnackBar);
|
||||||
#categories = signal<DisplayableCategory[]>([]);
|
private categoriesSubject = new BehaviorSubject<DisplayableCategory[]>([]);
|
||||||
#isLoading = signal(false);
|
private isLoadingSubject = new BehaviorSubject<boolean>(false);
|
||||||
isLoaded = signal(false);
|
private isLoadedSubject = new BehaviorSubject<boolean>(false);
|
||||||
|
|
||||||
#mapToDisplayableCategory(category: Category): DisplayableCategory {
|
private mapToDisplayableCategory(category: Category): DisplayableCategory {
|
||||||
return {
|
return {
|
||||||
id: category.id,
|
id: category.id,
|
||||||
name: category.name,
|
name: category.name,
|
||||||
subCategories: category.subCategories.map(subCategory => this.#mapToDisplayableSubCategory(subCategory)),
|
subCategories: category.subCategories.map(subCategory => this.mapToDisplayableSubCategory(subCategory)),
|
||||||
isOpenned: false
|
isOpenned: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#mapToDisplayableSubCategory(subCategory: Category): DisplayableSubCategory {
|
private mapToDisplayableSubCategory(subCategory: Category): DisplayableSubCategory {
|
||||||
return {
|
return {
|
||||||
id: subCategory.id,
|
id: subCategory.id,
|
||||||
name: subCategory.name
|
name: subCategory.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get categories(): Signal<DisplayableCategory[]> {
|
private get categories(): DisplayableCategory[] {
|
||||||
return this.#categories.asReadonly();
|
return this.categoriesSubject.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isLoading(): Signal<boolean> {
|
private save(categories: DisplayableCategory[]): void {
|
||||||
return this.#isLoading.asReadonly();
|
this.categoriesSubject.next(categories);
|
||||||
|
}
|
||||||
|
|
||||||
|
get categories$(): Observable<DisplayableCategory[]> {
|
||||||
|
return this.categoriesSubject.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
get isLoading$(): Observable<boolean> {
|
||||||
|
return this.isLoadingSubject.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
loadCategories(): void {
|
loadCategories(): void {
|
||||||
this.#isLoading.set(true);
|
this.isLoadingSubject.next(true);
|
||||||
this.isLoaded.set(false);
|
this.isLoadedSubject.next(false);
|
||||||
|
|
||||||
this.#categoryRestService.getCategories()
|
this.categoryRestService.getCategories()
|
||||||
.then(categories => {
|
.then(categories => {
|
||||||
const displayableCategories = categories
|
const displayableCategories = categories
|
||||||
.filter(category => category.subCategories?.length)
|
.filter(category => category.subCategories?.length)
|
||||||
.map(category => this.#mapToDisplayableCategory(category));
|
.map(category => this.mapToDisplayableCategory(category));
|
||||||
this.#categories.set(displayableCategories);
|
this.categoriesSubject.next(displayableCategories);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
const errorMessage = $localize`An error occured while loading categories.`;
|
const errorMessage = $localize`An error occured while loading categories.`;
|
||||||
console.error(errorMessage, error);
|
console.error(errorMessage, error);
|
||||||
this.#snackBar.open(errorMessage, $localize`Close`, {duration: 5000});
|
this.snackBar.open(errorMessage, $localize`Close`, {duration: 5000});
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.#isLoading.set(false);
|
this.isLoadingSubject.next(false);
|
||||||
this.isLoaded.set(true);
|
this.isLoadedSubject.next(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setOpened(category: DisplayableCategory): void {
|
setOpenned(category: DisplayableCategory): void {
|
||||||
const categories = this.#categories();
|
const categories = this.categories;
|
||||||
const matchingCategory = categories.find(categoryTemp => categoryTemp.id === category.id);
|
const matchingCategory = categories.find(categoryTemp => categoryTemp.id === category.id);
|
||||||
if (matchingCategory) {
|
if (matchingCategory) {
|
||||||
const actualOpennedCategory = categories.find(category => category.isOpenned);
|
const actualOpennedCategory = categories.find(category => category.isOpenned);
|
||||||
@@ -82,7 +91,7 @@ export class SideMenuService {
|
|||||||
categories.forEach(categoryTemp => categoryTemp.isOpenned = false);
|
categories.forEach(categoryTemp => categoryTemp.isOpenned = false);
|
||||||
matchingCategory.isOpenned = true;
|
matchingCategory.isOpenned = true;
|
||||||
}
|
}
|
||||||
this.#categories.set(categories);
|
this.save(categories);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user