diff options
-rw-r--r-- | src/client/views/collections/CollectionMasonryViewFieldRow.tsx | 133 | ||||
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 2 | ||||
-rw-r--r-- | src/server/authentication/models/current_user_utils.ts | 10 |
3 files changed, 58 insertions, 87 deletions
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index 42f0c4311..3bada43f0 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -2,13 +2,13 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; import { faPalette } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, observable } from "mobx"; +import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc } from "../../../new_fields/Doc"; import { PastelSchemaPalette, SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { ScriptField } from "../../../new_fields/ScriptField"; import { StrCast, NumCast } from "../../../new_fields/Types"; -import { numberRange } from "../../../Utils"; +import { numberRange, setupMoveUpEvents, emptyFunction } from "../../../Utils"; import { Docs } from "../../documents/Documents"; import { DragManager } from "../../util/DragManager"; import { CompileScript } from "../../util/Scripting"; @@ -44,37 +44,44 @@ interface CMVFieldRowProps { export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowProps> { @observable private _background = "inherit"; @observable private _createAliasSelected: boolean = false; - @observable private _collapsed: boolean = false; - @observable private _heading = this.props.headingObject ? this.props.headingObject.heading : this.props.heading; - @observable private _color = this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; + @observable private heading: string = ""; + @observable private color: string = "#f1efeb"; + @observable private collapsed: boolean = false; + private set _heading(value: string) { runInAction(() => this.props.headingObject && (this.props.headingObject.heading = this.heading = value)); } + private set _color(value: string) { runInAction(() => this.props.headingObject && (this.props.headingObject.color = this.color = value)); } + private set _collapsed(value: boolean) { runInAction(() => this.props.headingObject && (this.props.headingObject.collapsed = this.collapsed = value)); } private _dropDisposer?: DragManager.DragDropDisposer; private _headerRef: React.RefObject<HTMLDivElement> = React.createRef(); - private _startDragPosition: { x: number, y: number } = { x: 0, y: 0 }; private _contRef: React.RefObject<HTMLDivElement> = React.createRef(); - private _sensitivity: number = 16; private _ele: any; createRowDropRef = (ele: HTMLDivElement | null) => { - this._dropDisposer && this._dropDisposer(); + this._dropDisposer?.(); if (ele) { this._ele = ele; this.props.observeHeight(ele); this._dropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this)); } } + @action + componentDidMount() { + this.heading = this.props.headingObject?.heading || ""; + this.color = this.props.headingObject?.color || "#f1efeb"; + this.collapsed = this.props.headingObject?.collapsed || false; + } componentWillUnmount() { this.props.unobserveHeight(this._ele); } getTrueHeight = () => { - if (this._collapsed) { - this.props.setDocHeight(this._heading, 20); + if (this.collapsed) { + this.props.setDocHeight(this.heading, 20); } else { const rawHeight = this._contRef.current!.getBoundingClientRect().height + 15; //+ 15 accounts for the group header const transformScale = this.props.screenToLocalTransform().Scale; const trueHeight = rawHeight * transformScale; - this.props.setDocHeight(this._heading, trueHeight); + this.props.setDocHeight(this.heading, trueHeight); } } @@ -86,7 +93,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr (this.props.parent.Document.dropConverter instanceof ScriptField) && this.props.parent.Document.dropConverter.script.run({ dragData: de.complete.docDragData }); const key = StrCast(this.props.parent.props.Document._pivotField); - const castedValue = this.getValue(this._heading); + const castedValue = this.getValue(this.heading); de.complete.docDragData.droppedDocuments.forEach(d => d[key] = castedValue); this.props.parent.onInternalDrop(e, de); e.stopPropagation(); @@ -113,10 +120,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr } } this.props.docList.forEach(d => d[key] = castedValue); - if (this.props.headingObject) { - this.props.headingObject.setHeading(castedValue.toString()); - this._heading = this.props.headingObject.heading; - } + this._heading = castedValue.toString(); return true; } return false; @@ -125,10 +129,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr @action changeColumnColor = (color: string) => { this._createAliasSelected = false; - if (this.props.headingObject) { - this.props.headingObject.setColor(color); - this._color = color; - } + this._color = color; } pointerEnteredRow = action(() => SelectionManager.GetIsDragging() && (this._background = "#b4b4b4")); @@ -137,7 +138,6 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr pointerLeaveRow = () => { this._createAliasSelected = false; this._background = "inherit"; - document.removeEventListener("pointermove", this.startDrag); } @action @@ -161,65 +161,34 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr })); @action - collapseSection = () => { + collapseSection = (e: any) => { this._createAliasSelected = false; - if (this.props.headingObject) { - this.props.headingObject.setCollapsed(!this.props.headingObject.collapsed); - this.toggleVisibility(); - } - } - - startDrag = (e: PointerEvent) => { - const [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y); - if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) { - const alias = Doc.MakeAlias(this.props.parent.props.Document); - const key = StrCast(this.props.parent.props.Document._pivotField); - let value = this.getValue(this._heading); - value = typeof value === "string" ? `"${value}"` : value; - const script = `return doc.${key} === ${value}`; - const compiled = CompileScript(script, { params: { doc: Doc.name } }); - if (compiled.compiled) { - alias.viewSpecScript = new ScriptField(compiled); - DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY); - } - - e.stopPropagation(); - document.removeEventListener("pointermove", this.startDrag); - document.removeEventListener("pointerup", this.pointerUp); - } - } - - pointerUp = (e: PointerEvent) => { + this.toggleVisibility(); e.stopPropagation(); - e.preventDefault(); + } - if (this.props.parent.props.Document._chromeStatus === "disabled") { - this.collapseSection(); + headerMove = (e: PointerEvent) => { + const alias = Doc.MakeAlias(this.props.parent.props.Document); + const key = StrCast(this.props.parent.props.Document._pivotField); + let value = this.getValue(this.heading); + value = typeof value === "string" ? `"${value}"` : value; + const script = `return doc.${key} === ${value}`; + const compiled = CompileScript(script, { params: { doc: Doc.name } }); + if (compiled.compiled) { + alias.viewSpecScript = new ScriptField(compiled); + DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY); } - - document.removeEventListener("pointermove", this.startDrag); - document.removeEventListener("pointerup", this.pointerUp); + return true; } @action headerDown = (e: React.PointerEvent<HTMLDivElement>) => { - e.stopPropagation(); - e.preventDefault(); - - const [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX, e.clientY); - this._startDragPosition = { x: dx, y: dy }; - - if (this.props.parent.props.Document._chromeStatus === "disabled" || this._createAliasSelected) { - document.removeEventListener("pointermove", this.startDrag); - document.addEventListener("pointermove", this.startDrag); - document.removeEventListener("pointerup", this.pointerUp); - document.addEventListener("pointerup", this.pointerUp); - } + setupMoveUpEvents(this, e, this.headerMove, emptyFunction, () => (this.props.parent.props.Document._chromeStatus === "disabled") && this.collapseSection(e)); this._createAliasSelected = false; } renderColorPicker = () => { - const selected = this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; + const selected = this.color; const pink = PastelSchemaPalette.get("pink2"); const purple = PastelSchemaPalette.get("purple4"); @@ -249,7 +218,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr } toggleAlias = action(() => this._createAliasSelected = true); - toggleVisibility = action(() => this._collapsed = !this._collapsed); + toggleVisibility = () => this._collapsed = !this.collapsed; renderMenu = () => { const selected = this._createAliasSelected; @@ -264,7 +233,6 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr @computed get contentLayout() { const rows = Math.max(1, Math.min(this.props.docList.length, Math.floor((this.props.parent.props.PanelWidth() - 2 * this.props.parent.xMargin) / (this.props.parent.columnWidth + this.props.parent.gridGap)))); const style = this.props.parent; - const collapsed = this._collapsed; const chromeStatus = this.props.parent.props.Document._chromeStatus; const newEditableViewProps = { GetValue: () => "", @@ -272,9 +240,9 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr contents: "+ NEW", HeadingObject: this.props.headingObject, toggle: this.toggleVisibility, - color: this._color + color: this.color }; - return collapsed ? (null) : + return this.collapsed ? (null) : <div style={{ position: "relative" }}> {(chromeStatus !== 'view-mode' && chromeStatus !== 'disabled') ? <div className="collectionStackingView-addDocumentButton" @@ -300,10 +268,9 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr } @computed get headingView() { - const heading = this._heading; const noChrome = this.props.parent.props.Document._chromeStatus === "disabled"; const key = StrCast(this.props.parent.props.Document._pivotField); - const evContents = heading ? heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`; + const evContents = this.heading ? this.heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`; const headerEditableViewProps = { GetValue: () => evContents, SetValue: this.headingChanged, @@ -311,7 +278,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr oneLine: true, HeadingObject: this.props.headingObject, toggle: this.toggleVisibility, - color: this._color + color: this.color }; return this.props.parent.props.Document.miniHeaders ? <div className="collectionStackingView-miniHeader"> @@ -319,11 +286,11 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr </div> : !this.props.headingObject ? (null) : <div className="collectionStackingView-sectionHeader" ref={this._headerRef} > - <div className="collectionStackingView-sectionHeader-subCont" onPointerDown={this.headerDown} onClick={noChrome ? undefined : this.collapseSection} + <div className="collectionStackingView-sectionHeader-subCont" onPointerDown={this.headerDown} title={evContents === `NO ${key.toUpperCase()} VALUE` ? `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ""} - style={{ background: evContents !== `NO ${key.toUpperCase()} VALUE` ? this._color : "lightgrey" }}> - <EditableView {...headerEditableViewProps} /> + style={{ background: evContents !== `NO ${key.toUpperCase()} VALUE` ? this.color : "lightgrey" }}> + {noChrome ? evContents : <EditableView {...headerEditableViewProps} />} {noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? (null) : <div className="collectionStackingView-sectionColor"> <Flyout anchorPoint={anchorPoints.CENTER_RIGHT} content={this.renderColorPicker()}> @@ -334,7 +301,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr </div> } {noChrome ? (null) : <button className="collectionStackingView-sectionDelete" onClick={noChrome ? undefined : this.collapseSection}> - <FontAwesomeIcon icon={this._collapsed ? "chevron-down" : "chevron-up"} size="lg" /> + <FontAwesomeIcon icon={this.collapsed ? "chevron-down" : "chevron-up"} size="lg" /> </button>} {noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? (null) : <div className="collectionStackingView-sectionOptions"> @@ -349,17 +316,15 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr </div>; } render() { - const background = this._background; //to account for observables in Measure - const contentlayout = this.contentLayout; - const headingview = this.headingView; + const background = this._background; return <div className="collectionStackingView-masonrySection" style={{ width: this.props.parent.NodeWidth, background }} ref={this.createRowDropRef} onPointerEnter={this.pointerEnteredRow} onPointerLeave={this.pointerLeaveRow} > - {headingview} - {contentlayout} + {this.headingView} + {this.contentLayout} </div >; } }
\ No newline at end of file diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index c05594bbc..7f12aea29 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -218,7 +218,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp public hyperlinkTerms = (terms: string[], target: Doc) => { if (this._editorView && (this._editorView as any).docView && terms.some(t => t)) { const res = terms.filter(t => t).map(term => this.findInNode(this._editorView!, this._editorView!.state.doc, term)); - let tr = this._editorView.state.tr; + const tr = this._editorView.state.tr; const flattened: TextSelection[] = []; res.map(r => r.map(h => flattened.push(h))); const lastSel = Math.min(flattened.length - 1, this._searchIndex); diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index b5a44a8bc..1d41c3570 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -20,6 +20,7 @@ import { PrefetchProxy } from "../../../new_fields/Proxy"; import { FormattedTextBox } from "../../../client/views/nodes/FormattedTextBox"; import { MainView } from "../../../client/views/MainView"; import { DocumentType } from "../../../client/documents/DocumentTypes"; +import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; export class CurrentUserUtils { private static curr_id: string; @@ -108,10 +109,15 @@ export class CurrentUserUtils { const detailViewOpts = { title: "detailView", _width: 300, _fontFamily: "Arial", _fontSize: 12 }; const descriptionWrapperOpts = { title: "descriptions", _height: 300, columnWidth: -1, treeViewHideTitle: true, _pivotField: "title" }; - const descriptionWrapper = MasonryDocument([short, long], { ...shared, ...descriptionWrapperOpts }); - const detailView = Docs.Create.StackingDocument([carousel, details, descriptionWrapper], { ...shared, ...detailViewOpts }); + const descriptionWrapper = MasonryDocument([details, short, long], { ...shared, ...descriptionWrapperOpts }); + descriptionWrapper.sectionHeaders = new List<SchemaHeaderField>([ + new SchemaHeaderField("[Long Description]", "LemonChiffon", undefined, undefined, undefined, true), + new SchemaHeaderField("[Details]", "lightBlue", undefined, undefined, undefined, true), + ]); + const detailView = Docs.Create.StackingDocument([carousel, descriptionWrapper], { ...shared, ...detailViewOpts }); detailView.isTemplateDoc = makeTemplate(detailView); + details.title = "Details"; short.title = "A Short Description"; long.title = "Long Description"; |