From fdea2b570f45a833eb6d359dec79e640968488a5 Mon Sep 17 00:00:00 2001 From: "Patrik J. Braun" Date: Thu, 13 Apr 2023 00:16:31 +0200 Subject: [PATCH] Adding statistic to filter bar. fixes #654 --- .../filter/filter.gallery.component.css | 7 ++ .../filter/filter.gallery.component.html | 36 +++++++ .../filter/filter.gallery.component.ts | 93 ++++++++++++++++++- .../app/ui/gallery/filter/filter.service.ts | 3 +- .../navigator.gallery.component.html | 2 +- 5 files changed, 134 insertions(+), 7 deletions(-) diff --git a/src/frontend/app/ui/gallery/filter/filter.gallery.component.css b/src/frontend/app/ui/gallery/filter/filter.gallery.component.css index 3e1edbd7..c1a581fb 100644 --- a/src/frontend/app/ui/gallery/filter/filter.gallery.component.css +++ b/src/frontend/app/ui/gallery/filter/filter.gallery.component.css @@ -158,3 +158,10 @@ div.date-filter-wrapper > input[type=range]::-ms-tooltip { display: none; } +.date-frequency .date-frequency-column div { + box-sizing: content-box; +} + +.date-frequency > div { + height: 40px; +} diff --git a/src/frontend/app/ui/gallery/filter/filter.gallery.component.html b/src/frontend/app/ui/gallery/filter/filter.gallery.component.html index 4fdf3d39..73fdf840 100644 --- a/src/frontend/app/ui/gallery/filter/filter.gallery.component.html +++ b/src/frontend/app/ui/gallery/filter/filter.gallery.component.html @@ -2,6 +2,42 @@
+
+
+
+ +
+
+
{{freq.count}}
+
+
+
{{freq.count}}
+
+
+ {{freq.date | date: freq.dateStr}} +
+
+
+
+
+ +
+
+
+
+ +
+
'; @@ -22,7 +23,7 @@ export class GalleryFilterComponent implements OnInit, OnDestroy { get MinDatePrc(): number { return ( ((this.ActiveFilters.dateFilter.minFilter - - this.ActiveFilters.dateFilter.minDate) / + this.ActiveFilters.dateFilter.minDate) / (this.ActiveFilters.dateFilter.maxDate - this.ActiveFilters.dateFilter.minDate)) * 100 @@ -32,7 +33,7 @@ export class GalleryFilterComponent implements OnInit, OnDestroy { get MaxDatePrc(): number { return ( ((this.ActiveFilters.dateFilter.maxFilter - - this.ActiveFilters.dateFilter.minDate) / + this.ActiveFilters.dateFilter.minDate) / (this.ActiveFilters.dateFilter.maxDate - this.ActiveFilters.dateFilter.minDate)) * 100 @@ -53,6 +54,88 @@ export class GalleryFilterComponent implements OnInit, OnDestroy { return this.filterService.activeFilters.value; } + get MediaCountOverTime(): { date: Date, endDate: Date, dateStr: string, count: number, max: number }[] { + if (!this.filterService.prefiltered || + !this.filterService.prefiltered.media || + this.filterService.prefiltered.media.length === 0) { + return []; + } + const ret: { date: Date, endDate: Date, dateStr: string, count: number, max: number }[] = []; + const diff = (this.ActiveFilters.dateFilter.maxDate - this.ActiveFilters.dateFilter.minDate) / 1000; + const H = 60 * 60; + const D = H * 24; + const M = D * 30; + const Y = D * 365; + const Dec = Y * 10; + const Sen = Y * 100; + const divs = [H, D, M, Y, Dec, Sen]; + const startMediaTime = this.filterService.prefiltered.media.reduce((p, c) => p.metadata.creationDate < c.metadata.creationDate ? p : c).metadata.creationDate; + + // finding the resolution + let usedDiv = H; + for (let i = 0; i < divs.length; ++i) { + if (diff / divs[i] < 15) { + usedDiv = divs[i]; + break; + } + } + + // getting the first date (truncated to the resolution) + let startMediaDate = new Date(startMediaTime); + if (usedDiv >= Y) { + const fy = (new Date(startMediaTime).getFullYear()); + startMediaDate = new Date(fy - fy % (usedDiv / Y), 0, 1); + } else if (usedDiv === M) { + startMediaDate = new Date(startMediaDate.getFullYear(), startMediaDate.getMonth(), 1); + } else { + startMediaDate = new Date(startMediaTime - startMediaTime % usedDiv); + } + + this.filterService.prefiltered.media.forEach(m => { + const key = Math.floor((m.metadata.creationDate - startMediaTime) / 1000 / usedDiv); + + const getDate = (index: number) => { + let d: Date; + if (usedDiv >= Y) { + d = new Date(startMediaDate.getFullYear() + (index * (usedDiv / Y)), 0, 1); + } else if (usedDiv === M) { + d = new Date(startMediaDate.getFullYear(), startMediaDate.getMonth() + index, 1); + } else if (usedDiv === D) { + d = new Date(startMediaDate.getFullYear(), startMediaDate.getMonth(), startMediaDate.getDate() + index, 1); + } else { + d = (new Date(startMediaDate.getTime() + (index * usedDiv * 1000))); + } + return d; + }; + // extending the array + while (ret.length <= key) { + let dStr: string; + // getting date range start for entry and also UI date pattern + if (usedDiv >= Y) { + dStr = 'yyyy'; + } else if (usedDiv === M) { + dStr = 'MMM'; + } else if (usedDiv === D) { + dStr = 'EEE'; + } else { + dStr = 'HH'; + } + ret.push({date: getDate(ret.length), endDate: getDate(ret.length + 1), dateStr: dStr, count: 0, max: 0}); + } + + ret[key].count++; + }); + + // don't show if there is only one column + if (ret.length <= 1) { + return []; + } + + const max = ret.reduce((p, c) => Math.max(p, c.count), 0); + ret.forEach(v => v.max = max); + return ret; + } + ngOnDestroy(): void { setTimeout(() => this.filterService.setShowingFilters(false)); } diff --git a/src/frontend/app/ui/gallery/filter/filter.service.ts b/src/frontend/app/ui/gallery/filter/filter.service.ts index 441602fe..206b237b 100644 --- a/src/frontend/app/ui/gallery/filter/filter.service.ts +++ b/src/frontend/app/ui/gallery/filter/filter.service.ts @@ -120,14 +120,15 @@ export class FilterService { }, ], }); + public prefiltered: DirectoryContent; - private readonly HOUR = 60 * 60 * 1000; public applyFilters( directoryContent: Observable ): Observable { return directoryContent.pipe( switchMap((dirContent: DirectoryContent) => { + this.prefiltered = dirContent; this.resetFilters(false); return this.activeFilters.pipe( map((afilters) => { diff --git a/src/frontend/app/ui/gallery/navigator/navigator.gallery.component.html b/src/frontend/app/ui/gallery/navigator/navigator.gallery.component.html index e9b34e7b..2b696656 100644 --- a/src/frontend/app/ui/gallery/navigator/navigator.gallery.component.html +++ b/src/frontend/app/ui/gallery/navigator/navigator.gallery.component.html @@ -79,6 +79,6 @@