From 31597e51480e597b56995e0c6e1e4d69488c0f99 Mon Sep 17 00:00:00 2001 From: Volker Theile Date: Thu, 2 Apr 2020 11:03:52 +0200 Subject: [PATCH] mgr/dashboard: Unify Tasks and Notifications into a sidebar Fixes: https://tracker.ceph.com/issues/37402 Signed-off-by: Tiago Melo (cherry picked from commit 7fdb3c1504a96a991041934c8abd6453d762857d) Conflicts: src/pybind/mgr/dashboard/frontend/e2e/cluster/crush-map.po.ts src/pybind/mgr/dashboard/frontend/package-lock.json src/pybind/mgr/dashboard/frontend/package.json src/pybind/mgr/dashboard/frontend/src/app/app.component.html src/pybind/mgr/dashboard/frontend/src/app/app.module.ts src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.html src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.scss src/pybind/mgr/dashboard/frontend/src/app/core/navigation/notifications/notifications.component.ts src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.html src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.spec.ts src/pybind/mgr/dashboard/frontend/src/app/core/navigation/task-manager/task-manager.component.ts src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts src/pybind/mgr/dashboard/frontend/src/styles/popover.scss --- .../app/shared/pipes/duration.pipe.spec.ts | 24 ++++++++++ .../src/app/shared/pipes/duration.pipe.ts | 47 +++++++++++++++++++ .../src/app/shared/pipes/pipes.module.ts | 7 ++- 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.ts diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.spec.ts new file mode 100644 index 0000000000000..7241812e56047 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.spec.ts @@ -0,0 +1,24 @@ +import * as moment from 'moment'; + +import { DurationPipe } from './duration.pipe'; + +describe('DurationPipe', () => { + const pipe = new DurationPipe(); + + it('create an instance', () => { + expect(pipe).toBeTruthy(); + }); + + it('transforms seconds into a human readable duration', () => { + expect(pipe.transform(0)).toBe('1 second'); + expect(pipe.transform(6)).toBe('6 seconds'); + expect(pipe.transform(60)).toBe('1 minute'); + expect(pipe.transform(600)).toBe('10 minutes'); + expect(pipe.transform(6000)).toBe('1 hour 40 minutes'); + }); + + it('transforms date into a human readable relative duration', () => { + const date = moment().subtract(130, 'seconds'); + expect(pipe.transform(date, true)).toBe('2 minutes ago'); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.ts new file mode 100644 index 0000000000000..c2b874ac4570c --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/duration.pipe.ts @@ -0,0 +1,47 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +import * as moment from 'moment'; + +@Pipe({ + name: 'duration', + pure: false +}) +export class DurationPipe implements PipeTransform { + transform(date: any, isRelative = false): string { + if (isRelative) { + return moment(date).fromNow(); + } else { + return this._forHumans(date); + } + } + + /** + * Translates seconds into human readable format of seconds, minutes, hours, days, and years + * source: https://stackoverflow.com/a/34270811 + * + * @param {number} seconds The number of seconds to be processed + * @return {string} The phrase describing the the amount of time + */ + _forHumans(seconds: number): string { + const levels = [ + [`${Math.floor(seconds / 31536000)}`, 'years'], + [`${Math.floor((seconds % 31536000) / 86400)}`, 'days'], + [`${Math.floor((seconds % 86400) / 3600)}`, 'hours'], + [`${Math.floor((seconds % 3600) / 60)}`, 'minutes'], + [`${Math.floor(seconds % 60)}`, 'seconds'] + ]; + let returntext = ''; + + for (let i = 0, max = levels.length; i < max; i++) { + if (levels[i][0] === '0') { + continue; + } + returntext += + ' ' + + levels[i][0] + + ' ' + + (levels[i][0] === '1' ? levels[i][1].substr(0, levels[i][1].length - 1) : levels[i][1]); + } + return returntext.trim() || '1 second'; + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/pipes.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/pipes.module.ts index 858ee744c70bc..6e96dd1f30a29 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/pipes.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/pipes.module.ts @@ -8,6 +8,7 @@ import { CephShortVersionPipe } from './ceph-short-version.pipe'; import { DimlessBinaryPerSecondPipe } from './dimless-binary-per-second.pipe'; import { DimlessBinaryPipe } from './dimless-binary.pipe'; import { DimlessPipe } from './dimless.pipe'; +import { DurationPipe } from './duration.pipe'; import { EmptyPipe } from './empty.pipe'; import { EncodeUriPipe } from './encode-uri.pipe'; import { FilterPipe } from './filter.pipe'; @@ -48,7 +49,8 @@ import { UpperFirstPipe } from './upper-first.pipe'; NotAvailablePipe, IopsPipe, UpperFirstPipe, - RbdConfigurationSourcePipe + RbdConfigurationSourcePipe, + DurationPipe ], exports: [ BooleanTextPipe, @@ -72,7 +74,8 @@ import { UpperFirstPipe } from './upper-first.pipe'; NotAvailablePipe, IopsPipe, UpperFirstPipe, - RbdConfigurationSourcePipe + RbdConfigurationSourcePipe, + DurationPipe ], providers: [ BooleanTextPipe, -- 2.39.5