diff options
Diffstat (limited to 'src')
3 files changed, 452 insertions, 481 deletions
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index eb81f6e5e..f442559fb 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -1,35 +1,32 @@ -import React = require("react"); -import { CursorProperty } from "csstype"; -import { action, computed, IReactionDisposer, observable, reaction } from "mobx"; -import { observer } from "mobx-react"; -import { DataSym, Doc, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; -import { Copy, Id, ToScriptString, ToString } from "../../../fields/FieldSymbols"; -import { List } from "../../../fields/List"; -import { listSpec } from "../../../fields/Schema"; -import { SchemaHeaderField } from "../../../fields/SchemaHeaderField"; -import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types"; -import { TraceMobx } from "../../../fields/util"; -import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, returnZero, smoothScroll, Utils } from "../../../Utils"; -import { Docs, DocUtils } from "../../documents/Documents"; -import { DocumentType } from '../../documents/DocumentTypes'; -import { DragManager, dropActionType } from "../../util/DragManager"; -import { SnappingManager } from "../../util/SnappingManager"; -import { Transform } from "../../util/Transform"; -import { undoBatch } from "../../util/UndoManager"; -import { ContextMenu } from "../ContextMenu"; -import { ContextMenuProps } from "../ContextMenuItem"; -import { LightboxView } from "../LightboxView"; -import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; -import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment } from "../nodes/DocumentView"; -import { StyleProp } from "../StyleProvider"; -import "./CollectionNoteTakingView.scss"; -import CollectionNoteTakingViewDivider from "./CollectionNoteTakingViewDivider"; -import { CollectionNoteTakingViewColumn } from "./CollectionNoteTakingViewColumn"; -import { CollectionSubView } from "./CollectionSubView"; -import { CollectionViewType } from "./CollectionView"; -import { ObjectField } from "../../../fields/ObjectField"; -import { faThumbsDown } from "@fortawesome/free-solid-svg-icons"; -const _global = (window /* browser */ || global /* node */) as any; +import React = require('react'); +import { CursorProperty } from 'csstype'; +import { action, computed, IReactionDisposer, observable, reaction } from 'mobx'; +import { observer } from 'mobx-react'; +import { DataSym, Doc, HeightSym, Opt, WidthSym } from '../../../fields/Doc'; +import { Id } from '../../../fields/FieldSymbols'; +import { List } from '../../../fields/List'; +import { listSpec } from '../../../fields/Schema'; +import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; +import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; +import { TraceMobx } from '../../../fields/util'; +import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, returnZero, smoothScroll, Utils } from '../../../Utils'; +import { Docs, DocUtils } from '../../documents/Documents'; +import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; +import { DragManager, dropActionType } from '../../util/DragManager'; +import { SnappingManager } from '../../util/SnappingManager'; +import { Transform } from '../../util/Transform'; +import { undoBatch } from '../../util/UndoManager'; +import { ContextMenu } from '../ContextMenu'; +import { ContextMenuProps } from '../ContextMenuItem'; +import { LightboxView } from '../LightboxView'; +import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView'; +import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment } from '../nodes/DocumentView'; +import { StyleProp } from '../StyleProvider'; +import './CollectionNoteTakingView.scss'; +import { CollectionNoteTakingViewColumn } from './CollectionNoteTakingViewColumn'; +import CollectionNoteTakingViewDivider from './CollectionNoteTakingViewDivider'; +import { CollectionSubView } from './CollectionSubView'; +const _global = (window /* browser */ || global) /* node */ as any; export type collectionNoteTakingViewProps = { chromeHidden?: boolean; @@ -38,7 +35,7 @@ export type collectionNoteTakingViewProps = { NativeHeight?: () => number; }; -//TODO: somehow need to update the mapping and then have everything else rerender. Maybe with a refresh boolean like +//TODO: somehow need to update the mapping and then have everything else rerender. Maybe with a refresh boolean like // in Hypermedia? @observer @@ -51,32 +48,54 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti // @observable _docsByColumnHeader = new Map<string, Doc[]>(); //TODO: need to make sure that we save the mapping @observable docsDraggedRowCol: number[] = []; - @observable _cursor: CursorProperty = "grab"; + @observable _cursor: CursorProperty = 'grab'; @observable _scroll = 0; // used to force the document decoration to update when scrolling - @computed get chromeHidden() { return this.props.chromeHidden || BoolCast(this.layoutDoc.chromeHidden); } - @computed get columnHeaders() { return Cast(this.layoutDoc._columnHeaders, listSpec(SchemaHeaderField), null); } - @computed get pivotField() { return "Col" } - @computed get filteredChildren() { return this.childLayoutPairs.filter(pair => (pair.layout instanceof Doc) && !pair.layout.hidden).map(pair => pair.layout); } - @computed get headerMargin() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin); } - @computed get xMargin() { return NumCast(this.layoutDoc._xMargin, 2 * Math.min(this.gridGap, .05 * this.props.PanelWidth())); } - @computed get yMargin() { return this.props.yPadding || NumCast(this.layoutDoc._yMargin, 5); } // 2 * this.gridGap)); } - @computed get gridGap() { return NumCast(this.layoutDoc._gridGap, 10); } - @computed get numGroupColumns() { return this.columnHeaders.length; } - @observable columnStartXCoords: number[] = [] - @computed get PanelWidth() {return this.props.PanelWidth()} - @computed get maxColWdith() {return this.props.PanelWidth() - 2 * this.xMargin;} - - // If the user has not yet created any docs (in another view), this will create a single column. Otherwise, - // it will adjust according to the + @computed get chromeHidden() { + return this.props.chromeHidden || BoolCast(this.layoutDoc.chromeHidden); + } + @computed get columnHeaders() { + return Cast(this.layoutDoc._columnHeaders, listSpec(SchemaHeaderField), null); + } + @computed get pivotField() { + return 'Col'; + } + @computed get filteredChildren() { + return this.childLayoutPairs.filter(pair => pair.layout instanceof Doc && !pair.layout.hidden).map(pair => pair.layout); + } + @computed get headerMargin() { + return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin); + } + @computed get xMargin() { + return NumCast(this.layoutDoc._xMargin, 2 * Math.min(this.gridGap, 0.05 * this.props.PanelWidth())); + } + @computed get yMargin() { + return this.props.yPadding || NumCast(this.layoutDoc._yMargin, 5); + } // 2 * this.gridGap)); } + @computed get gridGap() { + return NumCast(this.layoutDoc._gridGap, 10); + } + @computed get numGroupColumns() { + return this.columnHeaders.length; + } + @observable columnStartXCoords: number[] = []; + @computed get PanelWidth() { + return this.props.PanelWidth(); + } + @computed get maxColWdith() { + return this.props.PanelWidth() - 2 * this.xMargin; + } + + // If the user has not yet created any docs (in another view), this will create a single column. Otherwise, + // it will adjust according to the constructor(props: any) { super(props); if (this.columnHeaders === undefined) { - this.layoutDoc._columnHeaders = new List<SchemaHeaderField>([new SchemaHeaderField('New Column')]); - this.columnStartXCoords = [0] - // add all of the docs that have not been added to a column to this new column + this.layoutDoc._columnHeaders = new List<SchemaHeaderField>([new SchemaHeaderField('New Column')]); + this.columnStartXCoords = [0]; + // add all of the docs that have not been added to a column to this new column } else { - const numHeaders = this.columnHeaders.length - this.resizeColumns(numHeaders) + const numHeaders = this.columnHeaders.length; + this.resizeColumns(numHeaders); } } @@ -88,49 +107,51 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti const height = () => this.getDocHeight(d); const width = () => this.getDocWidth(d); const style = { width: width(), marginTop: this.gridGap, height: height() }; - return <div className={`collectionNoteTakingView-columnDoc`} key={d[Id]} style={style} > - {this.getDisplayDoc(d, width)} - </div>; + return ( + <div className={`collectionNoteTakingView-columnDoc`} key={d[Id]} style={style}> + {this.getDisplayDoc(d, width)} + </div> + ); }); - } + }; // [CAVEATS] (1) keep track of the offsetting // (2) documentView gets unmounted as you remove it from the list get Sections() { const columnHeaders = this.columnHeaders; const sections = new Map<SchemaHeaderField, Doc[]>(columnHeaders.map(sh => [sh, []] as [SchemaHeaderField, []])); - let docs = this.childDocs - const rowCol = this.docsDraggedRowCol - + let docs = this.childDocs; + const rowCol = this.docsDraggedRowCol; + // filter out the currently dragged docs from the child docs, since we will insert them later if (rowCol.length && DragManager.docsBeingDragged.length) { - const docIdsToRemove = new Set() - DragManager.docsBeingDragged.forEach(d => { - docIdsToRemove.add(d[Id]) - }) - docs = docs.filter(d => !docIdsToRemove.has(d[Id])) + const docIdsToRemove = new Set(); + DragManager.docsBeingDragged.forEach(d => { + docIdsToRemove.add(d[Id]); + }); + docs = docs.filter(d => !docIdsToRemove.has(d[Id])); } // this will sort the docs into the correct columns (minus the ones you're currently dragging) docs.map(d => { - if (!d[this.pivotField]) { - d[this.pivotField] = columnHeaders.length > 0 ? columnHeaders[0].heading : `New Column` - }; - const sectionValue = d[this.pivotField] as object; - - // look for if header exists already - const existingHeader = columnHeaders.find(sh => sh.heading === sectionValue.toString()); - if (existingHeader) { - sections.get(existingHeader)!.push(d); - } + if (!d[this.pivotField]) { + d[this.pivotField] = columnHeaders.length > 0 ? columnHeaders[0].heading : `New Column`; + } + const sectionValue = d[this.pivotField] as object; + + // look for if header exists already + const existingHeader = columnHeaders.find(sh => sh.heading === sectionValue.toString()); + if (existingHeader) { + sections.get(existingHeader)!.push(d); + } }); // now we add back in the docs that we're dragging if (rowCol.length && DragManager.docsBeingDragged.length) { - const colHeader = columnHeaders[rowCol[1]] - // TODO: get the actual offset that occurs if the docs were in that column - const offset = 0 - sections.get(colHeader)?.splice(rowCol[0] - offset, 0, ...DragManager.docsBeingDragged) + const colHeader = columnHeaders[rowCol[1]]; + // TODO: get the actual offset that occurs if the docs were in that column + const offset = 0; + sections.get(colHeader)?.splice(rowCol[0] - offset, 0, ...DragManager.docsBeingDragged); } return sections; } @@ -140,12 +161,13 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti // reset section headers when a new filter is inputted this._pivotFieldDisposer = reaction( () => this.pivotField, - () => this.layoutDoc._columnHeaders = new List() + () => (this.layoutDoc._columnHeaders = new List()) ); - this._autoHeightDisposer = reaction(() => this.layoutDoc._autoHeight, - autoHeight => autoHeight && this.props.setHeight?.(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), - this.headerMargin + Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace("px", ""))))))); + this._autoHeightDisposer = reaction( + () => this.layoutDoc._autoHeight, + autoHeight => autoHeight && this.props.setHeight?.(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), this.headerMargin + Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', '')))))) + ); } componentWillUnmount() { @@ -157,47 +179,52 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti @action moveDocument = (doc: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean): boolean => { return this.props.removeDocument?.(doc) && addDocument?.(doc) ? true : false; - } + }; createRef = (ele: HTMLDivElement | null) => { this._masonryGridRef = ele; this.createDashEventsTarget(ele!); //so the whole grid is the drop target? - } + }; - @computed get onChildClickHandler() { return () => this.props.childClickScript || ScriptCast(this.Document.onChildClick); } - @computed get onChildDoubleClickHandler() { return () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick); } + @computed get onChildClickHandler() { + return () => this.props.childClickScript || ScriptCast(this.Document.onChildClick); + } + @computed get onChildDoubleClickHandler() { + return () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick); + } addDocTab = (doc: Doc, where: string) => { - if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) { + if (where === 'inPlace' && this.layoutDoc.isInPlaceContainer) { this.dataDoc[this.props.fieldKey] = new List<Doc>([doc]); return true; } return this.props.addDocTab(doc, where); - } + }; scrollToBottom = () => { smoothScroll(500, this._mainCont!, this._mainCont!.scrollHeight); - } + }; // let's dive in and get the actual document we want to drag/move around focusDocument = (doc: Doc, options?: DocFocusOptions) => { Doc.BrushDoc(doc); let focusSpeed = 0; - const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName("documentView-node")).find((node: any) => node.id === doc[Id]); + const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]); if (found) { const top = found.getBoundingClientRect().top; const localTop = this.props.ScreenToLocalTransform().transformPoint(0, top); if (Math.floor(localTop[1]) !== 0) { - smoothScroll(focusSpeed = doc.presTransition || doc.presTransition === 0 ? NumCast(doc.presTransition) : 500, this._mainCont!, localTop[1] + this._mainCont!.scrollTop); + smoothScroll((focusSpeed = doc.presTransition || doc.presTransition === 0 ? NumCast(doc.presTransition) : 500), this._mainCont!, localTop[1] + this._mainCont!.scrollTop); } } - const endFocus = async (moved: boolean) => options?.afterFocus ? options?.afterFocus(moved) : ViewAdjustment.doNothing; + const endFocus = async (moved: boolean) => (options?.afterFocus ? options?.afterFocus(moved) : ViewAdjustment.doNothing); this.props.focus(this.rootDoc, { - willZoom: options?.willZoom, scale: options?.scale, afterFocus: (didFocus: boolean) => - new Promise<ViewAdjustment>(res => setTimeout(async () => res(await endFocus(didFocus)), focusSpeed)) + willZoom: options?.willZoom, + scale: options?.scale, + afterFocus: (didFocus: boolean) => new Promise<ViewAdjustment>(res => setTimeout(async () => res(await endFocus(didFocus)), focusSpeed)), }); - } + }; styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string) => { if (property === StyleProp.Opacity && doc) { @@ -209,241 +236,243 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti } } return this.props.styleProvider?.(doc, props, property); - } + }; isContentActive = () => this.props.isSelected() || this.props.isContentActive(); // rules for displaying the documents getDisplayDoc(doc: Doc, width: () => number) { - const dataDoc = (!doc.isTemplateDoc && !doc.isTemplateForField && !doc.PARAMS) ? undefined : this.props.DataDoc; + const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField && !doc.PARAMS ? undefined : this.props.DataDoc; const height = () => this.getDocHeight(doc); let dref: Opt<DocumentView>; const noteTakingDocTransform = () => this.getDocTransform(doc, dref); - return <DocumentView ref={r => dref = r || undefined} - Document={doc} - DataDoc={dataDoc || (!Doc.AreProtosEqual(doc[DataSym], doc) && doc[DataSym])} - renderDepth={this.props.renderDepth + 1} - PanelWidth={width} - PanelHeight={height} - styleProvider={this.styleProvider} - docViewPath={this.props.docViewPath} - fitWidth={this.props.childFitWidth} - isContentActive={emptyFunction} - originalBackgroundColor={StrCast(doc.backgroundColor)} - //TODO: change this from a prop to a parameter passed into a function - isNoteTakingView={true} - isDocumentActive={this.isContentActive} - LayoutTemplate={this.props.childLayoutTemplate} - LayoutTemplateString={this.props.childLayoutString} - NativeWidth={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || doc._fitWidth && !Doc.NativeWidth(doc) ? width : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox - NativeHeight={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || doc._fitWidth && !Doc.NativeHeight(doc) ? height : undefined} - dontCenter={this.props.childIgnoreNativeSize ? "xy" : undefined} - dontRegisterView={dataDoc ? true : BoolCast(this.layoutDoc.childDontRegisterViews, this.props.dontRegisterView)} - rootSelected={this.rootSelected} - showTitle={this.props.childShowTitle} - dropAction={StrCast(this.layoutDoc.childDropAction) as dropActionType} - onClick={this.onChildClickHandler} - onDoubleClick={this.onChildDoubleClickHandler} - ScreenToLocalTransform={noteTakingDocTransform} - focus={this.focusDocument} - docFilters={this.childDocFilters} - hideDecorationTitle={this.props.childHideDecorationTitle?.()} - hideResizeHandles={this.props.childHideResizeHandles?.()} - hideTitle={this.props.childHideTitle?.()} - docRangeFilters={this.childDocRangeFilters} - searchFilterDocs={this.searchFilterDocs} - ContainingCollectionDoc={this.props.CollectionView?.props.Document} - ContainingCollectionView={this.props.CollectionView} - addDocument={this.props.addDocument} - moveDocument={this.props.moveDocument} - removeDocument={this.props.removeDocument} - contentPointerEvents={StrCast(this.layoutDoc.contentPointerEvents)} - whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged} - addDocTab={this.addDocTab} - bringToFront={returnFalse} - scriptContext={this.props.scriptContext} - pinToPres={this.props.pinToPres} - />; + return ( + <DocumentView + ref={r => (dref = r || undefined)} + Document={doc} + DataDoc={dataDoc || (!Doc.AreProtosEqual(doc[DataSym], doc) && doc[DataSym])} + renderDepth={this.props.renderDepth + 1} + PanelWidth={width} + PanelHeight={height} + styleProvider={this.styleProvider} + docViewPath={this.props.docViewPath} + fitWidth={this.props.childFitWidth} + isContentActive={emptyFunction} + originalBackgroundColor={StrCast(doc.backgroundColor)} + //TODO: change this from a prop to a parameter passed into a function + isNoteTakingView={true} + isDocumentActive={this.isContentActive} + LayoutTemplate={this.props.childLayoutTemplate} + LayoutTemplateString={this.props.childLayoutString} + NativeWidth={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || (doc._fitWidth && !Doc.NativeWidth(doc)) ? width : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox + NativeHeight={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || (doc._fitWidth && !Doc.NativeHeight(doc)) ? height : undefined} + dontCenter={this.props.childIgnoreNativeSize ? 'xy' : undefined} + dontRegisterView={dataDoc ? true : BoolCast(this.layoutDoc.childDontRegisterViews, this.props.dontRegisterView)} + rootSelected={this.rootSelected} + showTitle={this.props.childShowTitle} + dropAction={StrCast(this.layoutDoc.childDropAction) as dropActionType} + onClick={this.onChildClickHandler} + onDoubleClick={this.onChildDoubleClickHandler} + ScreenToLocalTransform={noteTakingDocTransform} + focus={this.focusDocument} + docFilters={this.childDocFilters} + hideDecorationTitle={this.props.childHideDecorationTitle?.()} + hideResizeHandles={this.props.childHideResizeHandles?.()} + hideTitle={this.props.childHideTitle?.()} + docRangeFilters={this.childDocRangeFilters} + searchFilterDocs={this.searchFilterDocs} + ContainingCollectionDoc={this.props.CollectionView?.props.Document} + ContainingCollectionView={this.props.CollectionView} + addDocument={this.props.addDocument} + moveDocument={this.props.moveDocument} + removeDocument={this.props.removeDocument} + contentPointerEvents={StrCast(this.layoutDoc.contentPointerEvents)} + whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged} + addDocTab={this.addDocTab} + bringToFront={returnFalse} + scriptContext={this.props.scriptContext} + pinToPres={this.props.pinToPres} + /> + ); } // This is used to get the coordinates of a document when we go from a view like freeform to columns getDocTransform(doc: Doc, dref?: DocumentView) { const y = this._scroll; // required for document decorations to update when the text box container is scrolled const { scale, translateX, translateY } = Utils.GetScreenTransform(dref?.ContentDiv || undefined); - // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off - return new Transform(- translateX + (dref?.centeringX || 0), - translateY + (dref?.centeringY || 0), 1).scale(this.props.ScreenToLocalTransform().Scale); + // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off + return new Transform(-translateX + (dref?.centeringX || 0), -translateY + (dref?.centeringY || 0), 1).scale(this.props.ScreenToLocalTransform().Scale); } // how to get the width of a document. Currently returns the width of the column (minus margins) // if a note doc. Otherwise, returns the normal width (for graphs, images, etc...) getDocWidth(d: Doc) { - const heading = d[this.pivotField] as object - const castedSectionValue = heading.toString() - const existingHeader = this.columnHeaders.find(sh => sh.heading === (castedSectionValue)); - const colStartXCoords = this.columnStartXCoords - if (!existingHeader) { - return 1000 - } - const index = this.columnHeaders.indexOf(existingHeader) - const endColValue = index == this.columnHeaders.length - 1 ? this.PanelWidth : this.columnStartXCoords[index+1] - const maxWidth = endColValue - colStartXCoords[index] - 3 * this.xMargin - if (d.type === DocumentType.RTF) { - return maxWidth - } - const width = d[WidthSym]() - return width < maxWidth ? width : maxWidth + const heading = d[this.pivotField] as object; + const castedSectionValue = heading.toString(); + const existingHeader = this.columnHeaders.find(sh => sh.heading === castedSectionValue); + const colStartXCoords = this.columnStartXCoords; + if (!existingHeader) { + return 1000; + } + const index = this.columnHeaders.indexOf(existingHeader); + const endColValue = index == this.columnHeaders.length - 1 ? this.PanelWidth : this.columnStartXCoords[index + 1]; + const maxWidth = endColValue - colStartXCoords[index] - 3 * this.xMargin; + if (d.type === DocumentType.RTF) { + return maxWidth; + } + const width = d[WidthSym](); + return width < maxWidth ? width : maxWidth; } // how to get the height of a document. Nothing special here. getDocHeight(d?: Doc) { if (!d || d.hidden) return 0; const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); - const childDataDoc = (!d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS) ? undefined : this.props.DataDoc; - const maxHeight = (lim => lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim)(NumCast(this.layoutDoc.childLimitHeight, -1)); + const childDataDoc = !d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS ? undefined : this.props.DataDoc; + const maxHeight = (lim => (lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim))(NumCast(this.layoutDoc.childLimitHeight, -1)); const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[WidthSym]() : 0); const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[HeightSym]() : 0); if (nw && nh) { // const colWid = this.columnWidth / this.numGroupColumns; // const docWid = this.layoutDoc._columnsFill ? colWid : Math.min(this.getDocWidth(d), colWid); - const docWid = this.getDocWidth(d) - return Math.min( - maxHeight, - docWid * nh / nw); + const docWid = this.getDocWidth(d); + return Math.min(maxHeight, (docWid * nh) / nw); } const childHeight = NumCast(childLayoutDoc._height); - const panelHeight = (childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin; + const panelHeight = childLayoutDoc._fitWidth || this.props.childFitWidth?.(d) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin; return Math.min(childHeight, maxHeight, panelHeight); } // called when a column is either added or deleted. This function creates n evenly spaced columns resizeColumns = (n: number) => { - const totalWidth = this.PanelWidth - const dividerWidth = 32 - const totaldividerWidth = (n - 1) * dividerWidth - const colWidth = (totalWidth - totaldividerWidth) / n - const newColXCoords: number[] = [] - let colStart = 0 - for (let i = 0; i < n; i++) { - newColXCoords.push(colStart) - colStart += colWidth + dividerWidth - } - this.columnStartXCoords = newColXCoords - } + const totalWidth = this.PanelWidth; + const dividerWidth = 32; + const totaldividerWidth = (n - 1) * dividerWidth; + const colWidth = (totalWidth - totaldividerWidth) / n; + const newColXCoords: number[] = []; + let colStart = 0; + for (let i = 0; i < n; i++) { + newColXCoords.push(colStart); + colStart += colWidth + dividerWidth; + } + this.columnStartXCoords = newColXCoords; + }; // This function is used to preview where a document will drop in a column once a drag is complete. @action onPointerOver = (e: React.PointerEvent) => { - if (DragManager.docsBeingDragged.length && this.childDocList) { - // get the current docs for the column based on the mouse's x coordinate - // will use again later, which is why we're saving as local - const xCoord = e.clientX - 2 * this.gridGap - const colDocs = this.getDocsFromXCoord(xCoord) - // get the index for where you need to insert the doc you are currently dragging - const clientY = e.clientY - let dropInd = -1; - // unsure whether we still want this dropAfter field - // let dropAfter = 0; - // manually set to 140, because not sure how to get exact value - let pos0 = 140 - colDocs.forEach((doc, i) => { - const noteTakingDocTransform = () => this.getDocTransform(doc); - let pos1 = noteTakingDocTransform().inverse().transformPoint(0, this.getDocHeight(doc) + 2 * this.gridGap)[1]; - pos1 += pos0 - // updating drop position based on y coordinates - const yCoordInBetween = clientY > pos0 && (clientY < pos1 || i == colDocs.length - 1) - if (yCoordInBetween) { - dropInd = i; - // dropAfter = 0; - if (clientY > (pos0 + pos1) / 2) { - // dropAfter = 1; - } - } - pos0 = pos1 - }) - // we alter the pivot fields of the docs in case they are moved to a new column. - const colIndex = this.getColumnFromXCoord(xCoord) - const colHeader = StrCast(this.columnHeaders[colIndex].heading) - DragManager.docsBeingDragged.forEach(d => d[this.pivotField] = colHeader) - // used to notify sections to re-render - // console.log([dropInd, this.getColumnFromXCoord(xCoord)]) - this.docsDraggedRowCol = [dropInd, this.getColumnFromXCoord(xCoord)] - } - } + if (DragManager.docsBeingDragged.length && this.childDocList) { + // get the current docs for the column based on the mouse's x coordinate + // will use again later, which is why we're saving as local + const xCoord = e.clientX - 2 * this.gridGap; + const colDocs = this.getDocsFromXCoord(xCoord); + // get the index for where you need to insert the doc you are currently dragging + const clientY = e.clientY; + let dropInd = -1; + // unsure whether we still want this dropAfter field + // let dropAfter = 0; + // manually set to 140, because not sure how to get exact value + let pos0 = 140; + colDocs.forEach((doc, i) => { + const noteTakingDocTransform = () => this.getDocTransform(doc); + let pos1 = noteTakingDocTransform() + .inverse() + .transformPoint(0, this.getDocHeight(doc) + 2 * this.gridGap)[1]; + pos1 += pos0; + // updating drop position based on y coordinates + const yCoordInBetween = clientY > pos0 && (clientY < pos1 || i == colDocs.length - 1); + if (yCoordInBetween) { + dropInd = i; + // dropAfter = 0; + if (clientY > (pos0 + pos1) / 2) { + // dropAfter = 1; + } + } + pos0 = pos1; + }); + // we alter the pivot fields of the docs in case they are moved to a new column. + const colIndex = this.getColumnFromXCoord(xCoord); + const colHeader = StrCast(this.columnHeaders[colIndex].heading); + DragManager.docsBeingDragged.forEach(d => (d[this.pivotField] = colHeader)); + // used to notify sections to re-render + // console.log([dropInd, this.getColumnFromXCoord(xCoord)]) + this.docsDraggedRowCol = [dropInd, this.getColumnFromXCoord(xCoord)]; + } + }; // returns the column index for a given x-coordinate getColumnFromXCoord = (xCoord: number): number => { - const numColumns = this.columnHeaders.length - const coords = this.columnStartXCoords.slice() - coords.push(this.PanelWidth) - let colIndex = 0 + const numColumns = this.columnHeaders.length; + const coords = this.columnStartXCoords.slice(); + coords.push(this.PanelWidth); + let colIndex = 0; for (let i = 0; i < numColumns; i++) { if (xCoord > coords[i] && xCoord < coords[i + 1]) { - colIndex = i - break + colIndex = i; + break; } } - return colIndex - } + return colIndex; + }; - // returns the docs of a column based on the x-coordinate provided. + // returns the docs of a column based on the x-coordinate provided. getDocsFromXCoord = (xCoord: number): Doc[] => { - const colIndex = this.getColumnFromXCoord(xCoord) - const colHeader = StrCast(this.columnHeaders[colIndex].heading) - // const docs = this.childDocList - const docs = this.childDocs - const docsMatchingHeader: Doc[] = [] - if (docs) { - docs.map(d => { - if (d instanceof Promise) return; - const sectionValue = d[this.pivotField] as object; - if (sectionValue.toString() == colHeader) { - docsMatchingHeader.push(d) - } - }) - } - return docsMatchingHeader; - } + const colIndex = this.getColumnFromXCoord(xCoord); + const colHeader = StrCast(this.columnHeaders[colIndex].heading); + // const docs = this.childDocList + const docs = this.childDocs; + const docsMatchingHeader: Doc[] = []; + if (docs) { + docs.map(d => { + if (d instanceof Promise) return; + const sectionValue = d[this.pivotField] as object; + if (sectionValue.toString() == colHeader) { + docsMatchingHeader.push(d); + } + }); + } + return docsMatchingHeader; + }; @undoBatch @action onInternalDrop = (e: Event, de: DragManager.DropEvent) => { if (de.complete.docDragData) { if (super.onInternalDrop(e, de)) { - DragManager.docsBeingDragged = [] - // this.docsDraggedRowCol = [] - // filter out the currently dragged docs from the child docs, since we will insert them later - const rowCol = this.docsDraggedRowCol - const droppedDocs = this.childDocs.slice().filter((d: Doc, ind: number) => ind >= this.childDocs.length); // if the drop operation adds something to the end of the list, then use that as the new document (may be different than what was dropped e.g., in the case of a button which is dropped but which creates say, a note). - const newDocs = droppedDocs.length ? droppedDocs : de.complete.docDragData.droppedDocuments; - - // const docs = this.childDocs - const docs = this.childDocList - if (docs && newDocs.length) { - // remove the dragged documents from the childDocList - newDocs.filter(d => docs.indexOf(d) !== -1).forEach(d => docs.splice(docs.indexOf(d), 1)) - // if the doc starts a columnm (or the drop index is undefined), we can just push it to the front. Otherwise we need to add it to the column properly - //TODO: you need to update childDocList instead. It seems that childDocs is a copy of the actual array we want to modify - if (rowCol[0] <= 0) { - docs.splice(0, 0, ...newDocs) - } else { - const colDocs = this.getDocsFromXCoord(de.x) - const previousDoc = colDocs[rowCol[0] - 1] - const previousDocIndex = docs.indexOf(previousDoc) - console.log(`docs: ${previousDocIndex}`) - docs.splice(previousDocIndex + 1, 0, ...newDocs) + DragManager.docsBeingDragged = []; + // this.docsDraggedRowCol = [] + // filter out the currently dragged docs from the child docs, since we will insert them later + const rowCol = this.docsDraggedRowCol; + const droppedDocs = this.childDocs.slice().filter((d: Doc, ind: number) => ind >= this.childDocs.length); // if the drop operation adds something to the end of the list, then use that as the new document (may be different than what was dropped e.g., in the case of a button which is dropped but which creates say, a note). + const newDocs = droppedDocs.length ? droppedDocs : de.complete.docDragData.droppedDocuments; + + // const docs = this.childDocs + const docs = this.childDocList; + if (docs && newDocs.length) { + // remove the dragged documents from the childDocList + newDocs.filter(d => docs.indexOf(d) !== -1).forEach(d => docs.splice(docs.indexOf(d), 1)); + // if the doc starts a columnm (or the drop index is undefined), we can just push it to the front. Otherwise we need to add it to the column properly + //TODO: you need to update childDocList instead. It seems that childDocs is a copy of the actual array we want to modify + if (rowCol[0] <= 0) { + docs.splice(0, 0, ...newDocs); + } else { + const colDocs = this.getDocsFromXCoord(de.x); + const previousDoc = colDocs[rowCol[0] - 1]; + const previousDocIndex = docs.indexOf(previousDoc); + console.log(`docs: ${previousDocIndex}`); + docs.splice(previousDocIndex + 1, 0, ...newDocs); + } } - } } } // it seems like we're creating a link here. Weird. I didn't know that you could establish links by dragging else if (de.complete.linkDragData?.dragDocument.context === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) { - const source = Docs.Create.TextDocument("", { _width: 200, _height: 75, _fitWidth: true, title: "dropped annotation" }); + const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _fitWidth: true, title: 'dropped annotation' }); this.props.addDocument?.(source); - de.complete.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: de.complete.linkDragData.linkSourceGetAnchor() }, "doc annotation", ""); // TODODO this is where in text links get passed + de.complete.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: de.complete.linkDragData.linkSourceGetAnchor() }, 'doc annotation', ''); // TODODO this is where in text links get passed e.stopPropagation(); - } - else if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de.complete.annoDragData); + } else if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de.complete.annoDragData); return false; - } + }; @undoBatch internalAnchorAnnoDrop(e: Event, annoDragData: DragManager.AnchorAnnoDragData) { @@ -461,16 +490,18 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti onExternalDrop = async (e: React.DragEvent): Promise<void> => { const where = [e.clientX, e.clientY]; let targInd = -1; - const docs = this.getDocsFromXCoord(where[0]) + const docs = this.getDocsFromXCoord(where[0]); docs.map((d, i) => { - const pos0 = this.getDocTransform(d).inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap); - const pos1 = this.getDocTransform(d).inverse().transformPoint(this.getDocWidth(d), this.getDocHeight(d)); - // const pos0 = cd.noteTakingDocTransform().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap); - // const pos1 = cd.noteTakingDocTransform().inverse().transformPoint(cd.width(), cd.height()); - if (where[0] > pos0[0] && where[0] < pos1[0] && where[1] > pos0[1] && where[1] < pos1[1]) { - targInd = i; - } - }) + const pos0 = this.getDocTransform(d) + .inverse() + .transformPoint(-2 * this.gridGap, -2 * this.gridGap); + const pos1 = this.getDocTransform(d).inverse().transformPoint(this.getDocWidth(d), this.getDocHeight(d)); + // const pos0 = cd.noteTakingDocTransform().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap); + // const pos1 = cd.noteTakingDocTransform().inverse().transformPoint(cd.width(), cd.height()); + if (where[0] > pos0[0] && where[0] < pos1[0] && where[1] > pos0[1] && where[1] < pos1[1]) { + targInd = i; + } + }); // this._docXfs.map((cd, i) => { // const pos = cd.noteTakingDocTransform().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap); // const pos1 = cd.noteTakingDocTransform().inverse().transformPoint(cd.width(), cd.height()); @@ -488,7 +519,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti } } }); - } + }; // setDocsForColHeader = (key: string, docs: Doc[]) => { // this._docsByColumnHeader = new Map(this._docsByColumnHeader.set(key, docs)) @@ -499,94 +530,96 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti refList: any[] = []; sectionNoteTaking = (heading: SchemaHeaderField | undefined, docList: Doc[]) => { - const type = "number"; - return <CollectionNoteTakingViewColumn - unobserveHeight={ref => this.refList.splice(this.refList.indexOf(ref), 1)} - observeHeight={ref => { - if (ref) { - this.refList.push(ref); - this.observer = new _global.ResizeObserver(action((entries: any) => { - if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { - const height = this.headerMargin + - Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), - Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace("px", ""))))); - if (!LightboxView.IsLightboxDocView(this.props.docViewPath())) { - this.props.setHeight?.(height); - } - } - })); - this.observer.observe(ref); - } - }} - addDocument={this.addDocument} - // docsByColumnHeader={this._docsByColumnHeader} - // setDocsForColHeader={this.setDocsForColHeader} - chromeHidden={this.chromeHidden} - columnHeaders={this.columnHeaders} - Document={this.props.Document} - DataDoc={this.props.DataDoc} - resizeColumns={this.resizeColumns.bind(this)} - renderChildren={this.children} - numGroupColumns={this.numGroupColumns} - gridGap={this.gridGap} - pivotField={this.pivotField} - columnStartXCoords={this.columnStartXCoords} - maxColWidth={this.maxColWdith} - PanelWidth={this.PanelWidth} - key={heading?.heading ?? ""} - headings={this.headings} - heading={heading?.heading ?? ""} - headingObject={heading} - docList={docList} - yMargin={this.yMargin} - type={type} - createDropTarget={this.createDashEventsTarget} - screenToLocalTransform={this.props.ScreenToLocalTransform} - editableViewProps={{ - GetValue: () => "", - SetValue: this.addGroup, - contents: "+ New Column" - }} - />; - } + const type = 'number'; + return ( + <CollectionNoteTakingViewColumn + unobserveHeight={ref => this.refList.splice(this.refList.indexOf(ref), 1)} + observeHeight={ref => { + if (ref) { + this.refList.push(ref); + this.observer = new _global.ResizeObserver( + action((entries: any) => { + if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { + const height = this.headerMargin + Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', ''))))); + if (!LightboxView.IsLightboxDocView(this.props.docViewPath())) { + this.props.setHeight?.(height); + } + } + }) + ); + this.observer.observe(ref); + } + }} + addDocument={this.addDocument} + // docsByColumnHeader={this._docsByColumnHeader} + // setDocsForColHeader={this.setDocsForColHeader} + chromeHidden={this.chromeHidden} + columnHeaders={this.columnHeaders} + Document={this.props.Document} + DataDoc={this.props.DataDoc} + resizeColumns={this.resizeColumns.bind(this)} + renderChildren={this.children} + numGroupColumns={this.numGroupColumns} + gridGap={this.gridGap} + pivotField={this.pivotField} + columnStartXCoords={this.columnStartXCoords} + maxColWidth={this.maxColWdith} + PanelWidth={this.PanelWidth} + key={heading?.heading ?? ''} + headings={this.headings} + heading={heading?.heading ?? ''} + headingObject={heading} + docList={docList} + yMargin={this.yMargin} + type={type} + createDropTarget={this.createDashEventsTarget} + screenToLocalTransform={this.props.ScreenToLocalTransform} + editableViewProps={{ + GetValue: () => '', + SetValue: this.addGroup, + contents: '+ New Column', + }} + /> + ); + }; // called when adding a new columnHeader @action addGroup = (value: string) => { if (value && this.columnHeaders) { - this.resizeColumns(this.columnHeaders.length + 1) + this.resizeColumns(this.columnHeaders.length + 1); const schemaHdrField = new SchemaHeaderField(value); this.columnHeaders.push(schemaHdrField); return true; } return false; - } + }; sortFunc = (a: [SchemaHeaderField, Doc[]], b: [SchemaHeaderField, Doc[]]): 1 | -1 => { - const descending = StrCast(this.layoutDoc._columnsSort) === "descending"; + 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; - } + }; 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.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" }); - subItems.push({ description: "Clear All", event: () => this.dataDoc.data = new List([]), icon: "times" }); - ContextMenu.Instance.addItem({ description: "Options...", subitems: subItems, icon: "eye" }); + 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' }); + subItems.push({ description: 'Clear All', event: () => (this.dataDoc.data = new List([])), icon: 'times' }); + ContextMenu.Instance.addItem({ description: 'Options...', subitems: subItems, icon: 'eye' }); } - } + }; // used to reset column sizes when using the drag handlers @action setColumnStartXCoords = (movementX: number, colIndex: number) => { - const coords = [...this.columnStartXCoords] - coords[colIndex] += movementX - this.columnStartXCoords = coords - } + const coords = [...this.columnStartXCoords]; + coords[colIndex] += movementX; + this.columnStartXCoords = coords; + }; @computed get renderedSections() { TraceMobx(); @@ -596,22 +629,16 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti // sections = this.layoutDoc._columnsSort ? entries.sort(this.sortFunc) : entries; // } const entries = Array.from(this.Sections.entries()); - const sections = entries.sort(this.sortFunc) - const eles: JSX.Element[] = [] + const sections = entries.sort(this.sortFunc); + const eles: JSX.Element[] = []; for (let i = 0; i < sections.length; i++) { - const col = this.sectionNoteTaking(sections[i][0], sections[i][1]) - eles.push(col) + const col = this.sectionNoteTaking(sections[i][0], sections[i][1]); + eles.push(col); if (i < sections.length - 1) { - eles.push( - <CollectionNoteTakingViewDivider - index={i + 1} - setColumnStartXCoords={this.setColumnStartXCoords.bind(this)} - xMargin={this.xMargin} - /> - ) + eles.push(<CollectionNoteTakingViewDivider index={i + 1} setColumnStartXCoords={this.setColumnStartXCoords.bind(this)} xMargin={this.xMargin} />); } } - return eles + return eles; } @computed get buttonMenu() { @@ -620,79 +647,82 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti if (menuDoc) { const width: number = NumCast(menuDoc._width, 30); const height: number = NumCast(menuDoc._height, 30); - return (<div className="buttonMenu-docBtn" - style={{ width: width, height: height }}> - <DocumentView - Document={menuDoc} - DataDoc={menuDoc} - isContentActive={this.props.isContentActive} - isDocumentActive={returnTrue} - addDocument={this.props.addDocument} - moveDocument={this.props.moveDocument} - addDocTab={this.props.addDocTab} - pinToPres={emptyFunction} - rootSelected={this.props.isSelected} - removeDocument={this.props.removeDocument} - ScreenToLocalTransform={Transform.Identity} - PanelWidth={() => 35} - PanelHeight={() => 35} - renderDepth={this.props.renderDepth} - focus={emptyFunction} - styleProvider={this.props.styleProvider} - docViewPath={returnEmptyDoclist} - whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} - docFilters={this.props.docFilters} - docRangeFilters={this.props.docRangeFilters} - searchFilterDocs={this.props.searchFilterDocs} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} - /> - </div> + return ( + <div className="buttonMenu-docBtn" style={{ width: width, height: height }}> + <DocumentView + Document={menuDoc} + DataDoc={menuDoc} + isContentActive={this.props.isContentActive} + isDocumentActive={returnTrue} + addDocument={this.props.addDocument} + moveDocument={this.props.moveDocument} + addDocTab={this.props.addDocTab} + pinToPres={emptyFunction} + rootSelected={this.props.isSelected} + removeDocument={this.props.removeDocument} + ScreenToLocalTransform={Transform.Identity} + PanelWidth={() => 35} + PanelHeight={() => 35} + renderDepth={this.props.renderDepth} + focus={emptyFunction} + styleProvider={this.props.styleProvider} + docViewPath={returnEmptyDoclist} + whenChildContentsActiveChanged={emptyFunction} + bringToFront={emptyFunction} + docFilters={this.props.docFilters} + docRangeFilters={this.props.docRangeFilters} + searchFilterDocs={this.props.searchFilterDocs} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + /> + </div> ); } } + @computed get nativeWidth() { + return this.props.NativeWidth?.() ?? Doc.NativeWidth(this.layoutDoc); + } + @computed get nativeHeight() { + return this.props.NativeHeight?.() ?? Doc.NativeHeight(this.layoutDoc); + } - @computed get nativeWidth() { return this.props.NativeWidth?.() ?? Doc.NativeWidth(this.layoutDoc); } - @computed get nativeHeight() { return this.props.NativeHeight?.() ?? Doc.NativeHeight(this.layoutDoc); } - - @computed get scaling() { return !this.nativeWidth ? 1 : this.props.PanelHeight() / this.nativeHeight; } + @computed get scaling() { + return !this.nativeWidth ? 1 : this.props.PanelHeight() / this.nativeHeight; + } - @computed get backgroundEvents() { return SnappingManager.GetIsDragging(); } + @computed get backgroundEvents() { + return SnappingManager.GetIsDragging(); + } observer: any; render() { TraceMobx(); const buttonMenu = this.rootDoc.buttonMenu; - const noviceExplainer = this.rootDoc.explainer; + const noviceExplainer = StrCast(this.rootDoc.explainer); return ( <> - {buttonMenu || noviceExplainer ? <div className="documentButtonMenu"> - {buttonMenu ? this.buttonMenu : null} - {Doc.UserDoc().noviceMode && noviceExplainer ? - <div className="documentExplanation"> - {noviceExplainer} - </div> - : null - } - </div> : null} - <div className="collectionNoteTakingView" + {buttonMenu || noviceExplainer ? ( + <div className="documentButtonMenu"> + {buttonMenu ? this.buttonMenu : null} + {Doc.UserDoc().noviceMode && noviceExplainer ? <div className="documentExplanation">{noviceExplainer}</div> : null} + </div> + ) : null} + <div + className="collectionNoteTakingView" ref={this.createRef} style={{ - overflowY: this.props.isContentActive() ? "auto" : "hidden", + overflowY: this.props.isContentActive() ? 'auto' : 'hidden', background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor), - pointerEvents: this.backgroundEvents ? "all" : undefined + pointerEvents: this.backgroundEvents ? 'all' : undefined, }} - onScroll={action(e => this._scroll = e.currentTarget.scrollTop)} + onScroll={action(e => (this._scroll = e.currentTarget.scrollTop))} onPointerOver={this.onPointerOver} onDrop={this.onExternalDrop.bind(this)} onContextMenu={this.onContextMenu} - onWheel={e => this.props.isContentActive(true) && e.stopPropagation()} - > + onWheel={e => this.props.isContentActive(true) && e.stopPropagation()}> {this.renderedSections} </div> </> - ); } -}
\ No newline at end of file +} diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 9a498858a..7385f933b 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -1,4 +1,4 @@ -@import "../global/globalCssVariables"; +@import '../global/globalCssVariables'; .collectionMasonryView { display: inline; @@ -33,7 +33,7 @@ color: $medium-blue; padding: 10px; border-radius: 5px; - border: solid .5px $medium-blue; + border: solid 0.5px $medium-blue; } } @@ -46,9 +46,9 @@ overflow-y: auto; overflow-x: hidden; flex-wrap: wrap; - transition: top .5s; + transition: top 0.5s; - >div { + > div { position: relative; display: block; } @@ -133,34 +133,8 @@ // Documents in stacking view .collectionStackingView-columnDoc { display: flex; - // margin: auto; // Removed auto so that it is no longer center aligned - this could be something we change + // margin: auto; // Removed auto so that it is no longer center aligned - this could be something we change position: relative; - - &:hover { - .hoverButtons{ - opacity: 1; - } - } - - .hoverButtons { - display: flex; - opacity: 0; - position: absolute; - height: 100%; - left: -35px; - justify-content: center; - align-items: center; - padding: 0px 10px; - - .buttonWrapper { - padding: 3px; - border-radius: 3px; - - &:hover { - background: rgba(0, 0, 0, 0.26); - } - } - } } .collectionStackingView-masonryDoc { @@ -201,7 +175,7 @@ span::before, span::after { - content: ""; + content: ''; width: 50%; border-top: dashed gray 1px; position: relative; @@ -242,7 +216,7 @@ .editableView-input:hover, .editableView-container-editing:hover, .editableView-container-editing-oneLine:hover { - cursor: text + cursor: text; } .collectionStackingView-sectionHeader-subCont { @@ -288,7 +262,7 @@ height: 100%; display: none; - [class*="css"] { + [class*='css'] { max-width: 102px; } @@ -330,7 +304,7 @@ height: 100%; display: none; - [class*="css"] { + [class*='css'] { max-width: 102px; } @@ -339,7 +313,6 @@ } .collectionStackingView-optionPicker { - .optionOptions { display: inline; } @@ -399,7 +372,7 @@ .editableView-input:hover, .editableView-container-editing:hover, .editableView-container-editing-oneLine:hover { - cursor: text + cursor: text; } .editableView-input { @@ -452,7 +425,7 @@ top: 4px; border-radius: 50% 50%; background-color: #fff; - content: " "; + content: ' '; cursor: pointer; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26); -webkit-transform: scale(1); @@ -482,7 +455,6 @@ } @media only screen and (max-device-width: 480px) { - .collectionStackingView .collectionStackingView-columnDragger, .collectionMasonryView .collectionStackingView-columnDragger { width: 0.1; @@ -490,4 +462,4 @@ opacity: 0; font-size: 0; } -}
\ No newline at end of file +} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index d3a8af03a..1927db51e 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -90,7 +90,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection } // are we stacking or masonry? @computed get isStackingView() { - return (this.props.viewType ?? this.layoutDoc._viewType) === (CollectionViewType.Stacking || CollectionViewType.NoteTaking); + return (this.props.viewType ?? this.layoutDoc._viewType) === CollectionViewType.Stacking; } // this is the number of StackingViewFieldColumns that we have @computed get numGroupColumns() { @@ -370,13 +370,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection getDocWidth(d?: Doc) { if (!d) return 0; const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); - // TODO: pj - replace with a better way to calculate the margin - let margin = 25; - d.margin = 25; - if (this.columnWidth < 150) { - margin = 0; - } - const maxWidth = this.columnWidth / this.numGroupColumns - margin * 2; + const maxWidth = this.columnWidth / this.numGroupColumns; if (!this.layoutDoc._columnsFill && !(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d))) { return Math.min(d[WidthSym](), maxWidth); } @@ -424,33 +418,10 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection ); } - // TODO: plj - @action - onPointerOver = (e: React.PointerEvent) => { - // console.log("hovering over something") - if (DragManager.docsBeingDragged.length) { - // essentially copying code from onInternalDrop for this: - const doc = DragManager.docsBeingDragged[0]; - // console.log(doc[LayoutSym]()) - - console.log(doc[DataSym]); - console.log(Doc.IndexOf(doc, this.childDocs)); - } - }; - - //used in onPointerOver to swap two nodes in the rendered filtered children list - swapNodes = (i: number, j: number) => {}; - - //plj added this - @action - onPointerDown = (e: React.PointerEvent) => {}; - - // TODO: plj - look at this. Start with making changes to db, and then transition to client side @undoBatch @action onInternalDrop = (e: Event, de: DragManager.DropEvent) => { // Fairly confident that this is where the swapping of nodes in the various arrays happens - console.log('drop'); const where = [de.x, de.y]; // start at -1 until we're sure we want to add it to the column let dropInd = -1; @@ -505,12 +476,10 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection return true; } + /// an item from outside of Dash is being dropped onto this stacking view (e.g, a document from the file system) @undoBatch @action - //What is the difference between internal and external drop?? Does internal mean we're dropping inside of a collection? - // I take it back: external drop means we took it out of column/collection that we were just in onExternalDrop = async (e: React.DragEvent): Promise<void> => { - console.log('external drop'); const where = [e.clientX, e.clientY]; let targInd = -1; this._docXfs.map((cd, i) => { @@ -633,8 +602,8 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection ); }; + /// add a new group category (column) to the active set of note categories. (e.g., if the pivot field is 'transportation', groups might be 'car', 'plane', 'bike', etc) @action - // What are we adding a group to? addGroup = (value: string) => { if (value && this.columnHeaders) { const schemaHdrField = new SchemaHeaderField(value); |