1
0

Merge branch 'feature/CST-9636' of bitbucket.org:4Science/dspace-angular into feature/CST-9636

This commit is contained in:
Giuseppe Digilio
2023-05-09 18:25:18 +02:00
14 changed files with 229 additions and 10 deletions

View File

@@ -16,4 +16,5 @@ export enum Context {
AdminWorkflowSearch = 'adminWorkflowSearch',
SideBarSearchModal = 'sideBarSearchModal',
SideBarSearchModalCurrent = 'sideBarSearchModalCurrent',
Bitstream = 'bitstream',
}

View File

@@ -43,6 +43,10 @@ import {
AccessControlArrayFormModule
} from '../../shared/access-control-array-form/access-control-array-form.component';
import { UiSwitchModule } from 'ngx-ui-switch';
import {
ItemAccessControlSelectBitstreamsModalComponent
} from './item-access-control/item-access-control-select-bitstreams-modal/item-access-control-select-bitstreams-modal.component';
import { ResultsBackButtonModule } from '../../shared/results-back-button/results-back-button.module';
/**
@@ -62,6 +66,7 @@ import { UiSwitchModule } from 'ngx-ui-switch';
DsoSharedModule,
AccessControlArrayFormModule,
UiSwitchModule,
ResultsBackButtonModule,
],
declarations: [
EditItemPageComponent,
@@ -89,7 +94,8 @@ import { UiSwitchModule } from 'ngx-ui-switch';
ItemAuthorizationsComponent,
IdentifierDataComponent,
ItemRegisterDoiComponent,
ItemAccessControlComponent
ItemAccessControlComponent,
ItemAccessControlSelectBitstreamsModalComponent
],
providers: [
BundleDataService,

View File

@@ -0,0 +1,33 @@
<div class="modal-header">
<h4 class="modal-title">Hi there!</h4>
<button type="button" class="close" aria-label="Close"
(click)="activeModal.dismiss('Cross click')">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<ng-container *ngIf="data$ | async as data">
<ds-viewable-collection
*ngIf="data.payload.page.length > 0"
[config]="paginationConfig"
[context]="context"
[objects]="data"
[selectable]="true"
[selectionConfig]="{ repeatable: true, listId: LIST_ID }"
[showPaginator]="true"
(pageChange)="loadForPage($event)">
</ds-viewable-collection>
<div *ngIf="data && data.payload.page.length === 0"
class="alert alert-info w-100" role="alert">
{{'browse.empty' | translate}}
</div>
</ng-container>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-dark"
(click)="activeModal.close('Close click')">
Close
</button>
</div>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ItemAccessControlSelectBitstreamsModalComponent } from './item-access-control-select-bitstreams-modal.component';
describe('ItemAccessControlSelectBitstreamsModalComponent', () => {
let component: ItemAccessControlSelectBitstreamsModalComponent;
let fixture: ComponentFixture<ItemAccessControlSelectBitstreamsModalComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ItemAccessControlSelectBitstreamsModalComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ItemAccessControlSelectBitstreamsModalComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,62 @@
import { Component, Input, OnInit } from '@angular/core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { PaginationService } from '../../../../core/pagination/pagination.service';
import { TranslateService } from '@ngx-translate/core';
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
import { BehaviorSubject } from 'rxjs';
import { Item } from '../../../../core/shared/item.model';
import { getFirstCompletedRemoteData } from '../../../../core/shared/operators';
import { PaginatedList } from '../../../../core/data/paginated-list.model';
import { Bitstream } from '../../../../core/shared/bitstream.model';
import { RemoteData } from '../../../../core/data/remote-data';
import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model';
import { hasValue } from '../../../../shared/empty.util';
import { Context } from '../../../../core/shared/context.model';
export const ITEM_ACCESS_CONTROL_SELECT_BITSTREAMS_LIST_ID = 'item-access-control-select-bitstreams'
@Component({
selector: 'ds-item-access-control-select-bitstreams-modal',
templateUrl: './item-access-control-select-bitstreams-modal.component.html',
styleUrls: [ './item-access-control-select-bitstreams-modal.component.scss' ]
})
export class ItemAccessControlSelectBitstreamsModalComponent implements OnInit {
LIST_ID = ITEM_ACCESS_CONTROL_SELECT_BITSTREAMS_LIST_ID;
@Input() item!: Item;
@Input() selectedBitstreams: string[] = [];
data$ = new BehaviorSubject<RemoteData<PaginatedList<Bitstream>> | null>(null);
paginationConfig: PaginationComponentOptions;
pageSize = 5;
context: Context = Context.Bitstream;
constructor(
private bitstreamService: BitstreamDataService,
protected paginationService: PaginationService,
protected translateService: TranslateService,
public activeModal: NgbActiveModal
) { }
ngOnInit() {
this.loadForPage(1);
this.paginationConfig = new PaginationComponentOptions();
this.paginationConfig.id = 'iacsbm';
this.paginationConfig.currentPage = 1;
if (hasValue(this.pageSize)) {
this.paginationConfig.pageSize = this.pageSize;
}
}
loadForPage(page: number) {
this.bitstreamService.findAllByItemAndBundleName(this.item, 'ORIGINAL', { currentPage: page}, false)
.pipe(
getFirstCompletedRemoteData(),
)
.subscribe(this.data$);
}
}

View File

@@ -87,6 +87,14 @@
<label class="form-check-label" for="processSelected">
{{ state.bitstream.selectedBitstreams.length }}
{{'access-control-bitstreams-selected' | translate}}
<button
*ngIf="itemRD$ | async as itemRD"
[disabled]="!state.bitstream.toggleStatus && state.bitstream.changesLimit !== 'selected'"
(click)="openSelectBitstreamsModal(itemRD.payload)" class="btn btn-outline-dark" type="button">
<i class="fa fa-search"></i>
</button>
</label>
</div>
</div>

View File

@@ -1,22 +1,42 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import {
AccessControlArrayFormComponent
} from '../../../shared/access-control-array-form/access-control-array-form.component';
import { shareReplay } from 'rxjs';
import { concatMap, Observable, shareReplay } from 'rxjs';
import { ItemAccessControlService } from './item-access-control.service';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import {
ITEM_ACCESS_CONTROL_SELECT_BITSTREAMS_LIST_ID,
ItemAccessControlSelectBitstreamsModalComponent
} from './item-access-control-select-bitstreams-modal/item-access-control-select-bitstreams-modal.component';
import { map, take } from 'rxjs/operators';
import { getFirstSucceededRemoteData } from '../../../core/shared/operators';
import { RemoteData } from '../../../core/data/remote-data';
import { Item } from '../../../core/shared/item.model';
import { ActivatedRoute } from '@angular/router';
import { SelectableListService } from '../../../shared/object-list/selectable-list/selectable-list.service';
import { ListableObject } from '../../../shared/object-collection/shared/listable-object.model';
@Component({
selector: 'ds-item-access-control',
templateUrl: './item-access-control.component.html',
styleUrls: ['./item-access-control.component.scss'],
providers: [ItemAccessControlService]
styleUrls: [ './item-access-control.component.scss' ],
providers: [ ItemAccessControlService ]
})
export class ItemAccessControlComponent implements OnInit {
export class ItemAccessControlComponent implements OnInit, OnDestroy {
itemRD$: Observable<RemoteData<Item>>;
@ViewChild('bitstreamAccessCmp', { static: true }) bitstreamAccessCmp: AccessControlArrayFormComponent;
@ViewChild('itemAccessCmp', { static: true }) itemAccessCmp: AccessControlArrayFormComponent;
constructor(private itemAccessControlService: ItemAccessControlService) {}
constructor(
private itemAccessControlService: ItemAccessControlService,
private selectableListService: SelectableListService,
protected modalService: NgbModal,
private route: ActivatedRoute,
private cdr: ChangeDetectorRef
) {}
state = initialState;
@@ -25,7 +45,9 @@ export class ItemAccessControlComponent implements OnInit {
);
ngOnInit(): void {
this.itemRD$ = this.route.parent.parent.data.pipe(
map((data) => data.dso)
).pipe(getFirstSucceededRemoteData()) as Observable<RemoteData<Item>>;
}
reset() {
@@ -52,6 +74,24 @@ export class ItemAccessControlComponent implements OnInit {
active ? this.itemAccessCmp.enable() : this.itemAccessCmp.disable();
}
}
openSelectBitstreamsModal(item: Item) {
const ref = this.modalService.open(ItemAccessControlSelectBitstreamsModalComponent);
ref.componentInstance.selectedBitstreams = this.state.bitstream.selectedBitstreams;
ref.componentInstance.item = item;
ref.closed.pipe(
concatMap(() => this.selectableListService.getSelectableList(ITEM_ACCESS_CONTROL_SELECT_BITSTREAMS_LIST_ID)),
take(1)
).subscribe((list) => {
this.state.bitstream.selectedBitstreams = list.selection;
this.cdr.detectChanges();
});
}
ngOnDestroy(): void {
this.selectableListService.deselectAll(ITEM_ACCESS_CONTROL_SELECT_BITSTREAMS_LIST_ID);
}
}
const initialState = {
@@ -63,6 +103,6 @@ const initialState = {
toggleStatus: false,
accessMode: '',
changesLimit: '', // 'all' | 'selected'
selectedBitstreams: []
selectedBitstreams: [] as ListableObject[],
},
};

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BitstreamListItemComponent } from './bitstream-list-item.component';
describe('BitstreamListItemComponent', () => {
let component: BitstreamListItemComponent;
let fixture: ComponentFixture<BitstreamListItemComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ BitstreamListItemComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(BitstreamListItemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,17 @@
import { Component } from '@angular/core';
import { listableObjectComponent } from '../../object-collection/shared/listable-object/listable-object.decorator';
import { ViewMode } from '../../../core/shared/view-mode.model';
import {
AbstractListableElementComponent
} from '../../object-collection/shared/object-collection-element/abstract-listable-element.component';
import { Bitstream } from '../../../core/shared/bitstream.model';
import { Context } from '../../../core/shared/context.model';
@listableObjectComponent(Bitstream, ViewMode.ListElement, Context.Bitstream)
@Component({
selector: 'ds-bitstream-list-item',
template: ` {{object.name}} `,
styleUrls: ['./bitstream-list-item.component.scss']
})
export class BitstreamListItemComponent extends AbstractListableElementComponent<Bitstream>{}

View File

@@ -48,7 +48,7 @@ export class ThemedObjectListComponent extends ThemedComponent<ObjectListCompone
@Input() selectionConfig: { repeatable: boolean, listId: string };
/**
w /**
* The link type of the listable elements
*/
@Input() linkType: CollectionElementLinkType;

View File

@@ -271,6 +271,7 @@ import { GroupSearchBoxComponent } from './eperson-group-list/group-search-box/g
import {
ThemedItemPageTitleFieldComponent
} from '../item-page/simple/field-components/specific-field/title/themed-item-page-field.component';
import { BitstreamListItemComponent } from './object-list/bitstream-list-item/bitstream-list-item.component';
const MODULES = [
CommonModule,
@@ -395,6 +396,7 @@ const ENTRY_COMPONENTS = [
SearchResultGridElementComponent,
ItemListElementComponent,
ItemGridElementComponent,
BitstreamListItemComponent,
ItemSearchResultListElementComponent,
ItemSearchResultGridElementComponent,
BrowseEntryListElementComponent,