diff --git a/src/backend/model/threading/MetadataLoader.ts b/src/backend/model/threading/MetadataLoader.ts index 34a03b4a..b111583e 100644 --- a/src/backend/model/threading/MetadataLoader.ts +++ b/src/backend/model/threading/MetadataLoader.ts @@ -264,7 +264,7 @@ export class MetadataLoader { // and keep the minimum amount only const exif = ExifReader.load(data); if (exif.Rating) { - metadata.rating = parseInt(exif.Rating.value, 10) as any; + metadata.rating = parseInt(exif.Rating.value, 10) as 0 | 1 | 2 | 3 | 4 | 5; if (metadata.rating < 0) { metadata.rating = 0; } @@ -287,7 +287,7 @@ export class MetadataLoader { const orientation = parseInt( exif.Orientation.value as any, 10 - ) as any; + ) as number; if (OrientationTypes.BOTTOM_LEFT < orientation) { // noinspection JSSuspiciousNameCombination const height = metadata.size.width; diff --git a/src/common/SearchQueryParser.ts b/src/common/SearchQueryParser.ts index 24b080c5..0e8183c2 100644 --- a/src/common/SearchQueryParser.ts +++ b/src/common/SearchQueryParser.ts @@ -19,7 +19,7 @@ import { TextSearchQueryTypes, ToDateSearch, } from './entities/SearchQueryDTO'; -import { Utils } from './Utils'; +import {Utils} from './Utils'; export interface QueryKeywords { portrait: string; @@ -72,7 +72,8 @@ export const defaultQueryKeywords: QueryKeywords = { }; export class SearchQueryParser { - constructor(private keywords: QueryKeywords = defaultQueryKeywords) {} + constructor(private keywords: QueryKeywords = defaultQueryKeywords) { + } public static stringifyText( text: string, @@ -115,8 +116,11 @@ export class SearchQueryParser { // Parsing ISO string try { const parts = text.split('-').map((t) => parseInt(t, 10)); + if (parts && parts.length === 2) { + timestamp = Date.UTC(parts[0], parts[1] - 1, 1, 0, 0, 0, 0); // Note: months are 0-based + } if (parts && parts.length === 3) { - timestamp = Date.UTC(parts[0], parts[1] - 1, parts[2]); // Note: months are 0-based + timestamp = Date.UTC(parts[0], parts[1] - 1, parts[2], 0, 0, 0, 0); // Note: months are 0-based } } catch (e) { // ignoring errors @@ -230,7 +234,7 @@ export class SearchQueryParser { const unfoldList = (q: SearchListQuery): SearchQueryDTO[] => { if (q.list) { if (q.type === SearchQueryTypes.UNKNOWN_RELATION) { - return q.list.map((e) => unfoldList(e as SearchListQuery)).flat() // flatten array + return q.list.map((e) => unfoldList(e as SearchListQuery)).flat(); // flatten array } else { q.list.forEach((e) => unfoldList(e as SearchListQuery)); } @@ -256,14 +260,14 @@ export class SearchQueryParser { return { type: SearchQueryTypes.from_date, value: SearchQueryParser.parseDate(str.substring(str.indexOf(':') + 1)), - ...(str.startsWith(this.keywords.from + '!:') && { negate: true }), // only add if the value is true + ...(str.startsWith(this.keywords.from + '!:') && {negate: true}), // only add if the value is true } as FromDateSearch; } if (kwStartsWith(str, this.keywords.to)) { return { type: SearchQueryTypes.to_date, value: SearchQueryParser.parseDate(str.substring(str.indexOf(':') + 1)), - ...(str.startsWith(this.keywords.to + '!:') && { negate: true }), // only add if the value is true + ...(str.startsWith(this.keywords.to + '!:') && {negate: true}), // only add if the value is true } as ToDateSearch; } @@ -271,14 +275,14 @@ export class SearchQueryParser { return { type: SearchQueryTypes.min_rating, value: parseInt(str.substring(str.indexOf(':') + 1), 10), - ...(str.startsWith(this.keywords.minRating + '!:') && { negate: true }), // only add if the value is true + ...(str.startsWith(this.keywords.minRating + '!:') && {negate: true}), // only add if the value is true } as MinRatingSearch; } if (kwStartsWith(str, this.keywords.maxRating)) { return { type: SearchQueryTypes.max_rating, value: parseInt(str.substring(str.indexOf(':') + 1), 10), - ...(str.startsWith(this.keywords.maxRating + '!:') && { negate: true }), // only add if the value is true + ...(str.startsWith(this.keywords.maxRating + '!:') && {negate: true}), // only add if the value is true } as MaxRatingSearch; } if (kwStartsWith(str, this.keywords.minResolution)) { @@ -312,7 +316,7 @@ export class SearchQueryParser { return { type: SearchQueryTypes.distance, distance: parseInt(new RegExp(/^\d*/).exec(str)[0], 10), - from: { text: from }, + from: {text: from}, ...(new RegExp('^\\d*-' + this.keywords.kmFrom + '!:').test(str) && { negate: true, }), // only add if the value is true @@ -331,11 +335,11 @@ export class SearchQueryParser { // parse text search const tmp = TextSearchQueryTypes.map((type) => ({ key: (this.keywords as any)[SearchQueryTypes[type]] + ':', - queryTemplate: { type, text: '' } as TextSearch, + queryTemplate: {type, text: ''} as TextSearch, })).concat( TextSearchQueryTypes.map((type) => ({ key: (this.keywords as any)[SearchQueryTypes[type]] + '!:', - queryTemplate: { type, text: '', negate: true } as TextSearch, + queryTemplate: {type, text: '', negate: true} as TextSearch, })) ); for (const typeTmp of tmp) { @@ -361,7 +365,7 @@ export class SearchQueryParser { } } - return { type: SearchQueryTypes.any_text, text: str } as TextSearch; + return {type: SearchQueryTypes.any_text, text: str} as TextSearch; } public stringify(query: SearchQueryDTO): string { diff --git a/test/common/unit/SearchQueryParser.ts b/test/common/unit/SearchQueryParser.ts index cf7f4e0b..a15b1edd 100644 --- a/test/common/unit/SearchQueryParser.ts +++ b/test/common/unit/SearchQueryParser.ts @@ -68,8 +68,20 @@ describe('SearchQueryParser', () => { check({type: SearchQueryTypes.to_date, value: (Date.UTC(2020, 1, 1)), negate: true} as ToDateSearch); const parser = new SearchQueryParser(defaultQueryKeywords); + + let query: RangeSearch = ({type: SearchQueryTypes.from_date, value: (Date.UTC(2020, 1, 4))} as FromDateSearch); + expect(parser.parse(defaultQueryKeywords.from + ':' + '2020-02-04')) + .to.deep.equals(query, parser.stringify(query)); + + expect(parser.parse(defaultQueryKeywords.from + ':' + '2020-2-4')) + .to.deep.equals(query, parser.stringify(query)); + + query = ({type: SearchQueryTypes.from_date, value: (Date.UTC(2020, 1, 1))} as FromDateSearch); + expect(parser.parse(defaultQueryKeywords.from + ':' + (new Date(query.value)).getFullYear() + '-' + '02')) + .to.deep.equals(query, parser.stringify(query)); + // test if date gets simplified on 1st of Jan. - let query: RangeSearch = {type: SearchQueryTypes.to_date, value: (Date.UTC(2020, 0, 1))} as ToDateSearch; + query = {type: SearchQueryTypes.to_date, value: (Date.UTC(2020, 0, 1))} as ToDateSearch; expect(parser.parse(defaultQueryKeywords.to + ':' + (new Date(query.value)).getFullYear())) .to.deep.equals(query, parser.stringify(query));