From 5290e6a69fdadb6037f3d8a03f5ed82e00927520 Mon Sep 17 00:00:00 2001 From: sharkiecodes Date: Mon, 21 Apr 2025 19:41:51 -0400 Subject: attempting to integrate scrapbooks --- src/client/views/nodes/scrapbook/ScrapbookBox.tsx | 106 +++++++++++++++++++++ .../views/nodes/scrapbook/ScrapbookContent.tsx | 23 +++++ src/client/views/nodes/scrapbook/ScrapbookSlot.tsx | 26 +++++ .../views/nodes/scrapbook/ScrapbookSlotTypes.ts | 25 +++++ 4 files changed, 180 insertions(+) create mode 100644 src/client/views/nodes/scrapbook/ScrapbookBox.tsx create mode 100644 src/client/views/nodes/scrapbook/ScrapbookContent.tsx create mode 100644 src/client/views/nodes/scrapbook/ScrapbookSlot.tsx create mode 100644 src/client/views/nodes/scrapbook/ScrapbookSlotTypes.ts (limited to 'src/client/views/nodes/scrapbook') diff --git a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx new file mode 100644 index 000000000..56cfcda70 --- /dev/null +++ b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx @@ -0,0 +1,106 @@ +import { makeObservable } from 'mobx'; +import * as React from 'react'; +import { ViewBoxAnnotatableComponent } from '../../DocComponent'; +import { FieldView, FieldViewProps } from '../FieldView'; +import { Docs } from '../../../documents/Documents'; +import { DocumentType } from '../../../documents/DocumentTypes'; +import { action, observable } from 'mobx'; +import { DocListCast } from '../../../../fields/Doc'; +import { Doc } from '../../../../fields/Doc'; +import { DocumentView } from '../DocumentView'; +import { FormattedTextBox } from '../formattedText/FormattedTextBox'; +import { List } from '../../../../fields/List'; +// Scrapbook view: a container that lays out its child items in a grid/template +export class ScrapbookBox extends ViewBoxAnnotatableComponent() { + @observable createdDate: string; + + constructor(props: FieldViewProps) { + super(props); + makeObservable(this); + this.createdDate = this.getFormattedDate(); + + // ensure we always have a List in dataDoc['items'] + if (!this.dataDoc[this.fieldKey]) { + this.dataDoc[this.fieldKey] = new List(); + } + this.createdDate = this.getFormattedDate(); + this.setTitle(); + } + + public static LayoutString(fieldStr: string) { + return FieldView.LayoutString(ScrapbookBox, fieldStr); + } + + + + + + + + getFormattedDate(): string { + return new Date().toLocaleDateString(undefined, { + year: 'numeric', + month: 'short', + day: 'numeric', + }); + } + + @action + setTitle() { + const title = `Scrapbook - ${this.createdDate}`; + if (this.dataDoc.title !== title) { + this.dataDoc.title = title; + } + } + + componentDidMount() { + this.setTitle(); + if (!this.dataDoc[this.fieldKey]) { + this.dataDoc[this.fieldKey] = new List(); + } + } + + render() { + // cast into an array even if empty + const items: Doc[] = DocListCast(this.dataDoc[this.fieldKey]); + + return ( +
+ +
+ + //
+ // {items.length === 0 + // ?
Drop docs here
+ // : items.map((childDoc, idx) => ( + // + // )) + // } + //
+ ); + } +} + + +// Register scrapbook +Docs.Prototypes.TemplateMap.set(DocumentType.SCRAPBOOK, { + layout: { view: ScrapbookBox, dataField: 'items' }, + options: { + acl: '', + _height: 200, + _xMargin: 10, + _yMargin: 10, + _layout_autoHeight: true, + _layout_reflowVertical: true, + _layout_reflowHorizontal: true, + defaultDoubleClick: 'ignore', + systemIcon: 'BsImages', + }, +}); diff --git a/src/client/views/nodes/scrapbook/ScrapbookContent.tsx b/src/client/views/nodes/scrapbook/ScrapbookContent.tsx new file mode 100644 index 000000000..ad1d308e8 --- /dev/null +++ b/src/client/views/nodes/scrapbook/ScrapbookContent.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import { observer } from "mobx-react-lite"; +// Import the Doc type from your actual module. +import { Doc } from "../../../../fields/Doc"; + +export interface ScrapbookContentProps { + doc: Doc; +} + +// A simple view that displays a document's title and content. +// Adjust how you extract the text if your Doc fields are objects. +export const ScrapbookContent: React.FC = observer(({ doc }) => { + // If doc.title or doc.content are not plain strings, convert them. + const titleText = doc.title ? doc.title.toString() : "Untitled"; + const contentText = doc.content ? doc.content.toString() : "No content available."; + + return ( +
+

{titleText}

+

{contentText}

