Improve tag list to display all tags in the selection

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/4/head
trivernis 3 years ago
parent b81a83a328
commit 45fffba33a

@ -48,6 +48,7 @@ import {MatMenuModule} from "@angular/material/menu";
import { ConfirmDialogComponent } from './components/confirm-dialog/confirm-dialog.component'; import { ConfirmDialogComponent } from './components/confirm-dialog/confirm-dialog.component';
import { FilesTabSidebarComponent } from './pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component'; import { FilesTabSidebarComponent } from './pages/home/files-tab/files-tab-sidebar/files-tab-sidebar.component';
import {MatExpansionModule} from "@angular/material/expansion"; import {MatExpansionModule} from "@angular/material/expansion";
import { TagItemComponent } from './components/tag-item/tag-item.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -66,6 +67,7 @@ import {MatExpansionModule} from "@angular/material/expansion";
AddRepositoryDialogComponent, AddRepositoryDialogComponent,
ConfirmDialogComponent, ConfirmDialogComponent,
FilesTabSidebarComponent, FilesTabSidebarComponent,
TagItemComponent,
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

@ -0,0 +1,4 @@
<div class="tag-item-wrapper">
<span *ngIf="tag.namespace" class="tag-item-namespace" [style]="{color: namespaceColor}">{{tag.namespace}}:</span>
<span class="tag-item-name" [style]="{color: tagColor}">{{tag.name}}</span>
</div>

