From 3c6e77b7d2bcf4782d981b19bc32e402e07863ad Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 28 Sep 2020 10:11:12 -0400 Subject: fixed docRangeFilters to be propagated everywhere and evaluated like docFilters (if the field isn't there, it fails) --- src/client/views/collections/TreeView.tsx | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/client/views/collections/TreeView.tsx') diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 744e8fed6..072cd23db 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -402,6 +402,7 @@ export class TreeView extends React.Component { focus={returnFalse} ScreenToLocalTransform={this.docTransform} docFilters={returnEmptyFilter} + docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} ContainingCollectionDoc={this.props.containingCollection} ContainingCollectionView={undefined} @@ -515,6 +516,7 @@ export class TreeView extends React.Component { bringToFront={emptyFunction} dontRegisterView={BoolCast(this.props.treeView.props.Document.dontRegisterChildViews)} docFilters={returnEmptyFilter} + docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} ContainingCollectionView={undefined} ContainingCollectionDoc={this.props.containingCollection} @@ -585,6 +587,7 @@ export class TreeView extends React.Component { focus={this.refocus} ScreenToLocalTransform={this.docTransform} docFilters={returnEmptyFilter} + docRangeFilters={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} ContainingCollectionDoc={this.props.containingCollection} ContainingCollectionView={undefined} -- cgit v1.2.3-70-g09d2 From 9ad43c9e2a068fdf6308339f6f82e29cf94d2c14 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 29 Sep 2020 02:46:28 -0400 Subject: changed sidebar functionality for textboxes to open outward and make handle blue when there are contents. added a fitToBox capability for contents of sidebar. --- src/client/views/DocumentButtonBar.tsx | 4 +-- src/client/views/PropertiesButtons.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 2 +- src/client/views/collections/TreeView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 36 ++++++++++++---------- src/client/views/nodes/WebBox.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 13 +++++--- src/client/views/pdf/Annotation.tsx | 8 ++--- src/client/views/pdf/PDFViewer.tsx | 4 +-- 9 files changed, 40 insertions(+), 33 deletions(-) (limited to 'src/client/views/collections/TreeView.tsx') diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index c5fd3c777..5ec43319b 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -363,9 +363,9 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV {![DocumentType.VID, DocumentType.WEB].includes(StrCast(this.view0.props.Document.type) as DocumentType) ? (null) :
{this.annotateButton}
} -
+ {!Doc.UserDoc()["documentLinksButton-fullMenu"] ? (null) :
{this.considerGoogleDocsPush} -
+
}
{this.considerGoogleDocsPull}
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 462091f63..9de4f9c67 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -529,7 +529,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
{this.clustersButton}
-
+
{this.fitContentButton}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 4ee00e0f4..423d39951 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -176,7 +176,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) const localTop = this.props.ScreenToLocalTransform().transformPoint(0, top); smoothScroll(doc.presTransition || doc.presTransition === 0 ? NumCast(doc.presTransition) : 500, this._mainCont!, localTop[1] + this._mainCont!.scrollTop); } - afterFocus && setTimeout(() => afterFocus?.(), 500); + afterFocus && setTimeout(afterFocus, 500); } getDisplayDoc(doc: Doc, dxf: () => Transform, width: () => number) { diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 072cd23db..06c35de03 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -664,7 +664,7 @@ export class TreeView extends React.Component { ignoreFields: string[] | undefined, firstLevel: boolean, whenActiveChanged: (isActive: boolean) => void, - dontRegisterView: boolean | undeifned) { + dontRegisterView: boolean | undefined) { const viewSpecScript = Cast(containingCollection.viewSpecScript, ScriptField); if (viewSpecScript) { childDocs = childDocs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 75ad8e5b0..967055638 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -104,28 +104,32 @@ export class CollectionFreeFormView extends CollectionSubView e.bounds && !e.bounds.z).map(e => e.bounds!), NumCast(this.layoutDoc._xPadding, 10), NumCast(this.layoutDoc._yPadding, 10)); } @computed get nativeWidth() { return this.fitToContent ? 0 : returnVal(this.props.NativeWidth?.(), NumCast(this.Document._nativeWidth)); } @computed get nativeHeight() { return this.fitToContent ? 0 : returnVal(this.props.NativeHeight?.(), NumCast(this.Document._nativeHeight)); } private get isAnnotationOverlay() { return this.props.isAnnotationOverlay; } private get scaleFieldKey() { return this.props.scaleField || "_viewScale"; } private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; } - 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 ? - Math.min(this.props.PanelHeight() / (this.contentBounds.b - this.contentBounds.y), - this.props.PanelWidth() / (this.contentBounds.r - this.contentBounds.x)) : - NumCast(this.Document[this.scaleFieldKey], 1)) - + private panX = () => this.fitToContent && !this.props.isAnnotationOverlay ? (this.contentBounds.x + this.contentBounds.r) / 2 : this.Document._panX || 0; + private panY = () => this.fitToContent && !this.props.isAnnotationOverlay ? (this.contentBounds.y + this.contentBounds.b) / 2 : this.Document._panY || 0; + private zoomScaling = () => { + const mult = this.fitToContentScaling / this.parentScaling; + if (this.fitToContent) { + const zs = !this.childDocs.length ? 1 : + Math.min(this.props.PanelHeight() / (this.contentBounds.b - this.contentBounds.y), this.props.PanelWidth() / (this.contentBounds.r - this.contentBounds.x)); + return mult * (this.props.isAnnotationOverlay ? Math.min(zs, 1) : zs); + } + return mult * NumCast(this.Document[this.scaleFieldKey], 1); + } @computed get cachedCenteringShiftX(): number { const scaling = this.fitToContent || !this.contentScaling ? 1 : this.contentScaling; - return !this.isAnnotationOverlay ? this.props.PanelWidth() / 2 / this.parentScaling / scaling : 0; // shift so pan position is at center of window for non-overlay collections + return !this.props.isAnnotationOverlay ? this.props.PanelWidth() / 2 / this.parentScaling / scaling : 0; // shift so pan position is at center of window for non-overlay collections } @computed get cachedCenteringShiftY(): number { const scaling = this.fitToContent || !this.contentScaling ? 1 : this.contentScaling; - return !this.isAnnotationOverlay ? this.props.PanelHeight() / 2 / this.parentScaling / scaling : 0;// shift so pan position is at center of window for non-overlay collections + return !this.props.isAnnotationOverlay ? this.props.PanelHeight() / 2 / this.parentScaling / scaling : 0;// shift so pan position is at center of window for non-overlay collections } @computed get cachedGetLocalTransform(): Transform { return Transform.Identity().scale(1 / this.zoomScaling()).translate(this.panX(), this.panY()); @@ -776,9 +780,6 @@ export class CollectionFreeFormView extends CollectionSubView { let deltaScale = deltaY > 0 ? (1 / 1.05) : 1.05; - if (deltaScale * this.zoomScaling() < 1 && this.isAnnotationOverlay) { - deltaScale = 1 / this.zoomScaling(); - } if (deltaScale < 0) deltaScale = -deltaScale; const [x, y] = this.getTransform().transformPoint(pointX, pointY); const localTransform = this.getLocalTransform().inverse().scaleAbout(deltaScale, x, y); @@ -1106,7 +1107,7 @@ export class CollectionFreeFormView extends CollectionSubView this._cachedPool.set(k[0], k[1])); - const elements: ViewDefResult[] = computedElementData.slice(); + const elements = computedElementData.slice(); const engine = this.props.layoutEngine?.() || StrCast(this.props.Document._layoutEngine); Array.from(newPool.entries()).filter(entry => this.isCurrent(entry[1].pair.layout)).forEach(entry => elements.push({ @@ -1127,8 +1128,9 @@ export class CollectionFreeFormView extends CollectionSubView {this.nonDocAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map(anno => - ) + ) }
; } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index e7b4b72f4..a0af8d60f 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -557,7 +557,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp sidebarDown = (e: React.PointerEvent) => { setupMoveUpEvents(this, e, this.sidebarMove, emptyFunction, - () => this.layoutDoc._showSidebar = ((this.layoutDoc._sidebarWidthPercent = StrCast(this.layoutDoc._sidebarWidthPercent, "0%") === "0%" ? "25%" : "0%")) !== "0%"); + action(() => { + const prevWidth = this.sidebarWidth(); + this.layoutDoc._showSidebar = ((this.layoutDoc._sidebarWidthPercent = StrCast(this.layoutDoc._sidebarWidthPercent, "0%") === "0%" ? "50%" : "0%")) !== "0%"; + this.layoutDoc._width = this.layoutDoc._showSidebar ? NumCast(this.layoutDoc._width) * 2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth); + })); } sidebarMove = (e: PointerEvent, down: number[], delta: number[]) => { const bounds = this.CurrentDiv.getBoundingClientRect(); @@ -1518,16 +1522,17 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } } - return1000 = () => 1000; @computed get sidebarCollection() { + const fitToBox = this.props.Document._fitToBox; return !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) :
{this.sidebarCollection} - {selected ?
: (null)} + {selected ?
: (null)} {!this.layoutDoc._showAudio ? (null) :
this._recording = !this._recording)} > diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index b7c7dae38..84b14cd61 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -1,7 +1,7 @@ import React = require("react"); import { action, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast, HeightSym, WidthSym, Field } from "../../../fields/Doc"; +import { Doc, DocListCast, HeightSym, WidthSym, Field, Opt } from "../../../fields/Doc"; import { Id } from "../../../fields/FieldSymbols"; import { List } from "../../../fields/List"; import { Cast, FieldValue, BoolCast, NumCast, StrCast, PromiseValue } from "../../../fields/Types"; @@ -17,7 +17,7 @@ interface IAnnotationProps { focus: (doc: Doc) => void; dataDoc: Doc; fieldKey: string; - showInfo: (anno: Doc) => void; + showInfo: (anno: Opt) => void; } @observer @@ -25,7 +25,7 @@ export class Annotation extends React.Component { render() { return DocListCast(this.props.anno.annotations).map(a => - ); + ); } } @@ -40,7 +40,7 @@ interface IRegionAnnotationProps { document: Doc; dataDoc: Doc; fieldKey: string; - showInfo: (anno: Doc) => void; + showInfo: (anno: Opt) => void; } @observer diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index e54464b77..fb87da744 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -703,10 +703,10 @@ export class PDFViewer extends ViewBoxAnnotatableComponent users.user.email === this._overlayAnnoInfo!.author)?.userColor }}> {this._overlayAnnoInfo.author + " " + Field.toString(this._overlayAnnoInfo.creationDate as Field)}
-
+
; } - showInfo = action((anno: Doc) => this._overlayAnnoInfo = anno); + showInfo = action((anno: Opt) => this._overlayAnnoInfo = anno); overlayTransform = () => this.scrollXf().scale(1 / this._zoomed); panelWidth = () => (this.Document.scrollHeight || this.Document._nativeHeight || 0); panelHeight = () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : (this.Document._nativeWidth || 0); -- cgit v1.2.3-70-g09d2 From 7e5779c7404d92fdd64958d6240a1418a2ee57d7 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 29 Sep 2020 20:37:26 -0400 Subject: simplfiled ':' menu and fixed creating items to not assume a template. add emptyNote. fixed scrolling in stacking views broken in previous commit. changed formattedTextBox to support stacking sidebar. --- src/client/documents/Documents.ts | 19 +++--- src/client/util/CurrentUserUtils.ts | 7 ++- .../views/collections/CollectionStackingView.tsx | 36 ++++++----- .../CollectionStackingViewFieldColumn.tsx | 31 +++++----- src/client/views/collections/TreeView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 69 +++++++++++++--------- 7 files changed, 97 insertions(+), 69 deletions(-) (limited to 'src/client/views/collections/TreeView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ad30e7d33..47fa7067d 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1,7 +1,8 @@ import { runInAction } from "mobx"; import { basename, extname } from "path"; import { DateField } from "../../fields/DateField"; -import { Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym, AclAddonly } from "../../fields/Doc"; +import { Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym } from "../../fields/Doc"; +import { Id } from "../../fields/FieldSymbols"; import { HtmlField } from "../../fields/HtmlField"; import { InkField } from "../../fields/InkField"; import { List } from "../../fields/List"; @@ -11,6 +12,7 @@ import { SchemaHeaderField } from "../../fields/SchemaHeaderField"; import { ComputedField, ScriptField } from "../../fields/ScriptField"; import { Cast, NumCast, StrCast } from "../../fields/Types"; import { AudioField, ImageField, PdfField, VideoField, WebField, YoutubeField } from "../../fields/URLField"; +import { SharingPermissions } from "../../fields/util"; import { MessageStore } from "../../server/Message"; import { Upload } from "../../server/SharedMediaTypes"; import { OmitKeys, Utils } from "../../Utils"; @@ -33,6 +35,7 @@ import { AudioBox } from "../views/nodes/AudioBox"; import { ColorBox } from "../views/nodes/ColorBox"; import { ComparisonBox } from "../views/nodes/ComparisonBox"; import { DocHolderBox } from "../views/nodes/DocHolderBox"; +import { FilterBox } from "../views/nodes/FilterBox"; import { FontIconBox } from "../views/nodes/FontIconBox"; import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox"; import { ImageBox } from "../views/nodes/ImageBox"; @@ -50,9 +53,6 @@ import { PresElementBox } from "../views/presentationview/PresElementBox"; import { SearchBox } from "../views/search/SearchBox"; import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo"; import { DocumentType } from "./DocumentTypes"; -import { FilterBox } from "../views/nodes/FilterBox"; -import { SharingPermissions } from "../../fields/util"; -import { SharingManager } from "../util/SharingManager"; const path = require('path'); const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", "")); @@ -208,6 +208,8 @@ export interface DocumentOptions { treeViewOutlineMode?: boolean; // whether slide should function as a text outline treeViewLockExpandedView?: boolean; // whether the expanded view can be changed treeViewDefaultExpandedView?: string; // default expanded view + sidebarColor?: string; // background color of text sidebar + sidebarViewType?: string; // collection type of text sidebar limitHeight?: number; // maximum height for newly created (eg, from pasting) text documents // [key: string]: Opt; pointerHack?: boolean; // for buttons, allows onClick handler to fire onPointerDown @@ -1094,8 +1096,8 @@ export namespace DocUtils { return ctor ? ctor(path, options) : undefined; } - export function addDocumentCreatorMenuItems(docTextAdder: (d: Doc) => void, docAdder: (d: Doc) => void, x: number, y: number): void { - ContextMenu.Instance.addItem({ + export function addDocumentCreatorMenuItems(docTextAdder: (d: Doc) => void, docAdder: (d: Doc) => void, x: number, y: number, simpleMenu: boolean = false): void { + !simpleMenu && ContextMenu.Instance.addItem({ description: "Add Note ...", subitems: DocListCast((Doc.UserDoc()["template-notes"] as Doc).data).map((note, i) => ({ description: ":" + StrCast(note.title), @@ -1114,14 +1116,15 @@ export namespace DocUtils { }); ContextMenu.Instance.addItem({ description: "Add Template Doc ...", - subitems: DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc).map((dragDoc, i) => ({ + subitems: DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({ description: ":" + StrCast(dragDoc.title), event: undoBatch((args: { x: number, y: number }) => { - const newDoc = Doc.ApplyTemplate(dragDoc); + const newDoc = Doc.copyDragFactory(dragDoc); if (newDoc) { newDoc.author = Doc.CurrentUserEmail; newDoc.x = x; newDoc.y = y; + if (newDoc.type === DocumentType.RTF) FormattedTextBox.SelectOnLoad = newDoc[Id]; docAdder(newDoc); } }), diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 3e76b189a..7cc35d67a 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -422,9 +422,13 @@ export class CurrentUserUtils { doc.emptyScreenshot = Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot", system: true, cloneFieldFilter: new List(["system"]) }); } if (doc.emptyAudio === undefined) { - doc.emptyAudio = Docs.Create.AudioDocument(nullAudio, { _width: 200, title: "ready to record audio", system: true, cloneFieldFilter: new List(["system"]) }); + doc.emptyAudio = Docs.Create.AudioDocument(nullAudio, { _width: 200, title: "audio recording", system: true, cloneFieldFilter: new List(["system"]) }); ((doc.emptyAudio as Doc).proto as Doc)["dragFactory-count"] = 0; } + if (doc.emptyNote === undefined) { + doc.emptyNote = Docs.Create.TextDocument("", { _width: 200, title: "text note", system: true, cloneFieldFilter: new List(["system"]) }); + ((doc.emptyNote as Doc).proto as Doc)["dragFactory-count"] = 0; + } if (doc.emptyImage === undefined) { doc.emptyImage = Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 250, _nativeWidth: 250, title: "an image of a cat", system: true }); } @@ -444,6 +448,7 @@ export class CurrentUserUtils { this.setupActiveMobileMenu(doc); } return [ + { toolTip: "Tap to create a note in a new pane, drag for a note", title: "Note", icon: "sticky-note", click: 'openOnRight(copyDragFactory(this.clickFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyNote as Doc, noviceMode: true, clickFactory: doc.emptyNote as Doc, }, { toolTip: "Tap to create a collection in a new pane, drag for a collection", title: "Col", icon: "folder", click: 'openOnRight(copyDragFactory(this.clickFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyCollection as Doc, noviceMode: true, clickFactory: doc.emptyPane as Doc, }, { toolTip: "Tap to create a webpage in a new pane, drag for a webpage", title: "Web", icon: "globe-asia", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyWebpage as Doc, noviceMode: true }, { toolTip: "Tap to create a progressive slide", title: "Slide", icon: "file", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptySlide as Doc, noviceMode: true }, diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 423d39951..daaee67dc 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -33,8 +33,12 @@ const _global = (window /* browser */ || global /* node */) as any; type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>; const StackingDocument = makeInterface(collectionSchema, documentSchema); +export type collectionStackingViewProps = { + chromeStatus?: string; +}; + @observer -export class CollectionStackingView extends CollectionSubView(StackingDocument) { +export class CollectionStackingView extends CollectionSubView>(StackingDocument) { _masonryGridRef: HTMLDivElement | null = null; _draggerRef = React.createRef(); _pivotFieldDisposer?: IReactionDisposer; @@ -44,15 +48,16 @@ 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 chromeStatus() { return this.props.chromeStatus || StrCast(this.layoutDoc._chromeStatus); } @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 && !pair.layout.hidden).map(pair => pair.layout); } @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, 5)); } // 2 * this.gridGap)); } + @computed get yMargin() { return Math.max(this.layoutDoc._showTitle && !this.layoutDoc._showTitleHover ? 30 : 0, this.props.yMargin || NumCast(this.layoutDoc._yMargin, 5)); } // 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.layoutDoc._chromeStatus !== 'view-mode' && this.layoutDoc._chromeStatus !== 'disabled')); } + @computed get showAddAGroup() { return (this.pivotField && (this.chromeStatus !== 'view-mode' && this.chromeStatus !== 'disabled')); } @computed get columnWidth() { 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)); @@ -354,7 +359,8 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) 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.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { - Doc.Layout(doc)._height = Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace("px", ""))))); + const height = Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace("px", ""))))); + Doc.Layout(doc)._height = Math.max(height, NumCast(doc[this.props.fieldKey + "-height"])); } })); this.observer.observe(ref); @@ -406,7 +412,8 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) 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.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); + const height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0); + Doc.Layout(doc)._height = Math.max(height, NumCast(doc[this.props.fieldKey + "-height"])); } })); this.observer.observe(ref); @@ -444,10 +451,6 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) return firstEntry[0].heading > secondEntry[0].heading ? 1 : -1; } - onToggle = (checked: Boolean) => { - 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()) { @@ -504,13 +507,14 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) style={{ width: !this.isStackingView ? "100%" : this.columnWidth / this.numGroupColumns - 10, marginTop: 10 }}>
} - {this.layoutDoc._chromeStatus !== 'disabled' && this.props.isSelected() ? : null} + {/* {this.chromeStatus === 'disabled' || !this.props.isSelected() ? (null) : + } */} ); } diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 44d264b36..1bc989e83 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -22,6 +22,8 @@ import { ContextMenuProps } from "../ContextMenuItem"; import { EditableView } from "../EditableView"; import { CollectionStackingView } from "./CollectionStackingView"; import "./CollectionStackingView.scss"; +import { FormattedTextBox } from "../nodes/formattedText/FormattedTextBox"; +import { Id } from "../../../fields/FieldSymbols"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -137,8 +139,9 @@ export class CollectionStackingViewFieldColumn extends React.Component NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading, 0); const heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3; newDoc.heading = heading; - this.props.parent.props.addDocument(newDoc); - return false; + FormattedTextBox.SelectOnLoad = newDoc[Id]; + FormattedTextBox.SelectOnLoadChar = " "; + return this.props.parent.props.addDocument(newDoc); } @action @@ -228,7 +231,10 @@ export class CollectionStackingViewFieldColumn extends React.Component { + FormattedTextBox.SelectOnLoad = doc[Id]; + return this.props.parent.props.addDocument(doc); + }, this.props.parent.props.addDocument, x, y, true); Array.from(Object.keys(Doc.GetProto(dataDoc))).filter(fieldKey => dataDoc[fieldKey] instanceof RichTextField || dataDoc[fieldKey] instanceof ImageField || typeof (dataDoc[fieldKey]) === "string").map(fieldKey => docItems.push({ @@ -256,13 +262,8 @@ export class CollectionStackingViewFieldColumn extends React.Component 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" }); - - ContextMenu.Instance.addItem({ description: "Doc Fields ...", subitems: docItems, icon: "eye" }); - ContextMenu.Instance.addItem({ description: "Containers ...", subitems: layoutItems, icon: "eye" }); + !Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ description: "Doc Fields ...", subitems: docItems, icon: "eye" }); + !Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ description: "Containers ...", subitems: layoutItems, icon: "eye" }); ContextMenu.Instance.setDefaultItem("::", (name: string): void => { Doc.GetProto(this.props.parent.props.Document)[name] = ""; const created = Docs.Create.TextDocument("", { title: name, _width: 250, _autoHeight: true }); @@ -285,7 +286,7 @@ export class CollectionStackingViewFieldColumn extends React.Component headings.indexOf(i) === idx); const evContents = heading ? heading : this.props?.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`; const headerEditableViewProps = { @@ -306,10 +307,10 @@ export class CollectionStackingViewFieldColumn extends React.Component
{/* the default bucket (no key value) has a tooltip that describes what it is. @@ -342,7 +343,7 @@ export class CollectionStackingViewFieldColumn extends React.Component : (null); for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth / style.numGroupColumns}px `; - const chromeStatus = this.props.parent.props.Document._chromeStatus; + const chromeStatus = this.props.parent.chromeStatus; const type = this.props.parent.props.Document.type; return <> {this.props.parent.Document._columnsHideIfEmpty ? (null) : headingView} @@ -365,7 +366,7 @@ export class CollectionStackingViewFieldColumn extends React.Component {(chromeStatus !== 'view-mode' && chromeStatus !== 'disabled' && type !== DocumentType.PRES) ?
+ style={{ width: style.columnWidth / style.numGroupColumns, marginBottom: 10 }}>
: null} diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 06c35de03..1dfa5615a 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -185,7 +185,7 @@ export class TreeView extends React.Component { } public static makeTextBullet() { - const bullet = Docs.Create.TextDocument("-text-", { title: "-title-", forceActive: true, _viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewOutlineMode: true, x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, _backgroundColor: "transparent", _width: 1000, _height: 10 }); + const bullet = Docs.Create.TextDocument("-text-", { title: "-title-", "sidebarColor": "transparent", "sidebarViewType": CollectionViewType.Freeform, forceActive: true, _viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewOutlineMode: true, x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, _backgroundColor: "transparent", _width: 1000, _height: 10 }); Doc.GetProto(bullet).layout = CollectionView.LayoutString("data"); Doc.GetProto(bullet).title = ComputedField.MakeFunction('self.text?.Text'); Doc.GetProto(bullet).data = new List([]); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index a3f76839d..89e0450d7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1627,7 +1627,7 @@ class CollectionFreeFormViewPannableContents extends React.Component { const target = e.target as any; - if (getComputedStyle(target.parentElement)?.overflow === "visible") { // if collection is visible, then scrolling will mess things up since there are no scroll bars + if (getComputedStyle(target)?.overflow === "visible") { // if collection is visible, then scrolling will mess things up since there are no scroll bars target.scrollTop = target.scrollLeft = 0; } }} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 1148087c6..93eb94854 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { isEqual } from "lodash"; +import { isEqual, max } from "lodash"; import { action, computed, IReactionDisposer, Lambda, observable, reaction, runInAction, trace } from "mobx"; import { observer } from "mobx-react"; import { baseKeymap, selectAll } from "prosemirror-commands"; @@ -58,6 +58,8 @@ import "./FormattedTextBox.scss"; import { FormattedTextBoxComment, formattedTextBoxCommentPlugin, findLinkMark } from './FormattedTextBoxComment'; import React = require("react"); import { DocumentManager } from '../../../util/DocumentManager'; +import { CollectionStackingView } from '../../collections/CollectionStackingView'; +import { CollectionViewType } from '../../collections/CollectionView'; export interface FormattedTextBoxProps { makeLink?: () => Opt; // bcz: hack: notifies the text document when the container has made a link. allows the text doc to react and setup a hyeprlink for any selected text @@ -1166,7 +1168,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const mark = schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) }); const curMarks = this._editorView.state.storedMarks ?? $from?.marksAcross(this._editorView.state.selection.$head) ?? []; const storedMarks = [...curMarks.filter(m => m.type !== mark.type), mark]; - this._editorView.dispatch(this._editorView.state.tr.setStoredMarks(storedMarks).insertText(FormattedTextBox.SelectOnLoadChar).setStoredMarks(storedMarks)); + const tr = this._editorView.state.tr.setStoredMarks(storedMarks).insertText(FormattedTextBox.SelectOnLoadChar, this._editorView.state.doc.content.size - 1, this._editorView.state.doc.content.size).setStoredMarks(storedMarks); + this._editorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(tr.doc.content.size)))); FormattedTextBox.SelectOnLoadChar = ""; } else if (curText?.Text) { selectAll(this._editorView!.state, this._editorView?.dispatch); @@ -1496,6 +1499,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp @action tryUpdateHeight(limitHeight?: number) { let scrollHeight = this.ProseRef?.scrollHeight || 0; + this.rootDoc[this.fieldKey + "-height"] = 0; if (this.props.renderDepth && this.layoutDoc._autoHeight && !this.props.ignoreAutoHeight && scrollHeight && !this.props.dontRegisterView) { // 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._viewScale, 1); if (limitHeight && scrollHeight > limitHeight) { @@ -1517,8 +1521,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp try { const boxHeight = Number(getComputedStyle(this._boxRef.current!).height.replace("px", "")); const outer = this.rootDoc[HeightSym]() - boxHeight - (this.props.ChromeHeight ? this.props.ChromeHeight() : 0); - this.rootDoc._height = newHeight + Math.max(0, outer); - this.layoutDoc._nativeHeight = nh ? scrollHeight : undefined; + const finalHeight = newHeight + Math.max(0, outer); + const maxsidebar = !this.sidebarWidth() ? 0 : Array.from(this._boxRef.current!.getElementsByClassName("collectionStackingViewFieldColumn")).reduce((prev, ele) => Math.max(prev, Number(getComputedStyle(ele).height.replace("px", ""))), 0); + if (this.rootDoc._height !== finalHeight && finalHeight > maxsidebar) { + this.rootDoc._height = finalHeight; + this.layoutDoc._nativeHeight = nh ? scrollHeight : undefined; + } + this.rootDoc[this.fieldKey + "-height"] = finalHeight; } catch (e) { console.log("Error in tryUpdateHeight"); } } } @@ -1545,36 +1554,42 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp @computed get sidebarCollection() { const fitToBox = this.props.Document._fitToBox; + const collectionProps = { + ...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit, + PanelHeight: this.props.PanelHeight, + PanelWidth: this.sidebarWidth, + xMargin: 0, + yMargin: 0, + chromeStatus: "enabled", + scaleField: this.annotationKey + "-scale", + annotationsKey: this.annotationKey, + isAnnotationOverlay: true, + fitToBox: fitToBox, + focus: this.props.focus, + isSelected: this.props.isSelected, + select: emptyFunction, + active: this.annotationsActive, + ContentScaling: returnOne, + whenActiveChanged: this.whenActiveChanged, + removeDocument: this.removeDocument, + moveDocument: this.moveDocument, + addDocument: this.addDocument, + CollectionView: undefined, + ScreenToLocalTransform: this.sidebarScreenToLocal, + renderDepth: this.props.renderDepth + 1, + ContainingCollectionDoc: this.props.ContainingCollectionDoc, + }; return !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) : -
- +
+ {this.layoutDoc.sidebarViewType === CollectionViewType.Freeform ? : }
; } @computed get sidebarWidthPercent() { return StrCast(this.layoutDoc._sidebarWidthPercent, "0%"); } sidebarWidth = () => Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100 * this.props.PanelWidth(); sidebarScreenToLocal = () => this.props.ScreenToLocalTransform().translate(-(this.props.PanelWidth() - this.sidebarWidth()) / this.props.ContentScaling(), 0); - @computed get sidebarColor() { return StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "transparent")); } + @computed get sidebarColor() { return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "#e4e4e4")); } render() { TraceMobx(); const selected = this.props.isSelected(); -- cgit v1.2.3-70-g09d2