add redux in csc

This commit is contained in:
Tykayn 2025-08-08 11:31:27 +02:00 committed by tykayn
parent a89007a81b
commit 3534919502
14 changed files with 277 additions and 12 deletions

1
.gitignore vendored
View file

@ -0,0 +1 @@
ng-demo

View file

@ -0,0 +1,15 @@
<div class="alert is-{{alertKind}}">
@if (alertKind == "warning"){
<i class="ri-triangle-line"></i>
}
@if (alertKind == "danger"){
<i class="ri-triangle-line"></i>
}
@if (alertKind == "error"){
<i class="ri-triangle-line"></i>
}
<slot name="main">
{{message}}
</slot>
<ng-content></ng-content>
</div>

View file

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AlertBox } from './alert-box';
describe('AlertBox', () => {
let component: AlertBox;
let fixture: ComponentFixture<AlertBox>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AlertBox]
})
.compileComponents();
fixture = TestBed.createComponent(AlertBox);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,22 @@
import {Component, Input} from '@angular/core';
import {NgClass} from '@angular/common';
@Component({
selector: 'app-alert-box',
imports: [
],
templateUrl: './alert-box.html',
styleUrl: './alert-box.scss'
})
export class AlertBox {
get alertKind(): string {
return this._alertKind;
}
set alertKind(value: string) {
this._alertKind = value;
}
@Input() public _alertKind: string = "warning";
@Input() public message: string = "";
}

View file

@ -7,7 +7,10 @@
"@angular/forms": "^20.1.0",
"bulma": "^1.0.4",
"remixicon": "^4.6.0",
"shepherd.js": "^14.5.1"
"shepherd.js": "^14.5.1",
"@ngrx/store": "^20.0.0",
"@ngrx/store-devtools": "^20.0.0"
},
"dependencies": {
"tslib": "^2.3.0"

View file

@ -27,3 +27,4 @@
@use '_layout_demo.scss';
@use '_main_button.scss';

View file

@ -14,6 +14,7 @@
"@angular/forms": "^20.1.0",
"@angular/platform-browser": "^20.1.0",
"@angular/router": "^20.1.0",
"@ngrx/store": "^20.0.0",
"remixicon": "^4.6.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
@ -4930,6 +4931,19 @@
"node": ">= 10"
}
},
"node_modules/@ngrx/store": {
"version": "20.0.0",
"resolved": "https://registry.npmjs.org/@ngrx/store/-/store-20.0.0.tgz",
"integrity": "sha512-UVj6UVayXknq1V/OXSGAVG+CdSXYg+oFM6T4aplcP2fuq/4oHtnVi93hkIYa9OU+rhAuHvfRsOsGsTtxlpj52w==",
"license": "MIT",
"dependencies": {
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/core": "^20.0.0",
"rxjs": "^6.5.3 || ^7.5.0"
}
},
"node_modules/@ngtools/webpack": {
"version": "20.1.4",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-20.1.4.tgz",

View file

@ -28,6 +28,7 @@
"@angular/forms": "^20.1.0",
"@angular/platform-browser": "^20.1.0",
"@angular/router": "^20.1.0",
"@ngrx/store": "^20.0.0",
"remixicon": "^4.6.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
@ -42,6 +43,7 @@
"@storybook/addon-docs": "^9.1.1",
"@storybook/angular": "^9.1.1",
"@types/jasmine": "~5.1.0",
"bulma": "^1.0.4 ",
"jasmine-core": "~5.8.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
@ -49,7 +51,6 @@
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"storybook": "^9.1.1",
"bulma": "^1.0.4 ",
"typescript": "~5.8.2"
}
}

View file

@ -1,9 +1,10 @@
import { Component, signal } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import {SaeLib} from '../../../my-workspace/projects/sae-lib/src/public-api';
@Component({
selector: 'app-root',
imports: [RouterOutlet],
imports: [RouterOutlet, SaeLib],
templateUrl: './app.html',
styleUrl: './app.scss'
})

View file

@ -0,0 +1,18 @@
// Define initial state
import {StateInterface} from './reducers';
export const initialState: StateInterface = {
app: {
backendAPIRoot: "",
demoMode: true, // selon l'environnement
},
currentLang: "fr_FR",
currentTheme: "light",
langsList: ["fr_FR", "en_US"],
themesList: ["light", "dark"],
user: {
isAuthenticated: false,
id: "",
},
};

View file

