From bf94b54dba511bb4badb0ffcb9f017dc9a81942e Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Fri, 15 May 2020 20:13:20 -0700 Subject: branch setup --- .../collections/CollectionCarousel3DView.scss | 68 +++++++++++ .../views/collections/CollectionCarousel3DView.tsx | 125 +++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 src/client/views/collections/CollectionCarousel3DView.scss create mode 100644 src/client/views/collections/CollectionCarousel3DView.tsx (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss new file mode 100644 index 000000000..2142eca39 --- /dev/null +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -0,0 +1,68 @@ +.collectionCarouselView-outer { + background: white; + height: 100%; + + .collectionCarouselView-center-container { + width: 70%; + margin: auto; + overflow: hidden; //fix ContentFittingView position!! + + .collectionCarouselView-caption { + height: 50; + display: inline-block; + width: 100%; + margin: auto; + } + + .collectionCarouselView-image { + height: calc(100% - 50px); + width: 70%; + display: inline-block; + user-select: none; + } + } + + .collectionCarouselView-prev { + position: absolute; + height: 50%; + width: 50%; + background-color: lightgrey; + left: 0; + top: 25%; + } + + .collectionCarouselView-next { + position: absolute; + height: 50%; + width: 50%; + background-color: lightgrey; + right: 0; + top: 25%; + } +} + +.carouselView-back, +.carouselView-fwd { + position: absolute; + display: flex; + top: 50%; + width: 30; + height: 30; + align-items: center; + border-radius: 5px; + justify-content: center; + background: rgba(255, 255, 255, 0.46); +} + +.carouselView-fwd { + right: 0; +} + +.carouselView-back { + left: 0; +} + +.carouselView-back:hover, +.carouselView-fwd:hover { + background: lightgray; +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx new file mode 100644 index 000000000..4de35a978 --- /dev/null +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -0,0 +1,125 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { observable, computed } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { documentSchema } from '../../../new_fields/documentSchemas'; +import { makeInterface } from '../../../new_fields/Schema'; +import { NumCast, StrCast } from '../../../new_fields/Types'; +import { DragManager } from '../../util/DragManager'; +import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView'; +import "./CollectionCarousel3DView.scss"; +import { CollectionSubView } from './CollectionSubView'; +import { faCaretLeft, faCaretRight } from '@fortawesome/free-solid-svg-icons'; +import { Doc } from '../../../new_fields/Doc'; +import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; +import { ContextMenu } from '../ContextMenu'; +import { ObjectField } from '../../../new_fields/ObjectField'; + +type Carousel3DDocument = makeInterface<[typeof documentSchema,]>; +const Carousel3DDocument = makeInterface(documentSchema); + +@observer +export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocument) { + private _dropDisposer?: DragManager.DragDropDisposer; + + componentWillUnmount() { this._dropDisposer?.(); } + + protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view + this._dropDisposer?.(); + if (ele) { + this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc); + } + } + + advance = (e: React.MouseEvent) => { + e.stopPropagation(); + this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + 1) % this.childLayoutPairs.length; + } + goback = (e: React.MouseEvent) => { + e.stopPropagation(); + this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; + } + + panelHeight = () => this.props.PanelHeight() - 50; + @computed get content() { + const index = NumCast(this.layoutDoc._itemIndex); + return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) : + <> +
+
+
+
+ +
+
+ +
+
+ ; + } + @computed get buttons() { + return <> +
+ +
+
+ +
+ ; + } + + + onContextMenu = (e: React.MouseEvent): void => { + // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout + if (!e.isPropagationStopped()) { + ContextMenu.Instance.addItem({ + description: "Make Hero Image", event: () => { + const index = NumCast(this.layoutDoc._itemIndex); + (this.dataDoc || Doc.GetProto(this.props.Document)).hero = ObjectField.MakeCopy(this.childLayoutPairs[index].layout.data as ObjectField); + }, icon: "plus" + }); + } + } + _downX = 0; + _downY = 0; + onPointerDown = (e: React.PointerEvent) => { + this._downX = e.clientX; + this._downY = e.clientY; + console.log("CAROUSEL down"); + document.addEventListener("pointerup", this.onpointerup); + } + private _lastTap: number = 0; + private _doubleTap = false; + onpointerup = (e: PointerEvent) => { + console.log("CAROUSEL up"); + this._doubleTap = (Date.now() - this._lastTap < 300 && e.button === 0 && Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2); + this._lastTap = Date.now(); + } + + onClick = (e: React.MouseEvent) => { + if (this._doubleTap) { + e.stopPropagation(); + this.props.Document.isLightboxOpen = true; + } + } + + render() { + return
+ {this.content} + {this.props.Document._chromeStatus !== "replaced" ? this.buttons : (null)} +
; + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 3c6e288fa031e8871618170d3b8d6db66dd3c66b Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Sun, 17 May 2020 23:38:58 -0700 Subject: add 3D carousel view to code base --- src/client/documents/Documents.ts | 4 ++ .../views/collections/CollectionCarousel3DView.tsx | 60 ++++++++++------------ src/client/views/collections/CollectionView.tsx | 4 ++ .../views/collections/CollectionViewChromes.tsx | 1 + 4 files changed, 35 insertions(+), 34 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 18a0b43ff..47e13c8e2 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -670,6 +670,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Carousel }); } + export function Carousel3DDocument(documents: Array, options: DocumentOptions) { + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Carousel3D }); + } + export function SchemaDocument(schemaColumns: SchemaHeaderField[], documents: Array, options: DocumentOptions) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List(schemaColumns), ...options, _viewType: CollectionViewType.Schema }); } diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 4de35a978..8839658d6 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -2,21 +2,20 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { observable, computed } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { documentSchema } from '../../../new_fields/documentSchemas'; -import { makeInterface } from '../../../new_fields/Schema'; -import { NumCast, StrCast } from '../../../new_fields/Types'; +import { documentSchema, collectionSchema } from '../../../fields/documentSchemas'; +import { makeInterface } from '../../../fields/Schema'; +import { NumCast, StrCast, ScriptCast, Cast } from '../../../fields/Types'; import { DragManager } from '../../util/DragManager'; import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView'; import "./CollectionCarousel3DView.scss"; import { CollectionSubView } from './CollectionSubView'; -import { faCaretLeft, faCaretRight } from '@fortawesome/free-solid-svg-icons'; -import { Doc } from '../../../new_fields/Doc'; -import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; +import { Doc } from '../../../fields/Doc'; import { ContextMenu } from '../ContextMenu'; -import { ObjectField } from '../../../new_fields/ObjectField'; +import { ObjectField } from '../../../fields/ObjectField'; +import { returnFalse } from '../../../Utils'; -type Carousel3DDocument = makeInterface<[typeof documentSchema,]>; -const Carousel3DDocument = makeInterface(documentSchema); +type Carousel3DDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>; +const Carousel3DDocument = makeInterface(documentSchema, collectionSchema); @observer export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocument) { @@ -39,44 +38,37 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume e.stopPropagation(); this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; } - panelHeight = () => this.props.PanelHeight() - 50; @computed get content() { const index = NumCast(this.layoutDoc._itemIndex); return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) : <> -
-
-
-
- -
-
- -
+
+
+
+
; } @computed get buttons() { return <>
- +
- +
; } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 3b2e5e4fc..8d6866632 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -21,6 +21,7 @@ import { FieldView, FieldViewProps } from '../nodes/FieldView'; import { ScriptBox } from '../ScriptBox'; import { Touchable } from '../Touchable'; import { CollectionCarouselView } from './CollectionCarouselView'; +import { CollectionCarousel3DView } from './CollectionCarousel3DView'; import { CollectionDockingView } from "./CollectionDockingView"; import { AddCustomFreeFormLayout } from './collectionFreeForm/CollectionFreeFormLayoutEngines'; import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; @@ -63,6 +64,7 @@ export enum CollectionViewType { Multirow = "multirow", Time = "time", Carousel = "carousel", + Carousel3D = "3D carousel", Linear = "linear", Staff = "staff", Map = "map", @@ -183,6 +185,7 @@ export class CollectionView extends Touchable); } case CollectionViewType.Pile: { return (); } case CollectionViewType.Carousel: { return (); } + case CollectionViewType.Carousel3D: { return (); } case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } case CollectionViewType.Time: { return (); } @@ -222,6 +225,7 @@ export class CollectionView extends Touchable func(CollectionViewType.Multirow), icon: "columns" }); subItems.push({ description: "Masonry", event: () => func(CollectionViewType.Masonry), icon: "columns" }); subItems.push({ description: "Carousel", event: () => func(CollectionViewType.Carousel), icon: "columns" }); + subItems.push({ description: "3D Carousel", event: () => func(CollectionViewType.Carousel3D), icon: "columns" }); subItems.push({ description: "Pivot/Time", event: () => func(CollectionViewType.Time), icon: "columns" }); subItems.push({ description: "Map", event: () => func(CollectionViewType.Map), icon: "globe-americas" }); if (addExtras && this.props.Document._viewType === CollectionViewType.Freeform) { diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 5dc0b09ac..53860d8ad 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -75,6 +75,7 @@ export class CollectionViewBaseChrome extends React.Component Date: Mon, 18 May 2020 00:33:19 -0700 Subject: rough 3D layout, add prev/next images --- .../collections/CollectionCarousel3DView.scss | 27 ++++++--------- .../views/collections/CollectionCarousel3DView.tsx | 39 +++++++++++++++++++--- 2 files changed, 46 insertions(+), 20 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index 2142eca39..ee92cde4c 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -2,27 +2,21 @@ background: white; height: 100%; - .collectionCarouselView-center-container { + .collectionCarouselView-image { + overflow: hidden; //fix ContentFittingView size + position: absolute; + height: 100%; width: 70%; + top: 0; + left: 0; + right: 0; + bottom: 0; margin: auto; - overflow: hidden; //fix ContentFittingView position!! - - .collectionCarouselView-caption { - height: 50; - display: inline-block; - width: 100%; - margin: auto; - } - - .collectionCarouselView-image { - height: calc(100% - 50px); - width: 70%; - display: inline-block; - user-select: none; - } + user-select: none; } .collectionCarouselView-prev { + overflow: hidden; position: absolute; height: 50%; width: 50%; @@ -32,6 +26,7 @@ } .collectionCarouselView-next { + overflow: hidden; position: absolute; height: 50%; width: 50%; diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 8839658d6..4452ceb6b 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -34,17 +34,48 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume e.stopPropagation(); this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + 1) % this.childLayoutPairs.length; } + goback = (e: React.MouseEvent) => { e.stopPropagation(); this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; } - panelHeight = () => this.props.PanelHeight() - 50; + @computed get content() { const index = NumCast(this.layoutDoc._itemIndex); + const prevIndex = (index - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; + const nextIndex = (index + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) : <> -
-
+
+ +
+
+ +
Date: Mon, 18 May 2020 00:59:32 -0700 Subject: fit ContentFittingViews into main/prev/next panels --- src/client/views/collections/CollectionCarousel3DView.scss | 11 +++-------- src/client/views/collections/CollectionCarousel3DView.tsx | 11 +++++++++-- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index ee92cde4c..0f2d20242 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -3,10 +3,9 @@ height: 100%; .collectionCarouselView-image { - overflow: hidden; //fix ContentFittingView size position: absolute; height: 100%; - width: 70%; + width: 60%; top: 0; left: 0; right: 0; @@ -16,21 +15,17 @@ } .collectionCarouselView-prev { - overflow: hidden; position: absolute; height: 50%; - width: 50%; - background-color: lightgrey; + width: 30%; left: 0; top: 25%; } .collectionCarouselView-next { - overflow: hidden; position: absolute; height: 50%; - width: 50%; - background-color: lightgrey; + width: 30%; right: 0; top: 25%; } diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 4452ceb6b..c2ed39cc9 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -40,6 +40,10 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; } + mainPanelWidth = () => this.props.PanelWidth() * 0.6; + sidePanelWidth = () => this.props.PanelWidth() * 0.3; + sidePanelHeight = () => this.props.PanelHeight() * 0.5; + @computed get content() { const index = NumCast(this.layoutDoc._itemIndex); const prevIndex = (index - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; @@ -55,7 +59,8 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume LayoutTemplateString={this.props.ChildLayoutString} Document={this.childLayoutPairs[prevIndex].layout} DataDoc={this.childLayoutPairs[prevIndex].data} - PanelHeight={this.props.PanelHeight} + PanelWidth={this.sidePanelWidth} + PanelHeight={this.sidePanelHeight} ScreenToLocalTransform={this.props.ScreenToLocalTransform} bringToFront={returnFalse} parentActive={this.props.active} @@ -70,7 +75,8 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume LayoutTemplateString={this.props.ChildLayoutString} Document={this.childLayoutPairs[nextIndex].layout} DataDoc={this.childLayoutPairs[nextIndex].data} - PanelHeight={this.props.PanelHeight} + PanelWidth={this.sidePanelWidth} + PanelHeight={this.sidePanelHeight} ScreenToLocalTransform={this.props.ScreenToLocalTransform} bringToFront={returnFalse} parentActive={this.props.active} @@ -85,6 +91,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume LayoutTemplateString={this.props.ChildLayoutString} Document={this.childLayoutPairs[index].layout} DataDoc={this.childLayoutPairs[index].data} + PanelWidth={this.mainPanelWidth} PanelHeight={this.props.PanelHeight} ScreenToLocalTransform={this.props.ScreenToLocalTransform} bringToFront={returnFalse} -- cgit v1.2.3-70-g09d2 From 8d4b00c3e2b62b1e83997f60e7df249e84766bdc Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Wed, 20 May 2020 00:44:27 -0700 Subject: basic image captioning --- .../collections/CollectionCarousel3DView.scss | 7 +++++++ .../views/collections/CollectionCarousel3DView.tsx | 23 ++++++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index 0f2d20242..c1260f899 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -2,6 +2,13 @@ background: white; height: 100%; + .test-button { + position: absolute; + top: 0; + left: 0; + z-index: 999; + } + .collectionCarouselView-image { position: absolute; height: 100%; diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index c2ed39cc9..d957b8749 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -13,6 +13,7 @@ import { Doc } from '../../../fields/Doc'; import { ContextMenu } from '../ContextMenu'; import { ObjectField } from '../../../fields/ObjectField'; import { returnFalse } from '../../../Utils'; +import { ScriptField } from '../../../fields/ScriptField'; type Carousel3DDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>; const Carousel3DDocument = makeInterface(documentSchema, collectionSchema); @@ -40,6 +41,18 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; } + addCaption = (e: React.MouseEvent) => { + e.stopPropagation(); + const index = NumCast(this.layoutDoc._itemIndex); + this.childLayoutPairs[index].layout._showCaption = "caption"; + } + + // @computed get gobackScript() { + // return ScriptField.MakeScript("this.layoutDoc._itemIndex = index", + // { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name, firstDoc: Doc.name }, + // { index: (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length }); + // } + mainPanelWidth = () => this.props.PanelWidth() * 0.6; sidePanelWidth = () => this.props.PanelWidth() * 0.3; sidePanelHeight = () => this.props.PanelHeight() * 0.5; @@ -50,10 +63,12 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume const nextIndex = (index + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) : <> -
+ +
-
+
Date: Wed, 20 May 2020 02:14:58 -0700 Subject: added 3D perspective --- src/client/views/collections/CollectionCarousel3DView.scss | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index c1260f899..7ae9dd2c6 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -1,6 +1,7 @@ .collectionCarouselView-outer { background: white; height: 100%; + perspective: 30em; .test-button { position: absolute; @@ -12,7 +13,7 @@ .collectionCarouselView-image { position: absolute; height: 100%; - width: 60%; + width: 50%; top: 0; left: 0; right: 0; @@ -24,17 +25,19 @@ .collectionCarouselView-prev { position: absolute; height: 50%; - width: 30%; + width: 25%; left: 0; top: 25%; + transform: rotateY(-20deg) } .collectionCarouselView-next { position: absolute; height: 50%; - width: 30%; + width: 25%; right: 0; top: 25%; + transform: rotateY(20deg) } } -- cgit v1.2.3-70-g09d2 From 210ce6f29e1674d4e2af893a9c5c995506e0c4b7 Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Wed, 20 May 2020 23:04:09 -0700 Subject: eliminated prev/next buttons, add caption by clicking on image --- src/client/views/.DS_Store | Bin 6148 -> 6148 bytes .../collections/CollectionCarousel3DView.scss | 6 +++ .../views/collections/CollectionCarousel3DView.tsx | 57 ++++++++------------- 3 files changed, 26 insertions(+), 37 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/.DS_Store b/src/client/views/.DS_Store index 5008ddfcf..3717a2923 100644 Binary files a/src/client/views/.DS_Store and b/src/client/views/.DS_Store differ diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index 7ae9dd2c6..25d1df2f4 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -20,6 +20,8 @@ bottom: 0; margin: auto; user-select: none; + transition: transform 0.5s; + transform-style: preserve-3d; } .collectionCarouselView-prev { @@ -65,4 +67,8 @@ .carouselView-back:hover, .carouselView-fwd:hover { background: lightgray; +} + +.carouselView-fwd:hover~.collectionCarouselView-image { + transform: translateX(50px) } \ No newline at end of file diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index d957b8749..fd1785641 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -1,4 +1,3 @@ -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { observable, computed } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; @@ -31,28 +30,14 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume } } - advance = (e: React.MouseEvent) => { - e.stopPropagation(); - this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + 1) % this.childLayoutPairs.length; - } - - goback = (e: React.MouseEvent) => { - e.stopPropagation(); - this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; - } - addCaption = (e: React.MouseEvent) => { e.stopPropagation(); const index = NumCast(this.layoutDoc._itemIndex); - this.childLayoutPairs[index].layout._showCaption = "caption"; + if (this.childLayoutPairs[index].layout._showCaption !== "caption") { + this.childLayoutPairs[index].layout._showCaption = "caption"; + } } - // @computed get gobackScript() { - // return ScriptField.MakeScript("this.layoutDoc._itemIndex = index", - // { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name, firstDoc: Doc.name }, - // { index: (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length }); - // } - mainPanelWidth = () => this.props.PanelWidth() * 0.6; sidePanelWidth = () => this.props.PanelWidth() * 0.3; sidePanelHeight = () => this.props.PanelHeight() * 0.5; @@ -63,12 +48,14 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume const nextIndex = (index + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) : <> - -
+
-
+
; } - @computed get buttons() { - return <> -
- -
-
- -
- ; - } - onContextMenu = (e: React.MouseEvent): void => { // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout @@ -164,7 +148,6 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume render() { return
{this.content} - {this.props.Document._chromeStatus !== "replaced" ? this.buttons : (null)}
; } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 07566108db7da0a8e30dcb4c6b884482b57394a1 Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Wed, 20 May 2020 23:15:06 -0700 Subject: code clean up --- .../collections/CollectionCarousel3DView.scss | 37 ---------------------- .../views/collections/CollectionCarousel3DView.tsx | 25 +++++---------- 2 files changed, 8 insertions(+), 54 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index 25d1df2f4..7da007ef3 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -3,13 +3,6 @@ height: 100%; perspective: 30em; - .test-button { - position: absolute; - top: 0; - left: 0; - z-index: 999; - } - .collectionCarouselView-image { position: absolute; height: 100%; @@ -41,34 +34,4 @@ top: 25%; transform: rotateY(20deg) } -} - -.carouselView-back, -.carouselView-fwd { - position: absolute; - display: flex; - top: 50%; - width: 30; - height: 30; - align-items: center; - border-radius: 5px; - justify-content: center; - background: rgba(255, 255, 255, 0.46); -} - -.carouselView-fwd { - right: 0; -} - -.carouselView-back { - left: 0; -} - -.carouselView-back:hover, -.carouselView-fwd:hover { - background: lightgray; -} - -.carouselView-fwd:hover~.collectionCarouselView-image { - transform: translateX(50px) } \ No newline at end of file diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index fd1785641..649ca4eba 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -30,18 +30,17 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume } } - addCaption = (e: React.MouseEvent) => { - e.stopPropagation(); - const index = NumCast(this.layoutDoc._itemIndex); - if (this.childLayoutPairs[index].layout._showCaption !== "caption") { - this.childLayoutPairs[index].layout._showCaption = "caption"; - } + @computed get changeIndexScript() { + return ScriptField.MakeScript( + "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)", + { fieldKey: String.name, collectionLayoutDoc: Doc.name }, + { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc } + ); } mainPanelWidth = () => this.props.PanelWidth() * 0.6; sidePanelWidth = () => this.props.PanelWidth() * 0.3; sidePanelHeight = () => this.props.PanelHeight() * 0.5; - @computed get content() { const index = NumCast(this.layoutDoc._itemIndex); const prevIndex = (index - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; @@ -51,11 +50,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
Date: Fri, 22 May 2020 17:08:16 -0700 Subject: styling changes --- package-lock.json | 44 ++++++++++++++++------ .../collections/CollectionCarousel3DView.scss | 10 ++--- .../views/collections/CollectionCarousel3DView.tsx | 43 ++++++++++----------- 3 files changed, 59 insertions(+), 38 deletions(-) (limited to 'src/client/views/collections') diff --git a/package-lock.json b/package-lock.json index 6532f27ec..23d9fc590 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2702,7 +2702,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -2720,11 +2721,13 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2737,15 +2740,18 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -2848,7 +2854,8 @@ }, "inherits": { "version": "2.0.4", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -2858,6 +2865,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2870,17 +2878,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "1.2.5", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.9.0", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -2897,6 +2908,7 @@ "mkdirp": { "version": "0.5.3", "bundled": true, + "optional": true, "requires": { "minimist": "^1.2.5" } @@ -2952,7 +2964,8 @@ }, "npm-normalize-package-bin": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "npm-packlist": { "version": "1.4.8", @@ -2977,7 +2990,8 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -2987,6 +3001,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -3055,7 +3070,8 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -3085,6 +3101,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3102,6 +3119,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3140,11 +3158,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.1.1", - "bundled": true + "bundled": true, + "optional": true } } } diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index 7da007ef3..df64d8cbe 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -1,11 +1,11 @@ .collectionCarouselView-outer { background: white; height: 100%; - perspective: 30em; + perspective: 40em; - .collectionCarouselView-image { + .collectionCarouselView-center { position: absolute; - height: 100%; + height: 80%; width: 50%; top: 0; left: 0; @@ -23,7 +23,7 @@ width: 25%; left: 0; top: 25%; - transform: rotateY(-20deg) + transform: rotateY(-20deg); } .collectionCarouselView-next { @@ -32,6 +32,6 @@ width: 25%; right: 0; top: 25%; - transform: rotateY(20deg) + transform: rotateY(20deg); } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 649ca4eba..0e704a1a0 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -38,8 +38,9 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume ); } - mainPanelWidth = () => this.props.PanelWidth() * 0.6; - sidePanelWidth = () => this.props.PanelWidth() * 0.3; + mainPanelWidth = () => this.props.PanelWidth() * 0.5; + mainPanelHeight = () => this.props.PanelHeight() * 0.8; + sidePanelWidth = () => this.props.PanelWidth() * 0.25; sidePanelHeight = () => this.props.PanelHeight() * 0.5; @computed get content() { const index = NumCast(this.layoutDoc._itemIndex); @@ -47,31 +48,35 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume const nextIndex = (index + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) : <> -
+
-
+
-
+
Date: Sat, 23 May 2020 23:57:10 -0700 Subject: reorganized & condensed render function --- .../views/collections/CollectionCarousel3DView.tsx | 87 +++++++++------------- 1 file changed, 37 insertions(+), 50 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 0e704a1a0..f95645a6c 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -43,62 +43,49 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume sidePanelWidth = () => this.props.PanelWidth() * 0.25; sidePanelHeight = () => this.props.PanelHeight() * 0.5; @computed get content() { - const index = NumCast(this.layoutDoc._itemIndex); - const prevIndex = (index - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; - const nextIndex = (index + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; - return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) : + const centerIndex = NumCast(this.layoutDoc._itemIndex); + const prevIndex = (centerIndex - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; + const nextIndex = (centerIndex + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; + + const displayDoc = (index: number, onClickAction: ScriptField | undefined, width: () => number, height: () => number) => { + return ; + }; + + const showCaptionScript = ScriptField.MakeScript( + "child._showCaption = 'caption'", + { child: Doc.name }, + { child: this.childLayoutPairs[centerIndex].layout } + ); + + const changeIndexScript = ScriptField.MakeScript( + "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)", + { fieldKey: String.name, collectionLayoutDoc: Doc.name }, + { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc } + ); + + return !(this.childLayoutPairs?.[centerIndex]?.layout instanceof Doc) ? (null) : <>
- + {displayDoc(centerIndex, showCaptionScript, this.mainPanelWidth, this.mainPanelHeight)}
- + {displayDoc(prevIndex, changeIndexScript, this.sidePanelWidth, this.sidePanelHeight)}
- + {displayDoc(nextIndex, changeIndexScript, this.sidePanelWidth, this.sidePanelHeight)}
; } -- cgit v1.2.3-70-g09d2 From 481ce09aa523de3792295e766c1bc4c80982bf53 Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Tue, 26 May 2020 23:31:44 -0700 Subject: re-structured 3D carousel --- .../collections/CollectionCarousel3DView.scss | 46 +++------ .../views/collections/CollectionCarousel3DView.tsx | 106 +++++++++++++-------- 2 files changed, 80 insertions(+), 72 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index df64d8cbe..d1504dd12 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -1,37 +1,21 @@ .collectionCarouselView-outer { - background: white; height: 100%; - perspective: 40em; + position: relative; + background-color: white; +} - .collectionCarouselView-center { - position: absolute; - height: 80%; - width: 50%; - top: 0; - left: 0; - right: 0; - bottom: 0; - margin: auto; - user-select: none; - transition: transform 0.5s; - transform-style: preserve-3d; - } - - .collectionCarouselView-prev { - position: absolute; - height: 50%; - width: 25%; - left: 0; - top: 25%; - transform: rotateY(-20deg); - } +.carousel-wrapper { + display: flex; + position: absolute; + top: 10px; + align-items: center; + transition: transform 0.75s cubic-bezier(0.455, 0.03, 0.515, 0.955); - .collectionCarouselView-next { - position: absolute; - height: 50%; - width: 25%; - right: 0; - top: 25%; - transform: rotateY(20deg); + .collectionCarouselView-item { + flex: 1; + transition: opacity 0.5s linear; + transition: transform 0.5s linear; + transition: height 0.5s linear; + transition: width 0.5s linear; } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index f95645a6c..9665e23ff 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -13,6 +13,7 @@ import { ContextMenu } from '../ContextMenu'; import { ObjectField } from '../../../fields/ObjectField'; import { returnFalse } from '../../../Utils'; import { ScriptField } from '../../../fields/ScriptField'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; type Carousel3DDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>; const Carousel3DDocument = makeInterface(documentSchema, collectionSchema); @@ -30,32 +31,36 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume } } - @computed get changeIndexScript() { - return ScriptField.MakeScript( - "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)", - { fieldKey: String.name, collectionLayoutDoc: Doc.name }, - { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc } - ); - } - mainPanelWidth = () => this.props.PanelWidth() * 0.5; - mainPanelHeight = () => this.props.PanelHeight() * 0.8; + mainPanelHeight = () => this.props.PanelHeight() * 0.9; sidePanelWidth = () => this.props.PanelWidth() * 0.25; sidePanelHeight = () => this.props.PanelHeight() * 0.5; + @computed get content() { - const centerIndex = NumCast(this.layoutDoc._itemIndex); - const prevIndex = (centerIndex - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; - const nextIndex = (centerIndex + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; + const currentIndex = NumCast(this.layoutDoc._itemIndex); + + + const displayDoc = (childPair: { layout: Doc, data: Doc }, width: () => number, height: () => number) => { + const showCaptionScript = ScriptField.MakeScript( + "child._showCaption = 'caption'", + { child: Doc.name }, + { child: childPair.layout } + ); + + // const changeIndexScript = ScriptField.MakeScript( + // "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)", + // { fieldKey: String.name, collectionLayoutDoc: Doc.name }, + // { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc } + // ); - const displayDoc = (index: number, onClickAction: ScriptField | undefined, width: () => number, height: () => number) => { return ; }; - const showCaptionScript = ScriptField.MakeScript( - "child._showCaption = 'caption'", - { child: Doc.name }, - { child: this.childLayoutPairs[centerIndex].layout } - ); - - const changeIndexScript = ScriptField.MakeScript( - "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)", - { fieldKey: String.name, collectionLayoutDoc: Doc.name }, - { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc } - ); - - return !(this.childLayoutPairs?.[centerIndex]?.layout instanceof Doc) ? (null) : - <> -
- {displayDoc(centerIndex, showCaptionScript, this.mainPanelWidth, this.mainPanelHeight)} -
-
- {displayDoc(prevIndex, changeIndexScript, this.sidePanelWidth, this.sidePanelHeight)} -
-
- {displayDoc(nextIndex, changeIndexScript, this.sidePanelWidth, this.sidePanelHeight)} -
- ; + return ( + this.childLayoutPairs.map((child, index) => { + if (index === currentIndex) { + return ( +
+ {displayDoc(child, this.mainPanelWidth, this.mainPanelHeight)} +
); + } else { + return ( +
+ {displayDoc(child, this.sidePanelWidth, this.sidePanelHeight)} +
); + } + })); + } + + advance = (e: React.MouseEvent) => { + e.stopPropagation(); + this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + 1) % this.childLayoutPairs.length; + } + goback = (e: React.MouseEvent) => { + e.stopPropagation(); + this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; } onContextMenu = (e: React.MouseEvent): void => { @@ -124,9 +130,27 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume } } + @computed get buttons() { + return <> +
+ +
+
+ +
+ ; + } + render() { + const index = NumCast(this.layoutDoc._itemIndex); + const offset = (index - 1) * (this.mainPanelWidth() - this.sidePanelWidth()) / this.childLayoutPairs.length; + const translateX = (1 - index) / this.childLayoutPairs.length * 100; + return
- {this.content} +
+ {this.content} +
+ {this.props.Document._chromeStatus !== "replaced" ? this.buttons : (null)}
; } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 04e285a5b65d0b66c0792fafcd97d7f80e05b7f4 Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Tue, 26 May 2020 23:33:31 -0700 Subject: added dots bar for navigating through carousel --- .../collections/CollectionCarousel3DView.scss | 23 ++++++++++++++++++++++ .../views/collections/CollectionCarousel3DView.tsx | 10 ++++++++++ 2 files changed, 33 insertions(+) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index d1504dd12..47ee8ef53 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -18,4 +18,27 @@ transition: height 0.5s linear; transition: width 0.5s linear; } +} + +.dot-bar { + display: flex; + position: absolute; + justify-content: center; + bottom: 5%; + width: 100%; + + .dot, + .dot-active { + height: 15px; + width: 15px; + border-radius: 50%; + margin: 3px; + display: inline-block; + background-color: lightgrey; + cursor: pointer; + } + + .dot-active { + background-color: grey; + } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 9665e23ff..aefac3512 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -141,6 +141,13 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume ; } + @computed get dots() { + return (this.childLayoutPairs.map((_child, index) => { + return
this.layoutDoc._itemIndex = index} />; + })); + } + render() { const index = NumCast(this.layoutDoc._itemIndex); const offset = (index - 1) * (this.mainPanelWidth() - this.sidePanelWidth()) / this.childLayoutPairs.length; @@ -151,6 +158,9 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume {this.content}
{this.props.Document._chromeStatus !== "replaced" ? this.buttons : (null)} +
+ {this.dots} +
; } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 8de2aa4c90926ce733f0cd6021c226ab91df15ee Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Wed, 27 May 2020 01:31:59 -0700 Subject: formatting changes --- .../collections/CollectionCarousel3DView.scss | 9 ++--- .../views/collections/CollectionCarousel3DView.tsx | 38 ++++++++-------------- 2 files changed, 17 insertions(+), 30 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index 47ee8ef53..601071917 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -7,16 +7,13 @@ .carousel-wrapper { display: flex; position: absolute; - top: 10px; + top: 15%; align-items: center; - transition: transform 0.75s cubic-bezier(0.455, 0.03, 0.515, 0.955); + transition: transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955); .collectionCarouselView-item { flex: 1; - transition: opacity 0.5s linear; - transition: transform 0.5s linear; - transition: height 0.5s linear; - transition: width 0.5s linear; + transition: opacity 0.5s linear, transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955); } } diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index aefac3512..b47ce0836 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -11,9 +11,10 @@ import { CollectionSubView } from './CollectionSubView'; import { Doc } from '../../../fields/Doc'; import { ContextMenu } from '../ContextMenu'; import { ObjectField } from '../../../fields/ObjectField'; -import { returnFalse } from '../../../Utils'; +import { returnFalse, Utils } from '../../../Utils'; import { ScriptField } from '../../../fields/ScriptField'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Id } from '../../../fields/FieldSymbols'; type Carousel3DDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>; const Carousel3DDocument = makeInterface(documentSchema, collectionSchema); @@ -31,15 +32,11 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume } } - mainPanelWidth = () => this.props.PanelWidth() * 0.5; - mainPanelHeight = () => this.props.PanelHeight() * 0.9; - sidePanelWidth = () => this.props.PanelWidth() * 0.25; - sidePanelHeight = () => this.props.PanelHeight() * 0.5; - + panelWidth = () => this.props.PanelWidth() / 3; + panelHeight = () => this.props.PanelHeight() * 0.6; @computed get content() { const currentIndex = NumCast(this.layoutDoc._itemIndex); - const displayDoc = (childPair: { layout: Doc, data: Doc }, width: () => number, height: () => number) => { const showCaptionScript = ScriptField.MakeScript( "child._showCaption = 'caption'", @@ -70,20 +67,14 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume }; return ( - this.childLayoutPairs.map((child, index) => { - if (index === currentIndex) { - return ( -
- {displayDoc(child, this.mainPanelWidth, this.mainPanelHeight)} -
); - } else { - return ( -
- {displayDoc(child, this.sidePanelWidth, this.sidePanelHeight)} -
); - } + this.childLayoutPairs.map((childPair, index) => { + return ( +
+ {displayDoc(childPair, this.panelWidth, this.panelHeight)} +
); })); } @@ -143,18 +134,17 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume @computed get dots() { return (this.childLayoutPairs.map((_child, index) => { - return
this.layoutDoc._itemIndex = index} />; })); } render() { const index = NumCast(this.layoutDoc._itemIndex); - const offset = (index - 1) * (this.mainPanelWidth() - this.sidePanelWidth()) / this.childLayoutPairs.length; const translateX = (1 - index) / this.childLayoutPairs.length * 100; return
-
+
{this.content}
{this.props.Document._chromeStatus !== "replaced" ? this.buttons : (null)} -- cgit v1.2.3-70-g09d2 From 7551a05109cafd4f1aba1b717a54c0eb32209234 Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Sun, 31 May 2020 14:30:45 -0700 Subject: add hold down arrow to autoscroll functionality --- .../collections/CollectionCarousel3DView.scss | 4 +- .../views/collections/CollectionCarousel3DView.tsx | 56 +++++++++++++++++++--- 2 files changed, 51 insertions(+), 9 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index 601071917..650b76b31 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -9,11 +9,11 @@ position: absolute; top: 15%; align-items: center; - transition: transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955); + transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955); .collectionCarouselView-item { flex: 1; - transition: opacity 0.5s linear, transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955); + transition: opacity 0.3s linear, transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955); } } diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index b47ce0836..4ec5394da 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -78,13 +78,51 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume })); } - advance = (e: React.MouseEvent) => { + handleArrowClick = (e: React.MouseEvent, direction: number) => { e.stopPropagation(); - this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + 1) % this.childLayoutPairs.length; + this.rotate(direction); } - goback = (e: React.MouseEvent) => { - e.stopPropagation(); - this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length; + + rotate = (direction: number) => { + this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length; + } + + timer?: NodeJS.Timeout; + interval?: NodeJS.Timeout; + onPress = (e: React.PointerEvent, direction: number) => { + e.stopPropagation; + document.removeEventListener("pointerup", this.onRelease); + document.addEventListener("pointerup", this.onRelease); + + this.timer = setTimeout(() => { + this.startScroll(direction); + }, 1500); + } + + onRelease = () => { + if (this.timer) { + clearTimeout(this.timer); + this.timer = undefined; + } + this.stopScroll(); + } + + startScroll = (direction: number) => { + this.interval = setInterval(() => { + this.rotate(direction); + }, 500); + } + + stopScroll = () => { + if (this.timer) { + clearTimeout(this.timer); + this.timer = undefined; + } + + if (this.interval) { + clearInterval(this.interval); + this.interval = undefined; + } } onContextMenu = (e: React.MouseEvent): void => { @@ -123,10 +161,14 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume @computed get buttons() { return <> -
+
this.handleArrowClick(e, -1)} + onPointerDown={(e) => this.onPress(e, -1)}>
-
+
this.handleArrowClick(e, 1)} + onPointerDown={(e) => this.onPress(e, 1)}>
; -- cgit v1.2.3-70-g09d2 From 3a1541e1ef4277471075936aedadd4541384f470 Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Mon, 1 Jun 2020 13:26:49 -0700 Subject: cleanup --- .../collections/CollectionCarousel3DView.scss | 5 +++ .../views/collections/CollectionCarousel3DView.tsx | 47 ++++++++-------------- 2 files changed, 21 insertions(+), 31 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index 650b76b31..6c746490a 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -38,4 +38,9 @@ .dot-active { background-color: grey; } +} + +.carouselView-back, +.carouselView-forward { + cursor: pointer; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 4ec5394da..0baf44aeb 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -36,30 +36,17 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume panelHeight = () => this.props.PanelHeight() * 0.6; @computed get content() { const currentIndex = NumCast(this.layoutDoc._itemIndex); - - const displayDoc = (childPair: { layout: Doc, data: Doc }, width: () => number, height: () => number) => { - const showCaptionScript = ScriptField.MakeScript( - "child._showCaption = 'caption'", - { child: Doc.name }, - { child: childPair.layout } - ); - - // const changeIndexScript = ScriptField.MakeScript( - // "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)", - // { fieldKey: String.name, collectionLayoutDoc: Doc.name }, - // { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc } - // ); - + const displayDoc = (childPair: { layout: Doc, data: Doc }, onClickScript: ScriptField | undefined) => { return { + const showCaptionScript = ScriptField.MakeScript( + "child._showCaption = 'caption'", + { child: Doc.name }, + { child: childPair.layout } + ); + return (
- {displayDoc(childPair, this.panelWidth, this.panelHeight)} + {displayDoc(childPair, index === currentIndex ? showCaptionScript : undefined)}
); })); } handleArrowClick = (e: React.MouseEvent, direction: number) => { e.stopPropagation(); - this.rotate(direction); + this.changeSlide(direction); } - rotate = (direction: number) => { + changeSlide = (direction: number) => { this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length; } @@ -91,25 +84,17 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume interval?: NodeJS.Timeout; onPress = (e: React.PointerEvent, direction: number) => { e.stopPropagation; - document.removeEventListener("pointerup", this.onRelease); - document.addEventListener("pointerup", this.onRelease); + document.removeEventListener("pointerup", this.stopScroll); + document.addEventListener("pointerup", this.stopScroll); this.timer = setTimeout(() => { this.startScroll(direction); }, 1500); } - onRelease = () => { - if (this.timer) { - clearTimeout(this.timer); - this.timer = undefined; - } - this.stopScroll(); - } - startScroll = (direction: number) => { this.interval = setInterval(() => { - this.rotate(direction); + this.changeSlide(direction); }, 500); } -- cgit v1.2.3-70-g09d2 From 7788d70d5ae6a5ccdf7cd354c31f463fb00731a2 Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Tue, 2 Jun 2020 14:02:02 -0700 Subject: fix timeout bug, disable pointer events for items on the side --- .../collections/CollectionCarousel3DView.scss | 8 ++- .../views/collections/CollectionCarousel3DView.tsx | 61 +++++++++++----------- 2 files changed, 37 insertions(+), 32 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index 6c746490a..d00a666f8 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -11,9 +11,15 @@ align-items: center; transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955); - .collectionCarouselView-item { + .collectionCarouselView-item, + .collectionCarouselView-item-active { flex: 1; transition: opacity 0.3s linear, transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955); + pointer-events: none; + } + + .collectionCarouselView-item-active { + pointer-events: unset; } } diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 0baf44aeb..bad3096c8 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -36,10 +36,14 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume panelHeight = () => this.props.PanelHeight() * 0.6; @computed get content() { const currentIndex = NumCast(this.layoutDoc._itemIndex); - const displayDoc = (childPair: { layout: Doc, data: Doc }, onClickScript: ScriptField | undefined) => { + const displayDoc = (childPair: { layout: Doc, data: Doc }) => { return { - const showCaptionScript = ScriptField.MakeScript( - "child._showCaption = 'caption'", - { child: Doc.name }, - { child: childPair.layout } - ); - return ( -
- {displayDoc(childPair, index === currentIndex ? showCaptionScript : undefined)} + {displayDoc(childPair)}
); })); } - handleArrowClick = (e: React.MouseEvent, direction: number) => { - e.stopPropagation(); - this.changeSlide(direction); - } - changeSlide = (direction: number) => { this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length; } - timer?: NodeJS.Timeout; - interval?: NodeJS.Timeout; - onPress = (e: React.PointerEvent, direction: number) => { + timer?: number; + interval?: number; + onArrowDown = (e: React.PointerEvent, direction: number) => { e.stopPropagation; - document.removeEventListener("pointerup", this.stopScroll); - document.addEventListener("pointerup", this.stopScroll); + document.removeEventListener("pointerup", () => this.onArrowRelease(direction)); + document.addEventListener("pointerup", () => this.onArrowRelease(direction)); - this.timer = setTimeout(() => { + this.layoutDoc.startScrollTimeout = 1500; + this.timer = window.setTimeout(() => { // if arrow is held down long enough, activate automatic scrolling + window.clearTimeout(this.timer); + this.timer = undefined; this.startScroll(direction); - }, 1500); + }, this.layoutDoc.startScrollTimeout); } startScroll = (direction: number) => { - this.interval = setInterval(() => { + this.layoutDoc.scrollInterval = 500; + this.interval = window.setInterval(() => { this.changeSlide(direction); - }, 500); + }, this.layoutDoc.scrollInterval); } - stopScroll = () => { + onArrowRelease = (direction: number) => { + document.removeEventListener("pointerup", () => this.onArrowRelease(direction)); + if (this.timer) { - clearTimeout(this.timer); + this.changeSlide(direction); // if click wasn't long enough to activate autoscroll, only advance/go back 1 slide + window.clearTimeout(this.timer); this.timer = undefined; } if (this.interval) { - clearInterval(this.interval); + window.clearInterval(this.interval); // stop scrolling this.interval = undefined; } } @@ -147,13 +148,11 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume @computed get buttons() { return <>
this.handleArrowClick(e, -1)} - onPointerDown={(e) => this.onPress(e, -1)}> + onPointerDown={(e) => this.onArrowDown(e, -1)}>
this.handleArrowClick(e, 1)} - onPointerDown={(e) => this.onPress(e, 1)}> + onPointerDown={(e) => this.onArrowDown(e, 1)}>
; -- cgit v1.2.3-70-g09d2 From ced0c14ea8410eeedcbdc8eba4e0227840c488b5 Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Tue, 2 Jun 2020 20:08:06 -0700 Subject: arrows bug fix --- package-lock.json | 84 +++++++++++++--------- .../views/collections/CollectionCarousel3DView.tsx | 27 ++++--- 2 files changed, 68 insertions(+), 43 deletions(-) (limited to 'src/client/views/collections') diff --git a/package-lock.json b/package-lock.json index 842553659..6ee723aab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2827,7 +2827,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -2845,11 +2846,13 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2862,15 +2865,18 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -2973,7 +2979,8 @@ }, "inherits": { "version": "2.0.4", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -2983,6 +2990,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2995,17 +3003,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "1.2.5", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.9.0", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3022,6 +3033,7 @@ "mkdirp": { "version": "0.5.3", "bundled": true, + "optional": true, "requires": { "minimist": "^1.2.5" } @@ -3077,7 +3089,8 @@ }, "npm-normalize-package-bin": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "npm-packlist": { "version": "1.4.8", @@ -3102,7 +3115,8 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -3112,6 +3126,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -3180,7 +3195,8 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -3210,6 +3226,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3227,6 +3244,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3265,11 +3283,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.1.1", - "bundled": true + "bundled": true, + "optional": true } } } @@ -9486,7 +9506,7 @@ }, "chownr": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "resolved": false, "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "ci-info": { @@ -9792,7 +9812,7 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "resolved": false, "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, "defaults": { @@ -10291,7 +10311,7 @@ }, "glob": { "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "resolved": false, "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "requires": { "fs.realpath": "^1.0.0", @@ -10379,7 +10399,7 @@ }, "hosted-git-info": { "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "resolved": false, "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" }, "http-cache-semantics": { @@ -10515,7 +10535,7 @@ }, "is-ci": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "resolved": false, "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", "requires": { "ci-info": "^1.5.0" @@ -10591,7 +10611,7 @@ }, "is-retry-allowed": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "resolved": false, "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" }, "is-stream": { @@ -11100,7 +11120,7 @@ }, "mkdirp": { "version": "0.5.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", + "resolved": false, "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", "requires": { "minimist": "^1.2.5" @@ -11108,7 +11128,7 @@ "dependencies": { "minimist": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "resolved": false, "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" } } @@ -11160,7 +11180,7 @@ }, "node-gyp": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-5.1.0.tgz", + "resolved": false, "integrity": "sha512-OUTryc5bt/P8zVgNUmC6xdXiDJxLMAW8cF5tLQOT9E5sOQj+UeQxnnPy74K3CLCa/SOjjBlbuzDLR8ANwA+wmw==", "requires": { "env-paths": "^2.2.0", @@ -11274,7 +11294,7 @@ }, "npm-packlist": { "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "resolved": false, "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", "requires": { "ignore-walk": "^3.0.1", @@ -11294,7 +11314,7 @@ }, "npm-profile": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/npm-profile/-/npm-profile-4.0.4.tgz", + "resolved": false, "integrity": "sha512-Ta8xq8TLMpqssF0H60BXS1A90iMoM6GeKwsmravJ6wYjWwSzcYBTdyWa3DZCYqPutacBMEm7cxiOkiIeCUAHDQ==", "requires": { "aproba": "^1.1.2 || 2", @@ -11304,7 +11324,7 @@ }, "npm-registry-fetch": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.3.tgz", + "resolved": false, "integrity": "sha512-WGvUx0lkKFhu9MbiGFuT9nG2NpfQ+4dCJwRwwtK2HK5izJEvwDxMeUyqbuMS7N/OkpVCqDorV6rO5E4V9F8lJw==", "requires": { "JSONStream": "^1.3.4", @@ -11739,7 +11759,7 @@ }, "rc": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "resolved": false, "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "requires": { "deep-extend": "^0.6.0", @@ -11750,7 +11770,7 @@ "dependencies": { "minimist": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "resolved": false, "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" } } @@ -11809,7 +11829,7 @@ }, "readable-stream": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "resolved": false, "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "requires": { "inherits": "^2.0.3", @@ -11830,7 +11850,7 @@ }, "registry-auth-token": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", + "resolved": false, "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", "requires": { "rc": "^1.1.6", @@ -11894,7 +11914,7 @@ }, "rimraf": { "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "resolved": false, "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "requires": { "glob": "^7.1.3" @@ -12193,7 +12213,7 @@ }, "string_decoder": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "resolved": false, "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "requires": { "safe-buffer": "~5.2.0" @@ -12201,7 +12221,7 @@ "dependencies": { "safe-buffer": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "resolved": false, "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" } } @@ -12513,7 +12533,7 @@ }, "widest-line": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "resolved": false, "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", "requires": { "string-width": "^2.1.1" diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index bad3096c8..097bbb7b3 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -71,15 +71,29 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume } changeSlide = (direction: number) => { + console.log("old", NumCast(this.layoutDoc._itemIndex), direction); this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length; + console.log("new", NumCast(this.layoutDoc._itemIndex)); + } + + startScroll = (direction: number) => { + this.layoutDoc.scrollInterval = 500; + this.interval = window.setInterval(() => { + this.changeSlide(direction); + }, this.layoutDoc.scrollInterval); } timer?: number; interval?: number; onArrowDown = (e: React.PointerEvent, direction: number) => { + console.log("onArrowDown", direction); e.stopPropagation; - document.removeEventListener("pointerup", () => this.onArrowRelease(direction)); - document.addEventListener("pointerup", () => this.onArrowRelease(direction)); + + const listener = () => { // is able to pass in the direction parameter and then correctly remove the listener + this.onArrowRelease(direction); + document.removeEventListener("pointerup", listener); + }; + document.addEventListener("pointerup", listener); this.layoutDoc.startScrollTimeout = 1500; this.timer = window.setTimeout(() => { // if arrow is held down long enough, activate automatic scrolling @@ -89,16 +103,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume }, this.layoutDoc.startScrollTimeout); } - startScroll = (direction: number) => { - this.layoutDoc.scrollInterval = 500; - this.interval = window.setInterval(() => { - this.changeSlide(direction); - }, this.layoutDoc.scrollInterval); - } - onArrowRelease = (direction: number) => { - document.removeEventListener("pointerup", () => this.onArrowRelease(direction)); - if (this.timer) { this.changeSlide(direction); // if click wasn't long enough to activate autoscroll, only advance/go back 1 slide window.clearTimeout(this.timer); -- cgit v1.2.3-70-g09d2 From 2ca409065cd851e58033c5b1ac06f503a9ffe141 Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Wed, 3 Jun 2020 17:16:52 -0700 Subject: clean up --- src/client/views/collections/CollectionCarousel3DView.tsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 097bbb7b3..2f161e255 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -61,7 +61,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume this.childLayoutPairs.map((childPair, index) => { return (
@@ -71,9 +71,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume } changeSlide = (direction: number) => { - console.log("old", NumCast(this.layoutDoc._itemIndex), direction); this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length; - console.log("new", NumCast(this.layoutDoc._itemIndex)); } startScroll = (direction: number) => { @@ -86,7 +84,6 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume timer?: number; interval?: number; onArrowDown = (e: React.PointerEvent, direction: number) => { - console.log("onArrowDown", direction); e.stopPropagation; const listener = () => { // is able to pass in the direction parameter and then correctly remove the listener @@ -95,7 +92,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume }; document.addEventListener("pointerup", listener); - this.layoutDoc.startScrollTimeout = 1500; + this.layoutDoc.startScrollTimeout = 500; this.timer = window.setTimeout(() => { // if arrow is held down long enough, activate automatic scrolling window.clearTimeout(this.timer); this.timer = undefined; @@ -174,7 +171,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume const index = NumCast(this.layoutDoc._itemIndex); const translateX = (1 - index) / this.childLayoutPairs.length * 100; - return
+ return
{this.content}
-- cgit v1.2.3-70-g09d2 From 05fe7bb89e51f3d8b643726f3283ba8adee740e4 Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Thu, 4 Jun 2020 16:22:27 -0700 Subject: hover to show autoscroll button --- src/client/views/DocumentDecorations.tsx | 7 +- .../collections/CollectionCarousel3DView.scss | 49 ++++++++++-- .../views/collections/CollectionCarousel3DView.tsx | 86 +++++++++++++--------- src/client/views/collections/CollectionView.tsx | 2 +- 4 files changed, 100 insertions(+), 44 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 04f02c683..7cdf955a1 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -1,5 +1,5 @@ import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; -import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faTextHeight, faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faShare, faStopCircle, faSyncAlt, faTag, faTimes } from '@fortawesome/free-solid-svg-icons'; +import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faTextHeight, faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faShare, faStopCircle, faSyncAlt, faTag, faTimes, faAngleLeft, faAngleRight, faAngleDoubleLeft, faAngleDoubleRight, faPause } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; @@ -38,6 +38,11 @@ library.add(faCheckCircle); library.add(faCloudUploadAlt); library.add(faSyncAlt); library.add(faShare); +library.add(faAngleDoubleLeft); +library.add(faAngleDoubleRight); +library.add(faAngleLeft); +library.add(faAngleRight); +library.add(faPause); @observer export class DocumentDecorations extends React.Component<{}, { value: string }> { diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index d00a666f8..ff63f4116 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -1,4 +1,4 @@ -.collectionCarouselView-outer { +.collectionCarousel3DView-outer { height: 100%; position: relative; background-color: white; @@ -11,14 +11,14 @@ align-items: center; transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955); - .collectionCarouselView-item, - .collectionCarouselView-item-active { + .collectionCarousel3DView-item, + .collectionCarousel3DView-item-active { flex: 1; transition: opacity 0.3s linear, transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955); pointer-events: none; } - .collectionCarouselView-item-active { + .collectionCarousel3DView-item-active { pointer-events: unset; } } @@ -46,7 +46,44 @@ } } -.carouselView-back, -.carouselView-forward { +.carousel3DView-back, +.carousel3DView-fwd, +.carousel3DView-back-scroll, +.carousel3DView-fwd-scroll { + position: absolute; + display: flex; + width: 30; + height: 30; + align-items: center; + border-radius: 5px; + justify-content: center; + background: rgba(255, 255, 255, 0.46); cursor: pointer; +} + +.carousel3DView-fwd { + top: 50%; + right: 0; +} + +.carousel3DView-back { + top: 50%; + left: 0; +} + +.carousel3DView-fwd-scroll { + top: calc(50% - 30px); + right: 0; +} + +.carousel3DView-back-scroll { + top: calc(50% - 30px); + left: 0; +} + +.carousel3DView-back:hover, +.carousel3DView-fwd:hover, +.carousel3DView-back-scroll:hover, +.carousel3DView-fwd-scroll:hover { + background: lightgray; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 2f161e255..1fa96df65 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -21,6 +21,10 @@ const Carousel3DDocument = makeInterface(documentSchema, collectionSchema); @observer export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocument) { + @computed get scrollSpeed() { + return this.layoutDoc._autoScrollSpeed ? NumCast(this.layoutDoc._autoScrollSpeed) : 1000; //default scroll speed + } + private _dropDisposer?: DragManager.DragDropDisposer; componentWillUnmount() { this._dropDisposer?.(); } @@ -74,43 +78,32 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length; } - startScroll = (direction: number) => { - this.layoutDoc.scrollInterval = 500; - this.interval = window.setInterval(() => { - this.changeSlide(direction); - }, this.layoutDoc.scrollInterval); + onArrowClick = (e: React.MouseEvent, direction: number) => { + e.stopPropagation(); + this.changeSlide(direction); } - timer?: number; interval?: number; - onArrowDown = (e: React.PointerEvent, direction: number) => { - e.stopPropagation; + startAutoScroll = (direction: number) => { + this.interval = window.setInterval(() => { + this.changeSlide(direction); + }, this.scrollSpeed); + } - const listener = () => { // is able to pass in the direction parameter and then correctly remove the listener - this.onArrowRelease(direction); - document.removeEventListener("pointerup", listener); - }; - document.addEventListener("pointerup", listener); + stopAutoScroll = () => { + window.clearInterval(this.interval); + this.interval = undefined; + } - this.layoutDoc.startScrollTimeout = 500; - this.timer = window.setTimeout(() => { // if arrow is held down long enough, activate automatic scrolling - window.clearTimeout(this.timer); - this.timer = undefined; - this.startScroll(direction); - }, this.layoutDoc.startScrollTimeout); + toggleAutoScroll = (direction: number) => { + this.layoutDoc.autoScrollOn = this.layoutDoc.autoScrollOn ? false : true; + this.layoutDoc.autoScrollOn ? this.startAutoScroll(direction) : this.stopAutoScroll(); } - onArrowRelease = (direction: number) => { - if (this.timer) { - this.changeSlide(direction); // if click wasn't long enough to activate autoscroll, only advance/go back 1 slide - window.clearTimeout(this.timer); - this.timer = undefined; - } + showAutoScrollButton = (direction: string) => { + // keep pause button visible while autoscroll is on, and don't show the other side's autoscroll button + !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = direction); - if (this.interval) { - window.clearInterval(this.interval); // stop scrolling - this.interval = undefined; - } } onContextMenu = (e: React.MouseEvent): void => { @@ -148,14 +141,35 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume } @computed get buttons() { - return <> -
this.onArrowDown(e, -1)}> - + if (!this.props.active()) return null; + return
this.showAutoScrollButton("none")}> +
this.onArrowClick(e, -1)} + onMouseEnter={() => this.showAutoScrollButton("back")}> +
-
this.onArrowDown(e, 1)}> - +
this.onArrowClick(e, 1)} + onMouseEnter={() => this.showAutoScrollButton("fwd")}> + +
+ {this.autoScrollButton} +
; + } + + @computed get autoScrollButton() { + const direction = this.layoutDoc.showScrollButton; + if (direction !== "back" && direction !== "fwd") return null; + + const offset = (direction === "back") ? -1 : 1; + return <> +
this.toggleAutoScroll(offset)}> + {this.layoutDoc.autoScrollOn ? + : + direction === "back" ? + : + }
; } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index a0f6ad9c7..82aa3dbd5 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -64,7 +64,7 @@ export enum CollectionViewType { Multirow = "multirow", Time = "time", Carousel = "carousel", - Carousel3D = "3D carousel", + Carousel3D = "3D Carousel", Linear = "linear", Staff = "staff", Map = "map", -- cgit v1.2.3-70-g09d2 From 45f4e8f821817e724fd2567ef05c178d7f7640ea Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Thu, 4 Jun 2020 16:33:45 -0700 Subject: added customizable scrollSpeed field in dropdown bar --- .../views/collections/CollectionViewChromes.scss | 75 ++++++++++++++-------- .../views/collections/CollectionViewChromes.tsx | 36 +++++++++++ 2 files changed, 83 insertions(+), 28 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index 03bd9a01a..b98dab707 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -3,7 +3,7 @@ .collectionViewChrome-cont { position: absolute; - width:100%; + width: 100%; opacity: 0.9; z-index: 9001; transition: top .5s; @@ -13,7 +13,7 @@ .collectionViewChrome { display: flex; padding-bottom: 1px; - height:32px; + height: 32px; border-bottom: .5px solid rgb(180, 180, 180); overflow: hidden; @@ -35,7 +35,7 @@ outline-color: black; } - .collectionViewBaseChrome-button{ + .collectionViewBaseChrome-button { font-size: 75%; text-transform: uppercase; letter-spacing: 2px; @@ -46,6 +46,7 @@ padding: 12px 10px 11px 10px; margin-left: 10px; } + .collectionViewBaseChrome-cmdPicker { margin-left: 3px; margin-right: 0px; @@ -54,15 +55,17 @@ border: none; color: grey; } + .commandEntry-outerDiv { pointer-events: all; background-color: gray; display: flex; flex-direction: row; - height:30px; + height: 30px; + .commandEntry-drop { - color:white; - width:25px; + color: white; + width: 25px; margin-top: auto; margin-bottom: auto; } @@ -76,15 +79,17 @@ pointer-events: all; // margin-top: 10px; } + .collectionViewBaseChrome-template, .collectionViewBaseChrome-viewModes { display: grid; background: rgb(238, 238, 238); - color:grey; - margin-top:auto; - margin-bottom:auto; + color: grey; + margin-top: auto; + margin-bottom: auto; margin-left: 5px; } + .collectionViewBaseChrome-viewModes { margin-left: 25px; } @@ -92,7 +97,7 @@ .collectionViewBaseChrome-viewSpecs { margin-left: 5px; display: grid; - + .collectionViewBaseChrome-filterIcon { position: relative; display: flex; @@ -165,7 +170,8 @@ .collectionStackingViewChrome-cont, - .collectionTreeViewChrome-cont { + .collectionTreeViewChrome-cont, + .collection3DCarouselViewChrome-cont { display: flex; justify-content: space-between; } @@ -189,23 +195,26 @@ .collectionStackingViewChrome-pivotField-cont, - .collectionTreeViewChrome-pivotField-cont { + .collectionTreeViewChrome-pivotField-cont, + .collection3DCarouselViewChrome-scrollSpeed-cont { justify-self: right; display: flex; font-size: 75%; letter-spacing: 2px; .collectionStackingViewChrome-pivotField-label, - .collectionTreeViewChrome-pivotField-label { + .collectionTreeViewChrome-pivotField-label, + .collection3DCarouselViewChrome-scrollSpeed-label { vertical-align: center; padding-left: 10px; - margin:auto; + margin: auto; } .collectionStackingViewChrome-pivotField, - .collectionTreeViewChrome-pivotField { + .collectionTreeViewChrome-pivotField, + .collection3DCarouselViewChrome-scrollSpeed { color: white; - width:100%; + width: 100%; min-width: 100px; display: flex; align-items: center; @@ -215,7 +224,7 @@ input, .editableView-container-editing-oneLine, .editableView-container-editing { - margin:auto; + margin: auto; border: 0px; color: grey; text-align: center; @@ -233,7 +242,8 @@ } .collectionStackingViewChrome-pivotField:hover, - .collectionTreeViewChrome-pivotField:hover { + .collectionTreeViewChrome-pivotField:hover, + .collection3DCarouselViewChrome-scrollSpeed:hover { cursor: text; } } @@ -244,7 +254,10 @@ display: flex; position: relative; align-items: center; - .fwdKeyframe, .numKeyframe, .backKeyframe { + + .fwdKeyframe, + .numKeyframe, + .backKeyframe { cursor: pointer; position: absolute; width: 20; @@ -253,26 +266,31 @@ background: gray; display: flex; align-items: center; - color:white; + color: white; } + .backKeyframe { - left:0; + left: 0; + svg { - display:block; - margin:auto; + display: block; + margin: auto; } } + .numKeyframe { - left:20; + left: 20; display: flex; flex-direction: column; padding: 5px; } + .fwdKeyframe { - left:40; + left: 40; + svg { - display:block; - margin:auto; + display: block; + margin: auto; } } } @@ -334,8 +352,9 @@ flex-direction: column; height: 40px; } + .commandEntry-inputArea { - display:flex; + display: flex; flex-direction: row; width: 150px; margin: auto auto auto auto; diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 199902923..e17e86e05 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -202,6 +202,7 @@ export class CollectionViewBaseChrome extends React.Component); case CollectionViewType.Tree: return (); case CollectionViewType.Masonry: return (); + case CollectionViewType.Carousel3D: return (); default: return null; } } @@ -563,3 +564,38 @@ export class CollectionTreeViewChrome extends React.Component { + @computed get scrollSpeed() { + return this.props.CollectionView.props.Document._autoScrollSpeed; + } + + @action + setValue = (value: string) => { + const numValue = Number(StrCast(value)); + if (numValue > 0) { + this.props.CollectionView.props.Document._autoScrollSpeed = numValue; + return true; + } + return false; + } + + render() { + return ( +
+
+
+ AUTOSCROLL SPEED: +
+
+ StrCast(this.scrollSpeed)} + oneLine + SetValue={this.setValue} + contents={this.scrollSpeed ? this.scrollSpeed : 1000} /> +
+
+
+ ); + } +} -- cgit v1.2.3-70-g09d2 From 633c62652ad7cef151c68d0cf6e2c420ed07de87 Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Thu, 4 Jun 2020 22:34:59 -0700 Subject: show autoscroll button on arrow click, then fade away after a while if it's not clicked --- .../collections/CollectionCarousel3DView.scss | 40 +++++++++++---- .../views/collections/CollectionCarousel3DView.tsx | 60 +++++++++++----------- 2 files changed, 58 insertions(+), 42 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index ff63f4116..5f8895c1f 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -32,8 +32,8 @@ .dot, .dot-active { - height: 15px; - width: 15px; + height: 10px; + width: 10px; border-radius: 50%; margin: 3px; display: inline-block; @@ -49,7 +49,9 @@ .carousel3DView-back, .carousel3DView-fwd, .carousel3DView-back-scroll, -.carousel3DView-fwd-scroll { +.carousel3DView-fwd-scroll, +.carousel3DView-back-scroll-hidden, +.carousel3DView-fwd-scroll-hidden { position: absolute; display: flex; width: 30; @@ -61,24 +63,40 @@ cursor: pointer; } -.carousel3DView-fwd { +.carousel3DView-fwd, +.carousel3DView-back { top: 50%; +} + +.carousel3DView-fwd-scroll, +.carousel3DView-back-scroll, +.carousel3DView-fwd-scroll-hidden, +.carousel3DView-back-scroll-hidden { + top: calc(50% - 30px); +} + +.carousel3DView-fwd, +.carousel3DView-fwd-scroll, +.carousel3DView-fwd-scroll-hidden { right: 0; } -.carousel3DView-back { - top: 50%; +.carousel3DView-back, +.carousel3DView-back-scroll, +.carousel3DView-back-scroll-hidden { left: 0; } -.carousel3DView-fwd-scroll { - top: calc(50% - 30px); - right: 0; +.carousel3DView-fwd-scroll-hidden, +.carousel3DView-back-scroll-hidden { + opacity: 0; + transition: opacity 0.5s linear; + pointer-events: none; } +.carousel3DView-fwd-scroll, .carousel3DView-back-scroll { - top: calc(50% - 30px); - left: 0; + opacity: 1; } .carousel3DView-back:hover, diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 1fa96df65..a7d9c41c8 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -46,8 +46,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume onClick={ScriptField.MakeScript( "child._showCaption = 'caption'", { child: Doc.name }, - { child: childPair.layout } - )} + { child: childPair.layout })} renderDepth={this.props.renderDepth + 1} LayoutTemplate={this.props.ChildLayoutTemplate} LayoutTemplateString={this.props.ChildLayoutString} @@ -61,17 +60,16 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume />; }; - return ( - this.childLayoutPairs.map((childPair, index) => { - return ( -
- {displayDoc(childPair)} -
); - })); + return (this.childLayoutPairs.map((childPair, index) => { + return ( +
+ {displayDoc(childPair)} +
); + })); } changeSlide = (direction: number) => { @@ -81,6 +79,8 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume onArrowClick = (e: React.MouseEvent, direction: number) => { e.stopPropagation(); this.changeSlide(direction); + !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = (direction === 1) ? "fwd" : "back"); // while autoscroll is on, keep the other autoscroll button hidden + !this.layoutDoc.autoScrollOn && this.fadeScrollButton(); // keep pause button visible while autoscroll is on } interval?: number; @@ -93,6 +93,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume stopAutoScroll = () => { window.clearInterval(this.interval); this.interval = undefined; + this.fadeScrollButton(); } toggleAutoScroll = (direction: number) => { @@ -100,10 +101,10 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume this.layoutDoc.autoScrollOn ? this.startAutoScroll(direction) : this.stopAutoScroll(); } - showAutoScrollButton = (direction: string) => { - // keep pause button visible while autoscroll is on, and don't show the other side's autoscroll button - !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = direction); - + fadeScrollButton = () => { + window.setTimeout(() => { + !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = "none"); //fade away after 1.5s if it's not clicked. + }, 1500); } onContextMenu = (e: React.MouseEvent): void => { @@ -142,15 +143,15 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume @computed get buttons() { if (!this.props.active()) return null; - return
this.showAutoScrollButton("none")}> + return
this.onArrowClick(e, -1)} - onMouseEnter={() => this.showAutoScrollButton("back")}> + >
this.onArrowClick(e, 1)} - onMouseEnter={() => this.showAutoScrollButton("fwd")}> + >
{this.autoScrollButton} @@ -158,18 +159,15 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume } @computed get autoScrollButton() { - const direction = this.layoutDoc.showScrollButton; - if (direction !== "back" && direction !== "fwd") return null; - - const offset = (direction === "back") ? -1 : 1; + const whichButton = this.layoutDoc.showScrollButton; return <> -
this.toggleAutoScroll(offset)}> - {this.layoutDoc.autoScrollOn ? - : - direction === "back" ? - : - } +
this.toggleAutoScroll(-1)}> + {this.layoutDoc.autoScrollOn ? : } +
+
this.toggleAutoScroll(1)}> + {this.layoutDoc.autoScrollOn ? : }
; } -- cgit v1.2.3-70-g09d2 From bcb2e70a5cd4628dd2909279ec61c4c644e07c37 Mon Sep 17 00:00:00 2001 From: Melissa Zhang Date: Fri, 5 Jun 2020 19:35:32 -0700 Subject: minor fixes --- src/client/views/collections/CollectionCarousel3DView.tsx | 5 +++-- src/client/views/collections/CollectionViewChromes.scss | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index a7d9c41c8..1344b70f4 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -1,9 +1,9 @@ -import { observable, computed } from 'mobx'; +import { computed } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { documentSchema, collectionSchema } from '../../../fields/documentSchemas'; import { makeInterface } from '../../../fields/Schema'; -import { NumCast, StrCast, ScriptCast, Cast } from '../../../fields/Types'; +import { NumCast, StrCast, ScriptCast } from '../../../fields/Types'; import { DragManager } from '../../util/DragManager'; import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView'; import "./CollectionCarousel3DView.scss"; @@ -86,6 +86,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume interval?: number; startAutoScroll = (direction: number) => { this.interval = window.setInterval(() => { + console.log(this.interval, this.scrollSpeed); this.changeSlide(direction); }, this.scrollSpeed); } diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index b98dab707..2ab771089 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -226,7 +226,7 @@ .editableView-container-editing { margin: auto; border: 0px; - color: grey; + color: grey !important; text-align: center; letter-spacing: 2px; outline-color: black; -- cgit v1.2.3-70-g09d2 From 639be55eaff422e1e982cf41d09edd9e96f014a4 Mon Sep 17 00:00:00 2001 From: yunahi <60233430+yunahi@users.noreply.github.com> Date: Thu, 18 Jun 2020 14:10:34 +0900 Subject: updated menu --- package-lock.json | 44 +++-- src/client/documents/Documents.ts | 10 +- src/client/util/CurrentUserUtils.ts | 4 + src/client/util/InteractionUtils.tsx | 64 +++++-- src/client/views/DocumentDecorations.scss | 50 +++-- src/client/views/DocumentDecorations.tsx | 81 +++++++- src/client/views/GestureOverlay.tsx | 21 ++- src/client/views/InkingStroke.tsx | 41 ++++- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- .../collectionFreeForm/InkOptionsMenu.tsx | 203 +++++++++++++++++++-- src/fields/InkField.ts | 4 +- 11 files changed, 459 insertions(+), 67 deletions(-) (limited to 'src/client/views/collections') diff --git a/package-lock.json b/package-lock.json index c956fd3e9..cd80ecc5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2832,7 +2832,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -2850,11 +2851,13 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2867,15 +2870,18 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -2978,7 +2984,8 @@ }, "inherits": { "version": "2.0.4", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -2988,6 +2995,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3000,17 +3008,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "1.2.5", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.9.0", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3027,6 +3038,7 @@ "mkdirp": { "version": "0.5.3", "bundled": true, + "optional": true, "requires": { "minimist": "^1.2.5" } @@ -3082,7 +3094,8 @@ }, "npm-normalize-package-bin": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "npm-packlist": { "version": "1.4.8", @@ -3107,7 +3120,8 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -3117,6 +3131,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -3185,7 +3200,8 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -3215,6 +3231,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3232,6 +3249,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3270,11 +3288,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.1.1", - "bundled": true + "bundled": true, + "optional": true } } } diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 8d867348f..cbf97e8e8 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -37,7 +37,7 @@ import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo"; import { QueryBox } from "../views/nodes/QueryBox"; import { ColorBox } from "../views/nodes/ColorBox"; import { DocHolderBox } from "../views/nodes/DocHolderBox"; -import { InkingStroke, ActiveInkColor, ActiveInkWidth, ActiveInkBezierApprox } from "../views/InkingStroke"; +import { InkingStroke, ActiveInkColor, ActiveInkWidth, ActiveInkBezierApprox, ActiveFillColor, ActiveArrowStart, ActiveArrowEnd, ActiveDash } from "../views/InkingStroke"; import { InkField } from "../../fields/InkField"; import { RichTextField } from "../../fields/RichTextField"; import { extname } from "path"; @@ -631,13 +631,17 @@ export namespace Docs { return doc; } - export function InkDocument(color: string, tool: string, strokeWidth: string, strokeBezier: string, points: { X: number, Y: number }[], options: DocumentOptions = {}) { + export function InkDocument(color: string, tool: string, strokeWidth: string, strokeBezier: string, fillColor: string, arrowStart: string, arrowEnd: string, dash: string, points: { X: number, Y: number }[], options: DocumentOptions = {}) { const I = new Doc(); I.type = DocumentType.INK; I.layout = InkingStroke.LayoutString("data"); I.color = color; I.strokeWidth = strokeWidth; I.strokeBezier = strokeBezier; + I.fillColor = fillColor; + I.arrowStart = arrowStart; + I.arrowEnd = arrowEnd; + I.dash = dash; I.tool = tool; I.title = "ink"; I.x = options.x; @@ -852,7 +856,7 @@ export namespace DocUtils { created = Docs.Create.AudioDocument((field).url.href, resolved); layout = AudioBox.LayoutString; } else if (field instanceof InkField) { - created = Docs.Create.InkDocument(ActiveInkColor(), Doc.GetSelectedTool(), ActiveInkWidth(), ActiveInkBezierApprox(), (field).inkData, resolved); + created = Docs.Create.InkDocument(ActiveInkColor(), Doc.GetSelectedTool(), ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), (field).inkData, resolved); layout = InkingStroke.LayoutString; } else if (field instanceof List && field[0] instanceof Doc) { created = Docs.Create.StackingDocument(DocListCast(field), resolved); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index b0cea9947..3d0c0ef4a 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -691,6 +691,10 @@ export class CurrentUserUtils { doc.activeInkColor = StrCast(doc.activeInkColor, "rgb(0, 0, 0)"); doc.activeInkWidth = StrCast(doc.activeInkWidth, "1"); doc.activeInkBezier = StrCast(doc.activeInkBezier, ""); + doc.activeFillColor = StrCast(doc.activeFillColor, "none"); + doc.activeArrowStart = StrCast(doc.activeArrowStart, "none"); + doc.activeArrowEnd = StrCast(doc.activeArrowEnd, "none"); + doc.activeDash = StrCast(doc.activeDash, "0"); doc.fontSize = NumCast(doc.fontSize, 12); doc["constants-snapThreshold"] = NumCast(doc["constants-snapThreshold"], 10); // doc["constants-dragThreshold"] = NumCast(doc["constants-dragThreshold"], 4); // diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index 81f9b9362..c6b96df45 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -1,6 +1,7 @@ import React = require("react"); import * as beziercurve from 'bezier-curve'; import * as fitCurve from 'fit-curve'; +import InkOptionsMenu from "../views/collections/collectionFreeForm/InkOptionsMenu"; export namespace InteractionUtils { export const MOUSETYPE = "mouse"; @@ -89,7 +90,8 @@ export namespace InteractionUtils { return myTouches; } - export function CreatePolyline(points: { X: number, Y: number }[], left: number, top: number, color: string, width: string, bezier: string, scalex: number, scaley: number, shape: string, pevents: string, drawHalo: boolean) { + + export function CreatePolyline(points: { X: number, Y: number }[], left: number, top: number, color: string, width: string, bezier: string, fill: string, arrowStart: string, arrowEnd: string, dash: string, scalex: number, scaley: number, shape: string, pevents: string, drawHalo: boolean) { var pts = ""; if (shape) { //if any of the shape are true @@ -116,22 +118,58 @@ export namespace InteractionUtils { //in the middle of drawing pts = points.reduce((acc: string, pt: { X: number, Y: number }) => acc + `${pt.X * scalex - left * scalex},${pt.Y * scaley - top * scaley} `, ""); } + const dashArray = String(Number(width) * Number(dash)); + return ( - + + + + {/* {makeArrow()} */} + + + + + {/* */} + + + + {/* */} + + + + + + + ); } + // export function makeArrow() { + // return ( + // InkOptionsMenu.Instance.getColors().map(color => { + // const id1 = "arrowHeadTest" + color; + // console.log(color); + // + // + // ; + // }) + // ); + // } + export function makePolygon(shape: string, points: { X: number, Y: number }[]) { if (points.length > 1 && points[points.length - 1].X === points[0].X && points[points.length - 1].Y + 1 === points[0].Y) { //pointer is up (first and last points are the same) diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index 0a96b058b..cf5871bda 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -22,11 +22,20 @@ $linkGap : 3px; } + .documentDecorations-rotation { + pointer-events: auto; + // cursor: grabbing; + cursor: ns-resize; + width: 10px; + height: 10px; + } + .documentDecorations-resizer { pointer-events: auto; background: $alt-accent; opacity: 0.1; } + .documentDecorations-resizer:hover { opacity: 1; } @@ -87,14 +96,17 @@ $linkGap : 3px; background: unset; opacity: 1; } + #documentDecorations-topLeftResizer { - border-left: 2px solid; - border-top: solid 2px; + border-left: 2px solid; + border-top: solid 2px; } + #documentDecorations-bottomRightResizer { - border-right: 2px solid; - border-bottom: solid 2px; + border-right: 2px solid; + border-bottom: solid 2px; } + #documentDecorations-topLeftResizer:hover, #documentDecorations-bottomRightResizer:hover { opacity: 1; @@ -110,14 +122,17 @@ $linkGap : 3px; background: unset; opacity: 1; } + #documentDecorations-topRightResizer { - border-right: 2px solid; - border-top: 2px solid; + border-right: 2px solid; + border-top: 2px solid; } + #documentDecorations-bottomLeftResizer { - border-left: 2px solid; - border-bottom: 2px solid; + border-left: 2px solid; + border-bottom: 2px solid; } + #documentDecorations-topRightResizer:hover, #documentDecorations-bottomLeftResizer:hover { cursor: nesw-resize; @@ -139,10 +154,11 @@ $linkGap : 3px; width: 25px; height: calc(100% + 8px); // 8px for the height of the top resizer bar grid-column-start: 2; - grid-column-end : 2; + grid-column-end: 2; pointer-events: all; padding-left: 5px; } + .documentDecorations-title { opacity: 1; grid-column-start: 3; @@ -150,14 +166,16 @@ $linkGap : 3px; pointer-events: auto; overflow: hidden; text-align: center; - display: flex; + display: flex; border-bottom: solid 1px; - margin-left:10px; + margin-left: 10px; width: calc(100% - 10px); } + .focus-visible { - margin-left:0px; + margin-left: 0px; } + .publishBox { width: 20px; height: 22px; @@ -194,8 +212,9 @@ $linkGap : 3px; width: 8px; height: $MINIMIZED_ICON_SIZE; max-height: 20px; - > svg { - margin:0; + + >svg { + margin: 0; } } @@ -332,7 +351,8 @@ $linkGap : 3px; padding: 2px 12px; list-style: none; - .templateToggle, .chromeToggle { + .templateToggle, + .chromeToggle { text-align: left; } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 6ca7331d6..8cb0c83ed 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -17,11 +17,13 @@ import { DocumentButtonBar } from './DocumentButtonBar'; import './DocumentDecorations.scss'; import { DocumentView } from "./nodes/DocumentView"; import React = require("react"); -import { Id } from '../../fields/FieldSymbols'; +import { Id, Copy, Update } from '../../fields/FieldSymbols'; import e = require('express'); import { CollectionDockingView } from './collections/CollectionDockingView'; import { SnappingManager } from '../util/SnappingManager'; import { HtmlField } from '../../fields/HtmlField'; +import { InkData, InkField, InkTool } from "../../fields/InkField"; +import { update } from 'serializr'; library.add(faCaretUp); library.add(faObjectGroup); @@ -50,6 +52,10 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> private _resizeUndo?: UndoManager.Batch; private _offX = 0; _offY = 0; // offset from click pt to inner edge of resize border private _snapX = 0; _snapY = 0; // last snapped location of resize border + private _prevX = 0; + private _prevY = 0; + private _centerPoints: { X: number, Y: number }[] = []; + @observable private _accumulatedTitle = ""; @observable private _titleControlString: string = "#title"; @observable private _edtingTitle = false; @@ -237,6 +243,77 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> return false; } + @action + onRotateDown = (e: React.PointerEvent): void => { + setupMoveUpEvents(this, e, this.onRotateMove, this.onRotateUp, (e) => { }); + this._prevX = e.clientX; + this._prevY = e.clientY; + SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => { + const doc = Document(element.rootDoc); + if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) { + const ink = Cast(doc.data, InkField)?.inkData; + if (ink) { + const xs = ink.map(p => p.X); + const ys = ink.map(p => p.Y); + const left = Math.min(...xs); + const top = Math.min(...ys); + const right = Math.max(...xs); + const bottom = Math.max(...ys); + this._centerPoints.push({ X: ((right - left) / 2) + left, Y: ((bottom - top) / 2) + bottom }); + } + } + })); + + } + @action + onRotateMove = (e: PointerEvent, down: number[]): boolean => { + // const distance = Math.sqrt((this._prevY - e.clientY) * (this._prevY - e.clientY) + (this._prevX - e.clientX) * (this._prevX - e.clientX)); + const distance = Math.abs(this._prevY - e.clientY); + var angle = 0; + //think of a better condition later... + // if ((down[0] < e.clientX && this._prevY < e.clientY) || (down[0] > e.clientX && this._prevY > e.clientY)) { + if (e.clientY > this._prevY) { + angle = distance * (Math.PI / 180); + // } else if ((down[0] < e.clientX && this._prevY > e.clientY) || (down[0] > e.clientX && this._prevY <= e.clientY)) { + } else if (e.clientY < this._prevY) { + angle = - distance * (Math.PI / 180); + } + this._prevX = e.clientX; + this._prevY = e.clientY; + var index = 0; + SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => { + const doc = Document(element.rootDoc); + if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) { + const ink = Cast(doc.data, InkField)?.inkData; + if (ink) { + const newPoints: { X: number, Y: number }[] = []; + for (var i = 0; i < ink.length; i++) { + const newX = Math.cos(angle) * (ink[i].X - this._centerPoints[index].X) - Math.sin(angle) * (ink[i].Y - this._centerPoints[index].Y) + this._centerPoints[index].X; + const newY = Math.sin(angle) * (ink[i].X - this._centerPoints[index].X) + Math.cos(angle) * (ink[i].Y - this._centerPoints[index].Y) + this._centerPoints[index].Y; + newPoints.push({ X: newX, Y: newY }); + } + doc.data = new InkField(newPoints); + const xs = newPoints.map(p => p.X); + const ys = newPoints.map(p => p.Y); + const left = Math.min(...xs); + const top = Math.min(...ys); + const right = Math.max(...xs); + const bottom = Math.max(...ys); + doc._height = bottom - top; + doc._width = right - left; + } + index++; + } + })); + return false; + } + + onRotateUp = (e: PointerEvent) => { + this._centerPoints = []; + } + + + _initialAutoHeight = false; _dragHeights = new Map(); @action @@ -521,6 +598,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
{SelectionManager.SelectedDocuments().length === 1 ? DocumentDecorations.DocumentIcon(StrCast(seldoc.props.Document.layout, "...")) : "..."}
+
e.preventDefault()}>
{ const b = this.getBounds(l); return - {InteractionUtils.CreatePolyline(l, b.left, b.top, ActiveInkColor(), ActiveInkWidth(), ActiveInkBezierApprox(), 1, 1, this.InkShape)} + {InteractionUtils.CreatePolyline(l, b.left, b.top, ActiveInkColor(), ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), 1, 1, this.InkShape, "none", false)} ; }), this._points.length <= 1 ? (null) : - {InteractionUtils.CreatePolyline(this._points, B.left, B.top, ActiveInkColor(), ActiveInkWidth(), ActiveInkBezierApprox(), 1, 1, this.InkShape)} + {InteractionUtils.CreatePolyline(this._points, B.left, B.top, ActiveInkColor(), ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), 1, 1, this.InkShape, "none", false)} ] ]; } @@ -901,12 +906,20 @@ Scripting.addGlobal("GestureOverlay", GestureOverlay); Scripting.addGlobal(function setToolglass(tool: any) { runInAction(() => GestureOverlay.Instance.Tool = tool); }); -Scripting.addGlobal(function setPen(width: any, color: any) { +Scripting.addGlobal(function setPen(width: any, color: any, fill: any, arrowStart: any, arrowEnd: any, dash: any) { runInAction(() => { GestureOverlay.Instance.SavedColor = ActiveInkColor(); SetActiveInkColor(color); GestureOverlay.Instance.SavedWidth = ActiveInkWidth(); SetActiveInkWidth(width); + GestureOverlay.Instance.SavedFill = ActiveFillColor(); + SetActiveFillColor(fill); + GestureOverlay.Instance.SavedArrowStart = ActiveArrowStart(); + SetActiveArrowStart(arrowStart); + GestureOverlay.Instance.SavedArrowEnd = ActiveArrowEnd(); + SetActiveArrowStart(arrowEnd); + GestureOverlay.Instance.SavedDash = ActiveDash(); + SetActiveDash(dash); }); }); Scripting.addGlobal(function resetPen() { diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index a7650163f..324665aea 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -58,11 +58,13 @@ export class InkingStroke extends ViewBoxBaseComponent 5 ? strokeColor : "transparent", + // strokeColor, (strokeWidth + 15).toString(), - StrCast(this.layoutDoc.strokeBezier, ActiveInkBezierApprox()), scaleX, scaleY, "", this.props.active() ? "visiblestroke" : "none", false); + StrCast(this.layoutDoc.strokeBezier, ActiveInkBezierApprox()), StrCast(this.layoutDoc.fillColor, ActiveFillColor()), StrCast(this.layoutDoc.arrowStart, ActiveArrowStart()), StrCast(this.layoutDoc.arrowEnd, ActiveArrowEnd()), StrCast(this.layoutDoc.dash, ActiveDash()), scaleX, scaleY, "", this.props.active() ? "visiblestroke" : "none", false); + console.log("#" + strokeColor); return ( { ContextMenu.Instance.addItem({ description: "Analyze Stroke", event: this.analyzeStrokes, icon: "paint-brush" }); @@ -93,6 +96,18 @@ export class InkingStroke extends ViewBoxBaseComponent + {/* + + */} + {/* + + + + + */} + {/* + + */} {hpoints} {points} @@ -105,17 +120,33 @@ export class InkingStroke extends ViewBoxBaseComponent) { super(props); @@ -29,18 +43,103 @@ export default class InkOptionsMenu extends AntimodeMenu { this._canFade = false; // don't let the inking menu fade away } + getColors = () => { + return this._palette; + } + + @action + changeArrow = (arrowStart: string, arrowEnd: string) => { + SetActiveArrowStart(arrowStart); + SetActiveArrowEnd(arrowEnd); + } + @action - changeColor = (color: string) => { + changeColor = (color: string, type: string) => { const col: ColorState = { hex: color, hsl: { a: 0, h: 0, s: 0, l: 0, source: "" }, hsv: { a: 0, h: 0, s: 0, v: 0, source: "" }, rgb: { a: 0, r: 0, b: 0, g: 0, source: "" }, oldHue: 0, source: "", }; - SetActiveInkColor(Utils.colorString(col)); + if (type === "color") { + SetActiveInkColor(Utils.colorString(col)); + } else if (type === "fill") { + SetActiveFillColor(Utils.colorString(col)); + } } + @action + editProperties = (value: any, field: string) => { + SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => { + const doc = Document(element.rootDoc); + if (doc.type === DocumentType.INK) { + switch (field) { + case "width": + doc.strokeWidth = Number(value); + break; + case "color": + doc.color = String(value); + break; + case "fill": + doc.fillColor = String(value); + break; + case "bezier": + // doc.strokeBezier === 300 ? doc.strokeBezier = 0 : doc.strokeBezier = 300; + break; + case "arrowStart": + doc.arrowStart = String(value); + break; + case "arrowEnd": + doc.arrowEnd = String(value); + break; + case "dash": + doc.dash = Number(value); + default: + break; + } + } + })); + } + + @action changeBezier = (e: React.PointerEvent): void => { SetActiveBezierApprox(!ActiveInkBezierApprox() ? "300" : ""); + this.editProperties(0, "bezier"); + } + @action + changeDash = (e: React.PointerEvent): void => { + SetActiveDash(ActiveDash() === "0" ? "2" : "0"); + this.editProperties(ActiveDash(), "dash"); + } + + @computed get arrowPicker() { + var currIcon; + for (var i = 0; i < this._arrowStart.length; i++) { + if (this._arrowStart[i] === ActiveArrowStart() && this._arrowEnd[i] === ActiveArrowEnd()) { + currIcon = this._arrowIcons[i]; + } + } + var arrowPicker = ; + if (this._arrowBtn) { + arrowPicker =
+ {arrowPicker} + {this._arrowStart.map((arrowStart, i) => { + return ; + })} +
; + } + return arrowPicker; } @computed get widthPicker() { @@ -58,7 +157,7 @@ export default class InkOptionsMenu extends AntimodeMenu { return ; @@ -68,6 +167,8 @@ export default class InkOptionsMenu extends AntimodeMenu { return widthPicker; } + + @computed get colorPicker() { var colorPicker = ; @@ -94,6 +195,35 @@ export default class InkOptionsMenu extends AntimodeMenu { return colorPicker; } + @computed get fillPicker() { + var fillPicker = ; + if (this._fillBtn) { + fillPicker =
+ {fillPicker} + {this._palette.map(color => { + return ; + })} + +
; + } + return fillPicker; + } + + + @computed get shapeButtons() { return <> {this._buttons.map((btn, i) => )}, + )} ; } + @computed get shapePicker() { + var currIcon; + if (GestureOverlay.Instance.InkShape === "") { + currIcon = "S"; + } else { + for (var i = 0; i < this._icons.length; i++) { + if (GestureOverlay.Instance.InkShape === this._buttons[i]) { + currIcon = this._icons[i]; + } + } + } + var shapePicker = ; + if (this._shapeBtn) { + shapePicker =
+ {shapePicker} + {this._buttons.map((btn, i) => { + return ; + })} +
; + } + return shapePicker; + } + @computed get bezierButton() { return ; } + @computed get dashButton() { + return ; + } + render() { const buttons = [ , - this.shapeButtons, + this.shapePicker, + // this.shapeButtons, this.bezierButton, this.widthPicker, this.colorPicker, + this.fillPicker, + this.arrowPicker, + this.dashButton ]; return this.getElement(buttons); } diff --git a/src/fields/InkField.ts b/src/fields/InkField.ts index 51a5768bf..7cfd74cc4 100644 --- a/src/fields/InkField.ts +++ b/src/fields/InkField.ts @@ -1,7 +1,7 @@ import { Deserializable } from "../client/util/SerializationHelper"; import { serializable, custom, createSimpleSchema, list, object, map } from "serializr"; import { ObjectField } from "./ObjectField"; -import { Copy, ToScriptString, ToString } from "./FieldSymbols"; +import { Copy, ToScriptString, ToString, Update } from "./FieldSymbols"; export enum InkTool { None = "none", @@ -31,6 +31,8 @@ const strokeDataSchema = createSimpleSchema({ export class InkField extends ObjectField { @serializable(list(object(strokeDataSchema))) readonly inkData: InkData; + // inkData: InkData; + constructor(data: InkData) { super(); -- cgit v1.2.3-70-g09d2 From 26d3d6c18d27a4ebb8f00e754bf3ea2cb5b08e00 Mon Sep 17 00:00:00 2001 From: yunahi <60233430+yunahi@users.noreply.github.com> Date: Sat, 20 Jun 2020 02:39:20 +0900 Subject: updated menu/fixed icon --- src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/InteractionUtils.scss | 4 ++ src/client/util/InteractionUtils.tsx | 65 +++++++++++++--------- src/client/views/GestureOverlay.tsx | 12 +++- src/client/views/InkingStroke.scss | 4 ++ src/client/views/MainView.tsx | 4 +- .../collectionFreeForm/InkOptionsMenu.scss | 7 ++- .../collectionFreeForm/InkOptionsMenu.tsx | 42 +++++++++----- 8 files changed, 94 insertions(+), 46 deletions(-) create mode 100644 src/client/util/InteractionUtils.scss (limited to 'src/client/views/collections') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 3d0c0ef4a..324b08603 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -690,7 +690,7 @@ export class CurrentUserUtils { doc.activeInkPen = doc; doc.activeInkColor = StrCast(doc.activeInkColor, "rgb(0, 0, 0)"); doc.activeInkWidth = StrCast(doc.activeInkWidth, "1"); - doc.activeInkBezier = StrCast(doc.activeInkBezier, ""); + doc.activeInkBezier = StrCast(doc.activeInkBezier, "0"); doc.activeFillColor = StrCast(doc.activeFillColor, "none"); doc.activeArrowStart = StrCast(doc.activeArrowStart, "none"); doc.activeArrowEnd = StrCast(doc.activeArrowEnd, "none"); diff --git a/src/client/util/InteractionUtils.scss b/src/client/util/InteractionUtils.scss new file mode 100644 index 000000000..6707157d4 --- /dev/null +++ b/src/client/util/InteractionUtils.scss @@ -0,0 +1,4 @@ +.halo { + opacity: 0.2; + stroke: black; +} \ No newline at end of file diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index c6b96df45..68dcbebe3 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -2,6 +2,7 @@ import React = require("react"); import * as beziercurve from 'bezier-curve'; import * as fitCurve from 'fit-curve'; import InkOptionsMenu from "../views/collections/collectionFreeForm/InkOptionsMenu"; +import "./InteractionUtils.scss"; export namespace InteractionUtils { export const MOUSETYPE = "mouse"; @@ -103,7 +104,7 @@ export namespace InteractionUtils { const newPoints: number[][] = []; const newPts: { X: number; Y: number; }[] = []; //convert to [][] for fitcurve module - for (var i = 0; i < points.length - 1; i++) { + for (var i = 0; i < points.length - 2; i++) { newPoints.push([points[i].X, points[i].Y]); } const bezierCurves = fitCurve(newPoints, parseInt(bezier)); @@ -123,25 +124,38 @@ export namespace InteractionUtils { return ( - - {/* {makeArrow()} */} - + {/* */} - + {/* */} - + + + {/* */} + ); @@ -239,24 +254,24 @@ export namespace InteractionUtils { } points.push({ X: Math.sqrt(Math.pow(radius, 2) - (Math.pow((top - centerY), 2))) + centerX, Y: top }); return points; - case "arrow": - const x1 = left; - const y1 = top; - const x2 = right; - const y2 = bottom; - const L1 = Math.sqrt(Math.pow(Math.abs(x1 - x2), 2) + (Math.pow(Math.abs(y1 - y2), 2))); - const L2 = L1 / 5; - const angle = 0.785398; - const x3 = x2 + (L2 / L1) * ((x1 - x2) * Math.cos(angle) + (y1 - y2) * Math.sin(angle)); - const y3 = y2 + (L2 / L1) * ((y1 - y2) * Math.cos(angle) - (x1 - x2) * Math.sin(angle)); - const x4 = x2 + (L2 / L1) * ((x1 - x2) * Math.cos(angle) - (y1 - y2) * Math.sin(angle)); - const y4 = y2 + (L2 / L1) * ((y1 - y2) * Math.cos(angle) + (x1 - x2) * Math.sin(angle)); - points.push({ X: x1, Y: y1 }); - points.push({ X: x2, Y: y2 }); - points.push({ X: x3, Y: y3 }); - points.push({ X: x4, Y: y4 }); - points.push({ X: x2, Y: y2 }); - return points; + // case "arrow": + // const x1 = left; + // const y1 = top; + // const x2 = right; + // const y2 = bottom; + // const L1 = Math.sqrt(Math.pow(Math.abs(x1 - x2), 2) + (Math.pow(Math.abs(y1 - y2), 2))); + // const L2 = L1 / 5; + // const angle = 0.785398; + // const x3 = x2 + (L2 / L1) * ((x1 - x2) * Math.cos(angle) + (y1 - y2) * Math.sin(angle)); + // const y3 = y2 + (L2 / L1) * ((y1 - y2) * Math.cos(angle) - (x1 - x2) * Math.sin(angle)); + // const x4 = x2 + (L2 / L1) * ((x1 - x2) * Math.cos(angle) - (y1 - y2) * Math.sin(angle)); + // const y4 = y2 + (L2 / L1) * ((y1 - y2) * Math.cos(angle) + (x1 - x2) * Math.sin(angle)); + // points.push({ X: x1, Y: y1 }); + // points.push({ X: x2, Y: y2 }); + // points.push({ X: x3, Y: y3 }); + // points.push({ X: x4, Y: y4 }); + // points.push({ X: x2, Y: y2 }); + // return points; case "line": points.push({ X: left, Y: top }); points.push({ X: right, Y: bottom }); diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 5b6cbc372..01ef0b664 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -681,6 +681,10 @@ export default class GestureOverlay extends Touchable { } else { this._points = []; } + SetActiveArrowStart("none"); + GestureOverlay.Instance.SavedArrowStart = ActiveArrowStart(); + SetActiveArrowEnd("none"); + GestureOverlay.Instance.SavedArrowEnd = ActiveArrowEnd(); document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); } @@ -692,7 +696,9 @@ export default class GestureOverlay extends Touchable { var left = Math.min(...xs); var bottom = Math.max(...ys); var top = Math.min(...ys); - + if (shape === "noRec") { + return; + } if (!gesture) { //if shape options is activated in inkOptionMenu //take second to last point because _point[length-1] is _points[0] @@ -751,7 +757,7 @@ export default class GestureOverlay extends Touchable { case "line": this._points.push({ X: left, Y: top }); this._points.push({ X: right, Y: bottom }); - this._points.push({ X: right, Y: bottom - 1 }); + // this._points.push({ X: right, Y: bottom - 1 }); break; case "arrow": const x1 = left; @@ -770,7 +776,7 @@ export default class GestureOverlay extends Touchable { this._points.push({ X: x3, Y: y3 }); this._points.push({ X: x4, Y: y4 }); this._points.push({ X: x2, Y: y2 }); - this._points.push({ X: x1, Y: y1 - 1 }); + // this._points.push({ X: x1, Y: y1 - 1 }); } } diff --git a/src/client/views/InkingStroke.scss b/src/client/views/InkingStroke.scss index 433433a42..30ab1967e 100644 --- a/src/client/views/InkingStroke.scss +++ b/src/client/views/InkingStroke.scss @@ -4,4 +4,8 @@ stroke-linecap: round; overflow: visible !important; transform-origin: top left; + + svg:not(:root) { + overflow: visible !important; + } } \ No newline at end of file diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 3677746cd..15a6239be 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -5,7 +5,7 @@ import { faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt, faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, - faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye + faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, reaction, runInAction } from 'mobx'; @@ -129,7 +129,7 @@ export class MainView extends React.Component { faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt, faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTrashAlt, faAngleRight, faBell, - faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye); + faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt); this.initEventListeners(); this.initAuthenticationRouters(); } diff --git a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.scss b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.scss index a7f4d4e53..a9fab4c1e 100644 --- a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.scss +++ b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.scss @@ -1,5 +1,10 @@ .antimodeMenu-button { - .color-preview { + .color-previewI { + width: 100%; + height: 40%; + } + + .color-previewII { width: 100%; height: 100%; } diff --git a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx index 96a9cbbdb..894227d84 100644 --- a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx +++ b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx @@ -14,21 +14,26 @@ import { SelectionManager } from "../../../util/SelectionManager"; import { DocumentView } from "../../../views/nodes/DocumentView"; import { Document } from "../../../../fields/documentSchemas"; import { DocumentType } from "../../../documents/DocumentTypes"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; +import { faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSubscript, faSuperscript, faIndent, faEyeDropper, faCaretDown, faPalette, faArrowsAlt, faHighlighter, faLink, faPaintRoller, faSleigh, faBars, faFillDrip, faBrush, faPenNib, faShapes, faArrowLeft, faEllipsisH, faBezierCurve } from "@fortawesome/free-solid-svg-icons"; + +library.add(faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSuperscript, faSubscript, faIndent, faEyeDropper, faCaretDown, faPalette, faArrowsAlt, faHighlighter, faLink, faPaintRoller, faBars, faFillDrip, faBrush, faPenNib, faShapes, faArrowLeft, faEllipsisH, faBezierCurve); @observer export default class InkOptionsMenu extends AntimodeMenu { static Instance: InkOptionsMenu; private _palette = ["D0021B", "F5A623", "F8E71C", "8B572A", "7ED321", "417505", "9013FE", "4A90E2", "50E3C2", "B8E986", "000000", "4A4A4A", "9B9B9B", "FFFFFF", "none"]; - private _width = ["1", "5", "10", "100", "200", "300"]; + private _width = ["1", "5", "10", "100"]; // private _buttons = ["circle", "triangle", "rectangle", "arrow", "line"]; // private _icons = ["O", "∆", "ロ", "➜", "-"]; - private _buttons = ["circle", "triangle", "rectangle", "line", ""]; - private _icons = ["O", "∆", "ロ", "-", " "]; + private _buttons = ["circle", "triangle", "rectangle", "line", "", "noRec"]; + private _icons = ["O", "∆", "ロ", "––", " ", "✖︎"]; //arrowStart and arrowEnd must match and defs must exist in Inking Stroke private _arrowStart = ["url(#arrowHead)", "url(#arrowHead)", "url(#dot)", "url(#dot)", "none"]; private _arrowEnd = ["none", "url(#arrowEnd)", "none", "url(#dot)", "none"]; - private _arrowIcons = ["➡︎", "↔︎", "o-", "o-o", " "]; + private _arrowIcons = ["→", "↔︎", "・", "・・", " "]; @observable _colorBtn = false; @observable _widthBtn = false; @@ -116,6 +121,7 @@ export default class InkOptionsMenu extends AntimodeMenu { for (var i = 0; i < this._arrowStart.length; i++) { if (this._arrowStart[i] === ActiveArrowStart() && this._arrowEnd[i] === ActiveArrowEnd()) { currIcon = this._arrowIcons[i]; + } } var arrowPicker = ; if (this._widthBtn) { widthPicker =
@@ -176,7 +182,9 @@ export default class InkOptionsMenu extends AntimodeMenu { title="colorChanger" onPointerDown={action(e => this._colorBtn = !this._colorBtn)} style={{ backgroundColor: this._colorBtn ? "121212" : "" }}> -
+ +
+ ; if (this._colorBtn) { colorPicker =
@@ -187,7 +195,8 @@ export default class InkOptionsMenu extends AntimodeMenu { key={color} onPointerDown={action(() => { this.changeColor(color, "color"); this._colorBtn = false; this.editProperties(color, "color"); })} style={{ backgroundColor: this._colorBtn ? "121212" : "" }}> -
+ {/* */} +
; })}
; @@ -202,7 +211,8 @@ export default class InkOptionsMenu extends AntimodeMenu { title="fillChanger" onPointerDown={action(e => this._fillBtn = !this._fillBtn)} style={{ backgroundColor: this._fillBtn ? "121212" : "" }}> -
+ +
; if (this._fillBtn) { fillPicker =
@@ -213,7 +223,7 @@ export default class InkOptionsMenu extends AntimodeMenu { key={color} onPointerDown={action(() => { this.changeColor(color, "fill"); this._fillBtn = false; this.editProperties(color, "fill"); })} style={{ backgroundColor: this._fillBtn ? "121212" : "" }}> -
+
; })} @@ -240,7 +250,7 @@ export default class InkOptionsMenu extends AntimodeMenu { @computed get shapePicker() { var currIcon; if (GestureOverlay.Instance.InkShape === "") { - currIcon = "S"; + currIcon = ; } else { for (var i = 0; i < this._icons.length; i++) { if (GestureOverlay.Instance.InkShape === this._buttons[i]) { @@ -252,7 +262,7 @@ export default class InkOptionsMenu extends AntimodeMenu { className="antimodeMenu-button" key="shape" onPointerDown={action(e => this._shapeBtn = !this._shapeBtn)} - style={{ backgroundColor: this._widthBtn ? "121212" : "" }}> + style={{ backgroundColor: this._shapeBtn ? "121212" : "" }}> {currIcon} ; if (this._shapeBtn) { @@ -280,7 +290,8 @@ export default class InkOptionsMenu extends AntimodeMenu { key="bezier" onPointerDown={e => this.changeBezier(e)} style={{ backgroundColor: ActiveInkBezierApprox() ? "121212" : "" }}> - B + + ; } @@ -291,13 +302,16 @@ export default class InkOptionsMenu extends AntimodeMenu { key="dash" onPointerDown={e => this.changeDash(e)} style={{ backgroundColor: ActiveDash() !== "0" ? "121212" : "" }}> - ... + + ; } render() { const buttons = [ - , + , this.shapePicker, // this.shapeButtons, this.bezierButton, -- cgit v1.2.3-70-g09d2 From 73299e354af3df1a5df712e24b32e14b5b0ec994 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 19 Jun 2020 18:17:59 -0400 Subject: a bunch of ink fixes --- src/client/util/InteractionUtils.tsx | 31 +++++++++++----------- src/client/views/GestureOverlay.tsx | 19 +++++++++---- src/client/views/InkingStroke.tsx | 5 ++-- .../collectionFreeForm/InkOptionsMenu.tsx | 6 ++--- 4 files changed, 35 insertions(+), 26 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index 9a9bb3d42..64facaca4 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -3,6 +3,7 @@ import * as beziercurve from 'bezier-curve'; import * as fitCurve from 'fit-curve'; import InkOptionsMenu from "../views/collections/collectionFreeForm/InkOptionsMenu"; import "./InteractionUtils.scss"; +import { Utils } from "../../Utils"; export namespace InteractionUtils { export const MOUSETYPE = "mouse"; @@ -93,15 +94,15 @@ export namespace InteractionUtils { export function CreatePolyline(points: { X: number, Y: number }[], left: number, top: number, color: string, width: number, strokeWidth: number, bezier: string, fill: string, arrowStart: string, arrowEnd: string, - dash: string, scalex: number, scaley: number, shape: string, pevents: string, drawHalo: boolean) { + dash: string, scalex: number, scaley: number, shape: string, pevents: string, drawHalo: boolean, nodefs: boolean) { let pts: { X: number; Y: number; }[] = []; if (shape) { //if any of the shape are true pts = makePolygon(shape, points); } else if (points.length > 1 && points[points.length - 1].X === points[0].X && points[points.length - 1].Y === points[0].Y) { //pointer is up (first and last points are the same) - points.pop(); const newPoints = points.reduce((p, pts) => { p.push([pts.X, pts.Y]); return p; }, [] as number[][]); + newPoints.pop(); const bezierCurves = fitCurve(newPoints, parseInt(bezier)); for (const curve of bezierCurves) { @@ -117,28 +118,26 @@ export namespace InteractionUtils { `${(pt.X - left - width / 2) * scalex + width / 2}, ${(pt.Y - top - width / 2) * scaley + width / 2} `, ""); const dashArray = String(Number(width) * Number(dash)); - - return ( - - + const defGuid = Utils.GenerateGuid(); + return ( {/* setting the svg fill sets the arrowhead fill */} + {nodefs ? (null) : + - - {/* */} - + + - - {/* */} - + + - + } ); diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 95dc2c7d4..43aa63eb1 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -24,6 +24,7 @@ import { RadialMenu } from "./nodes/RadialMenu"; import HorizontalPalette from "./Palette"; import { Touchable } from "./Touchable"; import TouchScrollableMenu, { TouchScrollableMenuItem } from "./TouchScrollableMenu"; +import HeightLabel from "./collections/collectionMulticolumn/MultirowHeightLabel"; @observer export default class GestureOverlay extends Touchable { @@ -812,20 +813,28 @@ export default class GestureOverlay extends Touchable { } @computed get elements() { - - const B = this.svgBounds; const width = Number(ActiveInkWidth()); + const B = this.svgBounds; + B.left = B.left - width / 2; + B.right = B.right + width / 2; + B.top = B.top - width / 2; + B.bottom = B.bottom + width / 2; + B.width += width; + B.height += width; return [ this.props.children, this._palette, [this._strokes.map((l, i) => { const b = this.getBounds(l); return - {InteractionUtils.CreatePolyline(l, b.left, b.top, ActiveInkColor(), width, width, ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), 1, 1, this.InkShape, "none", false)} + {InteractionUtils.CreatePolyline(l, b.left, b.top, ActiveInkColor(), width, width, + ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), + ActiveDash(), 1, 1, this.InkShape, "none", false, false)} ; }), - this._points.length <= 1 ? (null) : - {InteractionUtils.CreatePolyline(this._points, B.left, B.top, ActiveInkColor(), width, width, ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), 1, 1, this.InkShape, "none", false)} + this._points.length <= 1 ? (null) : + {InteractionUtils.CreatePolyline(this._points, B.left, B.top, ActiveInkColor(), width, width, ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), 1, 1, this.InkShape, "none", false, false)} ] ]; } diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index dc5d387d0..627760c38 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -15,6 +15,7 @@ import { FieldView, FieldViewProps } from "./nodes/FieldView"; import React = require("react"); import { Scripting } from "../util/Scripting"; import { Doc } from "../../fields/Doc"; +import { NodeFlags } from "typescript"; library.add(faPaintBrush); @@ -56,11 +57,11 @@ export class InkingStroke extends ViewBoxBaseComponent 5 ? strokeColor : "transparent", strokeWidth, (strokeWidth + 15), StrCast(this.layoutDoc.strokeBezier, ActiveInkBezierApprox()), StrCast(this.layoutDoc.fillColor, ActiveFillColor()), - "none", "none", "0", scaleX, scaleY, "", this.props.active() ? "visiblestroke" : "none", false); + "none", "none", "0", scaleX, scaleY, "", this.props.active() ? "visiblestroke" : "none", false, true); return ( Date: Wed, 24 Jun 2020 00:39:56 +0900 Subject: fixed inkmenu --- src/client/views/GestureOverlay.tsx | 4 +++- .../collectionFreeForm/InkOptionsMenu.tsx | 23 +++++++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 43aa63eb1..85695bbac 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -632,7 +632,9 @@ export default class GestureOverlay extends Touchable { this.makePolygon(this.InkShape, false); this.dispatchGesture(GestureUtils.Gestures.Stroke); this._points = []; - this.InkShape = ""; + if (this.InkShape !== "noRec") { + this.InkShape = ""; + } } // if we're not drawing in a toolglass try to recognize as gesture else { diff --git a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx index fb2640249..e43e6bbdd 100644 --- a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx +++ b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx @@ -16,7 +16,7 @@ import { Document } from "../../../../fields/documentSchemas"; import { DocumentType } from "../../../documents/DocumentTypes"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; -import { faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSubscript, faSuperscript, faIndent, faEyeDropper, faCaretDown, faPalette, faArrowsAlt, faHighlighter, faLink, faPaintRoller, faSleigh, faBars, faFillDrip, faBrush, faPenNib, faShapes, faArrowLeft, faEllipsisH, faBezierCurve } from "@fortawesome/free-solid-svg-icons"; +import { faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSubscript, faSuperscript, faIndent, faEyeDropper, faCaretDown, faPalette, faArrowsAlt, faHighlighter, faLink, faPaintRoller, faSleigh, faBars, faFillDrip, faBrush, faPenNib, faShapes, faArrowLeft, faEllipsisH, faBezierCurve, } from "@fortawesome/free-solid-svg-icons"; library.add(faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSuperscript, faSubscript, faIndent, faEyeDropper, faCaretDown, faPalette, faArrowsAlt, faHighlighter, faLink, faPaintRoller, faBars, faFillDrip, faBrush, faPenNib, faShapes, faArrowLeft, faEllipsisH, faBezierCurve); @@ -28,12 +28,12 @@ export default class InkOptionsMenu extends AntimodeMenu { private _width = ["1", "5", "10", "100"]; // private _buttons = ["circle", "triangle", "rectangle", "arrow", "line"]; // private _icons = ["O", "∆", "ロ", "➜", "-"]; - private _buttons = ["circle", "triangle", "rectangle", "line", "", "noRec"]; - private _icons = ["O", "∆", "ロ", "––", " ", "✖︎"]; + private _buttons = ["circle", "triangle", "rectangle", "line", "noRec", "",]; + private _icons = ["O", "∆", "ロ", "⎯", "✖︎", " "]; //arrowStart and arrowEnd must match and defs must exist in Inking Stroke private _arrowStart = ["arrowHead", "arrowHead", "dot", "dot", "none"]; private _arrowEnd = ["none", "arrowEnd", "none", "dot", "none"]; - private _arrowIcons = ["→", "↔︎", "・", "・・", " "]; + private _arrowIcons = ["→", "↔︎", "•", "••", " "]; @observable _colorBtn = false; @observable _widthBtn = false; @@ -121,7 +121,9 @@ export default class InkOptionsMenu extends AntimodeMenu { for (var i = 0; i < this._arrowStart.length; i++) { if (this._arrowStart[i] === ActiveArrowStart() && this._arrowEnd[i] === ActiveArrowEnd()) { currIcon = this._arrowIcons[i]; - + if (this._arrowIcons[i] === " ") { + currIcon = "➤"; + } } } var arrowPicker =
+
{this.props.GetValue()}
+ {this.renderEditor()} +
: this.renderEditor(); } else { this.props.autosuggestProps?.resetValue(); return (this.props.contents instanceof ObjectField ? (null) : diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index 2aac81146..50f0534bd 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -82,8 +82,6 @@ text-overflow: ellipsis; white-space: pre-wrap; min-width: 10px; - // width:100%;//width: max-content; - } .treeViewItem-openRight { @@ -100,6 +98,7 @@ border-left: dashed 1px #00000042; } +.treeViewItem-header-editing, .treeViewItem-header { border: transparent 1px solid; display: flex; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 68dc0ced2..7ffecdc26 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -13,7 +13,7 @@ import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from "../../documents/DocumentTypes"; import { DocumentManager } from '../../util/DocumentManager'; import { SnappingManager } from '../../util/SnappingManager'; -import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager"; +import { DragManager, dropActionType } from "../../util/DragManager"; import { Scripting } from '../../util/Scripting'; import { SelectionManager } from '../../util/SelectionManager'; import { Transform } from '../../util/Transform'; @@ -55,7 +55,7 @@ export interface TreeViewProps { ScreenToLocalTransform: () => Transform; backgroundColor?: (doc: Doc) => string | undefined; outerXf: () => { translateX: number, translateY: number }; - treeViewId: Doc; + treeViewDoc: Doc; parentKey: string; active: (outsideReaction?: boolean) => boolean; treeViewHideHeaderFields: () => boolean; @@ -76,31 +76,32 @@ export interface TreeViewProps { * treeViewExpandedView : name of field whose contents are being displayed as the document's subtree */ class TreeView extends React.Component { - static _editTitleScript: ScriptField | undefined; + private _editTitleScript: ScriptField | undefined; private _header?: React.RefObject = React.createRef(); private _treedropDisposer?: DragManager.DragDropDisposer; private _dref = React.createRef(); private _tref = React.createRef(); private _docRef = React.createRef(); + private _uniqueId = Utils.GenerateGuid(); + private _editMaxWidth: number | string = 0; + get doc() { return this.props.document; } get noviceMode() { return BoolCast(Doc.UserDoc().noviceMode, false); } - get displayName() { return "TreeView(" + this.props.document.title + ")"; } // this makes mobx trace() statements more descriptive - get defaultExpandedView() { return this.childDocs ? this.fieldKey : StrCast(this.props.document.defaultExpandedView, this.noviceMode ? "layout" : "fields"); } + get displayName() { return "TreeView(" + this.doc.title + ")"; } // this makes mobx trace() statements more descriptive + get defaultExpandedView() { return this.childDocs ? this.fieldKey : StrCast(this.doc.defaultExpandedView, this.noviceMode ? "layout" : "fields"); } @observable _overrideTreeViewOpen = false; // override of the treeViewOpen field allowing the display state to be independent of the document's state - set treeViewOpen(c: boolean) { if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c; else this.props.document.treeViewOpen = this._overrideTreeViewOpen = c; } - @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.props.document.treeViewPreventOpen && BoolCast(this.props.document.treeViewOpen)) || this._overrideTreeViewOpen; } - @computed get treeViewExpandedView() { return StrCast(this.props.document.treeViewExpandedView, this.defaultExpandedView); } + set treeViewOpen(c: boolean) { if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c; else this.doc.treeViewOpen = this._overrideTreeViewOpen = c; } + @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.doc.treeViewPreventOpen && BoolCast(this.doc.treeViewOpen)) || this._overrideTreeViewOpen; } + @computed get treeViewExpandedView() { return StrCast(this.doc.treeViewExpandedView, this.defaultExpandedView); } @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containingCollection.maxEmbedHeight, 200); } - @computed get dataDoc() { return this.props.document[DataSym]; } - @computed get fieldKey() { - const splits = StrCast(Doc.LayoutField(this.props.document)).split("fieldKey={\'"); - return splits.length > 1 ? splits[1].split("\'")[0] : "data"; - } + @computed get dataDoc() { return this.doc[DataSym]; } + @computed get layoutDoc() { return Doc.Layout(this.doc); } + @computed get fieldKey() { const splits = StrCast(Doc.LayoutField(this.doc)).split("fieldKey={\'"); return splits.length > 1 ? splits[1].split("\'")[0] : "data"; } childDocList(field: string) { - const layout = Doc.LayoutField(this.props.document) instanceof Doc ? Doc.LayoutField(this.props.document) as Doc : undefined; + const layout = Doc.LayoutField(this.doc) instanceof Doc ? Doc.LayoutField(this.doc) as Doc : undefined; return ((this.props.dataDoc ? DocListCast(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field (layout ? Cast(layout[field], listSpec(Doc)) : undefined) || // else if there's a layout doc, display it's fields - Cast(this.props.document[field], listSpec(Doc))) as Doc[]; // otherwise use the document's data field + Cast(this.doc[field], listSpec(Doc))) as Doc[]; // otherwise use the document's data field } @computed get childDocs() { return this.childDocList(this.fieldKey); } @computed get childLinks() { return this.childDocList("links"); } @@ -110,21 +111,27 @@ class TreeView extends React.Component { } @undoBatch openRight = () => this.props.addDocTab(this.props.document, "onRight", this.props.libraryPath); + @undoBatch openRight = () => this.props.addDocTab(this.doc, "onRight", this.props.libraryPath); @undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { - return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc); + return this.doc !== target && this.props.deleteDoc(doc) && addDoc(doc); } @undoBatch @action remove = (doc: Doc | Doc[], key: string) => { - return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => - flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true); + return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true); } @undoBatch @action removeDoc = (doc: Doc | Doc[]) => { return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.RemoveDocFromList(this.props.containingCollection, Doc.LayoutFieldKey(this.props.containingCollection), doc), true); } + constructor(props: any) { + super(props); + this._editTitleScript = ScriptField.MakeFunction(`setInPlace(self, 'editTitle', '${this._uniqueId}')`); + if (Doc.GetT(this.doc, "editTitle", "string", true) === "*") Doc.SetInPlace(this.doc, "editTitle", this._uniqueId, false); + } + protected createTreeDropTarget = (ele: HTMLDivElement) => { this._treedropDisposer?.(); - ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this), undefined, this.preTreeDrop.bind(this)), this.props.document); + ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this), undefined, this.preTreeDrop.bind(this)), this.doc); } onPointerEnter = (e: React.PointerEvent): void => { @@ -136,7 +143,9 @@ class TreeView extends React.Component { } onPointerLeave = (e: React.PointerEvent): void => { Doc.UnBrushDoc(this.dataDoc); - this._header!.current!.className = "treeViewItem-header"; + if (this._header?.current?.className !== "treeViewItem-header-editing") { + this._header!.current!.className = "treeViewItem-header"; + } document.removeEventListener("pointermove", this.onDragMove, true); } onDragMove = (e: PointerEvent): void => { @@ -144,7 +153,7 @@ class TreeView extends React.Component { const pt = [e.clientX, e.clientY]; const rect = this._header!.current!.getBoundingClientRect(); const before = pt[1] < rect.top + rect.height / 2; - const inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && DocListCast(this.dataDoc[this.fieldKey]).length); + const inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && this.childDocList.length); this._header!.current!.className = "treeViewItem-header"; if (inside) this._header!.current!.className += " treeViewItem-header-inside"; else if (before) this._header!.current!.className += " treeViewItem-header-above"; @@ -155,42 +164,38 @@ class TreeView extends React.Component { editableView = (key: string, style?: string) => ( StrCast(this.props.document[key])} + GetValue={() => StrCast(this.doc[key])} SetValue={undoBatch((value: string) => { - Doc.SetInPlace(this.props.document, key, value, false) || true; - Doc.SetInPlace(this.props.document, "editTitle", undefined, false); + Doc.SetInPlace(this.doc, key, value, false) || true; + Doc.SetInPlace(this.doc, "editTitle", undefined, false); })} OnFillDown={undoBatch((value: string) => { - Doc.SetInPlace(this.props.document, key, value, false); + Doc.SetInPlace(this.doc, key, value, false); const doc = Docs.Create.FreeformDocument([], { title: "-", x: 0, y: 0, _width: 100, _height: 25, _LODdisable: true, templates: new List([Templates.Title.Layout]) }); - Doc.SetInPlace(this.props.document, "editTitle", undefined, false); - Doc.SetInPlace(doc, "editTitle", true, false); + Doc.SetInPlace(this.doc, "editTitle", undefined, false); + Doc.SetInPlace(doc, "editTitle", "*", false); return this.props.addDocument(doc); })} onClick={() => { SelectionManager.DeselectAll(); - Doc.UserDoc().activeSelection = new List([this.props.document]); + Doc.UserDoc().activeSelection = new List([this.doc]); return false; }} OnTab={undoBatch((shift?: boolean) => { - EditableView.loadId = this.dataDoc[Id]; shift ? this.props.outdentDocument?.() : this.props.indentDocument?.(); - setTimeout(() => { // unsetting/setting brushing for this doc will recreate & refocus this editableView after all other treeview changes have been made to the Dom (which may remove focus from this document). - Doc.UnBrushDoc(this.props.document); - Doc.BrushDoc(this.props.document); - EditableView.loadId = ""; - }, 0); + setTimeout(() => Doc.SetInPlace(this.doc, "editTitle", "*", false), 0); })} />) preTreeDrop = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => { const dragData = de.complete.docDragData; - dragData && (dragData.dropAction = this.props.treeViewId[Id] === dragData.treeViewId ? "same" : dragData.dropAction); + dragData && (dragData.dropAction = this.props.treeViewDoc === dragData.treeViewDoc ? "same" : dragData.dropAction); } @undoBatch @@ -198,18 +203,18 @@ class TreeView extends React.Component { const pt = [de.x, de.y]; const rect = this._header!.current!.getBoundingClientRect(); const before = pt[1] < rect.top + rect.height / 2; - const inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && DocListCast(this.dataDoc[this.fieldKey]).length); + const inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && this.childDocList.length); const complete = de.complete; if (complete.linkDragData) { const sourceDoc = complete.linkDragData.linkSourceDocument; - const destDoc = this.props.document; + const destDoc = this.doc; DocUtils.MakeLink({ doc: sourceDoc }, { doc: destDoc }, "tree link"); e.stopPropagation(); } const docDragData = complete.docDragData; if (docDragData) { e.stopPropagation(); - if (docDragData.draggedDocuments[0] === this.props.document) return true; + if (docDragData.draggedDocuments[0] === this.doc) return true; const parentAddDoc = (doc: Doc | Doc[]) => this.props.addDocument(doc, undefined, before); let addDoc = parentAddDoc; if (inside) { @@ -222,35 +227,28 @@ class TreeView extends React.Component { return false; } - docTransform = () => { - const { scale, translateX, translateY } = Utils.GetScreenTransform(this._dref.current!); - const outerXf = this.props.outerXf(); - const offset = this.props.ScreenToLocalTransform().transformDirection((outerXf.translateX - translateX), outerXf.translateY - translateY); - const finalXf = this.props.ScreenToLocalTransform().translate(offset[0], offset[1]); - - return finalXf; - } - getTransform = () => { - const { scale, translateX, translateY } = Utils.GetScreenTransform(this._tref.current!); + refTransform = (ref: HTMLDivElement) => { + const { scale, translateX, translateY } = Utils.GetScreenTransform(ref); const outerXf = this.props.outerXf(); const offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); - const finalXf = this.props.ScreenToLocalTransform().translate(offset[0], offset[1]); - return finalXf; + return this.props.ScreenToLocalTransform().translate(offset[0], offset[1]); } + docTransform = () => this.refTransform(this._dref.current!) + getTransform = () => this.refTransform(this._tref.current!); docWidth = () => { - const layoutDoc = Doc.Layout(this.props.document); + const layoutDoc = this.layoutDoc; const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]()); if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.panelWidth() - 20)); return NumCast(layoutDoc._nativeWidth) ? Math.min(layoutDoc[WidthSym](), this.props.panelWidth() - 20) : this.props.panelWidth() - 20; } docHeight = () => { - const layoutDoc = Doc.Layout(this.props.document); + const layoutDoc = this.layoutDoc; const bounds = this.boundsOfCollectionDocument; return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => { const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]()); if (aspect) return this.docWidth() * aspect; if (bounds) return this.docWidth() * (bounds.b - bounds.y) / (bounds.r - bounds.x); - return layoutDoc._fitWidth ? (!this.props.document._nativeHeight ? NumCast(this.props.containingCollection._height) : + return layoutDoc._fitWidth ? (!this.doc._nativeHeight ? NumCast(this.props.containingCollection._height) : Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth, NumCast(this.props.containingCollection._height)))) : NumCast(layoutDoc._height) ? NumCast(layoutDoc._height) : 50; @@ -259,7 +257,7 @@ class TreeView extends React.Component { @computed get expandedField() { const ids: { [key: string]: string } = {}; - const doc = this.props.document; + const doc = this.doc; doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)); const rows: JSX.Element[] = []; @@ -273,13 +271,12 @@ class TreeView extends React.Component { const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce( (flg, doc) => flg && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true), true); contentElement = TreeView.GetChildElements(contents instanceof Doc ? [contents] : - DocListCast(contents), this.props.treeViewId, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, + DocListCast(contents), this.props.treeViewDoc, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, [...this.props.renderedIds, doc[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields); } else { - contentElement = { return rows; } - rtfWidth = () => Math.min(Doc.Layout(this.props.document)?.[WidthSym](), this.props.panelWidth() - 20); - rtfHeight = () => this.rtfWidth() < Doc.Layout(this.props.document)?.[WidthSym]() ? Math.min(Doc.Layout(this.props.document)?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT; + rtfWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.props.panelWidth() - 20); + rtfHeight = () => this.rtfWidth() < this.layoutDoc?.[WidthSym]() ? Math.min(this.layoutDoc?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT; @computed get renderContent() { TraceMobx(); @@ -320,32 +317,32 @@ class TreeView extends React.Component { const docs = expandKey === "links" ? this.childLinks : this.childDocs; const sortKey = `${this.fieldKey}-sortAscending`; return
    { - this.props.document[sortKey] = (this.props.document[sortKey] ? false : (this.props.document[sortKey] === false ? undefined : true)); + this.doc[sortKey] = (this.doc[sortKey] ? false : (this.doc[sortKey] === false ? undefined : true)); e.stopPropagation(); }}> {!docs ? (null) : - TreeView.GetChildElements(docs, this.props.treeViewId, Doc.Layout(this.props.document), + TreeView.GetChildElements(docs, this.props.treeViewDoc, this.layoutDoc, this.dataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, - StrCast(this.props.document.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, + StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, - [...this.props.renderedIds, this.props.document[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields)} + [...this.props.renderedIds, this.doc[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields)}
; } else if (this.treeViewExpandedView === "fields") { - return
    + return
      {this.expandedField}
    ; } else { - const layoutDoc = Doc.Layout(this.props.document); + const layoutDoc = this.layoutDoc; const panelHeight = layoutDoc.type === DocumentType.RTF ? this.rtfHeight : this.docHeight; const panelWidth = layoutDoc.type === DocumentType.RTF ? this.rtfWidth : this.docWidth; - return
    + return
    { } } - get onCheckedClick() { return this.props.onCheckedClick || ScriptCast(this.props.document.onCheckedClick); } + get onCheckedClick() { return this.props.onCheckedClick || ScriptCast(this.doc.onCheckedClick); } @action bulletClick = (e: React.MouseEvent) => { - if (this.onCheckedClick && this.props.document.type !== DocumentType.COL) { + if (this.onCheckedClick && this.doc.type !== DocumentType.COL) { // this.props.document.treeViewChecked = this.props.document.treeViewChecked === "check" ? "x" : this.props.document.treeViewChecked === "x" ? undefined : "check"; this.onCheckedClick.script.run({ - this: this.props.document.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.props.document, + this: this.doc.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.doc, heading: this.props.containingCollection.title, - checked: this.props.document.treeViewChecked === "check" ? "x" : this.props.document.treeViewChecked === "x" ? undefined : "check", - containingTreeView: this.props.treeViewId, + checked: this.doc.treeViewChecked === "check" ? "x" : this.doc.treeViewChecked === "x" ? undefined : "check", + containingTreeView: this.props.treeViewDoc, }, console.log); } else { this.treeViewOpen = !this.treeViewOpen; @@ -392,104 +389,110 @@ class TreeView extends React.Component { @computed get renderBullet() { - const checked = this.props.document.type === DocumentType.COL ? undefined : this.onCheckedClick ? (this.props.document.treeViewChecked ? this.props.document.treeViewChecked : "unchecked") : undefined; + const checked = this.doc.type === DocumentType.COL ? undefined : this.onCheckedClick ? (this.doc.treeViewChecked ?? "unchecked") : undefined; return
    + style={{ color: StrCast(this.doc.color, checked === "unchecked" ? "white" : "inherit"), opacity: checked === "unchecked" ? undefined : 0.4 }}> {}
    ; } showContextMenu = (e: React.MouseEvent) => { this._docRef.current?.ContentDiv && simulateMouseClick(this._docRef.current.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); - e.stopPropagation(); } focusOnDoc = (doc: Doc) => DocumentManager.Instance.getFirstDocumentView(doc)?.props.focus(doc, true); - contextMenuItems = () => { - const focusScript = ScriptField.MakeFunction(`DocFocus(self)`); - return [{ script: focusScript!, label: "Focus" }]; - } + contextMenuItems = () => [{ script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }] + truncateTitleWidth = () => NumCast(this.props.treeViewDoc.treeViewTruncateTitleWidth, 0); + showTitleEdit = () => ["*", this._uniqueId].includes(Doc.GetT(this.doc, "editTitle", "string", true) || "") /** * Renders the EditableView title element for placement into the tree. */ @computed get renderTitle() { TraceMobx(); - (!TreeView._editTitleScript) && (TreeView._editTitleScript = ScriptField.MakeFunction("setInPlace(self, 'editTitle', true)")); - const headerElements = ( + const headerElements = this.props.treeViewHideHeaderFields() ? (null) : <> - this.showContextMenu(e)}> + { this.showContextMenu(e); e.stopPropagation(); }} /> { if (this.treeViewOpen) { - this.props.document.treeViewExpandedView = this.treeViewExpandedView === this.fieldKey ? (Doc.UserDoc().noviceMode ? "layout" : "fields") : - this.treeViewExpandedView === "fields" && Doc.Layout(this.props.document) ? "layout" : - this.treeViewExpandedView === "layout" && this.props.document.links ? "links" : + this.doc.treeViewExpandedView = this.treeViewExpandedView === this.fieldKey ? (Doc.UserDoc().noviceMode ? "layout" : "fields") : + this.treeViewExpandedView === "fields" && this.layoutDoc ? "layout" : + this.treeViewExpandedView === "layout" && DocListCast(this.doc.links).length ? "links" : this.childDocs ? this.fieldKey : (Doc.UserDoc().noviceMode ? "layout" : "fields"); } this.treeViewOpen = true; })}> {this.treeViewExpandedView} - ); - const openRight = (
    - -
    ); + ; + const view = this.showTitleEdit() ? this.editableView("title") : + ; return <>
    - {Doc.GetT(this.props.document, "editTitle", "boolean", true) ? - this.editableView("title") : - } + {view}
    - {this.props.treeViewHideHeaderFields() ? (null) : headerElements} - {openRight} + {headerElements} +
    + +
    ; } render() { TraceMobx(); - const sorting = this.props.document[`${this.fieldKey}-sortAscending`]; - //setTimeout(() => runInAction(() => untracked(() => this._overrideTreeViewOpen = this.treeViewOpen)), 0); + const sorting = this.doc[`${this.fieldKey}-sortAscending`]; + if (this.showTitleEdit()) { // find containing CollectionTreeView and set our maximum width so the containing tree view won't have to scroll + let par: any = this._header?.current; + if (par) { + while (par && par.className !== "collectionTreeView-dropTarget") par = par.parentNode; + if (par) { + const par_rect = (par as HTMLElement).getBoundingClientRect(); + const my_recct = this._docRef.current?.ContentDiv?.getBoundingClientRect(); + this._editMaxWidth = Math.max(100, par_rect.right - (my_recct?.left || 0)); + } + } + } else this._editMaxWidth = ""; return
    this.props.active() && SelectionManager.DeselectAll()}>
  • -
    { +
    { if (this.props.active(true)) { e.stopPropagation(); e.preventDefault(); @@ -507,14 +510,14 @@ class TreeView extends React.Component { {this.renderTitle}
    - {!this.treeViewOpen || this.props.renderedIds.indexOf(this.props.document[Id]) !== -1 ? (null) : this.renderContent} + {!this.treeViewOpen || this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? (null) : this.renderContent}
  • ; } public static GetChildElements( childDocs: Doc[], - treeViewId: Doc, + treeViewDoc: Doc, containingCollection: Doc, dataDoc: Doc | undefined, key: string, @@ -624,7 +627,7 @@ class TreeView extends React.Component { libraryPath={libraryPath ? [...libraryPath, containingCollection] : undefined} containingCollection={containingCollection} prevSibling={docs[i]} - treeViewId={treeViewId} + treeViewDoc={treeViewDoc} key={child[Id]} indentDocument={indent} outdentDocument={outdent} @@ -665,21 +668,22 @@ export class CollectionTreeView extends CollectionSubView { this.treedropDisposer?.(); if (this._mainEle = ele) { - this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.props.Document, this.onInternalPreDrop.bind(this)); + this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.doc, this.onInternalPreDrop.bind(this)); } } protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => { const dragData = de.complete.docDragData; if (dragData) { - if (targetAction && !dragData.draggedDocuments.some(d => d.context === this.props.Document && this.childDocs.includes(d))) { + if (targetAction && !dragData.draggedDocuments.some(d => d.context === this.doc && this.childDocs.includes(d))) { dragData.dropAction = targetAction; - } else dragData.dropAction = this.props.Document[Id] === dragData?.treeViewId ? "same" : dragData.dropAction; + } else dragData.dropAction = this.doc === dragData?.treeViewDoc ? "same" : dragData.dropAction; } } @@ -691,7 +695,7 @@ export class CollectionTreeView extends CollectionSubView { const docs = doc instanceof Doc ? [doc] : doc; - const targetDataDoc = this.props.Document[DataSym]; + const targetDataDoc = this.doc[DataSym]; const value = DocListCast(targetDataDoc[this.props.fieldKey]); const result = value.filter(v => !docs.includes(v)); if (result.length !== value.length) { @@ -704,9 +708,9 @@ export class CollectionTreeView extends CollectionSubView, before?: boolean): boolean => { const doAddDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => - flg && Doc.AddDocToList(this.props.Document[DataSym], this.props.fieldKey, doc, relativeTo, before, false, false, false), true); - if (this.props.Document.resolvedDataDoc instanceof Promise) { - this.props.Document.resolvedDataDoc.then((resolved: any) => doAddDoc(doc)); + flg && Doc.AddDocToList(this.doc[DataSym], this.props.fieldKey, doc, relativeTo, before, false, false, false), true); + if (this.doc.resolvedDataDoc instanceof Promise) { + this.doc.resolvedDataDoc.then((resolved: any) => doAddDoc(doc)); } else { doAddDoc(doc); } @@ -714,22 +718,23 @@ export class CollectionTreeView extends CollectionSubView { // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout - if (!e.isPropagationStopped() && this.props.Document === Doc.UserDoc().myWorkspaces) { + if (!e.isPropagationStopped() && this.doc === Doc.UserDoc().myWorkspaces) { ContextMenu.Instance.addItem({ description: "Create Workspace", event: () => MainView.Instance.createNewWorkspace(), icon: "plus" }); - ContextMenu.Instance.addItem({ description: "Delete Workspace", event: () => this.remove(this.props.Document), icon: "minus" }); + ContextMenu.Instance.addItem({ description: "Delete Workspace", event: () => this.remove(this.doc), icon: "minus" }); e.stopPropagation(); e.preventDefault(); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); - } else if (!e.isPropagationStopped() && this.props.Document === Doc.UserDoc().myRecentlyClosed) { + } else if (!e.isPropagationStopped() && this.doc === Doc.UserDoc().myRecentlyClosed) { ContextMenu.Instance.addItem({ description: "Clear All", event: () => Doc.UserDoc().myRecentlyClosed = new List(), icon: "plus" }); e.stopPropagation(); e.preventDefault(); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); } else { const layoutItems: ContextMenuProps[] = []; - layoutItems.push({ description: (this.props.Document.treeViewPreventOpen ? "Persist" : "Abandon") + "Treeview State", event: () => this.props.Document.treeViewPreventOpen = !this.props.Document.treeViewPreventOpen, icon: "paint-brush" }); - layoutItems.push({ description: (this.props.Document.treeViewHideHeaderFields ? "Show" : "Hide") + " Header Fields", event: () => this.props.Document.treeViewHideHeaderFields = !this.props.Document.treeViewHideHeaderFields, icon: "paint-brush" }); - layoutItems.push({ description: (this.props.Document.treeViewHideTitle ? "Show" : "Hide") + " Title", event: () => this.props.Document.treeViewHideTitle = !this.props.Document.treeViewHideTitle, icon: "paint-brush" }); + layoutItems.push({ description: (this.doc.treeViewPreventOpen ? "Persist" : "Abandon") + "Treeview State", event: () => this.doc.treeViewPreventOpen = !this.doc.treeViewPreventOpen, icon: "paint-brush" }); + layoutItems.push({ description: (this.doc.treeViewHideHeaderFields ? "Show" : "Hide") + " Header Fields", event: () => this.doc.treeViewHideHeaderFields = !this.doc.treeViewHideHeaderFields, icon: "paint-brush" }); + layoutItems.push({ description: (this.doc.treeViewHideTitle ? "Show" : "Hide") + " Title", event: () => this.doc.treeViewHideTitle = !this.doc.treeViewHideTitle, icon: "paint-brush" }); + layoutItems.push({ description: (this.doc.treeViewHideLinkLines ? "Show" : "Hide") + " Link Lines", event: () => this.doc.treeViewHideLinkLines = !this.doc.treeViewHideLinkLines, icon: "paint-brush" }); ContextMenu.Instance.addItem({ description: "Options...", subitems: layoutItems, icon: "eye" }); } !Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ @@ -745,7 +750,7 @@ export class CollectionTreeView extends CollectionSubView { + this.childDocs?.map(d => { DocListCast(d.data).map((img, i) => { const caption = (d.captions as any)[i]; if (caption) { @@ -774,7 +779,7 @@ export class CollectionTreeView extends CollectionSubView UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onCheckedClick"), "edit onCheckedClick"), icon: "edit" + description: "Edit onChecked Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.doc, undefined, "onCheckedClick"), "edit onCheckedClick"), icon: "edit" }); !existingOnClick && ContextMenu.Instance.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" }); } @@ -784,7 +789,7 @@ export class CollectionTreeView extends CollectionSubView
    ; @@ -795,51 +800,51 @@ export class CollectionTreeView extends CollectionSubView this.addDoc(doc, relativeTo, before); const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(d, target, addDoc); const childDocs = this.props.overrideDocuments ? this.props.overrideDocuments : this.childDocs; return !childDocs ? (null) : ( -
    this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()} - onDrop={this.onTreeDrop} - ref={this.createTreeDropTarget}> - {(this.props.treeViewHideTitle || this.props.Document.treeViewHideTitle ? (null) : StrCast(this.dataDoc.title)} - SetValue={undoBatch((value: string) => Doc.SetInPlace(this.dataDoc, "title", value, false) || true)} - OnFillDown={undoBatch((value: string) => { - Doc.SetInPlace(this.dataDoc, "title", value, false); - const doc = Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, _width: 100, _height: 25, _LODdisable: true, templates: new List([Templates.Title.Layout]) }); - EditableView.loadId = doc[Id]; - Doc.SetInPlace(doc, "editTitle", true, false); - this.addDoc(doc, childDocs.length ? childDocs[0] : undefined, true); - })} />)} - {this.props.Document.allowClear ? this.renderClearButton : (null)} -
      - { - TreeView.GetChildElements(childDocs, this.props.Document, this.props.Document, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove, - moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, - this.outerXf, this.props.active, this.props.PanelWidth, this.props.ChromeHeight, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.props.Document.treeViewHideHeaderFields), - BoolCast(this.props.Document.treeViewPreventOpen), [], this.props.LibraryPath, this.props.onCheckedClick, - this.props.onChildClick || ScriptCast(this.props.Document.onChildClick), this.props.ignoreFields) - } -
    -
    +
    +
    this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()} + onDrop={this.onTreeDrop} + ref={this.createTreeDropTarget}> + {this.props.treeViewHideTitle || this.doc.treeViewHideTitle ? (null) : StrCast(this.dataDoc.title)} + SetValue={undoBatch((value: string) => Doc.SetInPlace(this.dataDoc, "title", value, false) || true)} + OnFillDown={undoBatch((value: string) => { + Doc.SetInPlace(this.dataDoc, "title", value, false); + const doc = Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, _width: 100, _height: 25, _LODdisable: true, templates: new List([Templates.Title.Layout]) }); + Doc.SetInPlace(doc, "editTitle", "*", false); + this.addDoc(doc, childDocs.length ? childDocs[0] : undefined, true); + })} />} + {this.doc.allowClear ? this.renderClearButton : (null)} +
      + { + TreeView.GetChildElements(childDocs, this.doc, this.doc, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove, + moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, + this.outerXf, this.props.active, this.props.PanelWidth, this.props.ChromeHeight, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields), + BoolCast(this.doc.treeViewPreventOpen), [], this.props.LibraryPath, this.props.onCheckedClick, + this.props.onChildClick || ScriptCast(this.doc.onChildClick), this.props.ignoreFields) + } +
    +
    +
    ); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index ae81b4b36..1a2421bfd 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -10,6 +10,7 @@ import React = require("react"); import { Utils, emptyFunction } from "../../../../Utils"; import { DocumentType } from "../../../documents/DocumentTypes"; import { SnappingManager } from "../../../util/SnappingManager"; +import { Cast } from "../../../../fields/Types"; @observer export class CollectionFreeFormLinksView extends React.Component { @@ -30,8 +31,8 @@ export class CollectionFreeFormLinksView extends React.Component { return drawnPairs; }, [] as { a: DocumentView, b: DocumentView, l: Doc[] }[]); return connections.filter(c => - c.a.props.Document.type === DocumentType.LINK && - c.a.props.pinToPres !== emptyFunction && c.b.props.pinToPres !== emptyFunction // bcz: this prevents links to be drawn to anchors in CollectionTree views -- this is a hack that should be fixed + c.a.props.Document.type === DocumentType.LINK + && !c.a.props.treeViewDoc?.treeViewHideLinkLines && !c.b.props.treeViewDoc?.treeViewHideLinkLines ).map(c => ); } diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index b7726f7ba..b978f6245 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -42,6 +42,17 @@ width:10px !important; } } + .documentView-treeView { + max-height: 1.5em; + text-overflow: ellipsis; + display: inline-block; + white-space: pre; + width: 100%; + overflow: hidden; + > .documentView-node { + position: absolute; + } + } .documentView-lock { width: 20; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index a2bb9700e..22917f18b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -69,7 +69,7 @@ export interface DocumentViewProps { onDoubleClick?: ScriptField; onPointerDown?: ScriptField; onPointerUp?: ScriptField; - treeViewId?: string; + treeViewDoc?: Doc; dropAction?: dropActionType; dragDivName?: string; nudge?: (x: number, y: number) => void; @@ -237,7 +237,7 @@ export class DocumentView extends DocComponent(Docu dragData.removeDocument = this.props.removeDocument; dragData.moveDocument = this.props.moveDocument;// this.layoutDoc.onDragStart ? undefined : this.props.moveDocument; dragData.dragDivName = this.props.dragDivName; - dragData.treeViewId = this.props.treeViewId; + dragData.treeViewDoc = this.props.treeViewDoc; DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: !dropAction && !this.layoutDoc.onDragStart }); } } @@ -1071,30 +1071,34 @@ export class DocumentView extends DocComponent(Docu anchorPanelHeight = () => this.props.PanelHeight() || 1; @computed get anchors() { TraceMobx(); - return this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.layoutDoc.presBox || this.props.dontRegisterView ? (null) : DocListCast(this.Document.links).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) => - ); + return (this.props.treeViewDoc && this.props.LayoutTemplateString) || // render nothing for: tree view anchor dots + this.layoutDoc.presBox || // presentationbox nodes + this.props.dontRegisterView ? (null) : // view that are not registered + DocListCast(this.Document.links).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) => + ); } @computed get innards() { TraceMobx(); - if (!this.props.PanelWidth()) { // this happens when the document is a tree view label - return
    + if (this.props.treeViewDoc && !this.props.LayoutTemplateString) { // this happens when the document is a tree view label (but not an anchor dot) + return
    {StrCast(this.props.Document.title)} {this.anchors}
    ; } + const showTitle = StrCast(this.layoutDoc._showTitle); const showTitleHover = StrCast(this.layoutDoc._showTitleHover); const showCaption = StrCast(this.layoutDoc._showCaption); @@ -1156,7 +1160,7 @@ export class DocumentView extends DocComponent(Docu renderLock() { return (this.Document.isBackground !== undefined || this.isSelected(false)) && ((this.Document.type === DocumentType.COL && this.Document._viewType !== CollectionViewType.Pile) || this.Document.type === DocumentType.IMG) && - this.props.renderDepth > 0 && this.props.PanelWidth() > 0 ? + this.props.renderDepth > 0 && !this.props.treeViewDoc ?
    this.toggleBackground(true)}>
    diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 2bcc6168b..d4ab70200 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -115,8 +115,9 @@ export class LinkAnchorBox extends ViewBoxBaseComponent 1 ? NumCast(this.rootDoc[this.fieldKey + "_x"], 100) : 0; - const y = this.props.PanelWidth() > 1 ? NumCast(this.rootDoc[this.fieldKey + "_y"], 100) : 0; + const small = this.props.PanelWidth() <= 1; // this happens when rendered in a treeView + const x = NumCast(this.rootDoc[this.fieldKey + "_x"], 100); + const y = NumCast(this.rootDoc[this.fieldKey + "_y"], 100); const c = StrCast(this.layoutDoc._backgroundColor, StrCast(this.layoutDoc.backgroundColor, StrCast(this.dataDoc.backgroundColor, "lightBlue"))); // note this is not where the typical lightBlue default color comes from. See Documents.Create.LinkDocument() const anchor = this.fieldKey === "anchor1" ? "anchor2" : "anchor1"; const anchorScale = (x === 0 || x === 100 || y === 0 || y === 100) ? 1 : .25; @@ -131,7 +132,6 @@ export class LinkAnchorBox extends ViewBoxBaseComponent}
    ); - const small = this.props.PanelWidth() <= 1; return
    LinkDocPreview.LinkInfo = undefined)} onPointerEnter={action(e => LinkDocPreview.LinkInfo = { @@ -143,8 +143,8 @@ export class LinkAnchorBox extends ViewBoxBaseComponent {!this._editing && !this._forceOpen ? (null) : diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index 74262d81a..2436bf418 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -85,7 +85,7 @@ export class SelectorContextMenu extends React.Component { const item = React.createRef(); return
    doc.col, undefined, undefined, undefined, undefined, () => SearchBox.Instance.closeSearch())}> + SetupDrag(item, () => doc.col, undefined, undefined, () => SearchBox.Instance.closeSearch())}>
    {doc.col.title} -- cgit v1.2.3-70-g09d2 From 501bf1a166c4adc766c98af712091a19dce97e00 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 27 Jun 2020 19:48:17 -0400 Subject: from last --- src/client/views/collections/CollectionTreeView.tsx | 1 - 1 file changed, 1 deletion(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 7ffecdc26..1088577d2 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -110,7 +110,6 @@ class TreeView extends React.Component { Doc.ComputeContentBounds(DocListCast(this.props.document[this.fieldKey])); } - @undoBatch openRight = () => this.props.addDocTab(this.props.document, "onRight", this.props.libraryPath); @undoBatch openRight = () => this.props.addDocTab(this.doc, "onRight", this.props.libraryPath); @undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { return this.doc !== target && this.props.deleteDoc(doc) && addDoc(doc); -- cgit v1.2.3-70-g09d2 From e8bac5f5e41524e1258d83a98fb440732190fda8 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 27 Jun 2020 20:02:34 -0400 Subject: made safe mode apply to all collections --- src/client/views/collections/CollectionView.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 508b9e5e7..5e3026979 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -105,15 +105,7 @@ export class CollectionView extends Touchable (this.props.isSelected(outsideReaction) || this.props.rootSelected(outsideReaction) || this.props.Document.forceActive || this._isChildActive || this.props.renderDepth === 0) ? true : false; -- cgit v1.2.3-70-g09d2 From b340defb4a4b8c5b7604099e7b0fb5b6846f70aa Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 27 Jun 2020 21:06:44 -0400 Subject: fixed safe mode & reverted to apply ontly to freeform and schema collections. --- src/client/views/Main.tsx | 2 ++ src/client/views/collections/CollectionView.tsx | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 6878658a8..77e37834d 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -6,12 +6,14 @@ import * as React from 'react'; import { DocServer } from "../DocServer"; import { AssignAllExtensions } from "../../extensions/General/Extensions"; import { Networking } from "../Network"; +import { CollectionView } from "./collections/CollectionView"; AssignAllExtensions(); export let resolvedPorts: { server: number, socket: number }; (async () => { + window.location.search.includes("safe") && CollectionView.SetSafeMode(true); const info = await CurrentUserUtils.loadCurrentUser(); resolvedPorts = JSON.parse(await Networking.FetchFromServer("/resolvedPorts")); DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts.socket, info.email); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 5e3026979..5f6e8c4a7 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -105,7 +105,15 @@ export class CollectionView extends Touchable (this.props.isSelected(outsideReaction) || this.props.rootSelected(outsideReaction) || this.props.Document.forceActive || this._isChildActive || this.props.renderDepth === 0) ? true : false; -- cgit v1.2.3-70-g09d2 From 55bdee9e73513118c242f1665150dc7698eac50e Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 28 Jun 2020 00:16:38 -0400 Subject: renamed some fields scale=>_viewScale, transtion=>dataTransition, panTransformType=>_viewTransform. fixed animation frames to not break acls (sort of). --- src/client/documents/Documents.ts | 4 +-- src/client/util/DocumentManager.ts | 2 +- src/client/views/MainView.tsx | 2 +- src/client/views/animationtimeline/Timeline.tsx | 4 +-- .../collectionFreeForm/CollectionFreeFormView.scss | 7 +---- .../collectionFreeForm/CollectionFreeFormView.tsx | 27 ++++++++--------- .../views/nodes/CollectionFreeFormDocumentView.tsx | 34 +++++++++++++--------- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/PresBox.tsx | 4 +-- .../views/nodes/formattedText/FormattedTextBox.tsx | 4 +-- src/client/views/pdf/PDFViewer.tsx | 2 +- src/fields/Doc.ts | 2 +- 12 files changed, 46 insertions(+), 48 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index b175c018e..e8801df90 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -92,7 +92,7 @@ export interface DocumentOptions { label?: string; // short form of title for use as an icon label style?: string; page?: number; - scale?: number; + _viewScale?: number; isDisplayPanel?: boolean; // whether the panel functions as GoldenLayout "stack" used to display documents forceActive?: boolean; layout?: string | Doc; // default layout string for a document @@ -228,7 +228,7 @@ export namespace Docs { }], [DocumentType.COL, { layout: { view: CollectionView, dataField: defaultDataKey }, - options: { _panX: 0, _panY: 0, scale: 1 } // , _width: 500, _height: 500 } + options: { _panX: 0, _panY: 0, _viewScale: 1 } // , _width: 500, _height: 500 } }], [DocumentType.KVP, { layout: { view: KeyValueBox, dataField: defaultDataKey }, diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 40d6b039a..fb5d1717e 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -170,7 +170,7 @@ export class DocumentManager { const targetDocContextView = getFirstDocView(targetDocContext); targetDocContext._scrollY = 0; // this will force PDFs to activate and load their annotations / allow scrolling if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first.. - targetDocContext.panTransformType = "Ease"; + targetDocContext._viewTransition = "transform 500ms"; targetDocContextView.props.focus(targetDocContextView.props.Document, willZoom); // now find the target document within the context diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index d7e7db592..68b81ab4f 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -83,7 +83,7 @@ export class MainView extends React.Component { componentDidMount() { - DocServer.setPlaygroundFields(["panTransformType", "transition", "_panX", "_panY", "scale", "_viewType"]); // can play with these fields on someone else's + DocServer.setPlaygroundFields(["dataTransition", "_viewTransition", "_panX", "_panY", "_viewScale", "_viewType"]); // can play with these fields on someone else's const tag = document.createElement('script'); diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx index ab984f727..f54bd3aff 100644 --- a/src/client/views/animationtimeline/Timeline.tsx +++ b/src/client/views/animationtimeline/Timeline.tsx @@ -288,13 +288,13 @@ export class Timeline extends React.Component { resetView(doc: Doc) { doc._panX = doc._customOriginX ?? 0; doc._panY = doc._customOriginY ?? 0; - doc.scale = doc._customOriginScale ?? 1; + doc._viewScale = doc._customOriginScale ?? 1; } setView(doc: Doc) { doc._customOriginX = doc._panX; doc._customOriginY = doc._panY; - doc._customOriginScale = doc.scale; + doc._customOriginScale = doc._viewScale; } /** * zooming mechanism (increment and spacing changes) diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index d9011c9d3..92aee3776 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -1,7 +1,6 @@ @import "../../globalCssVariables"; -.collectionfreeformview-none, -.collectionfreeformview-ease { +.collectionfreeformview-none { position: inherit; top: 0; left: 0; @@ -22,10 +21,6 @@ } } -.collectionfreeformview-ease { - transition: transform 500ms; -} - .collectionfreeformview-none { touch-action: none; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 2e543f137..5135c4ae4 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -63,7 +63,7 @@ export const panZoomSchema = createSchema({ fitToBox: "boolean", _xPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set _yPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set - panTransformType: "string", + _viewTransition: "string", scrollHeight: "number", fitX: "number", fitY: "number", @@ -110,9 +110,8 @@ export class CollectionFreeFormView extends CollectionSubView this.props.Document.panTransformType === "Ease"; private panX = () => this.fitToContent ? (this.contentBounds.x + this.contentBounds.r) / 2 : this.Document._panX || 0; private panY = () => this.fitToContent ? (this.contentBounds.y + this.contentBounds.b) / 2 : this.Document._panY || 0; private zoomScaling = () => (this.fitToContentScaling / this.parentScaling) * (this.fitToContent ? @@ -832,7 +831,7 @@ export class CollectionFreeFormView extends CollectionSubView { if (this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform) { // bcz: this isn't ideal, but want to try it out... this.setPan(NumCast(this.layoutDoc._panX) + this.props.PanelWidth() / 2 * x / this.zoomScaling(), - NumCast(this.layoutDoc._panY) + this.props.PanelHeight() / 2 * (-y) / this.zoomScaling(), "Ease", true); + NumCast(this.layoutDoc._panY) + this.props.PanelHeight() / 2 * (-y) / this.zoomScaling(), "transform 500ms", true); this._nudgeTime = Date.now(); - setTimeout(() => (Date.now() - this._nudgeTime >= 500) && (this.Document.panTransformType = undefined), 500); + setTimeout(() => (Date.now() - this._nudgeTime >= 500) && (this.Document._viewTransition = undefined), 500); return true; } return false; @@ -1354,8 +1353,7 @@ export class CollectionFreeFormView extends CollectionSubView {this.children} @@ -1434,7 +1432,6 @@ interface CollectionFreeFormViewPannableContentsProps { panX: () => number; panY: () => number; zoomScaling: () => number; - easing: () => boolean; viewDefDivClick?: ScriptField; children: () => JSX.Element[]; transition?: string; @@ -1443,7 +1440,7 @@ interface CollectionFreeFormViewPannableContentsProps { @observer class CollectionFreeFormViewPannableContents extends React.Component{ render() { - const freeformclass = "collectionfreeformview" + (this.props.viewDefDivClick ? "-viewDef" : (this.props.easing() ? "-ease" : "-none")); + const freeformclass = "collectionfreeformview" + (this.props.viewDefDivClick ? "-viewDef" : "-none"); const cenx = this.props.centeringShiftX(); const ceny = this.props.centeringShiftY(); const panx = -this.props.panX(); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 404d69730..090beba0b 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -22,7 +22,7 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { zIndex?: number; highlight?: boolean; jitterRotation: number; - transition?: string; + dataTransition?: string; fitToBox?: boolean; replica: string; } @@ -60,10 +60,10 @@ export class CollectionFreeFormDocumentView extends DocComponent(xindexed); + d["y-indexed"] = new List(yindexed); + d["opacity-indexed"] = new List(oindexed); } public static updateKeyframe(docs: Doc[], time: number) { const timecode = Math.round(time); @@ -94,14 +100,14 @@ export class CollectionFreeFormDocumentView extends DocComponent docs.forEach(doc => doc.transition = "inherit"), 1010); + setTimeout(() => docs.forEach(doc => doc.dataTransition = "inherit"), 1010); } public static gotoKeyframe(docs: Doc[]) { - docs.forEach(doc => doc.transition = "all 1s"); - setTimeout(() => docs.forEach(doc => doc.transition = "inherit"), 1010); + docs.forEach(doc => doc.dataTransition = "all 1s"); + setTimeout(() => docs.forEach(doc => doc.dataTransition = "inherit"), 1010); } public static setupKeyframes(docs: Doc[], timecode: number, progressivize: boolean = false) { @@ -119,7 +125,7 @@ export class CollectionFreeFormDocumentView extends DocComponent(Docu style={{ transformOrigin: this._animateScalingTo ? "center center" : undefined, transform: this._animateScalingTo ? `scale(${this._animateScalingTo})` : undefined, - transition: !this._animateScalingTo ? StrCast(this.Document.transition) : this._animateScalingTo < 1 ? "transform 0.5s ease-in" : "transform 0.5s ease-out", + transition: !this._animateScalingTo ? StrCast(this.Document.dataTransition) : this._animateScalingTo < 1 ? "transform 0.5s ease-in" : "transform 0.5s ease-out", pointerEvents: this.ignorePointerEvents ? "none" : undefined, color: StrCast(this.layoutDoc.color, "inherit"), outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px", diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index dbc879920..8818d375e 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -62,8 +62,8 @@ export class PresBox extends ViewBoxBaseComponent const lastFrame = Cast(presTargetDoc.lastFrame, "number", null); const curFrame = NumCast(presTargetDoc.currentFrame); if (lastFrame !== undefined && curFrame < lastFrame) { - presTargetDoc.transition = "all 1s"; - setTimeout(() => presTargetDoc.transition = undefined, 1010); + presTargetDoc._viewTransition = "all 1s"; + setTimeout(() => presTargetDoc._viewTransition = undefined, 1010); presTargetDoc.currentFrame = curFrame + 1; } else if (this.childDocs[this.itemIndex + 1] !== undefined) { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 135ab8cbc..7bc1078d7 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1221,7 +1221,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp tryUpdateHeight(limitHeight?: number) { let scrollHeight = this._ref.current?.scrollHeight; if (this.props.renderDepth && this.layoutDoc._autoHeight && !this.props.ignoreAutoHeight && scrollHeight) { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation - scrollHeight = scrollHeight * NumCast(this.layoutDoc.scale, 1); + scrollHeight = scrollHeight * NumCast(this.layoutDoc._viewScale, 1); if (limitHeight && scrollHeight > limitHeight) { scrollHeight = limitHeight; this.layoutDoc.limitHeight = undefined; @@ -1250,7 +1250,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp @computed get sidebarColor() { return StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "transparent")); } render() { TraceMobx(); - const scale = this.props.ContentScaling() * NumCast(this.layoutDoc.scale, 1); + const scale = this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1); const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : ""; const interactive = Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc.isBackground; if (this.props.isSelected()) { diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index bd74e0dd0..d8130ce63 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -433,7 +433,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent { if (layoutDoc._nativeWidth || layoutDoc._nativeHeight) { - layoutDoc.scale = NumCast(layoutDoc.scale, 1) * contentScale; + layoutDoc._viewScale = NumCast(layoutDoc._viewScale, 1) * contentScale; layoutDoc._nativeWidth = undefined; layoutDoc._nativeHeight = undefined; } -- cgit v1.2.3-70-g09d2 From 1f41121904a27fbd77b6afa4ad1ffe3552aef24c Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 28 Jun 2020 01:35:42 -0400 Subject: fixed zooming out on a collection when over a pdf. fixed filters on nested collections. --- src/client/views/collections/CollectionSubView.tsx | 3 +-- src/client/views/pdf/PDFViewer.tsx | 12 +++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 570f9375e..3a13ac822 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -104,8 +104,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: } docFilters = () => { return this.props.ignoreFields?.includes("_docFilters") ? [] : - this.props.docFilters !== returnEmptyFilter ? this.props.docFilters() : - Cast(this.props.Document._docFilters, listSpec("string"), []); + [...this.props.docFilters(), ...Cast(this.props.Document._docFilters, listSpec("string"), [])]; } @computed get childDocs() { const docFilters = this.docFilters(); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index d8130ce63..64f150dd5 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -641,11 +641,13 @@ export class PDFViewer extends ViewBoxAnnotatableComponent { - e.stopPropagation(); - if (e.ctrlKey) { - const curScale = Number(this._pdfViewer.currentScaleValue); - this._pdfViewer.currentScaleValue = Math.max(1, Math.min(10, curScale - curScale * e.deltaY / 1000)); - this._zoomed = Number(this._pdfViewer.currentScaleValue); + if (this.active()) { + e.stopPropagation(); + if (e.ctrlKey) { + const curScale = Number(this._pdfViewer.currentScaleValue); + this._pdfViewer.currentScaleValue = Math.max(1, Math.min(10, curScale - curScale * e.deltaY / 1000)); + this._zoomed = Number(this._pdfViewer.currentScaleValue); + } } } -- cgit v1.2.3-70-g09d2 From 790cc785a5cad47f0dd274c7f4773eff7d7d9c2e Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 28 Jun 2020 02:09:55 -0400 Subject: fixed selection of documents in nested collections with filter panel open --- src/client/views/collections/CollectionView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 5f6e8c4a7..469ae9f0e 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -191,7 +191,7 @@ export class CollectionView extends Touchable; } - screenToLocalTransform = () => this.props.ScreenToLocalTransform().scale(this.props.PanelWidth() / this.bodyPanelWidth()); + screenToLocalTransform = () => this.props.renderDepth ? this.props.ScreenToLocalTransform() : this.props.ScreenToLocalTransform().scale(this.props.PanelWidth() / this.bodyPanelWidth()); private SubViewHelper = (type: CollectionViewType, renderProps: CollectionRenderProps) => { const props: SubCollectionViewProps = { ...this.props, ...renderProps, ScreenToLocalTransform: this.screenToLocalTransform, CollectionView: this, annotationsKey: "" }; switch (type) { @@ -521,7 +521,7 @@ export class CollectionView extends Touchable {this.showIsTagged()} -
    +
    {this.collectionViewType !== undefined ? this.SubView(this.collectionViewType, props) : (null)}
    {this.lightbox(DocListCast(this.props.Document[this.props.fieldKey]).filter(d => d.type === DocumentType.IMG).map(d => -- cgit v1.2.3-70-g09d2 From 83ce7f1ad7c2e1b691dbdc67408cee7c65d669b8 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 28 Jun 2020 10:25:27 -0400 Subject: from last --- src/client/views/collections/CollectionView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 469ae9f0e..e61ccf015 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -521,7 +521,7 @@ export class CollectionView extends Touchable {this.showIsTagged()} -
    +
    {this.collectionViewType !== undefined ? this.SubView(this.collectionViewType, props) : (null)}
    {this.lightbox(DocListCast(this.props.Document[this.props.fieldKey]).filter(d => d.type === DocumentType.IMG).map(d => -- cgit v1.2.3-70-g09d2 From 2b9e542ea0e62b13e1f9e0b51f3cfb8e2ce8f78d Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 28 Jun 2020 11:55:49 -0400 Subject: slightly improved layout of workspace facet filter box --- src/client/util/SelectionManager.ts | 8 ++++++++ src/client/views/collections/CollectionTreeView.tsx | 2 +- src/client/views/collections/CollectionView.scss | 14 +++++++++----- src/client/views/collections/CollectionView.tsx | 5 +++-- src/fields/Doc.ts | 1 - 5 files changed, 21 insertions(+), 9 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index eb905d237..0f204bba4 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -3,6 +3,8 @@ import { Doc } from "../../fields/Doc"; import { DocumentView } from "../views/nodes/DocumentView"; import { computedFn } from "mobx-utils"; import { List } from "../../fields/List"; +import { Scripting } from "./Scripting"; +import { DocumentManager } from "./DocumentManager"; export namespace SelectionManager { @@ -86,3 +88,9 @@ export namespace SelectionManager { } } + +Scripting.addGlobal(function selectDoc(doc: any) { + const view = DocumentManager.Instance.getDocumentView(doc); + view && SelectionManager.SelectDoc(view, false); + //Doc.UserDoc().activeSelection = new List([doc]); +}); \ No newline at end of file diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 1088577d2..33e4acee5 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -124,7 +124,7 @@ class TreeView extends React.Component { constructor(props: any) { super(props); - this._editTitleScript = ScriptField.MakeFunction(`setInPlace(self, 'editTitle', '${this._uniqueId}')`); + this._editTitleScript = ScriptField.MakeScript(`{setInPlace(self, 'editTitle', '${this._uniqueId}'); selectDoc(self);} `); if (Doc.GetT(this.doc, "editTitle", "string", true) === "*") Doc.SetInPlace(this.doc, "editTitle", this._uniqueId, false); } diff --git a/src/client/views/collections/CollectionView.scss b/src/client/views/collections/CollectionView.scss index 7877fe155..b630f9cf8 100644 --- a/src/client/views/collections/CollectionView.scss +++ b/src/client/views/collections/CollectionView.scss @@ -11,16 +11,18 @@ height: 100%; overflow: hidden; // bcz: used to be 'auto' which would create scrollbars when there's a floating doc that's not visible. not sure if that's better, but the scrollbars are annoying... - .collectionTimeView-dragger { - background-color: lightgray; + .collectionView-filterDragger { + background-color: rgb(140, 139, 139); height: 40px; - width: 20px; + width: 10px; position: absolute; - border-radius: 10px; top: 55%; border: 1px black solid; + border-radius: 0; + border-top-left-radius: 20px; + border-bottom-left-radius: 20px; + border-right: unset; z-index: 2; - right: -10px; } .collectionTimeView-treeView { display: flex; @@ -30,6 +32,8 @@ position: absolute; right: 0; top: 0; + border-left: solid 1px; + z-index: 1; .collectionTimeView-addfacet { display: inline-block; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index e61ccf015..2aefb99f5 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -432,7 +432,7 @@ export class CollectionView extends Touchable { this._facetWidth = this.props.PanelWidth() - Math.max(this.props.ScreenToLocalTransform().transformPoint(e.clientX, 0)[0], 0); return false; - }), returnFalse, action(() => this._facetWidth = this.facetWidth() < 15 ? Math.min(this.props.PanelWidth() - 25, 200) : 0)); + }), returnFalse, action(() => this._facetWidth = this.facetWidth() < 15 ? Math.min(this.props.PanelWidth() - 25, 200) : 0), false); } filterBackground = () => "rgba(105, 105, 105, 0.432)"; get ignoreFields() { return ["_docFilters", "_docRangeFilters"]; } // this makes the tree view collection ignore these filters (otherwise, the filters would filter themselves) @@ -531,7 +531,8 @@ export class CollectionView extends Touchable +
    } {this.facetWidth() < 10 ? (null) : this.filterView}
    ); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 231ee88e3..dd7117594 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1159,7 +1159,6 @@ Scripting.addGlobal(function activePresentationItem() { const curPres = Doc.UserDoc().activePresentation as Doc; return curPres && DocListCast(curPres[Doc.LayoutFieldKey(curPres)])[NumCast(curPres._itemIndex)]; }); -Scripting.addGlobal(function selectDoc(doc: any) { Doc.UserDoc().activeSelection = new List([doc]); }); Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) { const docs = DocListCast(Doc.UserDoc().activeSelection). filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.DOCHOLDER && d.type !== DocumentType.KVP && -- cgit v1.2.3-70-g09d2 From 6490c93133151a08f65cce16fd2b56152539d636 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 28 Jun 2020 14:13:39 -0400 Subject: re-fixed copy/paste from one text box to a new text box by moving clearSelection() from SelectDoc to setPreviewCursor. Otherwise, clicking on an unselected text box wouldn't set the insertion point. --- src/client/util/SelectionManager.ts | 5 ----- src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 7 +++++-- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 0f204bba4..024532f90 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -12,17 +12,12 @@ export namespace SelectionManager { @observable IsDragging: boolean = false; SelectedDocuments: ObservableMap = new ObservableMap(); - clearSelection() { - if (window.getSelection) { window.getSelection()?.removeAllRanges(); } - else if (document.getSelection()) { document.getSelection()?.empty(); } - } @action SelectDoc(docView: DocumentView, ctrlPressed: boolean): void { // if doc is not in SelectedDocuments, add it if (!manager.SelectedDocuments.get(docView)) { if (!ctrlPressed) { this.DeselectAll(); - this.clearSelection(); } manager.SelectedDocuments.set(docView, true); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 1bc7c6fb5..099859109 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -20,8 +20,6 @@ import { CollectionView } from "../CollectionView"; import MarqueeOptionsMenu from "./MarqueeOptionsMenu"; import "./MarqueeView.scss"; import React = require("react"); -import { DateField } from "../../../../fields/DateField"; -import { DocServer } from "../../../DocServer"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -260,6 +258,10 @@ export class MarqueeView extends React.Component { if (drag) { @@ -275,6 +277,7 @@ export class MarqueeView extends React.Component Date: Sun, 28 Jun 2020 14:58:29 -0400 Subject: fixed errors. fixed selecting in an unselected text note to not create a phantom selection from the last selected point to the current point. --- src/client/views/collections/CollectionTreeView.tsx | 6 +++--- src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 12 +++++------- 3 files changed, 9 insertions(+), 11 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 33e4acee5..d54f4d6e6 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -232,7 +232,7 @@ class TreeView extends React.Component { const offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); return this.props.ScreenToLocalTransform().translate(offset[0], offset[1]); } - docTransform = () => this.refTransform(this._dref.current!) + docTransform = () => this.refTransform(this._dref.current!); getTransform = () => this.refTransform(this._tref.current!); docWidth = () => { const layoutDoc = this.layoutDoc; @@ -401,9 +401,9 @@ class TreeView extends React.Component { this._docRef.current?.ContentDiv && simulateMouseClick(this._docRef.current.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); } focusOnDoc = (doc: Doc) => DocumentManager.Instance.getFirstDocumentView(doc)?.props.focus(doc, true); - contextMenuItems = () => [{ script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }] + contextMenuItems = () => [{ script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }]; truncateTitleWidth = () => NumCast(this.props.treeViewDoc.treeViewTruncateTitleWidth, 0); - showTitleEdit = () => ["*", this._uniqueId].includes(Doc.GetT(this.doc, "editTitle", "string", true) || "") + showTitleEdit = () => ["*", this._uniqueId].includes(Doc.GetT(this.doc, "editTitle", "string", true) || ""); /** * Renders the EditableView title element for placement into the tree. */ diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 090beba0b..a3020f912 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -156,7 +156,7 @@ export class CollectionFreeFormDocumentView extends DocComponent { this.rootDoc._height = newHeight; - this.dataDoc._nativeHeight = nh ? scrollHeight : undefined; + this.layoutDoc._nativeHeight = nh ? scrollHeight : undefined; }, 10); } else { - this.rootDoc._height = newHeight; - this.dataDoc._nativeHeight = nh ? scrollHeight : undefined; + this.layoutDoc._height = newHeight; + this.layoutDoc._nativeHeight = nh ? scrollHeight : undefined; } } } -- cgit v1.2.3-70-g09d2 From 29f9cedd937697c56ce3b400931b26c82a23721d Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 29 Jun 2020 00:21:07 -0400 Subject: changed a lot of collection keys to start with "_" -- particularly for Stacking and Schema views. Also added filtering to facet filters. enabled facet filter for sidebar library. --- .../apis/google_docs/GooglePhotosClientUtils.ts | 1 - src/client/documents/Documents.ts | 40 +++++------ src/client/util/CurrentUserUtils.ts | 24 +++---- .../util/Import & Export/DirectoryImportBox.tsx | 2 +- src/client/views/MainView.tsx | 18 ++--- .../collections/CollectionMasonryViewFieldRow.tsx | 10 +-- .../views/collections/CollectionSchemaView.tsx | 16 +++-- .../views/collections/CollectionStackingView.tsx | 77 +++++++++++----------- .../CollectionStackingViewFieldColumn.tsx | 18 ++--- src/client/views/collections/CollectionSubView.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 4 +- src/client/views/collections/CollectionView.tsx | 8 +-- .../views/collections/CollectionViewChromes.tsx | 8 ++- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- .../collections/collectionFreeForm/MarqueeView.tsx | 1 - src/client/views/nodes/KeyValueBox.tsx | 4 +- .../views/nodes/formattedText/DashFieldView.tsx | 4 +- .../views/nodes/formattedText/RichTextRules.ts | 4 +- src/client/views/pdf/PDFViewer.tsx | 2 +- src/fields/documentSchemas.ts | 10 ++- src/fields/util.ts | 2 +- src/scraping/buxton/scraper.py | 3 +- 22 files changed, 131 insertions(+), 131 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts index a604c7de1..13bfb3a91 100644 --- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts +++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts @@ -130,7 +130,6 @@ export namespace GooglePhotos { const uploads = await Transactions.WriteMediaItemsToServer(response); const children = uploads.map((upload: Transactions.UploadInformation) => { const document = Docs.Create.ImageDocument(Utils.fileUrl(upload.fileNames.clean)); - document.fillColumn = true; document.contentSize = upload.contentSize; return document; }); diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f71984ca6..b70971c2d 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -62,7 +62,7 @@ export interface DocumentOptions { _dimUnit?: string; // "px" or "*" (default = "*") _fitWidth?: boolean; _fitToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents - _LODdisable?: boolean; + _freeformLOD?: boolean; // whether to use LOD to render a freeform document _showTitleHover?: string; // _showTitle?: string; // which field to display in the title area. leave empty to have no title _showCaption?: string; // which field to display in the caption area. leave empty to have no caption @@ -99,7 +99,7 @@ export interface DocumentOptions { childLayoutTemplate?: Doc; // template for collection to use to render its children (see PresBox or Buxton layout in tree view) childLayoutString?: string; // template string for collection to use to render its children hideFilterView?: boolean; // whether to hide the filter popout on collections - hideHeadings?: boolean; // whether stacking view column headings should be hidden + _columnsHideIfEmpty?: boolean; // whether stacking view column headings should be hidden isTemplateForField?: string; // the field key for which the containing document is a rendering template isTemplateDoc?: boolean; targetScriptKey?: string; // where to write a template script (used by collections with click templates which need to target onClick, onDoubleClick, etc) @@ -119,7 +119,7 @@ export interface DocumentOptions { defaultBackgroundColor?: string; isBackground?: boolean; isLinkButton?: boolean; - columnWidth?: number; + _columnWidth?: number; _fontSize?: number; _fontFamily?: string; curPage?: number; @@ -137,7 +137,8 @@ export interface DocumentOptions { "onCheckedClick-rawScript"?: string; // onChecked script in raw text form "onCheckedClick-params"?: List; // parameter list for onChecked treeview functions _pivotField?: string; // field key used to determine headings for sections in stacking, masonry, pivot views - schemaColumns?: List; + _columnHeaders?: List; // headers for stacking views + _schemaHeaders?: List; // headers for schema view dockingConfig?: string; annotationOn?: Doc; removeDropProperties?: List; // list of properties that should be removed from a document when it is dropped. e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document @@ -428,8 +429,7 @@ export namespace Docs { const parent = TreeDocument([loading], { title: "The Buxton Collection", _width: 400, - _height: 400, - _LODdisable: true + _height: 400 }); const parentProto = Doc.GetProto(parent); const { _socket } = DocServer; @@ -465,7 +465,7 @@ export namespace Docs { return imageDoc; }); // the main document we create - const doc = StackingDocument(deviceImages, { title, _LODdisable: true, hero: new ImageField(constructed[0].url) }); + const doc = StackingDocument(deviceImages, { title, hero: new ImageField(constructed[0].url) }); doc.nameAliases = new List([title.toLowerCase()]); // add the parsed attributes to this main document Doc.Get.FromJson({ data: device, appendToExisting: { targetDoc: Doc.GetProto(doc) } }); @@ -698,15 +698,15 @@ export namespace Docs { } export function FreeformDocument(documents: Array, options: DocumentOptions, id?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Freeform }, id); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Freeform }, id); } export function PileDocument(documents: Array, options: DocumentOptions, id?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", backgroundColor: "black", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Pile }, id); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", backgroundColor: "black", ...options, _viewType: CollectionViewType.Pile }, id); } export function LinearDocument(documents: Array, options: DocumentOptions, id?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", backgroundColor: "black", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Linear }, id); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", backgroundColor: "black", ...options, _viewType: CollectionViewType.Linear }, id); } export function MapDocument(documents: Array, options: DocumentOptions = {}) { @@ -714,35 +714,35 @@ export namespace Docs { } export function CarouselDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Carousel }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Carousel }); } export function Carousel3DDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Carousel3D }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Carousel3D }); } - export function SchemaDocument(schemaColumns: SchemaHeaderField[], documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List(schemaColumns.length ? schemaColumns : [new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Schema }); + export function SchemaDocument(schemaHeaders: SchemaHeaderField[], documents: Array, options: DocumentOptions) { + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _schemaHeaders: schemaHeaders.length ? new List(schemaHeaders) : undefined, ...options, _viewType: CollectionViewType.Schema }); } export function TreeDocument(documents: Array, options: DocumentOptions, id?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Tree }, id); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Tree }, id); } export function StackingDocument(documents: Array, options: DocumentOptions, id?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Stacking }, id); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Stacking }, id); } export function MulticolumnDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Multicolumn }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Multicolumn }); } export function MultirowDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Multirow }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Multirow }); } export function MasonryDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Masonry }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Masonry }); } export function LabelDocument(options?: DocumentOptions) { @@ -1054,7 +1054,7 @@ export namespace DocUtils { }); }); if (x !== undefined && y !== undefined) { - const newCollection = Docs.Create.PileDocument(docList, { title: "pileup", x: x - 55, y: y - 55, _width: 110, _height: 100, _LODdisable: true }); + const newCollection = Docs.Create.PileDocument(docList, { title: "pileup", x: x - 55, y: y - 55, _width: 110, _height: 100 }); newCollection.x = NumCast(newCollection.x) + NumCast(newCollection._width) / 2 - 55; newCollection.y = NumCast(newCollection.y) + NumCast(newCollection._height) / 2 - 55; newCollection._width = newCollection._height = 110; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 2b0b2c738..d0ca0e57e 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -43,7 +43,7 @@ export class CurrentUserUtils { const queryTemplate = Docs.Create.MulticolumnDocument( [ Docs.Create.QueryDocument({ title: "query", _height: 200 }), - Docs.Create.FreeformDocument([], { title: "data", _height: 100, _LODdisable: true }) + Docs.Create.FreeformDocument([], { title: "data", _height: 100 }) ], { _width: 400, _height: 300, title: "queryView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, hideFilterView: true } ); @@ -136,9 +136,9 @@ export class CurrentUserUtils { if (doc["template-button-switch"] === undefined) { const { FreeformDocument, MulticolumnDocument, TextDocument } = Docs.Create; - const yes = FreeformDocument([], { title: "yes", _height: 35, _width: 50, _LODdisable: true, _dimUnit: DimUnit.Pixel, _dimMagnitude: 40 }); + const yes = FreeformDocument([], { title: "yes", _height: 35, _width: 50, _dimUnit: DimUnit.Pixel, _dimMagnitude: 40 }); const name = TextDocument("name", { title: "name", _height: 35, _width: 70, _dimMagnitude: 1 }); - const no = FreeformDocument([], { title: "no", _height: 100, _width: 100, _LODdisable: true }); + const no = FreeformDocument([], { title: "no", _height: 100, _width: 100 }); const labelTemplate = { doc: { type: "doc", content: [{ @@ -193,10 +193,10 @@ export class CurrentUserUtils { const shared = { _chromeStatus: "disabled", _autoHeight: true, _xMargin: 0 }; const detailViewOpts = { title: "detailView", _width: 300, _fontFamily: "Arial", _fontSize: 12 }; - const descriptionWrapperOpts = { title: "descriptions", _height: 300, columnWidth: -1, treeViewHideTitle: true, _pivotField: "title" }; + const descriptionWrapperOpts = { title: "descriptions", _height: 300, _columnWidth: -1, treeViewHideTitle: true, _pivotField: "title" }; const descriptionWrapper = MasonryDocument([details, short, long], { ...shared, ...descriptionWrapperOpts }); - descriptionWrapper.sectionHeaders = new List([ + descriptionWrapper._columnHeaders = new List([ new SchemaHeaderField("[A Short Description]", "dimGray", undefined, undefined, undefined, false), new SchemaHeaderField("[Long Description]", "dimGray", undefined, undefined, undefined, true), new SchemaHeaderField("[Details]", "dimGray", undefined, undefined, undefined, true), @@ -225,7 +225,7 @@ export class CurrentUserUtils { if (doc["template-buttons"] === undefined) { doc["template-buttons"] = new PrefetchProxy(Docs.Create.MasonryDocument(requiredTypes, { title: "Advanced Item Prototypes", _xMargin: 0, _showTitle: "title", - _autoHeight: true, _width: 500, columnWidth: 35, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", + _autoHeight: true, _width: 500, _columnWidth: 35, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), })); } else { @@ -358,11 +358,11 @@ export class CurrentUserUtils { }[] { if (doc.emptyPresentation === undefined) { doc.emptyPresentation = Docs.Create.PresDocument(new List(), - { title: "Presentation", _viewType: CollectionViewType.Stacking, targetDropAction: "alias", _LODdisable: true, _chromeStatus: "replaced", _showTitle: "title", boxShadow: "0 0" }); + { title: "Presentation", _viewType: CollectionViewType.Stacking, targetDropAction: "alias", _chromeStatus: "replaced", _showTitle: "title", boxShadow: "0 0" }); } if (doc.emptyCollection === undefined) { doc.emptyCollection = Docs.Create.FreeformDocument([], - { _nativeWidth: undefined, _nativeHeight: undefined, _LODdisable: true, _width: 150, _height: 100, title: "freeform" }); + { _nativeWidth: undefined, _nativeHeight: undefined, _width: 150, _height: 100, title: "freeform" }); } if (doc.emptyDocHolder === undefined) { doc.emptyDocHolder = Docs.Create.DocumentDocument( @@ -430,7 +430,7 @@ export class CurrentUserUtils { if (dragCreatorSet === undefined) { doc.myItemCreators = new PrefetchProxy(Docs.Create.MasonryDocument(creatorBtns, { title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, - _autoHeight: true, _width: 500, columnWidth: 35, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", + _autoHeight: true, _width: 500, _columnWidth: 35, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), })); } else { @@ -493,7 +493,7 @@ export class CurrentUserUtils { static setupMobileDoc(userDoc: Doc) { return userDoc.activeMoble ?? Docs.Create.MasonryDocument(CurrentUserUtils.setupMobileButtons(userDoc), { - columnWidth: 100, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", title: "buttons", _autoHeight: true, _yMargin: 5 + _columnWidth: 100, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", title: "buttons", _autoHeight: true, _yMargin: 5 }); } @@ -655,7 +655,7 @@ export class CurrentUserUtils { // Finally, setup the list of buttons to display in the sidebar if (doc["tabs-buttons"] === undefined) { doc["tabs-buttons"] = new PrefetchProxy(Docs.Create.StackingDocument([searchBtn, libraryBtn, toolsBtn], { - _width: 500, _height: 80, boxShadow: "0 0", _pivotField: "title", hideHeadings: true, ignoreClick: true, _chromeStatus: "view-mode", + _width: 500, _height: 80, boxShadow: "0 0", _pivotField: "title", _columnsHideIfEmpty: true, ignoreClick: true, _chromeStatus: "view-mode", title: "sidebar btn row stack", backgroundColor: "dimGray", })); (toolsBtn.onClick as ScriptField).script.run({ this: toolsBtn }); @@ -704,7 +704,7 @@ export class CurrentUserUtils { if (doc.activePresentation === undefined) { doc.activePresentation = Docs.Create.PresDocument(new List(), { title: "Presentation", _viewType: CollectionViewType.Stacking, targetDropAction: "alias", - _LODdisable: true, _chromeStatus: "replaced", _showTitle: "title", boxShadow: "0 0" + _chromeStatus: "replaced", _showTitle: "title", boxShadow: "0 0" }); } } diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index af6c57e68..77f13e9f4 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -161,7 +161,7 @@ export class DirectoryImportBox extends React.Component { importContainer = Docs.Create.SchemaDocument(headers, docs, options); } runInAction(() => this.phase = 'External: uploading files to Google Photos...'); - importContainer.singleColumn = false; + importContainer._columnsStack = false; await GooglePhotos.Export.CollectionToAlbum({ collection: importContainer }); Doc.AddDocToList(Doc.GetProto(parent.props.Document), "data", importContainer); !this.persistent && this.props.removeDocument && this.props.removeDocument(doc); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 68b81ab4f..8f5a31b6c 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -206,7 +206,6 @@ export class MainView extends React.Component { _width: this._panelWidth * .7, _height: this._panelHeight, title: "Collection " + workspaceCount, - _LODdisable: true }; const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); const workspaceDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myCatalog as Doc] }], { title: `Workspace ${workspaceCount}` }, id, "row"); @@ -354,15 +353,6 @@ export class MainView extends React.Component { } } - @action - pointerOverDragger = () => { - // if (this.flyoutWidth === 0) { - // this.flyoutWidth = 250; - // this.sidebarButtonsDoc.columnWidth = this.flyoutWidth / 3 - 30; - // this._flyoutTranslate = false; - // } - } - @action pointerLeaveDragger = () => { if (!this._flyoutTranslate) { @@ -375,13 +365,13 @@ export class MainView extends React.Component { onPointerMove = (e: PointerEvent) => { this.flyoutWidth = Math.max(e.clientX, 0); Math.abs(this.flyoutWidth - this._flyoutSizeOnDown) > 6 && (this._canClick = false); - this.sidebarButtonsDoc.columnWidth = this.flyoutWidth / 3 - 30; + this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30; } @action onPointerUp = (e: PointerEvent) => { if (Math.abs(e.clientX - this._flyoutSizeOnDown) < 4 && this._canClick) { this.flyoutWidth = this.flyoutWidth < 15 ? 250 : 0; - this.flyoutWidth && (this.sidebarButtonsDoc.columnWidth = this.flyoutWidth / 3 - 30); + this.flyoutWidth && (this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30); } document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); @@ -470,7 +460,7 @@ export class MainView extends React.Component { }} >
    -
    { MainView.Instance._flyoutTranslate = true; MainView.Instance.flyoutWidth = (MainView.Instance.flyoutWidth || 250); - MainView.Instance.sidebarButtonsDoc.columnWidth = MainView.Instance.flyoutWidth / 3 - 30; + MainView.Instance.sidebarButtonsDoc._columnWidth = MainView.Instance.flyoutWidth / 3 - 30; }); @computed get expandButton() { diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index e0b53e762..627b22417 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -111,8 +111,8 @@ export class CollectionMasonryViewFieldRow extends React.Component i.heading).indexOf(castedValue.toString()) > -1) { + if (this.props.parent.columnHeaders) { + if (this.props.parent.columnHeaders.map(i => i.heading).indexOf(castedValue.toString()) > -1) { return false; } } @@ -151,9 +151,9 @@ export class CollectionMasonryViewFieldRow extends React.Component d[key] = undefined); - if (this.props.parent.sectionHeaders && this.props.headingObject) { - const index = this.props.parent.sectionHeaders.indexOf(this.props.headingObject); - this.props.parent.sectionHeaders.splice(index, 1); + if (this.props.parent.columnHeaders && this.props.headingObject) { + const index = this.props.parent.columnHeaders.indexOf(this.props.headingObject); + this.props.parent.columnHeaders.splice(index, 1); } })); diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 56a2a517c..b780da97e 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -240,10 +240,10 @@ export class SchemaTable extends React.Component { @computed get tableWidth() { return this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH - this.previewWidth(); } @computed get columns() { - return Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField), []); + return Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []); } set columns(columns: SchemaHeaderField[]) { - this.props.Document.schemaColumns = new List(columns); + this.props.Document._schemaHeaders = new List(columns); } @computed get childDocs() { @@ -375,10 +375,12 @@ export class SchemaTable extends React.Component { constructor(props: SchemaTableProps) { super(props); // convert old schema columns (list of strings) into new schema columns (list of schema header fields) - const oldSchemaColumns = Cast(this.props.Document.schemaColumns, listSpec("string"), []); - if (oldSchemaColumns && oldSchemaColumns.length && typeof oldSchemaColumns[0] !== "object") { - const newSchemaColumns = oldSchemaColumns.map(i => typeof i === "string" ? new SchemaHeaderField(i, "#f1efeb") : i); - this.props.Document.schemaColumns = new List(newSchemaColumns); + const oldSchemaHeaders = Cast(this.props.Document._schemaHeaders, listSpec("string"), []); + if (oldSchemaHeaders?.length && typeof oldSchemaHeaders[0] !== "object") { + const newSchemaHeaders = oldSchemaHeaders.map(i => typeof i === "string" ? new SchemaHeaderField(i, "#f1efeb") : i); + this.props.Document._schemaHeaders = new List(newSchemaHeaders); + } else if (this.props.Document._schemaHeaders === undefined) { + this.props.Document._schemaHeaders = new List([new SchemaHeaderField("title", "#f1efeb")]); } } @@ -740,7 +742,7 @@ export class SchemaTable extends React.Component { if(col === undefined) { return (doc as any)[key][row + ${row}]; } - return (doc as any)[key][row + ${row}][(doc as any).schemaColumns[col + ${col}].heading]; + return (doc as any)[key][row + ${row}][(doc as any)._schemaHeaders[col + ${col}].heading]; } return ${script}`; const compiled = CompileScript(script, { params: { this: Doc.name }, capturedVariables: { doc: this.props.Document, key: this.props.fieldKey }, typecheck: false, transformer: this.createTransformer(row, col) }); diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 4aab43b08..7bdf5e7df 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -43,27 +43,26 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) @observable _heightMap = new Map(); @observable _cursor: CursorProperty = "grab"; @observable _scroll = 0; // used to force the document decoration to update when scrolling - @computed get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); } - @computed get pivotField() { return StrCast(this.props.Document._pivotField); } + @computed get columnHeaders() { return Cast(this.layoutDoc._columnHeaders, listSpec(SchemaHeaderField)); } + @computed get pivotField() { return StrCast(this.layoutDoc._pivotField); } @computed get filteredChildren() { return this.childLayoutPairs.filter(pair => pair.layout instanceof Doc).map(pair => pair.layout); } - @computed get xMargin() { return NumCast(this.props.Document._xMargin, 2 * Math.min(this.gridGap, .05 * this.props.PanelWidth())); } - @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); } + @computed get xMargin() { return NumCast(this.layoutDoc._xMargin, 2 * Math.min(this.gridGap, .05 * this.props.PanelWidth())); } + @computed get yMargin() { return Math.max(this.layoutDoc._showTitle && !this.layoutDoc._showTitleHover ? 30 : 0, NumCast(this.layoutDoc._yMargin, 0)); } // 2 * this.gridGap)); } + @computed get gridGap() { return NumCast(this.layoutDoc._gridGap, 10); } + @computed get isStackingView() { return BoolCast(this.layoutDoc._columnsStack, true); } @computed get numGroupColumns() { return this.isStackingView ? Math.max(1, this.Sections.size + (this.showAddAGroup ? 1 : 0)) : 1; } - @computed get showAddAGroup() { return (this.pivotField && (this.props.Document._chromeStatus !== 'view-mode' && this.props.Document._chromeStatus !== 'disabled')); } + @computed get showAddAGroup() { return (this.pivotField && (this.layoutDoc._chromeStatus !== 'view-mode' && this.layoutDoc._chromeStatus !== 'disabled')); } @computed get columnWidth() { - TraceMobx(); - return Math.min(this.props.PanelWidth() / (this.props as any).ContentScaling() - 2 * this.xMargin, - this.isStackingView ? Number.MAX_VALUE : this.props.Document.columnWidth === -1 ? this.props.PanelWidth() - 2 * this.xMargin : NumCast(this.props.Document.columnWidth, 250)); + return Math.min(this.props.PanelWidth() / this.props.ContentScaling() - 2 * this.xMargin, + this.isStackingView ? Number.MAX_VALUE : this.layoutDoc._columnWidth === -1 ? this.props.PanelWidth() - 2 * this.xMargin : NumCast(this.layoutDoc._columnWidth, 250)); } @computed get NodeWidth() { return this.props.PanelWidth() - this.gridGap; } constructor(props: any) { super(props); - if (this.sectionHeaders === undefined) { - this.props.Document.sectionHeaders = new List(); + if (this.columnHeaders === undefined) { + this.layoutDoc._columnHeaders = new List(); } } @@ -89,14 +88,14 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) } get Sections() { - if (!this.pivotField || this.sectionHeaders instanceof Promise) return new Map(); + if (!this.pivotField || this.columnHeaders instanceof Promise) return new Map(); - if (this.sectionHeaders === undefined) { - setTimeout(() => this.props.Document.sectionHeaders = new List(), 0); + if (this.columnHeaders === undefined) { + setTimeout(() => this.layoutDoc._columnHeaders = new List(), 0); return new Map(); } - const sectionHeaders = Array.from(this.sectionHeaders); - const fields = new Map(sectionHeaders.map(sh => [sh, []] as [SchemaHeaderField, []])); + const columnHeaders = Array.from(this.columnHeaders); + const fields = new Map(columnHeaders.map(sh => [sh, []] as [SchemaHeaderField, []])); let changed = false; this.filteredChildren.map(d => { const sectionValue = (d[this.pivotField] ? d[this.pivotField] : `NO ${this.pivotField.toUpperCase()} VALUE`) as object; @@ -105,26 +104,26 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) const castedSectionValue = !isNaN(parsed) ? parsed : sectionValue; // look for if header exists already - const existingHeader = sectionHeaders.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`)); + const existingHeader = columnHeaders.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`)); if (existingHeader) { fields.get(existingHeader)!.push(d); } else { const newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`); fields.set(newSchemaHeader, [d]); - sectionHeaders.push(newSchemaHeader); + columnHeaders.push(newSchemaHeader); changed = true; } }); // remove all empty columns if hideHeadings is set - if (this.props.Document.hideHeadings) { + if (this.layoutDoc._columnsHideIfEmpty) { Array.from(fields.keys()).filter(key => !fields.get(key)!.length).map(header => { fields.delete(header); - sectionHeaders.splice(sectionHeaders.indexOf(header), 1); + columnHeaders.splice(columnHeaders.indexOf(header), 1); changed = true; }); } - changed && setTimeout(action(() => { if (this.sectionHeaders) { this.sectionHeaders.length = 0; this.sectionHeaders.push(...sectionHeaders); } }), 0); + changed && setTimeout(action(() => { if (this.columnHeaders) { this.columnHeaders.length = 0; this.columnHeaders.push(...columnHeaders); } }), 0); return fields; } @@ -136,7 +135,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) let wid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1); if (!layoutDoc._fitWidth && nw && nh) { const aspect = nw && nh ? nh / nw : 1; - if (!(this.props.Document.fillColumn)) wid = Math.min(layoutDoc[WidthSym](), wid); + if (!(this.layoutDoc._columnsFill)) wid = Math.min(layoutDoc[WidthSym](), wid); return wid * aspect; } return layoutDoc._fitWidth ? wid * NumCast(layoutDoc.scrollHeight, nh) / (nw || 1) : layoutDoc[HeightSym](); @@ -147,7 +146,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) // reset section headers when a new filter is inputted this._pivotFieldDisposer = reaction( () => this.pivotField, - () => this.props.Document.sectionHeaders = new List() + () => this.layoutDoc._columnHeaders = new List() ); } componentWillUnmount() { @@ -211,7 +210,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) fitToBox={false} dontRegisterView={this.props.dontRegisterView} rootSelected={this.rootSelected} - dropAction={StrCast(this.props.Document.childDropAction) as dropActionType} + dropAction={StrCast(this.layoutDoc.childDropAction) as dropActionType} onClick={this.onChildClickHandler} onDoubleClick={this.onChildDoubleClickHandler} ScreenToLocalTransform={dxf} @@ -236,7 +235,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) if (!d) return 0; const layoutDoc = Doc.Layout(d, this.props.ChildLayoutTemplate?.()); const nw = NumCast(layoutDoc._nativeWidth); - return Math.min(nw && !this.props.Document.fillColumn ? d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); + return Math.min(nw && !this.layoutDoc._columnsFill ? d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); } getDocHeight(d?: Doc) { if (!d) return 0; @@ -246,7 +245,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) let wid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1); if (!layoutDoc._fitWidth && nw && nh) { const aspect = nw && nh ? nh / nw : 1; - if (!(this.props.Document.fillColumn)) wid = Math.min(layoutDoc[WidthSym](), wid); + if (!(this.layoutDoc._columnsFill)) wid = Math.min(layoutDoc[WidthSym](), wid); return wid * aspect; } return layoutDoc._fitWidth ? !nh ? this.props.PanelHeight() - 2 * this.yMargin : @@ -259,7 +258,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) } @action onDividerMove = (e: PointerEvent, down: number[], delta: number[]) => { - this.layoutDoc.columnWidth = Math.max(10, this.columnWidth + delta[0]); + this.layoutDoc._columnWidth = Math.max(10, this.columnWidth + delta[0]); return false; } @@ -341,7 +340,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) this.refList.push(ref); const doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc; this.observer = new _global.ResizeObserver(action((entries: any) => { - if (this.props.Document._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { + if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { Doc.Layout(doc)._height = Math.min(1200, Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace("px", ""))))); } })); @@ -388,7 +387,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) this.refList.push(ref); const doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc; this.observer = new _global.ResizeObserver(action((entries: any) => { - if (this.props.Document._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { + if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { Doc.Layout(doc)._height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0); } })); @@ -411,9 +410,9 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) @action addGroup = (value: string) => { - if (value && this.sectionHeaders) { + if (value && this.columnHeaders) { const schemaHdrField = new SchemaHeaderField(value); - this.sectionHeaders.push(schemaHdrField); + this.columnHeaders.push(schemaHdrField); DocUtils.addFieldEnumerations(undefined, this.pivotField, [{ title: value, _backgroundColor: schemaHdrField.color }]); return true; } @@ -421,22 +420,22 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) } sortFunc = (a: [SchemaHeaderField, Doc[]], b: [SchemaHeaderField, Doc[]]): 1 | -1 => { - const descending = BoolCast(this.props.Document.stackingHeadersSortDescending); + const descending = StrCast(this.layoutDoc._columnsSort) === "descending"; const firstEntry = descending ? b : a; const secondEntry = descending ? a : b; return firstEntry[0].heading > secondEntry[0].heading ? 1 : -1; } onToggle = (checked: Boolean) => { - this.props.Document._chromeStatus = checked ? "collapsed" : "view-mode"; + this.layoutDoc._chromeStatus = checked ? "collapsed" : "view-mode"; } onContextMenu = (e: React.MouseEvent): void => { // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout if (!e.isPropagationStopped()) { const subItems: ContextMenuProps[] = []; - subItems.push({ description: `${this.props.Document.fillColumn ? "Variable Size" : "Autosize"} Column`, event: () => this.props.Document.fillColumn = !this.props.Document.fillColumn, icon: "plus" }); - subItems.push({ description: `${this.Document._autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight, icon: "plus" }); + subItems.push({ description: `${this.layoutDoc._columnsFill ? "Variable Size" : "Autosize"} Column`, event: () => this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill, icon: "plus" }); + subItems.push({ description: `${this.layoutDoc._autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight, icon: "plus" }); ContextMenu.Instance.addItem({ description: "Options...", subitems: subItems, icon: "eye" }); } } @@ -446,7 +445,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) let sections = [[undefined, this.filteredChildren] as [SchemaHeaderField | undefined, Doc[]]]; if (this.pivotField) { const entries = Array.from(this.Sections.entries()); - sections = entries.sort(this.sortFunc); + sections = this.layoutDoc._columnsSort ? entries.sort(this.sortFunc) : entries; } return sections.map((section, i) => this.isStackingView ? this.sectionStacking(section[0], section[1]) : this.sectionMasonry(section[0], section[1], i === 0)); } @@ -489,10 +488,10 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) style={{ width: !this.isStackingView ? "100%" : this.columnWidth / this.numGroupColumns - 10, marginTop: 10 }}>
    } - {this.props.Document._chromeStatus !== 'disabled' && this.props.isSelected() ? : null} diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index b60ed853b..b147b089b 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -96,8 +96,8 @@ export class CollectionStackingViewFieldColumn extends React.Component i.heading).indexOf(castedValue.toString()) > -1) { + if (this.props.parent.columnHeaders) { + if (this.props.parent.columnHeaders.map(i => i.heading).indexOf(castedValue.toString()) > -1) { return false; } } @@ -148,9 +148,9 @@ export class CollectionStackingViewFieldColumn extends React.Component { const key = StrCast(this.props.parent.props.Document._pivotField); this.props.docList.forEach(d => d[key] = undefined); - if (this.props.parent.sectionHeaders && this.props.headingObject) { - const index = this.props.parent.sectionHeaders.indexOf(this.props.headingObject); - this.props.parent.sectionHeaders.splice(index, 1); + if (this.props.parent.columnHeaders && this.props.headingObject) { + const index = this.props.parent.columnHeaders.indexOf(this.props.headingObject); + this.props.parent.columnHeaders.splice(index, 1); } } @@ -168,7 +168,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { const alias = Doc.MakeAlias(this.props.parent.props.Document); - alias._width = this.props.parent.props.PanelWidth() / (Cast(this.props.parent.props.Document.sectionHeaders, listSpec(SchemaHeaderField))?.length || 1); + alias._width = this.props.parent.props.PanelWidth() / (Cast(this.props.parent.columnHeaders, listSpec(SchemaHeaderField))?.length || 1); alias._pivotField = undefined; const key = StrCast(this.props.parent.props.Document._pivotField); let value = this.getValue(this._heading); @@ -259,8 +259,8 @@ export class CollectionStackingViewFieldColumn extends React.Component this.props.parent.props.addDocument(Docs.Create.FreeformDocument([], { _width: 200, _height: 200, _LODdisable: true })), icon: "compress-arrows-alt" }); - layoutItems.push({ description: ":carousel", event: () => this.props.parent.props.addDocument(Docs.Create.CarouselDocument([], { _width: 400, _height: 200, _LODdisable: true })), icon: "compress-arrows-alt" }); + layoutItems.push({ description: ":freeform", event: () => this.props.parent.props.addDocument(Docs.Create.FreeformDocument([], { _width: 200, _height: 200 })), icon: "compress-arrows-alt" }); + layoutItems.push({ description: ":carousel", event: () => this.props.parent.props.addDocument(Docs.Create.CarouselDocument([], { _width: 400, _height: 200 })), icon: "compress-arrows-alt" }); layoutItems.push({ description: ":columns", event: () => this.props.parent.props.addDocument(Docs.Create.MulticolumnDocument([], { _width: 200, _height: 200 })), icon: "compress-arrows-alt" }); layoutItems.push({ description: ":image", event: () => this.props.parent.props.addDocument(Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { _width: 200, _height: 200 })), icon: "compress-arrows-alt" }); @@ -359,7 +359,7 @@ export class CollectionStackingViewFieldColumn extends React.Component - {this.props.parent.Document.hideHeadings ? (null) : headingView} + {this.props.parent.Document._columnsHideIfEmpty ? (null) : headingView} { this.collapsed ? (null) :
    diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 3a13ac822..49480e759 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -341,7 +341,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: const rect = "getBoundingClientRect" in focusNode ? focusNode.getBoundingClientRect() : focusNode?.parentElement.getBoundingClientRect(); const x = (rect?.x || 0); const y = NumCast(srcWeb._scrollTop) + (rect?.y || 0); - const anchor = Docs.Create.FreeformDocument([], { _LODdisable: true, _backgroundColor: "transparent", _width: 25, _height: 25, x, y, annotationOn: srcWeb }); + const anchor = Docs.Create.FreeformDocument([], { _backgroundColor: "transparent", _width: 25, _height: 25, x, y, annotationOn: srcWeb }); anchor.context = srcWeb; const key = Doc.LayoutFieldKey(srcWeb); Doc.AddDocToList(srcWeb, key + "-annotations", anchor); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index d54f4d6e6..f6f6fb7cc 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -176,7 +176,7 @@ class TreeView extends React.Component { })} OnFillDown={undoBatch((value: string) => { Doc.SetInPlace(this.doc, key, value, false); - const doc = Docs.Create.FreeformDocument([], { title: "-", x: 0, y: 0, _width: 100, _height: 25, _LODdisable: true, templates: new List([Templates.Title.Layout]) }); + const doc = Docs.Create.FreeformDocument([], { title: "-", x: 0, y: 0, _width: 100, _height: 25, templates: new List([Templates.Title.Layout]) }); Doc.SetInPlace(this.doc, "editTitle", undefined, false); Doc.SetInPlace(doc, "editTitle", "*", false); return this.props.addDocument(doc); @@ -828,7 +828,7 @@ export class CollectionTreeView extends CollectionSubView Doc.SetInPlace(this.dataDoc, "title", value, false) || true)} OnFillDown={undoBatch((value: string) => { Doc.SetInPlace(this.dataDoc, "title", value, false); - const doc = Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, _width: 100, _height: 25, _LODdisable: true, templates: new List([Templates.Title.Layout]) }); + const doc = Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, _width: 100, _height: 25, templates: new List([Templates.Title.Layout]) }); Doc.SetInPlace(doc, "editTitle", "*", false); this.addDoc(doc, childDocs.length ? childDocs[0] : undefined, true); })} />} diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 5c87bc483..f2ffe7835 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -207,8 +207,8 @@ export class CollectionView extends Touchable); } case CollectionViewType.Carousel: { return (); } case CollectionViewType.Carousel3D: { return (); } - case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } - case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } + case CollectionViewType.Stacking: { this.props.Document._columnsStack = true; return (); } + case CollectionViewType.Masonry: { this.props.Document._columnsStack = false; return (); } case CollectionViewType.Time: { return (); } case CollectionViewType.Map: return (); case CollectionViewType.Grid: return (); @@ -360,7 +360,7 @@ export class CollectionView extends Touchable(); this.childDocs.filter(child => child).forEach(child => Object.keys(Doc.GetProto(child)).forEach(key => facets.add(key))); Doc.AreProtosEqual(this.dataDoc, this.props.Document) && this.childDocs.filter(child => child).forEach(child => Object.keys(child).forEach(key => facets.add(key))); - return Array.from(facets); + return Array.from(facets).filter(f => !f.startsWith("_") && !["proto", "zIndex", "isPrototype", "context", "text-noTemplate"].includes(f)).sort(); } /** @@ -534,7 +534,7 @@ export class CollectionView extends Touchable } diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 276bccede..ab0df88f8 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -406,7 +406,7 @@ export class CollectionStackingViewChrome extends React.Component => { @@ -450,7 +450,11 @@ export class CollectionStackingViewChrome extends React.Component { this.props.CollectionView.props.Document.stackingHeadersSortDescending = !this.props.CollectionView.props.Document.stackingHeadersSortDescending; }; + @action toggleSort = () => { + this.props.CollectionView.props.Document._columnsSort = + this.props.CollectionView.props.Document._columnsSort === "descending" ? "ascending" : + this.props.CollectionView.props.Document._columnsSort === "ascending" ? undefined : "descending"; + }; @action resetValue = () => { this._currentKey = this.pivotField; }; render() { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 5135c4ae4..ba20e9830 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1226,7 +1226,7 @@ export class CollectionFreeFormView extends CollectionSubView this.Document._LODdisable = !this.Document._LODdisable, icon: "table" }); + optionItems.push({ description: `${this.Document._freeformLOD ? "Enable LOD" : "Disable LOD"}`, event: () => this.Document._freeformLOD = !this.Document._freeformLOD, icon: "table" }); optionItems.push({ description: "Import document", icon: "upload", event: ({ x, y }) => { const input = document.createElement("input"); @@ -1390,7 +1390,7 @@ export class CollectionFreeFormView extends CollectionSubView - {!this.Document._LODdisable && !this.props.active() && !this.props.isAnnotationOverlay && !this.props.annotationsKey && this.props.renderDepth > 0 ? + {this.Document._freeformLOD && !this.props.active() && !this.props.isAnnotationOverlay && !this.props.annotationsKey && this.props.renderDepth > 0 ? this.placeholder : this.marqueeView} diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 099859109..97ed74c10 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -352,7 +352,6 @@ export class MarqueeView extends React.Component d.context = newCollection); diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index d375466c9..b732f5f83 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -169,8 +169,8 @@ export class KeyValueBox extends React.Component { getTemplate = async () => { const parent = Docs.Create.StackingDocument([], { _width: 800, _height: 800, title: "Template" }); - parent.singleColumn = false; - parent.columnWidth = 100; + parent._columnsStack = false; + parent._columnWidth = 100; for (const row of this.rows.filter(row => row.isChecked)) { await this.createTemplateField(parent, row); row.uncheck(); diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index 8c16f4a1a..8718bf329 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -184,9 +184,9 @@ export class DashFieldViewInternal extends React.Component(); + alias._columnHeaders = list = new List(); } list.map(c => c.heading).indexOf(this._fieldKey) === -1 && list.push(new SchemaHeaderField(this._fieldKey, "#f1efeb")); list.map(c => c.heading).indexOf("text") === -1 && list.push(new SchemaHeaderField("text", "#f1efeb")); diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index ba3230801..6a85e3b7c 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -275,7 +275,7 @@ export class RichTextRules { if (!fieldKey) { if (docid) { DocServer.GetRefField(docid).then(docx => { - const target = ((docx instanceof Doc) && docx) || Docs.Create.FreeformDocument([], { title: docid, _width: 500, _height: 500, _LODdisable: true, }, docid); + const target = ((docx instanceof Doc) && docx) || Docs.Create.FreeformDocument([], { title: docid, _width: 500, _height: 500, }, docid); DocUtils.Publish(target, docid, returnFalse, returnFalse); DocUtils.MakeLink({ doc: this.Document }, { doc: target }, "portal to"); }); @@ -305,7 +305,7 @@ export class RichTextRules { if (!fieldKey && !docid) return state.tr; docid && DocServer.GetRefField(docid).then(docx => { if (!(docx instanceof Doc && docx)) { - const docx = Docs.Create.FreeformDocument([], { title: docid, _width: 500, _height: 500, _LODdisable: true }, docid); + const docx = Docs.Create.FreeformDocument([], { title: docid, _width: 500, _height: 500 }, docid); DocUtils.Publish(docx, docid, returnFalse, returnFalse); } }); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 5ed1e6239..372d01b9c 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -293,7 +293,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent