]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.ts
import 15.2.4
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / nfs / nfs-list / nfs-list.component.ts
CommitLineData
11fdf7f2
TL
1import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
2
3import { I18n } from '@ngx-translate/i18n-polyfill';
4import * as _ from 'lodash';
5import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
6import { Subscription } from 'rxjs';
7
8import { NfsService } from '../../../shared/api/nfs.service';
e306af50 9import { ListWithDetails } from '../../../shared/classes/list-with-details.class';
11fdf7f2 10import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
eafe8130 11import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
11fdf7f2
TL
12import { TableComponent } from '../../../shared/datatable/table/table.component';
13import { CellTemplate } from '../../../shared/enum/cell-template.enum';
9f95a23c 14import { Icons } from '../../../shared/enum/icons.enum';
11fdf7f2
TL
15import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
16import { CdTableAction } from '../../../shared/models/cd-table-action';
17import { CdTableColumn } from '../../../shared/models/cd-table-column';
18import { CdTableSelection } from '../../../shared/models/cd-table-selection';
19import { FinishedTask } from '../../../shared/models/finished-task';
20import { Permission } from '../../../shared/models/permissions';
9f95a23c 21import { Task } from '../../../shared/models/task';
11fdf7f2
TL
22import { AuthStorageService } from '../../../shared/services/auth-storage.service';
23import { TaskListService } from '../../../shared/services/task-list.service';
24import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
25
26@Component({
27 selector: 'cd-nfs-list',
28 templateUrl: './nfs-list.component.html',
29 styleUrls: ['./nfs-list.component.scss'],
30 providers: [TaskListService]
31})
e306af50 32export class NfsListComponent extends ListWithDetails implements OnInit, OnDestroy {
9f95a23c 33 @ViewChild('nfsState', { static: false })
11fdf7f2 34 nfsState: TemplateRef<any>;
9f95a23c 35 @ViewChild('nfsFsal', { static: true })
11fdf7f2
TL
36 nfsFsal: TemplateRef<any>;
37
9f95a23c 38 @ViewChild('table', { static: true })
11fdf7f2
TL
39 table: TableComponent;
40
41 columns: CdTableColumn[];
42 permission: Permission;
43 selection = new CdTableSelection();
44 summaryDataSubscription: Subscription;
45 viewCacheStatus: any;
46 exports: any[];
47 tableActions: CdTableAction[];
48 isDefaultCluster = false;
49
50 modalRef: BsModalRef;
51
52 builders = {
9f95a23c 53 'nfs/create': (metadata: any) => {
11fdf7f2
TL
54 return {
55 path: metadata['path'],
56 cluster_id: metadata['cluster_id'],
57 fsal: metadata['fsal']
58 };
59 }
60 };
61
62 constructor(
63 private authStorageService: AuthStorageService,
64 private i18n: I18n,
65 private modalService: BsModalService,
66 private nfsService: NfsService,
67 private taskListService: TaskListService,
eafe8130
TL
68 private taskWrapper: TaskWrapperService,
69 public actionLabels: ActionLabelsI18n
11fdf7f2 70 ) {
e306af50 71 super();
11fdf7f2
TL
72 this.permission = this.authStorageService.getPermissions().nfs;
73 const getNfsUri = () =>
74 this.selection.first() &&
75 `${encodeURI(this.selection.first().cluster_id)}/${encodeURI(
76 this.selection.first().export_id
77 )}`;
78
eafe8130 79 const createAction: CdTableAction = {
11fdf7f2 80 permission: 'create',
9f95a23c 81 icon: Icons.add,
eafe8130 82 routerLink: () => '/nfs/create',
11fdf7f2 83 canBePrimary: (selection: CdTableSelection) => !selection.hasSingleSelection,
eafe8130 84 name: this.actionLabels.CREATE
11fdf7f2
TL
85 };
86
87 const editAction: CdTableAction = {
88 permission: 'update',
9f95a23c 89 icon: Icons.edit,
11fdf7f2 90 routerLink: () => `/nfs/edit/${getNfsUri()}`,
eafe8130 91 name: this.actionLabels.EDIT
11fdf7f2
TL
92 };
93
94 const deleteAction: CdTableAction = {
95 permission: 'delete',
9f95a23c 96 icon: Icons.destroy,
11fdf7f2 97 click: () => this.deleteNfsModal(),
eafe8130 98 name: this.actionLabels.DELETE
11fdf7f2
TL
99 };
100
eafe8130 101 this.tableActions = [createAction, editAction, deleteAction];
11fdf7f2
TL
102 }
103
104 ngOnInit() {
105 this.columns = [
106 {
eafe8130 107 name: this.i18n('Path'),
11fdf7f2
TL
108 prop: 'path',
109 flexGrow: 2,
110 cellTransformation: CellTemplate.executing
111 },
eafe8130
TL
112 {
113 name: this.i18n('Pseudo'),
114 prop: 'pseudo',
115 flexGrow: 2
116 },
11fdf7f2
TL
117 {
118 name: this.i18n('Cluster'),
119 prop: 'cluster_id',
120 flexGrow: 2
121 },
122 {
123 name: this.i18n('Daemons'),
124 prop: 'daemons',
125 flexGrow: 2
126 },
127 {
128 name: this.i18n('Storage Backend'),
129 prop: 'fsal',
130 flexGrow: 2,
131 cellTemplate: this.nfsFsal
132 },
133 {
134 name: this.i18n('Access Type'),
135 prop: 'access_type',
136 flexGrow: 2
137 }
138 ];
139
140 this.nfsService.daemon().subscribe(
141 (daemons: any) => {
142 const clusters = _(daemons)
143 .map((daemon) => daemon.cluster_id)
144 .uniq()
145 .value();
146
147 this.isDefaultCluster = clusters.length === 1 && clusters[0] === '_default_';
eafe8130 148 this.columns[2].isHidden = this.isDefaultCluster;
11fdf7f2
TL
149 if (this.table) {
150 this.table.updateColumns();
151 }
152
153 this.taskListService.init(
154 () => this.nfsService.list(),
155 (resp) => this.prepareResponse(resp),
156 (exports) => (this.exports = exports),
157 () => this.onFetchError(),
158 this.taskFilter,
159 this.itemFilter,
160 this.builders
161 );
162 },
163 () => {
164 this.onFetchError();
165 }
166 );
167 }
168
169 ngOnDestroy() {
170 if (this.summaryDataSubscription) {
171 this.summaryDataSubscription.unsubscribe();
172 }
173 }
174
175 prepareResponse(resp: any): any[] {
9f95a23c
TL
176 let result: any[] = [];
177 resp.forEach((nfs: any) => {
11fdf7f2
TL
178 nfs.id = `${nfs.cluster_id}:${nfs.export_id}`;
179 nfs.state = 'LOADING';
180 result = result.concat(nfs);
181 });
182
183 return result;
184 }
185
186 onFetchError() {
187 this.table.reset(); // Disable loading indicator.
188 this.viewCacheStatus = { status: ViewCacheStatus.ValueException };
189 }
190
9f95a23c 191 itemFilter(entry: any, task: Task) {
11fdf7f2
TL
192 return (
193 entry.cluster_id === task.metadata['cluster_id'] &&
194 entry.export_id === task.metadata['export_id']
195 );
196 }
197
9f95a23c 198 taskFilter(task: Task) {
11fdf7f2
TL
199 return ['nfs/create', 'nfs/delete', 'nfs/edit'].includes(task.name);
200 }
201
202 updateSelection(selection: CdTableSelection) {
203 this.selection = selection;
204 }
205
206 deleteNfsModal() {
207 const cluster_id = this.selection.first().cluster_id;
208 const export_id = this.selection.first().export_id;
209
210 this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
211 initialState: {
eafe8130
TL
212 itemDescription: this.i18n('NFS export'),
213 itemNames: [`${cluster_id}:${export_id}`],
11fdf7f2
TL
214 submitActionObservable: () =>
215 this.taskWrapper.wrapTaskAroundCall({
216 task: new FinishedTask('nfs/delete', {
217 cluster_id: cluster_id,
218 export_id: export_id
219 }),
220 call: this.nfsService.delete(cluster_id, export_id)
221 })
222 }
223 });
224 }
225}