+
+ ); +}); diff --git a/src/client/views/nodes/scrapbook/ScrapbookSlot.tsx b/src/client/views/nodes/scrapbook/ScrapbookSlot.tsx new file mode 100644 index 000000000..05215d3e5 --- /dev/null +++ b/src/client/views/nodes/scrapbook/ScrapbookSlot.tsx @@ -0,0 +1,26 @@ +export interface SlotDefinition { + id: string; + x: number; y: number; + defaultWidth: number; + defaultHeight: number; + } + + export interface SlotContentMap { + slotId: string; + docId?: string; + } + + export interface ScrapbookConfig { + slots: SlotDefinition[]; + contents?: SlotContentMap[]; + } + + export const DEFAULT_SCRAPBOOK_CONFIG: ScrapbookConfig = { + slots: [ + { id: "slot1", x: 10, y: 10, defaultWidth: 180, defaultHeight: 120 }, + { id: "slot2", x: 200, y: 10, defaultWidth: 180, defaultHeight: 120 }, + // …etc + ], + contents: [] + }; + \ No newline at end of file diff --git a/src/client/views/nodes/scrapbook/ScrapbookSlotTypes.ts b/src/client/views/nodes/scrapbook/ScrapbookSlotTypes.ts new file mode 100644 index 000000000..686917d9a --- /dev/null +++ b/src/client/views/nodes/scrapbook/ScrapbookSlotTypes.ts @@ -0,0 +1,25 @@ +// ScrapbookSlotTypes.ts +export interface SlotDefinition { + id: string; + title: string; + x: number; + y: number; + defaultWidth: number; + defaultHeight: number; + } + + export interface ScrapbookConfig { + slots: SlotDefinition[]; + contents?: { slotId: string; docId: string }[]; + } + + // give it three slots by default: + export const DEFAULT_SCRAPBOOK_CONFIG: ScrapbookConfig = { + slots: [ + { id: "main", title: "Main Content", x: 20, y: 20, defaultWidth: 360, defaultHeight: 200 }, + { id: "notes", title: "Notes", x: 20, y: 240, defaultWidth: 360, defaultHeight: 160 }, + { id: "resources", title: "Resources", x: 400, y: 20, defaultWidth: 320, defaultHeight: 380 }, + ], + contents: [], + }; + \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 6afd4147e7063348aa784a6057ca0a19c32a6dc8 Mon Sep 17 00:00:00 2001 From: sharkiecodes Date: Tue, 22 Apr 2025 09:59:17 -0400 Subject: trying to push scrapbook changes to git --- src/client/views/Main.tsx | 5 +- .../views/nodes/scrapbook/EmbeddedDocView.tsx | 52 +++++++++ .../views/nodes/scrapbook/ScrapbookSlot.scss | 85 ++++++++++++++ src/client/views/nodes/scrapbook/ScrapbookSlot.tsx | 2 + .../views/nodes/scrapbook/ScrapbookVersionTwo.tsx | 125 +++++++++++++++++++++ 5 files changed, 267 insertions(+), 2 deletions(-) create mode 100644 src/client/views/nodes/scrapbook/EmbeddedDocView.tsx create mode 100644 src/client/views/nodes/scrapbook/ScrapbookSlot.scss create mode 100644 src/client/views/nodes/scrapbook/ScrapbookVersionTwo.tsx (limited to 'src/client/views/nodes/scrapbook') diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 7992ed412..64334ac47 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -53,7 +53,7 @@ import { WebBox } from './nodes/WebBox'; import { CalendarBox } from './nodes/calendarBox/CalendarBox'; import { ChatBox } from './nodes/chatbot/chatboxcomponents/ChatBox'; import { DailyJournal } from './nodes/formattedText/DailyJournal'; -import { ScrapbookVersionTwo } from './nodes/scrapbook/ScrapbookVersionTwo'; +//import { ScrapbookVersionTwo } from './nodes/scrapbook/ScrapbookVersionTwo'; import { DashDocCommentView } from './nodes/formattedText/DashDocCommentView'; import { DashDocView } from './nodes/formattedText/DashDocView'; import { DashFieldView } from './nodes/formattedText/DashFieldView'; @@ -66,6 +66,7 @@ import { PresBox, PresSlideBox } from './nodes/trails'; import { FaceRecognitionHandler } from './search/FaceRecognitionHandler'; import { SearchBox } from './search/SearchBox'; import { StickerPalette } from './smartdraw/StickerPalette'; +import { ScrapbookBox } from './nodes/scrapbook/ScrapbookBox'; dotenv.config(); @@ -121,7 +122,7 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0, message: 'cache' }; FormattedTextBox, DailyJournal, // AARAV ImageBox, - ScrapbookVersionTwo, + ScrapbookBox, FontIconBox, LabelBox, EquationBox, diff --git a/src/client/views/nodes/scrapbook/EmbeddedDocView.tsx b/src/client/views/nodes/scrapbook/EmbeddedDocView.tsx new file mode 100644 index 000000000..e99bf67c7 --- /dev/null +++ b/src/client/views/nodes/scrapbook/EmbeddedDocView.tsx @@ -0,0 +1,52 @@ +//IGNORE FOR NOW, CURRENTLY NOT USED IN SCRAPBOOK IMPLEMENTATION +import * as React from "react"; +import { observer } from "mobx-react"; +import { Doc } from "../../../../fields/Doc"; +import { DocumentView } from "../DocumentView"; +import { Transform } from "../../../util/Transform"; + +interface EmbeddedDocViewProps { + doc: Doc; + width?: number; + height?: number; + slotId?: string; +} + +@observer +export class EmbeddedDocView extends React.Component { + render() { + const { doc, width = 300, height = 200, slotId } = this.props; + + // Use either an existing embedding or create one + let docToDisplay = doc; + + // If we need an embedding, create or use one + if (!docToDisplay.isEmbedding) { + docToDisplay = Doc.BestEmbedding(doc) || Doc.MakeEmbedding(doc); + // Set the container to the slot's ID so we can track it + if (slotId) { + docToDisplay.embedContainer = `scrapbook-slot-${slotId}`; + } + } + + return ( + width} + NativeHeight={() => height} + PanelWidth={() => width} + PanelHeight={() => height} + // Required state functions + isContentActive={() => true} + childFilters={() => []} + ScreenToLocalTransform={() => new Transform()} + // Display options + hideDeleteButton={true} + hideDecorations={true} + hideResizeHandles={true} + /> + ); + } +} \ No newline at end of file diff --git a/src/client/views/nodes/scrapbook/ScrapbookSlot.scss b/src/client/views/nodes/scrapbook/ScrapbookSlot.scss new file mode 100644 index 000000000..ae647ad36 --- /dev/null +++ b/src/client/views/nodes/scrapbook/ScrapbookSlot.scss @@ -0,0 +1,85 @@ +//IGNORE FOR NOW, CURRENTLY NOT USED IN SCRAPBOOK IMPLEMENTATION +.scrapbook-slot { + position: absolute; + background-color: rgba(245, 245, 245, 0.7); + border: 2px dashed #ccc; + border-radius: 5px; + box-sizing: border-box; + transition: all 0.2s ease; + overflow: hidden; + + &.scrapbook-slot-over { + border-color: #4a90e2; + background-color: rgba(74, 144, 226, 0.1); + } + + &.scrapbook-slot-filled { + border-style: solid; + border-color: rgba(0, 0, 0, 0.1); + background-color: transparent; + + &.scrapbook-slot-over { + border-color: #4a90e2; + background-color: rgba(74, 144, 226, 0.1); + } + } + + .scrapbook-slot-empty { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + } + + .scrapbook-slot-placeholder { + text-align: center; + color: #888; + } + + .scrapbook-slot-title { + font-weight: bold; + margin-bottom: 5px; + } + + .scrapbook-slot-instruction { + font-size: 0.9em; + font-style: italic; + } + + .scrapbook-slot-content { + width: 100%; + height: 100%; + position: relative; + } + + .scrapbook-slot-controls { + position: absolute; + top: 5px; + right: 5px; + z-index: 10; + opacity: 0; + transition: opacity 0.2s ease; + + .scrapbook-slot-remove-btn { + background-color: rgba(255, 255, 255, 0.8); + border: 1px solid #ccc; + border-radius: 50%; + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + font-size: 10px; + + &:hover { + background-color: rgba(255, 0, 0, 0.1); + } + } + } + + &:hover .scrapbook-slot-controls { + opacity: 1; + } +} \ No newline at end of file diff --git a/src/client/views/nodes/scrapbook/ScrapbookSlot.tsx b/src/client/views/nodes/scrapbook/ScrapbookSlot.tsx index 05215d3e5..2c8f93778 100644 --- a/src/client/views/nodes/scrapbook/ScrapbookSlot.tsx +++ b/src/client/views/nodes/scrapbook/ScrapbookSlot.tsx @@ -1,3 +1,5 @@ + +//IGNORE FOR NOW, CURRENTLY NOT USED IN SCRAPBOOK IMPLEMENTATION export interface SlotDefinition { id: string; x: number; y: number; diff --git a/src/client/views/nodes/scrapbook/ScrapbookVersionTwo.tsx b/src/client/views/nodes/scrapbook/ScrapbookVersionTwo.tsx new file mode 100644 index 000000000..d15d2fe56 --- /dev/null +++ b/src/client/views/nodes/scrapbook/ScrapbookVersionTwo.tsx @@ -0,0 +1,125 @@ +//IGNORE FOR NOW, CURRENTLY NOT USED IN SCRAPBOOK IMPLEMENTATION +import { action, makeObservable, observable } from 'mobx'; +import * as React from 'react'; +import { RichTextField } from '../../../../fields/RichTextField'; +import { Docs } from '../../../documents/Documents'; +import { DocumentType } from '../../../documents/DocumentTypes'; +import { ViewBoxAnnotatableComponent } from '../../DocComponent'; +import { FieldView, FieldViewProps } from '../FieldView'; +import { FormattedTextBox, FormattedTextBoxProps } from '../formattedText/FormattedTextBox'; + +export class ScrapbookVersionTwo extends ViewBoxAnnotatableComponent() { + @observable scrapbookDate: string; + + public static LayoutString(fieldStr: string) { + return FieldView.LayoutString(ScrapbookVersionTwo, fieldStr); + } + + constructor(props: FormattedTextBoxProps) { + super(props); + makeObservable(this); + this.scrapbookDate = this.getFormattedDate(); + + console.log('Constructor: Setting initial title and text...'); + this.setDailyTitle(); + this.setDailyText(); + } + + 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.scrapbookDate) { + console.log('Updating title to:', this.scrapbookDate); + this.dataDoc.title = this.scrapbookDate; + } + + console.log('New title after update:', this.dataDoc.title); + } + + @action + setDailyText() { + console.log('setDailyText() called...'); + const placeholderText = 'Start writing here...'; + const initialText = `Scrapbook - $\n${placeholderText}`; + + console.log('Checking if dataDoc has text field...'); + + const styles = { + bold: true, // Make the journal date bold + color: 'red', // Set the journal date color to blue + fontSize: 12, // Set the font size to 18px for the whole text + display: 'grid', + gridTemplateColumns: 'repeat(auto-fill, minmax(100px, 1fr))', + gap: '8px', + padding: '10px', + background: '#fafafa', + width: '100%', + height: '100%', + }; + + console.log('Setting new text field with:', initialText); + this.dataDoc[this.fieldKey] = RichTextField.textToRtf( + initialText, + undefined, // No image DocId + styles, // Pass the styles object here + placeholderText.length // The position for text selection + ); + + console.log('Current text field:', this.dataDoc[this.fieldKey]); + } + + componentDidMount(): void { + console.log('componentDidMount() triggered...'); + // bcz: This should be moved into Docs.Create.DailyJournalDocument() + // otherwise, it will override all the text whenever the note is reloaded + this.setDailyTitle(); + this.setDailyText(); + } + + render() { + return ( +
+ +
+ ); + } +} + +Docs.Prototypes.TemplateMap.set(DocumentType.SCRAPBOOK, { + layout: { view: ScrapbookVersionTwo, dataField: 'text' }, + options: { + acl: '', + _height: 35, + _xMargin: 10, + _yMargin: 10, + _layout_autoHeight: true, + _layout_nativeDimEditable: true, + _layout_reflowVertical: true, + _layout_reflowHorizontal: true, + defaultDoubleClick: 'ignore', + systemIcon: 'BsFileEarmarkTextFill', + }, +}); \ No newline at end of file -- cgit v1.2.3-70-g09d2 From e8f1d494d36a5e1f1ee33d59faa4be2559cd752e Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 22 Apr 2025 10:54:38 -0400 Subject: adding drop handling code for scrapbookBox --- src/client/documents/DocUtils.ts | 60 +++++++-------- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/InkingStroke.tsx | 2 +- src/client/views/Main.tsx | 4 +- .../views/collections/CollectionStackingView.tsx | 5 +- src/client/views/collections/CollectionSubView.tsx | 3 +- src/client/views/collections/CollectionView.tsx | 20 ++--- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 + .../collectionGrid/CollectionGridView.tsx | 1 + .../collectionLinear/CollectionLinearView.tsx | 1 + .../CollectionMulticolumnView.tsx | 1 + .../CollectionMultirowView.tsx | 1 + src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/nodes/FontIconBox/FontIconBox.tsx | 4 +- src/client/views/nodes/ImageBox.tsx | 5 +- src/client/views/nodes/scrapbook/ScrapbookBox.tsx | 87 ++++++++++++---------- 16 files changed, 104 insertions(+), 96 deletions(-) (limited to 'src/client/views/nodes/scrapbook') diff --git a/src/client/documents/DocUtils.ts b/src/client/documents/DocUtils.ts index db0770b12..df14dce5a 100644 --- a/src/client/documents/DocUtils.ts +++ b/src/client/documents/DocUtils.ts @@ -308,13 +308,7 @@ export namespace DocUtils { */ export async function DocumentFromType(type: string, path: string, options: DocumentOptions, overwriteDoc?: Doc): Promise> { let ctor: ((path: string, options: DocumentOptions, overwriteDoc?: Doc) => Doc | Promise) | undefined; - - if (type.indexOf('scrapbook') !== -1) { - ctor = Docs.Create.ScrapbookDocument; - if (!options._width) options._width = 400; - if (!options._title) options._title = 'New Scrapbook'; - } - + if (type.indexOf('image') !== -1) { ctor = Docs.Create.ImageDocument; if (!options._width) options._width = 300; @@ -718,33 +712,31 @@ export namespace DocUtils { nativeWidth: 40, nativeHeight: 40, }) - : (defaultTextTemplate?.type === DocumentType.JOURNAL ? Docs.Create.DailyJournalDocument:Docs.Create.TextDocument)( - '', - { - annotationOn, - backgroundColor, - x, - y, - title, - ...(defaultTextTemplate - ? {} // if the new doc will inherit from a template, don't set any layout fields since that would block the inheritance - : { - _width: width || BoolCast(Doc.UserDoc().fitBox) ? Number(StrCast(Doc.UserDoc().fontSize).replace('px', '')) * 1.5 * 6 : 200, - _height: BoolCast(Doc.UserDoc().fitBox) ? Number(StrCast(Doc.UserDoc().fontSize).replace('px', '')) * 1.5 : 35, - _layout_autoHeight: true, - backgroundColor: StrCast(Doc.UserDoc().textBackgroundColor), - borderColor: Doc.UserDoc().borderColor as string, - borderWidth: Doc.UserDoc().borderWidth as number, - text_centered: BoolCast(Doc.UserDoc().textCentered), - text_fitBox: BoolCast(Doc.UserDoc().fitBox), - text_align: StrCast(Doc.UserDoc().textAlign), - text_fontColor: StrCast(Doc.UserDoc().fontColor), - text_fontFamily: StrCast(Doc.UserDoc().fontFamily), - text_fontWeight: StrCast(Doc.UserDoc().fontWeight), - text_fontStyle: StrCast(Doc.UserDoc().fontStyle), - text_fontDecoration: StrCast(Doc.UserDoc().fontDecoration), - }), - }); + : (defaultTextTemplate?.type === DocumentType.JOURNAL ? Docs.Create.DailyJournalDocument : Docs.Create.TextDocument)('', { + annotationOn, + backgroundColor, + x, + y, + title, + ...(defaultTextTemplate + ? {} // if the new doc will inherit from a template, don't set any layout fields since that would block the inheritance + : { + _width: width || BoolCast(Doc.UserDoc().fitBox) ? Number(StrCast(Doc.UserDoc().fontSize).replace('px', '')) * 1.5 * 6 : 200, + _height: BoolCast(Doc.UserDoc().fitBox) ? Number(StrCast(Doc.UserDoc().fontSize).replace('px', '')) * 1.5 : 35, + _layout_autoHeight: true, + backgroundColor: StrCast(Doc.UserDoc().textBackgroundColor), + borderColor: Doc.UserDoc().borderColor as string, + borderWidth: Doc.UserDoc().borderWidth as number, + text_centered: BoolCast(Doc.UserDoc().textCentered), + text_fitBox: BoolCast(Doc.UserDoc().fitBox), + text_align: StrCast(Doc.UserDoc().textAlign), + text_fontColor: StrCast(Doc.UserDoc().fontColor), + text_fontFamily: StrCast(Doc.UserDoc().fontFamily), + text_fontWeight: StrCast(Doc.UserDoc().fontWeight), + text_fontStyle: StrCast(Doc.UserDoc().fontStyle), + text_fontDecoration: StrCast(Doc.UserDoc().fontDecoration), + }), + }); if (defaultTextTemplate) { tbox.layout_fieldKey = 'layout_' + StrCast(defaultTextTemplate.title); diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 7424aaf2c..3f11a4713 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -240,7 +240,7 @@ export class DocumentDecorations extends ObservableReactComponent() * factor for converting between ink and screen space. */ inkScaledData = () => { - const inkData = Cast(this.dataDoc[this.fieldKey], InkField, Cast(this.layoutDoc[this.fieldKey], InkField, null))?.inkData ?? []; + const inkData = Cast(this.dataDoc[this.fieldKey], InkField, Cast(this.layoutDoc[this.fieldKey], InkField, null) ?? null)?.inkData ?? []; const inkStrokeWidth = NumCast(this.layoutDoc.stroke_width, 1); const inkTop = Math.min(...inkData.map(p => p.Y)) - inkStrokeWidth / 2; const inkBottom = Math.max(...inkData.map(p => p.Y)) + inkStrokeWidth / 2; diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 7992ed412..b884eb8c8 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -53,7 +53,6 @@ import { WebBox } from './nodes/WebBox'; import { CalendarBox } from './nodes/calendarBox/CalendarBox'; import { ChatBox } from './nodes/chatbot/chatboxcomponents/ChatBox'; import { DailyJournal } from './nodes/formattedText/DailyJournal'; -import { ScrapbookVersionTwo } from './nodes/scrapbook/ScrapbookVersionTwo'; import { DashDocCommentView } from './nodes/formattedText/DashDocCommentView'; import { DashDocView } from './nodes/formattedText/DashDocView'; import { DashFieldView } from './nodes/formattedText/DashFieldView'; @@ -66,6 +65,7 @@ import { PresBox, PresSlideBox } from './nodes/trails'; import { FaceRecognitionHandler } from './search/FaceRecognitionHandler'; import { SearchBox } from './search/SearchBox'; import { StickerPalette } from './smartdraw/StickerPalette'; +import { ScrapbookBox } from './nodes/scrapbook/ScrapbookBox'; dotenv.config(); @@ -121,7 +121,6 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0, message: 'cache' }; FormattedTextBox, DailyJournal, // AARAV ImageBox, - ScrapbookVersionTwo, FontIconBox, LabelBox, EquationBox, @@ -136,6 +135,7 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0, message: 'cache' }; VideoBox, AudioBox, RecordingBox, + ScrapbookBox, PresBox, PresSlideBox, SearchBox, diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 9155227dd..f11e646cc 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -343,7 +343,7 @@ export class CollectionStackingView extends CollectionSubView Cast(this.Document.childLayoutFitWidth, 'boolean', this._props.childLayoutFitWidth?.(doc) ?? Cast(doc.layout_fitWidth, 'boolean', null) ?? null); // this is what renders the document that you see on the screen // called in Children: this actually adds a document to our children list - getDisplayDoc(doc: Doc, trans: () => string, count: number) { + getDisplayDoc = (doc: Doc, trans: () => string, count: number) => { const dataDoc = doc.isTemplateDoc || doc.isTemplateForField ? this._props.TemplateDataDocument : undefined; this._docXfs.push({ stackedDocTransform: this.getDocTransform(doc), width: this.getDocWidth(doc), height: this.getDocHeight(doc) }); return count > this._renderCount ? null : ( @@ -384,6 +384,7 @@ export class CollectionStackingView extends CollectionSubView ); - } + }; getDocTransform = computedFn((doc: Doc) => () => { // these must be referenced for document decorations to update when the text box container is scrolled diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index bc7d6f897..9a0fda3f8 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -58,6 +58,7 @@ export interface CollectionViewProps extends React.PropsWithChildren number; childContextMenuItems?: () => { script: ScriptField; label: string }[]; childLayoutTemplate?: () => Doc | undefined; // specify a layout Doc template to use for children of the collection + childRejectDrop?: (draggedDoc: Doc[] | undefined, subView?: DocumentView) => boolean; // whether a child document can be dropped on this document childHideDecorationTitle?: boolean; childHideResizeHandles?: boolean; childHideDecorations?: boolean; @@ -323,7 +324,7 @@ export function CollectionSubView() { protected onInternalDrop(e: Event, de: DragManager.DropEvent): boolean { const { docDragData } = de.complete; - if (docDragData && !docDragData.draggedDocuments.includes(this.Document)) { + if (docDragData && !docDragData.draggedDocuments.includes(this.Document) && !this._props.rejectDrop?.(docDragData.draggedDocuments, this.DocumentView?.())) { let added; const dropAction = docDragData.dropAction || docDragData.userDropAction; const targetDocments = DocListCast(this.dataDoc[this._props.fieldKey]); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index c9af92a1b..eb9caf29d 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -183,15 +183,17 @@ export class CollectionView extends ViewBoxAnnotatableComponent - onClicks.push({ - description: `Set child ${childClick.title}`, - icon: 'edit', - event: () => { - this.dataDoc[StrCast(childClick.targetScriptKey)] = ObjectField.MakeCopy(ScriptCast(childClick.data)); - }, - }) - ); + DocListCast(Cast(Doc.UserDoc()['clickFuncs-child'], Doc, null)?.data) + .filter(childClick => ScriptCast(childClick.data)) + .forEach(childClick => + onClicks.push({ + description: `Set child ${childClick.title}`, + icon: 'edit', + event: () => { + this.dataDoc[StrCast(childClick.targetScriptKey)] = ObjectField.MakeCopy(ScriptCast(childClick.data)!); + }, + }) + ); !Doc.IsSystem(this.Document) && !existingOnClick && cm.addItem({ description: 'OnClick...', noexpand: true, subitems: onClicks, icon: 'mouse-pointer' }); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 842293358..08126d4fe 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -496,6 +496,7 @@ export class CollectionFreeFormView extends CollectionSubView { + if (this._props.rejectDrop?.(de.complete.docDragData?.draggedDocuments, this._props.DocumentView?.())) return false; if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de, de.complete.annoDragData); if (de.complete.linkDragData) return this.internalLinkDrop(e, de, de.complete.linkDragData); if (de.complete.docDragData?.droppedDocuments.length) return this.internalDocDrop(e, de, de.complete.docDragData); @@ -1562,6 +1563,7 @@ export class CollectionFreeFormView extends CollectionSubView string | undefined; // is this document part of a group that is active // eslint-disable-next-line no-use-before-define setContentViewBox?: (view: ViewBoxInterface) => void; // called by rendered field's viewBox so that DocumentView can make direct calls to the viewBox - + rejectDrop?: (draggedDoc: Doc[] | undefined, subView?: DocumentView) => boolean; // whether a document drop is rejected PanelWidth: () => number; PanelHeight: () => number; isDocumentActive?: () => boolean | undefined; // whether a document should handle pointer events diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index 3190757e2..5941e1669 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -117,10 +117,10 @@ export class FontIconBox extends ViewBoxBaseComponent() { default: type = 'slider'; break; } // prettier-ignore - const numScript = (value?: number) => ScriptCast(this.Document.script).script.run({ this: this.Document, value, _readOnly_: value === undefined }); + const numScript = (value?: number) => ScriptCast(this.Document.script)?.script.run({ this: this.Document, value, _readOnly_: value === undefined }); const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string; // Script for checking the outcome of the toggle - const checkResult = Number(Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3))); + const checkResult = Number(Number(numScript()?.result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3))); return ( () { drop = undoable( action((e: Event, de: DragManager.DropEvent) => { - if (de.complete.docDragData) { + if (de.complete.docDragData && this._props.rejectDrop?.(de.complete.docDragData?.draggedDocuments, this.DocumentView?.())) { let added: boolean | undefined; const hitDropTarget = (ele: HTMLElement, dropTarget: HTMLDivElement | null): boolean => { if (!ele) return false; @@ -938,6 +938,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { ScreenToLocalTransform={this.screenToLocalTransform} select={emptyFunction} focus={this.focus} + rejectDrop={this._props.rejectDrop} getScrollHeight={this.getScrollHeight} NativeDimScaling={returnOne} isAnyChildContentActive={returnFalse} diff --git a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx index 56cfcda70..b02976067 100644 --- a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx +++ b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx @@ -1,24 +1,25 @@ -import { makeObservable } from 'mobx'; +import { action, makeObservable, observable } from 'mobx'; import * as React from 'react'; -import { ViewBoxAnnotatableComponent } from '../../DocComponent'; -import { FieldView, FieldViewProps } from '../FieldView'; +import { Doc } from '../../../../fields/Doc'; +import { List } from '../../../../fields/List'; +import { emptyFunction } from '../../../../Utils'; import { Docs } from '../../../documents/Documents'; import { DocumentType } from '../../../documents/DocumentTypes'; -import { action, observable } from 'mobx'; -import { DocListCast } from '../../../../fields/Doc'; -import { Doc } from '../../../../fields/Doc'; +import { CollectionView } from '../../collections/CollectionView'; +import { ViewBoxAnnotatableComponent } from '../../DocComponent'; import { DocumentView } from '../DocumentView'; -import { FormattedTextBox } from '../formattedText/FormattedTextBox'; -import { List } from '../../../../fields/List'; +import { FieldView, FieldViewProps } from '../FieldView'; +import { DragManager } from '../../../util/DragManager'; // Scrapbook view: a container that lays out its child items in a grid/template export class ScrapbookBox extends ViewBoxAnnotatableComponent() { @observable createdDate: string; + private _dropDisposer?: DragManager.DragDropDisposer; constructor(props: FieldViewProps) { super(props); makeObservable(this); this.createdDate = this.getFormattedDate(); - + // ensure we always have a List in dataDoc['items'] if (!this.dataDoc[this.fieldKey]) { this.dataDoc[this.fieldKey] = new List(); @@ -31,12 +32,6 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent() return FieldView.LayoutString(ScrapbookBox, fieldStr); } - - - - - - getFormattedDate(): string { return new Date().toLocaleDateString(undefined, { year: 'numeric', @@ -55,40 +50,50 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent() componentDidMount() { this.setTitle(); - if (!this.dataDoc[this.fieldKey]) { - this.dataDoc[this.fieldKey] = new List(); - } } + childRejectDrop = (draggedDoc: Doc[] | undefined, subView?: DocumentView) => { + if (draggedDoc?.length === 1 && subView) { + if (subView.Document.type === DocumentType.IMG && draggedDoc[0].$type !== DocumentType.IMG) { + return true; + } + } + return false; + }; + rejectDrop = (draggedDoc: Doc[] | undefined, subView?: DocumentView) => { + if (draggedDoc?.length === 1 && draggedDoc[0].$type !== DocumentType.IMG) { + return true; + } + return false; + }; + onInternalDrop = (e: Event, de: DragManager.DropEvent) => { + if (de.complete.docDragData?.draggedDocuments[0]?.$type === DocumentType.IMG) { + return true; + } + return false; + }; + + protected createDashEventsTarget = (ele: HTMLDivElement | null) => { + this._dropDisposer?.(); + if (ele) { + this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc); + } + }; + render() { - // cast into an array even if empty - const items: Doc[] = DocListCast(this.dataDoc[this.fieldKey]); - return ( -
- +
r && this.createDashEventsTarget(r)}> +
- - //
- // {items.length === 0 - // ?
Drop docs here
- // : items.map((childDoc, idx) => ( - // - // )) - // } - //
); - } + } } - // Register scrapbook Docs.Prototypes.TemplateMap.set(DocumentType.SCRAPBOOK, { layout: { view: ScrapbookBox, dataField: 'items' }, -- cgit v1.2.3-70-g09d2 From 6aa7649ea9195cf3fc53cf70e126095a9045e057 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 22 Apr 2025 10:58:03 -0400 Subject: from last --- src/client/views/nodes/LinkBox.tsx | 1 + .../views/nodes/imageEditor/imageMeshTool/imageMeshToolButton.tsx | 2 +- src/client/views/nodes/scrapbook/ScrapbookBox.tsx | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/client/views/nodes/scrapbook') diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 8bf65b637..78c8a686c 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -128,6 +128,7 @@ export class LinkBox extends ViewBoxBaseComponent() { const getAnchor = (field: FieldResult): Element[] => { const docField = DocCast(field); const doc = docField?.layout_unrendered ? DocCast(docField.annotationOn, docField) : docField; + if (!doc) return []; const ele = document.getElementById(DocumentView.UniquifyId(DocumentView.LightboxContains(this.DocumentView?.()), doc[Id])); if (ele?.className === 'linkBox-label') foundParent = true; if (ele?.getBoundingClientRect().width) return [ele]; diff --git a/src/client/views/nodes/imageEditor/imageMeshTool/imageMeshToolButton.tsx b/src/client/views/nodes/imageEditor/imageMeshTool/imageMeshToolButton.tsx index eb68410b0..c02a1eb94 100644 --- a/src/client/views/nodes/imageEditor/imageMeshTool/imageMeshToolButton.tsx +++ b/src/client/views/nodes/imageEditor/imageMeshTool/imageMeshToolButton.tsx @@ -19,7 +19,7 @@ interface ButtonContainerProps { export function MeshTransformButton({ loading, - onClick: startMeshTransform, + onClick, onReset, btnText, imageWidth, diff --git a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx index b02976067..24946f4d2 100644 --- a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx +++ b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx @@ -60,7 +60,7 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent() } return false; }; - rejectDrop = (draggedDoc: Doc[] | undefined, subView?: DocumentView) => { + rejectDrop = (draggedDoc: Doc[] | undefined /* , subView?: DocumentView */) => { if (draggedDoc?.length === 1 && draggedDoc[0].$type !== DocumentType.IMG) { return true; } -- cgit v1.2.3-70-g09d2 From 7671e543dc677c82071d6eaccc33bd164450620d Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 22 Apr 2025 14:45:05 -0400 Subject: protoype version of scrapboxBox. added rejectDrop prop to prevent drops on child documentviews --- src/client/views/PropertiesView.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 4 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 6 +- src/client/views/nodes/FieldView.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- src/client/views/nodes/scrapbook/ScrapbookBox.tsx | 81 +++++++++++++++------- 6 files changed, 64 insertions(+), 33 deletions(-) (limited to 'src/client/views/nodes/scrapbook') diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index e7186c0e3..acf6f928a 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -161,7 +161,7 @@ export class PropertiesView extends ObservableReactComponent (!this.selectedLayoutDoc ? 0 : Math.min(NumCast(this.selectedLayoutDoc?._width), this._props.width - 20)); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 9a0fda3f8..e79d0a76d 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -58,7 +58,7 @@ export interface CollectionViewProps extends React.PropsWithChildren number; childContextMenuItems?: () => { script: ScriptField; label: string }[]; childLayoutTemplate?: () => Doc | undefined; // specify a layout Doc template to use for children of the collection - childRejectDrop?: (draggedDoc: Doc[] | undefined, subView?: DocumentView) => boolean; // whether a child document can be dropped on this document + childRejectDrop?: (de: DragManager.DropEvent, subView?: DocumentView) => boolean; // whether a child document can be dropped on this document childHideDecorationTitle?: boolean; childHideResizeHandles?: boolean; childHideDecorations?: boolean; @@ -324,7 +324,7 @@ export function CollectionSubView() { protected onInternalDrop(e: Event, de: DragManager.DropEvent): boolean { const { docDragData } = de.complete; - if (docDragData && !docDragData.draggedDocuments.includes(this.Document) && !this._props.rejectDrop?.(docDragData.draggedDocuments, this.DocumentView?.())) { + if (docDragData && !docDragData.draggedDocuments.includes(this.Document) && !this._props.rejectDrop?.(de, this.DocumentView?.())) { let added; const dropAction = docDragData.dropAction || docDragData.userDropAction; const targetDocments = DocListCast(this.dataDoc[this._props.fieldKey]); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 08126d4fe..c4971c204 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -256,8 +256,8 @@ export class CollectionFreeFormView extends CollectionSubView { const { x, y, r, b } = aggregateBounds( this._layoutElements.filter(e => e.bounds?.width && !e.bounds.z).map(e => e.bounds!), - NumCast(this.layoutDoc._xPadding, this._props.xPadding ?? 0), - NumCast(this.layoutDoc._yPadding, this._props.yPadding ?? 0) + NumCast(this.layoutDoc._xPadding, NumCast(this.layoutDoc._xMargin, this._props.xPadding ?? 0)), + NumCast(this.layoutDoc._yPadding, NumCast(this.layoutDoc._yMargin, this._props.yPadding ?? 0)) ); const [width, height] = [r - x, b - y]; return { @@ -496,7 +496,7 @@ export class CollectionFreeFormView extends CollectionSubView { - if (this._props.rejectDrop?.(de.complete.docDragData?.draggedDocuments, this._props.DocumentView?.())) return false; + if (this._props.rejectDrop?.(de, this._props.DocumentView?.())) return false; if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de, de.complete.annoDragData); if (de.complete.linkDragData) return this.internalLinkDrop(e, de, de.complete.linkDragData); if (de.complete.docDragData?.droppedDocuments.length) return this.internalDocDrop(e, de, de.complete.docDragData); diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index b4473d9dc..34e3a5d76 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -68,7 +68,7 @@ export interface FieldViewSharedProps { isGroupActive?: () => string | undefined; // is this document part of a group that is active // eslint-disable-next-line no-use-before-define setContentViewBox?: (view: ViewBoxInterface) => void; // called by rendered field's viewBox so that DocumentView can make direct calls to the viewBox - rejectDrop?: (draggedDoc: Doc[] | undefined, subView?: DocumentView) => boolean; // whether a document drop is rejected + rejectDrop?: (de: DragManager.DropEvent, subView?: DocumentView) => boolean; // whether a document drop is rejected PanelWidth: () => number; PanelHeight: () => number; isDocumentActive?: () => boolean | undefined; // whether a document should handle pointer events diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index dc23a695d..9897a0062 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -586,7 +586,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent() { @observable createdDate: string; - private _dropDisposer?: DragManager.DragDropDisposer; constructor(props: FieldViewProps) { super(props); @@ -45,6 +46,28 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent() const title = `Scrapbook - ${this.createdDate}`; if (this.dataDoc.title !== title) { this.dataDoc.title = title; + + const image = Docs.Create.TextDocument('image'); + image.accepts_docType = DocumentType.IMG; + const placeholder = new Doc(); + placeholder.proto = image; + placeholder.original = image; + placeholder.height = 200; + placeholder.x = 0; + placeholder.y = -100; + //placeholder.overrideFields = new List(['x', 'y']); // shouldn't need to do this for layout fields since the placeholder already overrides its protos + + const summary = Docs.Create.TextDocument('summary'); + summary.accepts_docType = DocumentType.RTF; + summary.accepts_textType = 'one line'; + const placeholder2 = new Doc(); + placeholder2.proto = summary; + placeholder2.original = summary; + placeholder2.x = 0; + placeholder2.y = 200; + placeholder2._width = 250; + //placeholder2.overrideFields = new List(['x', 'y', '_width']); // shouldn't need to do this for layout fields since the placeholder already overrides its protos + this.dataDoc[this.fieldKey] = new List([placeholder, placeholder2]); } } @@ -52,43 +75,49 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent() this.setTitle(); } - childRejectDrop = (draggedDoc: Doc[] | undefined, subView?: DocumentView) => { - if (draggedDoc?.length === 1 && subView) { - if (subView.Document.type === DocumentType.IMG && draggedDoc[0].$type !== DocumentType.IMG) { - return true; - } - } - return false; + childRejectDrop = (de: DragManager.DropEvent, subView?: DocumentView) => { + return true; // disable dropping documents onto any child of the scrapbook. }; - rejectDrop = (draggedDoc: Doc[] | undefined /* , subView?: DocumentView */) => { - if (draggedDoc?.length === 1 && draggedDoc[0].$type !== DocumentType.IMG) { - return true; - } - return false; - }; - onInternalDrop = (e: Event, de: DragManager.DropEvent) => { - if (de.complete.docDragData?.draggedDocuments[0]?.$type === DocumentType.IMG) { - return true; - } - return false; + rejectDrop = (de: DragManager.DropEvent, subView?: DocumentView) => { + // Test to see if the dropped doc is dropped on an acceptable location (anywerhe? on a specific box). + // const draggedDocs = de.complete.docDragData?.draggedDocuments; + return false; // allow all Docs to be dropped onto scrapbook -- let filterAddDocument make the final decision. }; - protected createDashEventsTarget = (ele: HTMLDivElement | null) => { - this._dropDisposer?.(); - if (ele) { - this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc); + filterAddDocument = (docIn: Doc | Doc[]) => { + const docs = toList(docIn); + if (docs?.length === 1) { + const placeholder = DocListCast(this.dataDoc[this.fieldKey]).find(d => + (d.accepts_docType === docs[0].$type || // match fields based on type, or by analyzing content .. simple example of matching text in placeholder to dropped doc's type + RTFCast(d[Doc.LayoutDataKey(d)])?.Text.includes(StrCast(docs[0].$type))) + ); // prettier-ignore + + if (placeholder) { + // ugh. we have to tell the underlying view not to add the Doc so that we can add it where we want it. + // However, returning 'false' triggers an undo. so this settimeout is needed to make the assignment happen after the undo. + setTimeout( + undoable(() => { + //StrListCast(placeholder.overrideFields).map(field => (docs[0][field] = placeholder[field])); // // shouldn't need to do this for layout fields since the placeholder already overrides its protos + placeholder.proto = docs[0]; + }, 'Scrapbook add') + ); + return false; + } } + return false; }; render() { return ( -
r && this.createDashEventsTarget(r)}> +
+ {/*
Drop an image here
*/}
); } @@ -102,9 +131,11 @@ Docs.Prototypes.TemplateMap.set(DocumentType.SCRAPBOOK, { _height: 200, _xMargin: 10, _yMargin: 10, + _layout_fitWidth: false, _layout_autoHeight: true, _layout_reflowVertical: true, _layout_reflowHorizontal: true, + _freeform_fitContentsToBox: true, defaultDoubleClick: 'ignore', systemIcon: 'BsImages', }, -- cgit v1.2.3-70-g09d2 From e969c6c4abe08d7f46d51d5511a04a5500a76d3e Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 23 Apr 2025 14:39:29 -0400 Subject: fixed how pdf worker is copied and accessed. --- package-lock.json | 16 +++++++++++++++- src/client/views/nodes/scrapbook/ScrapbookBox.tsx | 3 ++- src/client/views/pdf/PDFViewer.tsx | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src/client/views/nodes/scrapbook') diff --git a/package-lock.json b/package-lock.json index 990f03462..b4c008ffd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -95,7 +95,6 @@ "cookie-parser": "^1.4.6", "cookie-session": "^2.0.0", "copy-webpack-plugin": "^13.0.0", - "copyfiles": "^2.4.1", "core-js": "^3.33.3", "cors": "^2.8.5", "css-loader": "^7.1.2", @@ -333,6 +332,7 @@ "@types/webscopeio__react-textarea-autocomplete": "^4.7.5", "@types/youtube": "^0.1.0", "chai": "^5.0.0", + "copyfiles": "^2.4.1", "cross-env": "^7.0.3", "eslint": "^9.12.0", "eslint-plugin-react": "^7.37.1", @@ -18747,6 +18747,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.4.1.tgz", "integrity": "sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==", + "dev": true, "license": "MIT", "dependencies": { "glob": "^7.0.5", @@ -18767,6 +18768,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -27705,6 +27707,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" @@ -28566,6 +28569,7 @@ "version": "0.0.0", "resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz", "integrity": "sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==", + "dev": true, "license": "ISC", "dependencies": { "inherits": "^2.0.1", @@ -28576,12 +28580,14 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true, "license": "MIT" }, "node_modules/noms/node_modules/readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "dev": true, "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", @@ -28594,6 +28600,7 @@ "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "dev": true, "license": "MIT" }, "node_modules/normalize-path": { @@ -37286,6 +37293,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, "license": "MIT", "dependencies": { "readable-stream": "~2.3.6", @@ -37296,12 +37304,14 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, "license": "MIT" }, "node_modules/through2/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", @@ -37317,12 +37327,14 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, "license": "MIT" }, "node_modules/through2/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" @@ -38769,6 +38781,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -40229,6 +40242,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.4" diff --git a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx index 6ee9f39ab..b241b27d7 100644 --- a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx +++ b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx @@ -52,7 +52,8 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent() const placeholder = new Doc(); placeholder.proto = image; placeholder.original = image; - placeholder.height = 200; + placeholder._width = 250; + placeholder._height = 200; placeholder.x = 0; placeholder.y = -100; //placeholder.overrideFields = new List(['x', 'y']); // shouldn't need to do this for layout fields since the placeholder already overrides its protos diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 21d987587..041fc0de7 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -31,7 +31,7 @@ import { Annotation } from './Annotation'; import { GPTPopup } from './GPTPopup/GPTPopup'; import './PDFViewer.scss'; import { DocumentViewProps } from '../nodes/DocumentContentsView'; -if (window?.Worker) GlobalWorkerOptions.workerSrc = 'files/pdf.worker.min.mjs'; +if (window?.Worker) GlobalWorkerOptions.workerSrc = 'files/node_modules/pdfjs-dist/build/pdf.worker.min.mjs'; // npm start/etc use copyfiles to copy the worker from the pdfjs-dist package to the public folder export * from 'pdfjs-dist/build/pdf.mjs'; interface IViewerProps extends FieldViewProps { -- cgit v1.2.3-70-g09d2 From 9a46e81d662e59413a076b2e0041d1455bc15294 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 23 Apr 2025 20:38:48 -0400 Subject: from last --- .../views/nodes/scrapbook/ScrapbookVersionTwo.tsx | 125 --------------------- src/server/ApiManagers/FireflyManager.ts | 2 +- 2 files changed, 1 insertion(+), 126 deletions(-) delete mode 100644 src/client/views/nodes/scrapbook/ScrapbookVersionTwo.tsx (limited to 'src/client/views/nodes/scrapbook') diff --git a/src/client/views/nodes/scrapbook/ScrapbookVersionTwo.tsx b/src/client/views/nodes/scrapbook/ScrapbookVersionTwo.tsx deleted file mode 100644 index d15d2fe56..000000000 --- a/src/client/views/nodes/scrapbook/ScrapbookVersionTwo.tsx +++ /dev/null @@ -1,125 +0,0 @@ -//IGNORE FOR NOW, CURRENTLY NOT USED IN SCRAPBOOK IMPLEMENTATION -import { action, makeObservable, observable } from 'mobx'; -import * as React from 'react'; -import { RichTextField } from '../../../../fields/RichTextField'; -import { Docs } from '../../../documents/Documents'; -import { DocumentType } from '../../../documents/DocumentTypes'; -import { ViewBoxAnnotatableComponent } from '../../DocComponent'; -import { FieldView, FieldViewProps } from '../FieldView'; -import { FormattedTextBox, FormattedTextBoxProps } from '../formattedText/FormattedTextBox'; - -export class ScrapbookVersionTwo extends ViewBoxAnnotatableComponent() { - @observable scrapbookDate: string; - - public static LayoutString(fieldStr: string) { - return FieldView.LayoutString(ScrapbookVersionTwo, fieldStr); - } - - constructor(props: FormattedTextBoxProps) { - super(props); - makeObservable(this); - this.scrapbookDate = this.getFormattedDate(); - - console.log('Constructor: Setting initial title and text...'); - this.setDailyTitle(); - this.setDailyText(); - } - - 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.scrapbookDate) { - console.log('Updating title to:', this.scrapbookDate); - this.dataDoc.title = this.scrapbookDate; - } - - console.log('New title after update:', this.dataDoc.title); - } - - @action - setDailyText() { - console.log('setDailyText() called...'); - const placeholderText = 'Start writing here...'; - const initialText = `Scrapbook - $\n${placeholderText}`; - - console.log('Checking if dataDoc has text field...'); - - const styles = { - bold: true, // Make the journal date bold - color: 'red', // Set the journal date color to blue - fontSize: 12, // Set the font size to 18px for the whole text - display: 'grid', - gridTemplateColumns: 'repeat(auto-fill, minmax(100px, 1fr))', - gap: '8px', - padding: '10px', - background: '#fafafa', - width: '100%', - height: '100%', - }; - - console.log('Setting new text field with:', initialText); - this.dataDoc[this.fieldKey] = RichTextField.textToRtf( - initialText, - undefined, // No image DocId - styles, // Pass the styles object here - placeholderText.length // The position for text selection - ); - - console.log('Current text field:', this.dataDoc[this.fieldKey]); - } - - componentDidMount(): void { - console.log('componentDidMount() triggered...'); - // bcz: This should be moved into Docs.Create.DailyJournalDocument() - // otherwise, it will override all the text whenever the note is reloaded - this.setDailyTitle(); - this.setDailyText(); - } - - render() { - return ( -
- -
- ); - } -} - -Docs.Prototypes.TemplateMap.set(DocumentType.SCRAPBOOK, { - layout: { view: ScrapbookVersionTwo, dataField: 'text' }, - options: { - acl: '', - _height: 35, - _xMargin: 10, - _yMargin: 10, - _layout_autoHeight: true, - _layout_nativeDimEditable: true, - _layout_reflowVertical: true, - _layout_reflowHorizontal: true, - defaultDoubleClick: 'ignore', - systemIcon: 'BsFileEarmarkTextFill', - }, -}); \ No newline at end of file diff --git a/src/server/ApiManagers/FireflyManager.ts b/src/server/ApiManagers/FireflyManager.ts index fd61f6c9e..0b19f66e0 100644 --- a/src/server/ApiManagers/FireflyManager.ts +++ b/src/server/ApiManagers/FireflyManager.ts @@ -6,9 +6,9 @@ import * as path from 'path'; import { DashUserModel } from '../authentication/DashUserModel'; import { DashUploadUtils } from '../DashUploadUtils'; import { _error, _invalid, _success, Method } from '../RouteManager'; +import { Upload } from '../SharedMediaTypes'; import { Directory, filesDirectory } from '../SocketData'; import ApiManager, { Registration } from './ApiManager'; -import { Upload } from '../SharedMediaTypes'; export default class FireflyManager extends ApiManager { getBearerToken = () => -- cgit v1.2.3-70-g09d2 From 78ac87b8acf63079071e5e8805692ed8c30042ce Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 23 Apr 2025 22:02:36 -0400 Subject: lots of typechecking fixes. --- .../apis/google_docs/GooglePhotosClientUtils.ts | 2 +- src/client/util/CalendarManager.tsx | 2 +- src/client/util/DocumentManager.ts | 8 +++--- src/client/util/LinkManager.ts | 3 +- src/client/util/ReplayMovements.ts | 6 ++-- src/client/util/ScriptManager.ts | 9 ++---- src/client/util/SearchUtil.ts | 5 ++-- .../util/reportManager/ReportManagerComponents.tsx | 4 +-- src/client/views/DashboardView.tsx | 28 +++++++++---------- src/client/views/InkStrokeProperties.ts | 8 +++--- src/client/views/InkingStroke.tsx | 12 ++++---- src/client/views/PropertiesButtons.tsx | 23 ++++++++-------- .../views/PropertiesDocBacklinksSelector.tsx | 8 ++---- src/client/views/PropertiesDocContextSelector.tsx | 4 +-- src/client/views/UndoStack.tsx | 5 +--- src/client/views/animationtimeline/Region.tsx | 32 ++++++++++------------ src/client/views/animationtimeline/Track.tsx | 24 ++++++++-------- src/client/views/collections/CollectionMenu.tsx | 4 +-- .../collections/CollectionNoteTakingViewColumn.tsx | 2 +- .../views/collections/CollectionPileView.tsx | 1 - .../collections/CollectionStackedTimeline.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 8 +++--- .../views/collections/FlashcardPracticeUI.tsx | 2 +- src/client/views/collections/TreeView.tsx | 4 +-- .../CollectionFreeFormLayoutEngines.tsx | 2 +- .../collectionFreeForm/FaceCollectionBox.tsx | 13 +++++---- .../collectionSchema/SchemaColumnHeader.tsx | 2 +- .../collectionSchema/SchemaTableCell.tsx | 18 ++++++------ src/client/views/linking/LinkMenuGroup.tsx | 5 ++-- src/client/views/linking/LinkMenuItem.tsx | 4 +-- .../views/newlightbox/ExploreView/ExploreView.tsx | 4 +-- src/client/views/newlightbox/NewLightboxView.tsx | 7 ++--- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 16 +++++------ .../views/nodes/DataVizBox/SchemaCSVPopUp.tsx | 6 ++-- .../nodes/DataVizBox/components/Histogram.tsx | 17 ++++++------ .../nodes/DataVizBox/components/LineChart.tsx | 25 +++++++++++------ .../views/nodes/DataVizBox/components/TableBox.tsx | 2 +- src/client/views/nodes/EquationBox.tsx | 1 - src/client/views/nodes/FieldView.tsx | 7 +++-- src/client/views/nodes/FunctionPlotBox.tsx | 11 ++++---- src/client/views/nodes/ImageBox.tsx | 2 +- .../views/nodes/MapBox/DirectionsAnchorMenu.tsx | 2 +- src/client/views/nodes/calendarBox/CalendarBox.tsx | 3 +- .../nodes/chatbot/chatboxcomponents/ChatBox.tsx | 20 ++++++++------ .../views/nodes/chatbot/tools/GetDocsTool.ts | 5 +++- .../views/nodes/chatbot/vectorstore/Vectorstore.ts | 15 +++++----- .../views/nodes/formattedText/DailyJournal.tsx | 2 +- src/client/views/nodes/scrapbook/ScrapbookBox.tsx | 2 +- src/client/views/pdf/Annotation.tsx | 7 +++-- src/client/views/search/FaceRecognitionHandler.tsx | 6 ++-- src/fields/Doc.ts | 2 +- src/fields/Types.ts | 2 ++ 52 files changed, 207 insertions(+), 207 deletions(-) (limited to 'src/client/views/nodes/scrapbook') diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts index 4b86a8341..15fd6313a 100644 --- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts +++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts @@ -311,7 +311,7 @@ export namespace GooglePhotos { sources .filter(source => ImageCast(Doc.GetProto(source).data)) .forEach(async source => { - const data = ImageCast(Doc.GetProto(source).data); + const data = ImageCast(Doc.GetProto(source).data)!; const url = data.url.href; const target = Doc.MakeEmbedding(source); const description = parseDescription(target, descriptionKey); diff --git a/src/client/util/CalendarManager.tsx b/src/client/util/CalendarManager.tsx index 4e321a893..b50e39c02 100644 --- a/src/client/util/CalendarManager.tsx +++ b/src/client/util/CalendarManager.tsx @@ -162,7 +162,7 @@ export class CalendarManager extends ObservableReactComponent { console.log('my calendars: ', Doc.MyCalendars); if (this.creationType === 'new-calendar') { - Doc.AddDocToList(Doc.MyCalendars, 'data', calendar); // add to new calendar to dashboard calendars + Doc.MyCalendars && Doc.AddDocToList(Doc.MyCalendars, 'data', calendar); // add to new calendar to dashboard calendars } } }; diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index ad57c2a62..3bae2881e 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -173,10 +173,10 @@ export class DocumentManager { while ( containerDocContext.length && DocCast(containerDocContext[0]?.embedContainer) && - DocCast(containerDocContext[0].embedContainer)?._type_collection !== CollectionViewType.Docking && + DocCast(containerDocContext[0].embedContainer)!._type_collection !== CollectionViewType.Docking && (includeExistingViews || !DocumentManager.Instance.getDocumentView(containerDocContext[0])) ) { - containerDocContext = [Cast(containerDocContext[0].embedContainer, Doc, null), ...containerDocContext]; + containerDocContext = [DocCast(containerDocContext[0].embedContainer)!, ...containerDocContext]; } return containerDocContext; } @@ -248,7 +248,7 @@ export class DocumentManager { finished?: (changed: boolean) => void // func called after focusing on target with flag indicating whether anything needed to be done. ) => { const options = optionsIn; - Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, targetDoc); + Doc.MyRecentlyClosed && Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, targetDoc); const docContextPath = DocumentManager.GetContextPath(targetDoc, true); if (docContextPath.some(doc => doc.hidden)) options.toggleTarget = false; let activatedTab = false; @@ -272,7 +272,7 @@ export class DocumentManager { })); if (options.openLocation?.includes(OpenWhere.lightbox)) { // even if we found the document view, if the target is a lightbox, we try to open it in the lightbox to preserve lightbox semantics (eg, there's only one active doc in the lightbox) - const target = DocCast(targetDoc.annotationOn, targetDoc); + const target = DocCast(targetDoc.annotationOn, targetDoc)!; const compView = this.getDocumentView(DocCast(target.embedContainer))?.ComponentView; if ((compView?.addDocTab ?? compView?._props.addDocTab)?.(target, options.openLocation)) { await new Promise(waitres => { diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 344e2e4c0..d8e0c4cbe 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -217,7 +217,8 @@ export class LinkManager { } // finds the opposite anchor of a given anchor in a link - public static getOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc | undefined { + public static getOppositeAnchor(linkDoc: Doc | undefined, anchor: Doc | undefined): Doc | undefined { + if (!linkDoc || !anchor) return undefined; const id = LinkManager.anchorIndex(linkDoc, anchor); const a1 = DocCast(linkDoc.link_anchor_1); const a2 = DocCast(linkDoc.link_anchor_2); diff --git a/src/client/util/ReplayMovements.ts b/src/client/util/ReplayMovements.ts index 62a09a8bc..4f0423342 100644 --- a/src/client/util/ReplayMovements.ts +++ b/src/client/util/ReplayMovements.ts @@ -108,9 +108,11 @@ export class ReplayMovements { movements.forEach((movement, i) => { if (typeof movement.doc === 'string') { - movements[i].doc = IdToDoc(movement.doc); - if (!movements[i].doc) { + const doc = IdToDoc(movement.doc); + if (!doc) { console.log('ERROR: tracked doc not found'); + } else { + movements[i].doc = doc; } } }); diff --git a/src/client/util/ScriptManager.ts b/src/client/util/ScriptManager.ts index 9158f6c0b..8c7f88bf6 100644 --- a/src/client/util/ScriptManager.ts +++ b/src/client/util/ScriptManager.ts @@ -1,7 +1,6 @@ -import { Doc, DocListCast } from '../../fields/Doc'; +import { Doc, DocListCast, StrListCast } from '../../fields/Doc'; import { List } from '../../fields/List'; -import { listSpec } from '../../fields/Schema'; -import { Cast, StrCast } from '../../fields/Types'; +import { StrCast } from '../../fields/Types'; import { Docs } from '../documents/Documents'; import { ScriptingGlobals } from './ScriptingGlobals'; @@ -10,7 +9,6 @@ export class ScriptManager { // eslint-disable-next-line no-use-before-define private static _instance: ScriptManager; public static get Instance(): ScriptManager { - // eslint-disable-next-line no-return-assign return this._instance || (this._instance = new this()); } private constructor() { @@ -58,7 +56,7 @@ export class ScriptManager { public static addScriptToGlobals(scriptDoc: Doc): void { ScriptingGlobals.removeGlobal(StrCast(scriptDoc.name)); - const params = Cast(scriptDoc['data-params'], listSpec('string'), []); + const params = StrListCast(scriptDoc['data-params']); const paramNames = params.reduce((o: string, p: string) => { let out = o; if (params.indexOf(p) === params.length - 1) { @@ -69,7 +67,6 @@ export class ScriptManager { return out; }, '' as string); - // eslint-disable-next-line no-new-func const f = new Function(paramNames, StrCast(scriptDoc.script)); Object.defineProperty(f, 'name', { value: StrCast(scriptDoc.name), writable: false }); diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index e4adcaa7e..fc3bb99ab 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -13,7 +13,7 @@ export namespace SearchUtil { const blockedKeys = matchKeyNames ? [] : Object.entries(DocOptions) - .filter(([, info]: [string, FInfo]) => !info?.searchable()) + .filter(([, info]: [string, FieldType | FInfo | undefined]) => (info instanceof FInfo ? !info.searchable() : true)) .map(([key]) => key); const exact = queryIn.startsWith('='); @@ -22,8 +22,7 @@ export namespace SearchUtil { const results = new ObservableMap(); if (collectionDoc) { const docs = DocListCast(collectionDoc[Doc.LayoutDataKey(collectionDoc)]); - // eslint-disable-next-line @typescript-eslint/ban-types - const docIDs: String[] = []; + const docIDs: string[] = []; SearchUtil.foreachRecursiveDoc(docs, (depth: number, doc: Doc) => { const dtype = StrCast(doc.type) as DocumentType; if (dtype && !blockedTypes.includes(dtype) && !docIDs.includes(doc[Id]) && depth >= 0) { diff --git a/src/client/util/reportManager/ReportManagerComponents.tsx b/src/client/util/reportManager/ReportManagerComponents.tsx index 92f877859..80653779e 100644 --- a/src/client/util/reportManager/ReportManagerComponents.tsx +++ b/src/client/util/reportManager/ReportManagerComponents.tsx @@ -1,5 +1,3 @@ -/* eslint-disable react/require-default-props */ -/* eslint-disable prefer-destructuring */ /* eslint-disable no-use-before-define */ import * as React from 'react'; import ReactMarkdown from 'react-markdown'; @@ -299,7 +297,7 @@ export function IssueView({ issue }: IssueViewProps) { )} - + {issueBody} diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index f61f6db18..3ceb23ffd 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -113,12 +113,12 @@ export class DashboardView extends ObservableReactComponent { getDashboards = (whichGroup: DashboardGroup) => { if (whichGroup === DashboardGroup.MyDashboards) { - return DocListCast(Doc.MyDashboards.data).filter(dashboard => dashboard.$author === ClientUtils.CurrentUserEmail()); + return DocListCast(Doc.MyDashboards?.data).filter(dashboard => dashboard.$author === ClientUtils.CurrentUserEmail()); } - return DocListCast(Doc.MySharedDocs.data_dashboards).filter(doc => doc.dockingConfig); + return DocListCast(Doc.MySharedDocs?.data_dashboards).filter(doc => doc.dockingConfig); }; - isUnviewedSharedDashboard = (dashboard: Doc) => !DocListCast(Doc.MySharedDocs.viewed).includes(dashboard); + isUnviewedSharedDashboard = (dashboard: Doc) => !DocListCast(Doc.MySharedDocs?.viewed).includes(dashboard); @undoBatch createNewDashboard = (name: string, background?: string) => { @@ -155,7 +155,7 @@ export class DashboardView extends ObservableReactComponent { @action openNewDashboardModal = () => { this.openModal = true; - this.setNewDashboardName(`Dashboard ${DocListCast(Doc.MyDashboards.data).length + 1}`); + this.setNewDashboardName(`Dashboard ${DocListCast(Doc.MyDashboards?.data).length + 1}`); }; _downX: number = 0; @@ -191,7 +191,7 @@ export class DashboardView extends ObservableReactComponent {