1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2024-11-03 21:04:03 +08:00

Adding statistic to filter bar. fixes #654

This commit is contained in:
Patrik J. Braun 2023-04-13 00:16:31 +02:00
parent 9014d98f6c
commit fdea2b570f
5 changed files with 134 additions and 7 deletions

View File

@ -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;
}

View File

@ -2,6 +2,42 @@
<div class="card-body">
<div class="row">
<div class="col-md-1-half col-12 d-table">
</div>
<div class="col-md-9 col-12 date-frequency" *ngIf="showStatistic">
<ng-container *ngFor="let freq of MediaCountOverTime; count as length">
<div class="d-inline-block date-frequency-column"
[style.width.%]="(1/length)*100"
[title]="(freq.date | date: 'medium') + ' (' + freq.count+')'">
<div class=" text-center " [style.height.%]="100-(freq.count/freq.max)*100">
<div class="d-none d-lg-block" *ngIf="freq.count < freq.max/2">{{freq.count}}</div>
</div>
<div class="text-bg-primary text-center border border-primary"
[class.text-bg-secondary]="freq.endDate.getTime()<ActiveFilters.dateFilter.minFilter || freq.date.getTime()>ActiveFilters.dateFilter.maxFilter "
[class.border-secondary]="freq.endDate.getTime()<ActiveFilters.dateFilter.minFilter || freq.date.getTime()>ActiveFilters.dateFilter.maxFilter "
[style.height.%]="(freq.count/freq.max)*100">
<div class="d-none d-lg-block" *ngIf="freq.count >= freq.max/2">{{freq.count}}</div>
</div>
<div class="text-center d-none d-md-block">
{{freq.date | date: freq.dateStr}}
</div>
</div>
</ng-container>
</div>
<div class="col-md-1-half col-12 d-table"></div>
</div>
<div class="row">
<div class="position-absolute">
<div class="text-center">
<span
[class.oi-chevron-bottom]="showStatistic"
[class.oi-chevron-top]="!showStatistic"
(click)="showStatistic = !showStatistic"
style="top: -2px; cursor: pointer"
class="oi"></span>
</div>
</div>
<div class="col-md-1-half col-12 d-table">
<div
*ngIf="ActiveFilters.dateFilter.minFilter !== NUMBER_MIN_VALUE"

View File

@ -1,6 +1,6 @@
import { OnDestroy, OnInit,Component } from '@angular/core';
import { RouterLink } from '@angular/router';
import { FilterOption, FilterService, SelectedFilter } from './filter.service';
import {Component, OnDestroy, OnInit} from '@angular/core';
import {RouterLink} from '@angular/router';
import {FilterOption, FilterService, SelectedFilter} from './filter.service';
@Component({
selector: 'app-gallery-filter',
@ -14,6 +14,7 @@ export class GalleryFilterComponent implements OnInit, OnDestroy {
maxDate = 100;
NUMBER_MAX_VALUE = Number.MAX_VALUE;
NUMBER_MIN_VALUE = Number.MIN_VALUE;
showStatistic = false;
constructor(public filterService: FilterService) {
this.unknownText = '<' + $localize`unknown` + '>';
@ -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));
}

View File

@ -120,14 +120,15 @@ export class FilterService {
},
],
});
public prefiltered: DirectoryContent;
private readonly HOUR = 60 * 60 * 1000;
public applyFilters(
directoryContent: Observable<DirectoryContent>
): Observable<DirectoryContent> {
return directoryContent.pipe(
switchMap((dirContent: DirectoryContent) => {
this.prefiltered = dirContent;
this.resetFilters(false);
return this.activeFilters.pipe(
map((afilters) => {

View File

@ -79,6 +79,6 @@
</div>
<app-gallery-filter #filterComponent
*ngIf="showFilters && ItemCount> 0"
[style.height]="sanitizer.bypassSecurityTrustStyle('calc(100dvh - '+(navigatorElement?.nativeElement?.getBoundingClientRect().top+navigatorElement?.nativeElement?.getBoundingClientRect().height)+'px)')"
[style.max-height]="sanitizer.bypassSecurityTrustStyle('calc(100dvh - '+(navigatorElement?.nativeElement?.getBoundingClientRect().top+navigatorElement?.nativeElement?.getBoundingClientRect().height)+'px)')"
class="position-absolute w-100"></app-gallery-filter>