rajah 11 месяцев назад
Родитель
Сommit
4d59c32711

+ 2 - 2
src/app/composants/categorie-list/categorie-list.component.ts

@@ -18,9 +18,9 @@ export class CategorieListComponent implements OnInit
 
   private retreiveDatas() { this.categorieService.getListCategorie().subscribe(data => { this.categories = data; }); }
 
-  goToRefreshListCategorie(){ this.retreiveDatas(); }
+  goToRefreshListCategorie() { this.retreiveDatas(); }
 
-  goToNewCategorie(){ this.router.navigate(['/categorie-create']); }
+  goToNewCategorie() { this.router.navigate(['/categorie-create']); }
 
   formCategorie(id: number) { this.router.navigate(['/categorie-details', id]); }
 

+ 1 - 1
src/app/composants/production-create/production-create.component.html

@@ -65,7 +65,7 @@
 				<label class="col-sm-4 col-form-label col-form-label-sm label-nobr"><span i18n>Gestionnaire</span>&nbsp;<sup><span class="text-danger">*</span></sup></label>
 				<div class="col-sm-8">
 					<div class="form-group">
-						<select class="form-select form-select-sm field-separate" id="numeroParticipant" name="numeroParticipant" [(ngModel)]="production.numeroParticipant">
+						<select class="form-select form-select-sm field-separate" id="numeroParticipant" name="numeroParticipant" [(ngModel)]="production.numeroParticipant" required>
 				    @for (participant of participants; track participant.numeroParticipant) {
 							<option [ngValue]="participant.numeroParticipant">{{ participant.pseudonyme }} = {{ participant.nom }}&nbsp;{{ participant.prenom }}</option>
 				    }

+ 12 - 4
src/app/composants/production-create/production-create.component.ts

@@ -1,11 +1,13 @@
 import { Component, OnInit, ViewChild } from '@angular/core';
+import { Router } from '@angular/router';
+import { FormsModule, NgForm } from '@angular/forms';
+
 import { MenuComponent } from '../menu/menu.component';
 import { Production, ProductionEnum, ProductionTypeList } from '../../interfaces/production';
 import { ProductionService } from '../../services/production.service';
 import { ParticipantShort } from '../../interfaces/participant';
 import { ParticipantService } from '../../services/participant.service';
-import { Router } from '@angular/router';
-import { FormsModule, NgForm } from '@angular/forms';
+import { AccountService } from '../../services/account.service'
 
 @Component({ selector: 'app-production-create', imports: [FormsModule, MenuComponent], templateUrl: './production-create.component.html', styleUrl: './production-create.component.css' })
 
@@ -20,9 +22,15 @@ export class ProductionCreateComponent implements OnInit
 
   production: Production = new Production();
 
-  constructor(private productionService: ProductionService, private participantService: ParticipantService, private router: Router, private menu: MenuComponent) { }
+  constructor(
+    private accountService : AccountService,
+    private productionService: ProductionService,
+    private participantService: ParticipantService,
+    private router: Router,
+    private menu: MenuComponent
+  ) { }
 
-  ngOnInit() { this.retreiveParticipants(); }
+  ngOnInit() { this.retreiveParticipants(); this.production.numeroParticipant = this.accountService.getNumeroParticipant(); }
 
   private retreiveParticipants() { this.participantService.getOptionListParticipant().subscribe(data => { this.participants = data; }); }
 

+ 10 - 1
src/app/composants/production-list/production-list.component.html

@@ -8,6 +8,15 @@
 				<button type="button" (click)="goToRefreshListProduction()" class="btn bg-gradient btn-primary btn-sm" style="margin-right: 5px;"><i class="fa-solid fa-rotate"></i>&nbsp;<span i18n>Actualiser</span></button>
 				<button type="button" (click)="goToNewProduction()" class="btn bg-gradient btn-primary btn-sm" style="margin-right: 5px;"><i class="fa-solid fa-plus"></i>&nbsp;<span i18n>Créer</span></button>
 			</div>
