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:
parent
af67a8ac1c
commit
928a8918c6
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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">
|
||||
|
@ -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 => {
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user