X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ceph%2Fsrc%2Fpybind%2Fmgr%2Fdashboard%2Ffrontend%2Fsrc%2Fapp%2Fceph%2Fcluster%2Fhosts%2Fhosts.component.ts;h=41594c1f55e7924504adb5cd137c36e031cafd19;hb=f6b5b4d738b87d88d2de35127b6b0e41eae2a272;hp=91e9faa7f2cbe67c45d07d5d6b9a808f9f2686e7;hpb=12732ca2e80d168d344a265acffc1fbd1fa1f1b5;p=ceph.git diff --git a/ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.ts b/ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.ts index 91e9faa7f..41594c1f5 100644 --- a/ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.ts +++ b/ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.ts @@ -7,8 +7,12 @@ import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal'; import { HostService } from '../../../shared/api/host.service'; import { ListWithDetails } from '../../../shared/classes/list-with-details.class'; import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component'; +import { FormModalComponent } from '../../../shared/components/form-modal/form-modal.component'; +import { SelectMessages } from '../../../shared/components/select/select-messages.model'; import { ActionLabelsI18n } from '../../../shared/constants/app.constants'; +import { TableComponent } from '../../../shared/datatable/table/table.component'; import { Icons } from '../../../shared/enum/icons.enum'; +import { NotificationType } from '../../../shared/enum/notification-type.enum'; import { CdTableAction } from '../../../shared/models/cd-table-action'; import { CdTableColumn } from '../../../shared/models/cd-table-column'; import { CdTableFetchDataContext } from '../../../shared/models/cd-table-fetch-data-context'; @@ -19,6 +23,7 @@ import { CephShortVersionPipe } from '../../../shared/pipes/ceph-short-version.p import { JoinPipe } from '../../../shared/pipes/join.pipe'; import { AuthStorageService } from '../../../shared/services/auth-storage.service'; import { DepCheckerService } from '../../../shared/services/dep-checker.service'; +import { NotificationService } from '../../../shared/services/notification.service'; import { TaskWrapperService } from '../../../shared/services/task-wrapper.service'; import { URLBuilderService } from '../../../shared/services/url-builder.service'; @@ -31,6 +36,11 @@ const BASE_URL = 'hosts'; providers: [{ provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }] }) export class HostsComponent extends ListWithDetails implements OnInit { + @ViewChild(TableComponent, { static: true }) + table: TableComponent; + @ViewChild('servicesTpl', { static: true }) + public servicesTpl: TemplateRef; + permissions: Permissions; columns: Array = []; hosts: Array = []; @@ -40,9 +50,6 @@ export class HostsComponent extends ListWithDetails implements OnInit { selection = new CdTableSelection(); modalRef: BsModalRef; - @ViewChild('servicesTpl', { static: true }) - public servicesTpl: TemplateRef; - constructor( private authStorageService: AuthStorageService, private hostService: HostService, @@ -54,7 +61,8 @@ export class HostsComponent extends ListWithDetails implements OnInit { private modalService: BsModalService, private taskWrapper: TaskWrapperService, private router: Router, - private depCheckerService: DepCheckerService + private depCheckerService: DepCheckerService, + private notificationService: NotificationService ) { super(); this.permissions = this.authStorageService.getPermissions(); @@ -73,6 +81,21 @@ export class HostsComponent extends ListWithDetails implements OnInit { ); } }, + { + name: this.actionLabels.EDIT, + permission: 'update', + icon: Icons.edit, + click: () => { + this.depCheckerService.checkOrchestratorOrModal( + this.actionLabels.EDIT, + this.i18n('Host'), + () => this.editAction() + ); + }, + disable: (selection: CdTableSelection) => + !selection.hasSingleSelection || !selection.first().sources.orchestrator, + disableDesc: this.getEditDisableDesc.bind(this) + }, { name: this.actionLabels.DELETE, permission: 'delete', @@ -81,7 +104,7 @@ export class HostsComponent extends ListWithDetails implements OnInit { this.depCheckerService.checkOrchestratorOrModal( this.actionLabels.DELETE, this.i18n('Host'), - () => this.deleteHostModal() + () => this.deleteAction() ); }, disable: () => !this.selection.hasSelection @@ -121,7 +144,59 @@ export class HostsComponent extends ListWithDetails implements OnInit { this.selection = selection; } - deleteHostModal() { + editAction() { + this.hostService.getLabels().subscribe((resp: string[]) => { + const host = this.selection.first(); + const allLabels = resp.map((label) => { + return { enabled: true, name: label }; + }); + this.modalService.show(FormModalComponent, { + initialState: { + titleText: this.i18n('Edit Host: {{hostname}}', host), + fields: [ + { + type: 'select-badges', + name: 'labels', + value: host['labels'], + label: this.i18n('Labels'), + typeConfig: { + customBadges: true, + options: allLabels, + messages: new SelectMessages( + { + empty: this.i18n('There are no labels.'), + filter: this.i18n('Filter or add labels'), + add: this.i18n('Add label') + }, + this.i18n + ) + } + } + ], + submitButtonText: this.i18n('Edit Host'), + onSubmit: (values: any) => { + this.hostService.update(host['hostname'], values.labels).subscribe(() => { + this.notificationService.show( + NotificationType.success, + this.i18n('Updated Host "{{hostname}}"', host) + ); + // Reload the data table content. + this.table.refreshBtn(); + }); + } + } + }); + }); + } + + getEditDisableDesc(selection: CdTableSelection): string | undefined { + if (selection && selection.hasSingleSelection && !selection.first().sources.orchestrator) { + return this.i18n('Host editing is disabled because the host is not managed by Orchestrator.'); + } + return undefined; + } + + deleteAction() { const hostname = this.selection.first().hostname; this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, { initialState: {