1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2025-01-14 14:43:17 +08:00

Improving autocomplete and search

This commit is contained in:
Patrik J. Braun 2021-05-05 20:47:02 +02:00
parent af67a8ac1c
commit 928a8918c6
7 changed files with 68 additions and 16 deletions

View File

@ -121,22 +121,26 @@ export class SearchQueryParser {
if (tokenEnd !== str.length - 1) {
if (str.startsWith(' ' + this.keywords.and, tokenEnd)) {
const rest = this.parse(str.slice(tokenEnd + (' ' + this.keywords.and).length), implicitOR);
return {
type: SearchQueryTypes.AND,
list: [this.parse(str.slice(0, tokenEnd), implicitOR), // trim brackets
this.parse(str.slice(tokenEnd + (' ' + this.keywords.and).length), implicitOR)]
...(rest.type === SearchQueryTypes.AND ? (rest as SearchListQuery).list : [rest])]
} as ANDSearchQuery;
} else if (str.startsWith(' ' + this.keywords.or, tokenEnd)) {
const rest = this.parse(str.slice(tokenEnd + (' ' + this.keywords.or).length), implicitOR);
return {
type: SearchQueryTypes.OR,
list: [this.parse(str.slice(0, tokenEnd), implicitOR), // trim brackets
this.parse(str.slice(tokenEnd + (' ' + this.keywords.or).length), implicitOR)]
...(rest.type === SearchQueryTypes.OR ? (rest as SearchListQuery).list : [rest])]
} as ORSearchQuery;
} else { // Relation cannot be detected
const t = implicitOR === true ? SearchQueryTypes.OR : SearchQueryTypes.UNKNOWN_RELATION;
const rest = this.parse(str.slice(tokenEnd), implicitOR);
return {
type: implicitOR === true ? SearchQueryTypes.OR : SearchQueryTypes.UNKNOWN_RELATION,
type: t,
list: [this.parse(str.slice(0, tokenEnd), implicitOR), // trim brackets
this.parse(str.slice(tokenEnd), implicitOR)]
...(rest.type === t ? (rest as SearchListQuery).list : [rest])]
} as SearchListQuery;
}
}
@ -249,24 +253,33 @@ export class SearchQueryParser {
return {type: SearchQueryTypes.any_text, text: str} as TextSearch;
}
public stringify(query: SearchQueryDTO): string {
const ret = this.stringifyOnEntry(query);
if (ret.charAt(0) === '(' && ret.charAt(ret.length - 1) === ')') {
return ret.slice(1, ret.length - 1);
}
return ret;
}
private stringifyOnEntry(query: SearchQueryDTO): string {
if (!query || !query.type) {
return '';
}
switch (query.type) {
case SearchQueryTypes.AND:
return '(' + (query as SearchListQuery).list.map(q => this.stringify(q)).join(' ' + this.keywords.and + ' ') + ')';
return '(' + (query as SearchListQuery).list.map(q => this.stringifyOnEntry(q)).join(' ' + this.keywords.and + ' ') + ')';
case SearchQueryTypes.OR:
return '(' + (query as SearchListQuery).list.map(q => this.stringify(q)).join(' ' + this.keywords.or + ' ') + ')';
return '(' + (query as SearchListQuery).list.map(q => this.stringifyOnEntry(q)).join(' ' + this.keywords.or + ' ') + ')';
case SearchQueryTypes.SOME_OF:
if ((query as SomeOfSearchQuery).min) {
return (query as SomeOfSearchQuery).min + '-' + this.keywords.NSomeOf + ':(' +
(query as SearchListQuery).list.map(q => this.stringify(q)).join(' ') + ')';
(query as SearchListQuery).list.map(q => this.stringifyOnEntry(q)).join(' ') + ')';
}
return this.keywords.someOf + ':(' +
(query as SearchListQuery).list.map(q => this.stringify(q)).join(' ') + ')';
(query as SearchListQuery).list.map(q => this.stringifyOnEntry(q)).join(' ') + ')';
case SearchQueryTypes.orientation:

View File

@ -1,6 +1,18 @@
.query-list{
.query-list {
padding-left: 25px;
}
label{
label {
margin-top: 0.3rem;
}
.match-type {
font-size: 2rem;
margin-top: -0.8rem;
font-weight: bold;
cursor: pointer;
}
.match-type.exact-match {
color: #0069d9;
}

View File

@ -59,6 +59,11 @@
</select>
</div>
<div class="input-group col-md-8" *ngIf="IsTextQuery">
<span title="exact match"
p18n-title
class="match-type"
(click)="toggleMatchType()"
[class.exact-match]="AsTextQuery.matchType === TextSearchQueryMatchTypes.exact_match">"</span>
<input
id="searchField"
name="searchField"
@ -68,6 +73,11 @@
(change)="onChange()"
(ngModelChange)="onChange()"
type="text"/>
<span title="exact match"
p18n-title
class="match-type"
(click)="toggleMatchType()"
[class.exact-match]="AsTextQuery.matchType === TextSearchQueryMatchTypes.exact_match">"</span>
</div>
<ng-container [ngSwitch]="queryEntry.type">
<div *ngSwitchCase="SearchQueryTypes.distance" class="col-md-8 d-flex">

View File

@ -9,6 +9,7 @@ import {
SearchQueryTypes,
SomeOfSearchQuery,
TextSearch,
TextSearchQueryMatchTypes,
TextSearchQueryTypes
} from '../../../../../../common/entities/SearchQueryDTO';
import {Utils} from '../../../../../../common/Utils';
@ -36,6 +37,7 @@ export class GallerySearchQueryEntryComponent implements ControlValueAccessor, V
public queryEntry: SearchQueryDTO;
public SearchQueryTypesEnum: { value: string; key: SearchQueryTypes }[];
public SearchQueryTypes = SearchQueryTypes;
public TextSearchQueryMatchTypes = TextSearchQueryMatchTypes;
@Output() delete = new EventEmitter<void>();
constructor() {
@ -145,6 +147,12 @@ export class GallerySearchQueryEntryComponent implements ControlValueAccessor, V
this.propagateChange(this.queryEntry);
}
public toggleMatchType(): void {
this.AsTextQuery.matchType = this.AsTextQuery.matchType === TextSearchQueryMatchTypes.exact_match ?
TextSearchQueryMatchTypes.like : TextSearchQueryMatchTypes.exact_match;
this.onChange();
}
private propagateChange = (_: any): void => {
};

View File

@ -13,6 +13,19 @@
z-index: 7;
}
.insert-button {
margin-right: -15px;
display: none;
margin-top: 2px;
}
.autocomplete-item-selected .insert-button {
display: block;
}
.autocomplete-item-selected .insert-button:hover {
color: black;
}
.autocomplete-item {
cursor: pointer;
padding-top: 2px;

View File

@ -5,7 +5,6 @@
placeholder="Search"
(keyup)="onSearchChange($event)"
(blur)="onFocusLost()"
(focus)="onFocus()"
[(ngModel)]="rawSearchText"
(ngModelChange)="onChange()"
(keydown.enter)="OnEnter($event)"
@ -49,6 +48,7 @@
<span *ngSwitchCase="SearchQueryTypes.distance" class="oi oi-map-marker"></span>
</span>
{{item.preText}}<strong>{{item.highLightText}}</strong>{{item.postText}}
<span class="oi oi-chevron-right insert-button float-right" (click)="applyAutoComplete(item)"></span>
</div>
</div>
</div>

View File

@ -109,16 +109,12 @@ export class GallerySearchFieldComponent implements ControlValueAccessor, Valida
}
public onFocusLost(): void {
return;
if (this.mouseOverAutoComplete === false) {
this.autoCompleteRenders = [];
}
}
public onFocus(): void {
// TODO: implement autocomplete
// this.autocomplete(this.searchText).catch(console.error);
}
applyHint($event: any): void {
if ($event.target.selectionStart !== this.rawSearchText.length) {