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 73fdf840..a2def918 100644 --- a/src/frontend/app/ui/gallery/filter/filter.gallery.component.html +++ b/src/frontend/app/ui/gallery/filter/filter.gallery.component.html @@ -5,10 +5,13 @@
- +
+ container="body" + triggers="mouseenter:mouseleave" + placement="bottom start" + [popover]="(freq.date | date: 'medium') + ' (' + freq.count+')'">
{{freq.count}}
@@ -18,7 +21,7 @@ [style.height.%]="(freq.count/freq.max)*100">
{{freq.count}}
-
+
{{freq.date | date: freq.dateStr}}
@@ -28,8 +31,8 @@
-
-
+
+
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 206b237b..a1109e54 100644 --- a/src/frontend/app/ui/gallery/filter/filter.service.ts +++ b/src/frontend/app/ui/gallery/filter/filter.service.ts @@ -120,15 +120,110 @@ export class FilterService { }, ], }); - public prefiltered: DirectoryContent; + public statistic: { date: Date; endDate: Date; dateStr: string; count: number; max: number; }[] = []; + private getStatistic(prefiltered: DirectoryContent): { date: Date, endDate: Date, dateStr: string, count: number, max: number }[] { + if (!prefiltered || + !prefiltered.media || + prefiltered.media.length === 0) { + return []; + } + const ret: { date: Date, endDate: Date, dateStr: string, count: number, max: number }[] = []; + const minDate = prefiltered.media.reduce( + (p, curr) => Math.min(p, curr.metadata.creationDate), + Number.MAX_VALUE - 1 + ); + const maxDate = prefiltered.media.reduce( + (p, curr) => Math.max(p, curr.metadata.creationDate), + Number.MIN_VALUE + 1 + ); + const diff = (maxDate - minDate) / 1000; + const H = 60 * 60; + const D = H * 24; + const M = D * 30; + const Y = D * 365; + const Y2 = Y * 2; + const Y5 = Y * 5; + const Dec = Y * 10; + const Sen = Y * 100; + const divs = [H, D, M, Y, Y2, Y5, Dec, Sen]; + + // finding the resolution + let usedDiv = H; + for (let i = 0; i < divs.length; ++i) { + if (diff / divs[i] < 26) { + usedDiv = divs[i]; + break; + } + } + + // getting the first date (truncated to the resolution) + const floorDate = (ts: number): number => { + let d = new Date(ts); + if (usedDiv >= Y) { + const fy = (d.getFullYear()); + d = new Date(fy - fy % (usedDiv / Y), 0, 1); + } else if (usedDiv === M) { + d = new Date(d.getFullYear(), d.getMonth(), 1); + } else { + d = new Date(ts - ts % usedDiv); + } + return d.getTime(); + }; + + const startMediaDate = new Date(floorDate(minDate)); + + prefiltered.media.forEach(m => { + const key = Math.floor((floorDate(m.metadata.creationDate) - startMediaDate.getTime()) / 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 = 'y'; + } else if (usedDiv === M) { + dStr = 'y 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; + } public applyFilters( directoryContent: Observable ): Observable { return directoryContent.pipe( switchMap((dirContent: DirectoryContent) => { - this.prefiltered = dirContent; + this.statistic = this.getStatistic(dirContent); this.resetFilters(false); return this.activeFilters.pipe( map((afilters) => {