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:
parent
9014d98f6c
commit
fdea2b570f
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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) => {
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user