@ -0,0 +1,172 @@
import {isDevMode} from '@angular/core';
import {ActionReducerMap, MetaReducer} from '@ngrx/store';
import {initialState} from '../initialState';
// Define action types
export enum ActionTypes {
UPDATE_USER = '[User] Update User',
UPDATE_APP = '[App] Update App',
UPDATE_CONVERSATIONS_LIST = '[Conversations] Update Conversations List',
UPDATE_ACTIVE_CONVERSATION = '[Conversations] Update Active Conversation',
POST_MESSAGE_TO_ACTIVE_CONVERSATION = '[Conversations] Post message to Active Conversation',
UPDATE_LAST_SEEN_MESSAGE = '[Conversations] Update Last Seen Message',
TOGGLE_CONVERSATIONS_LIST_PANEL = '[App] displayConversationListPanelLarge',
UPDATE_SINGLE_CONVERSATION = '[Conversations] Update Single Conversation',
SEND_USER_FEEDBACK = '[App] Send User Feedback',
SWITCH_TO_NEXT_THEME = '[App] Switch To Next Theme',
SWITCH_TO_NEXT_LANGUAGE = '[App] Switch To Next Language'
}
// Define action interfaces
export interface UpdateUserAction {
type: ActionTypes.UPDATE_USER;
payload: {
isAuthenticated: boolean;
id: string;
};
}
export interface UpdateAppAction {
type: ActionTypes.UPDATE_APP;
payload: {
backendAPIRoot?: string;
displayConversationListPanelLarge?: boolean;
displayFeedBackPanel?: boolean;
displayErrorResponse?: boolean;
displaySourcesPanelLarge?: boolean;
displayTour?: boolean;
displayWarningAIMaturing?: boolean;
feedBackInput?: string;
input?: string;
lang?: string;
notifications?: any[];
ollamaAvailable?: boolean;
searchInput?: string;
version?: string;
};
}
export interface SendUserFeedbackAction {
type: ActionTypes.SEND_USER_FEEDBACK;
payload: {
feedback: string;
};
}
export interface SwitchToNextThemeAction {
type: ActionTypes.SWITCH_TO_NEXT_THEME;
}
export interface SwitchToNextLanguageAction {
type: ActionTypes.SWITCH_TO_NEXT_LANGUAGE;
}
type Theme = 'light' | 'dark';
type Lang = 'fr_FR' | 'en_US';
export type AppActions =
| UpdateUserAction
| UpdateAppAction
| SendUserFeedbackAction
| SwitchToNextThemeAction
| SwitchToNextLanguageAction;
// Define the State interface
export interface StateInterface {
user: {
isAuthenticated: boolean;
id: string;
};
app: {
demoMode:boolean;
backendAPIRoot: string;
};
themesList: Array<Theme>;
currentTheme: Theme;
langsList: Array<Lang>;
currentLang: Lang;
}
// Define reducers
function userReducer(state = initialState.user, action: AppActions) {
switch (action.type) {
case ActionTypes.UPDATE_USER:
return {
...state,
...action.payload
};
default:
return state;
}
}
function appReducer(state = initialState.app, action: AppActions) {
switch (action.type) {
case ActionTypes.UPDATE_APP:
return {
...state,
...action.payload
};
default:
return state;
}
}
function themesListReducer(state = initialState.themesList, action: AppActions) {
switch (action.type) {
default:
return state;
}
}
function currentThemeReducer(state = initialState.currentTheme, action: AppActions) {
switch (action.type) {
case ActionTypes.SWITCH_TO_NEXT_THEME:
// Get the themesList from the store
const themesList = initialState.themesList;
// Find the index of the current theme
const currentThemeIndex = themesList.indexOf(state);
// Calculate the index of the next theme (or go back to the first theme if at the end)
const nextThemeIndex = (currentThemeIndex + 1) % themesList.length;
// Get the next theme
return themesList[nextThemeIndex];
default:
return state;
}
}
function langsListReducer(state = initialState.langsList, action: AppActions) {
switch (action.type) {
default:
return state;
}
}
function currentLangReducer(state = initialState.currentLang, action: AppActions) {
switch (action.type) {
case ActionTypes.SWITCH_TO_NEXT_LANGUAGE:
// Get the langsList from the store
const langsList = initialState.langsList;
// Find the index of the current language
const currentLangIndex = langsList.indexOf(state);
// Calculate the index of the next language (or go back to the first language if at the end)
const nextLangIndex = (currentLangIndex + 1) % langsList.length;
// Get the next language
return langsList[nextLangIndex];
default:
return state;
}
}
// Add reducers to ActionReducerMap
export const reducers: ActionReducerMap<StateInterface, AppActions> = {
user: userReducer,
app: appReducer,
themesList: themesListReducer,
currentTheme: currentThemeReducer,
langsList: langsListReducer,
currentLang: currentLangReducer
};
export const metaReducers: MetaReducer<StateInterface, AppActions>[] = isDevMode() ? [] : [];

View file

@ -1,13 +1,5 @@
// libs
@use 'remixicon/fonts/remixicon.scss';
@use 'bulma/sass/base/minireset.scss';
@use 'bulma/sass/grid/_index.scss';
@use 'bulma/sass/components/navbar.scss';
// dev tools
//@use '_app.scss';
@use '_global.scss';
@use '_debug.scss';
@use '_variables.scss';

View file

@ -2,4 +2,6 @@
// sass lang utils
@use "sass:color";
@use "app/styles/app.scss";
//@use "../../my-workspace/projects/sae-lib/app/styles/app.scss";
// lib SAE Aero styles
//@use 'sae-lib/src/styles/index.scss';
@use '../../my-workspace/projects/sae-lib/src/styles/index.scss';