From 6f43b2643b117748c6b9896f40b581eeec1ffe06 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 4 Feb 2020 18:30:52 -0500 Subject: small tweaks to templates... --- src/new_fields/Doc.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/new_fields') diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 4dcdc6581..3f2335702 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -481,7 +481,7 @@ export namespace Doc { // if the childDoc is a template for a field, then this will return the expanded layout with its data doc. // otherwise, it just returns the childDoc export function GetLayoutDataDocPair(containerDoc: Doc, containerDataDoc: Opt, childDoc: Doc) { - const resolvedDataDoc = containerDataDoc === containerDoc || !containerDataDoc ? undefined : containerDataDoc; + const resolvedDataDoc = containerDataDoc === containerDoc || !containerDataDoc || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField) ? undefined : containerDataDoc; return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc), data: resolvedDataDoc }; } export function CreateDocumentExtensionForField(doc: Doc, fieldKey: string) { @@ -568,7 +568,7 @@ export namespace Doc { let _applyCount: number = 0; export function ApplyTemplate(templateDoc: Doc) { if (templateDoc) { - const applied = ApplyTemplateTo(templateDoc, Doc.MakeDelegate(new Doc()), "layoutCustom", templateDoc.title + "(..." + _applyCount++ + ")"); + const applied = ApplyTemplateTo(Doc.MakeDelegate(templateDoc), Doc.MakeDelegate(new Doc()), "layout", templateDoc.title + "(..." + _applyCount++ + ")"); applied && (Doc.GetProto(applied).layout = applied.layout); return applied; } -- cgit v1.2.3-70-g09d2 From da92903fb49b2c7d34bb44f11bf72a6cd49b8c0d Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 4 Feb 2020 23:52:40 -0500 Subject: lots of small fixes to templates, presentations, default templates (icon, slide) --- src/client/views/MainView.tsx | 2 +- src/client/views/OverlayView.tsx | 2 +- .../views/collections/CollectionTimeView.tsx | 10 ++++---- .../CollectionMulticolumnView.scss | 1 + .../CollectionMulticolumnView.tsx | 13 ++++++---- .../CollectionMultirowView.scss | 1 + .../CollectionMultirowView.tsx | 12 ++++++---- src/client/views/nodes/DocumentView.tsx | 28 ++++++++++------------ src/client/views/nodes/PresBox.scss | 2 +- src/client/views/nodes/PresBox.tsx | 8 +++++-- .../views/presentationview/PresElementBox.tsx | 2 +- src/new_fields/Doc.ts | 16 +++++++++---- .../authentication/models/current_user_utils.ts | 20 +++++++++++++++- 13 files changed, 78 insertions(+), 39 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 87a81504c..0cc374cee 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,6 +1,6 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { - faArrowDown, faBullseye, faFilter, faArrowUp, faBolt, faCaretUp, faCat, faCheck, faChevronRight, faClone, faCloudUploadAlt, faCommentAlt, faCut, faEllipsisV, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faLongArrowAltRight, + faStickyNote, faArrowDown, faBullseye, faFilter, faArrowUp, faBolt, faCaretUp, faCat, faCheck, faChevronRight, faClone, faCloudUploadAlt, faCommentAlt, faCut, faEllipsisV, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faLongArrowAltRight, faMusic, faObjectGroup, faPause, faMousePointer, faPenNib, faFileAudio, faPen, faEraser, faPlay, faPortrait, faRedoAlt, faThumbtack, faTree, faTv, faUndoAlt, faHighlighter, faMicrophone, faCompressArrowsAlt, faPhone, faStamp, faClipboard } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 295cd7c6e..7a99bf0ae 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -144,7 +144,7 @@ export class OverlayView extends React.Component { return (null); } return CurrentUserUtils.UserDocument.overlays instanceof Doc && DocListCast(CurrentUserUtils.UserDocument.overlays.data).map(d => { - d.inOverlay = true; + setTimeout(() => d.inOverlay = true, 0); let offsetx = 0, offsety = 0; const onPointerMove = action((e: PointerEvent) => { if (e.buttons === 1) { diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index f999067d3..264423d72 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -46,6 +46,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { @computed get _allFacets() { const facets = new Set(); this.childDocs.forEach(child => Object.keys(Doc.GetProto(child)).forEach(key => facets.add(key))); + Doc.AreProtosEqual(this.dataDoc, this.props.Document) && this.childDocs.forEach(child => Object.keys(child).forEach(key => facets.add(key))); return facets.toArray(); } @@ -108,11 +109,10 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { const docItems: ContextMenuProps[] = []; const keySet: Set = new Set(); - this.childLayoutPairs.map(pair => - Array.from(Object.keys(Doc.GetProto(pair.layout))).filter(fieldKey => - pair.layout[fieldKey] instanceof RichTextField || - typeof (pair.layout[fieldKey]) === "number" || - typeof (pair.layout[fieldKey]) === "string").map(fieldKey => keySet.add(fieldKey))); + this.childLayoutPairs.map(pair => this._allFacets.filter(fieldKey => + pair.layout[fieldKey] instanceof RichTextField || + typeof (pair.layout[fieldKey]) === "number" || + typeof (pair.layout[fieldKey]) === "string").map(fieldKey => keySet.add(fieldKey))); keySet.toArray().map(fieldKey => docItems.push({ description: ":" + fieldKey, event: () => this.props.Document.pivotField = fieldKey, icon: "compress-arrows-alt" })); docItems.push({ description: ":(null)", event: () => this.props.Document.pivotField = undefined, icon: "compress-arrows-alt" }) diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss index f57ba438a..a5d5617bc 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss @@ -7,6 +7,7 @@ .document-wrapper { display: flex; flex-direction: column; + width: 100%; .label-wrapper { display: flex; diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index cbe064ec0..56f777f43 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -224,10 +224,11 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu Document={layout} DataDocument={layout.resolvedDataDoc as Doc} CollectionDoc={this.props.Document} - PanelWidth={() => this.lookupPixels(layout)} - PanelHeight={() => PanelHeight() - (BoolCast(Document.showWidthLabels) ? 20 : 0)} - getTransform={() => this.lookupIndividualTransform(layout)} + PanelWidth={() => this.lookupPixels(layout) - 2 * NumCast(Document._xMargin)} + PanelHeight={() => PanelHeight() - 2 * NumCast(Document._yMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0)} + getTransform={() => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin))} onClick={this.onChildClickHandler} + renderDepth={this.props.renderDepth + 1} /> +
{this.contents}
); diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.scss b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.scss index ef4b4a19c..ed737ea59 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.scss +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.scss @@ -8,6 +8,7 @@ .document-wrapper { display: flex; flex-direction: row; + height: 100%; .label-wrapper { display: flex; diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index 434bf14ff..8a2498458 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -224,9 +224,9 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument) Document={layout} DataDocument={layout.resolvedDataDoc as Doc} CollectionDoc={this.props.Document} - PanelHeight={() => this.lookupPixels(layout)} - PanelWidth={() => PanelWidth() - (BoolCast(Document.showHeightLabels) ? 20 : 0)} - getTransform={() => this.lookupIndividualTransform(layout)} + PanelHeight={() => this.lookupPixels(layout) - 2 * NumCast(Document._yMargin)} + PanelWidth={() => PanelWidth() - 2 * NumCast(Document._xMargin) - (BoolCast(Document.showHeightLabels) ? 20 : 0)} + getTransform={() => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin))} onClick={this.onChildClickHandler} renderDepth={this.props.renderDepth + 1} /> @@ -250,7 +250,11 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument) render(): JSX.Element { return ( -
+
{this.contents}
); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index d768dd7cf..c14d11cce 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -111,7 +111,7 @@ export class DocumentView extends DocComponent(Docu @computed get topMost() { return this.props.renderDepth === 0; } @computed get nativeWidth() { return this.layoutDoc._nativeWidth || 0; } @computed get nativeHeight() { return this.layoutDoc._nativeHeight || 0; } - @computed get onClickHandler() { return this.props.onClick ? this.props.onClick : this.Document.onClick; } + @computed get onClickHandler() { return this.props.onClick || this.layoutDoc.onClick || this.Document.onClick; } @computed get onPointerDownHandler() { return this.props.onPointerDown ? this.props.onPointerDown : this.Document.onPointerDown; } @computed get onPointerUpHandler() { return this.props.onPointerUp ? this.props.onPointerUp : this.Document.onPointerUp; } @@ -520,11 +520,8 @@ export class DocumentView extends DocComponent(Docu @undoBatch deleteClicked = (): void => { SelectionManager.DeselectAll(); this.props.removeDocument && this.props.removeDocument(this.props.Document); } - static makeNativeViewClicked = (doc: Doc, prevLayout: string) => { - undoBatch(() => { - if (StrCast(doc.title).endsWith("_" + prevLayout)) doc.title = StrCast(doc.title).replace("_" + prevLayout, ""); - doc.layoutKey = "layout"; - })(); + static makeNativeViewClicked = (doc: Doc) => { + undoBatch(() => Doc.setNativeView(doc))(); } static makeCustomViewClicked = (doc: Doc, dataDoc: Opt, creator: (documents: Array, options: DocumentOptions, id?: string) => Doc, name: string = "custom", docLayoutTemplate?: Doc) => { @@ -653,21 +650,22 @@ export class DocumentView extends DocComponent(Docu @action setCustomView = (custom: boolean, layout: string): void => { - if (this.props.ContainingCollectionView?.props.DataDoc || this.props.ContainingCollectionView?.props.Document.isTemplateDoc) { - Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.ContainingCollectionView.props.Document); - } else if (custom) { - DocumentView.makeNativeViewClicked(this.props.Document, StrCast(this.props.Document.layoutKey).split("_")[1]); - - let foundLayout: Opt = undefined; - DocListCast(Cast(CurrentUserUtils.UserDocument.expandingButtons, Doc, null)?.data)?.map(btnDoc => { + // if (this.props.ContainingCollectionView?.props.DataDoc || this.props.ContainingCollectionView?.props.Document.isTemplateDoc) { + // Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.ContainingCollectionView.props.Document); + // } else + if (custom) { + DocumentView.makeNativeViewClicked(this.props.Document); + + let foundLayout: Opt = Cast(Doc.UserDoc().iconView, Doc, null); + !foundLayout && DocListCast(Cast(CurrentUserUtils.UserDocument.expandingButtons, Doc, null)?.data)?.map(btnDoc => { if (StrCast(Cast(btnDoc?.dragFactory, Doc, null)?.title) === layout) { foundLayout = btnDoc.dragFactory as Doc; } }) DocumentView. - makeCustomViewClicked(this.props.Document, this.props.DataDoc, Docs.Create.StackingDocument, layout, foundLayout && Doc.MakeDelegate(foundLayout)); + makeCustomViewClicked(this.props.Document, this.props.DataDoc, Docs.Create.StackingDocument, layout, foundLayout); } else { - DocumentView.makeNativeViewClicked(this.props.Document, StrCast(this.props.Document.layoutKey).split("_")[1]); + DocumentView.makeNativeViewClicked(this.props.Document); } } diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index 01e7f4834..3e1967a18 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -6,7 +6,7 @@ top: 0; bottom: 0; width: 100%; - min-width: 100px; + min-width: 120px; height: 100%; min-height: 50px; letter-spacing: 2px; diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 06d8e688b..44411fa30 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -6,7 +6,6 @@ import { action, computed, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; import { listSpec } from "../../../new_fields/Schema"; -import { ComputedField } from "../../../new_fields/ScriptField"; import { Cast, FieldValue, NumCast } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { Docs } from "../../documents/Documents"; @@ -17,7 +16,6 @@ import { CollectionView, CollectionViewType } from "../collections/CollectionVie import { ContextMenu } from "../ContextMenu"; import { FieldView, FieldViewProps } from './FieldView'; import "./PresBox.scss"; -import { presSchema } from "../presentationview/PresElementBox"; library.add(faArrowLeft); library.add(faArrowRight); @@ -31,6 +29,7 @@ library.add(faEdit); @observer export class PresBox extends React.Component { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); } + _childReaction: IReactionDisposer | undefined; componentDidMount() { const userDoc = CurrentUserUtils.UserDocument; let presTemp = Cast(userDoc.presentationTemplate, Doc); @@ -43,6 +42,11 @@ export class PresBox extends React.Component { else { this.props.Document.childLayout = presTemp; } + this._childReaction = reaction(() => this.childDocs.slice(), + (children) => children.forEach((child, i) => child.presentationIndex = i), { fireImmediately: true }); + } + componentWillUnmount() { + this._childReaction?.(); } @computed get childDocs() { return DocListCast(this.props.Document[this.props.fieldKey]); } diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index dcc5247d5..ea3acf75c 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -50,7 +50,7 @@ export class PresElementBox extends DocExtendableComponent d instanceof Doc && MakeMetadataFieldTemplate(d, templateDoc)); (Doc.GetProto(templateField)[metadataFieldKey] = ObjectField.MakeCopy(templateField.data)); } - if (templateField.data instanceof RichTextField && templateField.data.Text) { + if (templateField.data instanceof RichTextField && (templateField.data.Text || templateField.data.Data.toString().includes("dashField"))) { templateField._textTemplate = ComputedField.MakeFunction(`copyField(this.${metadataFieldKey})`, { this: Doc.name }); } @@ -780,6 +781,12 @@ export namespace Doc { const fieldStr = Field.toString(fieldVal as Field); return fieldStr === value; } + + export function setNativeView(doc: any) { + const prevLayout = StrCast(doc.layoutKey).split("_")[1]; + if (StrCast(doc.title).endsWith("_" + prevLayout)) doc.title = StrCast(doc.title).replace("_" + prevLayout, ""); + doc.layoutKey = "layout"; + } } Scripting.addGlobal(function renameAlias(doc: any, n: any) { return StrCast(Doc.GetProto(doc).title).replace(/\([0-9]*\)/, "") + `(${n})`; }); @@ -792,6 +799,7 @@ Scripting.addGlobal(function copyField(field: any) { return ObjectField.MakeCopy Scripting.addGlobal(function aliasDocs(field: any) { return new List(field.map((d: any) => Doc.MakeAlias(d))); }); Scripting.addGlobal(function docList(field: any) { return DocListCast(field); }); Scripting.addGlobal(function sameDocs(doc1: any, doc2: any) { return Doc.AreProtosEqual(doc1, doc2); }); +Scripting.addGlobal(function setNativeView(doc: any) { Doc.setNativeView(doc); }); Scripting.addGlobal(function undo() { return UndoManager.Undo(); }); Scripting.addGlobal(function redo() { return UndoManager.Redo(); }); Scripting.addGlobal(function selectDoc(doc: any) { Doc.UserDoc().SelectedDocs = new List([doc]); }); diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 6bfc729de..f2c3aab35 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -15,6 +15,8 @@ import { nullAudio } from "../../../new_fields/URLField"; import { DragManager } from "../../../client/util/DragManager"; import { InkingControl } from "../../../client/views/InkingControl"; import { CollectionViewType } from "../../../client/views/collections/CollectionView"; +import { makeTemplate } from "../../../client/util/DropConverter"; +import { RichTextField } from "../../../new_fields/RichTextField"; export class CurrentUserUtils { private static curr_id: string; @@ -227,14 +229,30 @@ export class CurrentUserUtils { /// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window static setupExpandingButtons(doc: Doc) { + const slideTemplate = Docs.Create.StackingDocument( + [ + Docs.Create.MulticolumnDocument([], { title: "images", _height: 200, _xMargin: 10, _yMargin: 10 }), + Docs.Create.TextDocument("", { title: "contents", _height: 100 }) + ], + { _width: 400, _height: 300, title: "slide", _chromeStatus: "disabled", _autoHeight: true }); + slideTemplate.isTemplateDoc = makeTemplate(slideTemplate); + + const iconDoc = Docs.Create.TextDocument("", { title: "icon", _width: 150, _height: 30, onClick: ScriptField.MakeScript("setNativeView(this)") }); + Doc.GetProto(iconDoc).data = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', ""); + doc.isTemplateDoc = makeTemplate(iconDoc); + doc.iconView = iconDoc; + doc.undoBtn = Docs.Create.FontIconDocument( { _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: "alias", onClick: ScriptField.MakeScript("undo()"), removeDropProperties: new List(["dropAction"]), title: "undo button", icon: "undo-alt" }); doc.redoBtn = Docs.Create.FontIconDocument( { _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: "alias", onClick: ScriptField.MakeScript("redo()"), removeDropProperties: new List(["dropAction"]), title: "redo button", icon: "redo-alt" }); + doc.slidesBtn = Docs.Create.FontIconDocument( + { _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: "alias", onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: slideTemplate, removeDropProperties: new List(["dropAction"]), title: "slide button", icon: "sticky-note" }); - doc.expandingButtons = Docs.Create.LinearDocument([doc.undoBtn as Doc, doc.redoBtn as Doc], { + doc.expandingButtons = Docs.Create.LinearDocument([doc.undoBtn as Doc, doc.redoBtn as Doc, doc.slidesBtn as Doc], { title: "expanding buttons", _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", backgroundColor: "black", preventTreeViewOpen: true, forceActive: true, lockedPosition: true, + dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }) }); } -- cgit v1.2.3-70-g09d2 From a0ca191b6263e3ccff8740ddf6cf9cba68b9f2f9 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 5 Feb 2020 11:26:24 -0500 Subject: fixed iconify things. fixed presentation title bar. --- src/client/documents/Documents.ts | 3 ++- src/client/views/DocumentDecorations.tsx | 3 ++- src/client/views/nodes/DocumentView.tsx | 2 +- src/new_fields/Doc.ts | 4 +++- src/server/authentication/models/current_user_utils.ts | 11 +++++++---- 5 files changed, 15 insertions(+), 8 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 5eb4dc5fb..17570fcb5 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -106,6 +106,7 @@ export interface DocumentOptions { documentText?: string; borderRounding?: string; boxShadow?: string; + showTitle?: string; sectionFilter?: string; // field key used to determine headings for sections in stacking and masonry views schemaColumns?: List; dockingConfig?: string; @@ -340,7 +341,7 @@ export namespace Docs { export namespace Create { const delegateKeys = ["x", "y", "layoutKey", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "_dropAction", "_annotationOn", - "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_showSidebar"]; + "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_showSidebar", "showTitle"]; /** * This function receives the relevant document prototype and uses diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index c5034b901..a0ba16ea4 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -265,8 +265,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> const layoutKey = Cast(dv.props.Document.layoutKey, "string", null); const collapse = layoutKey !== "layout_icon"; if (collapse) { - if (layoutKey && layoutKey !== "layout") dv.props.Document.deiconifyLayout = layoutKey.replace("layout_", ""); dv.setCustomView(collapse, "icon"); + if (layoutKey && layoutKey !== "layout") dv.props.Document.deiconifyLayout = layoutKey.replace("layout_", ""); } else { const deiconifyLayout = Cast(dv.props.Document.deiconifyLayout, "string", null); dv.setCustomView(deiconifyLayout ? true : false, deiconifyLayout); @@ -274,6 +274,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } }); } + SelectionManager.DeselectAll(); } @action diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c14d11cce..1fb3dcb36 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -902,7 +902,7 @@ export class DocumentView extends DocComponent(Docu const showTitle = StrCast(this.getLayoutPropStr("showTitle")); const showTitleHover = StrCast(this.getLayoutPropStr("showTitleHover")); const showCaption = this.getLayoutPropStr("showCaption"); - const showTextTitle = showTitle && StrCast(this.layoutDoc.layout).indexOf("FormattedTextBox") !== -1 ? showTitle : undefined; + const showTextTitle = showTitle && (StrCast(this.layoutDoc.layout).indexOf("PresBox") !== -1 || StrCast(this.layoutDoc.layout).indexOf("FormattedTextBox") !== -1) ? showTitle : undefined; const searchHighlight = (!this.Document.searchFields ? (null) :
{this.Document.searchFields} diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 9b4844b19..862557302 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -784,8 +784,10 @@ export namespace Doc { export function setNativeView(doc: any) { const prevLayout = StrCast(doc.layoutKey).split("_")[1]; + const deiconify = prevLayout === "icon" && StrCast(doc.deiconifyLayout) ? "layout_" + StrCast(doc.deiconifyLayout) : ""; + doc.deiconifyLayout = undefined; if (StrCast(doc.title).endsWith("_" + prevLayout)) doc.title = StrCast(doc.title).replace("_" + prevLayout, ""); - doc.layoutKey = "layout"; + doc.layoutKey = deiconify || "layout"; } } diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index a6dd809f4..a4af46a63 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -17,6 +17,7 @@ import { InkingControl } from "../../../client/views/InkingControl"; import { CollectionViewType } from "../../../client/views/collections/CollectionView"; import { makeTemplate } from "../../../client/util/DropConverter"; import { RichTextField } from "../../../new_fields/RichTextField"; +import { PrefetchProxy } from "../../../new_fields/Proxy"; export class CurrentUserUtils { private static curr_id: string; @@ -47,17 +48,19 @@ export class CurrentUserUtils { // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools static setupCreatorButtons(doc: Doc, buttons?: string[]) { const notes = CurrentUserUtils.setupNoteTypes(doc); + const emptyPresentation = Docs.Create.PresDocument(new List(), { title: "Presentation", _viewType: CollectionViewType.Stacking, showTitle: "title", boxShadow: "0 0" }); + const emptyCollection = Docs.Create.FreeformDocument([], { _nativeWidth: undefined, _nativeHeight: undefined, _LODdisable: true, _width: 150, _height: 100, title: "freeform" }); doc.noteTypes = Docs.Create.TreeDocument(notes, { title: "Note Types", _height: 75 }); doc.activePen = doc; const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, ischecked?: string, activePen?: Doc, backgroundColor?: string, dragFactory?: Doc }[] = [ - { title: "collection", icon: "folder", ignoreClick: true, drag: 'Docs.Create.FreeformDocument([], { _nativeWidth: undefined, _nativeHeight: undefined, _LODdisable: true, _width: 150, _height: 100, title: "freeform" })' }, + { title: "collection", icon: "folder", click: 'openOnRight(getCopy(this.dragFactory))', drag: 'getCopy(this.dragFactory, true)', dragFactory: emptyCollection }, { title: "preview", icon: "expand", ignoreClick: true, drag: 'Docs.Create.DocumentDocument(ComputedField.MakeFunction("selectedDocs(this,true,[_last_])?.[0]"), { _width: 250, _height: 250, title: "container" })' }, { title: "todo item", icon: "check", ignoreClick: true, drag: 'getCopy(this.dragFactory, true)', dragFactory: notes[notes.length - 1] }, { title: "web page", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", {_width: 300, _height: 300, title: "New Webpage" })' }, { title: "cat image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 200, title: "an image of a cat" })' }, { title: "record", icon: "microphone", ignoreClick: true, drag: `Docs.Create.AudioDocument("${nullAudio}", { _width: 200, title: "ready to record audio" })` }, { title: "clickable button", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ _width: 150, _height: 50, title: "Button" })' }, - { title: "presentation", icon: "tv", ignoreClick: true, drag: `Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { _width: 200, _height: 500, _xMargin:5, _viewType: ${CollectionViewType.Stacking}, title: "a presentation trail" })` }, + { title: "presentation", icon: "tv", click: 'openOnRight(Doc.UserDoc().curPresentation = getCopy(this.dragFactory))', drag: `Doc.UserDoc().curPresentation = getCopy(this.dragFactory,true)`, dragFactory: emptyPresentation }, { title: "import folder", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' }, { title: "mobile view", icon: "phone", ignoreClick: true, drag: 'Doc.UserDoc().activeMobile' }, { title: "use pen", icon: "pen-nib", click: 'activatePen(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this,2, this.backgroundColor)', backgroundColor: "blue", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc }, @@ -240,7 +243,7 @@ export class CurrentUserUtils { const iconDoc = Docs.Create.TextDocument("", { title: "icon", _width: 150, _height: 30, onClick: ScriptField.MakeScript("setNativeView(this)") }); Doc.GetProto(iconDoc).data = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', ""); doc.isTemplateDoc = makeTemplate(iconDoc); - doc.iconView = iconDoc; + doc.iconView = new PrefetchProxy(iconDoc); doc.undoBtn = Docs.Create.FontIconDocument( { _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: "alias", onClick: ScriptField.MakeScript("undo()"), removeDropProperties: new List(["dropAction"]), title: "undo button", icon: "undo-alt" }); @@ -266,7 +269,7 @@ export class CurrentUserUtils { // the initial presentation Doc to use static setupDefaultPresentation(doc: Doc) { - doc.curPresentation = Docs.Create.PresDocument(new List(), { title: "Presentation", _viewType: CollectionViewType.Stacking, boxShadow: "0 0" }); + doc.curPresentation = Docs.Create.PresDocument(new List(), { title: "Presentation", _viewType: CollectionViewType.Stacking, showTitle: "title", boxShadow: "0 0" }); } static setupMobileUploads(doc: Doc) { -- cgit v1.2.3-70-g09d2 From bc2798dbab082c381f7af1aa7b5ed2b6027c45aa Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 5 Feb 2020 16:04:31 -0500 Subject: added aliasOf on aliasing .. and sourceContext for presentations --- src/client/util/SelectionManager.ts | 2 -- src/client/views/DocumentButtonBar.tsx | 1 + src/client/views/nodes/DocumentView.tsx | 1 + src/client/views/nodes/PresBox.tsx | 15 +++++++++------ src/new_fields/Doc.ts | 1 + 5 files changed, 12 insertions(+), 8 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 86a7a620e..4612f10f4 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -3,8 +3,6 @@ import { Doc } from "../../new_fields/Doc"; import { DocumentView } from "../views/nodes/DocumentView"; import { computedFn } from "mobx-utils"; import { List } from "../../new_fields/List"; -import { DocumentDecorations } from "../views/DocumentDecorations"; -import RichTextMenu from "./RichTextMenu"; export namespace SelectionManager { diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 121f79840..963d97d59 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -211,6 +211,7 @@ export class DocumentButtonBar extends React.Component<{ views: (DocumentView | DockedFrameRenderer.UnpinDoc(targetDoc); } else { + targetDoc.sourceContext = this.view0?.props.ContainingCollectionDoc; // bcz: !! Shouldn't need this ... use search to lookup contexts dynamically DockedFrameRenderer.PinDoc(targetDoc); } }}> diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 776d4b8c3..c04402360 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -210,6 +210,7 @@ export class DocumentView extends DocComponent(Docu dragData.moveDocument = this.props.moveDocument;// this.Document.onDragStart ? undefined : this.props.moveDocument; dragData.applyAsTemplate = applyAsTemplate; dragData.dragDivName = this.props.dragDivName; + this.props.Document.sourceContext = this.props.ContainingCollectionDoc; // bcz: !! shouldn't need this ... use search find the document's context dynamically DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: !dropAction && !this.Document.onDragStart }); } } diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 44411fa30..2b195855c 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -181,15 +181,17 @@ export class PresBox extends React.Component { }); //docToJump stayed same meaning, it was not in the group or was the last element in the group + const aliasOf = await Cast(docToJump.aliasOf, Doc); + const srcContext = aliasOf && await Cast(aliasOf.sourceContext, Doc); if (docToJump === curDoc) { //checking if curDoc has navigation open - const target = await curDoc.presentationTargetDoc as Doc; - if (curDoc.navButton) { - DocumentManager.Instance.jumpToDocument(target, false); - } else if (curDoc.showButton) { + const target = await Cast(curDoc.presentationTargetDoc, Doc); + if (curDoc.navButton && target) { + DocumentManager.Instance.jumpToDocument(target, false, undefined, srcContext); + } else if (curDoc.showButton && target) { const curScale = DocumentManager.Instance.getScaleOfDocView(fromDoc); //awaiting jump so that new scale can be found, since jumping is async - await DocumentManager.Instance.jumpToDocument(target, true); + await DocumentManager.Instance.jumpToDocument(target, true, undefined, srcContext); curDoc.viewScale = DocumentManager.Instance.getScaleOfDocView(target); //saving the scale user was on before zooming in @@ -203,7 +205,8 @@ export class PresBox extends React.Component { const curScale = DocumentManager.Instance.getScaleOfDocView(fromDoc); //awaiting jump so that new scale can be found, since jumping is async - await DocumentManager.Instance.jumpToDocument(await docToJump.presentationTargetDoc as Doc, willZoom); + const presTargetDoc = await docToJump.presentationTargetDoc as Doc; + await DocumentManager.Instance.jumpToDocument(presTargetDoc, willZoom, undefined, srcContext); const newScale = DocumentManager.Instance.getScaleOfDocView(await curDoc.presentationTargetDoc as Doc); curDoc.viewScale = newScale; //saving the scale that user was on diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 862557302..2f669aecc 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -427,6 +427,7 @@ export namespace Doc { if (layout instanceof Doc && layout !== alias && layout === Doc.Layout(alias)) { Doc.SetLayout(alias, Doc.MakeAlias(layout)); } + alias.aliasOf = doc; alias.title = ComputedField.MakeFunction(`renameAlias(this, ${Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1})`); return alias; } -- cgit v1.2.3-70-g09d2 From 714e66d2916971b5b023ba33c20b8794c1d536e2 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 6 Feb 2020 09:25:50 -0500 Subject: fixed unsetting of dropAction in buxton layouts. --- src/client/documents/Documents.ts | 6 +++--- src/client/util/DragManager.ts | 7 +++++-- src/client/views/collections/CollectionDockingView.tsx | 2 +- src/client/views/collections/CollectionTimeView.tsx | 2 +- src/client/views/collections/CollectionTreeView.tsx | 9 ++++----- src/client/views/nodes/DocumentView.tsx | 4 ++-- src/new_fields/documentSchemas.ts | 2 +- src/server/authentication/models/current_user_utils.ts | 16 ++++++++-------- 8 files changed, 25 insertions(+), 23 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 17570fcb5..64dc0d8b7 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -67,7 +67,7 @@ export interface DocumentOptions { _fitWidth?: boolean; _fitToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents _LODdisable?: boolean; - _dropAction?: dropActionType; + dropAction?: dropActionType; _chromeStatus?: string; _viewType?: number; _gridGap?: number; // gap between items in masonry view @@ -340,7 +340,7 @@ export namespace Docs { */ export namespace Create { - const delegateKeys = ["x", "y", "layoutKey", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "_dropAction", "_annotationOn", + const delegateKeys = ["x", "y", "layoutKey", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "dropAction", "_annotationOn", "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_showSidebar", "showTitle"]; /** @@ -745,7 +745,7 @@ export namespace Docs { } if (type.indexOf("excel") !== -1) { ctor = Docs.Create.DBDocument; - options._dropAction = "copy"; + options.dropAction = "copy"; } if (type.indexOf("html") !== -1) { if (path.includes(window.location.hostname)) { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index c05a2de96..b0dd90947 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -15,7 +15,7 @@ import { listSpec } from "../../new_fields/Schema"; import { Scripting } from "./Scripting"; import { convertDropDataToButtons } from "./DropConverter"; -export type dropActionType = "alias" | "copy" | undefined; +export type dropActionType = "alias" | "copy" | "move" | undefined; export function SetupDrag( _reference: React.RefObject, docFunc: () => Doc | Promise | undefined, @@ -197,7 +197,10 @@ export namespace DragManager { dragData.userDropAction === "copy" || (!dragData.userDropAction && dragData.dropAction === "copy") ? Doc.MakeCopy(d, true) : d) ); e.docDragData?.droppedDocuments.forEach((drop: Doc, i: number) => - Cast(dragData.draggedDocuments[i].removeDropProperties, listSpec("string"), []).map(prop => drop[prop] = undefined)); + Cast(dragData.draggedDocuments[i].removeDropProperties, listSpec("string"), []).map(prop => { + drop[prop] = "move"; + }) + ); }; dragData.draggedDocuments.map(d => d.dragFactory); // does this help? trying to make sure the dragFactory Doc is loaded StartDrag(eles, dragData, downX, downY, options, finishDrag); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 9c67d8041..2478aaecd 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -469,7 +469,7 @@ export class CollectionDockingView extends React.Component diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index 896fb74f0..ae5a3c7dc 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -33,7 +33,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { this.props.Document.excludeFields = new List(["_facetCollection", "_docFilter"]); const scriptText = "setDocFilter(containingTreeView.target, heading, this.title, checked)"; - const childText = "const alias = getAlias(this); Doc.ApplyTemplateTo(containingCollection.childDetailed, alias, 'layout_detailView'); alias._dropAction='alias'; alias.removeDropProperties=new List(['dropAction']); useRightSplit(alias, shiftKey); "; + const childText = "const alias = getAlias(this); Doc.ApplyTemplateTo(containingCollection.childDetailed, alias, 'layout_detailView'); alias.dropAction='alias'; alias.removeDropProperties=new List(['dropAction']); useRightSplit(alias, shiftKey); "; facetCollection.onCheckedClick = ScriptField.MakeScript(scriptText, { this: Doc.name, heading: "boolean", checked: "boolean", containingTreeView: Doc.name }); this.props.Document.onChildClick = ScriptField.MakeScript(childText, { this: Doc.name, heading: "boolean", containingCollection: Doc.name, shiftKey: "boolean" }); this.props.Document._facetCollection = facetCollection; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 19900c48b..f44c7a7b0 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -660,18 +660,16 @@ export class CollectionTreeView extends CollectionSubView(Document) { heroView.proto!.layout = ImageBox.LayoutString("hero"); heroView.showTitle = "title"; heroView.showTitleHover = "titlehover"; - heroView._dropAction = "alias"; - heroView.removeDropProperties = new List(["dropAction"]); Doc.AddDocToList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", Docs.Create.FontIconDocument({ - _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: "alias", onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), + _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: "alias", onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: heroView, removeDropProperties: new List(["dropAction"]), title: "hero view", icon: "portrait" })); Doc.AddDocToList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", Docs.Create.FontIconDocument({ - _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: "alias", onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), + _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: "alias", onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: detailView, removeDropProperties: new List(["dropAction"]), title: "detail view", icon: "file-alt" })); @@ -680,6 +678,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { Document.childDetailed = detailView; Document._viewType = CollectionViewType.Time; Document._forceActive = true; + Document.childDropAction = "alias"; Document.pivotField = "company"; } }); @@ -704,7 +703,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { } render() { - const dropAction = StrCast(this.props.Document._dropAction) as dropActionType; + const dropAction = StrCast(this.props.Document.dropAction) as dropActionType; const addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before, false, false, false); const moveDoc = (d: Doc, target: Doc | undefined, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); return !this.childDocs ? (null) : ( diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c04402360..f9d9e7212 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -348,7 +348,7 @@ export class DocumentView extends DocComponent(Docu if (Math.abs(this._downX - touch.clientX) > 3 || Math.abs(this._downY - touch.clientY) > 3) { if (!e.altKey && (!this.topMost || this.Document.onDragStart || this.Document.onClick)) { this.cleanUpInteractions(); - this.startDragging(this._downX, this._downY, this.Document._dropAction ? this.Document._dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag); + this.startDragging(this._downX, this._downY, this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag); } } e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers @@ -489,7 +489,7 @@ export class DocumentView extends DocComponent(Docu if (!e.altKey && (!this.topMost || this.Document.onDragStart || this.onClickHandler) && (e.buttons === 1 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE))) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); - this.startDragging(this._downX, this._downY, this.Document._dropAction ? this.Document._dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag); + this.startDragging(this._downX, this._downY, this.props.ContainingCollectionDoc?.childDropAction ? this.props.ContainingCollectionDoc?.childDropAction : this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag); } } e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts index 0b3bd6338..1aed5c242 100644 --- a/src/new_fields/documentSchemas.ts +++ b/src/new_fields/documentSchemas.ts @@ -8,7 +8,7 @@ export const documentSchema = createSchema({ layoutKey: "string", // holds the field key for the field that actually holds the current lyoat layout_custom: Doc, // used to hold a custom layout (there's nothing special about this field .. any field could hold a custom layout that can be selected by setting 'layoutKey') title: "string", // document title (can be on either data document or layout) - _dropAction: "string", // override specifying what should happen when this document is dropped (can be "alias" or "copy") + dropAction: "string", // override specifying what should happen when this document is dropped (can be "alias" or "copy") _nativeWidth: "number", // native width of document which determines how much document contents are scaled when the document's width is set _nativeHeight: "number", // " _width: "number", // width of document in its container's coordinate system diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 74db511df..b23ab5e49 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -71,7 +71,7 @@ export class CurrentUserUtils { { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activePen.pen = this;', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "white", activePen: doc }, ]; return docProtoData.filter(d => !buttons || !buttons.includes(d.title)).map(data => Docs.Create.FontIconDocument({ - _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: data.click ? "copy" : undefined, title: data.title, icon: data.icon, ignoreClick: data.ignoreClick, + _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: data.click ? "copy" : undefined, title: data.title, icon: data.icon, ignoreClick: data.ignoreClick, onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined, onClick: data.click ? ScriptField.MakeScript(data.click) : undefined, ischecked: data.ischecked ? ComputedField.MakeFunction(data.ischecked) : undefined, activePen: data.activePen, backgroundColor: data.backgroundColor, removeDropProperties: new List(["dropAction"]), dragFactory: data.dragFactory, @@ -109,7 +109,7 @@ export class CurrentUserUtils { { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activePen.pen = this;', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "white", activePen: doc }, ]; return docProtoData.filter(d => !buttons || !buttons.includes(d.title)).map(data => Docs.Create.FontIconDocument({ - _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: data.click ? "copy" : undefined, title: data.title, icon: data.icon, ignoreClick: data.ignoreClick, + _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: data.click ? "copy" : undefined, title: data.title, icon: data.icon, ignoreClick: data.ignoreClick, onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined, onClick: data.click ? ScriptField.MakeScript(data.click) : undefined, ischecked: data.ischecked ? ComputedField.MakeFunction(data.ischecked) : undefined, activePen: data.activePen, backgroundColor: data.backgroundColor, removeDropProperties: new List(["dropAction"]), dragFactory: data.dragFactory, @@ -125,7 +125,7 @@ export class CurrentUserUtils { { title: "ignore gestures", icon: "signature", pointerUp: "setToolglass('none')", pointerDown: "setToolglass('ignoregesture')", backgroundColor: "green", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc }, ]; return docProtoData.map(data => Docs.Create.FontIconDocument({ - _nativeWidth: 10, _nativeHeight: 10, _width: 10, _height: 10, _dropAction: data.pointerDown ? "copy" : undefined, title: data.title, icon: data.icon, ignoreClick: data.ignoreClick, + _nativeWidth: 10, _nativeHeight: 10, _width: 10, _height: 10, dropAction: data.pointerDown ? "copy" : undefined, title: data.title, icon: data.icon, ignoreClick: data.ignoreClick, onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined, clipboard: data.clipboard, onPointerUp: data.pointerUp ? ScriptField.MakeScript(data.pointerUp) : undefined, onPointerDown: data.pointerDown ? ScriptField.MakeScript(data.pointerDown) : undefined, @@ -158,7 +158,7 @@ export class CurrentUserUtils { }); // setup a color picker const color = Docs.Create.ColorDocument({ - title: "color picker", _width: 300, _dropAction: "alias", forceActive: true, removeDropProperties: new List(["dropAction", "forceActive"]) + title: "color picker", _width: 300, dropAction: "alias", forceActive: true, removeDropProperties: new List(["dropAction", "forceActive"]) }); return Docs.Create.ButtonDocument({ @@ -191,7 +191,7 @@ export class CurrentUserUtils { _width: 50, _height: 25, backgroundColor: "lightgrey", color: "rgb(34, 34, 34)", title: "Library", fontSize: 10, letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)", sourcePanel: Docs.Create.TreeDocument([doc.workspaces as Doc, doc.documents as Doc, doc.recentlyClosed as Doc], { - title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, _dropAction: "alias", lockedPosition: true, boxShadow: "0 0", + title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, dropAction: "alias", lockedPosition: true, boxShadow: "0 0", }), targetContainer: sidebarContainer, onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel;") @@ -246,11 +246,11 @@ export class CurrentUserUtils { doc.iconView = new PrefetchProxy(iconDoc); doc.undoBtn = Docs.Create.FontIconDocument( - { _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: "alias", onClick: ScriptField.MakeScript("undo()"), removeDropProperties: new List(["dropAction"]), title: "undo button", icon: "undo-alt" }); + { _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: "alias", onClick: ScriptField.MakeScript("undo()"), removeDropProperties: new List(["dropAction"]), title: "undo button", icon: "undo-alt" }); doc.redoBtn = Docs.Create.FontIconDocument( - { _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: "alias", onClick: ScriptField.MakeScript("redo()"), removeDropProperties: new List(["dropAction"]), title: "redo button", icon: "redo-alt" }); + { _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: "alias", onClick: ScriptField.MakeScript("redo()"), removeDropProperties: new List(["dropAction"]), title: "redo button", icon: "redo-alt" }); doc.slidesBtn = Docs.Create.FontIconDocument( - { _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, _dropAction: "alias", onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: slideTemplate, removeDropProperties: new List(["dropAction"]), title: "presentation slide", icon: "sticky-note" }); + { _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: "alias", onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: slideTemplate, removeDropProperties: new List(["dropAction"]), title: "presentation slide", icon: "sticky-note" }); doc.expandingButtons = Docs.Create.LinearDocument([doc.undoBtn as Doc, doc.redoBtn as Doc, doc.slidesBtn as Doc], { title: "expanding buttons", _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", backgroundColor: "black", preventTreeViewOpen: true, forceActive: true, lockedPosition: true, -- cgit v1.2.3-70-g09d2 From 0817d947b98b1b8e7f05df6b1d3db8eef4996ec9 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 6 Feb 2020 10:38:18 -0500 Subject: added synching of timelines with presentations --- .../views/collections/CollectionTimeView.tsx | 23 ++++++++++- src/client/views/nodes/PresBox.tsx | 45 ++++++++++++++-------- src/new_fields/ScriptField.ts | 4 +- 3 files changed, 52 insertions(+), 20 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index ae5a3c7dc..1c4bfa4e8 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -19,6 +19,7 @@ import React = require("react"); import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from "../ContextMenuItem"; import { RichTextField } from "../../../new_fields/RichTextField"; +import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; @observer export class CollectionTimeView extends CollectionSubView(doc => doc) { @@ -225,6 +226,21 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) {
; } + specificMenu = (e: React.MouseEvent) => { + const layoutItems: ContextMenuProps[] = []; + + layoutItems.push({ description: "Force Timeline", event: () => { this.props.Document._forceRenderEngine = "timeline" }, icon: "compress-arrows-alt" }); + layoutItems.push({ description: "Force Pivot", event: () => { this.props.Document._forceRenderEngine = "pivot" }, icon: "compress-arrows-alt" }); + layoutItems.push({ description: "Auto Time/Pivot layout", event: () => { this.props.Document._forceRenderEngine = undefined }, icon: "compress-arrows-alt" }); + layoutItems.push({ + description: "Sync with presentation", event: () => { + this.props.Document[this.props.fieldKey + "-timelineCur"] = ComputedField.MakeFunction("mainPres.curPresentation.data[mainPres.curPresentation._itemIndex].year || 0", { mainPres: Doc.name }, { mainPres: CurrentUserUtils.UserDocument }); + }, icon: "compress-arrows-alt" + }); + + ContextMenu.Instance.addItem({ description: "Pivot/Time Options ...", subitems: layoutItems, icon: "eye" }); + } + render() { const newEditableViewProps = { GetValue: () => "", @@ -248,7 +264,8 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { nonNumbers++; } }); - const doTimeline = nonNumbers / this.childDocs.length < 0.1 && this.props.PanelWidth() / this.props.PanelHeight() > 6; + const forceLayout = StrCast(this.props.Document._forceRenderEngine); + const doTimeline = forceLayout ? (forceLayout === "timeline") : nonNumbers / this.childDocs.length < 0.1 && this.props.PanelWidth() / this.props.PanelHeight() > 6; if (doTimeline !== (this._layoutEngine === "timeline")) { if (!this._changing) { this._changing = true; @@ -259,9 +276,11 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { } } + const facetCollection = Cast(this.props.Document?._facetCollection, Doc, null); return !facetCollection ? (null) : -
+
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 44405c413..be5d414a5 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -2,10 +2,10 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; import { faArrowLeft, faArrowRight, faEdit, faMinus, faPlay, faPlus, faStop, faTimes } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, IReactionDisposer, reaction, observable } from "mobx"; +import { action, computed, IReactionDisposer, reaction, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; -import { listSpec } from "../../../new_fields/Schema"; +import { listSpec, makeInterface } from "../../../new_fields/Schema"; import { Cast, FieldValue, NumCast } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { Docs } from "../../documents/Documents"; @@ -20,6 +20,9 @@ import { CollectionCarouselView } from "../collections/CollectionCarouselView"; import { returnFalse } from "../../../Utils"; import { ContextMenuProps } from "../ContextMenuItem"; import { CollectionTimeView } from "../collections/CollectionTimeView"; +import { documentSchema } from "../../../new_fields/documentSchemas"; +import { InkingControl } from "../InkingControl"; +import { InkTool } from "../../../new_fields/InkField"; library.add(faArrowLeft); library.add(faArrowRight); @@ -35,6 +38,8 @@ export class PresBox extends React.Component { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); } _childReaction: IReactionDisposer | undefined; _slideshowReaction: IReactionDisposer | undefined; + @observable _isChildActive = false; + componentDidMount() { const userDoc = CurrentUserUtils.UserDocument; this._slideshowReaction = reaction(() => this.props.Document._slideshow, @@ -54,16 +59,17 @@ export class PresBox extends React.Component { this.props.Document.childLayout = undefined; } }, { fireImmediately: true }); - this._childReaction = reaction(() => this.childDocs.slice(), - (children) => children.forEach((child, i) => child.presentationIndex = i), { fireImmediately: true }); + this._childReaction = reaction(() => this.childDocs.slice(), (children) => children.forEach((child, i) => child.presentationIndex = i), { fireImmediately: true }); } componentWillUnmount() { this._childReaction?.(); + this._slideshowReaction?.(); } @computed get childDocs() { return DocListCast(this.props.Document[this.props.fieldKey]); } next = async () => { + runInAction(() => Doc.UserDoc().curPresentation = this.props.Document); const current = NumCast(this.props.Document._itemIndex); //asking to get document at current index const docAtCurrentNext = await this.getDocAtIndex(current + 1); @@ -81,6 +87,7 @@ export class PresBox extends React.Component { } } back = async () => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); const current = NumCast(this.props.Document._itemIndex); //requesting for the doc at current index const docAtCurrent = await this.getDocAtIndex(current); @@ -120,12 +127,17 @@ export class PresBox extends React.Component { } } + whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive)); + active = (outsideReaction?: boolean) => ((InkingControl.Instance.selectedTool === InkTool.None && !this.props.Document.isBackground) && + (this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) + /** * This is the method that checks for the actions that need to be performed * after the document has been presented, which involves 3 button options: * Hide Until Presented, Hide After Presented, Fade After Presented */ showAfterPresented = (index: number) => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); this.childDocs.forEach((doc, ind) => { //the order of cases is aligned based on priority if (doc.hideTillShownButton && ind <= index) { @@ -146,6 +158,7 @@ export class PresBox extends React.Component { * Hide Until Presented, Hide After Presented, Fade After Presented */ hideIfNotPresented = (index: number) => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); this.childDocs.forEach((key, ind) => { //the order of cases is aligned based on priority @@ -167,6 +180,7 @@ export class PresBox extends React.Component { * te option open, navigates to that element. */ navigateToElement = async (curDoc: Doc, fromDocIndex: number) => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); const fromDoc = this.childDocs[fromDocIndex].presentationTargetDoc as Doc; let docToJump = curDoc; let willZoom = false; @@ -257,8 +271,8 @@ export class PresBox extends React.Component { //The function that is called when a document is clicked or reached through next or back. //it'll also execute the necessary actions if presentation is playing. - @action public gotoDocument = async (index: number, fromDoc: number) => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); Doc.UnBrushAllDocs(); const list = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc))); if (list && index >= 0 && index < list.length) { @@ -279,8 +293,8 @@ export class PresBox extends React.Component { } //The function that starts or resets presentaton functionally, depending on status flag. - @action startOrResetPres = () => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); if (this.props.Document.presStatus) { this.resetPresentation(); } else { @@ -299,8 +313,8 @@ export class PresBox extends React.Component { //The function that resets the presentation by removing every action done by it. It also //stops the presentaton. - @action resetPresentation = () => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); this.childDocs.forEach((doc: Doc) => { doc.opacity = 1; doc.viewScale = 1; @@ -315,6 +329,7 @@ export class PresBox extends React.Component { //The function that starts the presentation, also checking if actions should be applied //directly at start. startPresentation = (startIndex: number) => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); this.childDocs.map(doc => { if (doc.hideTillShownButton && this.childDocs.indexOf(doc) > startIndex) { doc.opacity = 0; @@ -343,18 +358,16 @@ export class PresBox extends React.Component { specificContextMenu = (e: React.MouseEvent): void => { const funcs: ContextMenuProps[] = []; - funcs.push({ description: "Make Current Presentation", event: action(() => Doc.UserDoc().curPresentation = this.props.Document), icon: "asterisk" }); - funcs.push({ description: "Make slideshow", event: action(() => this.props.Document._slideshow = "slideshow"), icon: "asterisk" }); - funcs.push({ description: "Make timeline", event: action(() => this.props.Document._slideshow = "timeline"), icon: "asterisk" }); - funcs.push({ description: "Make list", event: action(() => this.props.Document._slideshow = "list"), icon: "asterisk" }); - ContextMenu.Instance.addItem({ description: "Presentatoin Funcs...", subitems: funcs, icon: "asterisk" }); + funcs.push({ description: "Show as Slideshow", event: action(() => this.props.Document._slideshow = "slideshow"), icon: "asterisk" }); + funcs.push({ description: "Show as Timeline", event: action(() => this.props.Document._slideshow = "timeline"), icon: "asterisk" }); + funcs.push({ description: "Show as List", event: action(() => this.props.Document._slideshow = "list"), icon: "asterisk" }); + ContextMenu.Instance.addItem({ description: "Presentation Funcs...", subitems: funcs, icon: "asterisk" }); } /** * Initially every document starts with a viewScale 1, which means * that they will be displayed in a canvas with scale 1. */ - @action initializeScaleViews = (docList: Doc[], viewtype: number) => { this.props.Document._chromeStatus = "disabled"; const hgt = (viewtype === CollectionViewType.Tree) ? 50 : 46; @@ -384,7 +397,7 @@ export class PresBox extends React.Component { render() { this.initializeScaleViews(this.childDocs, NumCast(this.props.Document._viewType)); return (this.props.Document._slideshow ? -
+
{this.props.Document.inOverlay ? (null) :
{this.props.Document._slideshow === "slideshow" ? @@ -409,8 +422,8 @@ export class PresBox extends React.Component { {this.props.Document.inOverlay ? (null) : -
- +
+
}
); } diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts index f8a8d1226..4c78ea3aa 100644 --- a/src/new_fields/ScriptField.ts +++ b/src/new_fields/ScriptField.ts @@ -114,8 +114,8 @@ export class ScriptField extends ObjectField { }); return compiled; } - public static MakeFunction(script: string, params: object = {}) { - const compiled = ScriptField.CompileScript(script, params, true); + public static MakeFunction(script: string, params: object = {}, capturedVariables?: { [name: string]: Field }) { + const compiled = ScriptField.CompileScript(script, params, true, capturedVariables); return compiled.compiled ? new ScriptField(compiled) : undefined; } -- cgit v1.2.3-70-g09d2 From 96307685adc3460f4269606b5f826854ce3cf280 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 6 Feb 2020 11:09:52 -0500 Subject: switch pivotField to _pivotField and fixed the sync script to be more general with timelines. --- .../views/collections/CollectionTimeView.tsx | 27 +++++++++++----------- .../views/collections/CollectionTreeView.tsx | 2 +- .../CollectionFreeFormLayoutEngines.tsx | 4 ++-- src/new_fields/Doc.ts | 5 ++++ src/new_fields/documentSchemas.ts | 2 ++ 5 files changed, 24 insertions(+), 16 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index 1c4bfa4e8..a9114026f 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -115,8 +115,8 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { typeof (pair.layout[fieldKey]) === "number" || typeof (pair.layout[fieldKey]) === "string").map(fieldKey => keySet.add(fieldKey))); keySet.toArray().map(fieldKey => - docItems.push({ description: ":" + fieldKey, event: () => this.props.Document.pivotField = fieldKey, icon: "compress-arrows-alt" })); - docItems.push({ description: ":(null)", event: () => this.props.Document.pivotField = undefined, icon: "compress-arrows-alt" }) + docItems.push({ description: ":" + fieldKey, event: () => this.props.Document._pivotField = fieldKey, icon: "compress-arrows-alt" })); + docItems.push({ description: ":(null)", event: () => this.props.Document._pivotField = undefined, icon: "compress-arrows-alt" }) ContextMenu.Instance.addItem({ description: "Pivot Fields ...", subitems: docItems, icon: "eye" }); const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(x, y); ContextMenu.Instance.displayMenu(x, y, ":"); @@ -226,17 +226,18 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) {
; } + public static SyncTimelineToPresentation(doc: Doc) { + const fieldKey = Doc.LayoutFieldKey(doc); + doc[fieldKey + "-timelineCur"] = ComputedField.MakeFunction("(curPresentationItem()[this._pivotField || 'year'] || 0)"); + } specificMenu = (e: React.MouseEvent) => { const layoutItems: ContextMenuProps[] = []; + const doc = this.props.Document; - layoutItems.push({ description: "Force Timeline", event: () => { this.props.Document._forceRenderEngine = "timeline" }, icon: "compress-arrows-alt" }); - layoutItems.push({ description: "Force Pivot", event: () => { this.props.Document._forceRenderEngine = "pivot" }, icon: "compress-arrows-alt" }); - layoutItems.push({ description: "Auto Time/Pivot layout", event: () => { this.props.Document._forceRenderEngine = undefined }, icon: "compress-arrows-alt" }); - layoutItems.push({ - description: "Sync with presentation", event: () => { - this.props.Document[this.props.fieldKey + "-timelineCur"] = ComputedField.MakeFunction("mainPres.curPresentation.data[mainPres.curPresentation._itemIndex].year || 0", { mainPres: Doc.name }, { mainPres: CurrentUserUtils.UserDocument }); - }, icon: "compress-arrows-alt" - }); + layoutItems.push({ description: "Force Timeline", event: () => { doc._forceRenderEngine = "timeline" }, icon: "compress-arrows-alt" }); + layoutItems.push({ description: "Force Pivot", event: () => { doc._forceRenderEngine = "pivot" }, icon: "compress-arrows-alt" }); + layoutItems.push({ description: "Auto Time/Pivot layout", event: () => { doc._forceRenderEngine = undefined }, icon: "compress-arrows-alt" }); + layoutItems.push({ description: "Sync with presentation", event: () => CollectionTimeView.SyncTimelineToPresentation(doc), icon: "compress-arrows-alt" }); ContextMenu.Instance.addItem({ description: "Pivot/Time Options ...", subitems: layoutItems, icon: "eye" }); } @@ -246,20 +247,20 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { GetValue: () => "", SetValue: (value: any) => { if (value?.length) { - this.props.Document.pivotField = value; + this.props.Document._pivotField = value; return true; } return false; }, showMenuOnLoad: true, - contents: ":" + StrCast(this.props.Document.pivotField), + contents: ":" + StrCast(this.props.Document._pivotField), toggle: this.toggleVisibility, color: "#f1efeb" // this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; }; let nonNumbers = 0; this.childDocs.map(doc => { - const num = NumCast(doc[StrCast(this.props.Document.pivotField)], Number(StrCast(doc[StrCast(this.props.Document.pivotField)]))); + const num = NumCast(doc[StrCast(this.props.Document._pivotField)], Number(StrCast(doc[StrCast(this.props.Document._pivotField)]))); if (Number.isNaN(num)) { nonNumbers++; } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index f44c7a7b0..09f6a96d7 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -678,8 +678,8 @@ export class CollectionTreeView extends CollectionSubView(Document) { Document.childDetailed = detailView; Document._viewType = CollectionViewType.Time; Document._forceActive = true; + Document._pivotField = "company"; Document.childDropAction = "alias"; - Document.pivotField = "company"; } }); const existingOnClick = ContextMenu.Instance.findByDescription("OnClick..."); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index 84acbe0f0..d58925aab 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -85,7 +85,7 @@ export function computePivotLayout( const fieldKey = "data"; const pivotColumnGroups = new Map, Doc[]>(); - const pivotFieldKey = toLabel(pivotDoc.pivotField); + const pivotFieldKey = toLabel(pivotDoc._pivotField); for (const doc of childDocs) { const val = Field.toString(doc[pivotFieldKey] as Field); if (val) { @@ -191,7 +191,7 @@ export function computeTimelineLayout( const pivotDateGroups = new Map(); const docMap = new Map(); const groupNames: PivotData[] = []; - const timelineFieldKey = Field.toString(pivotDoc.pivotField as Field); + const timelineFieldKey = Field.toString(pivotDoc._pivotField as Field); const curTime = Cast(pivotDoc[fieldKey + "-timelineCur"], "number", null); const curTimeSpan = Cast(pivotDoc[fieldKey + "-timelineSpan"], "number", null); const minTimeReq = curTime === undefined ? Cast(pivotDoc[fieldKey + "-timelineMinReq"], "number", null) : curTimeSpan && (curTime - curTimeSpan); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 2f669aecc..6ae02720c 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -17,6 +17,7 @@ import { intersectRect } from "../Utils"; import { UndoManager } from "../client/util/UndoManager"; import { computedFn } from "mobx-utils"; import { RichTextField } from "./RichTextField"; +import { Script } from "vm"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -805,6 +806,10 @@ Scripting.addGlobal(function sameDocs(doc1: any, doc2: any) { return Doc.AreProt Scripting.addGlobal(function setNativeView(doc: any) { Doc.setNativeView(doc); }); Scripting.addGlobal(function undo() { return UndoManager.Undo(); }); Scripting.addGlobal(function redo() { return UndoManager.Redo(); }); +Scripting.addGlobal(function curPresentationItem() { + const curPres = Doc.UserDoc().curPresentation as Doc; + return curPres && DocListCast(curPres[Doc.LayoutFieldKey(curPres)])[NumCast(curPres._itemIndex)]; +}) Scripting.addGlobal(function selectDoc(doc: any) { Doc.UserDoc().SelectedDocs = new List([doc]); }); Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) { const docs = DocListCast(Doc.UserDoc().SelectedDocs).filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.DOCUMENT && d.type !== DocumentType.KVP && (!excludeCollections || !Cast(d.data, listSpec(Doc), null))); diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts index 1aed5c242..cb35c0681 100644 --- a/src/new_fields/documentSchemas.ts +++ b/src/new_fields/documentSchemas.ts @@ -9,12 +9,14 @@ export const documentSchema = createSchema({ layout_custom: Doc, // used to hold a custom layout (there's nothing special about this field .. any field could hold a custom layout that can be selected by setting 'layoutKey') title: "string", // document title (can be on either data document or layout) dropAction: "string", // override specifying what should happen when this document is dropped (can be "alias" or "copy") + childDropAction: "string", // specify the override for what should happen when the child of a collection is dragged from it and dropped (can be "alias" or "copy") _nativeWidth: "number", // native width of document which determines how much document contents are scaled when the document's width is set _nativeHeight: "number", // " _width: "number", // width of document in its container's coordinate system _height: "number", // " _freeformLayoutEngine: "string",// the string ID for the layout engine to use to layout freeform view documents _LODdisable: "boolean", // whether to disbale LOD switching for CollectionFreeFormViews + _pivotField: "string", // specifies which field should be used as the timeline/pivot axis color: "string", // foreground color of document backgroundColor: "string", // background color of document opacity: "number", // opacity of document -- cgit v1.2.3-70-g09d2 From 045233f2a8b8e79e6a3255ed594218929db1b042 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 6 Feb 2020 15:14:56 -0500 Subject: added pivoting into a pivot column --- src/client/views/collections/CollectionSubView.tsx | 6 +- .../views/collections/CollectionTimeView.tsx | 14 +++- .../CollectionFreeFormLayoutEngines.tsx | 87 ++++++++++++---------- .../collectionFreeForm/CollectionFreeFormView.tsx | 15 ++-- src/client/views/nodes/PresBox.tsx | 2 +- src/new_fields/Doc.ts | 31 ++++---- src/new_fields/util.ts | 2 +- 7 files changed, 87 insertions(+), 70 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 731b5b01d..a2700e75a 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -128,15 +128,11 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { const filteredDocs = docFilters.length ? viewedDocs.filter(d => { for (const key of Object.keys(clusters)) { const cluster = clusters[key]; - const satisfiesFacetx = !Object.keys(cluster).some((inner) => { - const modifier = cluster[inner]; - return ((modifier === "x") === Doc.matchFieldValue(d, key, inner)); - }); const satisfiesFacet = Object.keys(cluster).some(inner => { const modifier = cluster[inner]; return (modifier === "x") !== Doc.matchFieldValue(d, key, inner); }); - if (!satisfiesFacet || !satisfiesFacetx) { + if (!satisfiesFacet) { return false; } } diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index a9114026f..c0e18714e 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -20,6 +20,8 @@ import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from "../ContextMenuItem"; import { RichTextField } from "../../../new_fields/RichTextField"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; +import { Scripting } from "../../util/Scripting"; +import { ViewDefResult, ViewDefBounds } from "./collectionFreeForm/CollectionFreeFormLayoutEngines"; @observer export class CollectionTimeView extends CollectionSubView(doc => doc) { @@ -40,7 +42,11 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { this.props.Document._facetCollection = facetCollection; this.props.Document._fitToBox = true; } + if (!this.props.Document.onViewDefClick) { + this.props.Document.onViewDefDivClick = ScriptField.MakeScript("pivotColumnClick(this,payload)", { payload: "any" }) + } } + bodyPanelWidth = () => this.props.PanelWidth() - this._facetWidth; getTransform = () => this.props.ScreenToLocalTransform().translate(-this._facetWidth, 0); @@ -299,4 +305,10 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { }
; } -} \ No newline at end of file +} + +Scripting.addGlobal(function pivotColumnClick(pivotDoc: Doc, bounds: ViewDefBounds) { + console.log("filter down to key: " + pivotDoc._pivotField + " val:" + bounds.payload); + (bounds.payload as string[]).map(filterVal => + Doc.setDocFilter(pivotDoc, StrCast(pivotDoc._pivotField), filterVal, "check")); +}); \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index d58925aab..884f3b353 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -1,29 +1,18 @@ -import { Doc, Field, FieldResult, WidthSym, HeightSym } from "../../../../new_fields/Doc"; -import { NumCast, StrCast, Cast, DateCast, BoolCast } from "../../../../new_fields/Types"; +import { Doc, Field, FieldResult } from "../../../../new_fields/Doc"; +import { NumCast, StrCast, Cast } from "../../../../new_fields/Types"; import { ScriptBox } from "../../ScriptBox"; import { CompileScript } from "../../../util/Scripting"; import { ScriptField } from "../../../../new_fields/ScriptField"; import { OverlayView, OverlayElementOptions } from "../../OverlayView"; import { emptyFunction, aggregateBounds } from "../../../../Utils"; import React = require("react"); -import { ObservableMap, runInAction } from "mobx"; import { Id, ToString } from "../../../../new_fields/FieldSymbols"; import { ObjectField } from "../../../../new_fields/ObjectField"; import { RefField } from "../../../../new_fields/RefField"; -interface PivotData { - type: string; - text: string; - x: number; - y: number; - zIndex?: number; - width?: number; - height?: number; - fontSize: number; - color?: string; -} - export interface ViewDefBounds { + type: string; + text?: string; x: number; y: number; z?: number; @@ -31,7 +20,10 @@ export interface ViewDefBounds { width?: number; height?: number; transition?: string; + fontSize?: number; highlight?: boolean; + color?: string; + payload: any; } export interface PoolData { @@ -83,14 +75,14 @@ export function computePivotLayout( viewDefsToJSX: (views: any) => ViewDefResult[] ) { const fieldKey = "data"; - const pivotColumnGroups = new Map, Doc[]>(); + const pivotColumnGroups = new Map, { docs: Doc[], filters: string[] }>(); const pivotFieldKey = toLabel(pivotDoc._pivotField); for (const doc of childDocs) { const val = Field.toString(doc[pivotFieldKey] as Field); if (val) { - !pivotColumnGroups.get(val) && pivotColumnGroups.set(val, []); - pivotColumnGroups.get(val)!.push(doc); + !pivotColumnGroups.get(val) && pivotColumnGroups.set(val, { docs: [], filters: [val] }); + pivotColumnGroups.get(val)!.docs.push(doc); } } if (pivotColumnGroups.size > 10) { @@ -100,7 +92,10 @@ export function computePivotLayout( const numClusters = Math.ceil(sortedKeys.length / clusterSize); for (let i = 0; i < numClusters; i++) { for (let j = i * clusterSize + 1; j < Math.min(sortedKeys.length, (i + 1) * clusterSize); j++) { - pivotColumnGroups.get(sortedKeys[i * clusterSize])!.push(...pivotColumnGroups.get(sortedKeys[j])!); + const curgrp = pivotColumnGroups.get(sortedKeys[i * clusterSize])!; + const newgrp = pivotColumnGroups.get(sortedKeys[j])!; + curgrp.docs.push(...newgrp.docs); + curgrp.filters.push(...newgrp.filters); pivotColumnGroups.delete(sortedKeys[j]); } } @@ -109,7 +104,7 @@ export function computePivotLayout( const desc = `${fontSize}px ${getComputedStyle(document.body).fontFamily}`; const textlen = Array.from(pivotColumnGroups.keys()).map(c => getTextWidth(toLabel(c), desc)).reduce((p, c) => Math.max(p, c), 0 as number); const max_text = Math.min(Math.ceil(textlen / 120) * 28, panelDim[1] / 2); - let maxInColumn = Array.from(pivotColumnGroups.values()).reduce((p, s) => Math.max(p, s.length), 1); + let maxInColumn = Array.from(pivotColumnGroups.values()).reduce((p, s) => Math.max(p, s.docs.length), 1); const colWidth = panelDim[0] / pivotColumnGroups.size; const colHeight = panelDim[1] - max_text; @@ -129,7 +124,7 @@ export function computePivotLayout( } const docMap = new Map(); - const groupNames: PivotData[] = []; + const groupNames: ViewDefBounds[] = []; const expander = 1.05; const gap = .15; @@ -146,9 +141,10 @@ export function computePivotLayout( y: pivotAxisWidth, width: pivotAxisWidth * expander * numCols, height: max_text, - fontSize + fontSize, + payload: val }); - for (const doc of val) { + for (const doc of val.docs) { const layoutDoc = Doc.Layout(doc); let wid = pivotAxisWidth; let hgt = layoutDoc._nativeWidth ? (NumCast(layoutDoc._nativeHeight) / NumCast(layoutDoc._nativeWidth)) * pivotAxisWidth : pivotAxisWidth; @@ -157,10 +153,12 @@ export function computePivotLayout( wid = layoutDoc._nativeHeight ? (NumCast(layoutDoc._nativeWidth) / NumCast(layoutDoc._nativeHeight)) * pivotAxisWidth : pivotAxisWidth; } docMap.set(doc, { - x: x + xCount * pivotAxisWidth * expander + (pivotAxisWidth - wid) / 2 + (val.length < numCols ? (numCols - val.length) * pivotAxisWidth / 2 : 0), + type: "doc", + x: x + xCount * pivotAxisWidth * expander + (pivotAxisWidth - wid) / 2 + (val.docs.length < numCols ? (numCols - val.docs.length) * pivotAxisWidth / 2 : 0), y: -y + (pivotAxisWidth - hgt) / 2, width: wid, - height: hgt + height: hgt, + payload: undefined }); xCount++; if (xCount >= numCols) { @@ -172,12 +170,15 @@ export function computePivotLayout( }); const maxColHeight = pivotAxisWidth * expander * Math.ceil(maxInColumn / numCols); - const dividers = Array.from(pivotColumnGroups.values()).map((pg, i) => - ({ type: "div", color: "lightGray", x: i * pivotAxisWidth * (numCols * expander + gap), y: -maxColHeight + pivotAxisWidth, width: pivotAxisWidth * numCols * expander, height: maxColHeight } as any)); + const dividers = Array.from(pivotColumnGroups.values()).map((pkey, i) => + ({ type: "div", color: "lightGray", x: i * pivotAxisWidth * (numCols * expander + gap), y: -maxColHeight + pivotAxisWidth, width: pivotAxisWidth * numCols * expander, height: maxColHeight, payload: pkey.filters })); groupNames.push(...dividers); return normalizeResults(panelDim, max_text, childPairs, docMap, poolData, viewDefsToJSX, groupNames, 0, []); } +function toNumber(val: FieldResult) { + return val === undefined ? undefined : NumCast(val, Number(StrCast(val))); +} export function computeTimelineLayout( poolData: Map, @@ -190,9 +191,9 @@ export function computeTimelineLayout( const fieldKey = "data"; const pivotDateGroups = new Map(); const docMap = new Map(); - const groupNames: PivotData[] = []; + const groupNames: ViewDefBounds[] = []; const timelineFieldKey = Field.toString(pivotDoc._pivotField as Field); - const curTime = Cast(pivotDoc[fieldKey + "-timelineCur"], "number", null); + const curTime = toNumber(pivotDoc[fieldKey + "-timelineCur"]); const curTimeSpan = Cast(pivotDoc[fieldKey + "-timelineSpan"], "number", null); const minTimeReq = curTime === undefined ? Cast(pivotDoc[fieldKey + "-timelineMinReq"], "number", null) : curTimeSpan && (curTime - curTimeSpan); const maxTimeReq = curTime === undefined ? Cast(pivotDoc[fieldKey + "-timelineMaxReq"], "number", null) : curTimeSpan && (curTime + curTimeSpan); @@ -237,10 +238,10 @@ export function computeTimelineLayout( let prevKey = Math.floor(minTime); if (sortedKeys.length && scaling * (sortedKeys[0] - prevKey) > 25) { - groupNames.push({ type: "text", text: prevKey.toString(), x: x, y: 0, height: fontHeight, fontSize }); + groupNames.push({ type: "text", text: prevKey.toString(), x: x, y: 0, height: fontHeight, fontSize, payload: undefined }); } if (!sortedKeys.length && curTime !== undefined) { - groupNames.push({ type: "text", text: curTime.toString(), x: (curTime - minTime) * scaling, zIndex: 1000, color: "orange", y: 0, height: fontHeight, fontSize }); + groupNames.push({ type: "text", text: curTime.toString(), x: (curTime - minTime) * scaling, zIndex: 1000, color: "orange", y: 0, height: fontHeight, fontSize, payload: undefined }); } const pivotAxisWidth = NumCast(pivotDoc.pivotTimeWidth, panelDim[1] / 2.5); @@ -248,21 +249,23 @@ export function computeTimelineLayout( let zind = 0; sortedKeys.forEach(key => { if (curTime !== undefined && curTime > prevKey && curTime <= key) { - groupNames.push({ type: "text", text: curTime.toString(), x: (curTime - minTime) * scaling, y: 0, zIndex: 1000, color: "orange", height: fontHeight, fontSize }); + groupNames.push({ type: "text", text: curTime.toString(), x: (curTime - minTime) * scaling, y: 0, zIndex: 1000, color: "orange", height: fontHeight, fontSize, payload: key }); } const keyDocs = pivotDateGroups.get(key)!; x += scaling * (key - prevKey); const stack = findStack(x, stacking); prevKey = key; - !stack && (curTime === undefined || Math.abs(x - (curTime - minTime) * scaling) > pivotAxisWidth) && groupNames.push({ type: "text", text: key.toString(), x: x, y: stack * 25, height: fontHeight, fontSize }); + if (!stack && (curTime === undefined || Math.abs(x - (curTime - minTime) * scaling) > pivotAxisWidth)) { + groupNames.push({ type: "text", text: key.toString(), x: x, y: stack * 25, height: fontHeight, fontSize, payload: undefined }); + } layoutDocsAtTime(keyDocs, key); }); - if (sortedKeys.length && curTime > sortedKeys[sortedKeys.length - 1]) { + if (sortedKeys.length && curTime !== undefined && curTime > sortedKeys[sortedKeys.length - 1]) { x = (curTime - minTime) * scaling; - groupNames.push({ type: "text", text: curTime.toString(), x: x, y: 0, zIndex: 1000, color: "orange", height: fontHeight, fontSize }); + groupNames.push({ type: "text", text: curTime.toString(), x: x, y: 0, zIndex: 1000, color: "orange", height: fontHeight, fontSize, payload: undefined }); } if (Math.ceil(maxTime - minTime) * scaling > x + 25) { - groupNames.push({ type: "text", text: Math.ceil(maxTime).toString(), x: Math.ceil(maxTime - minTime) * scaling, y: 0, height: fontHeight, fontSize }); + groupNames.push({ type: "text", text: Math.ceil(maxTime).toString(), x: Math.ceil(maxTime - minTime) * scaling, y: 0, height: fontHeight, fontSize, payload: undefined }); } const divider = { type: "div", color: "black", x: 0, y: 0, width: panelDim[0], height: 1 } as any; @@ -279,8 +282,9 @@ export function computeTimelineLayout( wid = layoutDoc._nativeHeight ? (NumCast(layoutDoc._nativeWidth) / NumCast(layoutDoc._nativeHeight)) * pivotAxisWidth : pivotAxisWidth; } docMap.set(doc, { + type: "doc", x: x, y: -Math.sqrt(stack) * pivotAxisWidth / 2 - pivotAxisWidth + (pivotAxisWidth - hgt) / 2, - zIndex: (curTime === key ? 1000 : zind++), highlight: curTime === key, width: wid / (Math.max(stack, 1)), height: hgt + zIndex: (curTime === key ? 1000 : zind++), highlight: curTime === key, width: wid / (Math.max(stack, 1)), height: hgt, payload: undefined }); stacking[stack] = x + pivotAxisWidth; }); @@ -288,10 +292,10 @@ export function computeTimelineLayout( } function normalizeResults(panelDim: number[], fontHeight: number, childPairs: { data?: Doc, layout: Doc }[], docMap: Map, - poolData: Map, viewDefsToJSX: (views: any) => ViewDefResult[], groupNames: PivotData[], minWidth: number, extras: PivotData[]) { + poolData: Map, viewDefsToJSX: (views: any) => ViewDefResult[], groupNames: ViewDefBounds[], minWidth: number, extras: ViewDefBounds[]) { - const grpEles = groupNames.map(gn => ({ x: gn.x, y: gn.y, width: gn.width, height: gn.height }) as PivotData); - const docEles = childPairs.filter(d => docMap.get(d.layout)).map(pair => docMap.get(pair.layout) as PivotData); + const grpEles = groupNames.map(gn => ({ x: gn.x, y: gn.y, width: gn.width, height: gn.height }) as ViewDefBounds); + const docEles = childPairs.filter(d => docMap.get(d.layout)).map(pair => docMap.get(pair.layout) as ViewDefBounds); const aggBounds = aggregateBounds(docEles.concat(grpEles), 0, 0); aggBounds.r = Math.max(minWidth, aggBounds.r - aggBounds.x); const wscale = panelDim[0] / (aggBounds.r - aggBounds.x); @@ -323,7 +327,8 @@ function normalizeResults(panelDim: number[], fontHeight: number, childPairs: { color: gname.color, width: gname.width === undefined ? undefined : gname.width * scale, height: Math.max(fontHeight, (gname.height || 0) * scale), - fontSize: gname.fontSize + fontSize: gname.fontSize, + payload: gname.payload })))) }; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 54c45e43a..a34779046 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -32,7 +32,7 @@ import { FormattedTextBox } from "../../nodes/FormattedTextBox"; import { pageSchema } from "../../nodes/ImageBox"; import PDFMenu from "../../pdf/PDFMenu"; import { CollectionSubView } from "../CollectionSubView"; -import { computePivotLayout, ViewDefResult, computeTimelineLayout, PoolData } from "./CollectionFreeFormLayoutEngines"; +import { computePivotLayout, ViewDefResult, computeTimelineLayout, PoolData, ViewDefBounds } from "./CollectionFreeFormLayoutEngines"; import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors"; import "./CollectionFreeFormView.scss"; import MarqueeOptionsMenu from "./MarqueeOptionsMenu"; @@ -747,11 +747,14 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { }; } - viewDefsToJSX = (views: any[]) => { + viewDefsToJSX = (views: ViewDefBounds[]) => { return !Array.isArray(views) ? [] : views.filter(ele => this.viewDefToJSX(ele)).map(ele => this.viewDefToJSX(ele)!); } - private viewDefToJSX(viewDef: any): Opt { + onViewDefDivClick = (e: React.MouseEvent, payload: any) => { + (this.props.Document.onViewDefDivClick as ScriptField)?.script.run({ this: this.props.Document, payload }); + } + private viewDefToJSX(viewDef: ViewDefBounds): Opt { const x = Cast(viewDef.x, "number"); const y = Cast(viewDef.y, "number"); const z = Cast(viewDef.z, "number"); @@ -769,15 +772,15 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { style={{ width, height, color, fontSize, transform: `translate(${x}px, ${y}px)` }}> {text}
, - bounds: { x: x!, y: y!, z, zIndex, width, height } + bounds: viewDef }; } else if (viewDef.type === "div") { const backgroundColor = Cast(viewDef.color, "string"); return [x, y].some(val => val === undefined) ? undefined : { - ele:
this.onViewDefDivClick(e, viewDef)} style={{ width, height, backgroundColor, transform: `translate(${x}px, ${y}px)` }} />, - bounds: { x: x!, y: y!, z, zIndex, width, height } + bounds: viewDef }; } } diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index be5d414a5..6c4cbba12 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -360,7 +360,7 @@ export class PresBox extends React.Component { const funcs: ContextMenuProps[] = []; funcs.push({ description: "Show as Slideshow", event: action(() => this.props.Document._slideshow = "slideshow"), icon: "asterisk" }); funcs.push({ description: "Show as Timeline", event: action(() => this.props.Document._slideshow = "timeline"), icon: "asterisk" }); - funcs.push({ description: "Show as List", event: action(() => this.props.Document._slideshow = "list"), icon: "asterisk" }); + funcs.push({ description: "Show as List", event: action(() => this.props.Document._slideshow = undefined), icon: "asterisk" }); ContextMenu.Instance.addItem({ description: "Presentation Funcs...", subitems: funcs, icon: "asterisk" }); } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 6ae02720c..92b1fb090 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -791,6 +791,21 @@ export namespace Doc { if (StrCast(doc.title).endsWith("_" + prevLayout)) doc.title = StrCast(doc.title).replace("_" + prevLayout, ""); doc.layoutKey = deiconify || "layout"; } + export function setDocFilter(container: Doc, key: string, value: any, modifiers?: string) { + const docFilters = Cast(container._docFilter, listSpec("string"), []); + for (let i = 0; i < docFilters.length; i += 3) { + if (docFilters[i] === key && docFilters[i + 1] === value) { + docFilters.splice(i, 3); + break; + } + } + if (modifiers !== undefined) { + docFilters.push(key); + docFilters.push(value); + docFilters.push(modifiers); + container._docFilter = new List(docFilters); + } + } } Scripting.addGlobal(function renameAlias(doc: any, n: any) { return StrCast(Doc.GetProto(doc).title).replace(/\([0-9]*\)/, "") + `(${n})`; }); @@ -815,18 +830,4 @@ Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: bo const docs = DocListCast(Doc.UserDoc().SelectedDocs).filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.DOCUMENT && d.type !== DocumentType.KVP && (!excludeCollections || !Cast(d.data, listSpec(Doc), null))); return docs.length ? new List(docs) : prevValue; }); -Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers?: string) { - const docFilters = Cast(container._docFilter, listSpec("string"), []); - for (let i = 0; i < docFilters.length; i += 3) { - if (docFilters[i] === key && docFilters[i + 1] === value) { - docFilters.splice(i, 3); - break; - } - } - if (modifiers !== undefined) { - docFilters.push(key); - docFilters.push(value); - docFilters.push(modifiers); - container._docFilter = new List(docFilters); - } -}); \ No newline at end of file +Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers?: string) { Doc.setDocFilter(container, key, value, modifiers); }); \ No newline at end of file diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index 3495a934d..45ec676b2 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -101,7 +101,7 @@ export function makeEditable() { } let layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox", - "LODdisable", "dropAction", "chromeStatus", "viewType", "gridGap", "xMargin", "yMargin", "autoHeight"]; + "LODdisable", "chromeStatus", "viewType", "gridGap", "xMargin", "yMargin", "autoHeight"]; export function setter(target: any, in_prop: string | symbol | number, value: any, receiver: any): boolean { let prop = in_prop; if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" && -- cgit v1.2.3-70-g09d2 From d845002f60115fdb988b6fc02420fdb25b19c522 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 7 Feb 2020 13:52:13 -0500 Subject: fixed stacking layouts. fixed templates to copy cached expanded templates when docs are aliased --- .../views/collections/CollectionDockingView.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 23 ++++++++++++---------- src/new_fields/Doc.ts | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 2478aaecd..cb413b3e3 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -469,7 +469,7 @@ export class CollectionDockingView extends React.Component diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index e04f4e8a6..9e8600193 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -11,7 +11,6 @@ import { listSpec } from "../../../new_fields/Schema"; import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { BoolCast, Cast, NumCast, StrCast, ScriptCast } from "../../../new_fields/Types"; import { emptyFunction, Utils } from "../../../Utils"; -import { DocumentType } from "../../documents/DocumentTypes"; import { DragManager } from "../../util/DragManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; @@ -40,7 +39,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @computed get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); } @computed get sectionFilter() { return StrCast(this.props.Document.sectionFilter); } @computed get filteredChildren() { return this.childLayoutPairs.filter(pair => pair.layout instanceof Doc && !pair.layout.isMinimized).map(pair => pair.layout); } - @computed get xMargin() { return NumCast(this.props.Document._xMargin, 0); }// 2 * this.gridGap); } + @computed get xMargin() { return NumCast(this.props.Document._xMargin, 2 * this.gridGap); } @computed get yMargin() { return Math.max(this.props.Document.showTitle && !this.props.Document.showTitleHover ? 30 : 0, NumCast(this.props.Document._yMargin, 0)); } // 2 * this.gridGap)); } @computed get gridGap() { return NumCast(this.props.Document._gridGap, 10); } @computed get isStackingView() { return BoolCast(this.props.Document.singleColumn, true); } @@ -56,7 +55,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { this._docXfs.length = 0; return docs.map((d, i) => { const height = () => this.getDocHeight(d); - const width = () => (this.widthScale && !columns ? this.widthScale : 1) * Math.min(d._nativeWidth && !d.ignoreAspect && !this.props.Document.fillColumn ? d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); + const width = () => this.widthScale * Math.min(d._nativeWidth && !d.ignoreAspect && !this.props.Document.fillColumn ? d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); const dref = React.createRef(); const dxf = () => this.getDocTransform(d, dref.current!); this._docXfs.push({ dxf: dxf, width: width, height: height }); @@ -377,11 +376,15 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } return sections.map(section => this.isStackingView ? this.sectionStacking(section[0], section[1]) : this.sectionMasonry(section[0], section[1])); } - @computed get heightScale() { - return Math.min(this.props.Document[WidthSym]() / this.props.PanelWidth(), this.props.Document[HeightSym]() / this.props.PanelHeight()); + @computed get contentScale() { + const heightExtra = this.heightPercent > 1 ? this.heightPercent : 1; + return Math.max(this.props.Document[WidthSym]() / this.props.PanelWidth(), heightExtra * this.props.Document[HeightSym]() / this.props.PanelHeight()); } @computed get widthScale() { - return StrCast(this.props.Document.title).includes("slide") || true ? this.heightScale : undefined; + return this.heightPercent < 1 ? Math.max(1, this.contentScale) : 1; + } + @computed get heightPercent() { + return this.props.PanelHeight() / this.layoutDoc[HeightSym](); } render() { TraceMobx(); @@ -396,10 +399,10 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { ref={this.createRef} style={{ overflowY: this.props.active() ? "auto" : "hidden", - transform: `scale(${Math.min(1, this.props.PanelHeight() / this.layoutDoc[HeightSym]())})`, - height: `${Math.max(100, 100 * this.heightScale)}%`, - width: this.widthScale ? `${Math.max(100, 100 * this.widthScale)}%` : undefined, - transformOrigin: this.widthScale ? "top left" : "top", + transform: `scale(${Math.min(1, this.heightPercent)})`, + height: `${100 * Math.max(1, this.contentScale)}%`, + width: `${100 * this.widthScale}%`, + transformOrigin: "top left", }} onScroll={action((e: React.UIEvent) => this._scroll = e.currentTarget.scrollTop)} onDrop={this.onDrop.bind(this)} diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 92b1fb090..1b11c0f7f 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -544,7 +544,7 @@ export namespace Doc { } else if (cfield instanceof ComputedField) { copy[key] = ComputedField.MakeFunction(cfield.script.originalScript); } else if (field instanceof ObjectField) { - copy[key] = ObjectField.MakeCopy(field); + copy[key] = key.includes("layout[") && doc[key] instanceof Doc && false ? Doc.MakeCopy(doc[key] as Doc, false) : ObjectField.MakeCopy(field); } else if (field instanceof Promise) { debugger; //This shouldn't happend... } else { -- cgit v1.2.3-70-g09d2 From 688f54be8be328d733e05b0781aa8908305e14fa Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 7 Feb 2020 13:53:34 -0500 Subject: from last --- src/new_fields/Doc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/new_fields') diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 1b11c0f7f..529634990 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -544,7 +544,7 @@ export namespace Doc { } else if (cfield instanceof ComputedField) { copy[key] = ComputedField.MakeFunction(cfield.script.originalScript); } else if (field instanceof ObjectField) { - copy[key] = key.includes("layout[") && doc[key] instanceof Doc && false ? Doc.MakeCopy(doc[key] as Doc, false) : ObjectField.MakeCopy(field); + copy[key] = key.includes("layout[") && doc[key] instanceof Doc ? Doc.MakeCopy(doc[key] as Doc, false) : ObjectField.MakeCopy(field); } else if (field instanceof Promise) { debugger; //This shouldn't happend... } else { -- cgit v1.2.3-70-g09d2