mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Fix: fix validation and translation
Show/hide the datepicker based on the value
This commit is contained in:
@@ -1,65 +1,87 @@
|
|||||||
<form [formGroup]="form">
|
<form #ngForm="ngForm">
|
||||||
<div *ngIf="mode === 'replace' && allControlsAreEmpty && form.status !== 'DISABLED'" class="alert alert-warning">
|
<div *ngIf="mode === 'replace' && allControlsAreEmpty && ngForm.enabled"
|
||||||
|
class="alert alert-warning">
|
||||||
{{'access-control-no-access-conditions-warning-message' | translate}}
|
{{'access-control-no-access-conditions-warning-message' | translate}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-container *ngFor="let control of accessControl.controls; let i = index">
|
<ng-container *ngFor="let control of form.accessControls; let i = index">
|
||||||
<div [formGroup]="$any(control)"
|
<div ngModelGroup="access-control-item-{{i}}" class="access-control-item mt-3">
|
||||||
class="mt-3" data-testId="access-control-item"
|
|
||||||
style="display: grid; grid-template-columns: 1fr 50px; grid-gap: 10px">
|
|
||||||
|
|
||||||
<div class="d-flex flex-column">
|
<div class="d-flex flex-column">
|
||||||
<div>
|
<div>
|
||||||
<label for="accesscontroloption">{{'access-control-option-label' | translate}}</label>
|
<label for="accesscontroloption-{{i}}">
|
||||||
<select id="accesscontroloption" formControlName="itemName" class="form-control">
|
{{'access-control-option-label' | translate}}
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="accesscontroloption-{{i}}"
|
||||||
|
[(ngModel)]="control.itemName"
|
||||||
|
(ngModelChange)="accessControlChanged(control, $event)"
|
||||||
|
name="itemName-{{i}}"
|
||||||
|
class="form-control">
|
||||||
<option value=""></option>
|
<option value=""></option>
|
||||||
<option *ngFor="let option of dropdownOptions" [value]="option.name">
|
<option *ngFor="let option of dropdownOptions" [value]="option.name">
|
||||||
{{ option.name }}
|
{{ option.name }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<small class="form-text text-muted">{{'access-control-option-note' | translate}}</small>
|
<small class="form-text text-muted">
|
||||||
|
{{'access-control-option-note' | translate}}
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-group" [class.d-none]="control.get('endDate')?.disabled">
|
<div *ngIf="control.hasStartDate" class="mt-3">
|
||||||
<label for="accesscontrolstartdate">{{'access-control-option-start-date' | translate}}</label>
|
<label for="accesscontrolstartdate-{{i}}">
|
||||||
<input
|
{{'access-control-option-start-date' | translate}}
|
||||||
id="accesscontrolstartdate"
|
</label>
|
||||||
class="form-control"
|
<div class="input-group">
|
||||||
placeholder="yyyy-mm-dd"
|
<input
|
||||||
name="dp"
|
id="accesscontrolstartdate-{{i}}"
|
||||||
formControlName="startDate"
|
class="form-control"
|
||||||
[minDate]="control | maxStartDate: dropdownOptions"
|
placeholder="yyyy-mm-dd"
|
||||||
ngbDatepicker
|
[(ngModel)]="control.startDate"
|
||||||
#d="ngbDatepicker"
|
name="startDate-{{i}}"
|
||||||
/>
|
[minDate]="control.maxStartDate | toDate"
|
||||||
<div class="input-group-append">
|
ngbDatepicker
|
||||||
<button class="btn btn-outline-secondary fas fa-calendar"
|
#d="ngbDatepicker"
|
||||||
[disabled]="form.status === 'DISABLED'"
|
/>
|
||||||
(click)="d.toggle()"
|
<div class="input-group-append">
|
||||||
type="button"></button>
|
<button
|
||||||
|
class="btn btn-outline-secondary fas fa-calendar"
|
||||||
|
[disabled]="ngForm.disabled"
|
||||||
|
(click)="d.toggle()" type="button">
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<small class="form-text text-muted">{{'access-control-option-start-date-note' | translate}}</small>
|
<small class="form-text text-muted">
|
||||||
|
{{'access-control-option-start-date-note' | translate}}
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-group" [class.d-none]="control.get('endDate')?.disabled">
|
<div *ngIf="control.hasEndDate" class="mt-3">
|
||||||
<label for="accesscontrolenddate">{{'access-control-option-end-date' | translate}}</label>
|
<label for="accesscontrolenddate-{{i}}">
|
||||||
<input
|
{{'access-control-option-end-date' | translate}}
|
||||||
id="accesscontrolenddate"
|
</label>
|
||||||
class="form-control"
|
<div class="input-group">
|
||||||
placeholder="yyyy-mm-dd"
|
<input
|
||||||
name="dp"
|
id="accesscontrolenddate-{{i}}"
|
||||||
formControlName="endDate"
|
class="form-control"
|
||||||
[maxDate]="control | maxEndDate: dropdownOptions"
|
placeholder="yyyy-mm-dd"
|
||||||
ngbDatepicker
|
[(ngModel)]="control.endDate"
|
||||||
#d1="ngbDatepicker"
|
name="endDate-{{i}}"
|
||||||
/>
|
[maxDate]="control.maxEndDate | toDate"
|
||||||
<div class="input-group-append">
|
ngbDatepicker
|
||||||
<button type="button" class="btn btn-outline-secondary fas fa-calendar"
|
#d1="ngbDatepicker"
|
||||||
[disabled]="form.status === 'DISABLED'"
|
/>
|
||||||
(click)="d1.toggle()">
|
<div class="input-group-append">
|
||||||
</button>
|
<button
|
||||||
|
type="button" class="btn btn-outline-secondary fas fa-calendar"
|
||||||
|
[disabled]="ngForm.disabled"
|
||||||
|
(click)="d1.toggle()">
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<small class="form-text text-muted">{{'access-control-option-end-date-note' | translate}}</small>
|
<small class="form-text text-muted">
|
||||||
|
{{'access-control-option-end-date-note' | translate}}
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -68,18 +90,17 @@
|
|||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
|
|
||||||
<button type="button" class="btn btn-outline-danger"
|
<button type="button" class="btn btn-outline-danger"
|
||||||
[disabled]="form.status === 'DISABLED'"
|
[disabled]="ngForm.disabled"
|
||||||
(click)="removeAccessControlItem(i)">
|
(click)="removeAccessControlItem(i)">
|
||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<button type="button" id="add-btn" class="btn btn-outline-primary mt-3"
|
<button type="button" id="add-btn-{{type}}" class="btn btn-outline-primary mt-3"
|
||||||
[disabled]="form.status === 'DISABLED'"
|
[disabled]="ngForm.disabled"
|
||||||
(click)="addAccessControlItem()">
|
(click)="addAccessControlItem()">
|
||||||
<i class="fas fa-plus"></i>
|
<i class="fas fa-plus"></i>
|
||||||
{{'access-control-add-more' | translate}}
|
{{'access-control-add-more' | translate}}
|
||||||
|
@@ -0,0 +1,7 @@
|
|||||||
|
.access-control-item {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 50px;
|
||||||
|
grid-gap: 10px;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
border-bottom: 2px dotted grey;
|
||||||
|
}
|
||||||
|
@@ -1,15 +1,14 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { AccessControlArrayFormComponent } from './access-control-array-form.component';
|
import { AccessControlArrayFormComponent, AccessControlItem } from './access-control-array-form.component';
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { SharedBrowseByModule } from '../../browse-by/shared-browse-by.module';
|
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { ControlMaxStartDatePipe } from './control-max-start-date.pipe';
|
|
||||||
import { ControlMaxEndDatePipe } from './control-max-end-date.pipe';
|
|
||||||
import { DebugElement } from '@angular/core';
|
import { DebugElement } from '@angular/core';
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { ToDatePipe } from './to-date.pipe';
|
||||||
|
import { SharedBrowseByModule } from '../../browse-by/shared-browse-by.module';
|
||||||
|
|
||||||
describe('AccessControlArrayFormComponent', () => {
|
describe('AccessControlArrayFormComponent', () => {
|
||||||
let component: AccessControlArrayFormComponent;
|
let component: AccessControlArrayFormComponent;
|
||||||
@@ -17,8 +16,8 @@ describe('AccessControlArrayFormComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [ CommonModule, ReactiveFormsModule, SharedBrowseByModule, TranslateModule, NgbDatepickerModule ],
|
imports: [ CommonModule, FormsModule, SharedBrowseByModule, TranslateModule, NgbDatepickerModule ],
|
||||||
declarations: [ AccessControlArrayFormComponent, ControlMaxStartDatePipe, ControlMaxEndDatePipe ]
|
declarations: [ AccessControlArrayFormComponent, ToDatePipe ]
|
||||||
})
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
});
|
});
|
||||||
@@ -27,6 +26,7 @@ describe('AccessControlArrayFormComponent', () => {
|
|||||||
fixture = TestBed.createComponent(AccessControlArrayFormComponent);
|
fixture = TestBed.createComponent(AccessControlArrayFormComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
component.dropdownOptions = [{name: 'Option1'}, {name: 'Option2'}] as any;
|
component.dropdownOptions = [{name: 'Option1'}, {name: 'Option2'}] as any;
|
||||||
|
component.type = 'item';
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -35,37 +35,52 @@ describe('AccessControlArrayFormComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should have only one empty control access item in the form', () => {
|
it('should have only one empty control access item in the form', () => {
|
||||||
const accessControlItems = fixture.debugElement.queryAll(By.css('[data-testId="access-control-item"]'));
|
const accessControlItems = fixture.debugElement.queryAll(By.css('.access-control-item'));
|
||||||
expect(accessControlItems.length).toEqual(1);
|
expect(accessControlItems.length).toEqual(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add access control item', () => {
|
it('should add access control item', () => {
|
||||||
component.addAccessControlItem();
|
component.addAccessControlItem();
|
||||||
expect(component.accessControl.length).toEqual(2);
|
expect(component.form.accessControls.length).toEqual(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove access control item', () => {
|
it('should remove access control item', () => {
|
||||||
component.removeAccessControlItem(0);
|
component.removeAccessControlItem(0);
|
||||||
expect(component.accessControl.length).toEqual(0);
|
expect(component.form.accessControls.length).toEqual(0);
|
||||||
|
|
||||||
component.addAccessControlItem();
|
component.addAccessControlItem();
|
||||||
component.removeAccessControlItem(0);
|
component.removeAccessControlItem(0);
|
||||||
expect(component.accessControl.length).toEqual(0);
|
expect(component.form.accessControls.length).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set access control item value', () => {
|
it('should set access control item value', () => {
|
||||||
const item = { itemName: 'item1', startDate: '2022-01-01', endDate: '2022-02-01' };
|
const item: AccessControlItem = { itemName: 'item1', startDate: '2022-01-01', endDate: '2022-02-01' };
|
||||||
|
|
||||||
component.addAccessControlItem(item.itemName);
|
component.addAccessControlItem(item.itemName);
|
||||||
component.accessControl.controls[0].patchValue(item);
|
|
||||||
expect(component.form.value.accessControl[0]).toEqual(item);
|
// set value to item1
|
||||||
|
component.accessControlChanged(
|
||||||
|
component.form.accessControls[0],
|
||||||
|
'item1'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(component.form.accessControls[0].startDate).toEqual(item.startDate);
|
||||||
|
expect(component.form.accessControls[0].endDate).toEqual(item.endDate);
|
||||||
|
expect(component.form.accessControls[0].itemName).toEqual(item.itemName);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reset form value', () => {
|
it('should reset form value', () => {
|
||||||
const item = { itemName: 'item1', startDate: '2022-01-01', endDate: '2022-02-01' };
|
const item = { itemName: 'item1', startDate: '2022-01-01', endDate: '2022-02-01' };
|
||||||
component.addAccessControlItem(item.itemName);
|
component.addAccessControlItem(item.itemName);
|
||||||
component.accessControl.controls[1].patchValue(item);
|
|
||||||
|
// set value to item1
|
||||||
|
component.accessControlChanged(
|
||||||
|
component.form.accessControls[1],
|
||||||
|
'item1'
|
||||||
|
);
|
||||||
|
|
||||||
component.reset();
|
component.reset();
|
||||||
expect(component.form.value.accessControl[1].value).toEqual(undefined);
|
expect(component.form.accessControls[1].itemName).toEqual(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -82,11 +97,11 @@ describe('AccessControlArrayFormComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should add new access control items when clicking "Add more" button', () => {
|
it('should add new access control items when clicking "Add more" button', () => {
|
||||||
const addButton: DebugElement = fixture.debugElement.query(By.css('button#add-btn'));
|
const addButton: DebugElement = fixture.debugElement.query(By.css(`button#add-btn-${component.type}`));
|
||||||
addButton.nativeElement.click();
|
addButton.nativeElement.click();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const accessControlItems = fixture.debugElement.queryAll(By.css('[data-testId="access-control-item"]'));
|
const accessControlItems = fixture.debugElement.queryAll(By.css('.access-control-item'));
|
||||||
expect(accessControlItems.length).toEqual(2);
|
expect(accessControlItems.length).toEqual(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -95,7 +110,7 @@ describe('AccessControlArrayFormComponent', () => {
|
|||||||
removeButton.nativeElement.click();
|
removeButton.nativeElement.click();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const accessControlItems = fixture.debugElement.queryAll(By.css('[data-testId="access-control-item"]'));
|
const accessControlItems = fixture.debugElement.queryAll(By.css('.access-control-item'));
|
||||||
expect(accessControlItems.length).toEqual(0);
|
expect(accessControlItems.length).toEqual(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,46 +1,35 @@
|
|||||||
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
|
import {Component, Input, OnInit, ViewChild} from '@angular/core';
|
||||||
import { FormArray, FormBuilder, FormControl } from '@angular/forms';
|
import {NgForm} from '@angular/forms';
|
||||||
|
import {AccessesConditionOption} from '../../../core/config/models/config-accesses-conditions-options.model';
|
||||||
import { distinctUntilChanged, takeUntil } from 'rxjs/operators';
|
import {dateToISOFormat} from '../../date.util';
|
||||||
import { Subject } from 'rxjs';
|
|
||||||
import { AccessesConditionOption } from '../../../core/config/models/config-accesses-conditions-options.model';
|
|
||||||
import { dateToISOFormat } from '../../date.util';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-access-control-array-form',
|
selector: 'ds-access-control-array-form',
|
||||||
templateUrl: './access-control-array-form.component.html',
|
templateUrl: './access-control-array-form.component.html',
|
||||||
styleUrls: [ './access-control-array-form.component.scss' ],
|
styleUrls: ['./access-control-array-form.component.scss'],
|
||||||
exportAs: 'accessControlArrayForm'
|
exportAs: 'accessControlArrayForm'
|
||||||
})
|
})
|
||||||
export class AccessControlArrayFormComponent implements OnInit, OnDestroy {
|
export class AccessControlArrayFormComponent implements OnInit {
|
||||||
@Input() dropdownOptions: AccessesConditionOption[] = [];
|
@Input() dropdownOptions: AccessesConditionOption[] = [];
|
||||||
@Input() mode!: 'add' | 'replace';
|
@Input() mode!: 'add' | 'replace';
|
||||||
|
@Input() type!: 'item' | 'bitstream';
|
||||||
|
|
||||||
private destroy$ = new Subject<void>();
|
@ViewChild('ngForm', {static: true}) ngForm!: NgForm;
|
||||||
|
|
||||||
form = this.fb.group({
|
form: { accessControls: AccessControlItem[] } = {
|
||||||
accessControl: this.fb.array([])
|
accessControls: []
|
||||||
});
|
};
|
||||||
|
|
||||||
constructor(private fb: FormBuilder) {}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.addAccessControlItem();
|
this.addAccessControlItem();
|
||||||
this.handleValidationOnFormArrayChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Disable the form by default
|
||||||
* Get the access control form array.
|
setTimeout(() => this.disable(), 0);
|
||||||
*/
|
|
||||||
get accessControl() {
|
|
||||||
return this.form.get('accessControl') as FormArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get allControlsAreEmpty() {
|
get allControlsAreEmpty() {
|
||||||
if (this.accessControl.length === 0) {
|
return this.form.accessControls
|
||||||
return true;
|
.every(x => x.itemName === null || x.itemName === '');
|
||||||
}
|
|
||||||
return this.accessControl.value.every(x => x.itemName === null || x.itemName === '');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,11 +38,15 @@ export class AccessControlArrayFormComponent implements OnInit, OnDestroy {
|
|||||||
* @param itemName The name of the item to add
|
* @param itemName The name of the item to add
|
||||||
*/
|
*/
|
||||||
addAccessControlItem(itemName: string = null) {
|
addAccessControlItem(itemName: string = null) {
|
||||||
this.accessControl.push(this.fb.group({
|
this.form.accessControls.push({
|
||||||
itemName,
|
itemName,
|
||||||
startDate: new FormControl({ value: null, disabled: true }),
|
startDate: null,
|
||||||
endDate: new FormControl({ value: null, disabled: true })
|
hasStartDate: false,
|
||||||
}));
|
maxStartDate: null,
|
||||||
|
endDate: null,
|
||||||
|
hasEndDate: false,
|
||||||
|
maxEndDate: null,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,7 +54,7 @@ export class AccessControlArrayFormComponent implements OnInit, OnDestroy {
|
|||||||
* @param index
|
* @param index
|
||||||
*/
|
*/
|
||||||
removeAccessControlItem(index: number) {
|
removeAccessControlItem(index: number) {
|
||||||
this.accessControl.removeAt(index);
|
this.form.accessControls.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -70,7 +63,7 @@ export class AccessControlArrayFormComponent implements OnInit, OnDestroy {
|
|||||||
* @return The form value
|
* @return The form value
|
||||||
*/
|
*/
|
||||||
getValue() {
|
getValue() {
|
||||||
return (this.form.value.accessControl as any[])
|
return this.form.accessControls
|
||||||
.filter(x => x.itemName !== null && x.itemName !== '')
|
.filter(x => x.itemName !== null && x.itemName !== '')
|
||||||
.map(x => ({
|
.map(x => ({
|
||||||
name: x.itemName,
|
name: x.itemName,
|
||||||
@@ -83,77 +76,45 @@ export class AccessControlArrayFormComponent implements OnInit, OnDestroy {
|
|||||||
* Set the value of the form from the parent component.
|
* Set the value of the form from the parent component.
|
||||||
*/
|
*/
|
||||||
reset() {
|
reset() {
|
||||||
this.accessControl.reset([]);
|
this.form.accessControls = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable the form.
|
* Disable the form.
|
||||||
* This will be used to disable the form from the parent component.
|
* This will be used to disable the form from the parent component.
|
||||||
* This will also disable all date controls.
|
|
||||||
*/
|
*/
|
||||||
disable() {
|
disable = () => this.ngForm.control.disable();
|
||||||
this.form.disable();
|
|
||||||
|
|
||||||
// disable all date controls
|
|
||||||
for (const control of this.accessControl.controls) {
|
|
||||||
control.get('startDate').disable();
|
|
||||||
control.get('endDate').disable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable the form.
|
* Enable the form.
|
||||||
* This will be used to enable the form from the parent component.
|
* This will be used to enable the form from the parent component.
|
||||||
* This will also enable all date controls.
|
|
||||||
*/
|
*/
|
||||||
enable() {
|
enable = () => this.ngForm.control.enable();
|
||||||
this.form.enable();
|
|
||||||
|
|
||||||
// enable date controls
|
accessControlChanged(control: AccessControlItem, selectedItem: string) {
|
||||||
for (const control of this.accessControl.controls) {
|
const item = this.dropdownOptions
|
||||||
control.get('startDate').enable();
|
.find((x) => x.name === selectedItem);
|
||||||
control.get('endDate').enable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
control.startDate = null;
|
||||||
* Handle validation on form array changes.
|
control.endDate = null;
|
||||||
* This will be used to enable/disable date controls based on the selected item.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
private handleValidationOnFormArrayChanges() {
|
|
||||||
this.accessControl.valueChanges
|
|
||||||
.pipe(
|
|
||||||
distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),
|
|
||||||
takeUntil(this.destroy$)
|
|
||||||
)
|
|
||||||
.subscribe((value) => {
|
|
||||||
for (const [ index, controlValue ] of value.entries()) {
|
|
||||||
if (controlValue.itemName) {
|
|
||||||
const item = this.dropdownOptions.find((x) => x.name === controlValue.itemName);
|
|
||||||
const startDateCtrl = this.accessControl.controls[index].get('startDate');
|
|
||||||
const endDateCtrl = this.accessControl.controls[index].get('endDate');
|
|
||||||
|
|
||||||
if (item?.hasStartDate) {
|
control.hasStartDate = item?.hasStartDate || false;
|
||||||
startDateCtrl.enable({ emitEvent: false });
|
control.hasEndDate = item?.hasEndDate || false;
|
||||||
} else {
|
|
||||||
startDateCtrl.patchValue(null);
|
|
||||||
startDateCtrl.disable({ emitEvent: false });
|
|
||||||
}
|
|
||||||
if (item?.hasEndDate) {
|
|
||||||
endDateCtrl.enable({ emitEvent: false });
|
|
||||||
} else {
|
|
||||||
endDateCtrl.patchValue(null);
|
|
||||||
endDateCtrl.disable({ emitEvent: false });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
control.maxStartDate = item?.maxStartDate || null;
|
||||||
this.destroy$.next();
|
control.maxEndDate = item?.maxEndDate || null;
|
||||||
this.destroy$.complete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AccessControlItem {
|
||||||
|
itemName: string | null;
|
||||||
|
|
||||||
|
hasStartDate?: boolean;
|
||||||
|
startDate: string | null;
|
||||||
|
maxStartDate?: string | null;
|
||||||
|
|
||||||
|
hasEndDate?: boolean;
|
||||||
|
endDate: string | null;
|
||||||
|
maxEndDate?: string | null;
|
||||||
|
}
|
||||||
|
@@ -1,26 +0,0 @@
|
|||||||
import { Pipe, PipeTransform } from '@angular/core';
|
|
||||||
import { AbstractControl } from '@angular/forms';
|
|
||||||
import { NgbDateStruct } from '@ng-bootstrap/ng-bootstrap/datepicker/ngb-date-struct';
|
|
||||||
import { AccessesConditionOption } from '../../../core/config/models/config-accesses-conditions-options.model';
|
|
||||||
|
|
||||||
@Pipe({
|
|
||||||
// eslint-disable-next-line @angular-eslint/pipe-prefix
|
|
||||||
name: 'maxEndDate',
|
|
||||||
pure: false
|
|
||||||
})
|
|
||||||
export class ControlMaxEndDatePipe implements PipeTransform {
|
|
||||||
transform(control: AbstractControl, dropdownOptions: AccessesConditionOption[]): NgbDateStruct | null {
|
|
||||||
const { itemName } = control.value;
|
|
||||||
const item = dropdownOptions.find((x) => x.name === itemName);
|
|
||||||
if (!item?.hasEndDate) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const date = new Date(item.maxEndDate);
|
|
||||||
return {
|
|
||||||
year: date.getFullYear(),
|
|
||||||
month: date.getMonth() + 1,
|
|
||||||
day: date.getDate()
|
|
||||||
} as NgbDateStruct;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,27 +0,0 @@
|
|||||||
import { Pipe, PipeTransform } from '@angular/core';
|
|
||||||
import { AbstractControl } from '@angular/forms';
|
|
||||||
import { NgbDateStruct } from '@ng-bootstrap/ng-bootstrap/datepicker/ngb-date-struct';
|
|
||||||
import { AccessesConditionOption } from '../../../core/config/models/config-accesses-conditions-options.model';
|
|
||||||
|
|
||||||
|
|
||||||
@Pipe({
|
|
||||||
// eslint-disable-next-line @angular-eslint/pipe-prefix
|
|
||||||
name: 'maxStartDate',
|
|
||||||
pure: false
|
|
||||||
})
|
|
||||||
export class ControlMaxStartDatePipe implements PipeTransform {
|
|
||||||
transform(control: AbstractControl, dropdownOptions: AccessesConditionOption[]): NgbDateStruct | null {
|
|
||||||
const { itemName } = control.value;
|
|
||||||
const item = dropdownOptions.find((x) => x.name === itemName);
|
|
||||||
if (!item?.hasStartDate) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const date = new Date(item.maxStartDate);
|
|
||||||
return {
|
|
||||||
year: date.getFullYear(),
|
|
||||||
month: date.getMonth() + 1,
|
|
||||||
day: date.getDate()
|
|
||||||
} as NgbDateStruct;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -0,0 +1,23 @@
|
|||||||
|
import {Pipe, PipeTransform} from '@angular/core';
|
||||||
|
import {NgbDateStruct} from '@ng-bootstrap/ng-bootstrap/datepicker/ngb-date-struct';
|
||||||
|
|
||||||
|
@Pipe({
|
||||||
|
// eslint-disable-next-line @angular-eslint/pipe-prefix
|
||||||
|
name: 'toDate',
|
||||||
|
pure: false
|
||||||
|
})
|
||||||
|
export class ToDatePipe implements PipeTransform {
|
||||||
|
transform(dateValue: string | null): NgbDateStruct | null {
|
||||||
|
if (!dateValue) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const date = new Date(dateValue);
|
||||||
|
return {
|
||||||
|
year: date.getFullYear(),
|
||||||
|
month: date.getMonth() + 1,
|
||||||
|
day: date.getDate()
|
||||||
|
} as NgbDateStruct;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -53,6 +53,7 @@
|
|||||||
|
|
||||||
<ds-access-control-array-form
|
<ds-access-control-array-form
|
||||||
#itemAccessCmp
|
#itemAccessCmp
|
||||||
|
[type]="'item'"
|
||||||
[mode]="state.item.accessMode"
|
[mode]="state.item.accessMode"
|
||||||
[dropdownOptions]="(dropdownData$ | async)?.itemAccessConditionOptions || []">
|
[dropdownOptions]="(dropdownData$ | async)?.itemAccessConditionOptions || []">
|
||||||
</ds-access-control-array-form>
|
</ds-access-control-array-form>
|
||||||
@@ -141,6 +142,7 @@
|
|||||||
|
|
||||||
<ds-access-control-array-form
|
<ds-access-control-array-form
|
||||||
#bitstreamAccessCmp
|
#bitstreamAccessCmp
|
||||||
|
[type]="'bitstream'"
|
||||||
[mode]="state.bitstream.accessMode"
|
[mode]="state.bitstream.accessMode"
|
||||||
[dropdownOptions]="(dropdownData$ | async)?.bitstreamAccessConditionOptions || []">
|
[dropdownOptions]="(dropdownData$ | async)?.bitstreamAccessConditionOptions || []">
|
||||||
</ds-access-control-array-form>
|
</ds-access-control-array-form>
|
||||||
@@ -152,7 +154,7 @@
|
|||||||
|
|
||||||
<div *ngIf="showSubmit" class="d-flex justify-content-end">
|
<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()">
|
||||||
{{ 'access-control-reset' | translate }}
|
{{ 'access-control-cancel' | translate }}
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-primary"
|
<button class="btn btn-primary"
|
||||||
[disabled]="!state.item.toggleStatus && !state.bitstream.toggleStatus"
|
[disabled]="!state.item.toggleStatus && !state.bitstream.toggleStatus"
|
||||||
|
@@ -1,35 +1,31 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import {NgModule} from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import {CommonModule} from '@angular/common';
|
||||||
|
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import {TranslateModule} from '@ngx-translate/core';
|
||||||
import { UiSwitchModule } from 'ngx-ui-switch';
|
import {UiSwitchModule} from 'ngx-ui-switch';
|
||||||
|
|
||||||
import {
|
import {AccessControlArrayFormComponent} from './access-control-array-form/access-control-array-form.component';
|
||||||
AccessControlArrayFormComponent
|
import {SharedModule} from '../shared.module';
|
||||||
} from './access-control-array-form/access-control-array-form.component';
|
|
||||||
import { SharedModule } from '../shared.module';
|
|
||||||
import {
|
import {
|
||||||
ItemAccessControlSelectBitstreamsModalComponent
|
ItemAccessControlSelectBitstreamsModalComponent
|
||||||
} from './item-access-control-select-bitstreams-modal/item-access-control-select-bitstreams-modal.component';
|
} from './item-access-control-select-bitstreams-modal/item-access-control-select-bitstreams-modal.component';
|
||||||
import { AccessControlFormContainerComponent } from './access-control-form-container.component';
|
import {AccessControlFormContainerComponent} from './access-control-form-container.component';
|
||||||
import { ControlMaxStartDatePipe } from './access-control-array-form/control-max-start-date.pipe';
|
import {NgbDatepickerModule} from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { ControlMaxEndDatePipe } from './access-control-array-form/control-max-end-date.pipe';
|
import {ToDatePipe} from './access-control-array-form/to-date.pipe';
|
||||||
import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
SharedModule,
|
SharedModule,
|
||||||
TranslateModule,
|
TranslateModule,
|
||||||
UiSwitchModule,
|
UiSwitchModule,
|
||||||
NgbDatepickerModule
|
NgbDatepickerModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AccessControlFormContainerComponent,
|
AccessControlFormContainerComponent,
|
||||||
AccessControlArrayFormComponent,
|
AccessControlArrayFormComponent,
|
||||||
ItemAccessControlSelectBitstreamsModalComponent,
|
ItemAccessControlSelectBitstreamsModalComponent,
|
||||||
ControlMaxStartDatePipe,
|
ToDatePipe
|
||||||
ControlMaxEndDatePipe
|
|
||||||
],
|
],
|
||||||
exports: [ AccessControlFormContainerComponent, AccessControlArrayFormComponent ],
|
exports: [ AccessControlFormContainerComponent, AccessControlArrayFormComponent ],
|
||||||
})
|
})
|
||||||
|
@@ -227,17 +227,17 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
"admin.access-control.bulk-access": "Bulk access",
|
"admin.access-control.bulk-access": "Bulk Access Management",
|
||||||
|
|
||||||
"admin.access-control.bulk-access.title": "Bulk Access",
|
"admin.access-control.bulk-access.title": "Bulk Access Management",
|
||||||
|
|
||||||
"admin.access-control.bulk-access-browse.header": "Step 1: select objects",
|
"admin.access-control.bulk-access-browse.header": "Step 1: Select Objects",
|
||||||
|
|
||||||
"admin.access-control.bulk-access-browse.search.header": "Search",
|
"admin.access-control.bulk-access-browse.search.header": "Search",
|
||||||
|
|
||||||
"admin.access-control.bulk-access-browse.selected.header": "Current selection({{number}})",
|
"admin.access-control.bulk-access-browse.selected.header": "Current selection({{number}})",
|
||||||
|
|
||||||
"admin.access-control.bulk-access-settings.header": "Step 2: operation to perform",
|
"admin.access-control.bulk-access-settings.header": "Step 2: Operation to Perform",
|
||||||
|
|
||||||
"admin.access-control.epeople.actions.delete": "Delete EPerson",
|
"admin.access-control.epeople.actions.delete": "Delete EPerson",
|
||||||
|
|
||||||
@@ -2903,7 +2903,7 @@
|
|||||||
|
|
||||||
"menu.section.access_control_authorizations": "Authorizations",
|
"menu.section.access_control_authorizations": "Authorizations",
|
||||||
|
|
||||||
"menu.section.access_control_bulk": "Bulk access",
|
"menu.section.access_control_bulk": "Bulk Access Management",
|
||||||
|
|
||||||
"menu.section.access_control_groups": "Groups",
|
"menu.section.access_control_groups": "Groups",
|
||||||
|
|
||||||
@@ -5357,11 +5357,11 @@
|
|||||||
|
|
||||||
"admin.system-wide-alert.title": "System-wide Alerts",
|
"admin.system-wide-alert.title": "System-wide Alerts",
|
||||||
|
|
||||||
"item-access-control-title": "This form allows you to perform changes to the access condition of all the item's metadata and all its bitstreams.",
|
"item-access-control-title": "This form allows you to perform changes to the access conditions of the item's metadata or its bitstreams.",
|
||||||
|
|
||||||
"collection-access-control-title": "This form allows you to perform changes to the access condition of all the items owned by collection under this community. Changes can be performed on the access condition for the metadata (item) or for the content (bitstream).",
|
"collection-access-control-title": "This form allows you to perform changes to the access conditions of all the items owned by this collection. Changes may be performed to either all Item metadata or all content (bitstreams).",
|
||||||
|
|
||||||
"community-access-control-title": "This form allows you to perform changes to the access condition of all the items owned by collection under this community. Changes can be performed on the access condition for the metadata (item) or for the content (bitstream).",
|
"community-access-control-title": "This form allows you to perform changes to the access conditions of all the items owned by any collection under this community. Changes may be performed to either all Item metadata or all content (bitstreams).",
|
||||||
|
|
||||||
"access-control-item-header-toggle": "Item's Metadata",
|
"access-control-item-header-toggle": "Item's Metadata",
|
||||||
|
|
||||||
@@ -5371,7 +5371,7 @@
|
|||||||
|
|
||||||
"access-control-access-conditions": "Access conditions",
|
"access-control-access-conditions": "Access conditions",
|
||||||
|
|
||||||
"access-control-no-access-conditions-warning-message": "You have not specified any access conditions, the new items access conditions will be inherited from the owning collection.",
|
"access-control-no-access-conditions-warning-message": "Currently, no access conditions are specified below. If executed, this will replace the current access conditions with the default access conditions inherited from the owning collection.",
|
||||||
|
|
||||||
"access-control-replace-all": "Replace access conditions",
|
"access-control-replace-all": "Replace access conditions",
|
||||||
|
|
||||||
@@ -5379,11 +5379,11 @@
|
|||||||
|
|
||||||
"access-control-limit-to-specific": "Limit the changes to specific bitstreams",
|
"access-control-limit-to-specific": "Limit the changes to specific bitstreams",
|
||||||
|
|
||||||
"access-control-process-all-bitstreams": "process all the bitstreams in the item",
|
"access-control-process-all-bitstreams": "Update all the bitstreams in the item",
|
||||||
|
|
||||||
"access-control-bitstreams-selected": "bitstreams selected",
|
"access-control-bitstreams-selected": "bitstreams selected",
|
||||||
|
|
||||||
"access-control-reset": "Reset",
|
"access-control-cancel": "Cancel",
|
||||||
|
|
||||||
"access-control-execute": "Execute",
|
"access-control-execute": "Execute",
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user