mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-15 05:53:03 +00:00
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:
@@ -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 }}
|
||||
|
@@ -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>
|
||||
|
@@ -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);
|
||||
|
@@ -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>
|
||||
|
@@ -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 = {};
|
||||
|
||||
|
@@ -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",
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user