@ -0,0 +1,10 @@
.tag-item-wrapper {
display: inline;
width: 100%;
padding: 0.25em;
}
.tag-item-namespace {
margin-right: 0.25em;
opacity: 80%;
}

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TagItemComponent } from './tag-item.component';
describe('TagItemComponent', () => {
let component: TagItemComponent;
let fixture: ComponentFixture<TagItemComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ TagItemComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(TagItemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -0,0 +1,16 @@
import {Component, Input, OnInit} from '@angular/core';
import {Tag} from "../../models/Tag";
@Component({
selector: 'app-tag-item',
templateUrl: './tag-item.component.html',
styleUrls: ['./tag-item.component.scss']
})
export class TagItemComponent {
@Input() tag!: Tag;
@Input() namespaceColor: string | undefined;
@Input() tagColor: string | undefined;
constructor() { }
}

@ -1,19 +1,22 @@
<div class="sidebar-inner"> <div class="sidebar-inner">
<mat-tab-group headerPosition="below"> <mat-tab-group headerPosition="below">
<mat-tab label="Search"> <mat-tab label="Search">
<div class="search-tab-inner" fxLayout="column"> <div class="search-tab-inner" fxLayout="column">
<div id="file-search-input" > <div id="file-search-input" >
<app-file-search #filesearch (searchStartEvent)="this.searchStartEvent.emit()" <app-file-search #filesearch (searchStartEvent)="this.searchStartEvent.emit()"
(searchEndEvent)="this.searchEndEvent.emit()" [validTags]="this.getValidTagsForSearch()"></app-file-search> (searchEndEvent)="this.searchEndEvent.emit()" [validTags]="this.getValidTagsForSearch()"></app-file-search>
</div> </div>
<div id="file-tag-list" fxFlex fxFlexAlign="start" fxFlexFill> <mat-divider fxFlex="1em"></mat-divider>
<h1>Selection Tags</h1> <div class="tag-list-header" fxFlex="40px">
<mat-selection-list [multiple]="false" *ngIf="tags.length > 0" <h2>Tags</h2>
(selectionChange)="addSearchTagFromList($event)"> <mat-divider></mat-divider>
<mat-list-option </div>
*ngFor="let tag of tags" <div class="file-tag-list" fxFlex fxFlexAlign="start" fxFlexFill>
[value]="tag.getNormalizedOutput()">{{tag.getNormalizedOutput()}}</mat-list-option> <cdk-virtual-scroll-viewport itemSize="50" maxBufferPx="4000" minBufferPx="500">
</mat-selection-list> <div class="selectable-tag" *cdkVirtualFor="let tag of tags" matRipple (click)="addSearchTag(tag)">
<app-tag-item [tag]="tag"></app-tag-item>
</div>
</cdk-virtual-scroll-viewport>
</div> </div>
</div> </div>
</mat-tab> </mat-tab>

@ -8,13 +8,7 @@ app-file-search {
overflow: hidden; overflow: hidden;
} }
#file-tag-list { mat-tab-group, mat-tab, .file-tag-list {
height: 100%;
overflow-y: auto;
width: 100%;
}
mat-tab-group, mat-tab {
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
@ -29,3 +23,51 @@ mat-selection-list {
width: 100%; width: 100%;
display: block; display: block;
} }
.selectable-tag {
height: 50px;
display: flex;
font-size: 1.2em;
cursor: pointer;
transition-duration: 0.1s;
user-select: none;
app-tag-item {
margin: auto auto auto 0.25em;
}
}
.selectable-tag:hover {
background-color: darken(dimgrey, 10);
}
.selectable-tag:active {
cursor: pointer;
}
.file-tag-list-inner {
display: block;
height: 100%;
width: 100%;
overflow: hidden;
}
cdk-virtual-scroll-viewport {
height: 100%;
width: 100%;
overflow-y: auto;
}
mat-divider {
width: 100%;
}
.tag-list-header {
width: 100%;
display: flex;
flex-direction: column;
h2 {
margin: auto;
}
}

@ -36,31 +36,33 @@ export class FilesTabSidebarComponent implements OnInit, OnChanges {
this.files = files; this.files = files;
await this.loadTagsForDisplayedFiles(); await this.loadTagsForDisplayedFiles();
}); });
this.repoService.selectedRepository.subscribe(async (repo) => repo && this.fileSearch && await this.fileSearch.searchForFiles()); this.repoService.selectedRepository.subscribe(
async (repo) => repo && this.fileSearch && await this.fileSearch.searchForFiles());
} }
async ngOnInit() { async ngOnInit() {
this.fileSearch && await this.fileSearch.searchForFiles(); this.fileSearch && await this.fileSearch.searchForFiles();
if (this.tags.length === 0) {
this.tags = this.tagsOfFiles;
}
} }
public async ngOnChanges(changes: SimpleChanges): Promise<void >{ public async ngOnChanges(changes: SimpleChanges): Promise<void> {
if (changes["selectedFiles"]) { if (changes["selectedFiles"]) {
const tags = await this.tagService.getTagsForFiles(this.selectedFiles.map(f => f.hash)); await this.showFileDetails(this.selectedFiles);
this.tags = tags.sort((a, b) => a.getNormalizedOutput().localeCompare(b.getNormalizedOutput())); this.showAllTagsFallback();
} }
} }
async loadTagsForDisplayedFiles() { async loadTagsForDisplayedFiles() {
this.tagsOfFiles = await this.tagService.getTagsForFiles(this.files.map(f => f.hash)); this.tagsOfFiles = await this.tagService.getTagsForFiles(
this.files.map(f => f.hash));
this.showAllTagsFallback();
} }
async addSearchTagFromList(event: MatSelectionListChange) { async addSearchTag(tag: Tag) {
if (event.options.length > 0) { this.fileSearch.addSearchTag(tag.getNormalizedOutput());
const tag = event.options[0].value; await this.fileSearch.searchForFiles();
this.fileSearch.addSearchTag(tag);
await this.fileSearch.searchForFiles();
}
event.source.deselectAll();
} }
getValidTagsForSearch(): string[] { getValidTagsForSearch(): string[] {
@ -69,6 +71,14 @@ export class FilesTabSidebarComponent implements OnInit, OnChanges {
async showFileDetails(files: File[]) { async showFileDetails(files: File[]) {
this.tags = await this.tagService.getTagsForFiles(files.map(f => f.hash)) this.tags = await this.tagService.getTagsForFiles(files.map(f => f.hash))
this.tags = this.tags.sort((a, b) => a.getNormalizedOutput().localeCompare(b.getNormalizedOutput())); this.tags = this.tags.sort(
(a, b) => a.getNormalizedOutput().localeCompare(b.getNormalizedOutput()));
}
showAllTagsFallback() {
if (this.tags.length === 0) {
this.tags = this.tagsOfFiles.sort(
(a, b) => a.getNormalizedOutput().localeCompare(b.getNormalizedOutput()));;
}
} }
} }

Loading…
Cancel
Save