Pull request #265: Show list of available placeholders in report management

Merge in RED/ui from RED-1741 to master

* commit '9f967ec8b96a0cc4a440ba17e2b1378018934a9c':
  Show list of available placeholders in report management
This commit is contained in:
Adina Teudan 2021-08-11 14:21:03 +02:00
commit 9b6232fd76
9 changed files with 194 additions and 27 deletions

View File

@ -30,13 +30,14 @@
</div>
<div class="placeholders">
<div class="all-caps-label">Placeholders</div>
<div class="all-caps-label">Description</div>
<div class="all-caps-label" translate="reports-screen.table-header.placeholders"></div>
<div class="all-caps-label" translate="reports-screen.table-header.description"></div>
<ng-container *ngFor="let placeholder of placeholders">
<div class="placeholder">{{ getPlaceholderDisplayValue(placeholder) }}</div>
<div class="description">
What is and how to use it in your document. The readable content of a page when looking at its layout must be nice.
</div>
<div class="placeholder">{{ placeholder.placeholder }}</div>
<div
[innerHTML]="placeholder.descriptionTranslation | translate: { attribute: placeholder.attributeName }"
class="description"
></div>
</ng-container>
</div>
</div>
@ -82,4 +83,4 @@
</div>
</section>
<input #fileInput (change)="uploadFile($event)" hidden type="file" />
<input #fileInput (change)="uploadTemplate($event)" hidden type="file" />

View File

@ -103,7 +103,6 @@
.placeholder {
font-weight: 600;
text-transform: capitalize;
margin-left: 16px;
}

View File

