Pull request #48: RED-767: Search
Merge in RED/ui from search to master * commit '14f828cbcae5839bcd5ee5de3b21f05bad88f9b8': Project listing search Search in project overview
This commit is contained in:
commit
cf97303a25
@ -44,6 +44,7 @@ export class IconsModule {
|
||||
'radio-selected',
|
||||
'refresh',
|
||||
'report',
|
||||
'search',
|
||||
'secret',
|
||||
'sort-asc',
|
||||
'sort-desc',
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
</div>
|
||||
|
||||
<span class="all-caps-label">
|
||||
{{ 'dictionary-listing.table-header.title' | translate: { length: 0 } }}
|
||||
{{ 'dictionary-listing.table-header.title' | translate: { length: dictionaries.length } }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
@ -189,7 +189,7 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
private _configureTextPopup() {
|
||||
this.instance.textPopup.add(<any>{
|
||||
type: 'actionButton',
|
||||
img: '/assets/icons/general/search-viewer.svg',
|
||||
img: '/assets/icons/general/search.svg',
|
||||
title: this._translateService.instant('pdf-viewer.text-popup.actions.search'),
|
||||
onClick: () => {
|
||||
const text = this.instance.docViewer.getSelectedText();
|
||||
|
||||
@ -21,6 +21,12 @@
|
||||
[filters]="needsWorkFilters"
|
||||
[icon]="'red:needs-work'"
|
||||
></redaction-filter>
|
||||
<form [formGroup]="searchForm">
|
||||
<div class="red-input-group">
|
||||
<input [placeholder]="'project-listing.search' | translate" formControlName="query" name="query" type="text" class="with-icon" />
|
||||
<mat-icon class="icon-right" svgIcon="red:search"></mat-icon>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<redaction-icon-button
|
||||
*ngIf="permissionsService.isManager()"
|
||||
|
||||
@ -23,6 +23,8 @@ import { TranslateChartService } from '../../utils/translate-chart.service';
|
||||
import { RedactionFilterSorter } from '../../common/sorters/redaction-filter-sorter';
|
||||
import { StatusSorter } from '../../common/sorters/status-sorter';
|
||||
import { Router } from '@angular/router';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { debounce } from '../../utils/debounce';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-project-listing-screen',
|
||||
@ -33,6 +35,8 @@ export class ProjectListingScreenComponent implements OnInit, OnDestroy {
|
||||
public projectsChartData: DoughnutChartConfig[] = [];
|
||||
public documentsChartData: DoughnutChartConfig[] = [];
|
||||
|
||||
public searchForm: FormGroup;
|
||||
|
||||
public statusFilters: FilterModel[];
|
||||
public peopleFilters: FilterModel[];
|
||||
public needsWorkFilters: FilterModel[];
|
||||
@ -55,8 +59,15 @@ export class ProjectListingScreenComponent implements OnInit, OnDestroy {
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _router: Router,
|
||||
public readonly sortingService: SortingService,
|
||||
public readonly translateChartService: TranslateChartService
|
||||
) {}
|
||||
public readonly translateChartService: TranslateChartService,
|
||||
private readonly _formBuilder: FormBuilder
|
||||
) {
|
||||
this.searchForm = this._formBuilder.group({
|
||||
query: ['']
|
||||
});
|
||||
|
||||
this.searchForm.valueChanges.subscribe((value) => this._executeSearch(value));
|
||||
}
|
||||
|
||||
public ngOnInit(): void {
|
||||
this.appStateService.reset();
|
||||
@ -237,19 +248,30 @@ export class ProjectListingScreenComponent implements OnInit, OnDestroy {
|
||||
this._filterProjects();
|
||||
}
|
||||
|
||||
private _filterProjects() {
|
||||
private get _filteredProjects(): ProjectWrapper[] {
|
||||
const filters = [
|
||||
{ values: this.statusFilters, checker: projectStatusChecker },
|
||||
{ values: this.peopleFilters, checker: projectMemberChecker },
|
||||
{ values: this.needsWorkFilters, checker: annotationFilterChecker, matchAll: true, checkerArgs: this.permissionsService }
|
||||
];
|
||||
return getFilteredEntities(this.appStateService.allProjects, filters);
|
||||
}
|
||||
|
||||
private _filterProjects() {
|
||||
this.detailsContainerFilters = {
|
||||
statusFilters: this.statusFilters.map((f) => ({ ...f }))
|
||||
};
|
||||
this.displayedProjects = getFilteredEntities(this.appStateService.allProjects, filters);
|
||||
this.displayedProjects = this._filteredProjects.filter((project) =>
|
||||
project.name.toLowerCase().includes(this.searchForm.get('query').value.toLowerCase())
|
||||
);
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
@debounce(200)
|
||||
private _executeSearch(value: { query: string }) {
|
||||
this.displayedProjects = this._filteredProjects.filter((project) => project.name.toLowerCase().includes(value.query.toLowerCase()));
|
||||
}
|
||||
|
||||
openEditProjectDialog($event: MouseEvent, project: Project) {
|
||||
this._dialogService.openEditProjectDialog($event, project, () => {
|
||||
this._calculateData();
|
||||
|
||||
@ -22,6 +22,12 @@
|
||||
[filters]="needsWorkFilters"
|
||||
[icon]="'red:needs-work'"
|
||||
></redaction-filter>
|
||||
<form [formGroup]="searchForm">
|
||||
<div class="red-input-group">
|
||||
<input [placeholder]="'project-overview.search' | translate" formControlName="query" name="query" type="text" class="with-icon" />
|
||||
<mat-icon class="icon-right" svgIcon="red:search"></mat-icon>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
|
||||
@ -23,6 +23,8 @@ import { Subscription, timer } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { RedactionFilterSorter } from '../../common/sorters/redaction-filter-sorter';
|
||||
import { StatusSorter } from '../../common/sorters/status-sorter';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { debounce } from '../../utils/debounce';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-project-overview-screen',
|
||||
@ -35,6 +37,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
|
||||
public peopleFilters: FilterModel[];
|
||||
public needsWorkFilters: FilterModel[];
|
||||
public collapsedDetails = false;
|
||||
public searchForm: FormGroup;
|
||||
|
||||
displayedFiles: FileStatusWrapper[] = [];
|
||||
|
||||
@ -61,8 +64,15 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
|
||||
private readonly _router: Router,
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _fileDropOverlayService: FileDropOverlayService
|
||||
private readonly _fileDropOverlayService: FileDropOverlayService,
|
||||
private readonly _formBuilder: FormBuilder
|
||||
) {
|
||||
this.searchForm = this._formBuilder.group({
|
||||
query: ['']
|
||||
});
|
||||
|
||||
this.searchForm.valueChanges.subscribe((value) => this._executeSearch(value));
|
||||
|
||||
this._activatedRoute.params.subscribe((params) => {
|
||||
this.appStateService.activateProject(params.projectId);
|
||||
});
|
||||
@ -89,6 +99,12 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
|
||||
this.filesAutoUpdateTimer.unsubscribe();
|
||||
}
|
||||
|
||||
@debounce(200)
|
||||
private _executeSearch(value: { query: string }) {
|
||||
this.displayedFiles = this._filteredFiles.filter((file) => file.filename.toLowerCase().includes(value.query.toLowerCase()));
|
||||
this.selectedFileIds = this.displayedFiles.map((d) => d.fileId).filter((x) => this.selectedFileIds.includes(x));
|
||||
}
|
||||
|
||||
get displayReanalyseBtn() {
|
||||
return !!(
|
||||
this.permissionsService.isManagerAndOwner() &&
|
||||
@ -263,7 +279,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
|
||||
: [];
|
||||
}
|
||||
|
||||
private _filterFiles() {
|
||||
private get _filteredFiles(): FileStatusWrapper[] {
|
||||
const filters = [
|
||||
{ values: this.statusFilters, checker: keyChecker('status') },
|
||||
{ values: this.peopleFilters, checker: keyChecker('currentReviewer') },
|
||||
@ -274,7 +290,11 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
|
||||
checkerArgs: this.permissionsService
|
||||
}
|
||||
];
|
||||
this.displayedFiles = getFilteredEntities(this.appStateService.activeProject.files, filters);
|
||||
return getFilteredEntities(this.appStateService.activeProject.files, filters);
|
||||
}
|
||||
|
||||
private _filterFiles() {
|
||||
this.displayedFiles = this._filteredFiles.filter((file) => file.filename.toLowerCase().includes(this.searchForm.get('query').value.toLowerCase()));
|
||||
this.selectedFileIds = this.displayedFiles.map((d) => d.fileId).filter((x) => this.selectedFileIds.includes(x));
|
||||
this.detailsContainerFilters = {
|
||||
needsWorkFilters: this.needsWorkFilters.map((f) => ({ ...f })),
|
||||
|
||||
@ -69,6 +69,7 @@
|
||||
"action": "Download Redaction Report"
|
||||
},
|
||||
"project-listing": {
|
||||
"search": "Project name...",
|
||||
"reanalyse": {
|
||||
"action": "Reanalyse entire project"
|
||||
},
|
||||
@ -146,6 +147,7 @@
|
||||
"collapse": "Hide Details"
|
||||
},
|
||||
"project-overview": {
|
||||
"search": "Document name...",
|
||||
"header-actions": {
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512.005 512.005" style="enable-background:new 0 0 512.005 512.005;" xml:space="preserve">
|
||||
<g fill="rgb(136,142,149)">
|
||||
<path d="M505.749,475.587l-145.6-145.6c28.203-34.837,45.184-79.104,45.184-127.317c0-111.744-90.923-202.667-202.667-202.667
|
||||
S0,90.925,0,202.669s90.923,202.667,202.667,202.667c48.213,0,92.48-16.981,127.317-45.184l145.6,145.6
|
||||
c4.16,4.16,9.621,6.251,15.083,6.251s10.923-2.091,15.083-6.251C514.091,497.411,514.091,483.928,505.749,475.587z
|
||||
M202.667,362.669c-88.235,0-160-71.765-160-160s71.765-160,160-160s160,71.765,160,160S290.901,362.669,202.667,362.669z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 875 B |
7
apps/red-ui/src/assets/icons/general/search.svg
Normal file
7
apps/red-ui/src/assets/icons/general/search.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="100px" height="100px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>search</title>
|
||||
<g id="search" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M95.5,74.5 L76.5,55.5 C78.5,50.5 79.5,45.5 79.5,40 C79.5,18 61.5,0 39.5,0 C18,0 0,18 0,40 C0,62 18,80 40,80 C45.5,80 51,79 55.5,77 L74.5,96 C77.5,99 81.5,100.5 85,100.5 C89,100.5 92.5,99 95.5,96 C101.5,90 101.5,80 95.5,74.5 Z M10,40 C10,23.5 23.5,10 40,10 C56.5,10 70,23.5 70,40 C70,56.5 56.5,70 40,70 C23.5,70 10,56.5 10,40 Z M88.5,88.5 C86.5,90.5 83.5,90.5 81.5,88.5 L64.5,71.5 C67,69.5 69.5,67 71.5,64.5 L88.5,81.5 C90.5,83.5 90.5,86.5 88.5,88.5 Z" id="Shape" fill="currentColor" fill-rule="nonzero"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 841 B |
@ -5,6 +5,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 13px;
|
||||
position: relative;
|
||||
|
||||
.mat-form-field-underline {
|
||||
display: none;
|
||||
@ -20,6 +21,14 @@
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.icon-right {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
input,
|
||||
textarea,
|
||||
mat-select {
|
||||
@ -36,6 +45,10 @@
|
||||
margin-top: 3px;
|
||||
min-height: 34px;
|
||||
|
||||
&.with-icon {
|
||||
padding-right: 34px;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: $grey-1;
|
||||
}
|
||||
|
||||
@ -29,9 +29,22 @@ body {
|
||||
gap: 2px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> div:first-child {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
form {
|
||||
margin-left: 6px;
|
||||
|
||||
.red-input-group {
|
||||
width: 250px;
|
||||
|
||||
input {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user