+			<div class="form-group col-sm-2 label-nobr ms-auto">
+				<div class="input-group input-group-sn">
+					<button type="button" class="btn bg-gradient btn-secondary btn-sm field-separate" disabled><span i18n>Afficher</span></button>
+					<select class="form-select form-select-sm field-separate" id="select_solo" [(ngModel)]="soloFiltre" (change)="filtrageParSolo($event)">
+						<option value="0">Toutes</option>
+						<option value="1">Celles non rattachées aux catégories</option>
+					</select>
+				</div>
+			</div>
 			<div class="form-group col-sm-2 label-nobr">
 				<div class="input-group input-group-sn">
 					<button type="button" class="btn bg-gradient btn-secondary btn-sm field-separate" disabled><span i18n>Filtrer par type</span></button>
@@ -30,7 +39,7 @@
   			<span class="card-title">@if (production.type === types[0].key) { <i class="fa-solid fa-square-binary"></i> } @else if (production.type === types[1].key) { <i class="fa-solid fa-image"></i> } @else if (production.type === types[2].key) { <i class="fa-solid fa-music"></i> } @else if (production.type === types[3].key) { <i class="fa-solid fa-video"></i> } @else if (production.type === types[4].key) { <i class="fa-solid fa-comment"></i> } @else { <i class="fa-solid fa-question"></i> }
 	  		<a (click)="formProduction(production.numeroProduction)" class="text-primary pointeur-souris" style="margin-left:7px;">{{ production.titre }}</a></span><br/>
 				<small><span class="text-muted">par</span> {{ production.auteurs }} @if (production.groupes) { @if (production.groupes.length > 0) { &nbsp;/&nbsp;{{ production.groupes }} } }</small>
-			</div>
+		  </div>
 			<div class="card-body">
 			  <small><span class="text-muted">sur</span> {{ production.plateforme }}</small><br/>
 			 	<small>{{ production.commentaire }}</small><br/>

+ 3 - 1
src/app/composants/production-list/production-list.component.ts

@@ -16,14 +16,16 @@ export class ProductionListComponent implements OnInit
 
   types: ProductionEnum[] = ProductionTypeList;
   typeFiltre: string = "";
+  soloFiltre: number = 0;
 
   constructor(private productionService: ProductionService, private router: Router) { }
 
   ngOnInit() { this.retreiveDatas(); }
 
-  private retreiveDatas() { this.productionService.getListProduction(this.typeFiltre).subscribe(data => { this.productions = data; }); }
+  private retreiveDatas() { this.productionService.getListProduction(this.typeFiltre, this.soloFiltre).subscribe(data => { this.productions = data; }); }
 
   filtrageParType(event: any) { this.typeFiltre = event.target.value; this.goToRefreshListProduction(); }
+  filtrageParSolo(event: any) { this.soloFiltre = event.target.value; this.goToRefreshListProduction(); }
 
   goToRefreshListProduction(){ this.retreiveDatas(); }
 

+ 13 - 7
src/app/composants/show-links/show-links.component.html

@@ -2,16 +2,22 @@
 <div id="main">
 <div class="card shadow center">
 
-  <div class="card-header"><span i18n>Productions liées à la catégorie {{ categorie.libelle }}</span></div>
-	<div class="card-header shadow-sm">
+  <div class="card-header">
+    <span i18n>Rattacher des productions dans une catégorie</span>
+  </div>
+  <div class="card-header shadow-sm">
 		<button (click)="goToListPresentations()" class="btn bg-gradient btn-primary btn-sm"><i class="fa-solid fa-xmark"></i>&nbsp;<span i18n>Retour</span></button>
 	</div>
+  <div class="card-body hstack">
+    <div><small><span i18n>Dans {{ categorie.libelle }}</span></small></div>
+    <div class="ms-auto"><small><span i18n>Sans catégorie</span></small></div>
+  </div>
 	<div class="card-body"><div class="row align-items-start">
 
     <div class="col">
