aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/PropertiesView.tsx2
-rw-r--r--src/client/views/collections/CollectionSubView.tsx4
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx6
-rw-r--r--src/client/views/nodes/FieldView.tsx2
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx2
-rw-r--r--src/client/views/nodes/scrapbook/ScrapbookBox.tsx81
6 files changed, 64 insertions, 33 deletions
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<PropertiesViewProps
CollectionViewType.Card,
CollectionViewType.Carousel,
CollectionViewType.Grid,
- ].includes(this.selectedDoc?.type_collection as CollectionViewType);
+ ].includes(this.selectedDoc?.type_collection as CollectionViewType) || this.selectedDoc.$type === DocumentType.SCRAPBOOK; // prettier-ignore
}
rtfWidth = () => (!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<FieldViewPr
childOpacity?: () => 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<X>() {
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<Partial<collection
override contentBounds = () => {
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<Partial<collection
}, 'link drop');
onInternalDrop = (e: Event, de: DragManager.DropEvent): boolean => {
- 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<FieldViewProps>) => 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<FormattedTextB
return true;
}
const dragData = de.complete.docDragData;
- if (dragData) {
+ if (dragData && !this._props.rejectDrop?.(de, this.DocumentView?.())) {
const layoutProto = DocCast(this.layoutDoc.proto);
const dataDoc = layoutProto && Doc.IsDelegateField(layoutProto, this.fieldKey) ? layoutProto : this.dataDoc;
const effectiveAcl = GetEffectiveAcl(dataDoc);
diff --git a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx
index 24946f4d2..6ee9f39ab 100644
--- a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx
+++ b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx
@@ -1,6 +1,6 @@
import { action, makeObservable, observable } from 'mobx';
import * as React from 'react';
-import { Doc } from '../../../../fields/Doc';
+import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
import { List } from '../../../../fields/List';
import { emptyFunction } from '../../../../Utils';
import { Docs } from '../../../documents/Documents';
@@ -10,10 +10,11 @@ import { ViewBoxAnnotatableComponent } from '../../DocComponent';
import { DocumentView } from '../DocumentView';
import { FieldView, FieldViewProps } from '../FieldView';
import { DragManager } from '../../../util/DragManager';
+import { RTFCast, StrCast, toList } from '../../../../fields/Types';
+import { undoable } from '../../../util/UndoManager';
// Scrapbook view: a container that lays out its child items in a grid/template
export class ScrapbookBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@observable createdDate: string;
- private _dropDisposer?: DragManager.DragDropDisposer;
constructor(props: FieldViewProps) {
super(props);
@@ -45,6 +46,28 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
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<string>(['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<string>(['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<Doc>([placeholder, placeholder2]);
}
}
@@ -52,43 +75,49 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
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 (
- <div style={{ background: 'beige', width: '100%', height: '100%' }} ref={r => r && this.createDashEventsTarget(r)}>
+ <div style={{ background: 'beige', width: '100%', height: '100%' }}>
<CollectionView
{...this._props} //
setContentViewBox={emptyFunction}
rejectDrop={this.rejectDrop}
childRejectDrop={this.childRejectDrop}
+ filterAddDocument={this.filterAddDocument}
/>
+ {/* <div style={{ border: '1px black', borderStyle: 'dotted', position: 'absolute', top: '50%', width: '100%', textAlign: 'center' }}>Drop an image here</div> */}
</div>
);
}
@@ -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',
},