Merge pull request #4863 from tsiegleauq/ngrid-real-search-filter

Implement NGrids filter function
This commit is contained in:
Sean 2019-07-22 12:19:04 +02:00 committed by GitHub
commit 5c660a373f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 96 additions and 53 deletions

View File

@ -226,27 +226,29 @@ export abstract class BaseFilterListService<V extends BaseViewModel> {
const newDefinitions = this.getFilterDefinitions();
this.store.get<OsFilter[]>('filter_' + this.name).then(storedFilter => {
for (const newDef of newDefinitions) {
let count = 0;
const matchingExistingFilter = storedFilter.find(oldDef => oldDef.property === newDef.property);
for (const option of newDef.options) {
if (typeof option === 'object') {
if (matchingExistingFilter && matchingExistingFilter.options) {
const existingOption = matchingExistingFilter.options.find(
o =>
typeof o !== 'string' &&
JSON.stringify(o.condition) === JSON.stringify(option.condition)
) as OsFilterOption;
if (existingOption) {
option.isActive = existingOption.isActive;
}
if (option.isActive) {
count++;
if (!!storedFilter) {
for (const newDef of newDefinitions) {
let count = 0;
const matchingExistingFilter = storedFilter.find(oldDef => oldDef.property === newDef.property);
for (const option of newDef.options) {
if (typeof option === 'object') {
if (matchingExistingFilter && matchingExistingFilter.options) {
const existingOption = matchingExistingFilter.options.find(
o =>
typeof o !== 'string' &&
JSON.stringify(o.condition) === JSON.stringify(option.condition)
) as OsFilterOption;
if (existingOption) {
option.isActive = existingOption.isActive;
}
if (option.isActive) {
count++;
}
}
}
}
newDef.count = count;
}
newDef.count = count;
}
this.filterDefinitions = newDefinitions;

View File

@ -11,25 +11,30 @@
<!-- vScrollFixed="110" -->
<!-- vScrollAuto () -->
<pbl-ngrid
[ngClass]="showFilterBar ? 'virtual-scroll-with-head-bar' : 'virtual-scroll-full-page'"
[ngClass]="{
'virtual-scroll-with-head-bar ngrid-hide-head': showFilterBar,
'virtual-scroll-full-page': !showFilterBar,
'multiselect': multiSelect
}"
cellTooltip
showHeader="!showFilterBar"
[showHeader]="!showFilterBar"
matCheckboxSelection="selection"
vScrollFixed="110"
[dataSource]="dataSource"
[columns]="columnSet"
[hideColumns]="hiddenColumns"
(rowClick)="onSelectRow($event)"
>
<!-- "row" has the view model -->
<!-- "value" has the property, that was defined in the columnDefinition -->
<!-- "col" has a column reference -->
<!-- Projector column -->
<div *pblNgridCellDef="'projector'; row as viewModel" class="fill">
<div *pblNgridCellDef="'projector'; row as viewModel" class="fill ngrid-lg">
<os-projector-button class="projector-button" [object]="getProjectable(viewModel)"></os-projector-button>
</div>
<!-- Slot transclusion for the individual cells -->
<ng-content select=".cell-slot"></ng-content>
<ng-content class="ngrid-lg" select=".cell-slot"></ng-content>
</pbl-ngrid>
</mat-drawer-container>

View File

@ -3,3 +3,17 @@
.projector-button {
margin: auto;
}
.pbl-ngrid-row {
height: 110px;
}
.pbl-ngrid-cell {
height: inherit;
}
.multiselect {
.pbl-ngrid-cell {
cursor: pointer;
}
}

View File

@ -9,17 +9,19 @@ import {
ViewEncapsulation,
ChangeDetectorRef
} from '@angular/core';
import { Observable } from 'rxjs';
import { PblDataSource, columnFactory, PblNgridComponent, createDS } from '@pebula/ngrid';
import { PblColumnDefinition, PblNgridColumnSet } from '@pebula/ngrid/lib/table';
import { PblNgridDataMatrixRow } from '@pebula/ngrid/target-events';
import { BaseViewModel } from 'app/site/base/base-view-model';
import { BaseProjectableViewModel } from 'app/site/base/base-projectable-view-model';
import { BaseSortListService } from 'app/core/ui-services/base-sort-list.service';
import { BaseViewModelWithContentObject } from 'app/site/base/base-view-model-with-content-object';
import { PblDataSource, columnFactory, PblNgridComponent, createDS } from '@pebula/ngrid';
import { BaseFilterListService } from 'app/core/ui-services/base-filter-list.service';
import { Observable } from 'rxjs';
import { BaseRepository } from 'app/core/repositories/base-repository';
import { BaseModel } from 'app/shared/models/base/base-model';
import { PblColumnDefinition, PblNgridColumnSet } from '@pebula/ngrid/lib/table';
import { Permission, OperatorService } from 'app/core/core-services/operator.service';
import { StorageService } from 'app/core/core-services/storage.service';
import { ViewportService } from 'app/core/ui-services/viewport.service';
@ -221,7 +223,7 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
* Gets the amount of filtered data
*/
public get countFilter(): number {
return this.dataSource.source.length;
return this.dataSource.filteredData.length;
}
/**
@ -358,7 +360,7 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
// Define the columns. Has to be in the OnInit cause "columns" is slower than
// the constructor of this class
this.columnSet = columnFactory()
.default({ width: this.columnMinWidth, css: 'ngrid-lg' })
.default({ width: this.columnMinWidth })
.table(...this.defaultColumns, ...this.columns)
.build();
@ -368,6 +370,22 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
}
}
/**
* Generic click handler for rows. Allow so (multi) select anywhere
* @param event the clicked row
*/
public onSelectRow(event: PblNgridDataMatrixRow<V>): void {
if (this.multiSelect) {
const clickedModel: V = event.row;
const alreadySelected = this.dataSource.selection.isSelected(clickedModel);
if (alreadySelected) {
this.dataSource.selection.deselect(clickedModel);
} else {
this.dataSource.selection.select(clickedModel);
}
}
}
/**
* Depending on the view, the view model in the row can either be a
* `BaseViewModelWithContentObject` or a `BaseViewModelWithContentObject`.

View File

@ -58,6 +58,7 @@ import { AutofocusDirective } from './directives/autofocus.directive';
// PblNgrid. Cleanup Required.
import { PblNgridModule } from '@pebula/ngrid';
import { PblNgridMaterialModule } from '@pebula/ngrid-material';
import { PblNgridTargetEventsModule } from '@pebula/ngrid/target-events';
// components
import { HeadBarComponent } from './components/head-bar/head-bar.component';
@ -152,7 +153,8 @@ import { AttachmentControlComponent } from './components/attachment-control/atta
CdkTreeModule,
ScrollingModule,
PblNgridModule,
PblNgridMaterialModule
PblNgridMaterialModule,
PblNgridTargetEventsModule
],
exports: [
FormsModule,
@ -226,6 +228,7 @@ import { AttachmentControlComponent } from './components/attachment-control/atta
SpeakerButtonComponent,
PblNgridModule,
PblNgridMaterialModule,
PblNgridTargetEventsModule,
ListViewTableComponent,
AgendaContentObjectFormComponent,
ExtensionFieldComponent

View File

@ -303,7 +303,7 @@ export class AgendaListComponent extends BaseListViewComponent<ViewItem> impleme
* Export all items as CSV
*/
public csvExportItemList(): void {
this.csvExport.exportItemList(this.dataSource.source);
this.csvExport.exportItemList(this.dataSource.filteredData);
}
/**
@ -312,7 +312,7 @@ export class AgendaListComponent extends BaseListViewComponent<ViewItem> impleme
*/
public onDownloadPdf(): void {
const filename = this.translate.instant('Agenda');
this.pdfService.download(this.agendaPdfService.agendaListToDocDef(this.dataSource.source), filename);
this.pdfService.download(this.agendaPdfService.agendaListToDocDef(this.dataSource.filteredData), filename);
}
/**

View File

@ -89,7 +89,7 @@ export abstract class BaseListViewComponent<V extends BaseViewModel> extends Bas
* Select all files in the current data source
*/
public selectAll(): void {
this.dataSource.selection.select(...this.dataSource.source);
this.dataSource.selection.select(...this.dataSource.filteredData);
}
/**

View File

@ -66,7 +66,7 @@
</div>
<!-- the actual file manager -->
<pbl-ngrid class="file-manager-table" showHeader="false" vScrollAuto [dataSource]="dataSource" [columns]="columnSet">
<pbl-ngrid class="file-manager-table ngrid-hide-head" showHeader="false" vScrollAuto [dataSource]="dataSource" [columns]="columnSet">
<!-- Icon column -->
<div *pblNgridCellDef="'icon'; row as mediafile" class="fill clickable">
<a class="detail-link" target="_blank" [routerLink]="mediafile.url" *ngIf="mediafile.is_file"> </a>

View File

@ -57,7 +57,7 @@
font-size: 90%;
}
height: calc(100vh - 170px);
height: calc(100vh - 105px);
.pbl-ngrid-row {
$size: 60px;
@ -67,11 +67,4 @@
height: $size !important;
}
}
// For some reason, hiding the table header adds an empty meta bar.
.pbl-ngrid-container {
> div {
display: none;
}
}
}

View File

@ -38,6 +38,7 @@
<mat-card class="os-card">
<os-list-view-table
class="block-list"
[repo]="repo"
[showFilterBar]="false"
[columns]="tableColumnDefinition"

View File

@ -1,5 +1,13 @@
@import '~assets/styles/tables.scss';
::ng-deep .mat-form-field {
.block-list {
display: block;
.virtual-scroll-full-page {
height: calc(100vh - 150px);
}
}
.mat-form-field {
width: 50%;
}

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Title } from '@angular/platform-browser';
import { MatSnackBar } from '@angular/material/snack-bar';
@ -23,7 +23,8 @@ import { ViewMotionBlock } from 'app/site/motions/models/view-motion-block';
@Component({
selector: 'os-motion-block-list',
templateUrl: './motion-block-list.component.html',
styleUrls: ['./motion-block-list.component.scss']
styleUrls: ['./motion-block-list.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class MotionBlockListComponent extends BaseListViewComponent<ViewMotionBlock> implements OnInit {
/**

View File

@ -308,7 +308,7 @@ export class MotionListComponent extends BaseListViewComponent<ViewMotion> imple
exportDialogRef.afterClosed().subscribe((exportInfo: ExportFormData) => {
if (exportInfo && exportInfo.format) {
const data = this.isMultiSelect ? this.selectedRows : this.dataSource.source;
const data = this.isMultiSelect ? this.selectedRows : this.dataSource.filteredData;
if (exportInfo.format === FileFormat.PDF) {
try {
this.pdfExport.exportMotionCatalog(data, exportInfo);

View File

@ -245,7 +245,7 @@ export class UserListComponent extends BaseListViewComponent<ViewUser> implement
*/
public csvExportUserList(): void {
this.csvExport.export(
this.dataSource.source,
this.dataSource.filteredData,
[
{ property: 'title' },
{ property: 'first_name', label: 'Given name' },
@ -270,7 +270,7 @@ export class UserListComponent extends BaseListViewComponent<ViewUser> implement
* (access information, including personal information such as initial passwords)
*/
public onDownloadAccessPdf(): void {
this.userPdf.exportMultipleUserAccessPDF(this.dataSource.source);
this.userPdf.exportMultipleUserAccessPDF(this.dataSource.filteredData);
}
/**
@ -278,7 +278,7 @@ export class UserListComponent extends BaseListViewComponent<ViewUser> implement
* with all users currently matching the filter
*/
public pdfExportUserList(): void {
this.userPdf.exportUserList(this.dataSource.source);
this.userPdf.exportUserList(this.dataSource.filteredData);
}
/**

View File

@ -191,11 +191,6 @@
}
}
.ngrid-lg {
height: 110px;
min-height: 90px;
}
/** Define the general style-rules */
* {
font-family: OSFont, Fira Sans, Roboto, Arial, Helvetica, sans-serif;
@ -629,6 +624,7 @@ button.mat-menu-item.selected {
* Depending in mobile-mode and desktop mode we need to subtract different values
* from 100vh
*/
// no os-sort-filter-bar
.virtual-scroll-full-page {
height: calc(100vh - 64px);
}
@ -638,14 +634,16 @@ button.mat-menu-item.selected {
display: inline-block;
line-height: 150%;
}
// with os-sort-filter-bar
.virtual-scroll-with-head-bar {
height: calc(100vh - 125px);
}
.ngrid-hide-head {
// For some reason, hiding the table header adds an empty meta bar.
.pbl-ngrid-container {
> div {
display: none;
height: 0;
}
}
}