Improve client-side graphql scalar types (#4511)

* Add types to graphql scalars
* Upgrade dependencies
* Override UI config type
* Remove all IUIConfig casts
* Add tableColumns to IUIConfig
* Add BoolMap type, set strictScalars
* Add PluginConfigMap
* Replace any with unknown
* Add SavedObjectFilter and SavedUIOptions
* Remove unused items from CriterionType
This commit is contained in:
DingDongSoLong4
2024-02-07 00:49:32 +02:00
committed by GitHub
parent 9ac6505241
commit 2d73912f15
121 changed files with 887 additions and 1062 deletions

View File

@@ -23,7 +23,7 @@ export class CaptionCriterion extends StringCriterion {
super(CaptionsCriterionOption);
}
protected toCriterionInput() {
public toCriterionInput() {
const value = valueToCode(this.value) ?? "";
return {

View File

@@ -25,7 +25,7 @@ export class CircumcisedCriterion extends MultiStringCriterion {
super(CircumcisedCriterionOption);
}
protected toCriterionInput(): CircumcisionCriterionInput {
public toCriterionInput(): CircumcisionCriterionInput {
const value = this.value.map((v) =>
stringToCircumcised(v)
) as CircumisedEnum[];

View File

@@ -36,7 +36,7 @@ export type CriterionValue =
| ITimestampValue
| IPhashDistanceValue;
export interface IEncodedCriterion<T extends CriterionValue> {
export interface ISavedCriterion<T extends CriterionValue> {
modifier: CriterionModifier;
value: T | undefined;
}
@@ -142,29 +142,22 @@ export abstract class Criterion<V extends CriterionValue> {
return JSON.stringify(encodedCriterion);
}
public setFromEncodedCriterion(encodedCriterion: IEncodedCriterion<V>) {
if (
encodedCriterion.value !== undefined &&
encodedCriterion.value !== null
) {
this.value = encodedCriterion.value;
public setFromSavedCriterion(criterion: ISavedCriterion<V>) {
if (criterion.value !== undefined && criterion.value !== null) {
this.value = criterion.value;
}
this.modifier = encodedCriterion.modifier;
this.modifier = criterion.modifier;
}
public apply(outputFilter: Record<string, unknown>) {
outputFilter[this.criterionOption.type] = this.toCriterionInput();
}
protected toCriterionInput(): unknown {
public toCriterionInput(): unknown {
return {
value: this.value,
modifier: this.modifier,
};
}
public toSavedFilter(outputFilter: Record<string, unknown>) {
outputFilter[this.criterionOption.type] = {
public toSavedCriterion(): ISavedCriterion<V> {
return {
value: this.value,
modifier: this.modifier,
};
@@ -261,7 +254,7 @@ export class ILabeledIdCriterion extends Criterion<ILabeledId[]> {
return this.value.map((v) => v.label).join(", ");
}
protected toCriterionInput(): MultiCriterionInput {
public toCriterionInput(): MultiCriterionInput {
return {
value: this.value.map((v) => v.id),
modifier: this.modifier,
@@ -311,10 +304,10 @@ export class IHierarchicalLabeledIdCriterion extends Criterion<IHierarchicalLabe
}
}
public setFromEncodedCriterion(
encodedCriterion: IEncodedCriterion<IHierarchicalLabelValue>
public setFromSavedCriterion(
criterion: ISavedCriterion<IHierarchicalLabelValue>
) {
const { modifier, value } = encodedCriterion;
const { modifier, value } = criterion;
if (value !== undefined) {
this.value = {
@@ -351,7 +344,7 @@ export class IHierarchicalLabeledIdCriterion extends Criterion<IHierarchicalLabe
return `${labels} (+${this.value.depth > 0 ? this.value.depth : "all"})`;
}
protected toCriterionInput(): HierarchicalMultiCriterionInput {
public toCriterionInput(): HierarchicalMultiCriterionInput {
let excludes: string[] = [];
// if modifier is equals, depth must be 0
@@ -551,7 +544,7 @@ export function createBooleanCriterionOption(
}
export class BooleanCriterion extends StringCriterion {
protected toCriterionInput(): boolean {
public toCriterionInput(): boolean {
return this.value === "true";
}
@@ -578,7 +571,7 @@ export class StringBooleanCriterionOption extends CriterionOption {
}
export class StringBooleanCriterion extends StringCriterion {
protected toCriterionInput(): string {
public toCriterionInput(): string {
return this.value;
}
@@ -694,7 +687,7 @@ export class NumberCriterion extends Criterion<INumberValue> {
}
}
protected toCriterionInput(): IntCriterionInput {
public toCriterionInput(): IntCriterionInput {
return {
modifier: this.modifier,
value: this.value?.value ?? 0,
@@ -761,7 +754,7 @@ export class DurationCriterion extends Criterion<INumberValue> {
super(type, { value: undefined, value2: undefined });
}
protected toCriterionInput(): IntCriterionInput {
public toCriterionInput(): IntCriterionInput {
return {
modifier: this.modifier,
value: this.value?.value ?? 0,
@@ -841,7 +834,7 @@ export class DateCriterion extends Criterion<IDateValue> {
};
}
protected toCriterionInput(): DateCriterionInput {
public toCriterionInput(): DateCriterionInput {
return {
modifier: this.modifier,
value: this.value?.value,
@@ -940,7 +933,7 @@ export class TimestampCriterion extends Criterion<ITimestampValue> {
};
}
protected toCriterionInput(): TimestampCriterionInput {
public toCriterionInput(): TimestampCriterionInput {
return {
modifier: this.modifier,
value: this.transformValueToInput(this.value.value),

View File

@@ -6,7 +6,7 @@ import {
import { genderStrings, stringToGender } from "src/utils/gender";
import {
CriterionOption,
IEncodedCriterion,
ISavedCriterion,
MultiStringCriterion,
} from "./criterion";
@@ -29,7 +29,7 @@ export class GenderCriterion extends MultiStringCriterion {
super(GenderCriterionOption);
}
protected toCriterionInput(): GenderCriterionInput {
public toCriterionInput(): GenderCriterionInput {
const value = this.value.map((v) => stringToGender(v)) as GenderEnum[];
return {
@@ -38,17 +38,15 @@ export class GenderCriterion extends MultiStringCriterion {
};
}
public setFromEncodedCriterion(
encodedCriterion: IEncodedCriterion<string[]>
) {
public setFromSavedCriterion(criterion: ISavedCriterion<string[]>) {
// backwards compatibility - if the value is a string, convert it to an array
if (typeof encodedCriterion.value === "string") {
encodedCriterion = {
...encodedCriterion,
value: [encodedCriterion.value],
if (typeof criterion.value === "string") {
criterion = {
...criterion,
value: [criterion.value],
};
}
super.setFromEncodedCriterion(encodedCriterion);
super.setFromSavedCriterion(criterion);
}
}

View File

@@ -3,7 +3,7 @@ import { CriterionType } from "../types";
import { CriterionOption, StringCriterion, Option } from "./criterion";
export class IsMissingCriterion extends StringCriterion {
protected toCriterionInput(): string {
public toCriterionInput(): string {
return this.value;
}
}

View File

@@ -7,7 +7,7 @@ import {
} from "src/core/generated-graphql";
export class OrientationCriterion extends MultiStringCriterion {
protected toCriterionInput(): OrientationCriterionInput {
public toCriterionInput(): OrientationCriterionInput {
return {
value: this.value
.map((v) => stringToOrientation(v))

View File

@@ -5,7 +5,7 @@ import {
MultiCriterionInput,
} from "src/core/generated-graphql";
import { ILabeledId, ILabeledValueListValue } from "../types";
import { Criterion, CriterionOption, IEncodedCriterion } from "./criterion";
import { Criterion, CriterionOption, ISavedCriterion } from "./criterion";
const modifierOptions = [
CriterionModifier.IncludesAll,
@@ -49,10 +49,10 @@ export class PerformersCriterion extends Criterion<ILabeledValueListValue> {
}
}
public setFromEncodedCriterion(
encodedCriterion: IEncodedCriterion<ILabeledId[] | ILabeledValueListValue>
public setFromSavedCriterion(
criterion: ISavedCriterion<ILabeledId[] | ILabeledValueListValue>
) {
const { modifier, value } = encodedCriterion;
const { modifier, value } = criterion;
// #3619 - the format of performer value was changed from an array
// to an object. Check for both formats.
@@ -80,7 +80,7 @@ export class PerformersCriterion extends Criterion<ILabeledValueListValue> {
return this.value.items.map((v) => v.label).join(", ");
}
protected toCriterionInput(): MultiCriterionInput {
public toCriterionInput(): MultiCriterionInput {
let excludes: string[] = [];
if (this.value.excluded) {
excludes = this.value.excluded.map((v) => v.id);

View File

@@ -42,7 +42,7 @@ export class PhashCriterion extends Criterion<IPhashDistanceValue> {
}
}
protected toCriterionInput(): PhashDistanceCriterionInput {
public toCriterionInput(): PhashDistanceCriterionInput {
return {
value: this.value.value,
modifier: this.modifier,
@@ -62,7 +62,7 @@ export class DuplicatedCriterion extends StringCriterion {
super(DuplicatedCriterionOption);
}
protected toCriterionInput(): PHashDuplicationCriterionInput {
public toCriterionInput(): PHashDuplicationCriterionInput {
return {
duplicated: this.value === "true",
};

View File

@@ -11,7 +11,6 @@ import {
} from "src/core/generated-graphql";
import { INumberValue } from "../types";
import { Criterion, CriterionOption } from "./criterion";
import { IUIConfig } from "src/core/config";
const modifierOptions = [
CriterionModifier.Equals,
@@ -25,9 +24,7 @@ const modifierOptions = [
];
function getRatingSystemOptions(config?: ConfigDataFragment) {
return (
(config?.ui as IUIConfig)?.ratingSystemOptions ?? defaultRatingSystemOptions
);
return config?.ui.ratingSystemOptions ?? defaultRatingSystemOptions;
}
export const RatingCriterionOption = new CriterionOption({
@@ -58,7 +55,7 @@ export class RatingCriterion extends Criterion<INumberValue> {
}
}
protected toCriterionInput(): IntCriterionInput {
public toCriterionInput(): IntCriterionInput {
return {
modifier: this.modifier,
value: this.value.value ?? 0,

View File

@@ -32,7 +32,7 @@ class BaseResolutionCriterionOption extends CriterionOption {
}
class BaseResolutionCriterion extends StringCriterion {
protected toCriterionInput(): ResolutionCriterionInput | undefined {
public toCriterionInput(): ResolutionCriterionInput | undefined {
const value = stringToResolution(this.value);
if (value !== undefined) {

View File

@@ -43,7 +43,7 @@ export class StashIDCriterion extends Criterion<IStashIDValue> {
}
}
protected toCriterionInput(): StashIdCriterionInput {
public toCriterionInput(): StashIdCriterionInput {
return {
endpoint: this.value.endpoint,
stash_id: this.value.stashID,

View File

@@ -5,9 +5,18 @@ import {
SavedFilterDataFragment,
SortDirectionEnum,
} from "src/core/generated-graphql";
import { Criterion, CriterionValue } from "./criteria/criterion";
import {
Criterion,
CriterionValue,
ISavedCriterion,
} from "./criteria/criterion";
import { getFilterOptions } from "./factory";
import { CriterionType, DisplayMode } from "./types";
import {
CriterionType,
DisplayMode,
SavedObjectFilter,
SavedUIOptions,
} from "./types";
interface IDecodedParams {
perPage?: number;
@@ -127,9 +136,12 @@ export class ListFilterModel {
if (params.c !== undefined) {
for (const jsonString of params.c) {
try {
const encodedCriterion = JSON.parse(jsonString);
const criterion = this.makeCriterion(encodedCriterion.type);
criterion.setFromEncodedCriterion(encodedCriterion);
const { type: criterionType, ...savedCriterion } =
JSON.parse(jsonString);
const criterion = this.makeCriterion(criterionType);
criterion.setFromSavedCriterion(savedCriterion);
this.criteria.push(criterion);
} catch (err) {
// eslint-disable-next-line no-console
@@ -261,8 +273,7 @@ export class ListFilterModel {
this.sortBy = "random";
this.randomSeed = Number.parseInt(match[1], 10);
}
this.sortDirection =
(findFilter?.direction as SortDirectionEnum) ?? this.sortDirection;
this.sortDirection = findFilter?.direction ?? this.sortDirection;
this.searchTerm = findFilter?.q ?? this.searchTerm;
this.displayMode = uiOptions?.display_mode ?? this.displayMode;
@@ -272,11 +283,11 @@ export class ListFilterModel {
this.criteria = [];
if (objectFilter) {
Object.keys(objectFilter).forEach((key) => {
const criterion = this.makeCriterion(key as CriterionType);
criterion.setFromEncodedCriterion(objectFilter[key]);
for (const [k, v] of Object.entries(objectFilter)) {
const criterion = this.makeCriterion(k as CriterionType);
criterion.setFromSavedCriterion(v as ISavedCriterion<CriterionValue>);
this.criteria.push(criterion);
});
}
}
}
@@ -353,31 +364,6 @@ export class ListFilterModel {
};
}
public makeSavedFilterJSON() {
const encodedCriteria: string[] = this.criteria.map((criterion) =>
criterion.toJSON()
);
const result = {
perPage: this.itemsPerPage,
sortby: this.getSortBy(),
sortdir:
this.sortBy === "date"
? this.sortDirection === SortDirectionEnum.Asc
? "asc"
: undefined
: this.sortDirection === SortDirectionEnum.Desc
? "desc"
: undefined,
disp: this.displayMode,
q: this.searchTerm || undefined,
z: this.zoomIndex,
c: encodedCriteria,
};
return JSON.stringify(result);
}
public makeQueryParameters(): string {
const query: string[] = [];
const params = this.getEncodedParams();
@@ -424,8 +410,6 @@ export class ListFilterModel {
return option.makeCriterion(this.config);
}
// TODO: These don't support multiple of the same criteria, only the last one set is used.
public makeFindFilter(): FindFilterType {
return {
q: this.searchTerm,
@@ -438,23 +422,21 @@ export class ListFilterModel {
public makeFilter() {
const output: Record<string, unknown> = {};
this.criteria.forEach((criterion) => {
criterion.apply(output);
});
for (const c of this.criteria) {
output[c.criterionOption.type] = c.toCriterionInput();
}
return output;
}
public makeSavedFindFilter() {
const output: Record<string, unknown> = {};
this.criteria.forEach((criterion) => {
criterion.toSavedFilter(output);
});
public makeSavedFilter() {
const output: SavedObjectFilter = {};
for (const c of this.criteria) {
output[c.criterionOption.type] = c.toSavedCriterion();
}
return output;
}
public makeUIOptions(): Record<string, unknown> {
public makeSavedUIOptions(): SavedUIOptions {
return {
display_mode: this.displayMode,
zoom_index: this.zoomIndex,

View File

@@ -1,3 +1,14 @@
import { CriterionValue, ISavedCriterion } from "./criteria/criterion";
export type SavedObjectFilter = {
[K in CriterionType]?: ISavedCriterion<CriterionValue>;
};
export type SavedUIOptions = {
display_mode?: DisplayMode;
zoom_index?: number;
};
// NOTE: add new enum values to the end, to ensure existing data
// is not impacted
export enum DisplayMode {
@@ -114,7 +125,6 @@ export interface IOptionType {
export type CriterionType =
| "path"
| "rating"
| "rating100"
| "organized"
| "o_counter"
@@ -141,7 +151,6 @@ export type CriterionType =
| "country"
| "hair_color"
| "eye_color"
| "height"
| "height_cm"
| "weight"
| "measurements"
@@ -162,7 +171,6 @@ export type CriterionType =
| "performer_count"
| "death_year"
| "url"
| "stash_id"
| "interactive"
| "interactive_speed"
| "captions"