-      <select class="form-select-sm" multiple id="selectionLinked" (change)="changeEtatBoutonsLinked($event)">
-      @for (prod of linkedProductions; track prod.numeroProduction) {
-        <option [value]="prod.numeroProduction"> {{ prod.titre }}</option>
+      <select class="form-select-sm" size="16" id="selectionLinked" (change)="changeEtatBoutonsLinked($event)">
+      {{ resetLettre() }} @for (prod of linkedProductions; track prod.numeroProduction) { 
+        <option [value]="prod.numeroProduction">{{ nextLettre() }} - {{ prod.titre }} - {{ prod.auteurs }} / {{ prod.groupes }}</option>
       }
       </select>
     </div>
@@ -28,9 +34,9 @@
     </div>
 
     <div class="col">
-      <select class="form-select-sm" multiple id="selectionUnlinked" (change)="changeEtatBoutonsUnlinked($event)">
+      <select class="form-select-sm" size="16" id="selectionUnlinked" (change)="changeEtatBoutonsUnlinked($event)">
       @for (prod of unlinkedProductions; track prod.numeroProduction) {
-        <option [value]="prod.numeroProduction"> {{ prod.titre }}</option>
+        <option [value]="prod.numeroProduction"> {{ prod.titre }} - {{ prod.auteurs }} / {{ prod.groupes }}</option>
       }
       </select>
     </div>

+ 20 - 2
src/app/composants/show-links/show-links.component.ts

@@ -41,6 +41,8 @@ export class ShowLinksComponent implements OnInit
     this.categorieService.getByIdCategorie(this.numeroCategorie).subscribe( data => { this.categorie = data; });
 
     this.retreiveDatas();
+    this.resetEtatBoutonsUnlinked();
+    this.resetEtatBoutonsLinked();
   }
 
   private retreiveDatas()
@@ -49,6 +51,12 @@ export class ShowLinksComponent implements OnInit
     this.presentationService.getUnlinkedProductions().subscribe(data => { this.unlinkedProductions = data; });
   }
 
+  lettresOrdre: string[] = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
+  indexLettre: number = 0;
+
+  resetLettre() { this.indexLettre = 0; }
+  nextLettre(): string { if ((this.indexLettre >= 0) && (this.indexLettre < 26)) { this.indexLettre++; return "#" + this.lettresOrdre[this.indexLettre - 1];  } return ""; }
+
   goToListPresentations() { this.router.navigate(['/show-list'], { queryParams: { 'refresh': this.menu.getRandomInteger(1, 100000) } }); }
 
   changeEtatBoutonsUnlinked(event: any)
@@ -59,6 +67,10 @@ export class ShowLinksComponent implements OnInit
 
     if (this.boutonLier) { if (b) { this.renderer.removeClass(this.boutonLier.nativeElement, 'disabled'); } else { this.renderer.addClass(this.boutonLier.nativeElement, 'disabled'); } }
   }
+  resetEtatBoutonsUnlinked()
+  {
+    if (this.boutonLier) { this.renderer.addClass(this.boutonLier.nativeElement, 'disabled'); }
+  }
 
   changeEtatBoutonsLinked(event: any)
   {
@@ -70,10 +82,16 @@ export class ShowLinksComponent implements OnInit
     if (this.boutonAvancer) { if (b) { this.renderer.removeClass(this.boutonAvancer.nativeElement, 'disabled'); } else { this.renderer.addClass(this.boutonAvancer.nativeElement, 'disabled'); } }
     if (this.boutonReculer) { if (b) { this.renderer.removeClass(this.boutonReculer.nativeElement, 'disabled'); } else { this.renderer.addClass(this.boutonReculer.nativeElement, 'disabled'); } }
   }
+  resetEtatBoutonsLinked()
+  {
+    if (this.boutonRetirer) { this.renderer.addClass(this.boutonRetirer.nativeElement, 'disabled'); }
+    if (this.boutonAvancer) { this.renderer.addClass(this.boutonAvancer.nativeElement, 'disabled'); }
+    if (this.boutonReculer) { this.renderer.addClass(this.boutonReculer.nativeElement, 'disabled'); }
+  }
 
