import React from "react"; import _ from "lodash"; import { Form } from "react-bootstrap"; import { ParseSceneFilenamesQuery, SlimSceneDataFragment, } from "src/core/generated-graphql"; import { PerformerSelect, TagSelect, StudioSelect, } from "src/components/Shared"; import { TextUtils } from "src/utils"; class ParserResult { public value?: T; public originalValue?: T; public isSet: boolean = false; public setOriginalValue(value?: T) { this.originalValue = value; this.value = value; } public setValue(value?: T) { if (value) { this.value = value; this.isSet = !_.isEqual(this.value, this.originalValue); } } } export class SceneParserResult { public id: string; public filename: string; public title: ParserResult = new ParserResult(); public date: ParserResult = new ParserResult(); public rating: ParserResult = new ParserResult(); public studio: ParserResult = new ParserResult(); public tags: ParserResult = new ParserResult(); public performers: ParserResult = new ParserResult(); public scene: SlimSceneDataFragment; constructor( result: ParseSceneFilenamesQuery["parseSceneFilenames"]["results"][0] ) { this.scene = result.scene; this.id = this.scene.id; this.filename = TextUtils.fileNameFromPath(this.scene.path); this.title.setOriginalValue(this.scene.title ?? undefined); this.date.setOriginalValue(this.scene.date ?? undefined); this.rating.setOriginalValue(this.scene.rating ?? undefined); this.performers.setOriginalValue(this.scene.performers.map((p) => p.id)); this.tags.setOriginalValue(this.scene.tags.map((t) => t.id)); this.studio.setOriginalValue(this.scene.studio?.id); this.title.setValue(result.title ?? undefined); this.date.setValue(result.date ?? undefined); this.rating.setValue(result.rating ?? undefined); this.performers.setValue(result.performer_ids ?? undefined); this.tags.setValue(result.tag_ids ?? undefined); this.studio.setValue(result.studio_id ?? undefined); } // returns true if any of its fields have set == true public isChanged() { return ( this.title.isSet || this.date.isSet || this.rating.isSet || this.performers.isSet || this.studio.isSet || this.tags.isSet ); } public toSceneUpdateInput() { return { id: this.id, details: this.scene.details, url: this.scene.url, rating: this.rating.isSet ? this.rating.value : this.scene.rating, gallery_id: this.scene.gallery?.id, title: this.title.isSet ? this.title.value : this.scene.title, date: this.date.isSet ? this.date.value : this.scene.date, studio_id: this.studio.isSet ? this.studio.value : this.scene.studio?.id, performer_ids: this.performers.isSet ? this.performers.value : this.scene.performers.map((performer) => performer.id), tag_ids: this.tags.isSet ? this.tags.value : this.scene.tags.map((tag) => tag.id), }; } } interface ISceneParserFieldProps { parserResult: ParserResult; className?: string; onSetChanged: (isSet: boolean) => void; onValueChanged: (value: T) => void; originalParserResult?: ParserResult; } function SceneParserStringField(props: ISceneParserFieldProps) { function maybeValueChanged(value: string) { if (value !== props.parserResult.value) { props.onValueChanged(value); } } const result = props.originalParserResult || props.parserResult; return ( <> { props.onSetChanged(!props.parserResult.isSet); }} /> ) => maybeValueChanged(event.currentTarget.value) } /> ); } function SceneParserRatingField( props: ISceneParserFieldProps ) { function maybeValueChanged(value?: number) { if (value !== props.parserResult.value) { props.onValueChanged(value); } } const result = props.originalParserResult || props.parserResult; const options = ["", 1, 2, 3, 4, 5]; return ( <> { props.onSetChanged(!props.parserResult.isSet); }} /> ) => maybeValueChanged( event.currentTarget.value === "" ? undefined : Number.parseInt(event.currentTarget.value, 10) ) } > {options.map((opt) => ( ))} ); } function SceneParserPerformerField(props: ISceneParserFieldProps) { function maybeValueChanged(value: string[]) { if (value !== props.parserResult.value) { props.onValueChanged(value); } } const originalPerformers = (props.originalParserResult?.originalValue ?? []) as string[]; const newPerformers = props.parserResult.value ?? []; return ( <> { props.onSetChanged(!props.parserResult.isSet); }} /> { maybeValueChanged(items.map((i) => i.id)); }} ids={newPerformers} /> ); } function SceneParserTagField(props: ISceneParserFieldProps) { function maybeValueChanged(value: string[]) { if (value !== props.parserResult.value) { props.onValueChanged(value); } } const originalTags = props.originalParserResult?.originalValue ?? []; const newTags = props.parserResult.value ?? []; return ( <> { props.onSetChanged(!props.parserResult.isSet); }} /> { maybeValueChanged(items.map((i) => i.id)); }} ids={newTags} /> ); } function SceneParserStudioField(props: ISceneParserFieldProps) { function maybeValueChanged(value: string) { if (value !== props.parserResult.value) { props.onValueChanged(value); } } const originalStudio = props.originalParserResult?.originalValue ? [props.originalParserResult?.originalValue] : []; const newStudio = props.parserResult.value ? [props.parserResult.value] : []; return ( <> { props.onSetChanged(!props.parserResult.isSet); }} /> { maybeValueChanged(items[0].id); }} ids={newStudio} /> ); } interface ISceneParserRowProps { scene: SceneParserResult; onChange: (changedScene: SceneParserResult) => void; showFields: Map; } export const SceneParserRow = (props: ISceneParserRowProps) => { function changeParser(result: ParserResult, isSet: boolean, value?: T) { const newParser = _.clone(result); newParser.isSet = isSet; newParser.value = value; return newParser; } function onTitleChanged(set: boolean, value: string) { const newResult = _.clone(props.scene); newResult.title = changeParser(newResult.title, set, value); props.onChange(newResult); } function onDateChanged(set: boolean, value: string) { const newResult = _.clone(props.scene); newResult.date = changeParser(newResult.date, set, value); props.onChange(newResult); } function onRatingChanged(set: boolean, value?: number) { const newResult = _.clone(props.scene); newResult.rating = changeParser(newResult.rating, set, value); props.onChange(newResult); } function onPerformerIdsChanged(set: boolean, value: string[]) { const newResult = _.clone(props.scene); newResult.performers = changeParser(newResult.performers, set, value); props.onChange(newResult); } function onTagIdsChanged(set: boolean, value: string[]) { const newResult = _.clone(props.scene); newResult.tags = changeParser(newResult.tags, set, value); props.onChange(newResult); } function onStudioIdChanged(set: boolean, value: string) { const newResult = _.clone(props.scene); newResult.studio = changeParser(newResult.studio, set, value); props.onChange(newResult); } return ( {props.scene.filename} {props.showFields.get("Title") && ( onTitleChanged(isSet, props.scene.title.value ?? "") } onValueChanged={(value) => onTitleChanged(props.scene.title.isSet, value) } /> )} {props.showFields.get("Date") && ( onDateChanged(isSet, props.scene.date.value ?? "") } onValueChanged={(value) => onDateChanged(props.scene.date.isSet, value) } /> )} {props.showFields.get("Rating") && ( onRatingChanged(isSet, props.scene.rating.value ?? undefined) } onValueChanged={(value) => onRatingChanged(props.scene.rating.isSet, value) } /> )} {props.showFields.get("Performers") && ( onPerformerIdsChanged(set, props.scene.performers.value ?? []) } onValueChanged={(value) => onPerformerIdsChanged(props.scene.performers.isSet, value) } /> )} {props.showFields.get("Tags") && ( onTagIdsChanged(isSet, props.scene.tags.value ?? []) } onValueChanged={(value) => onTagIdsChanged(props.scene.tags.isSet, value) } /> )} {props.showFields.get("Studio") && ( onStudioIdChanged(set, props.scene.studio.value ?? "") } onValueChanged={(value) => onStudioIdChanged(props.scene.studio.isSet, value) } /> )} ); };