]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.ts
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / cluster / prometheus / silence-form / silence-form.component.ts
index d5ef6b35e6f596e2057b4a95e4a5227b391f490f..b3bc1401082a66487b29197b583f35551cb29b7c 100644 (file)
@@ -1,32 +1,30 @@
 import { Component } from '@angular/core';
 import { Validators } from '@angular/forms';
 import { ActivatedRoute, Router } from '@angular/router';
-import { I18n } from '@ngx-translate/i18n-polyfill';
 
-import * as _ from 'lodash';
-import { BsModalService } from 'ngx-bootstrap/modal';
+import _ from 'lodash';
+import moment from 'moment';
 
-import { PrometheusService } from '../../../../shared/api/prometheus.service';
-import {
-  ActionLabelsI18n,
-  SucceededActionLabelsI18n
-} from '../../../../shared/constants/app.constants';
-import { Icons } from '../../../../shared/enum/icons.enum';
-import { NotificationType } from '../../../../shared/enum/notification-type.enum';
-import { CdFormBuilder } from '../../../../shared/forms/cd-form-builder';
-import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
-import { CdValidators } from '../../../../shared/forms/cd-validators';
+import { DashboardNotFoundError } from '~/app/core/error/error';
+import { PrometheusService } from '~/app/shared/api/prometheus.service';
+import { ActionLabelsI18n, SucceededActionLabelsI18n } from '~/app/shared/constants/app.constants';
+import { Icons } from '~/app/shared/enum/icons.enum';
+import { NotificationType } from '~/app/shared/enum/notification-type.enum';
+import { CdFormBuilder } from '~/app/shared/forms/cd-form-builder';
+import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
+import { CdValidators } from '~/app/shared/forms/cd-validators';
 import {
   AlertmanagerSilence,
   AlertmanagerSilenceMatcher,
   AlertmanagerSilenceMatcherMatch
-} from '../../../../shared/models/alertmanager-silence';
-import { Permission } from '../../../../shared/models/permissions';
-import { AlertmanagerAlert, PrometheusRule } from '../../../../shared/models/prometheus-alerts';
-import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
-import { NotificationService } from '../../../../shared/services/notification.service';
-import { PrometheusSilenceMatcherService } from '../../../../shared/services/prometheus-silence-matcher.service';
-import { TimeDiffService } from '../../../../shared/services/time-diff.service';
+} from '~/app/shared/models/alertmanager-silence';
+import { Permission } from '~/app/shared/models/permissions';
+import { AlertmanagerAlert, PrometheusRule } from '~/app/shared/models/prometheus-alerts';
+import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
+import { ModalService } from '~/app/shared/services/modal.service';
+import { NotificationService } from '~/app/shared/services/notification.service';
+import { PrometheusSilenceMatcherService } from '~/app/shared/services/prometheus-silence-matcher.service';
+import { TimeDiffService } from '~/app/shared/services/time-diff.service';
 import { SilenceMatcherModalComponent } from '../silence-matcher-modal/silence-matcher-modal.component';
 
 @Component({
@@ -40,38 +38,36 @@ export class SilenceFormComponent {
   form: CdFormGroup;
   rules: PrometheusRule[];
 
-  // Date formatting rules can be found here: https://momentjs.com/docs/#/displaying/format/
-  bsConfig = { dateInputFormat: 'YYYY-MM-DDT HH:mm' };
-
   recreate = false;
   edit = false;
   id: string;
 
   action: string;
-  resource = this.i18n('silence');
+  resource = $localize`silence`;
 
   matchers: AlertmanagerSilenceMatcher[] = [];
   matcherMatch: AlertmanagerSilenceMatcherMatch = undefined;
   matcherConfig = [
     {
-      tooltip: this.i18n('Attribute name'),
+      tooltip: $localize`Attribute name`,
       icon: this.icons.paragraph,
       attribute: 'name'
     },
     {
-      tooltip: this.i18n('Value'),
+      tooltip: $localize`Value`,
       icon: this.icons.terminal,
       attribute: 'value'
     },
     {
-      tooltip: this.i18n('Regular expression'),
+      tooltip: $localize`Regular expression`,
       icon: this.icons.magic,
       attribute: 'isRegex'
     }
   ];
 
+  datetimeFormat = 'YYYY-MM-DD HH:mm';
+
   constructor(
-    private i18n: I18n,
     private router: Router,
     private authStorageService: AuthStorageService,
     private formBuilder: CdFormBuilder,
@@ -79,7 +75,7 @@ export class SilenceFormComponent {
     private notificationService: NotificationService,
     private route: ActivatedRoute,
     private timeDiff: TimeDiffService,
-    private bsModalService: BsModalService,
+    private modalService: ModalService,
     private silenceMatcher: PrometheusSilenceMatcherService,
     private actionLabels: ActionLabelsI18n,
     private succeededLabels: SucceededActionLabelsI18n
@@ -96,8 +92,8 @@ export class SilenceFormComponent {
   }
 
   private chooseMode() {
-    this.edit = this.router.url.startsWith('/monitoring/silence/edit');
-    this.recreate = this.router.url.startsWith('/monitoring/silence/recreate');
+    this.edit = this.router.url.startsWith('/monitoring/silences/edit');
+    this.recreate = this.router.url.startsWith('/monitoring/silences/recreate');
     if (this.edit) {
       this.action = this.actionLabels.EDIT;
     } else if (this.recreate) {
@@ -112,16 +108,20 @@ export class SilenceFormComponent {
     const allowed =
       this.permission.read && (this.edit ? this.permission.update : this.permission.create);
     if (!allowed) {
-      this.router.navigate(['/404']);
+      throw new DashboardNotFoundError();
     }
   }
 
   private createForm() {
+    const formatValidator = CdValidators.custom('format', (expiresAt: string) => {
+      const result = expiresAt === '' || moment(expiresAt, this.datetimeFormat).isValid();
+      return !result;
+    });
     this.form = this.formBuilder.group(
       {
-        startsAt: [null, [Validators.required]],
+        startsAt: ['', [Validators.required, formatValidator]],
         duration: ['2h', [Validators.min(1)]],
-        endsAt: [null, [Validators.required]],
+        endsAt: ['', [Validators.required, formatValidator]],
         createdBy: [this.authStorageService.getUsername(), [Validators.required]],
         comment: [null, [Validators.required]]
       },
@@ -132,21 +132,21 @@ export class SilenceFormComponent {
   }
 
   private setupDates() {
-    const now = new Date();
-    now.setSeconds(0, 0); // Normalizes start date
+    const now = moment().format(this.datetimeFormat);
     this.form.silentSet('startsAt', now);
     this.updateDate();
     this.subscribeDateChanges();
   }
 
   private updateDate(updateStartDate?: boolean) {
-    const next = this.timeDiff.calculateDate(
+    const date = moment(
       this.form.getValue(updateStartDate ? 'endsAt' : 'startsAt'),
-      this.form.getValue('duration'),
-      updateStartDate
-    );
+      this.datetimeFormat
+    ).toDate();
+    const next = this.timeDiff.calculateDate(date, this.form.getValue('duration'), updateStartDate);
     if (next) {
-      this.form.silentSet(updateStartDate ? 'startsAt' : 'endsAt', next);
+      const nextDate = moment(next).format(this.datetimeFormat);
+      this.form.silentSet(updateStartDate ? 'startsAt' : 'endsAt', nextDate);
     }
   }
 
@@ -163,7 +163,9 @@ export class SilenceFormComponent {
   }
 
   private onDateChange(updateStartDate?: boolean) {
-    if (this.form.getValue('startsAt') < this.form.getValue('endsAt')) {
+    const startsAt = moment(this.form.getValue('startsAt'), this.datetimeFormat);
+    const endsAt = moment(this.form.getValue('endsAt'), this.datetimeFormat);
+    if (startsAt.isBefore(endsAt)) {
       this.updateDuration();
     } else {
       this.updateDate(updateStartDate);
@@ -171,10 +173,9 @@ export class SilenceFormComponent {
   }
 
   private updateDuration() {
-    this.form.silentSet(
-      'duration',
-      this.timeDiff.calculateDuration(this.form.getValue('startsAt'), this.form.getValue('endsAt'))
-    );
+    const startsAt = moment(this.form.getValue('startsAt'), this.datetimeFormat).toDate();
+    const endsAt = moment(this.form.getValue('endsAt'), this.datetimeFormat).toDate();
+    this.form.silentSet('duration', this.timeDiff.calculateDuration(startsAt, endsAt));
   }
 
   private getData() {
@@ -201,9 +202,7 @@ export class SilenceFormComponent {
         this.rules = [];
         this.notificationService.show(
           NotificationType.info,
-          this.i18n(
-            'Please add your Prometheus host to the dashboard configuration and refresh the page'
-          ),
+          $localize`Please add your Prometheus host to the dashboard configuration and refresh the page`,
           undefined,
           undefined,
           'Prometheus'
@@ -232,7 +231,9 @@ export class SilenceFormComponent {
   private fillFormWithSilence(silence: AlertmanagerSilence) {
     this.id = silence.id;
     if (this.edit) {
-      ['startsAt', 'endsAt'].forEach((attr) => this.form.silentSet(attr, new Date(silence[attr])));
+      ['startsAt', 'endsAt'].forEach((attr) =>
+        this.form.silentSet(attr, moment(silence[attr]).format(this.datetimeFormat))
+      );
       this.updateDuration();
     }
     ['createdBy', 'comment'].forEach((attr) => this.form.silentSet(attr, silence[attr]));
@@ -271,14 +272,14 @@ export class SilenceFormComponent {
   }
 
   showMatcherModal(index?: number) {
-    const modalRef = this.bsModalService.show(SilenceMatcherModalComponent);
-    const modal = modalRef.content as SilenceMatcherModalComponent;
-    modal.rules = this.rules;
+    const modalRef = this.modalService.show(SilenceMatcherModalComponent);
+    const modalComponent = modalRef.componentInstance as SilenceMatcherModalComponent;
+    modalComponent.rules = this.rules;
     if (_.isNumber(index)) {
-      modal.editMode = true;
-      modal.preFillControls(this.matchers[index]);
+      modalComponent.editMode = true;
+      modalComponent.preFillControls(this.matchers[index]);
     }
-    modalRef.content.submitAction.subscribe((matcher: AlertmanagerSilenceMatcher) => {
+    modalComponent.submitAction.subscribe((matcher: AlertmanagerSilenceMatcher) => {
       this.setMatcher(matcher, index);
     });
   }
@@ -294,7 +295,7 @@ export class SilenceFormComponent {
     }
     this.prometheusService.setSilence(this.getSubmitData()).subscribe(
       (resp) => {
-        this.router.navigate(['/monitoring'], { fragment: 'silences' });
+        this.router.navigate(['/monitoring/silences']);
         this.notificationService.show(
           NotificationType.success,
           this.getNotificationTile(resp.body['silenceId']),
@@ -310,8 +311,8 @@ export class SilenceFormComponent {
   private getSubmitData(): AlertmanagerSilence {
     const payload = this.form.value;
     delete payload.duration;
-    payload.startsAt = payload.startsAt.toISOString();
-    payload.endsAt = payload.endsAt.toISOString();
+    payload.startsAt = moment(payload.startsAt, this.datetimeFormat).toISOString();
+    payload.endsAt = moment(payload.endsAt, this.datetimeFormat).toISOString();
     payload.matchers = this.matchers;
     if (this.edit) {
       payload.id = this.id;