9 } from '@angular/core';
10 import { BehaviorSubject, Observable, of } from 'rxjs';
11 import { catchError, switchMap, tap } from 'rxjs/operators';
12 import { CephfsSubvolumeService } from '~/app/shared/api/cephfs-subvolume.service';
13 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
14 import { CellTemplate } from '~/app/shared/enum/cell-template.enum';
15 import { Icons } from '~/app/shared/enum/icons.enum';
16 import { CdTableAction } from '~/app/shared/models/cd-table-action';
17 import { CdTableColumn } from '~/app/shared/models/cd-table-column';
18 import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context';
19 import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
20 import { CephfsSubvolume } from '~/app/shared/models/cephfs-subvolume.model';
21 import { CephfsSubvolumeFormComponent } from '../cephfs-subvolume-form/cephfs-subvolume-form.component';
22 import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
23 import { Permissions } from '~/app/shared/models/permissions';
24 import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
25 import { FinishedTask } from '~/app/shared/models/finished-task';
26 import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
27 import { FormControl } from '@angular/forms';
28 import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
29 import { CdForm } from '~/app/shared/forms/cd-form';
30 import { DeleteConfirmationModalComponent } from '~/app/shared/components/delete-confirmation-modal/delete-confirmation-modal.component';
31 import { CephfsSubvolumeGroupService } from '~/app/shared/api/cephfs-subvolume-group.service';
32 import { CephfsSubvolumeGroup } from '~/app/shared/models/cephfs-subvolume-group.model';
33 import { CephfsMountDetailsComponent } from '../cephfs-mount-details/cephfs-mount-details.component';
34 import { HealthService } from '~/app/shared/api/health.service';
35 import _ from 'lodash';
36 import { ModalCdsService } from '~/app/shared/services/modal-cds.service';
37 import { DEFAULT_SUBVOLUME_GROUP } from '~/app/shared/constants/cephfs.constant';
38 import { DeletionImpact } from '~/app/shared/enum/delete-confirmation-modal-impact.enum';
41 selector: 'cd-cephfs-subvolume-list',
42 templateUrl: './cephfs-subvolume-list.component.html',
43 styleUrls: ['./cephfs-subvolume-list.component.scss']
45 export class CephfsSubvolumeListComponent extends CdForm implements OnInit, OnChanges {
46 @ViewChild('quotaUsageTpl', { static: true })
49 @ViewChild('typeTpl', { static: true })
52 @ViewChild('modeToHumanReadableTpl', { static: true })
53 modeToHumanReadableTpl: any;
55 @ViewChild('nameTpl', { static: true })
58 @ViewChild('quotaSizeTpl', { static: true })
61 @ViewChild('removeTmpl', { static: true })
62 removeTmpl: TemplateRef<any>;
64 @Input() fsName: string;
65 @Input() pools: any[];
67 columns: CdTableColumn[] = [];
68 tableActions: CdTableAction[];
69 context: CdTableFetchDataContext;
70 selection = new CdTableSelection();
71 removeForm: CdFormGroup;
73 permissions: Permissions;
74 modalRef: NgbModalRef;
75 errorMessage: string = '';
76 selectedName: string = '';
78 subVolumes$: Observable<CephfsSubvolume[]>;
79 subVolumeGroups$: Observable<CephfsSubvolumeGroup[]>;
80 subject = new BehaviorSubject<CephfsSubvolume[]>([]);
81 groupsSubject = new BehaviorSubject<CephfsSubvolume[]>([]);
83 subvolumeGroupList: string[] = [];
84 subVolumesList: CephfsSubvolume[] = [];
86 activeGroupName: string = '';
89 private cephfsSubVolumeService: CephfsSubvolumeService,
90 private actionLabels: ActionLabelsI18n,
91 private modalService: ModalCdsService,
92 private authStorageService: AuthStorageService,
93 private taskWrapper: TaskWrapperService,
94 private cephfsSubvolumeGroupService: CephfsSubvolumeGroupService,
95 private healthService: HealthService
98 this.permissions = this.authStorageService.getPermissions();
104 name: $localize`Name`,
107 cellTemplate: this.nameTpl
110 name: $localize`Data Pool`,
111 prop: 'info.data_pool',
113 cellTransformation: CellTemplate.badge,
114 customTemplateConfig: {
115 class: 'badge-background-primary'
119 name: $localize`Usage`,
120 prop: 'info.bytes_pcent',
122 cellTemplate: this.quotaUsageTpl,
123 cellClass: 'text-right'
126 name: $localize`Path`,
129 cellTransformation: CellTemplate.path
132 name: $localize`Mode`,
135 cellTemplate: this.modeToHumanReadableTpl
138 name: $localize`Created`,
139 prop: 'info.created_at',
141 cellTransformation: CellTemplate.timeAgo
145 this.tableActions = [
147 name: this.actionLabels.CREATE,
148 permission: 'create',
150 click: () => this.openModal()
153 name: this.actionLabels.EDIT,
154 permission: 'update',
156 click: () => this.openModal(true)
159 name: this.actionLabels.ATTACH,
162 disable: () => !this.selection?.hasSelection,
163 click: () => this.showAttachInfo()
166 name: this.actionLabels.NFS_EXPORT,
167 permission: 'create',
168 icon: Icons.nfsExport,
170 '/cephfs/nfs/create',
172 _.isEmpty(this.activeGroupName) ? DEFAULT_SUBVOLUME_GROUP : this.activeGroupName,
173 { subvolume: this.selection?.first()?.name }
175 disable: () => !this.selection?.hasSingleSelection
178 name: this.actionLabels.REMOVE,
179 permission: 'delete',
181 click: () => this.removeSubVolumeModal()
185 this.subVolumeGroups$ = this.groupsSubject.pipe(
187 this.cephfsSubvolumeGroupService.get(this.fsName, false).pipe(
189 this.subvolumeGroupList = groups.map((group) => group.name);
190 this.subvolumeGroupList.unshift('');
193 this.context.error();
202 this.subject.next([]);
205 ngOnChanges(changes: SimpleChanges) {
206 if (changes.fsName) {
207 this.subject.next([]);
208 this.groupsSubject.next([]);
212 updateSelection(selection: CdTableSelection) {
213 this.selection = selection;
217 const selectedSubVolume = this.selection?.selected?.[0];
219 this.healthService.getClusterFsid().subscribe({
220 next: (clusterId: string) => {
221 this.modalRef = this.modalService.show(CephfsMountDetailsComponent, {
222 onSubmit: () => this.modalRef.close(),
226 rootPath: selectedSubVolume.info.path
233 openModal(edit = false) {
234 this.modalService.show(CephfsSubvolumeFormComponent, {
236 subVolumeName: this.selection?.first()?.name,
237 subVolumeGroupName: this.activeGroupName,
243 removeSubVolumeModal() {
244 this.removeForm = new CdFormGroup({
245 retainSnapshots: new FormControl(false)
247 this.errorMessage = '';
248 this.selectedName = this.selection.first().name;
249 this.modalService.show(DeleteConfirmationModalComponent, {
250 impact: DeletionImpact.high,
251 actionDescription: 'remove',
252 itemNames: [this.selectedName],
253 itemDescription: 'Subvolume',
254 childFormGroup: this.removeForm,
255 childFormGroupTemplate: this.removeTmpl,
258 .wrapTaskAroundCall({
259 task: new FinishedTask('cephfs/subvolume/remove', { subVolumeName: this.selectedName }),
260 call: this.cephfsSubVolumeService.remove(
263 this.activeGroupName,
264 this.removeForm.getValue('retainSnapshots')
268 complete: () => this.modalService.dismissAll(),
270 this.modalRef.componentInstance.stopLoadingSpinner();
271 this.errorMessage = error.error.detail;
277 selectSubVolumeGroup(subVolumeGroupName: string) {
278 this.activeGroupName = subVolumeGroupName;
279 this.getSubVolumes();
283 this.subVolumes$ = this.subject.pipe(
285 this.cephfsSubVolumeService.get(this.fsName, this.activeGroupName).pipe(
287 this.context?.error();