1 import { Component, ViewChild } from '@angular/core';
3 import { I18n } from '@ngx-translate/i18n-polyfill';
4 import { BlockUI, NgBlockUI } from 'ng-block-ui';
5 import { timer as observableTimer } from 'rxjs';
7 import { MgrModuleService } from '../../../../shared/api/mgr-module.service';
8 import { ListWithDetails } from '../../../../shared/classes/list-with-details.class';
9 import { TableComponent } from '../../../../shared/datatable/table/table.component';
10 import { CellTemplate } from '../../../../shared/enum/cell-template.enum';
11 import { Icons } from '../../../../shared/enum/icons.enum';
12 import { CdTableAction } from '../../../../shared/models/cd-table-action';
13 import { CdTableColumn } from '../../../../shared/models/cd-table-column';
14 import { CdTableFetchDataContext } from '../../../../shared/models/cd-table-fetch-data-context';
15 import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
16 import { Permission } from '../../../../shared/models/permissions';
17 import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
18 import { NotificationService } from '../../../../shared/services/notification.service';
21 selector: 'cd-mgr-module-list',
22 templateUrl: './mgr-module-list.component.html',
23 styleUrls: ['./mgr-module-list.component.scss']
25 export class MgrModuleListComponent extends ListWithDetails {
26 @ViewChild(TableComponent, { static: true })
27 table: TableComponent;
31 permission: Permission;
32 tableActions: CdTableAction[];
33 columns: CdTableColumn[] = [];
34 modules: object[] = [];
35 selection: CdTableSelection = new CdTableSelection();
38 private authStorageService: AuthStorageService,
39 private mgrModuleService: MgrModuleService,
40 private notificationService: NotificationService,
44 this.permission = this.authStorageService.getPermissions().configOpt;
47 name: this.i18n('Name'),
52 name: this.i18n('Enabled'),
55 cellClass: 'text-center',
56 cellTransformation: CellTemplate.checkIcon
59 name: this.i18n('Always-On'),
63 cellClass: 'text-center',
64 cellTransformation: CellTemplate.checkIcon
67 const getModuleUri = () =>
68 this.selection.first() && encodeURIComponent(this.selection.first().name);
71 name: this.i18n('Edit'),
74 if (!this.selection.hasSelection) {
77 // Disable the 'edit' button when the module has no options.
78 return Object.values(this.selection.first().options).length === 0;
80 routerLink: () => `/mgr-modules/edit/${getModuleUri()}`,
84 name: this.i18n('Enable'),
86 click: () => this.updateModuleState(),
87 disable: () => this.isTableActionDisabled('enabled'),
91 name: this.i18n('Disable'),
93 click: () => this.updateModuleState(),
94 disable: () => this.isTableActionDisabled('disabled'),
95 disableDesc: () => this.getTableActionDisabledDesc(),
101 getModuleList(context: CdTableFetchDataContext) {
102 this.mgrModuleService.list().subscribe(
103 (resp: object[]) => {
112 updateSelection(selection: CdTableSelection) {
113 this.selection = selection;
117 * Check if the table action is disabled.
118 * @param state The expected module state, e.g. ``enabled`` or ``disabled``.
119 * @returns If the specified state is validated to true or no selection is
120 * done, then ``true`` is returned, otherwise ``false``.
122 isTableActionDisabled(state: 'enabled' | 'disabled') {
123 if (!this.selection.hasSelection) {
126 const selected = this.selection.first();
127 // Make sure the user can't modify the run state of the 'Dashboard' module.
128 // This check is only done in the UI because the REST API should still be
130 if (selected.name === 'dashboard') {
133 // Always-on modules can't be disabled.
134 if (selected.always_on) {
139 return selected.enabled;
141 return !selected.enabled;
145 getTableActionDisabledDesc(): string | undefined {
146 if (this.selection.hasSelection) {
147 const selected = this.selection.first();
148 if (selected.always_on) {
149 return this.i18n('This Manager module is always on.');
157 * Update the Ceph Mgr module state to enabled or disabled.
159 updateModuleState() {
160 if (!this.selection.hasSelection) {
165 const fnWaitUntilReconnected = () => {
166 observableTimer(2000).subscribe(() => {
167 // Trigger an API request to check if the connection is
169 this.mgrModuleService.list().subscribe(
171 // Resume showing the notification toasties.
172 this.notificationService.suspendToasties(false);
173 // Unblock the whole UI.
175 // Reload the data table content.
176 this.table.refreshBtn();
179 fnWaitUntilReconnected();
185 // Note, the Ceph Mgr is always restarted when a module
186 // is enabled/disabled.
187 const module = this.selection.first();
188 if (module.enabled) {
189 $obs = this.mgrModuleService.disable(module.name);
191 $obs = this.mgrModuleService.enable(module.name);
196 // Suspend showing the notification toasties.
197 this.notificationService.suspendToasties(true);
198 // Block the whole UI to prevent user interactions until
199 // the connection to the backend is reestablished
200 this.blockUI.start(this.i18n('Reconnecting, please wait ...'));
201 fnWaitUntilReconnected();