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 { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-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';
40 selector: 'cd-cephfs-subvolume-list',
41 templateUrl: './cephfs-subvolume-list.component.html',
42 styleUrls: ['./cephfs-subvolume-list.component.scss']
44 export class CephfsSubvolumeListComponent extends CdForm implements OnInit, OnChanges {
45 @ViewChild('quotaUsageTpl', { static: true })
48 @ViewChild('typeTpl', { static: true })
51 @ViewChild('modeToHumanReadableTpl', { static: true })
52 modeToHumanReadableTpl: any;
54 @ViewChild('nameTpl', { static: true })
57 @ViewChild('quotaSizeTpl', { static: true })
60 @ViewChild('removeTmpl', { static: true })
61 removeTmpl: TemplateRef<any>;
63 @Input() fsName: string;
64 @Input() pools: any[];
66 columns: CdTableColumn[] = [];
67 tableActions: CdTableAction[];
68 context: CdTableFetchDataContext;
69 selection = new CdTableSelection();
70 removeForm: CdFormGroup;
72 permissions: Permissions;
73 modalRef: NgbModalRef;
74 errorMessage: string = '';
75 selectedName: string = '';
77 subVolumes$: Observable<CephfsSubvolume[]>;
78 subVolumeGroups$: Observable<CephfsSubvolumeGroup[]>;
79 subject = new BehaviorSubject<CephfsSubvolume[]>([]);
80 groupsSubject = new BehaviorSubject<CephfsSubvolume[]>([]);
82 subvolumeGroupList: string[] = [];
83 subVolumesList: CephfsSubvolume[] = [];
85 activeGroupName: string = '';
88 private cephfsSubVolumeService: CephfsSubvolumeService,
89 private actionLabels: ActionLabelsI18n,
90 private modalService: ModalCdsService,
91 private authStorageService: AuthStorageService,
92 private taskWrapper: TaskWrapperService,
93 private cephfsSubvolumeGroupService: CephfsSubvolumeGroupService,
94 private healthService: HealthService
97 this.permissions = this.authStorageService.getPermissions();
103 name: $localize`Name`,
106 cellTemplate: this.nameTpl
109 name: $localize`Data Pool`,
110 prop: 'info.data_pool',
112 cellTransformation: CellTemplate.badge,
113 customTemplateConfig: {
114 class: 'badge-background-primary'
118 name: $localize`Usage`,
119 prop: 'info.bytes_pcent',
121 cellTemplate: this.quotaUsageTpl,
122 cellClass: 'text-right'
125 name: $localize`Path`,
128 cellTransformation: CellTemplate.path
131 name: $localize`Mode`,
134 cellTemplate: this.modeToHumanReadableTpl
137 name: $localize`Created`,
138 prop: 'info.created_at',
140 cellTransformation: CellTemplate.timeAgo
144 this.tableActions = [
146 name: this.actionLabels.CREATE,
147 permission: 'create',
149 click: () => this.openModal()
152 name: this.actionLabels.EDIT,
153 permission: 'update',
155 click: () => this.openModal(true)
158 name: this.actionLabels.ATTACH,
161 disable: () => !this.selection?.hasSelection,
162 click: () => this.showAttachInfo()
165 name: this.actionLabels.NFS_EXPORT,
166 permission: 'create',
167 icon: Icons.nfsExport,
169 '/cephfs/nfs/create',
171 _.isEmpty(this.activeGroupName) ? DEFAULT_SUBVOLUME_GROUP : this.activeGroupName,
172 { subvolume: this.selection?.first()?.name }
174 disable: () => !this.selection?.hasSingleSelection
177 name: this.actionLabels.REMOVE,
178 permission: 'delete',
180 click: () => this.removeSubVolumeModal()
184 this.subVolumeGroups$ = this.groupsSubject.pipe(
186 this.cephfsSubvolumeGroupService.get(this.fsName, false).pipe(
188 this.subvolumeGroupList = groups.map((group) => group.name);
189 this.subvolumeGroupList.unshift('');
192 this.context.error();
201 this.subject.next([]);
204 ngOnChanges(changes: SimpleChanges) {
205 if (changes.fsName) {
206 this.subject.next([]);
207 this.groupsSubject.next([]);
211 updateSelection(selection: CdTableSelection) {
212 this.selection = selection;
216 const selectedSubVolume = this.selection?.selected?.[0];
218 this.healthService.getClusterFsid().subscribe({
219 next: (clusterId: string) => {
220 this.modalRef = this.modalService.show(CephfsMountDetailsComponent, {
221 onSubmit: () => this.modalRef.close(),
225 rootPath: selectedSubVolume.info.path
232 openModal(edit = false) {
233 this.modalService.show(CephfsSubvolumeFormComponent, {
235 subVolumeName: this.selection?.first()?.name,
236 subVolumeGroupName: this.activeGroupName,
242 removeSubVolumeModal() {
243 this.removeForm = new CdFormGroup({
244 retainSnapshots: new FormControl(false)
246 this.errorMessage = '';
247 this.selectedName = this.selection.first().name;
248 this.modalService.show(CriticalConfirmationModalComponent, {
249 actionDescription: 'Remove',
250 itemNames: [this.selectedName],
251 itemDescription: 'Subvolume',
252 childFormGroup: this.removeForm,
253 childFormGroupTemplate: this.removeTmpl,
256 .wrapTaskAroundCall({
257 task: new FinishedTask('cephfs/subvolume/remove', { subVolumeName: this.selectedName }),
258 call: this.cephfsSubVolumeService.remove(
261 this.activeGroupName,
262 this.removeForm.getValue('retainSnapshots')
266 complete: () => this.modalService.dismissAll(),
268 this.modalRef.componentInstance.stopLoadingSpinner();
269 this.errorMessage = error.error.detail;
275 selectSubVolumeGroup(subVolumeGroupName: string) {
276 this.activeGroupName = subVolumeGroupName;
277 this.getSubVolumes();
281 this.subVolumes$ = this.subject.pipe(
283 this.cephfsSubVolumeService.get(this.fsName, this.activeGroupName).pipe(
285 this.context?.error();