@ -1,11 +1,25 @@
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { AppStateService } from '@state/app-state.service';
import { ReportTemplate, ReportTemplateControllerService } from '@redaction/red-ui-http';
import { PlaceholdersResponse, ReportTemplate, ReportTemplateControllerService } from '@redaction/red-ui-http';
import { download } from '../../../../utils/file-download-utils';
import { AdminDialogService } from '../../services/admin-dialog.service';
import { LoadingService } from '@services/loading.service';
import { PermissionsService } from '@services/permissions.service';
import {
generalPlaceholdersDescriptionsTranslations,
placeholdersDescriptionsTranslations
} from '../../translations/placeholders-descriptions-translations';
import { removeBraces } from '../../../../utils/functions';
interface Placeholder {
placeholder: string;
descriptionTranslation: string;
attributeName?: string;
}
type PlaceholderType = 'generalPlaceholders' | 'fileAttributePlaceholders' | 'dossierAttributePlaceholders';
const placeholderTypes: PlaceholderType[] = ['generalPlaceholders', 'fileAttributePlaceholders', 'dossierAttributePlaceholders'];
@Component({
selector: 'redaction-reports-screen',
@ -13,7 +27,7 @@ import { PermissionsService } from '@services/permissions.service';
styleUrls: ['./reports-screen.component.scss']
})
export class ReportsScreenComponent implements OnInit {
placeholders: string[] = ['report', 'predefined placeholder 1', 'signature 01', 'new attribute'];
placeholders: Placeholder[];
availableTemplates: ReportTemplate[];
@ViewChild('fileInput') private _fileInput: ElementRef;
@ -29,45 +43,70 @@ export class ReportsScreenComponent implements OnInit {
this._appStateService.activateDossierTemplate(_activatedRoute.snapshot.params.dossierTemplateId);
}
getPlaceholderDisplayValue(placeholder: string): string {
return `{{${placeholder}}}`;
}
async ngOnInit() {
this._loadingService.start();
await this._loadReportTemplates();
await this._loadPlaceholders();
this._loadingService.stop();
}
async uploadFile($event) {
this._loadingService.start();
const file = $event.target.files[0];
await this._reportTemplateService.uploadTemplateForm(this._appStateService.activeDossierTemplateId, file).toPromise();
this._fileInput.nativeElement.value = null;
await this._loadReportTemplates();
async uploadTemplate($event) {
this._loadingService.loadWhile(this._uploadTemplate($event));
}
async download(template: ReportTemplate) {
this._loadingService.start();
const data = await this._reportTemplateService
.downloadReportTemplate(template.dossierTemplateId, template.templateId, 'response')
.toPromise();
this._loadingService.stop();
download(data, template.fileName);
}
deleteTemplate(template: ReportTemplate) {
this._dialogService.openDialog('confirm', null, null, async () => {
this._loadingService.start();
await this._reportTemplateService.deleteTemplate(template.dossierTemplateId, template.templateId).toPromise();
await this._loadReportTemplates();
this._loadingService.loadWhile(this._deleteTemplate(template));
});
}
private _getAttributeName(placeholder: string): string {
return removeBraces(placeholder).split('.').pop();
}
private _getPlaceholderDescriptionTranslation(type: PlaceholderType, placeholder: string): string {
return type === 'generalPlaceholders'
? generalPlaceholdersDescriptionsTranslations[removeBraces(placeholder)]
: placeholdersDescriptionsTranslations[type];
}
private async _uploadTemplate($event) {
const file = $event.target.files[0];
await this._reportTemplateService.uploadTemplateForm(this._appStateService.activeDossierTemplateId, file).toPromise();
this._fileInput.nativeElement.value = null;
await this._loadReportTemplates();
}
private async _deleteTemplate(template: ReportTemplate) {
await this._reportTemplateService.deleteTemplate(template.dossierTemplateId, template.templateId).toPromise();
await this._loadReportTemplates();
}
private async _loadReportTemplates() {
this._loadingService.start();
this.availableTemplates = await this._reportTemplateService
.getAvailableReportTemplates(this._appStateService.activeDossierTemplateId)
.toPromise();
this._loadingService.stop();
}
private async _loadPlaceholders() {
const placeholdersResponse: PlaceholdersResponse = await this._reportTemplateService
.getAvailablePlaceholders(this._appStateService.activeDossierTemplateId)
.toPromise();
this.placeholders = placeholderTypes.flatMap(type =>
placeholdersResponse[type].map(placeholder => ({
placeholder,
descriptionTranslation: this._getPlaceholderDescriptionTranslation(type, placeholder),
attributeName: this._getAttributeName(placeholder)
}))
);
}
}

View File

@ -0,0 +1,18 @@
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
export const placeholdersDescriptionsTranslations: { [key: string]: string } = {
dossierAttributePlaceholders: _('reports-screen.descriptions.dossier-attributes'),
fileAttributePlaceholders: _('reports-screen.descriptions.file-attributes')
};
export const generalPlaceholdersDescriptionsTranslations: { [key: string]: string } = {
'file.name': _('reports-screen.descriptions.general.file.name'),
'redaction.page': _('reports-screen.descriptions.general.redaction.page'),
'redaction.paragraph': _('reports-screen.descriptions.general.redaction.paragraph'),
'redaction.justification': _('reports-screen.descriptions.general.redaction.justification'),
'date.yyyy-MM-dd': _('reports-screen.descriptions.general.date.y-m-d'),
'date.dd.MM.yyyy': _('reports-screen.descriptions.general.date.d-m-y'),
'date.MM/dd/yyyy': _('reports-screen.descriptions.general.date.m-d-y'),
'time.HH:mm': _('reports-screen.descriptions.general.time.h-m'),
'dossier.name': _('reports-screen.descriptions.general.dossier.name')
};

View File

@ -85,3 +85,7 @@ export function getLeftDateTime(ISOString: string) {
return { daysLeft, hoursLeft, minutesLeft };
}
export function removeBraces(str: any): string {
return str.replace(/[{}]/g, '');
}

View File

@ -1193,9 +1193,38 @@
"reports": "Reports",
"reports-screen": {
"description": "A short text explaining how to create report documents. It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.",
"descriptions": {
"dossier-attributes": "This placeholder gets replaced with the value of the dossier attribute <code>{attribute}</code>.",
"file-attributes": "This placeholder gets replaced with the value of the file attribute <code>{attribute}</code>.",
"general": {
"date": {
"d-m-y": "?",
"m-d-y": "?",
"y-m-d": "?"
},
"dossier": {
"name": "?"
},
"file": {
"name": "?"
},
"redaction": {
"justification": "?",
"page": "?",
"paragraph": "?"
},
"time": {
"h-m": "?"
}
}
},
"document-setup-description": "A short text explaining what placeholders are and how to use them in your report template. It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.",
"document-setup-heading": "Document Setup",
"report-documents": "Report Documents",
"table-header": {
"description": "Description",
"placeholders": "Placeholders"
},
"title": "Reports",
"upload-document": "Upload a Document"
},

View File

@ -20,6 +20,7 @@ import { ReportTemplate } from '../model/reportTemplate';
import { BASE_PATH } from '../variables';
import { Configuration } from '../configuration';
import { PlaceholdersResponse } from '../model/placeholdersResponse';
@Injectable()
export class ReportTemplateControllerService {
@ -41,6 +42,61 @@ export class ReportTemplateControllerService {
}
}
/**
* Returns list of available placeholders
* None
* @param dossierTemplateId dossierTemplateId
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
*/
public getAvailablePlaceholders(
dossierTemplateId: string,
observe?: 'body',
reportProgress?: boolean
): Observable<PlaceholdersResponse>;
public getAvailablePlaceholders(
dossierTemplateId: string,
observe?: 'response',
reportProgress?: boolean
): Observable<HttpResponse<PlaceholdersResponse>>;
public getAvailablePlaceholders(
dossierTemplateId: string,
observe?: 'events',
reportProgress?: boolean
): Observable<HttpEvent<PlaceholdersResponse>>;
public getAvailablePlaceholders(dossierTemplateId: string, observe: any = 'body', reportProgress: boolean = false): Observable<any> {
if (dossierTemplateId === null || dossierTemplateId === undefined) {
throw new Error('Required parameter dossierTemplateId was null or undefined when calling getAvailablePlaceholders.');
}
let headers = this.defaultHeaders;
// authentication (RED-OAUTH) required
if (this.configuration.accessToken) {
const accessToken =
typeof this.configuration.accessToken === 'function' ? this.configuration.accessToken() : this.configuration.accessToken;
headers = headers.set('Authorization', 'Bearer ' + accessToken);
}
// to determine the Accept header
const httpHeaderAccepts: string[] = ['application/json'];
const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts);
if (httpHeaderAcceptSelected !== undefined) {
headers = headers.set('Accept', httpHeaderAcceptSelected);
}
return this.httpClient.request<PlaceholdersResponse>(
'get',
`${this.basePath}/placeholders/${encodeURIComponent(String(dossierTemplateId))}`,
{
withCredentials: this.configuration.withCredentials,
headers: headers,
observe: observe,
reportProgress: reportProgress
}
);
}
/**
* Delete template file for redaction-report
* None

View File

@ -79,3 +79,4 @@ export * from './manualLegalBasisChange';
export * from './searchRequest';
export * from './searchResult';
export * from './matchedDocument';
export * from './placeholdersResponse';

View File

@ -0,0 +1,20 @@
/**
* API Documentation for Redaction Gateway
* Description for redaction
*
* OpenAPI spec version: 1.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/**
* Object containing available placeholders.
*/
export interface PlaceholdersResponse {
dossierAttributePlaceholders?: Array<string>;
fileAttributePlaceholders?: Array<string>;
generalPlaceholders?: Array<string>;
}