add page to test api

This commit is contained in:
Tykayn 2025-10-01 16:58:05 +02:00 committed by tykayn
parent 6380dcc647
commit 55489a049a
10 changed files with 574 additions and 214 deletions

View file

@ -4,23 +4,22 @@
<div class="columns">
<div class="column">
Tester les actions de l'api
<br>
<app-main-button
<sae-m-button
(click)="login()" class="button" label='appel de login'>
</app-main-button>
</sae-m-button>
<br>
<app-main-button (click)="sendMessage()" class="button" label='envoi de message'>
<sae-m-button (click)="sendMessage()" class="button" label='envoi de message'>
</app-main-button>
</sae-m-button>
<br>
<app-main-button (click)="sendFeedback()" class="button" label='envoi de feedback'>
<sae-m-button (click)="sendFeedback()" class="button" label='envoi de feedback'>
</app-main-button>
</sae-m-button>
<br>
<app-main-button (click)="sendFile()" class="button" label='envoi de fichier'>
<sae-m-button (click)="sendFile()" class="button" label='envoi de fichier'>
</app-main-button>
</sae-m-button>
</div>
<div class="column">
<pre>

View file

@ -1,10 +1,11 @@
import {Component} from '@angular/core';
import {ApiService} from '../../services/api-service';
import {MainButton} from '../../buttons/main-button/main-button';
import {MainButton} from 'sae-lib/buttons/main-button/main-button';
@Component({
selector: 'app-testing-api',
imports: [
MainButton,
MainButton
],
templateUrl: './testing-api.html',

View file

@ -1,204 +1,208 @@
@use "sass:color";
@use "../../src/styles/variables.scss";
.feedback-button {
font-family: variables.$font-family;
background: #E3EAF1;
color: #005AA2;
border-radius: 8px 8px 0 0;
transform: rotate(270deg);
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
:host {
margin-right: -35px;
position: fixed;
right: 0;
top: 240px;
z-index: 100;
border: 0;
padding: 10px;
text-align: center;
font-size: 14px;
font-style: normal;
font-weight: 600;
line-height: 8px; /* 57.143% */
&:hover {
background: #d9e8f6;
}
i {
font-size: 16px;
}
// Modal styles
.feedback-modal-overlay {
position: fixed;
top: 92px;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.feedback-modal {
.feedback-button {
font-family: variables.$font-family;
background: #E3EAF1;
border-radius: 8px;
width: 90%;
max-width: 500px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
color: #005AA2;
border-radius: 8px 8px 0 0;
transform: rotate(270deg);
cursor: pointer;
display: flex;
flex-direction: column;
max-height: 90vh;
overflow: hidden;
}
.modal-header {
background: transparent;
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 20px;
border-bottom: 1px solid #eee;
gap: 8px;
h3 {
margin: 0;
font-size: 18px;
font-weight: 600;
color: #083b7d;
}
.close-button {
background: none;
border: none;
cursor: pointer;
font-size: 20px;
color: #666;
padding: 4px;
&:hover {
color: #333;
}
}
}
.modal-body {
margin-right: -35px;
position: fixed;
right: 0;
top: 240px;
z-index: 100;
border: 0;
padding: 20px;
overflow-y: auto;
background: transparent;
text-align: center;
.modal-description {
margin-bottom: 16px;
color: #555;
font-size: 14px;
font-style: normal;
font-weight: 600;
line-height: 8px; /* 57.143% */
&:hover {
background: #d9e8f6;
}
textarea {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 4px;
resize: vertical;
font-family: inherit;
font-size: 14px;
&:focus {
outline: none;
border-color: #083b7d;
}
&:disabled {
background-color: #f5f5f5;
cursor: not-allowed;
}
i {
font-size: 16px;
}
.success-message, .error-message {
margin-top: 16px;
padding: 10px;
border-radius: 4px;
// Modal styles
.feedback-modal-overlay {
position: fixed;
top: 92px;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
z-index: 1000;
}
i {
.feedback-modal {
background: #E3EAF1;
border-radius: 8px;
width: 90vw;
max-width: 500px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
display: flex;
flex-direction: column;
max-height: 90vh;
overflow: hidden;
}
.modal-header {
background: transparent;
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 20px;
border-bottom: 1px solid #eee;
h3 {
margin: 0;
font-size: 18px;
font-weight: 600;
color: #083b7d;
}
.close-button {
background: none;
border: none;
cursor: pointer;
font-size: 20px;
color: #666;
padding: 4px;
&:hover {
color: #333;
}
}
}
.success-message {
background-color: #e6f7e6;
color: #2e7d32;
}
.modal-body {
padding: 20px;
overflow-y: auto;
background: transparent;
.error-message {
background-color: #fdecea;
color: #d32f2f;
}
}
.modal-description {
margin-bottom: 16px;
color: #555;
}
.modal-footer {
padding: 16px 20px;
border-top: 1px solid #eee;
display: flex;
justify-content: flex-end;
gap: 12px;
textarea {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 4px;
resize: vertical;
font-family: inherit;
font-size: 14px;
button {
padding: 8px 16px;
border-radius: 4px;
font-weight: 500;
cursor: pointer;
&:focus {
outline: none;
border-color: #083b7d;
}
&:disabled {
opacity: 0.6;
cursor: not-allowed;
&:disabled {
background-color: #f5f5f5;
cursor: not-allowed;
}
}
.success-message, .error-message {
margin-top: 16px;
padding: 10px;
border-radius: 4px;
display: flex;
align-items: center;
gap: 8px;
i {
font-size: 18px;
}
}
.success-message {
background-color: #e6f7e6;
color: #2e7d32;
}
.error-message {
background-color: #fdecea;
color: #d32f2f;
}
}
.cancel-button {
background: none;
border: 1px solid #ddd;
color: #555;
&:hover:not(:disabled) {
background-color: #f5f5f5;
}
}
.submit-button {
background-color: #083b7d;
color: white;
border: none;
.modal-footer {
padding: 16px 20px;
border-top: 1px solid #eee;
display: flex;
align-items: center;
gap: 8px;
justify-content: flex-end;
gap: 12px;
&:hover:not(:disabled) {
background-color: #062c5e;
button {
padding: 8px 16px;
border-radius: 4px;
font-weight: 500;
cursor: pointer;
&:disabled {
opacity: 0.6;
cursor: not-allowed;
}
}
.cancel-button {
background: none;
border: 1px solid #ddd;
color: #555;
&:hover:not(:disabled) {
background-color: #f5f5f5;
}
}
.submit-button {
background-color: #083b7d;
color: white;
border: none;
display: flex;
align-items: center;
gap: 8px;
&:hover:not(:disabled) {
background-color: #062c5e;
}
}
}
}
// Spinner animation
.spinning {
animation: spin 1s linear infinite;
}
// Spinner animation
.spinning {
animation: spin 1s linear infinite;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
}
}

View file

@ -3,6 +3,7 @@ import {Main} from './pages/main/main';
import {Admin} from './pages/admin/admin';
import {SimilarCases} from './pages/similar-cases/similar-cases';
import {Login} from './pages/login/login';
import {TestingApi} from './pages/testing-api/testing-api';
export const routes: Routes = [{
path: '',
@ -28,6 +29,11 @@ export const routes: Routes = [{
path: 'login/home',
component: Main
},
{
path: 'api-testing',
component: TestingApi,
},
{
path: 'similar-cases',
component: SimilarCases

View file

@ -0,0 +1,111 @@
<div id="testingApiLand">
<h1>Test d'api CSC</h1>
<div class="columns">
<div class="column">
Tester les actions de l'api
<section>
<h2>
Login
</h2>
<sae-m-button
(click)="login()"
[kind]="'primary'" class="button" label='appel de login'>
</sae-m-button>
</section>
<section>
<br>
<h2>
Post /api/v1/messages
</h2>
entrez votre message:
<input [(ngModel)]="input" type="text">
<br>
<sae-m-button
(click)="sendMessage()"
[kind]="'primary'"
[label]="'Envoyer un message'" class="button" label='envoi de message'>
</sae-m-button>
<sae-bot-talks [message]="message">
</sae-bot-talks>
</section>
<br>
</div>
<div class="column">
<h2>Réponse</h2>
<pre>
{{ response }}
</pre>
<hr>
<section>
<h2>
Feedback
</h2>
conversationID:
<input [(ngModel)]="conversationID" type="text">
<sae-m-button
(click)="sendFeedback()"
[kind]="'secondary'" class="button"
label='envoi de feedback'>
</sae-m-button>
</section>
<section>
<h2>Envoi de fichier</h2>
<!-- <br>-->
<sae-m-button
(click)="sendFile()"
class="button" kind="secondary"
label='envoi de fichier'>
</sae-m-button>
</section>
<section>
<h2>Suppression</h2>
Delete /api/v1/conversations/{conversationID}
<sae-m-button
(click)="deleteConversation()"
class="button" kind="secondary"
label='suppression de conversation'>
</sae-m-button>
</section>
<section>
<h2>Get last answer </h2>
Get /api/v1/conversations/{conversationID}/last-answer
<sae-m-button
(click)="getLastAnswer()"
class="button" kind="secondary"
label='get last answer'>
</sae-m-button>
</section>
<section>
<h2>Get history</h2>
<sae-m-button
(click)="getHistory()"
class="button" kind="secondary"
label='get history'>
</sae-m-button>
</section>
<section>
<h2>Get user conversations</h2>
<sae-m-button
(click)="getUserConversations()"
class="button" kind="secondary"
label='get user conversations'>
</sae-m-button>
</section>
</div>
</div>
</div>

View file

@ -0,0 +1,28 @@
:host {
#testingApiLand {
padding: 4rem;
background: #f3fbff;
min-height: 100vh;
}
h2 {
margin-bottom: 2rem;
}
input {
padding: 1.5rem;
border: solid 1px grey;
border-radius: 0.5rem;
display: block;
margin: 0.5rem;
}
pre {
background: #cad5dd;
}
section {
border: 1px solid #ccc;
padding: 1rem;
}
}

View file

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

View file

@ -0,0 +1,118 @@
import {Component} from '@angular/core';
import {MainButton} from 'sae-lib/buttons/main-button/main-button';
import {FormsModule} from '@angular/forms';
import {BotTalks} from 'sae-lib/chatbot/bot-talks/bot-talks';
let defaultHeaders = {
'Access-Control-Allow-Headers': 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token',
'Access-Control-Allow-Methods': 'OPTIONS,POST',
'Access-Control-Allow-Origin': '*'
};
@Component({
selector: 'app-testing-api',
imports: [
MainButton,
FormsModule,
BotTalks
],
templateUrl: './testing-api.html',
styleUrl: './testing-api.scss'
})
export class TestingApi {
protected response: string = "(pas de réponse pour le moment)";
protected backend: string = "localhost";
protected input: string = "bonjour le backend";
protected message: string = "salut, ici le backend";
protected conversationID: string = "1234";
constructor() {
}
login() {
fetch(`http://${this.backend}/login`, {})
.then(response => response.json())
.then(data => {
console.log(data);
this.response = JSON.stringify(data);
}
)
.catch(error => console.error('Error:', error));
}
sendMessage() {
const dataBody = JSON.stringify({
question: "What are the main causes of engine failures in Boeing 737?",
conversationId: "uuid-optional",
databases: [
"Incident Reports", "Academic Papers",
"General Reports", "Patent Files",
"Press Articles", "Safety Directives"
],
search_engines: [
"Google Search", "Google Patents", "Google Scholar"
],
qualification_tag: "auto"
// / "specific_question" / "structured_list" / "conv_continuation"
})
fetch(`http://${this.backend}/api/v1/messages`, {
method: "POST",
mode: "cors",
body: dataBody,
headers: defaultHeaders
})
.then(response => response.json())
.then(data => {
console.log(data);
this.response = JSON.stringify(data);
}
)
.catch(error => console.error('Error:', error));
}
sendFeedback() {
const dataBody = JSON.stringify({
feedback: "This response was very helpful and accurate"
})
fetch(`http://${this.backend}/api/v1/${this.conversationID}/feedback`, {
method: "POST",
mode: "cors",
body: dataBody
})
.then(response => response.json())
.then(data => {
console.log(data);
this.response = JSON.stringify(data);
}
)
.catch(error => console.error('Error:', error));
}
sendFile() {
console.log('sendFile TODO')
}
deleteConversation() {
console.log('sendFile TODO')
}
getLastAnswer() {
console.log('getLastAnswer TODO')
}
getHistory() {
console.log('getHistory TODO')
}
getUserConversations() {
console.log('getUserConversations TODO')
}
}

View file

@ -3,7 +3,7 @@ import {StateInterface} from './reducers';
import {filtersCSC} from './filters';
export const initialState: StateInterface = {
const initialState: StateInterface = {
app: {
backendAPIRoot: "",
demoMode: true,
@ -23,58 +23,114 @@ export const initialState: StateInterface = {
}],
filters: {
engineType: {
availableList: [],
availableList: [
{
label: 'LEAP-1A',
value: 'LEAP-1A',
},
{
label: 'LEAP-1B',
value: 'LEAP-1B',
},
{
label: 'LEAP-1C',
value: 'LEAP-1C',
},
{
label: 'CFM56-5A',
value: 'CFM56-5A',
},
{
label: 'CFM56-5B',
value: 'CFM56-5B',
},
{
label: 'CFM56-5C',
value: 'CFM56-5C',
},
{
label: 'CFM56-2',
value: 'CFM56-2',
},
{
label: 'CFM56-3',
value: 'CFM56-3',
},
],
selectedList: [
{
label: 'DEF',
value: 'DEF',
}, {
label: 'GER',
value: 'GER',
}, {
label: '134D',
value: '134D',
},
label: 'demo',
value: 'demo',
}
]
},
findings: {
// filtersCSC.findings
availableList:
filtersCSC.findings
// [
// {
// label: 'FRETTING : Usure induite par petit debat',
// value: 'FRETTING',
// },
// {
// label: 'DENT : Impact a bord arrondi',
// value: 'DENT',
// }, {
// label: 'MISSING PAINT/COATING',
// value: 'MISSING_PAINT_COATING',
// }]
filtersCSC.findings
,
selectedList: []
},
ata: {
availableList: [{
label: 'DEF',
value: 'DEF',
}],
availableList: [
{
label: '72-00-00',
value: '72-00-00',
}, {
label: '72-21-02',
value: '72-21-02',
}, {
label: '72-52-46',
value: '72-52-46',
},
],
selectedList: []
},
partNumber: {
availableList: [{
label: 'DEF',
value: 'DEF',
}],
availableList: [
{
label: '362-074-103-0',
value: '362-074-103-0',
}, {
label: '362-040-010-0',
value: '362-040-010-0',
}, {
label: '91C28501',
value: '91C28501',
}, {
label: '91C00302',
value: '91C00302',
},
],
selectedList: []
},
technicalManual: {
availableList: [{
label: 'DEF',
value: 'DEF',
label: 'ESM',
value: 'ESM',
}, {
label: 'AMM',
value: 'AMM',
}, {
label: 'TSM',
value: 'TSM',
}, {
label: 'SB',
value: 'SB',
}, {
label: 'CMM',
value: 'CMM',
}, {
label: 'IPC',
value: 'IPC',
}, {
label: 'RD',
value: 'RD',
}, {
label: 'SPM',
value: 'SPM',
}],
selectedList: [{
label: 'DEF',
@ -82,7 +138,19 @@ export const initialState: StateInterface = {
}]
},
onOffWing: {
availableList: [],
availableList: [{
label: 'On Wing',
value: 'On-wing',
},
{
label: 'Off Wing',
value: 'Off-wing',
},
{
label: 'All',
value: 'All',
}
],
selectedList: []
}
},
@ -443,3 +511,4 @@ export const initialState: StateInterface = {
login: "Borhème",
},
};
export default initialState

View file

@ -1,6 +1,6 @@
import {isDevMode} from '@angular/core';
import {ActionReducerMap, MetaReducer} from '@ngrx/store';
import {initialState} from '../initialState';
import initialState from '../initialState';
// Define action types
export enum ActionTypes {
@ -27,6 +27,7 @@ export interface UpdateUserAction {
id: string;
};
}
export interface UpdateFilterAction {
type: ActionTypes.UPDATE_FILTER;
payload: {
@ -171,7 +172,7 @@ function appReducer(state = initialState.app, action: AppActions) {
...action.payload
};
case ActionTypes.UPDATE_FILTER: {
const { filter, choice } = (action as UpdateFilterAction).payload;
const {filter, choice} = (action as UpdateFilterAction).payload;
const filterGroup = state.filters[filter as keyof typeof state.filters];
if (!filterGroup) {
return state;