diff options
Diffstat (limited to 'src/client/views/collections/CollectionSchemaView.tsx')
-rw-r--r-- | src/client/views/collections/CollectionSchemaView.tsx | 138 |
1 files changed, 62 insertions, 76 deletions
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index a003de0d3..257099783 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -7,11 +7,11 @@ 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 { Doc, Opt } from "../../../fields/Doc"; import { List } from "../../../fields/List"; import { listSpec } from "../../../fields/Schema"; import { PastelSchemaPalette, SchemaHeaderField } from "../../../fields/SchemaHeaderField"; -import { Cast, NumCast } from "../../../fields/Types"; +import { Cast, NumCast, BoolCast } from "../../../fields/Types"; import { TraceMobx } from "../../../fields/util"; import { emptyFunction, returnFalse, returnOne, returnZero, setupMoveUpEvents } from "../../../Utils"; import { SnappingManager } from "../../util/SnappingManager"; @@ -20,10 +20,12 @@ 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 { SchemaTable } from "./SchemaTable"; +import { SelectionManager } from "../../util/SelectionManager"; +import { ContextMenu } from "../ContextMenu"; +import { ContextMenuProps } from "../ContextMenuItem"; library.add(faCog, faPlus, faSortUp, faSortDown); library.add(faTable); @@ -62,8 +64,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @observable _menuWidth = 0; @observable _headerOpen = false; - @observable _isOpen = false; - @observable _node: HTMLDivElement | null = null; @observable _headerIsEditing = false; @observable _col: any = ""; @observable _menuHeight = 0; @@ -71,12 +71,22 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @observable _pointerY = 0; @observable _openTypes: boolean = false; @computed get menuCoordinates() { - const x = Math.max(0, Math.min(document.body.clientWidth - this._menuWidth, this._pointerX)); - const y = Math.max(0, Math.min(document.body.clientHeight - this._menuHeight, this._pointerY)); + let searchx = 0; + let searchy = 0; + if (this.props.Document._searchDoc !== undefined) { + const el = document.getElementsByClassName("collectionSchemaView-searchContainer")[0]; + if (el !== undefined) { + const rect = el.getBoundingClientRect(); + searchx = rect.x; + searchy = rect.y; + } + } + const x = Math.max(0, Math.min(document.body.clientWidth - this._menuWidth, this._pointerX)) - searchx; + const y = Math.max(0, Math.min(document.body.clientHeight - this._menuHeight, this._pointerY)) - searchy; return this.props.ScreenToLocalTransform().transformPoint(x, y); } - @observable scale = this.props.ScreenToLocalTransform().Scale; + @computed get scale() { return this.props.ScreenToLocalTransform().Scale; } @computed get columns() { return Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []); @@ -101,31 +111,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } @computed get possibleKeys() { return this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.heading.toUpperCase() === key.toUpperCase()) === -1); } - - componentDidMount() { - document.addEventListener("pointerdown", this.detectClick); - } - - componentWillUnmount() { - document.removeEventListener("pointerdown", this.detectClick); - } - @action setHeaderIsEditing = (isEditing: boolean) => this._headerIsEditing = isEditing; - detectClick = (e: PointerEvent): void => { - if (this._node && this._node.contains(e.target as Node)) { - } else { - this._isOpen = false; - this.setHeaderIsEditing(false); - this.closeHeader(); - } - } - - @action - toggleIsOpen = (): void => { - this._isOpen = !this._isOpen; - this.setHeaderIsEditing(this._isOpen); - } @action changeColumnType = (type: ColumnType, col: any): void => { @@ -178,16 +165,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { this.columns = columns; } - @action - setNode = (node: HTMLDivElement): void => { - node && (this._node = node); - } - - @action - typesDropdownChange = (bool: boolean) => { - this._openTypes = bool; - } - renderTypes = (col: any) => { if (columnTypes.get(col.heading)) return (null); @@ -251,10 +228,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { type === ColumnType.Date ? dateType : imageType; return ( - <div className="collectionSchema-headerMenu-group"> - <div onClick={() => this.typesDropdownChange(!this._openTypes)}> - <label>Column type:</label> - <FontAwesomeIcon icon={"caret-down"} size="lg" style={{ float: "right" }} /> + <div className="collectionSchema-headerMenu-group" onClick={action(() => this._openTypes = !this._openTypes)}> + <div> + <label style={{ cursor: "pointer" }}>Column type:</label> + <FontAwesomeIcon icon={"caret-down"} size="lg" style={{ float: "right", transform: `rotate(${this._openTypes ? "180deg" : 0})`, transition: "0.2s all ease" }} /> </div> {this._openTypes ? allColumnTypes : justColType} </div > @@ -336,7 +313,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { else { this.props.Document._docFilters = undefined; if (this.props.Document.selectedDoc !== undefined) { - const doc = Cast(this.props.Document.selectedDoc, Doc) as Doc; + const doc = Cast(this.props.Document.selectedDoc, Doc, null); doc._docFilters = undefined; } } @@ -348,7 +325,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action openHeader = (col: any, screenx: number, screeny: number) => { this._col = col; - this._headerOpen = !this._headerOpen; + this._headerOpen = true; this._pointerX = screenx; this._pointerY = screeny; } @@ -356,17 +333,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action closeHeader = () => { this._headerOpen = false; } - renderKeysDropDown = (col: any) => { - return <KeysDropdown - keyValue={col.heading} - possibleKeys={this.possibleKeys} - existingKeys={this.columns.map(c => c.heading)} - canAddNew={true} - addNew={false} - onSelect={this.changeColumns} - setIsEditing={this.setHeaderIsEditing} - />; - } + @undoBatch @action @@ -390,7 +357,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action onHeaderClick = (e: React.PointerEvent) => { - this.props.active(true); e.stopPropagation(); } @@ -405,12 +371,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get renderMenuContent() { TraceMobx(); return <div className="collectionSchema-header-menuOptions"> - <div className="collectionSchema-headerMenu-group"> - <label>Key:</label> - {this.renderKeysDropDown(this._col)} - </div> {this.renderTypes(this._col)} - {this.renderSorting(this._col)} + {/* {this.renderSorting(this._col)} */} {this.renderColors(this._col)} <div className="collectionSchema-headerMenu-group"> <button onClick={() => { this.deleteColumn(this._col.heading); }} @@ -424,11 +386,14 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { super.CreateDropTarget(ele); } - isFocused = (doc: Doc): boolean => this.props.isSelected() && doc === this._focusedTable; + isFocused = (doc: Doc, outsideReaction: boolean): boolean => this.props.isSelected(outsideReaction) && doc === this._focusedTable; @action setFocused = (doc: Doc) => this._focusedTable = doc; - @action setPreviewDoc = (doc: Doc) => this.previewDoc = doc; + @action setPreviewDoc = (doc: Opt<Doc>) => { + SelectionManager.SelectSchemaDoc(this, doc); + this.previewDoc = doc; + } //toggles preview side-panel of schema @action @@ -533,6 +498,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { documentKeys={this.documentKeys} headerIsEditing={this._headerIsEditing} openHeader={this.openHeader} + onClick={e => { e.stopPropagation(); this.closeHeader(); }} onPointerDown={this.onTablePointerDown} onResizedChange={this.onResizedChange} setColumns={this.setColumns} @@ -554,15 +520,29 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { </div> </div>; } + onSpecificMenu = (e: React.MouseEvent) => { + if ((e.target as any)?.className?.includes?.("collectionSchemaView-cell") || (e.target instanceof HTMLSpanElement)) { + const cm = ContextMenu.Instance; + const options = cm.findByDescription("Options..."); + const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : []; + optionItems.push({ description: "remove", event: () => this.previewDoc && this.props.removeDocument(this.previewDoc), icon: "trash" }); + !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" }); + cm.displayMenu(e.clientX, e.clientY); + (e.nativeEvent as any).SchemaHandled = true; // not sure why this is needed, but if you right-click quickly on a cell, the Document/Collection contextMenu handlers still fire without this. + e.stopPropagation(); + } + } @action onTablePointerDown = (e: React.PointerEvent): void => { + if (!(e.target as any)?.className?.includes?.("collectionSchemaView-cell") && !(e.target instanceof HTMLSpanElement)) { + this.setPreviewDoc(undefined); + } this.setFocused(this.props.Document); if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey && this.props.isSelected(true)) { e.stopPropagation(); } - this._pointerY = e.screenY; - this._pointerX = e.screenX; + // this.closeHeader(); } onResizedChange = (newResized: Resize[], event: any) => { @@ -611,14 +591,19 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { onKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => { } render() { + let name = "collectionSchemaView-container"; + if (this.props.Document._searchDoc !== undefined) { + name = "collectionSchemaView-searchContainer"; + } + if (!this.props.active()) setTimeout(() => this.closeHeader(), 0); TraceMobx(); const menuContent = this.renderMenuContent; - const menu = <div className="collectionSchema-header-menu" ref={this.setNode} + const menu = <div className="collectionSchema-header-menu" onWheel={e => this.onZoomMenu(e)} onPointerDown={e => this.onHeaderClick(e)} style={{ - position: "fixed", background: "white", - transform: `translate(${this.menuCoordinates[0] / this.scale}px, ${this.menuCoordinates[1] / this.scale}px)` + position: "fixed", background: "white", border: "black 1px solid", + transform: `translate(${(this.menuCoordinates[0])}px, ${(this.menuCoordinates[1])}px)` }}> <Measure offset onResize={action((r: any) => { const dim = this.props.ScreenToLocalTransform().inverse().transformDirection(r.offset.width, r.offset.height); @@ -627,15 +612,16 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { {({ measureRef }) => <div ref={measureRef}> {menuContent} </div>} </Measure> </div>; - return <div className="collectionSchemaView-container" + return <div className={name} style={{ - overflow: this.props.overflow === true ? "auto" : undefined, + overflow: this.props.overflow === true ? "scroll" : undefined, backgroundColor: "white", pointerEvents: !this.props.active() && !SnappingManager.GetIsDragging() ? "none" : undefined, - width: this.props.PanelWidth() || "100%", height: this.props.PanelHeight() || "100%", position: "relative", + width: name === "collectionSchemaView-searchContainer" ? "auto" : this.props.PanelWidth() || "100%", height: this.props.PanelHeight() || "100%", position: "relative", }} > <div className="collectionSchemaView-tableContainer" - style={{ backgroundColor: "white", width: `calc(100% - ${this.previewWidth()}px)` }} + style={{ width: `calc(100% - ${this.previewWidth()}px)` }} onKeyPress={this.onKeyPress} + onContextMenu={this.onSpecificMenu} onPointerDown={this.onPointerDown} onWheel={e => this.props.active(true) && e.stopPropagation()} onDrop={e => this.onExternalDrop(e, {})} @@ -644,7 +630,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { </div> {this.dividerDragger} {!this.previewWidth() ? (null) : this.previewPanel} - {this._headerOpen ? menu : null} + {this._headerOpen && this.props.active() ? menu : null} </div>; } }
\ No newline at end of file |