diff options
-rw-r--r-- | src/client/documents/Documents.ts | 52 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/DailyJournal.tsx | 145 |
2 files changed, 169 insertions, 28 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index fe121021d..668725d2b 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -920,36 +920,36 @@ export namespace Docs { // AARAV ADD // export function DailyJournalDocument(text: string | RichTextField, options: DocumentOptions = {}, fieldKey: string = 'text') { - const getFormattedDate = () => { - const date = new Date().toLocaleDateString(undefined, { - weekday: 'long', - year: 'numeric', - month: 'long', - day: 'numeric', - }); - return date; - }; - - const getDailyText = () => { - const placeholderText = 'Start writing here...'; - const dateText = `${getFormattedDate()}`; - - return RichTextField.textToRtfFormat( - [ - { text: 'Journal Entry:', styles: { bold: true, color: 'black', fontSize: 20 } }, - { text: dateText, styles: { italic: true, color: 'gray', fontSize: 15 } }, - { text: placeholderText, styles: { fontSize: 14, color: 'gray' } }, - ], - undefined, - placeholderText.length - ); - }; + // const getFormattedDate = () => { + // const date = new Date().toLocaleDateString(undefined, { + // weekday: 'long', + // year: 'numeric', + // month: 'long', + // day: 'numeric', + // }); + // return date; + // }; + + // const getDailyText = () => { + // const placeholderText = 'Start writing here...'; + // const dateText = `${getFormattedDate()}`; + + // return RichTextField.textToRtfFormat( + // [ + // { text: 'Journal Entry:', styles: { bold: true, color: 'black', fontSize: 20 } }, + // { text: dateText, styles: { italic: true, color: 'gray', fontSize: 15 } }, + // { text: placeholderText, styles: { fontSize: 14, color: 'gray' } }, + // ], + // undefined, + // placeholderText.length + // ); + // }; return InstanceFromProto( Prototypes.get(DocumentType.JOURNAL), - getDailyText(), + "", { - title: getFormattedDate(), + title: "", ...options, }, undefined, diff --git a/src/client/views/nodes/formattedText/DailyJournal.tsx b/src/client/views/nodes/formattedText/DailyJournal.tsx index 51e9d9ec1..31108f05a 100644 --- a/src/client/views/nodes/formattedText/DailyJournal.tsx +++ b/src/client/views/nodes/formattedText/DailyJournal.tsx @@ -1,12 +1,17 @@ -import { makeObservable } from 'mobx'; +import { makeObservable, action, observable, autorun } from 'mobx'; import * as React from 'react'; import { Docs } from '../../../documents/Documents'; import { DocumentType } from '../../../documents/DocumentTypes'; import { ViewBoxAnnotatableComponent } from '../../DocComponent'; import { FieldView, FieldViewProps } from '../FieldView'; import { FormattedTextBox, FormattedTextBoxProps } from './FormattedTextBox'; +import { gptAPICall, GPTCallType, gptImageLabel } from '../../../apis/gpt/GPT'; +import { RichTextField } from '../../../../fields/RichTextField'; +import { TextSelection } from 'prosemirror-state'; export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>() { + @observable journalDate: string; + public static LayoutString(fieldStr: string) { return FieldView.LayoutString(DailyJournal, fieldStr); } @@ -14,8 +19,126 @@ export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>() constructor(props: FormattedTextBoxProps) { super(props); makeObservable(this); + this.journalDate = this.getFormattedDate(); + } + + getFormattedDate(): string { + const date = new Date().toLocaleDateString(undefined, { + weekday: 'long', + year: 'numeric', + month: 'long', + day: 'numeric', + }); + console.log('getFormattedDate():', date); + return date; + } + + @action + setDailyTitle() { + console.log('setDailyTitle() called...'); + console.log('Current title before update:', this.dataDoc.title); + + if (!this.dataDoc.title || this.dataDoc.title !== this.journalDate) { + console.log('Updating title to:', this.journalDate); + this.dataDoc.title = this.journalDate; + } + + console.log('New title after update:', this.dataDoc.title); + } + + @action + setDailyText() { + const placeholderText = 'Start writing here...'; + const dateText = `${this.journalDate}\n`; + + console.log('Checking if dataDoc has text field...'); + + this.dataDoc[this.fieldKey] = RichTextField.textToRtfFormat( + [ + { text: 'Journal Entry:', styles: { bold: true, color: 'black', fontSize: 20 } }, + { text: dateText, styles: { italic: true, color: 'gray', fontSize: 15 } }, + { text: placeholderText, styles: { fontSize: 14, color: 'gray' } }, + ], + undefined, + placeholderText.length + ); + + console.log('Current text field:', this.dataDoc[this.fieldKey]); + } + + componentDidMount(): void { + console.log('componentDidMount() triggered...'); + console.log("Text: " + (this.Document.text as any)?.Text); + + const rawText = (this.Document.text as any)?.Text ?? ''; + const isTextEmpty = !rawText || rawText === ""; + + const currentTitle = this.dataDoc.title || ""; + const isTitleString = typeof currentTitle === 'string'; + const isDefaultTitle = isTitleString && currentTitle.includes("Untitled DailyJournal"); + + if (isTextEmpty && isDefaultTitle) { + console.log('Journal title and text are default. Initializing...'); + this.setDailyTitle(); + this.setDailyText(); + } else { + console.log('Journal already has content. Skipping initialization.'); + } } + @action handleGeneratePrompts = async () => { + const rawText = (this.Document.text as any)?.Text ?? ''; + console.log('Extracted Journal Text:', rawText); + console.log('Before Update:', this.Document.text, 'Type:', typeof this.Document.text); + + if (!rawText.trim()) { + alert('Journal is empty! Write something first.'); + return; + } + + try { + // Call GPT API to generate prompts + const res = await gptAPICall('Generate 1-2 short journal prompts for the following journal entry: ' + rawText, GPTCallType.COMPLETION); + + if (!res) { + console.error('GPT call failed.'); + return; + } + + const editorView = this._ref.current?.EditorView; + if (!editorView) { + console.error('EditorView is not available.'); + return; + } + + else { + const { state, dispatch } = editorView; + const { schema } = state; + + // Use available marks + const boldMark = schema.marks.strong.create(); + const italicMark = schema.marks.em.create(); + const fontSizeMark = schema.marks.pFontSize.create({ fontSize: "14px" }); + const fontColorMark = schema.marks.pFontColor.create({ fontColor: "gray" }); + + // Create text nodes with formatting + const headerText = schema.text('\n\n# Suggested Prompts:\n', [boldMark, italicMark, fontSizeMark, fontColorMark]); + const responseText = schema.text(res, [fontSizeMark, fontColorMark]); + + // Insert formatted text + const transaction = state.tr.insert( + state.selection.from, headerText).insert( + state.selection.from + headerText.nodeSize, responseText); + dispatch(transaction); + } + + } catch (err) { + console.error('Error calling GPT:', err); + } + }; + + _ref = React.createRef<FormattedTextBox>(); + render() { return ( <div @@ -34,7 +157,25 @@ export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>() backgroundSize: '100% 20px', backgroundRepeat: 'repeat', }}> - <FormattedTextBox {...this._props} fieldKey={'text'} Document={this.Document} TemplateDataDocument={undefined} /> + {/* GPT Button */} + <button + style={{ + position: 'absolute', + bottom: '5px', + right: '5px', + padding: '5px 10px', + backgroundColor: '#9EAD7C', + color: 'white', + border: 'none', + borderRadius: '5px', + cursor: 'pointer', + zIndex: 10, + }} + onClick={this.handleGeneratePrompts}> + Prompts + </button> + + <FormattedTextBox ref={this._ref} {...this._props} fieldKey={'text'} Document={this.Document} TemplateDataDocument={undefined} /> </div> ); } |