]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-list/rgw-bucket-list.component.ts
import ceph 16.2.7
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / rgw / rgw-bucket-list / rgw-bucket-list.component.ts
CommitLineData
f67539c2 1import { Component, NgZone, OnInit, TemplateRef, ViewChild } from '@angular/core';
11fdf7f2 2
f67539c2 3import _ from 'lodash';
11fdf7f2
TL
4import { forkJoin as observableForkJoin, Observable, Subscriber } from 'rxjs';
5
f67539c2
TL
6import { RgwBucketService } from '~/app/shared/api/rgw-bucket.service';
7import { ListWithDetails } from '~/app/shared/classes/list-with-details.class';
f67539c2
TL
8import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
9import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
10import { TableComponent } from '~/app/shared/datatable/table/table.component';
11import { Icons } from '~/app/shared/enum/icons.enum';
12import { CdTableAction } from '~/app/shared/models/cd-table-action';
13import { CdTableColumn } from '~/app/shared/models/cd-table-column';
14import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context';
15import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
16import { Permission } from '~/app/shared/models/permissions';
17import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe';
18import { DimlessPipe } from '~/app/shared/pipes/dimless.pipe';
19import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
20import { ModalService } from '~/app/shared/services/modal.service';
21import { URLBuilderService } from '~/app/shared/services/url-builder.service';
11fdf7f2
TL
22
23const BASE_URL = 'rgw/bucket';
24
25@Component({
26 selector: 'cd-rgw-bucket-list',
27 templateUrl: './rgw-bucket-list.component.html',
28 styleUrls: ['./rgw-bucket-list.component.scss'],
29 providers: [{ provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }]
30})
f6b5b4d7 31export class RgwBucketListComponent extends ListWithDetails implements OnInit {
9f95a23c 32 @ViewChild(TableComponent, { static: true })
11fdf7f2 33 table: TableComponent;
f6b5b4d7
TL
34 @ViewChild('bucketSizeTpl', { static: true })
35 bucketSizeTpl: TemplateRef<any>;
36 @ViewChild('bucketObjectTpl', { static: true })
37 bucketObjectTpl: TemplateRef<any>;
11fdf7f2
TL
38
39 permission: Permission;
40 tableActions: CdTableAction[];
41 columns: CdTableColumn[] = [];
42 buckets: object[] = [];
43 selection: CdTableSelection = new CdTableSelection();
1911f103 44 staleTimeout: number;
11fdf7f2
TL
45
46 constructor(
47 private authStorageService: AuthStorageService,
f6b5b4d7
TL
48 private dimlessBinaryPipe: DimlessBinaryPipe,
49 private dimlessPipe: DimlessPipe,
11fdf7f2 50 private rgwBucketService: RgwBucketService,
f67539c2 51 private modalService: ModalService,
11fdf7f2 52 private urlBuilder: URLBuilderService,
1911f103 53 public actionLabels: ActionLabelsI18n,
522d829b 54 protected ngZone: NgZone
11fdf7f2 55 ) {
522d829b 56 super(ngZone);
1911f103
TL
57 }
58
f6b5b4d7 59 ngOnInit() {
f67539c2 60 this.permission = this.authStorageService.getPermissions().rgw;
f6b5b4d7
TL
61 this.columns = [
62 {
f67539c2 63 name: $localize`Name`,
f6b5b4d7
TL
64 prop: 'bid',
65 flexGrow: 2
66 },
67 {
f67539c2 68 name: $localize`Owner`,
f6b5b4d7 69 prop: 'owner',
f67539c2 70 flexGrow: 2.5
f6b5b4d7
TL
71 },
72 {
f67539c2 73 name: $localize`Used Capacity`,
f6b5b4d7 74 prop: 'bucket_size',
f67539c2 75 flexGrow: 0.6,
f6b5b4d7
TL
76 pipe: this.dimlessBinaryPipe
77 },
78 {
f67539c2 79 name: $localize`Capacity Limit %`,
f6b5b4d7
TL
80 prop: 'size_usage',
81 cellTemplate: this.bucketSizeTpl,
f67539c2 82 flexGrow: 0.8
f6b5b4d7
TL
83 },
84 {
f67539c2 85 name: $localize`Objects`,
f6b5b4d7 86 prop: 'num_objects',
f67539c2 87 flexGrow: 0.6,
f6b5b4d7
TL
88 pipe: this.dimlessPipe
89 },
90 {
f67539c2 91 name: $localize`Object Limit %`,
f6b5b4d7
TL
92 prop: 'object_usage',
93 cellTemplate: this.bucketObjectTpl,
f67539c2 94 flexGrow: 0.8
f6b5b4d7
TL
95 }
96 ];
f67539c2
TL
97 const getBucketUri = () =>
98 this.selection.first() && `${encodeURIComponent(this.selection.first().bid)}`;
99 const addAction: CdTableAction = {
100 permission: 'create',
101 icon: Icons.add,
102 routerLink: () => this.urlBuilder.getCreate(),
103 name: this.actionLabels.CREATE,
104 canBePrimary: (selection: CdTableSelection) => !selection.hasSelection
105 };
106 const editAction: CdTableAction = {
107 permission: 'update',
108 icon: Icons.edit,
109 routerLink: () => this.urlBuilder.getEdit(getBucketUri()),
110 name: this.actionLabels.EDIT
111 };
112 const deleteAction: CdTableAction = {
113 permission: 'delete',
114 icon: Icons.destroy,
115 click: () => this.deleteAction(),
116 disable: () => !this.selection.hasSelection,
117 name: this.actionLabels.DELETE,
118 canBePrimary: (selection: CdTableSelection) => selection.hasMultiSelection
119 };
120 this.tableActions = [addAction, editAction, deleteAction];
522d829b 121 this.setTableRefreshTimeout();
f6b5b4d7
TL
122 }
123
124 transformBucketData() {
125 _.forEach(this.buckets, (bucketKey) => {
f6b5b4d7
TL
126 const maxBucketSize = bucketKey['bucket_quota']['max_size'];
127 const maxBucketObjects = bucketKey['bucket_quota']['max_objects'];
b3b6e05e
TL
128 bucketKey['bucket_size'] = 0;
129 bucketKey['num_objects'] = 0;
130 if (!_.isEmpty(bucketKey['usage'])) {
131 bucketKey['bucket_size'] = bucketKey['usage']['rgw.main']['size_actual'];
132 bucketKey['num_objects'] = bucketKey['usage']['rgw.main']['num_objects'];
133 }
134 bucketKey['size_usage'] =
135 maxBucketSize > 0 ? bucketKey['bucket_size'] / maxBucketSize : undefined;
f6b5b4d7 136 bucketKey['object_usage'] =
b3b6e05e 137 maxBucketObjects > 0 ? bucketKey['num_objects'] / maxBucketObjects : undefined;
f6b5b4d7
TL
138 });
139 }
140
11fdf7f2 141 getBucketList(context: CdTableFetchDataContext) {
522d829b 142 this.setTableRefreshTimeout();
a4b75251 143 this.rgwBucketService.list(true).subscribe(
11fdf7f2
TL
144 (resp: object[]) => {
145 this.buckets = resp;
f6b5b4d7 146 this.transformBucketData();
11fdf7f2
TL
147 },
148 () => {
149 context.error();
150 }
151 );
152 }
153
154 updateSelection(selection: CdTableSelection) {
155 this.selection = selection;
156 }
157
158 deleteAction() {
f67539c2
TL
159 this.modalService.show(CriticalConfirmationModalComponent, {
160 itemDescription: this.selection.hasSingleSelection ? $localize`bucket` : $localize`buckets`,
161 itemNames: this.selection.selected.map((bucket: any) => bucket['bid']),
162 submitActionObservable: () => {
163 return new Observable((observer: Subscriber<any>) => {
164 // Delete all selected data table rows.
165 observableForkJoin(
166 this.selection.selected.map((bucket: any) => {
167 return this.rgwBucketService.delete(bucket.bid);
168 })
169 ).subscribe({
170 error: (error) => {
171 // Forward the error to the observer.
172 observer.error(error);
173 // Reload the data table content because some deletions might
174 // have been executed successfully in the meanwhile.
175 this.table.refreshBtn();
176 },
177 complete: () => {
178 // Notify the observer that we are done.
179 observer.complete();
180 // Reload the data table content.
181 this.table.refreshBtn();
182 }
11fdf7f2 183 });
f67539c2 184 });
11fdf7f2
TL
185 }
186 });
187 }
188}