From a6aefc5059f036568fddd80605baf845eeb7c80d Mon Sep 17 00:00:00 2001 From: Passam KASSEM <passam.kassem@focati-solutions.com> Date: Thu, 9 Sep 2021 16:43:16 +0200 Subject: [PATCH] [VAS] BUG 7428 : APP Recherche, le champ 'chemin' sur le panneau d'information d'une UA devrait reconstituer le chemin de l'UA --- .../modules/models/criteria/criteria.enums.ts | 44 +++++++++++ .../src/app/modules/models/index.ts | 1 + .../archive-preview.component.html | 70 ++++++++++------- .../archive-preview.component.scss | 23 ++++-- .../archive-preview.component.spec.ts | 1 + .../archive-preview.component.ts | 45 +++++------ .../src/app/archive/archive.service.ts | 75 ++++++++++++++++--- .../archive-search/src/assets/i18n/en.json | 3 +- .../archive-search/src/assets/i18n/fr.json | 3 +- 9 files changed, 194 insertions(+), 71 deletions(-) create mode 100644 ui/ui-frontend-common/src/app/modules/models/criteria/criteria.enums.ts diff --git a/ui/ui-frontend-common/src/app/modules/models/criteria/criteria.enums.ts b/ui/ui-frontend-common/src/app/modules/models/criteria/criteria.enums.ts new file mode 100644 index 000000000..b582b22e8 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/models/criteria/criteria.enums.ts @@ -0,0 +1,44 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +export enum CriteriaOperator { + EQ = 'EQ' +} + +export enum CriteriaDataType { + STRING = 'STRING' +} diff --git a/ui/ui-frontend-common/src/app/modules/models/index.ts b/ui/ui-frontend-common/src/app/modules/models/index.ts index a5ab1058f..b40db41df 100644 --- a/ui/ui-frontend-common/src/app/modules/models/index.ts +++ b/ui/ui-frontend-common/src/app/modules/models/index.ts @@ -39,6 +39,7 @@ export * from './app.configuration.interface'; export * from './content-disposition.enum'; export * from './criteria/criteria.interface'; export * from './criteria/criterion.interface'; +export * from './criteria/criteria.enums'; export * from './customer/index'; export * from './group/index'; export * from './id.interface'; diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.html b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.html index 01847fbc7..db1dc0e70 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.html +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.html @@ -1,22 +1,25 @@ <vitamui-common-sidenav-header - [title]="archiveUnit?.Title ? archiveUnit?.Title : archiveUnit.Title_.fr ? archiveUnit.Title_.fr : archiveUnit.Title_.en " - [icon]="(archiveUnit?.DescriptionLevel === 'File' || archiveUnit?.DescriptionLevel === 'Item' )? 'vitamui-icon-file': 'vitamui-icon-folder' " - (onclose)="emitClose()"> + [title]="archiveUnit?.Title ? archiveUnit?.Title : archiveUnit.Title_.fr ? archiveUnit.Title_.fr : archiveUnit.Title_.en" + [icon]=" + archiveUnit?.DescriptionLevel === 'File' || archiveUnit?.DescriptionLevel === 'Item' ? 'vitamui-icon-file' : 'vitamui-icon-folder' + " + (onclose)="emitClose()" +> </vitamui-common-sidenav-header> <div class="vitamui-sidepanel-body"> <mat-tab-group class="preview-tab-group"> - <mat-tab label="{{'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.TABS.INFORMATIONS' | translate}}"> + <mat-tab label="{{ 'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.TABS.INFORMATIONS' | translate }}"> <div class="row"> <div class="col-12"> <div class="read-only-field"> - <label>{{'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.NAME' | translate}} :</label> + <label>{{ 'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.NAME' | translate }} :</label> <div> - <ng-container *ngIf="archiveUnit?.Title ;else subTitleFr"> + <ng-container *ngIf="archiveUnit?.Title; else subTitleFr"> {{ archiveUnit?.Title }} </ng-container> <ng-template #subTitleFr> - <ng-container *ngIf="archiveUnit.Title_.fr ;else subTitleEn"> + <ng-container *ngIf="archiveUnit.Title_.fr; else subTitleEn"> {{ archiveUnit.Title_.fr }} </ng-container> </ng-template> @@ -32,9 +35,9 @@ <div class="row"> <div class="col-12"> <div class="read-only-field"> - <label>{{'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.GUID' | translate}} :</label> + <label>{{ 'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.GUID' | translate }} :</label> <div> - {{archiveUnit['#opi']}} + {{ archiveUnit['#opi'] }} </div> </div> </div> @@ -42,9 +45,9 @@ <div class="row"> <div class="col-12"> <div class="read-only-field"> - <label>{{'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.UAID' | translate}} :</label> + <label>{{ 'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.UAID' | translate }} :</label> <div> - {{archiveUnit['#id']}} + {{ archiveUnit['#id'] }} </div> </div> </div> @@ -52,10 +55,10 @@ <div class="row"> <div class="col-12"> <div class="read-only-field text-justify"> - <label>{{'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.DESCRIPTION' | translate}} :</label> + <label>{{ 'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.DESCRIPTION' | translate }} :</label> <div> <p class="text-justify"> - {{archiveUnit.Description}} + {{ archiveUnit.Description }} </p> </div> </div> @@ -65,30 +68,35 @@ <div class="row"> <div class="col-6"> <div class="read-only-field"> - <label>{{'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.SP' | translate}} :</label><br/> - <label>{{'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.SP_CODE' | translate}} :</label> + <label>{{ 'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.SP' | translate }} :</label><br /> + <label>{{ 'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.SP_CODE' | translate }} :</label> <div> - {{ archiveUnit['#originating_agencies']}} + {{ archiveUnit['#originating_agencies'] }} </div> </div> </div> <div class="col-6"> <div class="read-only-field"> - <label></label><br/> - <label>{{'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.SP_LABEL' | translate}} :</label> + <label></label><br /> + <label>{{ 'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.SP_LABEL' | translate }} :</label> <div> - {{ archiveUnit['originating_agencyName']}} + {{ archiveUnit['originating_agencyName'] }} </div> </div> </div> - </div> <div class="row"> <div class="col-6"> <div class="read-only-field"> - <label>{{'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.PATH' | translate}} :</label> + <label + >{{ 'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.PATH' | translate }} + <button class="ml-2 btn-show-full-path" type="button" (click)="showArchiveUniteFullPath()"> + {{ 'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.BTN_SHOW_COMPLETE_PATH' | translate }} + </button> + </label> <div> - {{archiveUnit.DescriptionLevel}} + <span *ngIf="!fullPath">{{ (uaPath$ | async)?.resumePath }}</span> + <span *ngIf="fullPath">{{ (uaPath$ | async)?.fullPath }}</span> </div> </div> </div> @@ -105,26 +113,30 @@ <div class="row"> <div class="col-6"> <div class="read-only-field"> - <label>{{'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.START_DATE' | translate}} :</label> + <label>{{ 'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.START_DATE' | translate }} :</label> <div> - {{archiveUnit?.StartDate | date: 'dd/MM/yyyy'}} + {{ archiveUnit?.StartDate | date: 'dd/MM/yyyy' }} </div> </div> </div> <div class="col-6"> <div class="read-only-field"> - <label>{{'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.END_DATE' | translate}} :</label> + <label>{{ 'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.END_DATE' | translate }} :</label> <div> - {{archiveUnit?.EndDate | date: 'dd/MM/yyyy'}} + {{ archiveUnit?.EndDate | date: 'dd/MM/yyyy' }} </div> </div> </div> <div class="row"> <div class="col-12"> - <button class="btn secondary download-btn" [disabled]="archiveUnit['#object'] == null" - (click)="onDownloadObjectFromUnit(archiveUnit)"> - <i class="vitamui-icon vitamui-icon-deposit"></i> <span>{{'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.DOWNLOAD_DOC' | translate}}</span> + <button + class="btn secondary download-btn" + [disabled]="archiveUnit['#object'] == null" + (click)="onDownloadObjectFromUnit(archiveUnit)" + > + <i class="vitamui-icon vitamui-icon-deposit"></i> + <span>{{ 'ARCHIVE_SEARCH.ARCHIVE_UNIT_PREVIEW.FIELDS.DOWNLOAD_DOC' | translate }}</span> </button> </div> </div> diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.scss b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.scss index 76cc1c61b..f2dbaf4ed 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.scss +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.scss @@ -1,9 +1,18 @@ +.download-btn { + border-radius: 100px; + color: white; + font-size: 14px; + font-weight: bold; + margin: 20px 20px 20px 120px; +} + +.btn-show-full-path { + border: 1px solid var(--vitamui-grey); + border-radius: 10px; + font-size: 10px; +} -.download-btn{ - border-radius: 100px; - color: white; - font-size: 14px; - font-weight: bold; - margin: 20px; - margin-left: 120px; +.btn-show-full-path:hover { + background-color: var(--vitamui-grey-400); + cursor: pointer; } diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.spec.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.spec.ts index 84f1052dc..88b26531a 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.spec.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.spec.ts @@ -70,6 +70,7 @@ describe('ArchivePreviewComponent', () => { const archiveServiceMock = { getBaseUrl: () => '/fake-api', + buildArchiveUnitPath: () => of({ resumePath: '', fullPath: '' }), }; TestBed.configureTestingModule({ diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.ts index 540ddd126..0a80f92c5 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.ts @@ -1,58 +1,61 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; - import { Unit } from '../models/unit.interface'; +import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; +import { Unit } from '../models/unit.interface'; import { HttpHeaders } from '@angular/common/http'; import { ArchiveService } from '../archive.service'; -import { StartupService } from 'ui-frontend-common'; import { ActivatedRoute } from '@angular/router'; +import { Observable } from 'rxjs'; @Component({ selector: 'app-archive-preview', templateUrl: './archive-preview.component.html', - styleUrls: ['./archive-preview.component.scss'] + styleUrls: ['./archive-preview.component.scss'], }) -export class ArchivePreviewComponent implements OnInit { - +export class ArchivePreviewComponent implements OnInit, OnChanges { @Input() archiveUnit: Unit; @Input() - accessContract : string; + accessContract: string; @Output() previewClose: EventEmitter<any> = new EventEmitter(); @Input() isPopup: boolean; - tenantIdentifier: string; - constructor(private archiveService : ArchiveService, private startupService : StartupService, private route: ActivatedRoute) { - this.route.params.subscribe(params => { + uaPath$: Observable<{ fullPath: string; resumePath: string }>; + fullPath = false; + + constructor(private archiveService: ArchiveService, private route: ActivatedRoute) { + this.route.params.subscribe((params) => { this.tenantIdentifier = params.tenantIdentifier; }); - } ngOnInit() { + this.uaPath$ = this.archiveService.buildArchiveUnitPath(this.archiveUnit, this.accessContract); + } + ngOnChanges(changes: SimpleChanges): void { + if (changes['archiveUnit'].firstChange) { + return; } - + if (changes['archiveUnit'].currentValue['#id'] !== changes['archiveUnit'].previousValue['#id']) { + this.uaPath$ = this.archiveService.buildArchiveUnitPath(this.archiveUnit, this.accessContract); + } + this.fullPath = false; + } onDownloadObjectFromUnit(archiveUnit: Unit) { let headers = new HttpHeaders().append('Content-Type', 'application/json'); headers = headers.append('X-Access-Contract-Id', this.accessContract); - return this.archiveService.downloadObjectFromUnit(archiveUnit['#id'], archiveUnit?.Title , archiveUnit?.Title_, headers); + return this.archiveService.downloadObjectFromUnit(archiveUnit['#id'], archiveUnit?.Title, archiveUnit?.Title_, headers); } emitClose() { this.previewClose.emit(); } - - - openPopup() { - window.open(this.startupService.getConfigStringValue('UI_URL') - + '/archive-search/tenant/' + this.tenantIdentifier + '/' + this.accessContract + '/id/' + this.archiveUnit['#id'], - 'detailPopup', 'width=684, height=713, resizable=no, location=no'); - this.emitClose(); + showArchiveUniteFullPath() { + this.fullPath = true; } - } diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive.service.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive.service.ts index 73111aed9..4772c89a1 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive.service.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive.service.ts @@ -37,19 +37,19 @@ import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http'; import { Inject, Injectable, LOCALE_ID } from '@angular/core'; import { MatSnackBar } from '@angular/material/snack-bar'; +import { ArchiveApiService } from '../core/api/archive-api.service'; +import { CriteriaDataType, CriteriaOperator, SearchService, SecurityService } from 'ui-frontend-common'; import { Observable, of, throwError, TimeoutError } from 'rxjs'; import { catchError, map, tap } from 'rxjs/operators'; -import { SearchService, SecurityService } from 'ui-frontend-common'; -import { ArchiveApiService } from '../core/api/archive-api.service'; import { ExportDIPCriteriaList } from './models/dip-request-detail.interface'; import { FilingHoldingSchemeNode } from './models/node.interface'; import { SearchResponse } from './models/search-response.interface'; -import { PagedResult, ResultFacet, SearchCriteriaDto } from './models/search.criteria'; +import { PagedResult, ResultFacet, SearchCriteriaDto, SearchCriteriaTypeEnum } from './models/search.criteria'; import { Unit } from './models/unit.interface'; import { VitamUISnackBarComponent } from './shared/vitamui-snack-bar'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class ArchiveService extends SearchService<any> { constructor( @@ -71,7 +71,7 @@ export class ArchiveService extends SearchService<any> { public loadFilingHoldingSchemeTree(tenantIdentifier: number, accessContractId: string): Observable<FilingHoldingSchemeNode[]> { const headers = new HttpHeaders({ 'X-Tenant-Id': '' + tenantIdentifier, - 'X-Access-Contract-Id': accessContractId + 'X-Access-Contract-Id': accessContractId, }); return this.archiveApiService.getFilingHoldingScheme(headers).pipe( @@ -100,7 +100,7 @@ export class ArchiveService extends SearchService<any> { parents: parentNode ? [parentNode] : [], vitamId: unit['#id'], checked: false, - hidden: false + hidden: false, }; outNode.children = this.buildNestedTreeLevels(arr, outNode).sort(byTitle(this.locale)); out.push(outNode); @@ -131,7 +131,7 @@ export class ArchiveService extends SearchService<any> { this.snackBar.openFromComponent(VitamUISnackBarComponent, { panelClass: 'vitamui-snack-bar', data: { type: 'exportCsvLimitReached' }, - duration: 10000 + duration: 10000, }); } } @@ -151,18 +151,18 @@ export class ArchiveService extends SearchService<any> { // Return other errors return of({ $hits: null, $results: [] }); }), - map((results) => this.buildPagedResults(results)) + map((results) => ArchiveService.buildPagedResults(results)) ); } - private buildPagedResults(response: SearchResponse): PagedResult { + private static buildPagedResults(response: SearchResponse): PagedResult { const pagedResult: PagedResult = { results: response.$results, totalResults: response.$hits.total, pageNumbers: +response.$hits.size !== 0 ? Math.floor(+response.$hits.total / +response.$hits.size) + (+response.$hits.total % +response.$hits.size === 0 ? 0 : 1) - : 0 + : 0, }; const resultFacets: ResultFacet[] = []; if (response.$facetResults && response.$facetResults) { @@ -182,11 +182,11 @@ export class ArchiveService extends SearchService<any> { downloadObjectFromUnit(id: string, title?: string, title_?: any, headers?: HttpHeaders) { return this.archiveApiService.downloadObjectFromUnit(id, headers).subscribe( (response) => { - let filename = null; + let filename; if (response.headers.get('content-disposition').includes('filename')) { filename = response.headers.get('content-disposition').split('=')[1]; } else { - filename = this.normalizeTitle(title ? title : title_ ? (title_.fr ? title_.fr : title_.en) : title_.en); + filename = this.normalizeTitle(ArchiveService.fetchTitle(title, title_)); } const element = document.createElement('a'); @@ -203,6 +203,10 @@ export class ArchiveService extends SearchService<any> { ); } + private static fetchTitle(title: string, title_: any) { + return title ? title : title_ ? (title_.fr ? title_.fr : title_.en) : title_.en; + } + normalizeTitle(title: string): string { title = title.replace(/[&\/\\|.'":*?<> ]/g, ''); return title.substring(0, 218); @@ -244,6 +248,53 @@ export class ArchiveService extends SearchService<any> { duration: 100000, }); } + + buildArchiveUnitPath(archiveUnit: Unit, accessContract: string) { + const criteriaSearchList = []; + + criteriaSearchList.push({ + criteria: '#id', + values: archiveUnit['#allunitups'].map((unitUp) => ({ id: unitUp, value: unitUp })), + operator: CriteriaOperator.EQ, + category: SearchCriteriaTypeEnum[SearchCriteriaTypeEnum.FIELDS], + dataType: CriteriaDataType.STRING, + }); + + const searchCriteria = { + criteriaList: criteriaSearchList, + pageNumber: 0, + size: archiveUnit['#allunitups'].length, + }; + + return this.searchArchiveUnitsByCriteria(searchCriteria, accessContract).pipe( + map((pagedResult: PagedResult) => { + let resumePath = '/'; + let fullPath = '/'; + + if (pagedResult.results) { + resumePath = `/${pagedResult.results.map((ua) => ArchiveService.fetchTitle(ua.Title, ua.Title_)).join('/')}`; + fullPath = `/${pagedResult.results.map((ua) => ArchiveService.fetchTitle(ua.Title, ua.Title_)).join('/')}`; + + if (pagedResult.results.length > 6) { + const upperBoundPath = pagedResult.results + .slice(0, 3) + .map((ua) => ArchiveService.fetchTitle(ua.Title, ua.Title_)) + .join('/'); + const lowerBoundPath = pagedResult.results + .slice(-3) + .map((ua) => ArchiveService.fetchTitle(ua.Title, ua.Title_)) + .join('/'); + resumePath = `/${upperBoundPath}/../${lowerBoundPath}`; + } + } + + return { + fullPath, + resumePath, + }; + }) + ); + } } function idExists(units: Unit[], id: string): boolean { diff --git a/ui/ui-frontend/projects/archive-search/src/assets/i18n/en.json b/ui/ui-frontend/projects/archive-search/src/assets/i18n/en.json index 6b8f5ba4c..e70dad03f 100644 --- a/ui/ui-frontend/projects/archive-search/src/assets/i18n/en.json +++ b/ui/ui-frontend/projects/archive-search/src/assets/i18n/en.json @@ -133,7 +133,8 @@ "SP_LABEL": "Name", "PATH": "Path", "DESCRIPTION_LEVEL": "Description level", - "DOWNLOAD_DOC": "Download the document" + "DOWNLOAD_DOC": "Download the document", + "BTN_SHOW_COMPLETE_PATH": "SHOW COMPLETE PATH" }, "TABS": { "INFORMATIONS": "Informations" diff --git a/ui/ui-frontend/projects/archive-search/src/assets/i18n/fr.json b/ui/ui-frontend/projects/archive-search/src/assets/i18n/fr.json index 685e1ec13..e40ca6234 100644 --- a/ui/ui-frontend/projects/archive-search/src/assets/i18n/fr.json +++ b/ui/ui-frontend/projects/archive-search/src/assets/i18n/fr.json @@ -161,7 +161,8 @@ "SP_LABEL": "Nom", "PATH": "Chemin", "DESCRIPTION_LEVEL": "Niveau de description", - "DOWNLOAD_DOC": "Télécharger le document" + "DOWNLOAD_DOC": "Télécharger le document", + "BTN_SHOW_COMPLETE_PATH": "AFFICHER TOUT" }, "TABS": { "INFORMATIONS": "Informations" -- GitLab