CST-9639: Fixed error on control remove, fixed cancel button behavior, fixed bad state of access control tab on load, fixed translations, added jsdocs

This commit is contained in:
Enea Jahollari
2023-06-07 13:00:12 +02:00
parent d99b98d140
commit 47e0314c9b
6 changed files with 92 additions and 43 deletions

View File

@@ -7,7 +7,7 @@
<div class="d-flex justify-content-end">
<button class="btn btn-outline-primary mr-3" (click)="reset()">
{{ 'access-control-reset' | translate }}
{{ 'access-control-cancel' | translate }}
</button>
<button class="btn btn-primary" [disabled]="!canExport()" (click)="submit()">
{{ 'access-control-execute' | translate }}

View File

@@ -1,22 +1,22 @@
<form #ngForm="ngForm">
<div *ngIf="mode === 'replace' && allControlsAreEmpty && ngForm.enabled"
class="alert alert-warning">
<div *ngIf="showWarning" class="alert alert-warning">
{{'access-control-no-access-conditions-warning-message' | translate}}
</div>
<ng-container *ngFor="let control of form.accessControls; let i = index">
<div ngModelGroup="access-control-item-{{i}}" class="access-control-item mt-3">
<ng-container *ngFor="let control of form.accessControls; trackBy: trackById">
<div #ngModelGroup="ngModelGroup" ngModelGroup="access-control-item-{{control.id}}" class="access-control-item mt-3">
<div class="d-flex flex-column">
<div>
<label for="accesscontroloption-{{i}}">
<label for="accesscontroloption-{{control.id}}">
{{'access-control-option-label' | translate}}
</label>
<select
id="accesscontroloption-{{i}}"
id="accesscontroloption-{{control.id}}"
[disabled]="ngForm.disabled"
[(ngModel)]="control.itemName"
(ngModelChange)="accessControlChanged(control, $event)"
name="itemName-{{i}}"
name="itemName-{{control.id}}"
class="form-control">
<option value=""></option>
<option *ngFor="let option of dropdownOptions" [value]="option.name">
@@ -29,16 +29,16 @@
</div>
<div *ngIf="control.hasStartDate" class="mt-3">
<label for="accesscontrolstartdate-{{i}}">
<label for="accesscontrolstartdate-{{control.id}}">
{{'access-control-option-start-date' | translate}}
</label>
<div class="input-group">
<input
id="accesscontrolstartdate-{{i}}"
id="accesscontrolstartdate-{{control.id}}"
class="form-control"
placeholder="yyyy-mm-dd"
[(ngModel)]="control.startDate"
name="startDate-{{i}}"
name="startDate-{{control.id}}"
[minDate]="control.maxStartDate | toDate"
ngbDatepicker
#d="ngbDatepicker"
@@ -57,16 +57,16 @@
</div>
<div *ngIf="control.hasEndDate" class="mt-3">
<label for="accesscontrolenddate-{{i}}">
<label for="accesscontrolenddate-{{control.id}}">
{{'access-control-option-end-date' | translate}}
</label>
<div class="input-group">
<input
id="accesscontrolenddate-{{i}}"
id="accesscontrolenddate-{{control.id}}"
class="form-control"
placeholder="yyyy-mm-dd"
[(ngModel)]="control.endDate"
name="endDate-{{i}}"
name="endDate-{{control.id}}"
[maxDate]="control.maxEndDate | toDate"
ngbDatepicker
#d1="ngbDatepicker"
@@ -90,8 +90,8 @@
<div class="input-group">
<button type="button" class="btn btn-outline-danger"
[disabled]="ngForm.disabled"
(click)="removeAccessControlItem(i)">
[disabled]="ngForm.disabled || form.accessControls.length === 1"
(click)="removeAccessControlItem(ngModelGroup, control.id)">
<i class="fas fa-trash"></i>
</button>
</div>

View File

