UI: Add resources in use dialog with force to delete
This commit is contained in:
parent
cd6063fd09
commit
caf9063638
@ -22,7 +22,13 @@ import {
|
||||
EntityTableConfig
|
||||
} from '@home/models/entity/entities-table-config.models';
|
||||
import { Router } from '@angular/router';
|
||||
import { Resource, ResourceInfo, ResourceType, ResourceTypeTranslationMap } from '@shared/models/resource.models';
|
||||
import {
|
||||
Resource,
|
||||
ResourceInfo, ResourceInfoWithReferences,
|
||||
ResourceType,
|
||||
ResourceTypeTranslationMap,
|
||||
toResourceDeleteResult
|
||||
} from '@shared/models/resource.models';
|
||||
import { EntityType, entityTypeResources, entityTypeTranslations } from '@shared/models/entity-type.models';
|
||||
import { NULL_UUID } from '@shared/models/id/has-uuid';
|
||||
import { DatePipe } from '@angular/common';
|
||||
@ -35,9 +41,19 @@ import { Authority } from '@shared/models/authority.enum';
|
||||
import { ResourcesLibraryComponent } from '@home/components/resources/resources-library.component';
|
||||
import { PageLink } from '@shared/models/page/page-link';
|
||||
import { EntityAction } from '@home/models/entity/entity-component.models';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
import { ResourcesTableHeaderComponent } from '@home/pages/admin/resource/resources-table-header.component';
|
||||
import { ResourceLibraryTabsComponent } from '@home/pages/admin/resource/resource-library-tabs.component';
|
||||
import { forkJoin, of } from "rxjs";
|
||||
import {
|
||||
ResourcesInUseDialogComponent,
|
||||
ResourcesInUseDialogData
|
||||
} from "@shared/components/resource/resources-in-use-dialog.component";
|
||||
import { parseHttpErrorMessage } from "@core/utils";
|
||||
import { ActionNotificationShow } from "@core/notification/notification.actions";
|
||||
import { ResourcesDatasource } from "@home/pages/admin/resource/resources-datasource";
|
||||
import { MatDialog } from "@angular/material/dialog";
|
||||
import { DialogService } from "@core/services/dialog.service";
|
||||
|
||||
@Injectable()
|
||||
export class ResourcesLibraryTableConfigResolver {
|
||||
@ -49,6 +65,8 @@ export class ResourcesLibraryTableConfigResolver {
|
||||
private resourceService: ResourceService,
|
||||
private translate: TranslateService,
|
||||
private router: Router,
|
||||
private dialog: MatDialog,
|
||||
private dialogService: DialogService,
|
||||
private datePipe: DatePipe) {
|
||||
|
||||
this.config.entityType = EntityType.TB_RESOURCE;
|
||||
@ -76,19 +94,27 @@ export class ResourcesLibraryTableConfigResolver {
|
||||
icon: 'file_download',
|
||||
isEnabled: () => true,
|
||||
onAction: ($event, entity) => this.downloadResource($event, entity)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: this.translate.instant('resource.delete'),
|
||||
icon: 'delete',
|
||||
isEnabled: (resource) => this.config.deleteEnabled(resource),
|
||||
onAction: ($event, entity) => this.deleteResource($event, entity)
|
||||
},
|
||||
);
|
||||
|
||||
this.config.deleteEntityTitle = resource => this.translate.instant('resource.delete-resource-title',
|
||||
{ resourceTitle: resource.title });
|
||||
this.config.deleteEntityContent = () => this.translate.instant('resource.delete-resource-text');
|
||||
this.config.deleteEntitiesTitle = count => this.translate.instant('resource.delete-resources-title', {count});
|
||||
this.config.deleteEntitiesContent = () => this.translate.instant('resource.delete-resources-text');
|
||||
this.config.groupActionDescriptors = [{
|
||||
name: this.translate.instant('action.delete'),
|
||||
icon: 'delete',
|
||||
isEnabled: true,
|
||||
onAction: ($event, entities) => this.deleteResources($event, entities)
|
||||
}];
|
||||
|
||||
this.config.entitiesDeleteEnabled = false;
|
||||
|
||||
this.config.entitiesFetchFunction = pageLink => this.resourceService.getResources(pageLink, this.config.componentsData.resourceType);
|
||||
this.config.loadEntity = id => this.resourceService.getResourceInfoById(id.id);
|
||||
this.config.saveEntity = resource => this.saveResource(resource);
|
||||
this.config.deleteEntity = id => this.resourceService.deleteResource(id.id);
|
||||
|
||||
this.config.onEntityAction = action => this.onResourceAction(action);
|
||||
}
|
||||
@ -147,6 +173,8 @@ export class ResourcesLibraryTableConfigResolver {
|
||||
case 'downloadResource':
|
||||
this.downloadResource(action.event, action.entity);
|
||||
return true;
|
||||
case 'deleteLibrary':
|
||||
this.deleteResource(action.event, action.entity);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -165,4 +193,138 @@ export class ResourcesLibraryTableConfigResolver {
|
||||
return authority === Authority.SYS_ADMIN;
|
||||
}
|
||||
}
|
||||
|
||||
private deleteResource($event: Event, resource: ResourceInfo) {
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
}
|
||||
this.dialogService.confirm(
|
||||
this.translate.instant('resource.delete-resource-title', { resourceTitle: resource.title }),
|
||||
this.translate.instant('resource.delete-resource-text'),
|
||||
this.translate.instant('action.no'),
|
||||
this.translate.instant('action.yes'),
|
||||
true
|
||||
).subscribe((result) => {
|
||||
if (result) {
|
||||
this.resourceService.deleteResource(resource.id.id, false, {ignoreErrors: true}).pipe(
|
||||
map(() => toResourceDeleteResult(resource)),
|
||||
catchError((err) => of(toResourceDeleteResult(resource, err)))
|
||||
).subscribe(
|
||||
(deleteResult) => {
|
||||
if (deleteResult.success) {
|
||||
if (this.config.getEntityDetailsPage()) {
|
||||
this.config.getEntityDetailsPage().goBack();
|
||||
} else {
|
||||
this.config.updateData(true);
|
||||
}
|
||||
} else if (deleteResult.resourceIsReferencedError) {
|
||||
const resources: ResourceInfoWithReferences[] = [{...resource, ...{references: deleteResult.references}}];
|
||||
const data = {
|
||||
multiple: false,
|
||||
resources,
|
||||
configuration: {
|
||||
title: 'resource.resource-is-in-use',
|
||||
message: this.translate.instant('resource.resource-is-in-use-text', {title: resources[0].title}),
|
||||
deleteText: 'resource.delete-resource-in-use-text',
|
||||
selectedText: 'resource.selected-resources',
|
||||
columns: ['select', 'title', 'references']
|
||||
}
|
||||
};
|
||||
this.dialog.open<ResourcesInUseDialogComponent, ResourcesInUseDialogData,
|
||||
ResourceInfo[]>(ResourcesInUseDialogComponent, {
|
||||
disableClose: true,
|
||||
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
|
||||
data
|
||||
}).afterClosed().subscribe((resources) => {
|
||||
if (resources) {
|
||||
this.resourceService.deleteResource(resource.id.id, true).subscribe(() => {
|
||||
if (this.config.getEntityDetailsPage()) {
|
||||
this.config.getEntityDetailsPage().goBack();
|
||||
} else {
|
||||
this.config.updateData(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const errorMessageWithTimeout = parseHttpErrorMessage(deleteResult.error, this.translate);
|
||||
setTimeout(() => {
|
||||
this.store.dispatch(new ActionNotificationShow({message: errorMessageWithTimeout.message, type: 'error'}));
|
||||
}, errorMessageWithTimeout.timeout);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private deleteResources($event: Event, resources: ResourceInfo[]) {
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
}
|
||||
if (resources && resources.length) {
|
||||
const title = this.translate.instant('resource.delete-resources-title', {count: resources.length});
|
||||
const content = this.translate.instant('resource.delete-resources-text');
|
||||
this.dialogService.confirm(title, content,
|
||||
this.translate.instant('action.no'),
|
||||
this.translate.instant('action.yes')).subscribe((result) => {
|
||||
if (result) {
|
||||
const tasks = resources.map((resource) =>
|
||||
this.resourceService.deleteResource(resource.id.id, false, {ignoreErrors: true}).pipe(
|
||||
map(() => toResourceDeleteResult(resource)),
|
||||
catchError((err) => of(toResourceDeleteResult(resource, err)))
|
||||
)
|
||||
);
|
||||
forkJoin(tasks).subscribe(
|
||||
(deleteResults) => {
|
||||
const anySuccess = deleteResults.some(res => res.success);
|
||||
const referenceErrors = deleteResults.filter(res => res.resourceIsReferencedError);
|
||||
const otherError = deleteResults.find(res => !res.success);
|
||||
if (anySuccess) {
|
||||
this.config.updateData();
|
||||
}
|
||||
if (referenceErrors?.length) {
|
||||
const resourcesWithReferences: ResourceInfoWithReferences[] =
|
||||
referenceErrors.map(ref => ({...ref.resource, ...{references: ref.references}}));
|
||||
const data = {
|
||||
multiple: true,
|
||||
resources: resourcesWithReferences,
|
||||
configuration: {
|
||||
title: 'resource.resources-are-in-use',
|
||||
message: this.translate.instant('resource.resources-are-in-use-text'),
|
||||
deleteText: 'resource.delete-resource-in-use-text',
|
||||
selectedText: 'resource.selected-resources',
|
||||
datasource: new ResourcesDatasource(this.resourceService, resourcesWithReferences, () => true),
|
||||
columns: ['select', 'title', 'references']
|
||||
}
|
||||
};
|
||||
this.dialog.open<ResourcesInUseDialogComponent, ResourcesInUseDialogData,
|
||||
ResourceInfo[]>(ResourcesInUseDialogComponent, {
|
||||
disableClose: true,
|
||||
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
|
||||
data
|
||||
}).afterClosed().subscribe((forceDeleteResources) => {
|
||||
if (forceDeleteResources && forceDeleteResources.length) {
|
||||
const forceDeleteTasks = forceDeleteResources.map((resource) =>
|
||||
this.resourceService.deleteResource(resource.id.id, true)
|
||||
);
|
||||
forkJoin(forceDeleteTasks).subscribe(
|
||||
() => {
|
||||
this.config.updateData();
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
} else if (otherError) {
|
||||
const errorMessageWithTimeout = parseHttpErrorMessage(otherError.error, this.translate);
|
||||
setTimeout(() => {
|
||||
this.store.dispatch(new ActionNotificationShow({message: errorMessageWithTimeout.message, type: 'error'}));
|
||||
}, errorMessageWithTimeout.timeout);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4497,7 +4497,12 @@
|
||||
"scada-symbol": "Scada symbol",
|
||||
"extension": "Extension",
|
||||
"module": "Module"
|
||||
}
|
||||
},
|
||||
"resource-is-in-use": "Resource is used by other entities",
|
||||
"resources-are-in-use": "Resources are used by other entities",
|
||||
"resource-is-in-use-text": "The Resource <b>'{{title}}'</b> was not deleted because it is used by the following entities:",
|
||||
"resources-are-in-use-text": "Not all Resources have been deleted because they are used by other entities.</br>You can view referenced entities by clicking the <b>References</b> button in the corresponding resource row.</br>If you still want to delete these resources, select them in the table below and click the <b>Delete selected</b> button.",
|
||||
"delete-resource-in-use-text": "If you still want to delete the resource, click the <b>Delete anyway</b> button."
|
||||
},
|
||||
"javascript": {
|
||||
"add": "Add JavaScript resource",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user