mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-09 19:13:08 +00:00

# Conflicts: # src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.spec.ts # src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts # src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts # src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.spec.ts # src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts # src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts # src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts # src/app/+admin/admin-import-metadata-page/metadata-import-page.component.ts # src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts # src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts # src/app/+admin/admin-search-page/admin-search-results/admin-search-result-grid-element/item-search-result/item-admin-search-result-grid-element.component.spec.ts # src/app/+admin/admin-search-page/admin-search-results/admin-search-result-list-element/item-search-result/item-admin-search-result-list-element.component.spec.ts # src/app/+bitstream-page/bitstream-page.resolver.ts # src/app/+bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts # src/app/+bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts # src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.ts # src/app/+collection-page/collection-page.component.ts # src/app/+collection-page/edit-collection-page/collection-roles/collection-roles.component.ts # src/app/+collection-page/edit-item-template-page/item-template-page.resolver.spec.ts # src/app/+collection-page/edit-item-template-page/item-template-page.resolver.ts # src/app/+item-page/edit-item-page/item-authorizations/item-authorizations.component.ts # src/app/+item-page/edit-item-page/item-bitstreams/item-bitstreams.component.spec.ts # src/app/+item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts # src/app/+item-page/edit-item-page/item-collection-mapper/item-collection-mapper.component.ts # src/app/+item-page/edit-item-page/item-private/item-private.component.ts # src/app/+item-page/edit-item-page/item-public/item-public.component.ts # src/app/+item-page/edit-item-page/item-reinstate/item-reinstate.component.ts # src/app/+item-page/edit-item-page/item-relationships/edit-relationship-list/edit-relationship-list.component.ts # src/app/+item-page/edit-item-page/item-relationships/item-relationships.component.ts # src/app/+item-page/edit-item-page/item-withdraw/item-withdraw.component.ts # src/app/+item-page/simple/item-types/shared/item-relationships-utils.ts # src/app/+my-dspace-page/collection-selector/collection-selector.component.spec.ts # src/app/+search-page/search-tracker.component.ts # src/app/app-routing.module.ts # src/app/community-list-page/community-list-service.ts # src/app/community-list-page/community-list.reducer.spec.ts # src/app/core/auth/auth-response-parsing.service.spec.ts # src/app/core/auth/auth.interceptor.spec.ts # src/app/core/browse/browse.service.spec.ts # src/app/core/browse/browse.service.ts # src/app/core/cache/builders/link.service.spec.ts # src/app/core/cache/builders/remote-data-build.service.ts # src/app/core/cache/object-cache.service.spec.ts # src/app/core/cache/response.models.ts # src/app/core/data/base-response-parsing.service.ts # src/app/core/data/bitstream-data.service.ts # src/app/core/data/bitstream-format-data.service.ts # src/app/core/data/bundle-data.service.spec.ts # src/app/core/data/bundle-data.service.ts # src/app/core/data/change-analyzer.ts # src/app/core/data/collection-data.service.spec.ts # src/app/core/data/collection-data.service.ts # src/app/core/data/comcol-data.service.spec.ts # src/app/core/data/comcol-data.service.ts # src/app/core/data/data.service.ts # src/app/core/data/entity-type-data.service.ts # src/app/core/data/entity-type.service.ts # src/app/core/data/feature-authorization/authorization-data.service.ts # src/app/core/data/feature-authorization/feature-data.service.ts # src/app/core/data/item-template-data.service.ts # src/app/core/data/license-data.service.ts # src/app/core/data/metadata-field-data.service.ts # src/app/core/data/processes/process-data.service.ts # src/app/core/data/processes/script-data.service.ts # src/app/core/data/relationship.service.spec.ts # src/app/core/data/relationship.service.ts # src/app/core/data/remote-data.ts # src/app/core/data/request.actions.ts # src/app/core/data/request.effects.ts # src/app/core/data/request.reducer.spec.ts # src/app/core/data/request.reducer.ts # src/app/core/data/request.service.spec.ts # src/app/core/data/request.service.ts # src/app/core/dspace-rest/dspace-rest.service.spec.ts # src/app/core/eperson/eperson-data.service.spec.ts # src/app/core/eperson/eperson-data.service.ts # src/app/core/eperson/group-data.service.spec.ts # src/app/core/eperson/group-data.service.ts # src/app/core/forward-client-ip/forward-client-ip.interceptor.spec.ts # src/app/core/index/index.reducer.ts # src/app/core/json-patch/json-patch-operations.service.spec.ts # src/app/core/json-patch/json-patch-operations.service.ts # src/app/core/locale/locale.interceptor.spec.ts # src/app/core/registry/registry.service.ts # src/app/core/resource-policy/resource-policy.service.ts # src/app/core/shared/operators.ts # src/app/core/shared/search/search.service.ts # src/app/core/submission/submission-object-data.service.ts # src/app/core/submission/submission-rest.service.ts # src/app/core/submission/vocabularies/vocabulary-entries-response-parsing.service.spec.ts # src/app/core/submission/vocabularies/vocabulary.service.spec.ts # src/app/core/submission/vocabularies/vocabulary.service.ts # src/app/core/submission/workflowitem-data.service.ts # src/app/core/tasks/tasks.service.ts # src/app/curation-form/curation-form.component.ts # src/app/process-page/process-page.resolver.ts # src/app/shared/collection-dropdown/collection-dropdown.component.spec.ts # src/app/shared/collection-dropdown/collection-dropdown.component.ts # src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.spec.ts # src/app/shared/comcol-forms/create-comcol-page/create-comcol-page.component.ts # src/app/shared/comcol-forms/edit-comcol-page/comcol-metadata/comcol-metadata.component.spec.ts # src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.spec.ts # src/app/shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role.component.ts # src/app/shared/dso-selector/dso-selector/dso-selector.component.ts # src/app/shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component.ts # src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.ts # src/app/shared/form/builder/form-builder.service.ts # src/app/shared/item/item-versions/item-versions.component.ts # src/app/shared/mocks/remote-data-build.service.mock.ts # src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts # src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.spec.ts # src/app/shared/object-select/collection-select/collection-select.component.spec.ts # src/app/shared/object-select/item-select/item-select.component.spec.ts # src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts # src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts # src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts # src/app/shared/search/search-query-response.model.ts # src/app/statistics/statistics.module.ts # src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.spec.ts # src/app/submission/sections/form/section-form.component.ts # src/app/submission/sections/upload/section-upload.component.spec.ts # src/app/submission/sections/upload/section-upload.component.ts # src/app/submission/submission.service.spec.ts # src/app/submission/submission.service.ts
241 lines
8.9 KiB
TypeScript
241 lines
8.9 KiB
TypeScript
import { Component, OnDestroy, OnInit } from '@angular/core';
|
|
import { FormBuilder } from '@angular/forms';
|
|
import { Router } from '@angular/router';
|
|
import { TranslateService } from '@ngx-translate/core';
|
|
import { BehaviorSubject, combineLatest as observableCombineLatest, Subscription, Observable, ObservedValueOf, of as observableOf } from 'rxjs';
|
|
import { filter } from 'rxjs/operators';
|
|
import { catchError, map, switchMap, take } from 'rxjs/operators';
|
|
import { DSpaceObjectDataService } from '../../../core/data/dspace-object-data.service';
|
|
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
|
|
import { FeatureID } from '../../../core/data/feature-authorization/feature-id';
|
|
import { PaginatedList, buildPaginatedList } from '../../../core/data/paginated-list.model';
|
|
import { RemoteData } from '../../../core/data/remote-data';
|
|
import { RequestService } from '../../../core/data/request.service';
|
|
import { EPersonDataService } from '../../../core/eperson/eperson-data.service';
|
|
import { GroupDataService } from '../../../core/eperson/group-data.service';
|
|
import { EPerson } from '../../../core/eperson/models/eperson.model';
|
|
import { GroupDtoModel } from '../../../core/eperson/models/group-dto.model';
|
|
import { Group } from '../../../core/eperson/models/group.model';
|
|
import { RouteService } from '../../../core/services/route.service';
|
|
import { DSpaceObject } from '../../../core/shared/dspace-object.model';
|
|
import {
|
|
getAllSucceededRemoteDataPayload,
|
|
getFirstCompletedRemoteData
|
|
} from '../../../core/shared/operators';
|
|
import { PageInfo } from '../../../core/shared/page-info.model';
|
|
import { hasValue } from '../../../shared/empty.util';
|
|
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
|
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
|
import { NoContent } from '../../../core/shared/NoContent.model';
|
|
|
|
@Component({
|
|
selector: 'ds-groups-registry',
|
|
templateUrl: './groups-registry.component.html',
|
|
})
|
|
/**
|
|
* A component used for managing all existing groups within the repository.
|
|
* The admin can create, edit or delete groups here.
|
|
*/
|
|
export class GroupsRegistryComponent implements OnInit, OnDestroy {
|
|
|
|
messagePrefix = 'admin.access-control.groups.';
|
|
|
|
/**
|
|
* Pagination config used to display the list of groups
|
|
*/
|
|
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
|
id: 'groups-list-pagination',
|
|
pageSize: 5,
|
|
currentPage: 1
|
|
});
|
|
|
|
/**
|
|
* A list of all the current Groups within the repository or the result of the search
|
|
*/
|
|
groups$: BehaviorSubject<RemoteData<PaginatedList<Group>>> = new BehaviorSubject<RemoteData<PaginatedList<Group>>>({} as any);
|
|
/**
|
|
* A BehaviorSubject with the list of GroupDtoModel objects made from the Groups in the repository or
|
|
* as the result of the search
|
|
*/
|
|
groupsDto$: BehaviorSubject<PaginatedList<GroupDtoModel>> = new BehaviorSubject<PaginatedList<GroupDtoModel>>({} as any);
|
|
|
|
/**
|
|
* An observable for the pageInfo, needed to pass to the pagination component
|
|
*/
|
|
pageInfoState$: BehaviorSubject<PageInfo> = new BehaviorSubject<PageInfo>(undefined);
|
|
|
|
// The search form
|
|
searchForm;
|
|
|
|
// Current search in groups registry
|
|
currentSearchQuery: string;
|
|
|
|
/**
|
|
* List of subscriptions
|
|
*/
|
|
subs: Subscription[] = [];
|
|
|
|
constructor(public groupService: GroupDataService,
|
|
private ePersonDataService: EPersonDataService,
|
|
private dSpaceObjectDataService: DSpaceObjectDataService,
|
|
private translateService: TranslateService,
|
|
private notificationsService: NotificationsService,
|
|
private formBuilder: FormBuilder,
|
|
protected routeService: RouteService,
|
|
private router: Router,
|
|
private authorizationService: AuthorizationDataService,
|
|
public requestService: RequestService) {
|
|
this.currentSearchQuery = '';
|
|
this.searchForm = this.formBuilder.group(({
|
|
query: this.currentSearchQuery,
|
|
}));
|
|
}
|
|
|
|
ngOnInit() {
|
|
this.search({ query: this.currentSearchQuery });
|
|
}
|
|
|
|
/**
|
|
* Event triggered when the user changes page
|
|
* @param event
|
|
*/
|
|
onPageChange(event) {
|
|
this.config.currentPage = event;
|
|
this.search({ query: this.currentSearchQuery });
|
|
}
|
|
|
|
/**
|
|
* Search in the groups (searches by group name and by uuid exact match)
|
|
* @param data Contains query param
|
|
*/
|
|
search(data: any) {
|
|
const query: string = data.query;
|
|
if (query != null && this.currentSearchQuery !== query) {
|
|
this.router.navigateByUrl(this.groupService.getGroupRegistryRouterLink());
|
|
this.currentSearchQuery = query;
|
|
this.config.currentPage = 1;
|
|
}
|
|
this.subs.push(this.groupService.searchGroups(this.currentSearchQuery.trim(), {
|
|
currentPage: this.config.currentPage,
|
|
elementsPerPage: this.config.pageSize
|
|
}).pipe(getFirstCompletedRemoteData())
|
|
.subscribe((groupsRD: RemoteData<PaginatedList<Group>>) => {
|
|
this.groups$.next(groupsRD);
|
|
this.pageInfoState$.next(groupsRD.payload.pageInfo);
|
|
}
|
|
));
|
|
|
|
this.subs.push(this.groups$.pipe(
|
|
getAllSucceededRemoteDataPayload(),
|
|
switchMap((groups: PaginatedList<Group>) => {
|
|
return observableCombineLatest(...groups.page.map((group: Group) => {
|
|
return observableCombineLatest(
|
|
this.authorizationService.isAuthorized(FeatureID.CanDelete, hasValue(group) ? group.self : undefined),
|
|
this.hasLinkedDSO(group),
|
|
(isAuthorized: ObservedValueOf<Observable<boolean>>, hasLinkedDSO: ObservedValueOf<Observable<boolean>>) => {
|
|
const groupDtoModel: GroupDtoModel = new GroupDtoModel();
|
|
groupDtoModel.ableToDelete = isAuthorized && !hasLinkedDSO;
|
|
groupDtoModel.group = group;
|
|
return groupDtoModel;
|
|
}
|
|
);
|
|
})).pipe(map((dtos: GroupDtoModel[]) => {
|
|
return buildPaginatedList(groups.pageInfo, dtos);
|
|
}));
|
|
})).subscribe((value: PaginatedList<GroupDtoModel>) => {
|
|
this.groupsDto$.next(value);
|
|
this.pageInfoState$.next(value.pageInfo);
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* Delete Group
|
|
*/
|
|
deleteGroup(group: Group) {
|
|
if (hasValue(group.id)) {
|
|
this.groupService.delete(group.id).pipe(getFirstCompletedRemoteData())
|
|
.subscribe((rd: RemoteData<NoContent>) => {
|
|
if (rd.hasSucceeded) {
|
|
this.notificationsService.success(this.translateService.get(this.messagePrefix + 'notification.deleted.success', { name: group.name }));
|
|
this.reset();
|
|
} else {
|
|
this.notificationsService.error(
|
|
this.translateService.get(this.messagePrefix + 'notification.deleted.failure.title', { name: group.name }),
|
|
this.translateService.get(this.messagePrefix + 'notification.deleted.failure.content', { cause: rd.errorMessage }));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This method will ensure that the page gets reset and that the cache is cleared
|
|
*/
|
|
reset() {
|
|
this.groupService.getBrowseEndpoint().pipe(
|
|
switchMap((href) => this.requestService.removeByHrefSubstring(href)),
|
|
filter((isCached) => isCached),
|
|
take(1)
|
|
).subscribe(() => {
|
|
this.cleanupSubscribes();
|
|
this.search({ query: this.currentSearchQuery });
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get the members (epersons embedded value of a group)
|
|
* @param group
|
|
*/
|
|
getMembers(group: Group): Observable<RemoteData<PaginatedList<EPerson>>> {
|
|
return this.ePersonDataService.findAllByHref(group._links.epersons.href);
|
|
}
|
|
|
|
/**
|
|
* Get the subgroups (groups embedded value of a group)
|
|
* @param group
|
|
*/
|
|
getSubgroups(group: Group): Observable<RemoteData<PaginatedList<Group>>> {
|
|
return this.groupService.findAllByHref(group._links.subgroups.href);
|
|
}
|
|
|
|
/**
|
|
* Check if group has a linked object (community or collection linked to a workflow group)
|
|
* @param group
|
|
*/
|
|
hasLinkedDSO(group: Group): Observable<boolean> {
|
|
return this.dSpaceObjectDataService.findByHref(group._links.object.href).pipe(
|
|
map((rd: RemoteData<DSpaceObject>) => hasValue(rd) && hasValue(rd.payload)),
|
|
catchError(() => observableOf(false)),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Reset all input-fields to be empty and search all search
|
|
*/
|
|
clearFormAndResetResult() {
|
|
this.searchForm.patchValue({
|
|
query: '',
|
|
});
|
|
this.search({ query: '' });
|
|
}
|
|
|
|
/**
|
|
* Extract optional UUID from a group name => To be resolved to community or collection with link
|
|
* (Or will be resolved in backend and added to group object, tbd) //TODO
|
|
* @param groupName
|
|
*/
|
|
getOptionalComColFromName(groupName: string): string {
|
|
return this.groupService.getUUIDFromString(groupName);
|
|
}
|
|
|
|
/**
|
|
* Unsub all subscriptions
|
|
*/
|
|
ngOnDestroy(): void {
|
|
this.cleanupSubscribes();
|
|
}
|
|
|
|
cleanupSubscribes() {
|
|
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
|
|
}
|
|
}
|