diff options
Diffstat (limited to 'src/client/views/nodes/ComparisonBox.tsx')
-rw-r--r-- | src/client/views/nodes/ComparisonBox.tsx | 71 |
1 files changed, 39 insertions, 32 deletions
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 715b23fb6..62f630c6c 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -159,6 +159,37 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() moveDoc2 = (doc: Doc | Doc[], targetCol: Doc | undefined, addDoc: any) => (doc instanceof Doc ? [doc] : doc).reduce((res, doc: Doc) => res && this.moveDoc(doc, addDoc, this.fieldKey + '_2'), true); remDoc1 = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((res, doc) => res && this.remDoc(doc, this.fieldKey + '_1'), true); remDoc2 = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((res, doc) => res && this.remDoc(doc, this.fieldKey + '_2'), true); + + /** + * Tests for whether a comparison box slot (ie, before or after) has renderable text content + * @param whichSlot field key for start or end slot + * @returns a JSX layout string if a text field is found, othwerise undefined + */ + testForTextFields = (whichSlot: string) => { + const slotHasText = Doc.Get(this.dataDoc, whichSlot, true) instanceof RichTextField || typeof Doc.Get(this.dataDoc, whichSlot, true) === 'string'; + const subjectText = RTFCast(this.Document[this.fieldKey])?.Text.trim(); + const altText = RTFCast(this.Document[this.fieldKey + '_alternate'])?.Text.trim(); + const layoutTemplateString = + slotHasText ? FormattedTextBox.LayoutString(whichSlot): + whichSlot.endsWith('1') ? (subjectText !== undefined ? FormattedTextBox.LayoutString(this.fieldKey) : undefined) : + altText !== undefined ? FormattedTextBox.LayoutString(this.fieldKey + '_alternate'): undefined; // prettier-ignore + + // A bit hacky to try out the concept of using GPT to fill in flashcards + // If the second slot doesn't have anything in it, but the fieldKey slot has text (e.g., this.text is a string) + // and the fieldKey + "_alternate" has text that includes a GPT query (indicated by (( && )) ) that is parameterized (optionally) by the fieldKey text (this) or other metadata (this.<field>). + // eg., this.text_alternate is + // "((Provide a one sentence definition for (this) that doesn't use any word in (this.excludeWords) ))" + // where (this) is replaced by the text in the fieldKey slot abd this.excludeWords is repalced by the conetnts of the excludeWords field + // The GPT call will put the "answer" in the second slot of the comparison (eg., text_2) + if (whichSlot.endsWith('2') && !layoutTemplateString?.includes(whichSlot)) { + var queryText = altText.replace('(this)', subjectText); // TODO: this should be done in KeyValueBox.setField but it doesn't know about the fieldKey ... + if (queryText && queryText.match(/\(\(.*\)\)/)) { + KeyValueBox.SetField(this.Document, whichSlot, ':=' + queryText, false); // make the second slot be a computed field on the data doc that calls ChatGpt + } + } + return layoutTemplateString; + }; + _closeRef = React.createRef<HTMLDivElement>(); render() { const clearButton = (which: string) => { @@ -176,48 +207,24 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() /** * Display the Docs in the before/after fields of the comparison. This also supports a GPT flash card use case * where if there are no Docs in the slots, but the main fieldKey contains text, then - * @param which + * @param whichSlot * @returns */ - const displayDoc = (which: string) => { - const whichDoc = DocCast(this.dataDoc[which]); + const displayDoc = (whichSlot: string) => { + const whichDoc = DocCast(this.dataDoc[whichSlot]); const targetDoc = DocCast(whichDoc?.annotationOn, whichDoc); - const subjectText = RTFCast(this.Document[this.fieldKey])?.Text.trim(); - // if there is no Doc in the first comparison slot, but the comparison box's fieldKey slot has a RichTextField, then render a text box to show the contents of the document's field key slot - // of if there is no Doc in the second comparison slot, but the second slot has a RichTextField, then render a text box to show the contents of the document's field key slot - const layoutTemplateString = !targetDoc - ? which.endsWith('1') && subjectText !== undefined - ? FormattedTextBox.LayoutString(this.fieldKey) - : which.endsWith('2') && (this.Document[which] instanceof RichTextField || typeof this.Document[which] === 'string') - ? FormattedTextBox.LayoutString(which) - : undefined - : undefined; - - // A bit hacky to try out the concept of using GPT to fill in flashcards -- this whole process should probably be packaged into a script to be more generic. - // If the second slot doesn't have anything in it, but the fieldKey slot has text (e.g., this.text is a string) - // and the fieldKey + "_alternate" has text, then treat the _alternate's text as a GPT query (indicated by (( && )) ) that is parameterized (optionally) - // by the field references in the text (eg., this.text_alternate is - // "((Provide a one sentence definition for (this) that doesn't use any word in (this.excludeWords) ))" - // where (this) is replaced by the text in the fieldKey slot abd this.excludeWords is repalced by the conetnts of the excludeWords field - // A GPT call will put the "answer" in the second slot of the comparison (eg., text_2) - if (which.endsWith('2') && !layoutTemplateString && !targetDoc) { - var queryText = RTFCast(this.Document[this.fieldKey + '_alternate']) - ?.Text.replace('(this)', subjectText) // TODO: this should be done in KeyValueBox.setField but it doesn't know about the fieldKey ... - .trim(); - if (subjectText && queryText.match(/\(\(.*\)\)/)) { - KeyValueBox.SetField(this.Document, which, ':=' + queryText, false); // make the second slot be a computed field on the data doc that calls ChatGpt - } - } + const layoutTemplateString = targetDoc ? '' : this.testForTextFields(whichSlot); return targetDoc || layoutTemplateString ? ( <> <DocumentView {...this._props} + ignoreUsePath={layoutTemplateString ? true : undefined} renderDepth={this.props.renderDepth + 1} LayoutTemplateString={layoutTemplateString} Document={layoutTemplateString ? this.Document : targetDoc} containerViewPath={this.DocumentView?.().docViewPath} - moveDocument={which.endsWith('1') ? this.moveDoc1 : this.moveDoc2} - removeDocument={which.endsWith('1') ? this.remDoc1 : this.remDoc2} + moveDocument={whichSlot.endsWith('1') ? this.moveDoc1 : this.moveDoc2} + removeDocument={whichSlot.endsWith('1') ? this.remDoc1 : this.remDoc2} NativeWidth={returnZero} NativeHeight={returnZero} isContentActive={emptyFunction} @@ -227,7 +234,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() hideLinkButton={true} pointerEvents={this._isAnyChildContentActive ? undefined : returnNone} /> - {layoutTemplateString ? null : clearButton(which)} + {layoutTemplateString ? null : clearButton(whichSlot)} </> // placeholder image if doc is missing ) : ( <div className="placeholder"> |