aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/scrapbook/ScrapbookBox.tsx
diff options
context:
space:
mode:
authorsharkiecodes <lanyi_stroud@brown.edu>2025-05-01 00:44:14 -0400
committersharkiecodes <lanyi_stroud@brown.edu>2025-05-01 00:44:14 -0400
commitfec7f7dd736af3296a2df52acd07f3eadb8123c3 (patch)
tree31bfce10179ea90f71eaae5e0dc3688dd957c97d /src/client/views/nodes/scrapbook/ScrapbookBox.tsx
parent37cdff4fb2383953f39cb0fee384a4779cd9fa7b (diff)
marquee selection
Diffstat (limited to 'src/client/views/nodes/scrapbook/ScrapbookBox.tsx')
-rw-r--r--src/client/views/nodes/scrapbook/ScrapbookBox.tsx231
1 files changed, 230 insertions, 1 deletions
diff --git a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx
index 33761efc9..731715964 100644
--- a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx
+++ b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx
@@ -12,21 +12,36 @@ import { FieldView, FieldViewProps } from '../FieldView';
import { DragManager } from '../../../util/DragManager';
import { RTFCast, StrCast, toList } from '../../../../fields/Types';
import { undoable } from '../../../util/UndoManager';
+import { ScrapbookItemConfig, ScrapbookPreset } from './ScrapbookPreset';
+
+enum ScrapbookPresetType {
+ Classic = 'Classic',
+ Default = 'Default',
+ Collage = 'Collage',
+ Spotlight = 'Spotlight',
+}
+
// Scrapbook view: a container that lays out its child items in a grid/template
export class ScrapbookBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@observable createdDate: string;
+ @observable configs : ScrapbookItemConfig[]
constructor(props: FieldViewProps) {
super(props);
makeObservable(this);
this.createdDate = this.getFormattedDate();
+ this.configs =
+ ScrapbookPreset.createPreset(presetType);
+
// 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.initScrapbook(ScrapbookPresetType.Default);
this.setTitle();
+ //this.setLayout(ScrapbookPreset.Spotlight);
}
public static LayoutString(fieldStr: string) {
@@ -41,6 +56,188 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
});
}
+
+ @action
+ initScrapbook(presetType: ScrapbookPresetType) {
+ // 1) ensure title is set
+ const title = `Scrapbook - ${this.createdDate}`;
+ if (this.dataDoc.title !== title) {
+ this.dataDoc.title = title;
+ }
+
+ // 2) build placeholders from the preset
+ const configs = ScrapbookPreset.createPreset(presetType);
+ const placeholders: Doc[] = [];
+
+ for (const cfg of configs) {
+ if (cfg.children) {
+ // --- nested container ---
+ const childDocs = cfg.children.map(child => {
+ const doc = Docs.Create.TextDocument(child.tag);
+ doc.accepts_docType = child.type;
+ doc.accepts_tagType = child.acceptTag ?? child.tag;
+
+ const ph = new Doc();
+ ph.proto = doc;
+ ph.original = doc;
+ ph.x = child.x;
+ ph.y = child.y;
+ if (child.width != null) ph._width = child.width;
+ if (child.height != null) ph._height = child.height;
+ return ph;
+ });
+
+ const protoW = cfg.containerWidth ?? cfg.width;
+ const protoH = cfg.containerHeight ?? cfg.height;
+ const containerProto = Docs.Create.StackingDocument(
+ childDocs,
+ {
+ ...(protoW != null ? { _width: protoW } : {}),
+ ...(protoH != null ? { _height: protoH } : {}),
+ title: cfg.tag
+ }
+ );
+
+ const ph = new Doc();
+ ph.proto = containerProto;
+ ph.original = containerProto;
+ ph.x = cfg.x;
+ ph.y = cfg.y;
+ if (cfg.width != null) ph._width = cfg.width;
+ if (cfg.height != null) ph._height = cfg.height;
+ placeholders.push(ph);
+
+ } else {
+ // --- flat placeholder ---
+ const doc = Docs.Create.TextDocument(cfg.tag);
+ doc.accepts_docType = cfg.type;
+ doc.accepts_tagType = cfg.acceptTag ?? cfg.tag;
+
+ const ph = new Doc();
+ ph.proto = doc;
+ ph.original = doc;
+ ph.x = cfg.x;
+ ph.y = cfg.y;
+ if (cfg.width != null) ph._width = cfg.width;
+ if (cfg.height != null) ph._height = cfg.height;
+ placeholders.push(ph);
+ }
+ }
+
+ // 3) commit them into the field
+ this.dataDoc[this.fieldKey] = new List<Doc>(placeholders);
+ }
+ @action
+ //INACTIVE VER ignore!! not in use rn, implementation ver 1
+ setLayout(preset: ScrapbookPreset) {
+ // helper to wrap a TextDocument proto in a Doc with positioning
+ function makePlaceholder(
+ proto: Doc, x: number, y: number,
+ width: number, height: number
+ ): Doc {
+ const d = new Doc();
+ d.proto = proto;
+ d.original = proto;
+ d.x = x;
+ d.y = y;
+ d._width = width;
+ d._height = height;
+ return d;
+ }
+
+ let placeholders: Doc[];
+
+ switch (preset) {
+ case ScrapbookPresetType.Classic:
+ // One large landscape image on top, caption below, sidebar at right
+ const imgClassic = Docs.Create.TextDocument('image');
+ imgClassic.accepts_docType = DocumentType.IMG;
+ imgClassic.accepts_tagType = 'LANDSCAPE';
+ const phImageClassic = makePlaceholder(imgClassic, 0, -120, 300, 180);
+
+ const captionClassic = Docs.Create.TextDocument('caption');
+ captionClassic.accepts_docType = DocumentType.RTF;
+ captionClassic.accepts_tagType = 'caption';
+ const phCaptionClassic = makePlaceholder(captionClassic, 0, 80, 300, 60);
+
+ const sidebarClassic = Docs.Create.TextDocument('sidebar');
+ sidebarClassic.accepts_docType = DocumentType.RTF;
+ sidebarClassic.accepts_tagType = 'lengthy description';
+ const phSidebarClassic = makePlaceholder(sidebarClassic, 320, -50, 80, 200);
+
+ placeholders = [phImageClassic, phCaptionClassic, phSidebarClassic];
+ break;
+
+ case ScrapbookPresetType.Collage:
+ // Grid of four person images, small captions under each
+ const personDocs: Doc[] = [];
+ for (let i = 0; i < 4; i++) {
+ const img = Docs.Create.TextDocument(`person ${i+1}`);
+ img.accepts_docType = DocumentType.IMG;
+ img.accepts_tagType = 'PERSON';
+ // position in 2x2 grid
+ const x = (i % 2) * 160 - 80;
+ const y = Math.floor(i / 2) * 160 - 80;
+ personDocs.push(makePlaceholder(img, x, y, 150, 120));
+
+ const cap = Docs.Create.TextDocument(`caption ${i+1}`);
+ cap.accepts_docType = DocumentType.RTF;
+ cap.accepts_tagType = 'caption';
+ personDocs.push(makePlaceholder(cap, x, y + 70, 150, 30));
+ }
+ placeholders = personDocs;
+ break;
+
+ case ScrapbookPresetType.Spotlight:
+ // Full-width title, then a stacking of an internal person image + landscape, then description
+ const titleSpot = Docs.Create.TextDocument('title');
+ titleSpot.accepts_docType = DocumentType.RTF;
+ titleSpot.accepts_tagType = 'title';
+ const phTitleSpot = makePlaceholder(titleSpot, 0, -180, 400, 60);
+
+ const internalImg = Docs.Create.TextDocument('<person>');
+ internalImg.accepts_docType = DocumentType.IMG;
+ internalImg.accepts_tagType = 'PERSON';
+ const phInternal = makePlaceholder(internalImg, -100, -120, 120, 160);
+
+ const landscapeImg = Docs.Create.TextDocument('<landscape>');
+ landscapeImg.accepts_docType = DocumentType.IMG;
+ landscapeImg.accepts_tagType = 'LANDSCAPE';
+ const phLandscape = makePlaceholder(landscapeImg, 50, 0, 200, 160);
+
+ const stack = Docs.Create.StackingDocument(
+ [phInternal, phLandscape],
+ { _width: 360, _height: 180, title: 'spotlight stack' }
+ );
+ const phStack = (() => {
+ const d = new Doc();
+ d.proto = stack;
+ d.original = stack;
+ d.x = 8;
+ d.y = -84;
+ d._width = 360;
+ d._height = 180;
+ return d;
+ })();
+
+ const descSpot = Docs.Create.TextDocument('description');
+ descSpot.accepts_docType = DocumentType.RTF;
+ descSpot.accepts_tagType = 'lengthy description';
+ const phDescSpot = makePlaceholder(descSpot, 0, 140, 400, 100);
+
+ placeholders = [phTitleSpot, phStack, phDescSpot];
+ break;
+
+ default:
+ placeholders = [];
+ }
+
+ // finally assign into the dataDoc
+ this.dataDoc[this.fieldKey] = new List<Doc>(placeholders);
+ }
+
+
+
@action
setTitle() {
const title = `Scrapbook - ${this.createdDate}`;
@@ -120,13 +317,14 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
difference between passing a new List<Doc> versus just the raw array?
*/
- this.dataDoc[this.fieldKey] = new List<Doc>([placeholder, placeholder2, placeholder3, placeholder4]);
+ this.dataDoc[this.fieldKey] = this.dataDoc[this.fieldKey] ?? new List<Doc>([placeholder, placeholder2, placeholder3, placeholder4]);
}
}
componentDidMount() {
+ //this.initScrapbook(ScrapbookPresetType.Default);
this.setTitle();
}
@@ -222,6 +420,37 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
}
}
+
+
+function extractScrapbookConfigs(docs: Doc[]): ScrapbookItemConfig[] {
+ return docs.map(doc => extractConfig(doc));
+}
+
+// function extractConfig(doc: Doc): ScrapbookItemConfig {
+// const layoutKey = Doc.LayoutDataKey(doc);
+// const childDocs = doc[layoutKey] ? DocListCast(doc[layoutKey]) : [];
+
+// const isContainer = childDocs.length > 0;
+
+// const cfg: ScrapbookItemConfig = {
+// type: isContainer ? DocumentType.COL : doc.$type,
+// tag:
+// acceptTag: doc.accepts_tagType,
+// x: doc.x || 0,
+// y: doc.y || 0,
+// width: doc._width,
+// height: doc._height,
+// };
+
+// if (isContainer) {
+// cfg.containerWidth = doc.proto._width;
+// cfg.containerHeight = doc.proto._height;
+// cfg.children = childDocs.map(child => extractConfig(child));
+// }
+
+// return cfg;
+// }
+
// Register scrapbook
Docs.Prototypes.TemplateMap.set(DocumentType.SCRAPBOOK, {
layout: { view: ScrapbookBox, dataField: 'items' },