diff options
Diffstat (limited to 'src/client/views/collections')
16 files changed, 676 insertions, 329 deletions
diff --git a/src/client/views/collections/CollectionLinearView.scss b/src/client/views/collections/CollectionLinearView.scss index b8b72e756..f5c4299a9 100644 --- a/src/client/views/collections/CollectionLinearView.scss +++ b/src/client/views/collections/CollectionLinearView.scss @@ -2,7 +2,7 @@ @import "../_nodeModuleOverrides"; .collectionLinearView-outer { - overflow: hidden; + overflow: visible; height: 100%; .collectionLinearView { diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index a1f5ff657..9ae72ba53 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -1,37 +1,35 @@ import React = require("react"); +import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon, FontAwesomeIconProps } from "@fortawesome/react-fontawesome"; -import { action, computed, observable, reaction, runInAction, Lambda } from "mobx"; +import { Tooltip } from "@material-ui/core"; +import { action, computed, Lambda, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast, Opt, Field } from "../../../fields/Doc"; -import { BoolCast, Cast, StrCast, NumCast } from "../../../fields/Types"; -import AntimodeMenu from "../AntimodeMenu"; -import "./CollectionMenu.scss"; -import { undoBatch } from "../../util/UndoManager"; -import { CollectionViewType, CollectionView, COLLECTION_BORDER_WIDTH } from "./CollectionView"; -import { emptyFunction, setupMoveUpEvents, Utils } from "../../../Utils"; -import { DragManager } from "../../util/DragManager"; -import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; -import { List } from "../../../fields/List"; -import { EditableView } from "../EditableView"; +import { ColorState } from "react-color"; +import { Doc, DocListCast, Opt } from "../../../fields/Doc"; +import { Document } from "../../../fields/documentSchemas"; import { Id } from "../../../fields/FieldSymbols"; -import { listSpec } from "../../../fields/Schema"; -import FormatShapePane from "./collectionFreeForm/FormatShapePane"; -import { ActiveFillColor, SetActiveInkWidth, ActiveInkColor, SetActiveBezierApprox, SetActiveArrowEnd, SetActiveArrowStart, SetActiveFillColor, SetActiveInkColor } from "../InkingStroke"; -import GestureOverlay from "../GestureOverlay"; import { InkTool } from "../../../fields/InkField"; -import { DocumentType } from "../../documents/DocumentTypes"; -import { Document } from "../../../fields/documentSchemas"; -import { SelectionManager } from "../../util/SelectionManager"; -import { DocumentView } from "../nodes/DocumentView"; -import { ColorState } from "react-color"; +import { List } from "../../../fields/List"; import { ObjectField } from "../../../fields/ObjectField"; -import RichTextMenu from "../nodes/formattedText/RichTextMenu"; import { RichTextField } from "../../../fields/RichTextField"; +import { listSpec } from "../../../fields/Schema"; import { ScriptField } from "../../../fields/ScriptField"; -import { IconProp } from '@fortawesome/fontawesome-svg-core'; -import { DocUtils } from "../../documents/Documents"; -import { Tooltip } from "@material-ui/core"; +import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types"; +import { emptyFunction, setupMoveUpEvents, Utils } from "../../../Utils"; +import { DocumentType } from "../../documents/DocumentTypes"; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; +import { DragManager } from "../../util/DragManager"; +import { SelectionManager } from "../../util/SelectionManager"; +import { undoBatch } from "../../util/UndoManager"; +import AntimodeMenu from "../AntimodeMenu"; +import { EditableView } from "../EditableView"; +import GestureOverlay from "../GestureOverlay"; +import { ActiveFillColor, ActiveInkColor, SetActiveArrowEnd, SetActiveArrowStart, SetActiveBezierApprox, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth } from "../InkingStroke"; +import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; +import { DocumentView } from "../nodes/DocumentView"; +import RichTextMenu from "../nodes/formattedText/RichTextMenu"; +import "./CollectionMenu.scss"; +import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView"; @observer export default class CollectionMenu extends AntimodeMenu { @@ -185,7 +183,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp initialize: (button: Doc) => { button['target-docFilters'] = this.target._docFilters instanceof ObjectField ? ObjectField.MakeCopy(this.target._docFilters as any as ObjectField) : ""; }, }; - @computed get _freeform_commands() { return Doc.UserDoc().noviceMode ? [this._viewCommand, this._saveFilterCommand] : [this._viewCommand, this._saveFilterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand]; } + @computed get _freeform_commands() { return Doc.UserDoc().noviceMode ? [this._viewCommand] : [this._viewCommand, this._saveFilterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand]; } @computed get _stacking_commands() { return Doc.UserDoc().noviceMode ? undefined : [this._contentCommand, this._templateCommand]; } @computed get _masonry_commands() { return Doc.UserDoc().noviceMode ? undefined : [this._contentCommand, this._templateCommand]; } @computed get _schema_commands() { return Doc.UserDoc().noviceMode ? undefined : [this._templateCommand, this._narrativeCommand]; } @@ -236,7 +234,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp @computed get subChrome() { switch (this.props.type) { - default: + default: return this.otherSubChrome; case CollectionViewType.Freeform: return (<CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={this.props.type === CollectionViewType.Invalid} />); case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" {...this.props} />); case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" {...this.props} />); @@ -247,6 +245,21 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp case CollectionViewType.Docking: return (<CollectionDockingChrome key="collchrome" {...this.props} />); } } + + @computed get otherSubChrome() { + const docType = this.props.docView.Document.type; + switch (docType) { + default: return (null); + case DocumentType.IMG: return (<CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={false} isDoc={true} />); + case DocumentType.PDF: return (<CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={false} isDoc={true} />); + case DocumentType.INK: return (<CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={false} isDoc={true} />); + case DocumentType.WEB: return (<CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={false} isDoc={true} />); + case DocumentType.VID: return (<CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={false} isDoc={true} />); + case DocumentType.RTF: return (<CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={this.props.type === CollectionViewType.Invalid} isDoc={true} />); + } + } + + private dropDisposer?: DragManager.DragDropDisposer; protected createDropTarget = (ele: HTMLDivElement) => { this.dropDisposer?.(); @@ -392,7 +405,7 @@ export class CollectionDockingChrome extends React.Component<CollectionMenuProps } @observer -export class CollectionFreeFormViewChrome extends React.Component<CollectionMenuProps & { isOverlay: boolean }> { +export class CollectionFreeFormViewChrome extends React.Component<CollectionMenuProps & { isOverlay: boolean, isDoc?: boolean }> { public static Instance: CollectionFreeFormViewChrome; constructor(props: any) { super(props); @@ -590,34 +603,36 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu </div>; } + @observable viewType = this.selectedDoc?._viewType; + render() { return !this.props.docView.layoutDoc ? (null) : <div className="collectionFreeFormMenu-cont"> - {this.props.docView.props.renderDepth !== 0 || this.isText ? (null) : + {this.props.docView.props.renderDepth !== 0 || this.isText || this.props.isDoc ? (null) : <Tooltip key="map" title={<div className="dash-tooltip">Toggle Mini Map</div>} placement="bottom"> - <div className="backKeyframe" onClick={this.miniMap}> + <div className="backKeyframe" onClick={this.miniMap} style={{ marginRight: "5px" }}> <FontAwesomeIcon icon={"map"} size={"lg"} /> </div> </Tooltip> } - {!this.isText ? <Tooltip key="back" title={<div className="dash-tooltip">Back Frame</div>} placement="bottom"> + {!this.isText && !this.props.isDoc ? <Tooltip key="back" title={<div className="dash-tooltip">Back Frame</div>} placement="bottom"> <div className="backKeyframe" onClick={this.prevKeyframe}> <FontAwesomeIcon icon={"caret-left"} size={"lg"} /> </div> </Tooltip> : null} - {!this.isText ? <Tooltip key="num" title={<div className="dash-tooltip">Toggle View All</div>} placement="bottom"> + {!this.isText && !this.props.isDoc ? <Tooltip key="num" title={<div className="dash-tooltip">Toggle View All</div>} placement="bottom"> <div className="numKeyframe" style={{ backgroundColor: this.document.editing ? "#759c75" : "#c56565" }} onClick={action(() => this.document.editing = !this.document.editing)} > {NumCast(this.document.currentFrame)} </div> </Tooltip> : null} - {!this.isText ? <Tooltip key="fwd" title={<div className="dash-tooltip">Forward Frame</div>} placement="bottom"> + {!this.isText && !this.props.isDoc ? <Tooltip key="fwd" title={<div className="dash-tooltip">Forward Frame</div>} placement="bottom"> <div className="fwdKeyframe" onClick={this.nextKeyframe}> <FontAwesomeIcon icon={"caret-right"} size={"lg"} /> </div> </Tooltip> : null} - {!this.props.isOverlay || this.document.type !== DocumentType.WEB || this.isText ? (null) : + {!this.props.isOverlay || this.document.type !== DocumentType.WEB || this.isText || this.props.isDoc ? (null) : <Tooltip key="hypothesis" title={<div className="dash-tooltip">Use Hypothesis</div>} placement="bottom"> <button className={"antimodeMenu-button"} key="hypothesis" style={{ @@ -655,6 +670,24 @@ export class CollectionStackingViewChrome extends React.Component<CollectionMenu getKeySuggestions = async (value: string): Promise<string[]> => { value = value.toLowerCase(); const docs = DocListCast(this.document[this.props.fieldKey]); + + if (Doc.UserDoc().noviceMode) { + if (docs instanceof Doc) { + const keys = Object.keys(docs).filter(key => key.indexOf("title") >= 0 || key.indexOf("author") >= 0 || + key.indexOf("creationDate") >= 0 || key.indexOf("lastModified") >= 0 || + (key[0].toUpperCase() === key[0] && key.substring(0, 3) !== "ACL" && key !== "UseCors" && key[0] !== "_")); + return keys.filter(key => key.toLowerCase().indexOf(value.toLowerCase()) > -1); + } else { + const keys = new Set<string>(); + docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key))); + const noviceKeys = Array.from(keys).filter(key => key.indexOf("title") >= 0 || + key.indexOf("author") >= 0 || key.indexOf("creationDate") >= 0 || + key.indexOf("lastModified") >= 0 || (key[0].toUpperCase() === key[0] && + key.substring(0, 3) !== "ACL" && key !== "UseCors" && key[0] !== "_")); + return noviceKeys.filter(key => key.toLowerCase().indexOf(value.toLowerCase()) > -1); + } + } + if (docs instanceof Doc) { return Object.keys(docs).filter(key => key.toLowerCase().startsWith(value)); } else { diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index eecaf7672..d11d6a5ba 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -32,6 +32,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import DatePicker from "react-datepicker"; import "react-datepicker/dist/react-datepicker.css"; import { DateField } from "../../../fields/DateField"; +import { RichTextField } from "../../../fields/RichTextField"; const path = require('path'); library.add(faExpand); @@ -193,7 +194,8 @@ export class CollectionSchemaCell extends React.Component<CellProps> { const fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc); const onItemDown = (e: React.PointerEvent) => { - fieldIsDoc && SetupDrag(this._focusRef, + //fieldIsDoc && + SetupDrag(this._focusRef, () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document, this._document[props.fieldKey] instanceof Doc ? (doc: Doc | Doc[], target: Doc | undefined, addDoc: (newDoc: Doc | Doc[]) => any) => addDoc(doc) : this.props.moveDocument, this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e); @@ -240,25 +242,72 @@ export class CollectionSchemaCell extends React.Component<CellProps> { // <FontAwesomeIcon icon="expand" size="sm" /> // </div> // ); - trace(); - - - + const positions = []; + if (StrCast(this.props.Document._searchString).toLowerCase() !== "") { + const cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey])); + let term = ""; + if (cfield !== undefined) { + if (cfield.Text !== undefined) { + term = cfield.Text; + } + else if (StrCast(cfield)) { + term = StrCast(cfield); + } + else { + term = String(NumCast(cfield)); + } + } + term = term.toLowerCase(); + const search = StrCast(this.props.Document._searchString).toLowerCase(); + let start = term.indexOf(search); + let tally = 0; + if (start !== -1) { + positions.push(start); + } + while (start < contents.length && start !== -1) { + term = term.slice(start + search.length + 1); + tally += start + search.length + 1; + start = term.indexOf(search); + positions.push(tally + start); + } + if (positions.length > 1) { + positions.pop(); + } + } return ( - <div className="collectionSchemaView-cellContainer" style={{ cursor: fieldIsDoc ? "grab" : "auto" }} ref={dragRef} onPointerDown={this.onPointerDown} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave}> + <div className="collectionSchemaView-cellContainer" style={{ cursor: fieldIsDoc ? "grab" : "auto" }} + ref={dragRef} onPointerDown={this.onPointerDown} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave}> <div className={className} ref={this._focusRef} onPointerDown={onItemDown} tabIndex={-1}> <div className="collectionSchemaView-cellContents" ref={type === undefined || type === "document" ? this.dropRef : null} key={props.Document[Id]}> - - <EditableView + positions={positions.length > 0 ? positions : undefined} + search={StrCast(this.props.Document._searchString) ? StrCast(this.props.Document._searchString) : undefined} editing={this._isEditing} isEditingCallback={this.isEditingCallback} display={"inline"} contents={contents ? contents : type === "number" ? "0" : "undefined"} + highlight={positions.length > 0 ? true : undefined} //contents={StrCast(contents)} height={"auto"} maxHeight={Number(MAX_ROW_HEIGHT)} placeholder={"enter value"} + bing={() => { + const cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey])); + if (cfield !== undefined) { + console.log(typeof (cfield)); + // if (typeof(cfield)===RichTextField) + const a = cfield as RichTextField; + if (a.Text !== undefined) { + return (a.Text); + } + else if (StrCast(cfield)) { + return StrCast(cfield); + } + else { + return String(NumCast(cfield)); + } + } + }} GetValue={() => { if (type === "number" && (contents === 0 || contents === "0")) { return "0"; @@ -272,6 +321,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> { const val = cscript !== undefined ? (cfinalScript?.endsWith(";") ? `:=${cfinalScript?.substring(0, cfinalScript.length - 2)}` : cfinalScript) : Field.IsField(cfield) ? Field.toScriptString(cfield) : ""; return val; + } }} @@ -827,3 +877,69 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell { ); } } + + +@observer +export class CollectionSchemaButtons extends CollectionSchemaCell { + + render() { + // const reference = React.createRef<HTMLDivElement>(); + // const onItemDown = (e: React.PointerEvent) => { + // (!this.props.CollectionView || !this.props.CollectionView.props.isSelected() ? undefined : + // SetupDrag(reference, () => this._document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); + // }; + const doc = this.props.rowProps.original; + let buttons: JSX.Element | undefined = undefined; + buttons = <div style={{ + paddingTop: 8, + paddingLeft: 3, + }}><button onClick={() => { + doc.searchMatch = false; + setTimeout(() => doc.searchMatch = true, 0); + doc.searchIndex = NumCast(doc.searchIndex); + }} style={{ padding: 2, left: 77 }}> + <FontAwesomeIcon icon="arrow-up" size="sm" /> + </button> + <button onClick={() => { + { + doc.searchMatchAlt = false; + setTimeout(() => doc.searchMatchAlt = true, 0); + doc.searchIndex = NumCast(doc.searchIndex); + } + }} style={{ padding: 2 }}> + <FontAwesomeIcon icon="arrow-down" size="sm" /> + </button></div>; + const type = StrCast(doc.type); + if (type === "pdf") { + buttons = <div><button + style={{ + position: "relative", + height: 30, + width: 28, + left: 1, + }} + + onClick={() => { + doc.searchMatch = false; + setTimeout(() => doc.searchMatch = true, 0); + doc.searchIndex = NumCast(doc.searchIndex); + }}> + <FontAwesomeIcon icon="arrow-down" size="sm" /> + </button></div >; + } + else if (type !== "rtf") { + buttons = undefined; + } + + if (BoolCast(this.props.Document._searchDoc) === true) { + + } + else { + buttons = undefined; + } + return ( + <div> {buttons}</div> + ); + } +} + diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index efff4db98..e65adcf76 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -9,6 +9,8 @@ import { ColumnType } from "./CollectionSchemaView"; import { faFile } from "@fortawesome/free-regular-svg-icons"; import { SchemaHeaderField, PastelSchemaPalette } from "../../../fields/SchemaHeaderField"; import { undoBatch } from "../../util/UndoManager"; +import { Doc } from "../../../fields/Doc"; +import { StrCast } from "../../../fields/Types"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -76,14 +78,6 @@ export class CollectionSchemaAddColumnHeader extends React.Component<AddColumnHe - - - - - - - - export interface ColumnMenuProps { columnField: SchemaHeaderField; // keyValue: string; @@ -288,9 +282,10 @@ export interface KeysDropdownProps { existingKeys: string[]; canAddNew: boolean; addNew: boolean; - onSelect: (oldKey: string, newKey: string, addnew: boolean) => void; + onSelect: (oldKey: string, newKey: string, addnew: boolean, filter?: string) => void; setIsEditing: (isEditing: boolean) => void; width?: string; + docs?: Doc[]; } @observer export class KeysDropdown extends React.Component<KeysDropdownProps> { @@ -306,10 +301,23 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> { @action onSelect = (key: string): void => { - this.props.onSelect(this._key, key, this.props.addNew); - this.setKey(key); + if (key.slice(0, this._key.length) === this._key && this._key !== key) { + const filter = key.slice(this._key.length - key.length); + this.props.onSelect(this._key, this._key, this.props.addNew, filter); + } + else { + this.props.onSelect(this._key, key, this.props.addNew); + this.setKey(key); + this._isOpen = false; + this.props.setIsEditing(false); + } + } + + @action + onSelect2 = (key: string): void => { + this._searchTerm = this._searchTerm.slice(0, this._key.length) + key; this._isOpen = false; - this.props.setIsEditing(false); + } @undoBatch @@ -371,22 +379,53 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> { }); // if search term does not already exist as a group type, give option to create new group type - if (!exactFound && this._searchTerm !== "" && this.props.canAddNew) { - options.push(<div key={""} className="key-option" style={{ + if (this._key !== this._searchTerm.slice(0, this._key.length)) { + if (!exactFound && this._searchTerm !== "" && this.props.canAddNew) { + options.push(<div key={""} className="key-option" style={{ + border: "1px solid lightgray", + width: this.props.width, maxWidth: this.props.width, overflowX: "hidden" + }} + onClick={() => { this.onSelect(this._searchTerm); this.setSearchTerm(""); }}> + Create "{this._searchTerm}" key</div>); + } + } + + return options; + } + + renderFilterOptions = (): JSX.Element[] | JSX.Element => { + if (!this._isOpen) return <></>; + const keyOptions: string[] = []; + const temp = this._searchTerm.slice(this._key.length); + this.props.docs?.forEach((doc) => { + const key = StrCast(doc[this._key]); + if (keyOptions.includes(key) === false && key.includes(temp)) { + keyOptions.push(key); + } + }); + + + const options = keyOptions.map(key => { + return <div key={key} className="key-option" style={{ border: "1px solid lightgray", width: this.props.width, maxWidth: this.props.width, overflowX: "hidden" }} - onClick={() => { this.onSelect(this._searchTerm); this.setSearchTerm(""); }}> - Create "{this._searchTerm}" key</div>); - } + onPointerDown={e => e.stopPropagation()} onClick={() => { this.onSelect2(key); }}>{key}</div>; + }); return options; } + render() { return ( - <div className="keys-dropdown" style={{ width: this.props.width, maxWidth: this.props.width, overflowX: "hidden" }}> - <input className="keys-search" //style={{ width: this.props.width, maxWidth: "1000" }} + <div className="keys-dropdown" style={{ zIndex: 10, width: this.props.width, maxWidth: this.props.width }}> + {this._key === this._searchTerm.slice(0, this._key.length) ? + <div style={{ position: "absolute", marginLeft: "4px", marginTop: "3", color: "grey", pointerEvents: "none", lineHeight: 1.15 }}> + {this._key} + </div> + : undefined} + <input className="keys-search" style={{ width: "100%" }} ref={this._inputRef} type="text" value={this._searchTerm} placeholder="Column key" onKeyDown={this.onKeyDown} onChange={e => this.onChange(e.target.value)} onClick={(e) => { @@ -395,10 +434,11 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> { }} onFocus={this.onFocus} onBlur={this.onBlur}></input> <div className="keys-options-wrapper" style={{ backgroundColor: "white", - width: this.props.width, maxWidth: this.props.width, overflowX: "hidden" + width: this.props.width, maxWidth: this.props.width, }} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerOut}> - {this.renderOptions()} + {this._key === this._searchTerm.slice(0, this._key.length) ? + this.renderFilterOptions() : this.renderOptions()} </div> </div > ); diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index b77173b25..dade4f2f2 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -209,6 +209,14 @@ export class MovableRow extends React.Component<MovableRowProps> { return doc !== targetCollection && doc !== targetView?.props.ContainingCollectionDoc && this.props.removeDoc(doc) && addDoc(doc); } + @action + onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { + console.log("yes"); + if (e.key === "Backspace" || e.key === "Delete") { + undoBatch(() => this.props.removeDoc(this.props.rowInfo.original)); + } + } + render() { const { children = null, rowInfo } = this.props; if (!rowInfo) { @@ -227,14 +235,14 @@ export class MovableRow extends React.Component<MovableRowProps> { if (this.props.rowWrapped) className += " row-wrapped"; return ( - <div className={className} ref={this.createRowDropTarget} onContextMenu={this.onRowContextMenu}> - <div className="collectionSchema-row-wrapper" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}> - <ReactTableDefaults.TrComponent> - <div className="row-dragger"> + <div className={className} onKeyPress={this.onKeyDown} ref={this.createRowDropTarget} onContextMenu={this.onRowContextMenu}> + <div className="collectionSchema-row-wrapper" onKeyPress={this.onKeyDown} ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}> + <ReactTableDefaults.TrComponent onKeyPress={this.onKeyDown} > + {/* <div className="row-dragger"> <div className="row-option" onClick={undoBatch(() => this.props.removeDoc(this.props.rowInfo.original))}><FontAwesomeIcon icon="trash" size="sm" /></div> <div className="row-option" style={{ cursor: "grab" }} ref={reference} onPointerDown={onItemDown}><FontAwesomeIcon icon="grip-vertical" size="sm" /></div> <div className="row-option" onClick={() => this.props.addDocTab(this.props.rowInfo.original, "onRight")}><FontAwesomeIcon icon="external-link-alt" size="sm" /></div> - </div> + </div> */} {children} </ReactTableDefaults.TrComponent> </div> diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 5226a60f1..ba0a259c5 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -6,7 +6,7 @@ border-style: solid; border-radius: $border-radius; box-sizing: border-box; - position: absolute; + position: relative; top: 0; width: 100%; height: 100%; @@ -25,7 +25,6 @@ .collectionSchemaView-tableContainer { width: 100%; height: 100%; - overflow: scroll; } .collectionSchemaView-dividerDragger { @@ -59,9 +58,7 @@ } .rt-thead { - width: calc(100% - 52px); - margin-left: 50px; - + width: 100%; z-index: 100; overflow-y: visible; @@ -96,7 +93,7 @@ } .rt-tbody { - width: calc(100% - 2px); + width: 100%; direction: rtl; overflow: visible; } @@ -164,16 +161,6 @@ .collectionSchema-col { height: 100%; - - .collectionSchema-col-wrapper { - &.col-before { - border-left: 2px solid red; - } - - &.col-after { - border-right: 2px solid red; - } - } } @@ -297,7 +284,6 @@ button.add-column { background-color: white; border: 1px solid lightgray; padding: 2px 3px; - overflow-x: hidden; &:not(:first-child) { border-top: 0; @@ -525,14 +511,21 @@ button.add-column { .collectionSchemaView-table { width: 100%; height: 100%; - overflow: visible; } .reactTable-sub { padding: 10px 30px; background-color: rgb(252, 252, 252); - width: calc(100% - 50px); - margin-left: 50px; + width: 100%; + + .rt-thead { + display:none; + } + .collectionSchemaView-table{ + border: solid 1px; + overflow: hidden; + } + .row-dragger { background-color: rgb(252, 252, 252); @@ -567,7 +560,6 @@ button.add-column { text-transform: uppercase; cursor: pointer; font-size: 10.5px; - padding: 10px; margin-left: 50px; margin-top: 10px; }
\ No newline at end of file diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index f67e049fd..a003de0d3 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -4,27 +4,26 @@ import { faCog, faPlus, faSortDown, faSortUp, faTable } from '@fortawesome/free- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, untracked } from "mobx"; import { observer } from "mobx-react"; +import Measure from "react-measure"; import { Resize } from "react-table"; import "react-table/react-table.css"; import { Doc } from "../../../fields/Doc"; import { List } from "../../../fields/List"; import { listSpec } from "../../../fields/Schema"; -import { SchemaHeaderField, PastelSchemaPalette } from "../../../fields/SchemaHeaderField"; -import { Cast, NumCast, StrCast } from "../../../fields/Types"; -import { Docs, DocumentOptions } from "../../documents/Documents"; +import { PastelSchemaPalette, SchemaHeaderField } from "../../../fields/SchemaHeaderField"; +import { Cast, NumCast } from "../../../fields/Types"; +import { TraceMobx } from "../../../fields/util"; +import { emptyFunction, returnFalse, returnOne, returnZero, setupMoveUpEvents } from "../../../Utils"; +import { SnappingManager } from "../../util/SnappingManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; import { COLLECTION_BORDER_WIDTH } from '../../views/globalCssVariables.scss'; import '../DocumentDecorations.scss'; +import { ContentFittingDocumentView } from "../nodes/ContentFittingDocumentView"; import { KeysDropdown } from "./CollectionSchemaHeaders"; import "./CollectionSchemaView.scss"; import { CollectionSubView } from "./CollectionSubView"; -import { ContentFittingDocumentView } from "../nodes/ContentFittingDocumentView"; -import { setupMoveUpEvents, emptyFunction, returnZero, returnOne, returnFalse } from "../../../Utils"; -import { SnappingManager } from "../../util/SnappingManager"; -import Measure from "react-measure"; import { SchemaTable } from "./SchemaTable"; -import { TraceMobx } from "../../../fields/util"; library.add(faCog, faPlus, faSortUp, faSortDown); library.add(faTable); @@ -170,6 +169,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action setColumnSort = (columnField: SchemaHeaderField, descending: boolean | undefined) => { const columns = this.columns; + columns.forEach(col => col.setDesc(undefined)); + const index = columns.findIndex(c => c.heading === columnField.heading); const column = columns[index]; column.setDesc(descending); @@ -310,7 +311,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @undoBatch @action - changeColumns = (oldKey: string, newKey: string, addNew: boolean) => { + changeColumns = (oldKey: string, newKey: string, addNew: boolean, filter?: string) => { const columns = this.columns; if (columns === undefined) { this.columns = new List<SchemaHeaderField>([new SchemaHeaderField(newKey, "f1efeb")]); @@ -325,6 +326,20 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { column.setHeading(newKey); columns[index] = column; this.columns = columns; + if (filter) { + Doc.setDocFilter(this.props.Document, newKey, filter, "match"); + if (this.props.Document.selectedDoc !== undefined) { + const doc = Cast(this.props.Document.selectedDoc, Doc) as Doc; + Doc.setDocFilter(doc, newKey, filter, "match"); + } + } + else { + this.props.Document._docFilters = undefined; + if (this.props.Document.selectedDoc !== undefined) { + const doc = Cast(this.props.Document.selectedDoc, Doc) as Doc; + doc._docFilters = undefined; + } + } } } } @@ -591,6 +606,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } } + + + onKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => { + } render() { TraceMobx(); const menuContent = this.renderMenuContent; @@ -608,14 +627,15 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { {({ measureRef }) => <div ref={measureRef}> {menuContent} </div>} </Measure> </div>; - return <div className="collectionSchemaView-container" style={{ + overflow: this.props.overflow === true ? "auto" : undefined, pointerEvents: !this.props.active() && !SnappingManager.GetIsDragging() ? "none" : undefined, - width: this.props.PanelWidth() || "100%", height: this.props.PanelHeight() || "100%" + width: this.props.PanelWidth() || "100%", height: this.props.PanelHeight() || "100%", position: "relative", }} > <div className="collectionSchemaView-tableContainer" - style={{ width: `calc(100% - ${this.previewWidth()}px)` }} + style={{ backgroundColor: "white", width: `calc(100% - ${this.previewWidth()}px)` }} + onKeyPress={this.onKeyPress} onPointerDown={this.onPointerDown} onWheel={e => this.props.active(true) && e.stopPropagation()} onDrop={e => this.onExternalDrop(e, {})} diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index fbc4e1552..f193a9787 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -369,7 +369,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC </div> {(chromeStatus !== 'view-mode' && chromeStatus !== 'disabled' && type !== DocumentType.PRES) ? <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton" - style={{ width: style.columnWidth / style.numGroupColumns }}> + style={{ width: style.columnWidth / style.numGroupColumns, marginBottom: 70 }}> <EditableView {...newEditableViewProps} menuCallback={this.menuCallback} /> </div> : null} </div> diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 3ebc6baca..4025e25f9 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -1,7 +1,7 @@ import { action, computed, IReactionDisposer, reaction, observable, runInAction } from "mobx"; import { basename } from 'path'; import CursorField from "../../../fields/CursorField"; -import { Doc, Opt, Field } from "../../../fields/Doc"; +import { Doc, Opt, Field, DocListCast } from "../../../fields/Doc"; import { Id } from "../../../fields/FieldSymbols"; import { List } from "../../../fields/List"; import { listSpec } from "../../../fields/Schema"; @@ -112,9 +112,10 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: [...this.props.docFilters(), ...Cast(this.props.Document._docFilters, listSpec("string"), [])]; } @computed get childDocs() { + let rawdocs: (Doc | Promise<Doc>)[] = DocListCast(this.props.Document._searchDocs); - let rawdocs: (Doc | Promise<Doc>)[] = []; - if (this.dataField instanceof Doc) { // if collection data is just a document, then promote it to a singleton list; + if (rawdocs.length !== 0) { + } else if (this.dataField instanceof Doc) { // if collection data is just a document, then promote it to a singleton list; rawdocs = [this.dataField]; } else if (Cast(this.dataField, listSpec(Doc), null)) { // otherwise, if the collection data is a list, then use it. rawdocs = Cast(this.dataField, listSpec(Doc), null); @@ -126,11 +127,66 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: } const docs = rawdocs.filter(d => !(d instanceof Promise)).map(d => d as Doc); + const viewSpecScript = Cast(this.props.Document.viewSpecScript, ScriptField); + let childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs; + + const searchDocs = DocListCast(this.props.Document._searchDocs); + // if (searchDocs !== undefined && searchDocs.length > 0) { + // let newdocs: Doc[] = []; + // childDocs.forEach((el) => { + // searchDocs.includes(el) ? newdocs.push(el) : undefined; + // }); + // childDocs = newdocs; + // } + + let docsforFilter: Doc[] = childDocs; + if (searchDocs !== undefined && searchDocs.length > 0) { + docsforFilter = []; + // let newdocs: Doc[] = []; + // let newarray: Doc[] = []; + //while (childDocs.length > 0) { + //newarray = []; + childDocs.forEach((d) => { + if (d.data !== undefined) { + console.log(d); + let newdocs = DocListCast(d.data); + if (newdocs.length > 0) { + let vibecheck: boolean | undefined = undefined; + let newarray: Doc[] = []; + while (newdocs.length > 0) { + newarray = []; + newdocs.forEach((t) => { + if (d.data !== undefined) { + const newdocs = DocListCast(t.data); + newdocs.forEach((newdoc) => { + newarray.push(newdoc); + }); + } + if (searchDocs.includes(t)) { + vibecheck = true; + } + }); + newdocs = newarray; + } + if (vibecheck === true) { + docsforFilter.push(d); + } + } + } + if (searchDocs.includes(d)) { + docsforFilter.push(d); + } + }); + //childDocs = newarray; + //} + } + childDocs = docsforFilter; + + const docFilters = this.docFilters(); - const viewSpecScript = ScriptCast(this.props.Document.viewSpecScript); const docRangeFilters = this.props.ignoreFields?.includes("_docRangeFilters") ? [] : Cast(this.props.Document._docRangeFilters, listSpec("string"), []); - return this.props.Document.dontRegisterView ? docs : DocUtils.FilterDocs(docs, docFilters, docRangeFilters, viewSpecScript); + return this.props.Document.dontRegisterView ? docs : DocUtils.FilterDocs(docs, this.docFilters(), docRangeFilters, viewSpecScript); } @action @@ -436,4 +492,3 @@ import { CollectionView, CollectionViewType } from "./CollectionView"; import { SelectionManager } from "../../util/SelectionManager"; import { OverlayView } from "../OverlayView"; import { setTimeout } from "timers"; - diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index 50f0534bd..c9bf82406 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -22,7 +22,7 @@ ul { list-style: none; padding-left: 20px; - margin-bottom: 1px;// otherwise vertical scrollbars may pop up for no apparent reason.... + margin-bottom: 1px; // otherwise vertical scrollbars may pop up for no apparent reason.... } @@ -35,7 +35,7 @@ width: 15px; color: $intermediate-color; margin-top: 3px; - transform: scale(1.3, 1.3); + transform: scale(1.3, 1.3); border: #80808030 1px solid; border-radius: 4px; } @@ -67,8 +67,10 @@ margin-left: 3px; display: none; } + .collectionTreeView-keyHeader:hover { background: #797777; + cursor: pointer; } .collectionTreeView-subtitle { @@ -89,8 +91,10 @@ height: 17px; width: 15px; } + .treeViewItem-openRight:hover { background: #797777; + cursor: pointer; } .treeViewItem-border { @@ -106,10 +110,12 @@ .editableView-container-editing-oneLine { min-width: 15px; } + .documentView-node-topmost { width: unset; } - > svg { + + >svg { display: none; } @@ -119,7 +125,8 @@ .collectionTreeView-keyHeader { display: inherit; } - > svg { + + >svg { display: inherit; } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 89034a0c0..6e15cb887 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -74,7 +74,7 @@ export enum CollectionViewType { Pile = "pileup" } export interface CollectionViewCustomProps { - filterAddDocument: (doc: Doc | Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example) + filterAddDocument?: (doc: Doc | Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example) childLayoutTemplate?: () => Opt<Doc>; // specify a layout Doc template to use for children of the collection childLayoutString?: string; // specify a layout string to use for children of the collection childOpacity?: () => number; @@ -88,6 +88,7 @@ export interface CollectionRenderProps { active: () => boolean; whenActiveChanged: (isActive: boolean) => void; PanelWidth: () => number; + PanelHeight: () => number; ChildLayoutTemplate?: () => Doc; ChildLayoutString?: string; } @@ -523,6 +524,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus </div> <div className="collectionTimeView-tree" key="tree"> <CollectionTreeView + PanelPosition={""} Document={facetCollection} DataDoc={facetCollection} fieldKey={`${this.props.fieldKey}-filter`} @@ -574,6 +576,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus active: this.active, whenActiveChanged: this.whenActiveChanged, PanelWidth: this.bodyPanelWidth, + PanelHeight: this.props.PanelHeight, ChildLayoutTemplate: this.childLayoutTemplate, ChildLayoutString: this.childLayoutString, }; @@ -582,7 +585,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus return (<div className={"collectionView"} onContextMenu={this.onContextMenu} style={{ pointerEvents: this.props.Document.isBackground ? "none" : undefined, boxShadow }}> {this.showIsTagged()} - <div className="collectionView-facetCont" style={{ width: `calc(100% - ${this.facetWidth()}px)` }}> + <div className="collectionView-facetCont" style={{ display: this.props.PanelPosition === "absolute" ? "flex" : "", justifyContent: this.props.PanelPosition === "absolute" ? "center" : "", width: `calc(100% - ${this.facetWidth()}px)` }}> {this.collectionViewType !== undefined ? this.SubView(this.collectionViewType, props) : (null)} </div> {this.lightbox(DocListCast(this.props.Document[this.props.fieldKey]).filter(d => d.type === DocumentType.IMG).map(d => diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx index 7e2840c2c..75d484cbe 100644 --- a/src/client/views/collections/SchemaTable.tsx +++ b/src/client/views/collections/SchemaTable.tsx @@ -11,22 +11,22 @@ import { List } from "../../../fields/List"; import { listSpec } from "../../../fields/Schema"; import { SchemaHeaderField } from "../../../fields/SchemaHeaderField"; import { ComputedField } from "../../../fields/ScriptField"; -import { Cast, FieldValue, NumCast, StrCast, BoolCast } from "../../../fields/Types"; +import { Cast, FieldValue, NumCast, StrCast } from "../../../fields/Types"; +import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero } from "../../../Utils"; import { Docs, DocumentOptions } from "../../documents/Documents"; +import { DocumentType } from "../../documents/DocumentTypes"; import { CompileScript, Transformer, ts } from "../../util/Scripting"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; import { COLLECTION_BORDER_WIDTH } from '../../views/globalCssVariables.scss'; import { ContextMenu } from "../ContextMenu"; import '../DocumentDecorations.scss'; -import { CellProps, CollectionSchemaCell, CollectionSchemaCheckboxCell, CollectionSchemaDocCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaImageCell, CollectionSchemaListCell, CollectionSchemaDateCell } from "./CollectionSchemaCells"; +import { ContentFittingDocumentView } from "../nodes/ContentFittingDocumentView"; +import { CellProps, CollectionSchemaButtons, CollectionSchemaCell, CollectionSchemaCheckboxCell, CollectionSchemaDateCell, CollectionSchemaDocCell, CollectionSchemaImageCell, CollectionSchemaListCell, CollectionSchemaNumberCell, CollectionSchemaStringCell } from "./CollectionSchemaCells"; import { CollectionSchemaAddColumnHeader, KeysDropdown } from "./CollectionSchemaHeaders"; import { MovableColumn, MovableRow } from "./CollectionSchemaMovableTableHOC"; import "./CollectionSchemaView.scss"; import { CollectionView } from "./CollectionView"; -import { ContentFittingDocumentView } from "../nodes/ContentFittingDocumentView"; -import { emptyFunction, returnZero, returnOne, returnFalse, returnEmptyFilter, emptyPath } from "../../../Utils"; -import { TouchScrollableMenuItem } from "../TouchScrollableMenu"; enum ColumnType { @@ -128,7 +128,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { } @computed get sorted(): SortingRule[] { return this.props.columns.reduce((sorted, shf) => { - shf.desc && sorted.push({ id: shf.heading, desc: shf.desc }); + shf.desc !== undefined && sorted.push({ id: shf.heading, desc: shf.desc }); return sorted; }, [] as SortingRule[]); } @@ -160,7 +160,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { const focusedCol = this._focusedCell.col; const isEditable = !this.props.headerIsEditing; - if (this.childDocs.reduce((found, doc) => found || doc.type === "collection", false)) { + if (this.childDocs.reduce((found, doc) => found || doc.type === DocumentType.COL, false)) { columns.push( { expander: true, @@ -177,6 +177,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { } ); } + console.log(columns); const cols = this.props.columns.map(col => { @@ -188,7 +189,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { addNew={false} onSelect={this.props.changeColumns} setIsEditing={this.props.setHeaderIsEditing} - + docs={this.props.childDocs} // try commenting this out width={"100%"} />; @@ -216,21 +217,21 @@ export class SchemaTable extends React.Component<SchemaTableProps> { className="collectionSchemaView-menuOptions-wrapper" style={{ background: col.color, padding: "2px", - display: "flex" + display: "flex", cursor: "default", height: "100%", }}> - <FontAwesomeIcon icon={icon} size="lg" style={{ display: "inline", paddingLeft: "7px" }} /> - <div className="keys-dropdown" - style={{ display: "inline", zIndex: 1000 }}> - {keysDropdown} - </div> + <FontAwesomeIcon icon={icon} size="lg" style={{ display: "inline", paddingBottom: "1px", paddingTop: "4px" }} /> + {/* <div className="keys-dropdown" + style={{ display: "inline", zIndex: 1000 }}> */} + {keysDropdown} + {/* </div> */} <div onClick={e => this.changeSorting(col)} - style={{ paddingRight: "6px", marginLeft: "4px", display: "inline" }}> - <FontAwesomeIcon icon={sortIcon} size="sm" /> - </div> - <div onClick={e => this.props.openHeader(col, e.clientX, e.clientY)} - style={{ float: "right", paddingRight: "6px" }}> - <FontAwesomeIcon icon={"cog"} size="sm" /> + style={{ width: 21, padding: 1, display: "inline", zIndex: 1, background: "inherit" }}> + <FontAwesomeIcon icon={sortIcon} size="lg" /> </div> + {/* <div onClick={e => this.props.openHeader(col, e.clientX, e.clientY)} + style={{ float: "right", paddingRight: "6px", zIndex: 1, background: "inherit" }}> + <FontAwesomeIcon icon={"compass"} size="sm" /> + </div> */} </div>; return { @@ -283,13 +284,63 @@ export class SchemaTable extends React.Component<SchemaTableProps> { Header: <CollectionSchemaAddColumnHeader createColumn={this.createColumn} />, accessor: (doc: Doc) => 0, id: "add", - Cell: (rowProps: CellInfo) => <></>, + Cell: (rowProps: CellInfo) => { + const rowIndex = rowProps.index; + const columnIndex = this.props.columns.map(c => c.heading).indexOf(rowProps.column.id!); + const isFocused = focusedRow === rowIndex && focusedCol === columnIndex && tableIsFocused; + const props: CellProps = { + row: rowIndex, + col: columnIndex, + rowProps: rowProps, + isFocused: isFocused, + changeFocusedCellByIndex: this.changeFocusedCellByIndex, + CollectionView: this.props.CollectionView, + ContainingCollection: this.props.ContainingCollectionView, + Document: this.props.Document, + fieldKey: this.props.fieldKey, + renderDepth: this.props.renderDepth, + addDocTab: this.props.addDocTab, + pinToPres: this.props.pinToPres, + moveDocument: this.props.moveDocument, + setIsEditing: this.setCellIsEditing, + isEditable: isEditable, + setPreviewDoc: this.props.setPreviewDoc, + setComputed: this.setComputed, + getField: this.getField, + showDoc: this.showDoc, + }; + + return <CollectionSchemaButtons {...props} />; + }, width: 28, resizable: false }); + console.log(columns); return columns; } + + + @action + nextHighlight = (e: React.MouseEvent, doc: Doc) => { + e.preventDefault(); + e.stopPropagation(); + doc.searchMatch = false; + console.log(doc.searchMatch); + setTimeout(() => doc.searchMatch = true, 0); + console.log(doc.searchMatch); + + doc.searchIndex = NumCast(doc.searchIndex); + } + + @action + nextHighlight2 = (doc: Doc) => { + + doc.searchMatchAlt = false; + setTimeout(() => doc.searchMatchAlt = true, 0); + doc.searchIndex = NumCast(doc.searchIndex); + } + constructor(props: SchemaTableProps) { super(props); // convert old schema columns (list of strings) into new schema columns (list of schema header fields) @@ -574,7 +625,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> { return <div className="collectionSchemaView-table" onPointerDown={this.props.onPointerDown} onWheel={e => this.props.active(true) && e.stopPropagation()} onDrop={e => this.props.onDrop(e, {})} onContextMenu={this.onContextMenu} > {this.reactTable} - <div className="collectionSchemaView-addRow" onClick={() => this.createRow()}>+ new</div> + {StrCast(this.props.Document.type) !== "search" ? <div className="collectionSchemaView-addRow" onClick={() => this.createRow()}>+ new</div> + : undefined} {!this._showDoc ? (null) : <div className="collectionSchemaView-documentPreview" //onClick={() => { this.onOpenClick(); }} style={{ diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 65cd28742..f2ad0ba58 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1258,7 +1258,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P this.props.ContainingCollectionView && optionItems.push({ description: "Promote Collection", event: this.promoteCollection, icon: "table" }); optionItems.push({ description: this.layoutDoc._lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: this.layoutDoc._lockedTransform ? "unlock" : "lock" }); - appearanceItems.push({ description: "Use Background Color as Default", event: () => Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor), icon: "palette" }); + optionItems.push({ description: "Use Background Color as Default", event: () => Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor), icon: "palette" }); if (!Doc.UserDoc().noviceMode) { optionItems.push({ description: (!this.layoutDoc._nativeWidth || !this.layoutDoc._nativeHeight ? "Freeze" : "Unfreeze") + " Aspect", event: this.toggleNativeDimensions, icon: "snowflake" }); optionItems.push({ description: `${this.Document._freeformLOD ? "Enable LOD" : "Disable LOD"}`, event: () => this.Document._freeformLOD = !this.Document._freeformLOD, icon: "table" }); diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss index 89124129b..5b41db90e 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss @@ -41,7 +41,7 @@ font-size: 12.5px; &:hover { - cursor: pointer; + cursor: text; } } @@ -617,6 +617,7 @@ display: flex; margin-bottom: 3px; + margin-left: 4px; .arrows-head { @@ -650,7 +651,7 @@ .dashed { display: flex; - margin-left: 74px; + margin-left: 64px; margin-bottom: 6px; .dashed-title { @@ -662,4 +663,15 @@ margin-top: 2px; } } +} + +.editable-title { + border: none; + padding: 6px; + padding-bottom: 2px; + + + &:hover { + border: 0.75px solid rgb(122, 28, 28); + } }
\ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index dcbf8e989..89f48fc65 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -29,6 +29,9 @@ import "./FormatShapePane.scss"; import { discovery_v1 } from "googleapis"; import { PresBox } from "../../nodes/PresBox"; import { DocumentManager } from "../../../util/DocumentManager"; +const higflyout = require("@hig/flyout"); +export const { anchorPoints } = higflyout; +export const Flyout = higflyout.default; interface PropertiesViewProps { @@ -74,6 +77,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @observable openPresProgressivize: boolean = true; @observable openSlideOptions: boolean = true; + @observable inActions: boolean = false; @observable _controlBtn: boolean = false; @observable _lock: boolean = false; @@ -174,7 +178,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)); const rows: JSX.Element[] = []; for (const key of Object.keys(ids).slice().sort()) { - if ((key[0] === key[0].toUpperCase() && key.substring(0, 3) !== "ACL") + if ((key[0] === key[0].toUpperCase() && key.substring(0, 3) !== "ACL" && key !== "UseCors") || key[0] === "#" || key === "author" || key === "creationDate" || key.indexOf("lastModified") !== -1) { @@ -254,7 +258,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { rootSelected={returnFalse} treeViewDoc={undefined} backgroundColor={() => "lightgrey"} - fitToBox={false} + fitToBox={true} FreezeDimensions={true} NativeWidth={layoutDoc.type === StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : returnZero} @@ -277,6 +281,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { bringToFront={returnFalse} ContentScaling={returnOne} dontRegisterView={true} + dropAction={undefined} /> </div>; } else { @@ -367,20 +372,19 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { />; } - @undoBatch @action toggleCheckbox = () => { this.layoutFields = !this.layoutFields; } @computed get editableTitle() { - return <EditableView + return <div className="editable-title"><EditableView key="editableView" contents={StrCast(this.selectedDoc?.title)} height={25} fontSize={14} GetValue={() => StrCast(this.selectedDoc?.title)} - SetValue={this.setTitle} />; + SetValue={this.setTitle} /> </div>; } @undoBatch @@ -417,15 +421,14 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { var index = 0; if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) { doc.rotation = Number(doc.rotation) + Number(angle); - const ink = Cast(doc.data, InkField)?.inkData; - if (ink) { - + const inks = Cast(doc.data, InkField)?.inkData; + if (inks) { const newPoints: { X: number, Y: number }[] = []; - for (var i = 0; i < ink.length; i++) { - const newX = Math.cos(angle) * (ink[i].X - _centerPoints[index].X) - Math.sin(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].X; - const newY = Math.sin(angle) * (ink[i].X - _centerPoints[index].X) + Math.cos(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].Y; + inks.forEach(ink => { + const newX = Math.cos(angle) * (ink.X - _centerPoints[index].X) - Math.sin(angle) * (ink.Y - _centerPoints[index].Y) + _centerPoints[index].X; + const newY = Math.sin(angle) * (ink.X - _centerPoints[index].X) + Math.cos(angle) * (ink.Y - _centerPoints[index].Y) + _centerPoints[index].Y; newPoints.push({ X: newX, Y: newY }); - } + }); doc.data = new InkField(newPoints); const xs = newPoints.map(p => p.X); const ys = newPoints.map(p => p.Y); @@ -552,7 +555,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { getField(key: string) { //if (this.selectedDoc) { - return Field.toString(this?.[key] as Field); + return Field.toString(this.selectedDoc?.[key] as Field); // } else { // return undefined as Opt<string>; // } @@ -594,14 +597,18 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { set colorFil(value) { value && (this._lastFill = value); this.selectedDoc && (this.selectedDoc.fillColor = value ? value : undefined); } set colorStk(value) { value && (this._lastLine = value); this.selectedDoc && (this.selectedDoc.color = value ? value : undefined); } - colorButton(value: string, setter: () => {}) { - return <div className="color-button" key="color" onPointerDown={undoBatch(action(e => setter()))}> - <div className="color-button-preview" style={{ - backgroundColor: value ?? "121212", width: 15, height: 15, - display: value === "" || value === "transparent" ? "none" : "" - }} /> - {value === "" || value === "transparent" ? <p style={{ fontSize: 25, color: "red", marginTop: -14, position: "fixed" }}>☒</p> : ""} - </div>; + colorButton(value: string, type: string, setter: () => {}) { + return <Flyout anchorPoint={anchorPoints.LEFT_TOP} + content={type === "fill" ? this.fillPicker : this.linePicker}> + <div className="color-button" key="color" onPointerDown={undoBatch(action(e => setter()))}> + <div className="color-button-preview" style={{ + backgroundColor: value ?? "121212", width: 15, height: 15, + display: value === "" || value === "transparent" ? "none" : "" + }} /> + {value === "" || value === "transparent" ? <p style={{ fontSize: 25, color: "red", marginTop: -14, position: "fixed" }}>☒</p> : ""} + </div> + </Flyout>; + } @undoBatch @@ -627,8 +634,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { color={type === "stk" ? this.colorStk : this.colorFil} />; } - @computed get fillButton() { return this.colorButton(this.colorFil, () => { this._fillBtn = !this._fillBtn; this._lineBtn = false; return true; }); } - @computed get lineButton() { return this.colorButton(this.colorStk, () => { this._lineBtn = !this._lineBtn; this._fillBtn = false; return true; }); } + @computed get fillButton() { return this.colorButton(this.colorFil, "fill", () => { this._fillBtn = !this._fillBtn; this._lineBtn = false; return true; }); } + @computed get lineButton() { return this.colorButton(this.colorStk, "line", () => { this._lineBtn = !this._lineBtn; this._fillBtn = false; return true; }); } @computed get fillPicker() { return this.colorPicker((color: string) => this.colorFil = color, "fil"); } @computed get linePicker() { return this.colorPicker((color: string) => this.colorStk = color, "stk"); } @@ -645,8 +652,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div className="stroke-button">{this.lineButton}</div> </div> </div> - {this._fillBtn ? this.fillPicker : ""} - {this._lineBtn ? this.linePicker : ""} + {/* {this._fillBtn ? this.fillPicker : ""} + {this._lineBtn ? this.linePicker : ""} */} </div>; } @@ -753,201 +760,203 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return <div className="propertiesView" style={{ width: this.props.width }}> <div className="propertiesView-title" style={{ width: this.props.width }}> No Document Selected - <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}> - <FontAwesomeIcon icon="times" color="black" size="xs" /> - </div> </div> </div>; - } - const novice = Doc.UserDoc().noviceMode; - - if (this.selectedDoc && !this.isPres) { - return <div className="propertiesView" style={{ width: this.props.width }} > - <div className="propertiesView-title" style={{ width: this.props.width }}> - Properties - <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}> + } else { + const novice = Doc.UserDoc().noviceMode; + + if (this.selectedDoc && !this.isPres) { + return <div className="propertiesView" style={{ + width: this.props.width, + // overflowY: this.inActions ? "visible" : "scroll" + }} > + <div className="propertiesView-title" style={{ width: this.props.width }}> + Properties + {/* <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}> <FontAwesomeIcon icon="times" color="black" size="sm" /> + </div> */} </div> - </div> - <div className="propertiesView-name"> - {this.editableTitle} - </div> - <div className="propertiesView-settings"> - <div className="propertiesView-settings-title" - onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })} - style={{ backgroundColor: this.openActions ? "black" : "" }}> - Actions - <div className="propertiesView-settings-title-icon"> - <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" /> + <div className="propertiesView-name"> + {this.editableTitle} + </div> + <div className="propertiesView-settings" onPointerEnter={() => runInAction(() => { this.inActions = true; })} + onPointerLeave={action(() => this.inActions = false)}> + <div className="propertiesView-settings-title" + onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })} + style={{ backgroundColor: this.openActions ? "black" : "" }}> + Actions + <div className="propertiesView-settings-title-icon"> + <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> + {!this.openActions ? (null) : + <div className="propertiesView-settings-content"> + <PropertiesButtons /> + </div>} </div> - {!this.openActions ? (null) : - <div className="propertiesView-settings-content"> - <PropertiesButtons /> - </div>} - </div> - <div className="propertiesView-sharing"> - <div className="propertiesView-sharing-title" - onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })} - style={{ backgroundColor: this.openSharing ? "black" : "" }}> - Sharing {"&"} Permissions - <div className="propertiesView-sharing-title-icon"> - <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" /> + <div className="propertiesView-sharing"> + <div className="propertiesView-sharing-title" + onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })} + style={{ backgroundColor: this.openSharing ? "black" : "" }}> + Sharing {"&"} Permissions + <div className="propertiesView-sharing-title-icon"> + <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> + {!this.openSharing ? (null) : + <div className="propertiesView-sharing-content"> + {this.sharingTable} + </div>} </div> - {!this.openSharing ? (null) : - <div className="propertiesView-sharing-content"> - {this.sharingTable} + + {!this.isInk ? (null) : + <div className="propertiesView-appearance"> + <div className="propertiesView-appearance-title" + onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })} + style={{ backgroundColor: this.openAppearance ? "black" : "" }}> + Appearance + <div className="propertiesView-appearance-title-icon"> + <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> + </div> + {!this.openAppearance ? (null) : + <div className="propertiesView-appearance-content"> + {this.appearanceEditor} + </div>} </div>} - </div> - {!this.isInk ? (null) : - <div className="propertiesView-appearance"> - <div className="propertiesView-appearance-title" - onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })} - style={{ backgroundColor: this.openAppearance ? "black" : "" }}> - Appearance - <div className="propertiesView-appearance-title-icon"> - <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" /> + {this.isInk ? <div className="propertiesView-transform"> + <div className="propertiesView-transform-title" + onPointerDown={() => runInAction(() => { this.openTransform = !this.openTransform; })} + style={{ backgroundColor: this.openTransform ? "black" : "" }}> + Transform + <div className="propertiesView-transform-title-icon"> + <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" /> </div> </div> - {!this.openAppearance ? (null) : - <div className="propertiesView-appearance-content"> - {this.appearanceEditor} - </div>} - </div>} - - {this.isInk ? <div className="propertiesView-transform"> - <div className="propertiesView-transform-title" - onPointerDown={() => runInAction(() => { this.openTransform = !this.openTransform; })} - style={{ backgroundColor: this.openTransform ? "black" : "" }}> - Transform - <div className="propertiesView-transform-title-icon"> - <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" /> - </div> - </div> - {this.openTransform ? <div className="propertiesView-transform-content"> - {this.transformEditor} + {this.openTransform ? <div className="propertiesView-transform-content"> + {this.transformEditor} + </div> : null} </div> : null} - </div> : null} - - <div className="propertiesView-fields"> - <div className="propertiesView-fields-title" - onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })} - style={{ backgroundColor: this.openFields ? "black" : "" }}> - <div className="propertiesView-fields-title-name"> - Fields {"&"} Tags - <div className="propertiesView-fields-title-icon"> - <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" /> + + <div className="propertiesView-fields"> + <div className="propertiesView-fields-title" + onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })} + style={{ backgroundColor: this.openFields ? "black" : "" }}> + <div className="propertiesView-fields-title-name"> + Fields {"&"} Tags + <div className="propertiesView-fields-title-icon"> + <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> </div> + {!novice && this.openFields ? <div className="propertiesView-fields-checkbox"> + {this.fieldsCheckbox} + <div className="propertiesView-fields-checkbox-text">Layout</div> + </div> : null} + {!this.openFields ? (null) : + <div className="propertiesView-fields-content"> + {novice ? this.noviceFields : this.expandedField} + </div>} </div> - {!novice && this.openFields ? <div className="propertiesView-fields-checkbox"> - {this.fieldsCheckbox} - <div className="propertiesView-fields-checkbox-text">Layout</div> - </div> : null} - {!this.openFields ? (null) : - <div className="propertiesView-fields-content"> - {novice ? this.noviceFields : this.expandedField} - </div>} - </div> - <div className="propertiesView-layout"> - <div className="propertiesView-layout-title" - onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })} - style={{ backgroundColor: this.openLayout ? "black" : "" }}> - Layout - <div className="propertiesView-layout-title-icon" onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}> - <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" /> + <div className="propertiesView-layout"> + <div className="propertiesView-layout-title" + onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })} + style={{ backgroundColor: this.openLayout ? "black" : "" }}> + Layout + <div className="propertiesView-layout-title-icon" onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}> + <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> + {this.openLayout ? <div className="propertiesView-layout-content">{this.layoutPreview}</div> : null} </div> - {this.openLayout ? <div className="propertiesView-layout-content">{this.layoutPreview}</div> : null} - </div> - </div>; - } - if (this.isPres) { - return <div className="propertiesView" style={{ width: this.props.width }} > - <div className="propertiesView-title" style={{ width: this.props.width }}> - Presentation - <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}> - <FontAwesomeIcon icon="times" color="black" size="sm" /> + </div>; + } + if (this.isPres) { + return <div className="propertiesView" style={{ width: this.props.width }} > + <div className="propertiesView-title" style={{ width: this.props.width }}> + Presentation + <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}> + <FontAwesomeIcon icon="times" color="black" size="sm" /> + </div> </div> - </div> - <div className="propertiesView-name"> - {this.editableTitle} - <div className="propertiesView-presSelected"> - {PresBox.Instance._selectedArray.length} selected - <div className="propertiesView-selectedList"> - {PresBox.Instance.listOfSelected} + <div className="propertiesView-name"> + {this.editableTitle} + <div className="propertiesView-presSelected"> + {PresBox.Instance._selectedArray.length} selected + <div className="propertiesView-selectedList"> + {PresBox.Instance.listOfSelected} + </div> </div> </div> - </div> - <div className="propertiesView-settings"> - <div className="propertiesView-settings-title" - onPointerDown={() => runInAction(() => { this.openAddSlide = !this.openAddSlide; })} - style={{ backgroundColor: this.openAddSlide ? "black" : "" }}> - <FontAwesomeIcon icon={"plus"} /> Add new slide - <div className="propertiesView-settings-title-icon"> - <FontAwesomeIcon icon={this.openAddSlide ? "caret-down" : "caret-right"} size="lg" color="white" /> + <div className="propertiesView-settings"> + <div className="propertiesView-settings-title" + onPointerDown={() => runInAction(() => { this.openAddSlide = !this.openAddSlide; })} + style={{ backgroundColor: this.openAddSlide ? "black" : "" }}> + <FontAwesomeIcon icon={"plus"} /> Add new slide + <div className="propertiesView-settings-title-icon"> + <FontAwesomeIcon icon={this.openAddSlide ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> + {this.openAddSlide ? <div className="propertiesView-settings-content"> + {PresBox.Instance.newDocumentDropdown} + </div> : null} </div> - {this.openAddSlide ? <div className="propertiesView-settings-content"> - {PresBox.Instance.newDocumentDropdown} - </div> : null} - </div> - <div className="propertiesView-sharing"> - <div className="propertiesView-sharing-title" - onPointerDown={() => runInAction(() => { this.openPresTransitions = !this.openPresTransitions; })} - style={{ backgroundColor: this.openPresTransitions ? "black" : "" }}> - <FontAwesomeIcon icon={"rocket"} /> Transitions - <div className="propertiesView-sharing-title-icon"> - <FontAwesomeIcon icon={this.openPresTransitions ? "caret-down" : "caret-right"} size="lg" color="white" /> + <div className="propertiesView-sharing"> + <div className="propertiesView-sharing-title" + onPointerDown={() => runInAction(() => { this.openPresTransitions = !this.openPresTransitions; })} + style={{ backgroundColor: this.openPresTransitions ? "black" : "" }}> + <FontAwesomeIcon icon={"rocket"} /> Transitions + <div className="propertiesView-sharing-title-icon"> + <FontAwesomeIcon icon={this.openPresTransitions ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> + {this.openPresTransitions ? <div className="propertiesView-sharing-content"> + {PresBox.Instance.transitionDropdown} + </div> : null} </div> - {this.openPresTransitions ? <div className="propertiesView-sharing-content"> - {PresBox.Instance.transitionDropdown} - </div> : null} - </div> - <div className="propertiesView-sharing"> - <div className="propertiesView-sharing-title" - onPointerDown={() => runInAction(() => { this.openPresProgressivize = !this.openPresProgressivize; })} - style={{ backgroundColor: this.openPresProgressivize ? "black" : "" }}> - <FontAwesomeIcon icon={"tasks"} /> Progressivize - <div className="propertiesView-sharing-title-icon"> - <FontAwesomeIcon icon={this.openPresProgressivize ? "caret-down" : "caret-right"} size="lg" color="white" /> + <div className="propertiesView-sharing"> + <div className="propertiesView-sharing-title" + onPointerDown={() => runInAction(() => { this.openPresProgressivize = !this.openPresProgressivize; })} + style={{ backgroundColor: this.openPresProgressivize ? "black" : "" }}> + <FontAwesomeIcon icon={"tasks"} /> Progressivize + <div className="propertiesView-sharing-title-icon"> + <FontAwesomeIcon icon={this.openPresProgressivize ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> + {this.openPresProgressivize ? <div className="propertiesView-sharing-content"> + {PresBox.Instance.progressivizeDropdown} + </div> : null} </div> - {this.openPresProgressivize ? <div className="propertiesView-sharing-content"> - {PresBox.Instance.progressivizeDropdown} - </div> : null} - </div> - <div className="propertiesView-sharing"> - <div className="propertiesView-sharing-title" - onPointerDown={() => runInAction(() => { this.openSlideOptions = !this.openSlideOptions; })} - style={{ backgroundColor: this.openSlideOptions ? "black" : "" }}> - <FontAwesomeIcon icon={"cog"} /> {PresBox.Instance.stringType} options - <div className="propertiesView-sharing-title-icon"> - <FontAwesomeIcon icon={this.openSlideOptions ? "caret-down" : "caret-right"} size="lg" color="white" /> + <div className="propertiesView-sharing"> + <div className="propertiesView-sharing-title" + onPointerDown={() => runInAction(() => { this.openSlideOptions = !this.openSlideOptions; })} + style={{ backgroundColor: this.openSlideOptions ? "black" : "" }}> + <FontAwesomeIcon icon={"cog"} /> {PresBox.Instance.stringType} options + <div className="propertiesView-sharing-title-icon"> + <FontAwesomeIcon icon={this.openSlideOptions ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> + {this.openSlideOptions ? <div className="propertiesView-sharing-content"> + {PresBox.Instance.optionsDropdown} + </div> : null} </div> - {this.openSlideOptions ? <div className="propertiesView-sharing-content"> - {PresBox.Instance.optionsDropdown} - </div> : null} - </div> - <div className="propertiesView-sharing"> - <div className="propertiesView-sharing-title" - onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })} - style={{ backgroundColor: this.openSharing ? "black" : "" }}> - Sharing {"&"} Permissions - <div className="propertiesView-sharing-title-icon"> - <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" /> + <div className="propertiesView-sharing"> + <div className="propertiesView-sharing-title" + onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })} + style={{ backgroundColor: this.openSharing ? "black" : "" }}> + Sharing {"&"} Permissions + <div className="propertiesView-sharing-title-icon"> + <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> + {this.openSharing ? <div className="propertiesView-sharing-content"> + {this.sharingTable} + </div> : null} </div> - {this.openSharing ? <div className="propertiesView-sharing-content"> - {this.sharingTable} - </div> : null} - </div> - </div>; + </div>; + } } } }
\ No newline at end of file diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index 21f77e47b..e6ac7021a 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -240,7 +240,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { w: Math.min(w, this.numCols), // reduces width if greater than numCols static: BoolCast(this.childLayoutPairs.find(({ layout }) => layout[Id] === i)?.layout.lockedPosition, false) // checks if the lock position item has been selected in the context menu })) : - this.savedLayoutList.map((layout, index) => Object.assign(layout, this.unflexedPosition(index))); + this.savedLayoutList.map((layout, index) => { Object.assign(layout, this.unflexedPosition(index)); return layout; }); } /** |
