From 2a1a44ee5ab70e8efc19afc5a2d5ebc5fb32866b Mon Sep 17 00:00:00 2001 From: GabrielMeyer Date: Mon, 29 Jul 2019 16:15:47 +0200 Subject: [PATCH] Saves the value of the local search in 'list-view-table' - Builds a new component 'rounded-input' to have a input-field with rounded borders. - Saves the input on every change in the local storage. - In the `OnInit`-function this value is restored. --- .../list-view-table.component.html | 3 +- .../list-view-table.component.ts | 43 ++++- .../rounded-input.component.html | 17 ++ .../rounded-input.component.scss | 47 ++++++ .../rounded-input.component.spec.ts | 26 ++++ .../rounded-input/rounded-input.component.ts | 147 ++++++++++++++++++ .../sort-filter-bar.component.html | 20 +-- .../sort-filter-bar.component.scss | 4 + .../sort-filter-bar.component.ts | 40 ++--- client/src/app/shared/shared.module.ts | 7 +- .../agenda-list/agenda-list.component.html | 15 +- .../assignment-list.component.html | 2 +- .../motion-block-list.component.html | 2 +- .../motion-list/motion-list.component.html | 2 +- .../workflow-list.component.html | 12 +- .../user-list/user-list.component.html | 14 +- 16 files changed, 337 insertions(+), 64 deletions(-) create mode 100644 client/src/app/shared/components/rounded-input/rounded-input.component.html create mode 100644 client/src/app/shared/components/rounded-input/rounded-input.component.scss create mode 100644 client/src/app/shared/components/rounded-input/rounded-input.component.spec.ts create mode 100644 client/src/app/shared/components/rounded-input/rounded-input.component.ts diff --git a/client/src/app/shared/components/list-view-table/list-view-table.component.html b/client/src/app/shared/components/list-view-table/list-view-table.component.html index aa9659cf3..87a3165b4 100644 --- a/client/src/app/shared/components/list-view-table/list-view-table.component.html +++ b/client/src/app/shared/components/list-view-table/list-view-table.component.html @@ -4,6 +4,7 @@ [filterCount]="countFilter" [filterService]="filterService" [sortService]="sortService" + [searchFieldInput]="inputValue" (searchFieldChange)="searchFilter($event)" > @@ -14,7 +15,7 @@ [ngClass]="{ 'virtual-scroll-with-head-bar ngrid-hide-head': showFilterBar, 'virtual-scroll-full-page': !showFilterBar, - 'multiselect': multiSelect + multiselect: multiSelect }" cellTooltip [showHeader]="!showFilterBar" diff --git a/client/src/app/shared/components/list-view-table/list-view-table.component.ts b/client/src/app/shared/components/list-view-table/list-view-table.component.ts index 1276accdd..567eaa6eb 100644 --- a/client/src/app/shared/components/list-view-table/list-view-table.component.ts +++ b/client/src/app/shared/components/list-view-table/list-view-table.component.ts @@ -64,7 +64,7 @@ export interface ColumnRestriction { * [hiddenInMobile]="['state']" * [allowProjector]="false" * [multiSelect]="isMultiSelect" - * scrollKey="motion" + * listStorageKey="motion" * [(selectedRows)]="selectedRows" * (dataSourceChange)="onDataSourceChange($event)" * > @@ -157,7 +157,7 @@ export class ListViewTableComponent { + this.inputValue = await this.store.get(`query_${key}`); + } + /** * Automatically scrolls to a stored scroll position * diff --git a/client/src/app/shared/components/rounded-input/rounded-input.component.html b/client/src/app/shared/components/rounded-input/rounded-input.component.html new file mode 100644 index 000000000..29d5ca83d --- /dev/null +++ b/client/src/app/shared/components/rounded-input/rounded-input.component.html @@ -0,0 +1,17 @@ +
+
+ search +
+ +
+ close +
+
diff --git a/client/src/app/shared/components/rounded-input/rounded-input.component.scss b/client/src/app/shared/components/rounded-input/rounded-input.component.scss new file mode 100644 index 000000000..f0bcbba45 --- /dev/null +++ b/client/src/app/shared/components/rounded-input/rounded-input.component.scss @@ -0,0 +1,47 @@ +.input-container { + position: relative; + height: 100%; + &, + div { + display: flex; + align-items: center; + z-index: 1; + } + div { + position: absolute; + &.input-prefix { + left: 8px; + } + &.input-suffix { + right: 8px; + color: #666; + } + } + + .rounded-input { + outline: 0; + z-index: 0; + height: 24px; + width: 100%; + padding: 8px 39px; + border-radius: 32px; + font-size: 16px; + border: 1px solid #ccc; + color: #666; + transition: all 0.25s ease; + + &.small { + height: 14px; + font-size: 14px; + width: 100px; + + &:focus { + width: 200px; + } + } + } + + mat-icon { + cursor: pointer; + } +} diff --git a/client/src/app/shared/components/rounded-input/rounded-input.component.spec.ts b/client/src/app/shared/components/rounded-input/rounded-input.component.spec.ts new file mode 100644 index 000000000..c0af92e7a --- /dev/null +++ b/client/src/app/shared/components/rounded-input/rounded-input.component.spec.ts @@ -0,0 +1,26 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { E2EImportsModule } from 'e2e-imports.module'; + +import { RoundedInputComponent } from './rounded-input.component'; + +describe('RoundedInputComponent', () => { + let component: RoundedInputComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [E2EImportsModule] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(RoundedInputComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/shared/components/rounded-input/rounded-input.component.ts b/client/src/app/shared/components/rounded-input/rounded-input.component.ts new file mode 100644 index 000000000..b0e18750f --- /dev/null +++ b/client/src/app/shared/components/rounded-input/rounded-input.component.ts @@ -0,0 +1,147 @@ +import { Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; +import { FormControl } from '@angular/forms'; + +import { Subscription } from 'rxjs'; +import { debounceTime } from 'rxjs/operators'; + +@Component({ + selector: 'os-rounded-input', + templateUrl: './rounded-input.component.html', + styleUrls: ['./rounded-input.component.scss'] +}) +export class RoundedInputComponent implements OnInit, OnDestroy { + /** + * Reference to the ``-element. + */ + @ViewChild('osInput', { static: true }) + public osInput: ElementRef; + + /** + * Setter for the model. This could be useful, if the value of the input + * should be set from outside of this component. + * + * @param value The new value of the input. + */ + @Input() + public set model(value: string) { + if (!!value) { + this.modelForm.setValue(value); + } + } + + /** + * Getter for the model. + * + * @returns {string} The value of the FormControl. If this is undefined or null, it returns an empty string. + */ + public get model(): string { + return this.modelForm ? this.modelForm.value : ''; + } + + /** + * Controls the size of the input. + * + * Possible values are `'small' | 'medium' | 'large'`. + * Defaults to `'medium'`. + */ + @Input() + public size: 'small' | 'medium' | 'large' = 'medium'; + + /** + * Custom `FormControl`. + */ + @Input() + public modelForm: FormControl; + + /** + * Boolean, whether the input should be focussed automatically, if the component enters the DOM. + */ + @Input() + public autofocus = false; + + /** + * Boolean, whether the input should fire the value-change-event after a specific time. + */ + @Input() + public lazyInput = false; + + /** + * Placeholder for the input. Defaults to `Search...`. + */ + @Input() + public placeholder = 'Search...'; + + /** + * Boolean, whether the input will be cleared, if the user presses `Escape`. + */ + @Input() + public clearOnEscape = true; + + /** + * EventHandler for the input-changes. + */ + @Output() + public oninput: EventEmitter = new EventEmitter(); + + /** + * EventHandler for the key-events. + */ + @Output() + public onkeyup: EventEmitter = new EventEmitter(); + + /** + * Subscription, that will handle the value-changes of the input. + */ + private subscription: Subscription; + + /** + * Default constructor + */ + public constructor() { + if (!this.modelForm) { + this.modelForm = new FormControl(this.model); + } + } + + /** + * Overwrites `OnInit` - initializes the subscription. + */ + public ngOnInit(): void { + this.subscription = this.modelForm.valueChanges + .pipe(debounceTime(this.lazyInput ? 250 : 0)) + .subscribe(nextValue => { + this.oninput.emit(nextValue); + }); + } + + /** + * Overwrites `OnDestroy` - clears the subscription. + */ + public ngOnDestroy(): void { + if (this.subscription) { + this.subscription.unsubscribe(); + this.subscription = null; + } + } + + /** + * Function to clear the input and refocus it. + */ + public clear(): void { + this.osInput.nativeElement.focus(); + this.modelForm.setValue(''); + } + + /** + * Function to handle typing. + * Useful to listen to special keys. + * + * @param event The `KeyboardEvent`. + */ + public keyPressed(event: KeyboardEvent): void { + if (this.clearOnEscape && event.key === 'Escape') { + this.clear(); + } + this.onkeyup.emit(event); + } +} diff --git a/client/src/app/shared/components/sort-filter-bar/sort-filter-bar.component.html b/client/src/app/shared/components/sort-filter-bar/sort-filter-bar.component.html index 2cfc5a2cf..2c01903f0 100644 --- a/client/src/app/shared/components/sort-filter-bar/sort-filter-bar.component.html +++ b/client/src/app/shared/components/sort-filter-bar/sort-filter-bar.component.html @@ -35,22 +35,18 @@ - - - - + - +
keyboard_arrow_right diff --git a/client/src/app/shared/components/sort-filter-bar/sort-filter-bar.component.scss b/client/src/app/shared/components/sort-filter-bar/sort-filter-bar.component.scss index c80222af3..2be3bfe6e 100644 --- a/client/src/app/shared/components/sort-filter-bar/sort-filter-bar.component.scss +++ b/client/src/app/shared/components/sort-filter-bar/sort-filter-bar.component.scss @@ -69,3 +69,7 @@ span.right-with-margin { height: 0px; width: 0px; } + +os-rounded-input { + margin: 0 10px; +} diff --git a/client/src/app/shared/components/sort-filter-bar/sort-filter-bar.component.ts b/client/src/app/shared/components/sort-filter-bar/sort-filter-bar.component.ts index cc762135c..19bb28a8c 100644 --- a/client/src/app/shared/components/sort-filter-bar/sort-filter-bar.component.ts +++ b/client/src/app/shared/components/sort-filter-bar/sort-filter-bar.component.ts @@ -63,6 +63,16 @@ export class SortFilterBarComponent { @Input() public itemsVerboseName: string; + /** + * Custom input for the search-field. + * Used to change the value of the input from outside of this component. + */ + @Input() + public searchFieldInput: string; + + /** + * EventEmitter to emit the next search-value. + */ @Output() public searchFieldChange = new EventEmitter(); @@ -83,11 +93,6 @@ export class SortFilterBarComponent { */ private _showFilterSort = true; - /** - * The 'opened/active' state of the fulltext filter input field - */ - public isSearchBar = false; - /** * Return the amount of data passing filters. Priorizes the override in {@link filterCount} over * the information from the filterService @@ -183,18 +188,6 @@ export class SortFilterBarComponent { } } - /** - * Listen to keypresses on the quick-search input - */ - public applySearch(event: KeyboardEvent, value?: string): void { - if (event.key === 'Escape') { - this.searchFieldChange.emit(''); - this.isSearchBar = false; - } else { - this.searchFieldChange.emit(value); - } - } - /** * Checks if there is an active SortService present */ @@ -230,17 +223,4 @@ export class SortFilterBarComponent { const itemProperty = option.property as string; return itemProperty.charAt(0).toUpperCase() + itemProperty.slice(1); } - - /** - * Open/closes the 'quick search input'. When closing, also removes the filter - * that input applied - */ - public toggleSearchBar(): void { - if (!this.isSearchBar) { - this.isSearchBar = true; - } else { - this.searchFieldChange.emit(''); - this.isSearchBar = false; - } - } } diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index 6e7928cac..78dec5a97 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts @@ -94,6 +94,7 @@ import { ListViewTableComponent } from './components/list-view-table/list-view-t import { AgendaContentObjectFormComponent } from './components/agenda-content-object-form/agenda-content-object-form.component'; import { ExtensionFieldComponent } from './components/extension-field/extension-field.component'; import { AttachmentControlComponent } from './components/attachment-control/attachment-control.component'; +import { RoundedInputComponent } from './components/rounded-input/rounded-input.component'; /** * Share Module for all "dumb" components and pipes. @@ -231,7 +232,8 @@ import { AttachmentControlComponent } from './components/attachment-control/atta PblNgridTargetEventsModule, ListViewTableComponent, AgendaContentObjectFormComponent, - ExtensionFieldComponent + ExtensionFieldComponent, + RoundedInputComponent ], declarations: [ PermsDirective, @@ -268,7 +270,8 @@ import { AttachmentControlComponent } from './components/attachment-control/atta ListViewTableComponent, AgendaContentObjectFormComponent, ExtensionFieldComponent, - AttachmentControlComponent + AttachmentControlComponent, + RoundedInputComponent ], providers: [ { provide: DateAdapter, useClass: OpenSlidesDateAdapter }, diff --git a/client/src/app/site/agenda/components/agenda-list/agenda-list.component.html b/client/src/app/site/agenda/components/agenda-list/agenda-list.component.html index ce5b33753..8e3bad714 100644 --- a/client/src/app/site/agenda/components/agenda-list/agenda-list.component.html +++ b/client/src/app/site/agenda/components/agenda-list/agenda-list.component.html @@ -21,7 +21,7 @@ [restricted]="restrictedColumns" [hiddenInMobile]="['info']" [filterProps]="filterProps" - scrollKey="agenda" + listStorageKey="agenda" [(selectedRows)]="selectedRows" (dataSourceChange)="onDataSourceChange($event)" > @@ -200,12 +200,21 @@ - - diff --git a/client/src/app/site/assignments/components/assignment-list/assignment-list.component.html b/client/src/app/site/assignments/components/assignment-list/assignment-list.component.html index 9cfefbc86..c72c3f88d 100644 --- a/client/src/app/site/assignments/components/assignment-list/assignment-list.component.html +++ b/client/src/app/site/assignments/components/assignment-list/assignment-list.component.html @@ -26,7 +26,7 @@ [columns]="tableColumnDefinition" [filterProps]="filterProps" [multiSelect]="isMultiSelect" - scrollKey="assignments" + listStorageKey="assignments" [(selectedRows)]="selectedRows" (dataSourceChange)="onDataSourceChange($event)" > diff --git a/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.html b/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.html index 1ffecbfdb..be4934842 100644 --- a/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.html +++ b/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.html @@ -43,7 +43,7 @@ [showFilterBar]="false" [columns]="tableColumnDefinition" [multiSelect]="isMultiSelect" - scrollKey="motionBlock" + listStorageKey="motionBlock" [(selectedRows)]="selectedRows" (dataSourceChange)="onDataSourceChange($event)" > diff --git a/client/src/app/site/motions/modules/motion-list/components/motion-list/motion-list.component.html b/client/src/app/site/motions/modules/motion-list/components/motion-list/motion-list.component.html index a8843f637..879e7d01d 100644 --- a/client/src/app/site/motions/modules/motion-list/components/motion-list/motion-list.component.html +++ b/client/src/app/site/motions/modules/motion-list/components/motion-list/motion-list.component.html @@ -50,7 +50,7 @@ [restricted]="restrictedColumns" [filterProps]="filterProps" [hiddenInMobile]="['state']" - scrollKey="motion" + listStorageKey="motion" [(selectedRows)]="selectedRows" (dataSourceChange)="onDataSourceChange($event)" > diff --git a/client/src/app/site/motions/modules/motion-workflow/components/workflow-list/workflow-list.component.html b/client/src/app/site/motions/modules/motion-workflow/components/workflow-list/workflow-list.component.html index 0a62cf95d..9dedeecc4 100644 --- a/client/src/app/site/motions/modules/motion-workflow/components/workflow-list/workflow-list.component.html +++ b/client/src/app/site/motions/modules/motion-workflow/components/workflow-list/workflow-list.component.html @@ -6,7 +6,7 @@ @@ -36,11 +36,17 @@

Please enter a name for the new workflow:

- +
- - +