1 import { Component, Input, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
2 import { ActivatedRoute, Router } from '@angular/router';
3 import { NvmeofService, GroupsComboboxItem } from '~/app/shared/api/nvmeof.service';
4 import { DeleteConfirmationModalComponent } from '~/app/shared/components/delete-confirmation-modal/delete-confirmation-modal.component';
5 import { ActionLabelsI18n, URLVerbs } from '~/app/shared/constants/app.constants';
6 import { DeletionImpact } from '~/app/shared/enum/delete-confirmation-modal-impact.enum';
7 import { Icons } from '~/app/shared/enum/icons.enum';
8 import { CdTableAction } from '~/app/shared/models/cd-table-action';
9 import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
10 import { FinishedTask } from '~/app/shared/models/finished-task';
11 import { NvmeofSubsystemNamespace } from '~/app/shared/models/nvmeof';
12 import { Permission } from '~/app/shared/models/permissions';
13 import { CephServiceSpec } from '~/app/shared/models/service.interface';
14 import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe';
15 import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
16 import { ModalCdsService } from '~/app/shared/services/modal-cds.service';
17 import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
18 import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
19 import { catchError, map, switchMap, takeUntil } from 'rxjs/operators';
21 const BASE_URL = 'block/nvmeof/subsystems';
22 const DEFAULT_PLACEHOLDER = $localize`Enter group name`;
25 selector: 'cd-nvmeof-namespaces-list',
26 templateUrl: './nvmeof-namespaces-list.component.html',
27 styleUrls: ['./nvmeof-namespaces-list.component.scss'],
30 export class NvmeofNamespacesListComponent implements OnInit, OnDestroy {
35 @ViewChild('deleteTpl', { static: true })
36 deleteTpl: TemplateRef<any>;
37 namespacesColumns: any;
38 tableActions: CdTableAction[];
39 selection = new CdTableSelection();
40 permission: Permission;
41 namespaces$: Observable<NvmeofSubsystemNamespace[]>;
42 private namespaceSubject = new BehaviorSubject<void>(undefined);
44 // Gateway group dropdown properties
45 gwGroups: GroupsComboboxItem[] = [];
46 gwGroupsEmpty: boolean = false;
47 gwGroupPlaceholder: string = DEFAULT_PLACEHOLDER;
49 private destroy$ = new Subject<void>();
52 public actionLabels: ActionLabelsI18n,
53 private router: Router,
54 private route: ActivatedRoute,
55 private modalService: ModalCdsService,
56 private authStorageService: AuthStorageService,
57 private taskWrapper: TaskWrapperService,
58 private nvmeofService: NvmeofService,
59 private dimlessBinaryPipe: DimlessBinaryPipe
61 this.permission = this.authStorageService.getPermissions().nvmeof;
65 this.route.queryParams.pipe(takeUntil(this.destroy$)).subscribe((params) => {
66 if (params?.['group']) this.onGroupSelection({ content: params?.['group'] });
68 this.setGatewayGroups();
69 this.namespacesColumns = [
71 name: $localize`Namespace ID`,
75 name: $localize`Size`,
76 prop: 'rbd_image_size',
77 pipe: this.dimlessBinaryPipe
80 name: $localize`Pool`,
84 name: $localize`Image`,
85 prop: 'rbd_image_name'
88 name: $localize`Subsystem`,
89 prop: 'ns_subsystem_nqn'
94 name: this.actionLabels.CREATE,
99 [BASE_URL, { outlets: { modal: [URLVerbs.CREATE, this.subsystemNQN, 'namespace'] } }],
100 { queryParams: { group: this.group } }
102 canBePrimary: (selection: CdTableSelection) => !selection.hasSelection,
103 disable: () => !this.group
106 name: this.actionLabels.EDIT,
107 permission: 'update',
110 this.router.navigate(
119 this.selection.first().nsid
124 { queryParams: { group: this.group } }
128 name: this.actionLabels.DELETE,
129 permission: 'delete',
131 click: () => this.deleteNamespaceModal()
135 this.namespaces$ = this.namespaceSubject.pipe(
140 return this.nvmeofService.listNamespaces(this.group).pipe(
141 map((res: NvmeofSubsystemNamespace[] | { namespaces: NvmeofSubsystemNamespace[] }) => {
142 return Array.isArray(res) ? res : res.namespaces || [];
144 catchError(() => of([]))
147 takeUntil(this.destroy$)
151 updateSelection(selection: CdTableSelection) {
152 this.selection = selection;
156 this.namespaceSubject.next();
160 this.namespaceSubject.next();
163 // Gateway groups methods
164 onGroupSelection(selected: GroupsComboboxItem) {
165 selected.selected = true;
166 this.group = selected.content;
167 this.listNamespaces();
172 this.listNamespaces();
178 .pipe(takeUntil(this.destroy$))
180 next: (response: CephServiceSpec[][]) => this.handleGatewayGroupsSuccess(response),
181 error: (error) => this.handleGatewayGroupsError(error)
185 handleGatewayGroupsSuccess(response: CephServiceSpec[][]) {
186 if (response?.[0]?.length) {
187 this.gwGroups = this.nvmeofService.formatGwGroupsList(response);
191 this.updateGroupSelectionState();
194 updateGroupSelectionState() {
195 if (!this.group && this.gwGroups.length) {
196 this.onGroupSelection(this.gwGroups[0]);
197 this.gwGroupsEmpty = false;
198 this.gwGroupPlaceholder = DEFAULT_PLACEHOLDER;
199 } else if (!this.gwGroups.length) {
200 this.gwGroupsEmpty = true;
201 this.gwGroupPlaceholder = $localize`No groups available`;
205 handleGatewayGroupsError(error: any) {
207 this.gwGroupsEmpty = true;
208 this.gwGroupPlaceholder = $localize`Unable to fetch Gateway groups`;
209 if (error?.preventDefault) {
210 error?.preventDefault?.();
214 deleteNamespaceModal() {
215 const namespace = this.selection.first();
216 const subsystemNqn = namespace.ns_subsystem_nqn;
217 this.modalService.show(DeleteConfirmationModalComponent, {
218 itemDescription: $localize`Namespace`,
219 impact: DeletionImpact.high,
220 bodyTemplate: this.deleteTpl,
221 itemNames: [namespace.nsid],
222 actionDescription: 'delete',
224 deletionMessage: $localize`Deleting the namespace <strong>${namespace.nsid}</strong> will permanently remove all resources, services, and configurations within it. This action cannot be undone.`
226 submitActionObservable: () =>
227 this.taskWrapper.wrapTaskAroundCall({
228 task: new FinishedTask('nvmeof/namespace/delete', {
232 call: this.nvmeofService.deleteNamespace(subsystemNqn, namespace.nsid, this.group)
238 this.destroy$.next();
239 this.destroy$.complete();