diff options
-rw-r--r-- | src/client/views/nodes/formattedText/DailyJournal.tsx | 61 |
1 files changed, 56 insertions, 5 deletions
diff --git a/src/client/views/nodes/formattedText/DailyJournal.tsx b/src/client/views/nodes/formattedText/DailyJournal.tsx index 871c556e6..d6d30dc13 100644 --- a/src/client/views/nodes/formattedText/DailyJournal.tsx +++ b/src/client/views/nodes/formattedText/DailyJournal.tsx @@ -9,6 +9,7 @@ import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT'; import { RichTextField } from '../../../../fields/RichTextField'; import { Plugin } from 'prosemirror-state'; import { RTFCast } from '../../../../fields/Types'; +import { Mark } from 'prosemirror-model'; export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>() { @observable journalDate: string; @@ -17,6 +18,7 @@ export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>() _ref = React.createRef<FormattedTextBox>(); // reference to the formatted textbox predictiveTextRange: { from: number; to: number } | null = null; // where predictive text starts and ends private predictiveText: string | null = ' ... why?'; + private prePredictiveMarks: Mark[] = []; public static LayoutString(fieldStr: string) { return FieldView.LayoutString(DailyJournal, fieldStr); @@ -84,6 +86,27 @@ export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>() } /** + * Method to set initial date of document in the calendar view + */ + + @action setInitialDateRange() { + if (!this.dataDoc.date_range && this.journalDate) { + const parsedDate = new Date(this.journalDate); + if (!isNaN(parsedDate.getTime())) { + const localStart = new Date(parsedDate.getFullYear(), parsedDate.getMonth(), parsedDate.getDate()); + const localEnd = new Date(localStart); // same day + + this.dataDoc.date_range = `${localStart.toISOString()}|${localEnd.toISOString()}`; + this.dataDoc.allDay = true; + + console.log('Set date_range and allDay on journal (from local date):', this.dataDoc.date_range); + } else { + console.log('Could not parse journalDate:', this.journalDate); + } + } + } + + /** * Tracks user typing text inout into the node, to call the insert predicted * text function when appropriate (i.e. when the user stops typing) */ @@ -94,6 +117,22 @@ export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>() if (this.typingTimeout) clearTimeout(this.typingTimeout); + const { state } = editorView; + const cursorPos = state.selection.from; + + // characters before cursor + const triggerText = state.doc.textBetween(Math.max(0, cursorPos - 4), cursorPos); + + if (triggerText === '/ask') { + // remove /ask text + const tr = state.tr.delete(cursorPos - 4, cursorPos); + editorView.dispatch(tr); + + // insert predicted question + this.insertPredictiveQuestion(); + return; + } + this.typingTimeout = setTimeout(() => { this.insertPredictiveQuestion(); }, 3500); @@ -129,11 +168,17 @@ export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>() // Only insert if we're at end of node, or there's a newline node after if (!isAtEndOfParent && !hasNewlineAfter) return; - const fontSizeMark = schema.marks.pFontSize.create({ fontSize: '14px' }); + // Save current marks at cursor + const currentMarks = state.storedMarks || resolvedPos.marks(); + this.prePredictiveMarks = [...currentMarks]; + + // color and italics are preset for predictive question, font and size are adaptive const fontColorMark = schema.marks.pFontColor.create({ fontColor: 'lightgray' }); const fontItalicsMark = schema.marks.em.create(); + const fontSizeMark = this.prePredictiveMarks.find(m => m.type.name === 'pFontSize'); + const fontFamilyMark = this.prePredictiveMarks.find(m => m.type.name === 'pFontFamily'); // if applicable - this.predictiveText = ' ...'; // placeholder for now + this.predictiveText = ' ...'; // placeholder const fullTextUpToCursor = state.doc.textBetween(0, state.selection.to, '\n', '\n'); const gptPrompt = `Given the following incomplete journal entry, generate a single 2-5 word question that continues the user's thought:\n\n"${fullTextUpToCursor}"`; @@ -142,10 +187,10 @@ export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>() // styled text node const text = ` ... ${res.trim()}`; - const predictedText = schema.text(text, [fontSizeMark, fontColorMark, fontItalicsMark]); + const predictedText = schema.text(text, [fontColorMark, fontItalicsMark, ...(fontSizeMark ? [fontSizeMark] : []), ...(fontFamilyMark ? [fontFamilyMark] : [])]); // Insert styled text at cursor position - const transaction = state.tr.insert(insertPos, predictedText).setStoredMarks([state.schema.marks.pFontColor.create({ fontColor: 'gray' })]); // should probably instead inquire marks before predictive prompt + const transaction = state.tr.insert(insertPos, predictedText).setStoredMarks(this.prePredictiveMarks); dispatch(transaction); this.predictiveText = text; @@ -172,11 +217,16 @@ export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>() const fontSizeMark = state.schema.marks.pFontSize.create({ fontSize: '14px' }); const fontColorMark = state.schema.marks.pFontColor.create({ fontColor: 'gray' }); tr.setStoredMarks([]); - tr.setStoredMarks([fontSizeMark, fontColorMark]); + if (this.prePredictiveMarks.length > 0) { + tr.setStoredMarks(this.prePredictiveMarks); + } else { + tr.setStoredMarks([fontSizeMark, fontColorMark]); + } dispatch(tr); this.predictiveText = null; + this.prePredictiveMarks = []; return false; } return true; @@ -217,6 +267,7 @@ export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>() console.log('Journal title and text are default. Initializing...'); this.setDailyTitle(); this.setDailyText(); + this.setInitialDateRange(); } else { console.log('Journal already has content. Skipping initialization.'); } |