1 import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
2 import { BehaviorSubject, Observable, forkJoin, of } from 'rxjs';
3 import { catchError, shareReplay, switchMap, tap } from 'rxjs/operators';
4 import { CephfsSubvolumeGroupService } from '~/app/shared/api/cephfs-subvolume-group.service';
5 import { CephfsSubvolumeService } from '~/app/shared/api/cephfs-subvolume.service';
6 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
7 import { CellTemplate } from '~/app/shared/enum/cell-template.enum';
8 import { Icons } from '~/app/shared/enum/icons.enum';
9 import { CdTableAction } from '~/app/shared/models/cd-table-action';
10 import { CdTableColumn } from '~/app/shared/models/cd-table-column';
11 import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context';
12 import { CephfsSubvolume, SubvolumeSnapshot } from '~/app/shared/models/cephfs-subvolume.model';
13 import { CephfsSubvolumeSnapshotsFormComponent } from './cephfs-subvolume-snapshots-form/cephfs-subvolume-snapshots-form.component';
14 import { ModalService } from '~/app/shared/services/modal.service';
15 import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
16 import { Permissions } from '~/app/shared/models/permissions';
17 import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
18 import { CdDatePipe } from '~/app/shared/pipes/cd-date.pipe';
19 import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
20 import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
21 import { FinishedTask } from '~/app/shared/models/finished-task';
22 import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
25 selector: 'cd-cephfs-subvolume-snapshots-list',
26 templateUrl: './cephfs-subvolume-snapshots-list.component.html',
27 styleUrls: ['./cephfs-subvolume-snapshots-list.component.scss']
29 export class CephfsSubvolumeSnapshotsListComponent implements OnInit, OnChanges {
30 @Input() fsName: string;
32 context: CdTableFetchDataContext;
33 columns: CdTableColumn[] = [];
34 tableActions: CdTableAction[];
35 selection = new CdTableSelection();
36 permissions: Permissions;
37 modalRef: NgbModalRef;
39 subVolumes$: Observable<CephfsSubvolume[]>;
40 snapshots$: Observable<any[]>;
41 snapshotSubject = new BehaviorSubject<SubvolumeSnapshot[]>([]);
42 subVolumeSubject = new BehaviorSubject<CephfsSubvolume[]>([]);
44 subvolumeGroupList: string[] = [];
45 subVolumesList: string[];
48 activeSubVolumeName = '';
50 isSubVolumesAvailable = false;
53 observables: any = [];
56 private cephfsSubvolumeGroupService: CephfsSubvolumeGroupService,
57 private cephfsSubvolumeService: CephfsSubvolumeService,
58 private actionLabels: ActionLabelsI18n,
59 private modalService: ModalService,
60 private authStorageService: AuthStorageService,
61 private cdDatePipe: CdDatePipe,
62 private taskWrapper: TaskWrapperService
64 this.permissions = this.authStorageService.getPermissions();
70 name: $localize`Name`,
75 name: $localize`Created`,
76 prop: 'info.created_at',
81 name: $localize`Pending Clones`,
82 prop: 'info.has_pending_clones',
84 cellTransformation: CellTemplate.badge,
85 customTemplateConfig: {
87 no: { class: 'badge-success' },
88 yes: { class: 'badge-info' }
96 name: this.actionLabels.CREATE,
99 click: () => this.openModal()
102 name: this.actionLabels.REMOVE,
103 permission: 'delete',
105 click: () => this.deleteSnapshot()
109 this.cephfsSubvolumeGroupService
112 switchMap((groups) => {
113 // manually adding the group '_nogroup' to the list.
114 groups.unshift({ name: '' });
116 const observables = groups.map((group) =>
117 this.cephfsSubvolumeService.existsInFs(this.fsName, group.name).pipe(
118 switchMap((resp) => {
120 this.subvolumeGroupList.push(group.name);
122 return of(resp); // Emit the response
127 return forkJoin(observables);
131 if (this.subvolumeGroupList.length) {
132 this.isSubVolumesAvailable = true;
134 this.isLoading = false;
138 ngOnChanges(changes: SimpleChanges): void {
139 if (changes.fsName) {
140 this.subVolumeSubject.next([]);
144 selectSubVolumeGroup(subVolumeGroupName: string) {
145 this.activeGroupName = subVolumeGroupName;
146 this.getSubVolumes();
149 selectSubVolume(subVolumeName: string) {
150 this.activeSubVolumeName = subVolumeName;
151 this.getSubVolumesSnapshot();
155 this.subVolumes$ = this.subVolumeSubject.pipe(
157 this.cephfsSubvolumeService.get(this.fsName, this.activeGroupName, false).pipe(
159 this.subVolumesList = resp.map((subVolume) => subVolume.name);
160 this.activeSubVolumeName = resp[0].name;
161 this.getSubVolumesSnapshot();
168 getSubVolumesSnapshot() {
169 this.snapshots$ = this.snapshotSubject.pipe(
171 this.cephfsSubvolumeService
172 .getSnapshots(this.fsName, this.activeSubVolumeName, this.activeGroupName)
175 this.context.error();
185 this.snapshotSubject.next([]);
188 openModal(edit = false) {
189 this.modalService.show(
190 CephfsSubvolumeSnapshotsFormComponent,
193 subVolumeName: this.activeSubVolumeName,
194 subVolumeGroupName: this.activeGroupName,
195 subVolumeGroups: this.subvolumeGroupList,
202 updateSelection(selection: CdTableSelection) {
203 this.selection = selection;
207 const snapshotName = this.selection.first().name;
208 const subVolumeName = this.activeSubVolumeName;
209 const subVolumeGroupName = this.activeGroupName;
210 const fsName = this.fsName;
211 this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
212 actionDescription: 'Remove',
213 itemNames: [snapshotName],
214 itemDescription: 'Snapshot',
217 .wrapTaskAroundCall({
218 task: new FinishedTask('cephfs/subvolume/snapshot/delete', {
220 subVolumeName: subVolumeName,
221 subVolumeGroupName: subVolumeGroupName,
222 snapshotName: snapshotName
224 call: this.cephfsSubvolumeService.deleteSnapshot(
232 complete: () => this.modalRef.close(),
233 error: () => this.modalRef.componentInstance.stopLoadingSpinner()