1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2024-12-23 01:27:14 +02:00

Implementing filter pinning #287

This commit is contained in:
Patrik J. Braun 2022-02-18 23:58:23 +01:00
parent 44e7445e0f
commit d30c0f5292
4 changed files with 81 additions and 10 deletions

View File

@ -7,6 +7,33 @@
cursor: pointer; cursor: pointer;
} }
.filter-option .oi {
height: 0;
font-size: 0;
transition: all 0.1s;
display: inline-block;
padding: 0;
margin: 0;
color: #aaa;
}
.filter-option:hover .oi.filter-pin, .filter-option .oi.filter-only-selected {
display: inline-block;
height: auto;
font-size: 1rem;
padding: 0 0.3rem;
margin-left: -0.6rem;
}
.filter-option:hover .oi.filter-pin:hover {
color: #212529;
}
.filter-option .oi.filter-only-selected {
color: #007bff;
}
.filter-container { .filter-container {
margin-top: -1rem; margin-top: -1rem;
} }

View File

@ -11,15 +11,23 @@
<ul class="list-group" *ngIf="filter.options.length > 0"> <ul class="list-group" *ngIf="filter.options.length > 0">
<li <li
*ngFor="let option of filter.options" *ngFor="let option of filter.options"
[class.unselected] = "!option.selected" [class.unselected]="!option.selected"
(click)="option.selected = !option.selected; filterService.onFilterChange()" (click)="option.selected = !option.selected; filterService.onFilterChange()"
class="filter-option list-group-item list-group-item-action d-flex justify-content-between align-items-center"> class="filter-option list-group-item list-group-item-action d-flex justify-content-between align-items-center">
{{option.name === undefined ? unknownText : option.name}}
<div>
<span (click)="toggleSelectOnly(filter, option, $event)"
class="oi oi-pin" title="Select only this"
[ngClass]="isOnlySelected(filter,option) ? 'filter-only-selected' : 'filter-pin'"
i18n-title></span>
{{option.name === undefined ? unknownText : option.name}}
</div>
<span class="badge badge-pill" <span class="badge badge-pill"
[class.badge-primary] = "option.selected" [class.badge-primary]="option.selected"
[class.badge-secondary] = "!option.selected" [class.badge-secondary]="!option.selected"
>{{option.count}}</span> >{{option.count}}</span>
</li> </li>
</ul> </ul>
<div class="card-body text-center" *ngIf="filter.options.length === 0" i18n>Nothing to filter</div> <div class="card-body text-center" *ngIf="filter.options.length === 0" i18n>Nothing to filter</div>

View File

@ -1,6 +1,6 @@
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {RouterLink} from '@angular/router'; import {RouterLink} from '@angular/router';
import {FilterService} from './filter.service'; import {FilterOption, FilterService, SelectedFilter} from './filter.service';
import {OnDestroy, OnInit} from '../../../../../../node_modules/@angular/core'; import {OnDestroy, OnInit} from '../../../../../../node_modules/@angular/core';
@Component({ @Component({
@ -25,5 +25,29 @@ export class GalleryFilterComponent implements OnInit, OnDestroy {
this.filterService.setShowingFilters(true); this.filterService.setShowingFilters(true);
} }
isOnlySelected(filter: SelectedFilter, option: FilterOption): boolean {
for (const o of filter.options) {
if (o === option) {
if (o.selected === false) {
return false;
}
} else {
if (o.selected === true) {
return false;
}
}
}
return true;
}
toggleSelectOnly(filter: SelectedFilter, option: FilterOption, event: MouseEvent): void {
if (this.isOnlySelected(filter, option)) {
filter.options.forEach(o => o.selected = true);
} else {
filter.options.forEach(o => o.selected = (o === option));
}
event.stopPropagation();
this.filterService.onFilterChange();
}
} }

View File

@ -8,16 +8,22 @@ export enum FilterRenderType {
enum = 1, range = 2 enum = 1, range = 2
} }
interface Filter { export interface Filter {
name: string; name: string;
mapFn: (m: PhotoDTO) => (string | number)[] | (string | number); mapFn: (m: PhotoDTO) => (string | number)[] | (string | number);
renderType: FilterRenderType; renderType: FilterRenderType;
isArrayValue?: boolean; isArrayValue?: boolean;
} }
interface SelectedFilter { export interface FilterOption {
name: string;
count: number;
selected: boolean;
}
export interface SelectedFilter {
filter: Filter; filter: Filter;
options: { name: string, count: number, selected: boolean }[]; options: FilterOption[];
} }
@Injectable() @Injectable()
@ -35,6 +41,12 @@ export class FilterService {
renderType: FilterRenderType.enum, renderType: FilterRenderType.enum,
isArrayValue: true, isArrayValue: true,
}, },
{
name: $localize`Faces groups`,
mapFn: (m: PhotoDTO): string => m.metadata.faces?.map(f => f.name).sort().join(', '),
renderType: FilterRenderType.enum,
isArrayValue: false,
},
/* { /* {
name: $localize`Date`, name: $localize`Date`,
mapFn: (m: PhotoDTO): number => m.metadata.creationDate, mapFn: (m: PhotoDTO): number => m.metadata.creationDate,
@ -77,10 +89,10 @@ export class FilterService {
filter: this.AVAILABLE_FILTERS[1], filter: this.AVAILABLE_FILTERS[1],
options: [] options: []
}, { }, {
filter: this.AVAILABLE_FILTERS[4], filter: this.AVAILABLE_FILTERS[5],
options: [] options: []
}, { }, {
filter: this.AVAILABLE_FILTERS[2], filter: this.AVAILABLE_FILTERS[3],
options: [] options: []
} }
]); ]);