diff options
author | sharkiecodes <lanyi_stroud@brown.edu> | 2025-04-21 19:41:51 -0400 |
---|---|---|
committer | sharkiecodes <lanyi_stroud@brown.edu> | 2025-04-21 19:41:51 -0400 |
commit | 5290e6a69fdadb6037f3d8a03f5ed82e00927520 (patch) | |
tree | 2ab7cb47f242905b14f78653ba74024b9b4b0b5a | |
parent | 17e24e780b54f2f7015c0ca955c3aa5091bba19c (diff) |
attempting to integrate scrapbooks
-rw-r--r-- | src/client/documents/DocumentTypes.ts | 1 | ||||
-rw-r--r-- | src/client/documents/Documents.ts | 44 | ||||
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 3 | ||||
-rw-r--r-- | src/client/views/Main.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/scrapbook/ScrapbookBox.tsx | 106 | ||||
-rw-r--r-- | src/client/views/nodes/scrapbook/ScrapbookContent.tsx | 23 | ||||
-rw-r--r-- | src/client/views/nodes/scrapbook/ScrapbookSlot.tsx | 26 | ||||
-rw-r--r-- | src/client/views/nodes/scrapbook/ScrapbookSlotTypes.ts | 25 |
8 files changed, 230 insertions, 0 deletions
diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index 5c6559836..cef44e999 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -44,6 +44,7 @@ export enum DocumentType { SCRIPTDB = 'scriptdb', // database of scripts GROUPDB = 'groupdb', // database of groups + SCRAPBOOK = 'scrapbook', JOURNAL = 'journal', // AARAV ADD } export enum CollectionViewType { diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index be857da6d..2a2f9d342 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -526,6 +526,16 @@ export class DocumentOptions { ai_firefly_seed?: number; ai_firefly_prompt?: string; + /** + * JSON‐stringified slot configuration for ScrapbookBox + */ + scrapbookConfig?: string; + + /** + * The list of embedded Doc instances in each Scrapbook slot + */ + scrapbookContents?: List<Doc>; + _outpaintingMetadata?: STRt = new StrInfo('serialized JSON metadata needed for image outpainting', false); } @@ -590,6 +600,18 @@ export namespace Docs { }, ], // AARAV ADD // + + [ + DocumentType.SCRAPBOOK, + { + layout: { view: EmptyBox, dataField: 'text' }, + options: { + title: 'Scrapbook', + acl_Guest: SharingPermissions.View, + }, + + }, + ], ]); const suffix = 'Proto'; @@ -922,6 +944,26 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.RTF), field, options, undefined, fieldKey); } + export function ScrapbookDocument( + items: Doc[] = [], + options: DocumentOptions = {}, + fieldKey: string = 'items' + ) { + return InstanceFromProto( + Prototypes.get(DocumentType.SCRAPBOOK), + new List<Doc>(items), + { + title: options.title + ?? new Date().toLocaleDateString(undefined, { + year: 'numeric', month: 'short', day: 'numeric' + }), + ...options, + }, + undefined, + fieldKey + ); + } + // AARAV ADD // export function DailyJournalDocument(text: string | RichTextField, options: DocumentOptions = {}, fieldKey: string = 'text') { @@ -964,6 +1006,8 @@ export namespace Docs { // AARAV ADD // + + export function LinkDocument(source: Doc, target: Doc, options: DocumentOptions = {}, id?: string) { const linkDoc = InstanceFromProto( Prototypes.get(DocumentType.LINK), diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 99a67ebb2..8f4d568ab 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -407,6 +407,8 @@ pie title Minerals in my tap water {key: "DataViz", creator: opts => Docs.Create.DataVizDocument("", opts), opts: { _width: 300, _height: 300, }}, // AARAV ADD // {key: "DailyJournal",creator:opts => Docs.Create.DailyJournalDocument("", opts),opts: { _width: 300, _height: 300, }}, + {key: "Scrapbook",creator:opts => Docs.Create.ScrapbookDocument([], opts),opts:{ _width: 300, _height: 300}}, + //{key: "Scrapbook",creator:opts => Docs.Create.ScrapbookDocument([], opts),opts:{ _width: 300, _height: 300}}, {key: "Chat", creator: Docs.Create.ChatDocument, opts: { _width: 500, _height: 500, _layout_fitWidth: true, }}, {key: "MetaNote", creator: metaNoteTemplate, opts: { _width: 300, _height: 120, _header_pointerEvents: "all", _header_height: 50, _header_fontSize: 9,_layout_autoHeightMargins: 50, _layout_autoHeight: true, treeView_HideUnrendered: true}}, {key: "ViewSlide", creator: slideView, opts: { _width: 400, _height: 300, _xMargin: 3, _yMargin: 3,}}, @@ -449,6 +451,7 @@ pie title Minerals in my tap water { toolTip: "Tap or drag to create a button", title: "Button", icon: "circle", dragFactory: doc.emptyButton as Doc, clickFactory: DocCast(doc.emptyButton)}, { toolTip: "Tap or drag to create a scripting box", title: "Script", icon: "terminal", dragFactory: doc.emptyScript as Doc, clickFactory: DocCast(doc.emptyScript), funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a data viz node", title: "DataViz", icon: "chart-bar", dragFactory: doc.emptyDataViz as Doc, clickFactory: DocCast(doc.emptyDataViz)}, + { toolTip: "Tap or drag to create a scrapbook template", title: "Scrapbook", icon: "palette", dragFactory: doc.emptyScrapbook as Doc,clickFactory:DocCast(doc.emptyScrapbook), }, { toolTip: "Tap or drag to create a journal entry", title: "Journal", icon: "book", dragFactory:doc.emptyDailyJournal as Doc,clickFactory: DocCast(doc.emptyDataJournal), }, { toolTip: "Tap or drag to create a bullet slide", title: "PPT Slide", icon:"person-chalkboard",dragFactory: doc.emptySlide as Doc, clickFactory: DocCast(doc.emptySlide), openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a view slide", title: "View Slide", icon: "address-card", dragFactory: doc.emptyViewSlide as Doc, clickFactory: DocCast(doc.emptyViewSlide), openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}}, diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index e4bbb1c0f..7992ed412 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -53,6 +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 { DashDocCommentView } from './nodes/formattedText/DashDocCommentView'; import { DashDocView } from './nodes/formattedText/DashDocView'; import { DashFieldView } from './nodes/formattedText/DashFieldView'; @@ -120,6 +121,7 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0, message: 'cache' }; FormattedTextBox, DailyJournal, // AARAV ImageBox, + ScrapbookVersionTwo, FontIconBox, LabelBox, EquationBox, 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<FieldViewProps>() { + @observable createdDate: string; + + constructor(props: FieldViewProps) { + super(props); + makeObservable(this); + this.createdDate = this.getFormattedDate(); + + // ensure we always have a List<Doc> in dataDoc['items'] + if (!this.dataDoc[this.fieldKey]) { + this.dataDoc[this.fieldKey] = new List<Doc>(); + } + 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<Doc>(); + } + } + + render() { + // cast into an array even if empty + const items: Doc[] = DocListCast(this.dataDoc[this.fieldKey]); + + return ( + <div style={{ background: 'beige', width: '100%', height: '100%' }}> + + </div> + + // <div + // style={{ + // }} + // > + // {items.length === 0 + // ? <div style={{color:'#888',fontStyle:'italic'}}>Drop docs here</div> + // : items.map((childDoc, idx) => ( + // <DocumentView + // key={String(childDoc.id ?? idx)} + // {...this._props} + // Document={childDoc} + // /> + // )) + // } + // </div> + ); + } +} + + +// 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<ScrapbookContentProps> = 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 ( + <div className="scrapbook-content"> + <h3>{titleText}</h3> + <p>{contentText}</p> + </div> + ); +}); 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 |