-  lierProduction() { if (this.numeroProduction > 0) { this.presentationService.lierProduction(this.numeroCategorie, this.numeroProduction).subscribe(() => { this.retreiveDatas(); }); } }
+  lierProduction() { if (this.numeroProduction > 0) { this.presentationService.lierProduction(this.numeroCategorie, this.numeroProduction).subscribe(() => { this.retreiveDatas(); this.resetEtatBoutonsUnlinked(); }); } }
 
-  retirerProduction() { if (this.numeroProduction < 0) { this.presentationService.retirerProduction(this.numeroCategorie, this.numeroProduction).subscribe(() => { this.retreiveDatas(); }); } }
+  retirerProduction() { if (this.numeroProduction < 0) { this.presentationService.retirerProduction(this.numeroCategorie, this.numeroProduction).subscribe(() => { this.retreiveDatas(); this.resetEtatBoutonsLinked(); }); } }
 
   avancerProduction() { if (this.numeroProduction < 0) { this.presentationService.avancerProduction(this.numeroCategorie, this.numeroProduction).subscribe(() => { this.retreiveDatas(); }); } }
 

+ 7 - 8
src/app/composants/show-list/show-list.component.html

@@ -12,23 +12,22 @@
 </div>
 
 @for (categorie of categories; track categorie.numeroCategorie) { @if (categorie.available) {
-<div class="card shadow overflow-x-auto" style="height:22rem;">
+<div class="card shadow">
   <div class="card-header">
     {{ categorie.libelle }}&nbsp;&nbsp;&nbsp;&nbsp;
-    <button type="button" (click)="lierProductions(categorie.numeroCategorie)" class="btn bg-gradient btn-primary btn-sm" style="margin-right: 5px;" i18n-tootip tooltip="Rattacher des productions et les ordonner" placement="right" container="body"><i class="fa-solid fa-link"></i>&nbsp;<span i18n>Affilier</span></button>
+    <button type="button" (click)="lierProductions(categorie.numeroCategorie)" class="btn bg-gradient btn-primary btn-sm" style="margin-right: 5px;" i18n-tootip tooltip="Rattacher des productions à cette catégorie et les ordonner" placement="right" container="body"><i class="fa-solid fa-link"></i>&nbsp;<span i18n>Rattacher</span></button>
     @if (categorie.uploadable) { }
     @if (categorie.pollable) { }
     @if (categorie.computed) { }
     @if (categorie.displayable) { }
   </div>
-  <div class="card-body">
-@for (production of productions; track production.numeroProduction) { @if (categorie.numeroCategorie == production.numeroCategorie) {
-    <div class="card shadow" style="max-height:20rem;">
+  <div class="card-body hstack align-items-baseline" style="height:30rem;overflow-x:auto;">
+{{ resetLettre() }} @for (production of productions; track production.numeroProduction) { @if (categorie.numeroCategorie == production.numeroCategorie) {
+    <div class="card shadow" style="min-width:10rem;max-width:17rem;">
       <img src="{{ production.vignette }}" class="img-fluid card-img-top pointeur-souris" (click)="formProduction(production.numeroProduction)">
       <div class="card-header">
-        <span class="card-title">@if (production.type === types[0].key) { <i class="fa-solid fa-square-binary"></i> } @else if (production.type === types[1].key) { <i class="fa-solid fa-image"></i> } @else if (production.type === types[2].key) { <i class="fa-solid fa-music"></i> } @else if (production.type === types[3].key) { <i class="fa-solid fa-video"></i> } @else if (production.type === types[4].key) { <i class="fa-solid fa-comment"></i> } @else { <i class="fa-solid fa-question"></i> }
-          <a (click)="formProduction(production.numeroProduction)" class="text-primary pointeur-souris" style="margin-left:7px;">{{ production.titre }}</a></span><br/>
-          <small><span class="text-muted">par</span> {{ production.auteurs }} @if (production.groupes) { @if (production.groupes.length > 0) { &nbsp;/&nbsp;{{ production.groupes }} } }</small>
+        <span class="card-title">{{ nextLettre() }} -<a (click)="formProduction(production.numeroProduction)" class="text-primary pointeur-souris" style="margin-left:7px;">{{ production.titre }}</a></span><br/>
+        <small><span class="text-muted">par</span> {{ production.auteurs }} @if (production.groupes) { @if (production.groupes.length > 0) { &nbsp;/&nbsp;{{ production.groupes }} } }</small>
       </div>
       <div class="card-body">
         <small><span class="text-muted">sur</span> {{ production.plateforme }}</small><br/>

+ 14 - 2
src/app/composants/show-list/show-list.component.ts

@@ -9,6 +9,7 @@ import { Categorie } from '../../interfaces/categorie';
 import { CategorieService } from '../../services/categorie.service';
 
 import { ProductionShort, ProductionEnum, ProductionTypeList } from '../../interfaces/production';
+import { PresentationService } from '../../services/presentation.service';
 import { ProductionService } from '../../services/production.service';
 
 @Component({ selector: 'app-show-list', imports: [FormsModule, TooltipModule, MenuComponent], templateUrl: './show-list.component.html', styleUrl: './show-list.component.css' })
@@ -21,16 +22,27 @@ export class ShowListComponent implements OnInit
   types: ProductionEnum[] = ProductionTypeList;
   productions: ProductionShort[] = [];
 
-  constructor(private categorieService: CategorieService, private productionService: ProductionService, private router: Router) { }
+  constructor(
+    private categorieService: CategorieService,
+    private presentationService: PresentationService,
+    private productionService: ProductionService,
+    private router: Router
+  ) { }
 
   ngOnInit() { this.retreiveDatas(); }
 
   private retreiveDatas()
   {
     this.categorieService.getListCategorie().subscribe(data => { this.categories = data; });
-    this.productionService.getListProduction('').subscribe(data => { this.productions = data; });
+    this.presentationService.getListProduction().subscribe(data => { this.productions = data; });
   }
 
+  lettresOrdre: string[] = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
+  indexLettre: number = 0;
+
+  resetLettre() { this.indexLettre = 0; }
+  nextLettre(): string { if ((this.indexLettre >= 0) && (this.indexLettre < 26)) { this.indexLettre++; return "#" + this.lettresOrdre[this.indexLettre - 1];  } return ""; }
+
   goToRefreshListCategorie(){ this.retreiveDatas(); }
 
   formProduction(id: number) { this.router.navigate(['/production-details', id]); }

+ 1 - 0
src/app/interfaces/user.ts

@@ -1,6 +1,7 @@
 
 export class User
 {
+  numeroParticipant: number = 0;
   username: string = "";
   password: string = "";
   nom: string = "";

+ 7 - 6
src/app/services/account.service.ts

@@ -30,12 +30,13 @@ export class AccountService
     this.user = this.userSubject.asObservable();
   }
 
-  public isLogged() { if (this.userSubject.value) { return true; } return false; }
-  public getUsername() { if (this.userSubject.value) { return this.userSubject.value.username; } return ""; }
-  public getRole() { if (this.userSubject.value) { return this.userSubject.value.role; } return ""; }
-  public getDelaiAvantDeconnexion() { if (this.userSubject.value) { return this.userSubject.value.delaiAvantDeconnexion; } return 15; }
-  public getAccessToken() { if (this.userSubject.value) { return this.userSubject.value.accessToken; } return ""; }
-  private getRefreshToken() { if (this.userSubject.value) { return this.userSubject.value.refreshToken; } return ""; }
+  public isLogged():boolean { if (this.userSubject.value) { return true; } return false; }
+  public getNumeroParticipant():number { if (this.userSubject.value) { return this.userSubject.value.numeroParticipant; } return 0; }
+  public getUsername():string { if (this.userSubject.value) { return this.userSubject.value.username; } return ""; }
+  public getRole():string { if (this.userSubject.value) { return this.userSubject.value.role; } return ""; }
+  public getDelaiAvantDeconnexion():number { if (this.userSubject.value) { return this.userSubject.value.delaiAvantDeconnexion; } return 15; }
+  public getAccessToken():string { if (this.userSubject.value) { return this.userSubject.value.accessToken; } return ""; }
+  private getRefreshToken():string { if (this.userSubject.value) { return this.userSubject.value.refreshToken; } return ""; }
 
   salute(): Observable<Journees>
   {

+ 10 - 5
src/app/services/presentation.service.ts

@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
 import { HttpClient, HttpParams } from '@angular/common/http'
 import { Observable } from 'rxjs';
 import { Environnement } from '../env';
-import { ProductionItem } from '../interfaces/production';
+import { ProductionShort, ProductionItem } from '../interfaces/production';
 
 @Injectable({ providedIn: 'root' })
 
@@ -13,6 +13,11 @@ export class PresentationService
 
   constructor(private httpClient: HttpClient) { }
 
+  getListProduction(): Observable<ProductionShort[]>
+  {
+    return this.httpClient.get<ProductionShort[]>(`${this.baseURL}/list-all`);
+  }
+
   getLinkedProductions(id: number): Observable<ProductionItem[]> { return this.httpClient.get<ProductionItem[]>(`${this.baseURL}/list-linked/${id}`); }
 
   getUnlinkedProductions(): Observable<ProductionItem[]> { return this.httpClient.get<ProductionItem[]>(`${this.baseURL}/list-unlinked`); }
@@ -24,7 +29,7 @@ export class PresentationService
     params = params.append('id_cat', id_cat);
     params = params.append('id_prod', id_prod);
 
-    return this.httpClient.put(`${this.baseURL}/add`, { params: params });
+    return this.httpClient.get(`${this.baseURL}/add`, { params: params });
   }
 
   retirerProduction(id_cat: number, id_prod: number): Observable<Object>
@@ -34,7 +39,7 @@ export class PresentationService
     params = params.append('id_cat', id_cat);
     params = params.append('id_prod', id_prod);
 
-    return this.httpClient.put(`${this.baseURL}/remove`, { params: params });
+    return this.httpClient.get(`${this.baseURL}/remove`, { params: params });
   }
 
   avancerProduction(id_cat: number, id_prod: number): Observable<Object>
@@ -44,7 +49,7 @@ export class PresentationService
     params = params.append('id_cat', id_cat);
     params = params.append('id_prod', id_prod);
 
-    return this.httpClient.put(`${this.baseURL}/forward`, { params: params });
+    return this.httpClient.get(`${this.baseURL}/up`, { params: params });
   }
 
   reculerProduction(id_cat: number, id_prod: number): Observable<Object>
@@ -54,7 +59,7 @@ export class PresentationService
     params = params.append('id_cat', id_cat);
     params = params.append('id_prod', id_prod);
 
-    return this.httpClient.put(`${this.baseURL}/backward`, { params: params });
+    return this.httpClient.get(`${this.baseURL}/down`, { params: params });
   }
 
 }

+ 2 - 1
src/app/services/production.service.ts

@@ -13,11 +13,12 @@ export class ProductionService
 
   constructor(private httpClient: HttpClient) { }
 
-  getListProduction(filtreType: string): Observable<ProductionShort[]>
+  getListProduction(filtreType: string, filtreSolo: number): Observable<ProductionShort[]>
   {
     let params = new HttpParams();
 
     if (filtreType !== null) { params = params.append('type', filtreType); }
+    if (filtreSolo == 1) { params = params.append('solo', filtreSolo); }
 
     return this.httpClient.get<ProductionShort[]>(`${this.baseURL}/list`, { params: params });
   }