@@ -1,5 +1,5 @@
import {Component, Input, OnInit, ViewChild} from '@angular/core';
import {NgForm} from '@angular/forms';
import {NgForm, NgModelGroup} from '@angular/forms';
import {AccessesConditionOption} from '../../../core/config/models/config-accesses-conditions-options.model';
import {dateToISOFormat} from '../../date.util';
@@ -17,14 +17,13 @@ export class AccessControlArrayFormComponent implements OnInit {
@ViewChild('ngForm', {static: true}) ngForm!: NgForm;
form: { accessControls: AccessControlItem[] } = {
accessControls: []
accessControls: [emptyAccessControlItem()] // Start with one empty access control item
};
ngOnInit(): void {
this.addAccessControlItem();
formDisabled = true;
// Disable the form by default
setTimeout(() => this.disable(), 0);
ngOnInit(): void {
this.disable(); // Disable the form by default
}
get allControlsAreEmpty() {
@@ -32,29 +31,31 @@ export class AccessControlArrayFormComponent implements OnInit {
.every(x => x.itemName === null || x.itemName === '');
}
get showWarning() {
return this.mode === 'replace' && this.allControlsAreEmpty && !this.formDisabled;
}
/**
* Add a new access control item to the form.
* Start and end date are disabled by default.
* @param itemName The name of the item to add
*/
addAccessControlItem(itemName: string = null) {
this.form.accessControls.push({
itemName,
startDate: null,
hasStartDate: false,
maxStartDate: null,
endDate: null,
hasEndDate: false,
maxEndDate: null,
});
this.form.accessControls = [
...this.form.accessControls,
{...emptyAccessControlItem(), itemName}
];
}
/**
* Remove an access control item from the form.
* @param ngModelGroup
* @param index
*/
removeAccessControlItem(index: number) {
this.form.accessControls.splice(index, 1);
removeAccessControlItem(ngModelGroup: NgModelGroup, id: number) {
this.ngForm.removeFormGroup(ngModelGroup);
this.form.accessControls = this.form.accessControls.filter(item => item.id !== id);
}
/**
@@ -77,19 +78,30 @@ export class AccessControlArrayFormComponent implements OnInit {
*/
reset() {
this.form.accessControls = [];
// Add an empty access control item by default
this.addAccessControlItem();
this.disable();
}
/**
* Disable the form.
* This will be used to disable the form from the parent component.
*/
disable = () => this.ngForm.control.disable();
disable = () => {
this.ngForm.form.disable();
this.formDisabled = true;
};
/**
* Enable the form.
* This will be used to enable the form from the parent component.
*/
enable = () => this.ngForm.control.enable();
enable = () => {
this.ngForm.form.enable();
this.formDisabled = false;
};
accessControlChanged(control: AccessControlItem, selectedItem: string) {
const item = this.dropdownOptions
@@ -105,9 +117,16 @@ export class AccessControlArrayFormComponent implements OnInit {
control.maxEndDate = item?.maxEndDate || null;
}
trackById(index: number, item: AccessControlItem) {
return item.id;
}
}
export interface AccessControlItem {
id: number; // will be used only locally
itemName: string | null;
hasStartDate?: boolean;
@@ -118,3 +137,16 @@ export interface AccessControlItem {
endDate: string | null;
maxEndDate?: string | null;
}
const emptyAccessControlItem = (): AccessControlItem => ({
id: randomID(),
itemName: null,
startDate: null,
hasStartDate: false,
maxStartDate: null,
endDate: null,
hasEndDate: false,
maxEndDate: null,
});
const randomID = () => Math.floor(Math.random() * 1000000);

View File

@@ -153,12 +153,12 @@
<hr *ngIf="showSubmit">
<div *ngIf="showSubmit" class="d-flex justify-content-end">
<button class="btn btn-outline-primary mr-3" (click)="reset()">
<button class="btn btn-outline-primary mr-3" (click)="reset()" type="button">
{{ 'access-control-cancel' | translate }}
</button>
<button class="btn btn-primary"
[disabled]="!state.item.toggleStatus && !state.bitstream.toggleStatus"
(click)="submit()">
(click)="submit()" type="submit">
{{ 'access-control-execute' | translate }}
</button>
</div>

View File

@@ -21,6 +21,9 @@ export interface BulkAccessPayload {
itemAccess: any;
}
/**
* This service is used to create a payload file and execute the bulk access control script
*/
@Injectable({ providedIn: 'root' })
export class BulkAccessControlService {
constructor(
@@ -28,10 +31,13 @@ export class BulkAccessControlService {
private router: Router,
private scriptService: ScriptDataService,
private translationService: TranslateService
) {
}
) {}
/**
* Create a payload file from the given payload and return the file and the url to the file
* The created file will be used as input for the bulk access control script
* @param payload The payload to create the file from
*/
createPayloadFile(payload: BulkAccessPayload) {
const content = convertToBulkAccessControlFileModel(payload);
@@ -48,6 +54,11 @@ export class BulkAccessControlService {
return { url, file };
}
/**
* Execute the bulk access control script with the given uuids and file
* @param uuids
* @param file
*/
executeScript(uuids: string[], file: File): Observable<boolean> {
console.log('execute', { uuids, file });
@@ -80,6 +91,10 @@ export class BulkAccessControlService {
}
}
/**
* Convert the given payload to a BulkAccessControlFileModel
* @param payload
*/
export const convertToBulkAccessControlFileModel = (payload: { state: AccessControlFormState, bitstreamAccess: AccessCondition[], itemAccess: AccessCondition[] }): BulkAccessControlFileModel => {
let finalPayload: BulkAccessControlFileModel = {};

View File

@@ -225,7 +225,9 @@
"admin.registries.schema.title": "Metadata Schema Registry",
"admin.access-control.bulk-access.breadcrumbs": "Bulk Access Management",
"administrativeBulkAccess.search.results.head": "Search Results",
"admin.access-control.bulk-access": "Bulk Access Management",
@@ -5399,14 +5401,14 @@
"access-control-option-label": "Access condition type",
"access-control-option-note": "Select an access condition to apply on the bitstream once the item is deposited",
"access-control-option-note": "Choose an access condition to apply to selected objects.",
"access-control-option-start-date": "Grant access from",
"access-control-option-start-date-note": "Select the date from which the relate access condition is applied",
"access-control-option-start-date-note": "Select the date from which the related access condition is applied",
"access-control-option-end-date": "Grant access until",
"access-control-option-end-date-note": "Select the date until which the relate access condition is applied",
"access-control-option-end-date-note": "Select the date until which the related access condition is applied",
}