1 import { Component, ViewChild } from '@angular/core';
3 import { BlockUI, NgBlockUI } from 'ng-block-ui';
4 import { timer as observableTimer } from 'rxjs';
6 import { MgrModuleService } from '../../../../shared/api/mgr-module.service';
7 import { ListWithDetails } from '../../../../shared/classes/list-with-details.class';
8 import { TableComponent } from '../../../../shared/datatable/table/table.component';
9 import { CellTemplate } from '../../../../shared/enum/cell-template.enum';
10 import { Icons } from '../../../../shared/enum/icons.enum';
11 import { CdTableAction } from '../../../../shared/models/cd-table-action';
12 import { CdTableColumn } from '../../../../shared/models/cd-table-column';
13 import { CdTableFetchDataContext } from '../../../../shared/models/cd-table-fetch-data-context';
14 import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
15 import { Permission } from '../../../../shared/models/permissions';
16 import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
17 import { NotificationService } from '../../../../shared/services/notification.service';
20 selector: 'cd-mgr-module-list',
21 templateUrl: './mgr-module-list.component.html',
22 styleUrls: ['./mgr-module-list.component.scss']
24 export class MgrModuleListComponent extends ListWithDetails {
25 @ViewChild(TableComponent, { static: true })
26 table: TableComponent;
30 permission: Permission;
31 tableActions: CdTableAction[];
32 columns: CdTableColumn[] = [];
33 modules: object[] = [];
34 selection: CdTableSelection = new CdTableSelection();
37 private authStorageService: AuthStorageService,
38 private mgrModuleService: MgrModuleService,
39 private notificationService: NotificationService
42 this.permission = this.authStorageService.getPermissions().configOpt;
45 name: $localize`Name`,
50 name: $localize`Enabled`,
53 cellClass: 'text-center',
54 cellTransformation: CellTemplate.checkIcon
57 name: $localize`Always-On`,
61 cellClass: 'text-center',
62 cellTransformation: CellTemplate.checkIcon
65 const getModuleUri = () =>
66 this.selection.first() && encodeURIComponent(this.selection.first().name);
69 name: $localize`Edit`,
72 if (!this.selection.hasSelection) {
75 // Disable the 'edit' button when the module has no options.
76 return Object.values(this.selection.first().options).length === 0;
78 routerLink: () => `/mgr-modules/edit/${getModuleUri()}`,
82 name: $localize`Enable`,
84 click: () => this.updateModuleState(),
85 disable: () => this.isTableActionDisabled('enabled'),
89 name: $localize`Disable`,
91 click: () => this.updateModuleState(),
92 disable: () => this.isTableActionDisabled('disabled'),
93 disableDesc: () => this.getTableActionDisabledDesc(),
99 getModuleList(context: CdTableFetchDataContext) {
100 this.mgrModuleService.list().subscribe(
101 (resp: object[]) => {
110 updateSelection(selection: CdTableSelection) {
111 this.selection = selection;
115 * Check if the table action is disabled.
116 * @param state The expected module state, e.g. ``enabled`` or ``disabled``.
117 * @returns If the specified state is validated to true or no selection is
118 * done, then ``true`` is returned, otherwise ``false``.
120 isTableActionDisabled(state: 'enabled' | 'disabled') {
121 if (!this.selection.hasSelection) {
124 const selected = this.selection.first();
125 // Make sure the user can't modify the run state of the 'Dashboard' module.
126 // This check is only done in the UI because the REST API should still be
128 if (selected.name === 'dashboard') {
131 // Always-on modules can't be disabled.
132 if (selected.always_on) {
137 return selected.enabled;
139 return !selected.enabled;
143 getTableActionDisabledDesc(): string | undefined {
144 if (this.selection.hasSelection) {
145 const selected = this.selection.first();
146 if (selected.always_on) {
147 return $localize`This Manager module is always on.`;
155 * Update the Ceph Mgr module state to enabled or disabled.
157 updateModuleState() {
158 if (!this.selection.hasSelection) {
163 const fnWaitUntilReconnected = () => {
164 observableTimer(2000).subscribe(() => {
165 // Trigger an API request to check if the connection is
167 this.mgrModuleService.list().subscribe(
169 // Resume showing the notification toasties.
170 this.notificationService.suspendToasties(false);
171 // Unblock the whole UI.
173 // Reload the data table content.
174 this.table.refreshBtn();
177 fnWaitUntilReconnected();
183 // Note, the Ceph Mgr is always restarted when a module
184 // is enabled/disabled.
185 const module = this.selection.first();
186 if (module.enabled) {
187 $obs = this.mgrModuleService.disable(module.name);
189 $obs = this.mgrModuleService.enable(module.name);
194 // Suspend showing the notification toasties.
195 this.notificationService.suspendToasties(true);
196 // Block the whole UI to prevent user interactions until
197 // the connection to the backend is reestablished
198 this.blockUI.start($localize`Reconnecting, please wait ...`);
199 fnWaitUntilReconnected();