From 6c7dc0f939635982ae619eb5831ff45063d7021e Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Wed, 17 Jul 2019 14:08:24 -0400 Subject: can add columns and delete columns through column header --- .../views/collections/CollectionSchemaView.tsx | 286 +++++++++++++-------- 1 file changed, 181 insertions(+), 105 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index f72b1aa07..8ddf26be2 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -4,10 +4,10 @@ import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; -import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table"; +import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, TableCellRenderer } from "react-table"; import "react-table/react-table.css"; import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils"; -import { Doc, DocListCast, DocListCastAsync, Field } from "../../../new_fields/Doc"; +import { Doc, DocListCast, DocListCastAsync, Field, FieldResult } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; @@ -31,12 +31,28 @@ import { CollectionVideoView } from "./CollectionVideoView"; import { CollectionView } from "./CollectionView"; import { undoBatch } from "../../util/UndoManager"; import { timesSeries } from "async"; +import { CollectionSchemaHeader, CollectionSchemaAddColumnHeader } from "./CollectionSchemaHeaders"; +import { CellProps, CollectionSchemaCell } from "./CollectionSchemaCells"; library.add(faCog); library.add(faPlus); // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 +export enum ColumnType { + Any, + Number, + String, + Boolean, + Doc, + Checkbox +} +// this map should be used for keys that should have a const type of value +const columnTypes: Map = new Map([ + ["x", ColumnType.Number], ["y", ColumnType.Number], ["width", ColumnType.Number], ["height", ColumnType.Number], + ["nativeWidth", ColumnType.Number], ["nativeHeight", ColumnType.Number], ["isPrototype", ColumnType.Boolean], + ["page", ColumnType.Number], ["curPage", ColumnType.Number], ["libraryBrush", ColumnType.Boolean], ["zIndex", ColumnType.Number] +]); @observer class KeyToggle extends React.Component<{ keyName: string, checked: boolean, toggle: (key: string) => void }> { @@ -66,21 +82,72 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @observable _keys: string[] = []; @observable _newKeyName: string = ""; @observable previewScript: string = ""; + @observable _headerIsEditing: boolean = false; @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); } @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; } @computed get tableWidth() { return this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH - this.previewWidth(); } @computed get columns() { return Cast(this.props.Document.schemaColumns, listSpec("string"), []); } + set columns(columns: string[]) { this.props.Document.schemaColumns = new List(columns); } @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } @computed get tableColumns() { - return this.columns.map(col => { - const ref = React.createRef(); + let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1); + + let cols = this.columns.map(col => { return { - Header:

this.onHeaderDrag(col), undefined, "copy")}>{col}

, + Header: , accessor: (doc: Doc) => doc ? doc[col] : 0, - id: col + id: col, + Cell: (rowProps: CellInfo) => { + let row = rowProps.index; + let column = this.columns.indexOf(rowProps.column.id!); + // let isFocused = focusedRow === row && focusedCol === column; + let isFocused = false; + + let props: CellProps = { + row: row, + col: column, + rowProps: rowProps, + isFocused: isFocused, + changeFocusedCellByDirection: action(emptyFunction),//this.changeFocusedCellByDirection, + changeFocusedCellByIndex: action(emptyFunction), //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, + moveDocument: this.props.moveDocument, + setIsEditing: action(emptyFunction), //this.setCellIsEditing, + isEditable: true //isEditable + }; + return + } }; + }) as {Header: TableCellRenderer, accessor: (doc: Doc) => FieldResult, id: string, Cell: (rowProps: CellInfo) => JSX.Element}[]; + + cols.push({ + Header: , + accessor: (doc: Doc) => 0, + id: "add", + Cell: (rowProps: CellInfo) => <>, }); + + return cols; } onHeaderDrag = (columnName: string) => { @@ -97,72 +164,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return this.props.Document; } - renderCell = (rowProps: CellInfo) => { - let props: FieldViewProps = { - Document: rowProps.original, - DataDoc: rowProps.original, - fieldKey: rowProps.column.id as string, - fieldExt: "", - ContainingCollectionView: this.props.CollectionView, - isSelected: returnFalse, - select: emptyFunction, - renderDepth: this.props.renderDepth + 1, - selectOnLoad: false, - ScreenToLocalTransform: Transform.Identity, - focus: emptyFunction, - active: returnFalse, - whenActiveChanged: emptyFunction, - PanelHeight: returnZero, - PanelWidth: returnZero, - addDocTab: this.props.addDocTab, - }; - let fieldContentView = ; - let reference = React.createRef(); - let onItemDown = (e: React.PointerEvent) => { - (!this.props.CollectionView.props.isSelected() ? undefined : - SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); - }; - let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { - const res = run({ this: doc }); - if (!res.success) return false; - doc[props.fieldKey] = res.result; - return true; - }; - return ( -
- { - let field = props.Document[props.fieldKey]; - if (Field.IsField(field)) { - return Field.toScriptString(field); - } - return ""; - }} - SetValue={(value: string) => { - let script = CompileScript(value, { addReturn: true, params: { this: Doc.name } }); - if (!script.compiled) { - return false; - } - return applyToDoc(props.Document, script.run); - }} - OnFillDown={async (value: string) => { - let script = CompileScript(value, { addReturn: true, params: { this: Doc.name } }); - if (!script.compiled) { - return; - } - const run = script.run; - //TODO This should be able to be refactored to compile the script once - const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]); - val && val.forEach(doc => applyToDoc(doc, run)); - }}> - -
- ); - } - private getTrProps: ComponentPropsGetterR = (state, rowInfo) => { const that = this; if (!rowInfo) { @@ -189,6 +190,11 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { super.CreateDropTarget(ele); } + @action + setHeaderIsEditing = (isEditing: boolean) => { + this._headerIsEditing = isEditing; + } + @action toggleKey = (key: string) => { let list = Cast(this.props.Document.schemaColumns, listSpec("string")); @@ -278,10 +284,60 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } @action - newKeyChange = (e: React.ChangeEvent) => { - this._newKeyName = e.currentTarget.value; + deleteColumn = (key: string) => { + let list = Cast(this.props.Document.schemaColumns, listSpec("string")); + if (list === undefined) { + this.props.Document.schemaColumns = list = new List([]); + } else { + const index = list.indexOf(key); + if (index > -1) { + list.splice(index, 1); + } + } + } + + @action + changeColumns = (oldKey: string, newKey: string, addNew: boolean) => { + let list = Cast(this.props.Document.schemaColumns, listSpec("string")); + if (list === undefined) { + this.props.Document.schemaColumns = list = new List([newKey]); + } else { + if (addNew) { + this.columns.push(newKey); + } else { + const index = list.indexOf(oldKey); + if (index > -1) { + list[index] = newKey; + } + } + } + } + + getColumnType = (key: string): ColumnType => { + if (columnTypes.get(key)) return columnTypes.get(key)!; + const typesDoc = FieldValue(Cast(this.props.Document.schemaColumnTypes, Doc)); + if (!typesDoc) return ColumnType.Any; + return NumCast(typesDoc[key]); + } + + setColumnType = (key: string, type: ColumnType): void => { + if (columnTypes.get(key)) return; + const typesDoc = FieldValue(Cast(this.props.Document.schemaColumnTypes, Doc)); + if (!typesDoc) { + // let newTypesDoc = new Doc(); + // newTypesDoc[key] = type; + // this.props.Document.schemaColumnTypes = newTypesDoc; + return; + } else { + typesDoc[key] = type; + } } + // @action + // newKeyChange = (e: React.ChangeEvent) => { + // this._newKeyName = e.currentTarget.value; + // } + @computed get previewDocument(): Doc | undefined { const selected = this.childDocs.length > this._selectedIndex ? this.childDocs[this._selectedIndex] : undefined; @@ -289,11 +345,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return pdc; } - getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate( - - this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth) + getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth); - get documentKeysCheckList() { + get documentKeys() { const docs = DocListCast(this.props.Document[this.props.fieldKey]); let keys: { [key: string]: boolean } = {}; // bcz: ugh. this is untracked since otherwise a large collection of documents will blast the server for all their fields. @@ -305,39 +360,60 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => keys[key] = false)))); this.columns.forEach(key => keys[key] = true); - return Array.from(Object.keys(keys)).map(item => - ()); - } - - get tableOptionsPanel() { - return !this.props.active() ? (null) : - ( -
Options
-
-
Preview Window
-
Show Preview
-
Displayed Columns
-
    - {this.documentKeysCheckList} -
- - -
- - }> - -
); - } + return Array.from(Object.keys(keys)); + } + + // get documentKeysCheckList() { + // const docs = DocListCast(this.props.Document[this.props.fieldKey]); + // let keys: { [key: string]: boolean } = {}; + // // bcz: ugh. this is untracked since otherwise a large collection of documents will blast the server for all their fields. + // // then as each document's fields come back, we update the documents _proxies. Each time we do this, the whole schema will be + // // invalidated and re-rendered. This workaround will inquire all of the document fields before the options button is clicked. + // // then by the time the options button is clicked, all of the fields should be in place. If a new field is added while this menu + // // is displayed (unlikely) it won't show up until something else changes. + // //TODO Types + // untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => keys[key] = false)))); + + // this.columns.forEach(key => keys[key] = true); + // return Array.from(Object.keys(keys)).map(item => + // ()); + // } + + // get tableOptionsPanel() { + // return !this.props.active() ? (null) : + // ( + //
Options
+ //
+ //
Preview Window
+ //
Show Preview
+ //
Displayed Columns
+ //
    + // {this.documentKeysCheckList} + //
+ // + // + //
+ // + // }> + // + //
); + // } @computed get reactTable() { let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; - return ; } @@ -392,7 +468,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { {this.reactTable} {this.dividerDragger} {!this.previewWidth() ? (null) : this.previewPanel} - {this.tableOptionsPanel} + {/* {this.tableOptionsPanel} */} ); } -- cgit v1.2.3-70-g09d2 From 235bc1ea11df56e13d8a1103d4c029be42cf208d Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Wed, 17 Jul 2019 16:34:58 -0400 Subject: can change column type to any, string, number, bool, or checkbox --- .../views/collections/CollectionSchemaCells.tsx | 276 +++------------------ .../views/collections/CollectionSchemaHeaders.tsx | 4 + .../views/collections/CollectionSchemaView.tsx | 17 +- 3 files changed, 45 insertions(+), 252 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index f15734df6..691c4f630 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -63,7 +63,6 @@ export class CollectionSchemaCell extends React.Component { @action onKeyDown = (e: KeyboardEvent): void => { if (this.props.isFocused && this.props.isEditable) { - // console.log("schema cell", this.props.isEditable); document.removeEventListener("keydown", this.onKeyDown); this._isEditing = true; this.props.setIsEditing(true); @@ -82,72 +81,6 @@ export class CollectionSchemaCell extends React.Component { this.props.changeFocusedCellByIndex(this.props.row, this.props.col); } - renderCell = (rowProps: CellInfo) => { - let props: FieldViewProps = { - Document: rowProps.original, - DataDoc: rowProps.original, - fieldKey: rowProps.column.id as string, - fieldExt: "", - ContainingCollectionView: this.props.CollectionView, - isSelected: returnFalse, - select: emptyFunction, - renderDepth: this.props.renderDepth + 1, - selectOnLoad: false, - ScreenToLocalTransform: Transform.Identity, - focus: emptyFunction, - active: returnFalse, - whenActiveChanged: emptyFunction, - PanelHeight: returnZero, - PanelWidth: returnZero, - addDocTab: this.props.addDocTab, - }; - let fieldContentView = ; - let reference = React.createRef(); - let onItemDown = (e: React.PointerEvent) => { - (!this.props.CollectionView.props.isSelected() ? undefined : - SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); - }; - let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { - const res = run({ this: doc }); - if (!res.success) return false; - doc[props.fieldKey] = res.result; - return true; - }; - return ( -
- { - let field = props.Document[props.fieldKey]; - if (Field.IsField(field)) { - return Field.toScriptString(field); - } - return ""; - }} - SetValue={(value: string) => { - let script = CompileScript(value, { addReturn: true, params: { this: Doc.name } }); - if (!script.compiled) { - return false; - } - return applyToDoc(props.Document, script.run); - }} - OnFillDown={async (value: string) => { - let script = CompileScript(value, { addReturn: true, params: { this: Doc.name } }); - if (!script.compiled) { - return; - } - const run = script.run; - //TODO This should be able to be refactored to compile the script once - const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]); - val && val.forEach(doc => applyToDoc(doc, run)); - }}> - -
- ); - } - renderCellWithType(type: string | undefined) { let props: FieldViewProps = { Document: this.props.rowProps.original, @@ -167,7 +100,6 @@ export class CollectionSchemaCell extends React.Component { PanelWidth: returnZero, addDocTab: this.props.addDocTab, }; - let fieldContentView: JSX.Element = ; let reference = React.createRef(); let onItemDown = (e: React.PointerEvent) => { // (!this.props.CollectionView.props.isSelected() ? undefined : @@ -181,8 +113,11 @@ export class CollectionSchemaCell extends React.Component { }; let field = props.Document[props.fieldKey]; - let contents = type === undefined ? : type === "number" ? NumCast(field) : type === "boolean" ? (BoolCast(field) ? "true" : "false") : "incorrect type"; - // let contents = typeof field === "number" ? NumCast(field) : "incorrect type"; + let contents: any = "incorrect type"; + if (type === undefined) contents = ; + if (type === "number") contents = typeof field === "number" ? NumCast(field) : "--" + typeof field + "--"; + if (type === "string") contents = typeof field === "string" ? (StrCast(field) === "" ? "--" : StrCast(field)) : "--" + typeof field + "--"; + if (type === "boolean") contents = typeof field === "boolean" ? (BoolCast(field) ? "true" : "false") : "--" + typeof field + "--"; return (
@@ -191,7 +126,7 @@ export class CollectionSchemaCell extends React.Component { editing={this._isEditing} // isEditingCallback={this.isEditingCallback} display={"inline"} - contents={fieldContentView} + contents={contents} height={Number(MAX_ROW_HEIGHT)} GetValue={() => { let field = props.Document[props.fieldKey]; @@ -224,7 +159,7 @@ export class CollectionSchemaCell extends React.Component { } render() { - return this.renderCell(this.props.rowProps); + return this.renderCellWithType(undefined); } } @@ -251,190 +186,37 @@ export class CollectionSchemaStringCell extends CollectionSchemaCell { @observer export class CollectionSchemaCheckboxCell extends CollectionSchemaCell { + @observable private _isChecked: boolean = typeof this.props.rowProps.original[this.props.rowProps.column.id as string] === "boolean" ? BoolCast(this.props.rowProps.original[this.props.rowProps.column.id as string]) : false; + private _doc: Doc = this.props.rowProps.original; + + applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { + const res = run({ this: doc }); + if (!res.success) return false; + doc[this.props.rowProps.column.id as string] = res.result; + return true; + } + + @action + toggleChecked = (e: React.ChangeEvent) => { + this._isChecked = e.target.checked; + let script = CompileScript(e.target.checked.toString(), { requiredType: "boolean", addReturn: true, params: { this: Doc.name } }); + if (script.compiled) { + this.applyToDoc(this._doc, script.run); + } + } + render() { - console.log("render checkbox cell"); - let props: FieldViewProps = { - Document: this.props.rowProps.original, - DataDoc: this.props.rowProps.original, - fieldKey: this.props.rowProps.column.id as string, - fieldExt: "", - ContainingCollectionView: this.props.CollectionView, - isSelected: returnFalse, - select: emptyFunction, - renderDepth: this.props.renderDepth + 1, - selectOnLoad: false, - ScreenToLocalTransform: Transform.Identity, - focus: emptyFunction, - active: returnFalse, - whenActiveChanged: emptyFunction, - PanelHeight: returnZero, - PanelWidth: returnZero, - addDocTab: this.props.addDocTab, - }; - let fieldContentView: JSX.Element = ; let reference = React.createRef(); let onItemDown = (e: React.PointerEvent) => { // (!this.props.CollectionView.props.isSelected() ? undefined : // SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); }; - let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { - const res = run({ this: doc }); - if (!res.success) return false; - doc[props.fieldKey] = res.result; - return true; - }; - - let field = props.Document[props.fieldKey]; - let contents = BoolCast(field); - console.log("contents", contents); - // let contents = typeof field === "number" ? NumCast(field) : "incorrect type"; - - let toggleChecked = (e: React.ChangeEvent) => { - console.log("toggle check", e.target.checked); - // this._isChecked = e.target.checked; - - let document = this.props.rowProps.original; - let script = CompileScript(e.target.checked.toString(), { requiredType: "boolean", addReturn: true, params: { this: Doc.name } }); - if (script.compiled) { - let applied = applyToDoc(document, script.run); - console.log("applied", applied); - } - }; - return (
-
- - {/* { - let field = props.Document[props.fieldKey]; - if (Field.IsField(field)) { - return Field.toScriptString(field); - } - return ""; - } - } - SetValue={(value: string) => { - let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } }); - if (!script.compiled) { - return false; - } - return applyToDoc(props.Document, script.run); - }} - OnFillDown={async (value: string) => { - let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } }); - if (!script.compiled) { - return; - } - const run = script.run; - //TODO This should be able to be refactored to compile the script once - const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]); - val && val.forEach(doc => applyToDoc(doc, run)); - }} /> */} +
+
); } -} - - // @observer -// export class CollectionSchemaCheckboxCell extends CollectionSchemaCell { -// // @observable private _isChecked: boolean = BoolCast(this.props.rowProps.original[this.props.fieldKey]); - -// render() { -// console.log("checkbox rneder"); - -// let props: FieldViewProps = { -// Document: this.props.rowProps.original, -// DataDoc: this.props.rowProps.original, -// fieldKey: this.props.rowProps.column.id as string, -// fieldExt: "", -// ContainingCollectionView: this.props.CollectionView, -// isSelected: returnFalse, -// select: emptyFunction, -// renderDepth: this.props.renderDepth + 1, -// selectOnLoad: false, -// ScreenToLocalTransform: Transform.Identity, -// focus: emptyFunction, -// active: returnFalse, -// whenActiveChanged: emptyFunction, -// PanelHeight: returnZero, -// PanelWidth: returnZero, -// addDocTab: this.props.addDocTab, -// }; -// let reference = React.createRef(); -// let onItemDown = (e: React.PointerEvent) => { -// (!this.props.CollectionView.props.isSelected() ? undefined : -// SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); -// }; - -// let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { -// const res = run({ this: doc }); -// if (!res.success) return false; -// doc[this.props.fieldKey] = res.result; -// return true; -// }; - -// let toggleChecked = (e: React.ChangeEvent) => { -// console.log("toggle check", e.target.checked); -// // this._isChecked = e.target.checked; - -// let document = this.props.rowProps.original; -// let script = CompileScript(e.target.checked.toString(), { requiredType: "boolean", addReturn: true, params: { this: Doc.name } }); -// if (script.compiled) { -// console.log("script compiled"); -// applyToDoc(document, script.run); -// } -// }; - - -// let field = props.Document[props.fieldKey]; -// // let contents = typeof field === "boolean" ? BoolCast(field) : "incorrect type"; -// let checked = typeof field === "boolean" ? BoolCast(field) : false; - -// return ( -//
-//
-// - -// {/* { -// let field = props.Document[props.fieldKey]; -// if (typeof field === "string") { -// return Field.toScriptString(field); -// } -// return ""; -// } -// } -// SetValue={(value: string) => { -// let script = CompileScript(value, { requiredType: "boolean", addReturn: true, params: { this: Doc.name } }); -// if (!script.compiled) { -// return false; -// } -// return applyToDoc(props.Document, script.run); -// }} -// OnFillDown={async (value: string) => { -// let script = CompileScript(value, { requiredType: "boolean", addReturn: true, params: { this: Doc.name } }); -// if (!script.compiled) { -// return; -// } -// const run = script.run; -// //TODO This should be able to be refactored to compile the script once -// const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]); -// val && val.forEach(doc => applyToDoc(doc, run)); -// }} /> */} -//
-//
-// ); -// } -// } \ No newline at end of file +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index a9d4a0170..3d45089a3 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -35,6 +35,7 @@ export class CollectionSchemaHeader extends React.Component { possibleKeys={this.props.possibleKeys} existingKeys={this.props.existingKeys} keyType={this.props.keyType} + typeConst={this.props.typeConst} menuButtonContent={
{this.props.keyValue}
} addNew={false} onSelect={this.props.onSelect} @@ -95,6 +96,7 @@ export interface ColumnMenuProps { possibleKeys: string[]; existingKeys: string[]; keyType: ColumnType; + typeConst: boolean; menuButtonContent: JSX.Element; addNew: boolean; onSelect: (oldKey: string, newKey: string, addnew: boolean) => void; @@ -150,6 +152,7 @@ export class CollectionSchemaColumnMenu extends React.Component addNew={this.props.addNew} onSelect={this.props.onSelect} /> + {!this.props.typeConst ? addNew={false} onSelect={this.setColumnType} /> + : null}
); diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 8ddf26be2..3572fac55 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -32,7 +32,7 @@ import { CollectionView } from "./CollectionView"; import { undoBatch } from "../../util/UndoManager"; import { timesSeries } from "async"; import { CollectionSchemaHeader, CollectionSchemaAddColumnHeader } from "./CollectionSchemaHeaders"; -import { CellProps, CollectionSchemaCell } from "./CollectionSchemaCells"; +import { CellProps, CollectionSchemaCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaBooleanCell, CollectionSchemaCheckboxCell } from "./CollectionSchemaCells"; library.add(faCog); @@ -100,7 +100,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { possibleKeys={possibleKeys} existingKeys={this.columns} keyType={this.getColumnType(col)} - typeConst={false} + typeConst={columnTypes.get(col) !== undefined} onSelect={this.changeColumns} setIsEditing={this.setHeaderIsEditing} deleteColumn={this.deleteColumn} @@ -130,6 +130,12 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { setIsEditing: action(emptyFunction), //this.setCellIsEditing, isEditable: true //isEditable }; + + let colType = this.getColumnType(col); + if (colType === ColumnType.Number) return + if (colType === ColumnType.String) return + if (colType === ColumnType.Boolean) return + if (colType === ColumnType.Checkbox) return return } }; @@ -324,9 +330,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { if (columnTypes.get(key)) return; const typesDoc = FieldValue(Cast(this.props.Document.schemaColumnTypes, Doc)); if (!typesDoc) { - // let newTypesDoc = new Doc(); - // newTypesDoc[key] = type; - // this.props.Document.schemaColumnTypes = newTypesDoc; + let newTypesDoc = new Doc(); + newTypesDoc[key] = type; + this.props.Document.schemaColumnTypes = newTypesDoc; + console.log("no typesDoc"); return; } else { typesDoc[key] = type; -- cgit v1.2.3-70-g09d2 From 928f217b51acd105b5366b57fbb0c043740f97a6 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Wed, 17 Jul 2019 20:47:54 -0400 Subject: column menu styling --- .../views/collections/CollectionSchemaCells.tsx | 46 ++- .../views/collections/CollectionSchemaHeaders.tsx | 153 +++++--- .../views/collections/CollectionSchemaView.scss | 413 +++++++-------------- .../views/collections/CollectionSchemaView.tsx | 32 +- 4 files changed, 272 insertions(+), 372 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 691c4f630..1bb661f88 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -81,6 +81,13 @@ export class CollectionSchemaCell extends React.Component { this.props.changeFocusedCellByIndex(this.props.row, this.props.col); } + applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { + const res = run({ this: doc }); + if (!res.success) return false; + doc[this.props.rowProps.column.id as string] = res.result; + return true; + } + renderCellWithType(type: string | undefined) { let props: FieldViewProps = { Document: this.props.rowProps.original, @@ -105,12 +112,6 @@ export class CollectionSchemaCell extends React.Component { // (!this.props.CollectionView.props.isSelected() ? undefined : // SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); }; - let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { - const res = run({ this: doc }); - if (!res.success) return false; - doc[props.fieldKey] = res.result; - return true; - }; let field = props.Document[props.fieldKey]; let contents: any = "incorrect type"; @@ -141,7 +142,7 @@ export class CollectionSchemaCell extends React.Component { if (!script.compiled) { return false; } - return applyToDoc(props.Document, script.run); + return this.applyToDoc(props.Document, script.run); }} OnFillDown={async (value: string) => { let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } }); @@ -151,7 +152,7 @@ export class CollectionSchemaCell extends React.Component { const run = script.run; //TODO This should be able to be refactored to compile the script once const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]); - val && val.forEach(doc => applyToDoc(doc, run)); + val && val.forEach(doc => this.applyToDoc(doc, run)); }} />
@@ -187,21 +188,13 @@ export class CollectionSchemaStringCell extends CollectionSchemaCell { @observer export class CollectionSchemaCheckboxCell extends CollectionSchemaCell { @observable private _isChecked: boolean = typeof this.props.rowProps.original[this.props.rowProps.column.id as string] === "boolean" ? BoolCast(this.props.rowProps.original[this.props.rowProps.column.id as string]) : false; - private _doc: Doc = this.props.rowProps.original; - - applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { - const res = run({ this: doc }); - if (!res.success) return false; - doc[this.props.rowProps.column.id as string] = res.result; - return true; - } @action toggleChecked = (e: React.ChangeEvent) => { this._isChecked = e.target.checked; let script = CompileScript(e.target.checked.toString(), { requiredType: "boolean", addReturn: true, params: { this: Doc.name } }); if (script.compiled) { - this.applyToDoc(this._doc, script.run); + this.applyToDoc(this._document, script.run); } } @@ -213,10 +206,27 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell { }; return (
-
+
); } +} + +@observer +export class CollectionSchemaDocCell extends CollectionSchemaCell { + render() { + let reference = React.createRef(); + let onItemDown = (e: React.PointerEvent) => { + // (!this.props.CollectionView.props.isSelected() ? undefined : + // SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); + }; + return ( +
+
+
+
+ ); + } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index 3d45089a3..d6ebaf8d8 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -2,14 +2,14 @@ import React = require("react"); import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; import "./CollectionSchemaView.scss"; -import { faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare } from '@fortawesome/free-solid-svg-icons'; +import { faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn } from '@fortawesome/free-solid-svg-icons'; import { library, IconProp } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Flyout, anchorPoints } from "../DocumentDecorations"; import { ColumnType } from "./CollectionSchemaView"; import { emptyFunction } from "../../../Utils"; -library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare); +library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn); export interface HeaderProps { keyValue: string; @@ -26,7 +26,7 @@ export interface HeaderProps { export class CollectionSchemaHeader extends React.Component { render() { let icon: IconProp = this.props.keyType === ColumnType.Number ? "hashtag" : this.props.keyType === ColumnType.String ? "font" : - this.props.keyType === ColumnType.Checkbox || this.props.keyType === ColumnType.Boolean ? "check-square" : "align-justify"; + this.props.keyType === ColumnType.Checkbox ? "check-square" : this.props.keyType === ColumnType.Boolean ? "toggle-on" : "align-justify"; return (
@@ -67,7 +67,7 @@ export class CollectionSchemaAddColumnHeader extends React.Component console.log("add clicked")}>; + let addButton = ; return (
{/* {this._creatingColumn ? <> : */} @@ -76,6 +76,7 @@ export class CollectionSchemaAddColumnHeader extends React.Component this.props.setColumnType(this.props.keyValue, type); } - renderContent = () => { - let keyTypeStr = ColumnType[this.props.keyType]; - let colTypes = []; - for (let type in ColumnType) { - if (!(parseInt(type, 10) >= 0)) colTypes.push(type); - } + renderTypes = () => { + if (this.props.typeConst) return <>; + return ( +
+ +
+ + + + + +
+
+ ); + } - if (this._isOpen) { - if (this.props.onlyShowOptions) { - return ( -
- -
- ); - } else { - return ( -
- - {!this.props.typeConst ? - - : null} + renderContent = () => { + return ( +
+ +
+ +
+ {this.props.onlyShowOptions ? <> : + <> + {this.renderTypes()} +
- ); - } - } + + } +
+ ); } render() { return ( - // {this.renderContent()}
}> - //
{ this.props.setIsEditing(true); console.log("clicked anchor"); }}>{this.props.menuButton}
- //
-
this.toggleIsOpen()}>{this.props.menuButtonContent}
- {this.renderContent()} + +
{ this.props.setIsEditing(true); }}>{this.props.menuButtonContent}
+
); } } +{/* //
+ //
this.toggleIsOpen()}>{this.props.menuButtonContent}
+ // {this.renderContent()} + //
*/} + interface KeysDropdownProps { keyValue: string; @@ -190,27 +197,56 @@ interface KeysDropdownProps { canAddNew: boolean; addNew: boolean; onSelect: (oldKey: string, newKey: string, addnew: boolean) => void; - } @observer class KeysDropdown extends React.Component { @observable private _key: string = this.props.keyValue; @observable private _searchTerm: string = ""; + @observable private _isOpen: boolean = false; + @observable private _canClose: boolean = true; @action setSearchTerm = (value: string): void => { this._searchTerm = value; }; @action setKey = (key: string): void => { this._key = key; }; + @action setIsOpen = (isOpen: boolean): void => {this._isOpen = isOpen;}; @action onSelect = (key: string): void => { this.props.onSelect(this._key, key, this.props.addNew); this.setKey(key); + this._isOpen = false; } onChange = (val: string): void => { this.setSearchTerm(val); } + @action + onFocus = (e: React.FocusEvent): void => { + this._isOpen = true; + } + + @action + onBlur = (e: React.FocusEvent): void => { + // const that = this; + if (this._canClose) this._isOpen = false; + // setTimeout(function() { // TODO: this might be too hacky lol + // that.setIsOpen(false); + // }, 100); + } + + @action + onPointerEnter = (e: React.PointerEvent): void => { + this._canClose = false; + } + + @action + onPointerOut = (e: React.PointerEvent): void => { + this._canClose = true; + } + renderOptions = (): JSX.Element[] | JSX.Element => { + if (!this._isOpen) return <>; + let keyOptions = this._searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1); let exactFound = keyOptions.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1 || this.props.existingKeys.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1; @@ -222,7 +258,8 @@ class KeysDropdown extends React.Component { // 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(
{ this.onSelect(this._searchTerm); this.setSearchTerm(""); }}>Create "{this._searchTerm}" key
); + onClick={() => { this.onSelect(this._searchTerm); this.setSearchTerm(""); }}> + Create "{this._searchTerm}" key
); } return options; @@ -231,9 +268,9 @@ class KeysDropdown extends React.Component { render() { return (
- this.onChange(e.target.value)} > -
+ this.onChange(e.target.value)} onFocus={this.onFocus} onBlur={this.onBlur}> +
{this.renderOptions()}
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 4ab38b9d9..4bc7a778c 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -1,7 +1,5 @@ @import "../globalCssVariables"; - - .collectionSchemaView-container { border-width: $COLLECTION_BORDER_WIDTH; border-color: $intermediate-color; @@ -13,15 +11,6 @@ height: 100%; overflow: hidden; - .collectionSchemaView-cellContents { - height: $MAX_ROW_HEIGHT; - - img { - width: auto; - max-height: $MAX_ROW_HEIGHT; - } - } - .collectionSchemaView-previewRegion { position: relative; background: $light-color; @@ -47,16 +36,6 @@ } } - .collectionSchemaView-previewHandle { - position: absolute; - height: 15px; - width: 15px; - z-index: 20; - right: 0; - top: 20px; - background: Black; - } - .collectionSchemaView-dividerDragger { position: relative; background: black; @@ -67,324 +46,198 @@ right: 0; top: 0; background: $main-accent; - } - - .collectionSchemaView-columnsHandle { - position: absolute; - height: 37px; - width: 20px; - z-index: 20; - left: 0; - bottom: 0; - background: $main-accent; - } - - .collectionSchemaView-colDividerDragger { - position: relative; - box-sizing: border-box; - border-top: 1px solid $intermediate-color; - border-bottom: 1px solid $intermediate-color; - float: top; - width: 100%; - } - - .collectionSchemaView-dividerDragger { - position: relative; box-sizing: border-box; border-left: 1px solid $intermediate-color; border-right: 1px solid $intermediate-color; - float: left; - height: 100%; } +} - .collectionSchemaView-tableContainer { - position: relative; - float: left; - height: 100%; - } +.ReactTable { + width: 100%; + height: 100%; + background: $light-color; + box-sizing: border-box; + border: none !important; - .ReactTable { - // position: absolute; // display: inline-block; - // overflow: auto; - width: 100%; + .rt-table { + overflow-y: auto; + overflow-x: auto; height: 100%; - background: $light-color; - box-sizing: border-box; - border: none !important; - - .rt-table { - overflow-y: auto; - overflow-x: auto; - height: 100%; - display: -webkit-inline-box; - direction: ltr; // direction:rtl; - // display:block; - } - - .rt-tbody { - //direction: ltr; - direction: rtl; - } + display: -webkit-inline-box; + direction: ltr; + } - .rt-tr-group { - direction: ltr; - max-height: $MAX_ROW_HEIGHT; + .rt-thead { + &.-header { + background: $intermediate-color; + color: $light-color; + font-size: 12px; + height: 30px; } - .rt-td { - border-width: 1px; - border-right-color: $intermediate-color; - - .imageBox-cont { - position: relative; - max-height: 100%; - } - - .imageBox-cont img { - object-fit: contain; - max-width: 100%; - height: 100%; - } + .rt-resizable-header { + padding: 0; + height: 30px; - .videoBox-cont { - object-fit: contain; - width: auto; - height: 100%; + &:last-child { + overflow: visible; } } - } - .ReactTable .rt-thead.-header { - background: $intermediate-color; - color: $light-color; - // text-transform: uppercase; - letter-spacing: 2px; - font-size: 12px; - height: 30px; - padding-top: 4px; + .rt-resizable-header-content { + height: 100%; + overflow: visible; + } } - .ReactTable .rt-th, - .ReactTable .rt-td { + .rt-th { max-height: $MAX_ROW_HEIGHT; padding: 3px 7px; font-size: 13px; text-align: center; } - .ReactTable .rt-tbody .rt-tr-group:last-child { - border-bottom: $intermediate-color; - border-bottom-style: solid; - border-bottom-width: 1; + .rt-tbody { + direction: rtl; } - .documentView-node-topmost { - text-align: left; - transform-origin: center top; - display: inline-block; - } + .rt-tr-group { + direction: ltr; + max-height: $MAX_ROW_HEIGHT; - .documentView-node:first-child { - background: $light-color; + &:last-child { + border-bottom: $intermediate-color; + border-bottom-style: solid; + border-bottom-width: 1; + } } - .ReactTable .rt-thead .rt-resizable-header:last-child { - overflow: visible; - } -} + .rt-td { + border-width: 1px; + border-right-color: $intermediate-color; + max-height: $MAX_ROW_HEIGHT; + padding: 3px 7px; + font-size: 13px; + text-align: center; -.collectionSchema-header-menuOptions { - position: absolute; - top: $MAX_ROW_HEIGHT; - left: 0; - z-index: 9999; - background-color: $light-color-secondary; - color: black; - border: 1px solid $main-accent; - width: 250px; - padding: 10px; + .imageBox-cont { + position: relative; + max-height: 100%; + } - input { - color: black; - width: 100%; + .imageBox-cont img { + object-fit: contain; + max-width: 100%; + height: 100%; + } + + .videoBox-cont { + object-fit: contain; + width: auto; + height: 100%; + } } } -//options menu styling -#schemaOptionsMenuBtn { - position: absolute; - height: 20px; - width: 20px; - border-radius: 50%; - z-index: 21; - right: 4px; - top: 4px; - pointer-events: auto; - background-color: black; +.documentView-node-topmost { + text-align: left; + transform-origin: center top; display: inline-block; - padding: 0px; - font-size: 100%; -} - -ul { - list-style-type: disc; } -#schema-options-header { - text-align: center; - padding: 0px; - margin: 0px; +.documentView-node:first-child { + background: $light-color; } -.schema-options-subHeader { - color: $intermediate-color; - margin-bottom: 5px; -} +.collectionSchemaView-header { + height: 100%; -#schemaOptionsMenuBtn:hover { - transform: scale(1.15); -} + .collectionSchema-header-menu { + height: 100%; -#preview-schema-checkbox-div { - margin-left: 20px; - font-size: 12px; -} + .collectionSchema-header-toggler { + width: 100%; + height: 100%; + padding: 4px; -#options-flyout-div { - text-align: left; - padding: 0px; - z-index: 100; - font-family: $sans-serif; - padding-left: 5px; + svg { + margin-right: 4px; + } + } + } } -#schema-col-checklist { - overflow: scroll; +.collectionSchema-header-menuOptions { + // position: absolute; + // top: 30px; + // left: 50%; + // transform: translateX(-50%); + // z-index: 9999; + // background-color: $light-color-secondary; + color: black; + // border: 1px solid $main-accent; + width: 175px; + // padding: 10px; text-align: left; - //background-color: $light-color-secondary; - line-height: 25px; - max-height: 175px; - font-family: $sans-serif; - font-size: 12px; -} - -.Resizer { - box-sizing: border-box; - background: #000; - opacity: 0.5; - z-index: 1; - background-clip: padding-box; - - &.horizontal { - height: 11px; - margin: -5px 0; - border-top: 5px solid rgba(255, 255, 255, 0); - border-bottom: 5px solid rgba(255, 255, 255, 0); - cursor: row-resize; - width: 100%; - - &:hover { - border-top: 5px solid rgba(0, 0, 0, 0.5); - border-bottom: 5px solid rgba(0, 0, 0, 0.5); - } + .collectionSchema-headerMenu-group { + margin-bottom: 10px; } - &.vertical { - width: 11px; - margin: 0 -5px; - border-left: 5px solid rgba(255, 255, 255, 0); - border-right: 5px solid rgba(255, 255, 255, 0); - cursor: col-resize; - - &:hover { - border-left: 5px solid rgba(0, 0, 0, 0.5); - border-right: 5px solid rgba(0, 0, 0, 0.5); - } + label { + color: $main-accent; + font-weight: normal; } - &:hover { - -webkit-transition: all 2s ease; - transition: all 2s ease; + input { + color: black; + width: 100%; } -} -.vertical { - section { - width: 100vh; - height: 100vh; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - } + .keys-dropdown { + position: relative; + max-width: 175px; - header { - padding: 1rem; - background: #eee; - } + // .keys-search { - footer { - padding: 1rem; - background: #eee; - } -} + // } -.horizontal { - section { - width: 100vh; - height: 100vh; - display: flex; - flex-direction: column; + .keys-options-wrapper { + width: 100%; + max-height: 150px; + overflow-y: scroll; + position: absolute; + top: 20px; + + .key-option { + background-color: $light-color; + border: 1px solid $light-color-secondary; + padding: 2px 3px; + + &:not(:last-child) { + border-top: 0; + } + + &:hover { + background-color: $light-color-secondary; + } + } + } } - header { - padding: 1rem; - background: #eee; - } + .columnMenu-types { + display: flex; + justify-content: space-between; - footer { - padding: 1rem; - background: #eee; + button { + border-radius: 20px; + } } } -.parent { - width: 100%; - height: 100%; - -webkit-box-flex: 1; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; -} - -.header { - background: #aaa; - height: 3rem; - line-height: 3rem; -} - -.wrapper { - background: #ffa; - margin: 5rem; - -webkit-box-flex: 1; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; +#preview-schema-checkbox-div { + margin-left: 20px; + font-size: 12px; } .-even { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 3572fac55..3ef58bcaf 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -44,7 +44,7 @@ export enum ColumnType { Number, String, Boolean, - Doc, + // Doc, Checkbox } // this map should be used for keys that should have a const type of value @@ -54,21 +54,21 @@ const columnTypes: Map = new Map([ ["page", ColumnType.Number], ["curPage", ColumnType.Number], ["libraryBrush", ColumnType.Boolean], ["zIndex", ColumnType.Number] ]); -@observer -class KeyToggle extends React.Component<{ keyName: string, checked: boolean, toggle: (key: string) => void }> { - constructor(props: any) { - super(props); - } - - render() { - return ( -
- this.props.toggle(this.props.keyName)} /> - {this.props.keyName} -
- ); - } -} +// @observer +// class KeyToggle extends React.Component<{ keyName: string, checked: boolean, toggle: (key: string) => void }> { +// constructor(props: any) { +// super(props); +// } + +// render() { +// return ( +//
+// this.props.toggle(this.props.keyName)} /> +// {this.props.keyName} +//
+// ); +// } +// } @observer export class CollectionSchemaView extends CollectionSubView(doc => doc) { -- cgit v1.2.3-70-g09d2 From 28420a749a0e06ee105a2d8f1cc3c273469b83d7 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 18 Jul 2019 17:55:19 -0400 Subject: shema rows can be moved by dragging --- .../views/collections/CollectionSchemaCells.tsx | 12 +- .../views/collections/CollectionSchemaHeaders.tsx | 3 + .../CollectionSchemaMovableTableHOC.tsx | 261 +++++++++++++++++++++ .../views/collections/CollectionSchemaView.scss | 82 +++++-- .../views/collections/CollectionSchemaView.tsx | 183 +++++++++++---- 5 files changed, 476 insertions(+), 65 deletions(-) create mode 100644 src/client/views/collections/CollectionSchemaMovableTableHOC.tsx (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 1bb661f88..51e9016b7 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -109,8 +109,8 @@ export class CollectionSchemaCell extends React.Component { }; let reference = React.createRef(); let onItemDown = (e: React.PointerEvent) => { - // (!this.props.CollectionView.props.isSelected() ? undefined : - // SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); + (!this.props.CollectionView.props.isSelected() ? undefined : + SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); }; let field = props.Document[props.fieldKey]; @@ -201,8 +201,8 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell { render() { let reference = React.createRef(); let onItemDown = (e: React.PointerEvent) => { - // (!this.props.CollectionView.props.isSelected() ? undefined : - // SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); + (!this.props.CollectionView.props.isSelected() ? undefined : + SetupDrag(reference, () => this._document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); }; return (
@@ -219,8 +219,8 @@ export class CollectionSchemaDocCell extends CollectionSchemaCell { render() { let reference = React.createRef(); let onItemDown = (e: React.PointerEvent) => { - // (!this.props.CollectionView.props.isSelected() ? undefined : - // SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); + (!this.props.CollectionView.props.isSelected() ? undefined : + SetupDrag(reference, () => this._document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); }; return (
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index d6ebaf8d8..c81cf1aef 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -177,7 +177,10 @@ export class CollectionSchemaColumnMenu extends React.Component return (
+ {/*
*/}
{ this.props.setIsEditing(true); }}>{this.props.menuButtonContent}
+ {/* {this._isOpen ? this.renderContent() : <>} */} + {/*
*/}
); diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx new file mode 100644 index 000000000..44a134d31 --- /dev/null +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -0,0 +1,261 @@ +import React = require("react"); +import { TableProps, ReactTableDefaults, Column, TableCellRenderer, ComponentPropsGetterR, ComponentPropsGetter0 } from "react-table"; +import { ComponentType, ComponentClass } from 'react'; +import { action } from "mobx"; +import "./CollectionSchemaView.scss"; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { faBars } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Transform } from "../../util/Transform"; +import { Doc } from "../../../new_fields/Doc"; +import { DragManager, SetupDrag } from "../../util/DragManager"; +import { SelectionManager } from "../../util/SelectionManager"; +import { Cast, FieldValue } from "../../../new_fields/Types"; + +library.add(faBars); + +// export interface MovableSchemaProps { +// ScreenToLocalTransform: () => Transform; +// addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean; +// moveDoc: DragManager.MoveFunction; +// columnsValues: string[]; +// columnsList: Column[]; +// setColumnsOrder: (columns: string[]) => void; +// numImmovableColumns?: number; +// } + +// export default function CollectionSchemaMovableHOC>(WrappedComponent: ComponentType): ComponentClass { +// return class CollectionSchemaMovableSchemaHOC extends React.Component { +// constructor(props: any) { +// super(props); +// } + +// reorderColumns(toMove: string, relativeTo: string, before: boolean, columnsValues: string[], setColumnsOrder: (columns: string[]) => void) { +// let columns = [...columnsValues]; +// let oldIndex = columns.indexOf(toMove); +// let relIndex = columns.indexOf(relativeTo); +// let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex; + +// if (oldIndex === newIndex) return; + +// columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]); +// setColumnsOrder(columns); +// } + +// createColumns(columnsValues: string[], columnsList: Column[], setColumnsOrder: (columnsValues: string[]) => void, ScreenToLocalTransform: () => Transform): Column[] { +// let immovableIndex = this.props.numImmovableColumns ? columnsList.length - this.props.numImmovableColumns! : columnsList.length; +// return columnsList.map((col, index) => { +// if (index >= immovableIndex) { +// return col; +// } else { +// return ({ ...col, Header: MovableColumn(col.Header, columnsValues[index], columnsValues, setColumnsOrder, this.reorderColumns, ScreenToLocalTransform) }); +// } +// }); +// } + +// render() { +// console.log("THIS IS THE RIGHT HOC"); +// const { ScreenToLocalTransform, addDoc, moveDoc, columnsValues, columnsList, setColumnsOrder, getTrProps, ...props } = this.props; +// return ( +// +// ); +// } + +// }; +// } +// //TrComponent={MovableRow(ScreenToLocalTransform, addDoc, moveDoc)} +// //columns={this.createColumns(columnsValues, columnsList, setColumnsOrder, ScreenToLocalTransform)} + +// export function MovableSchemaHOC>(WrappedComponent: ComponentType): ComponentClass { +// return class MovableSchemaHOC extends React.Component { +// constructor(props: any) { +// super(props); +// } + +// createColumns(columnsValues: string[], columnsList: Column[], setColumnsOrder: (columnsValues: string[]) => void, ScreenToLocalTransform: () => Transform): Column[] { +// let immovableIndex = this.props.numImmovableColumns ? columnsList.length - this.props.numImmovableColumns! : columnsList.length; +// return columnsList.map((col, index) => { +// if (index >= immovableIndex) { +// return col; +// } else { +// return ({ ...col, Header: MovableColumn(col.Header, columnsValues[index], columnsValues, setColumnsOrder, this.reorderColumns, ScreenToLocalTransform) }); +// } +// }); +// } + +// reorderColumns(toMove: string, relativeTo: string, before: boolean, columnsValues: string[], setColumnsOrder: (columns: string[]) => void) { +// let columns = [...columnsValues]; +// let oldIndex = columns.indexOf(toMove); +// let relIndex = columns.indexOf(relativeTo); +// let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex; + +// if (oldIndex === newIndex) return; + +// columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]); +// setColumnsOrder(columns); +// } + +// render() { +// const { ScreenToLocalTransform, addDoc, moveDoc, columnsValues, columnsList, setColumnsOrder, getTrProps, ...props } = this.props; +// return ( +// +// ); +// } +// }; +// } + + + + +export interface MovableColumnProps { + columnRenderer: TableCellRenderer; + columnValue: string; + allColumns: string[]; + reorderColumns: (toMove: string, relativeTo: string, before: boolean, columns: string[]) => void; + ScreenToLocalTransform: () => Transform; +} +export class MovableColumn extends React.Component { + // private _ref: React.RefObject = React.createRef(); + + onDragStart = (e: React.DragEvent, ref: React.RefObject): void => { + console.log("drag start"); + e.dataTransfer.setData("column", this.props.columnValue); + } + + onDragOver = (e: React.DragEvent,ref: React.RefObject): void => { + console.log("drag over"); + let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); + let rect = ref.current!.getBoundingClientRect(); + let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + ((rect.right - rect.left) / 2), rect.top); + let before = x[0] < bounds[0]; + + ref.current!.className = "collectionSchema-column-header"; + if (before) ref.current!.className += " col-before"; + if (!before) ref.current!.className += " col-after"; + // e.stopPropagation(); + } + + onDragLeave = (e: React.DragEvent, ref: React.RefObject): void => { + console.log("drag leave"); + ref.current!.className = "collectionSchema-column-header"; + e.stopPropagation(); + } + + onDrop = (e: React.DragEvent,ref: React.RefObject): void => { + console.log("on drop"); + // TODO: get column being dropped and before/after + let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); + let rect = ref.current!.getBoundingClientRect(); + let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + ((rect.right - rect.left) / 2), rect.top); + let before = x[0] < bounds[0]; + + this.props.reorderColumns(e.dataTransfer.getData("column"), this.props.columnValue, before, this.props.allColumns); + ref.current!.className = "collectionSchema-column-header"; + } + + render() { + let ref: React.RefObject = React.createRef(); + return ( +
console.log("pointer down")} onPointerEnter={() => console.log("pointer enter")} onPointerOut={() => console.log("pointer exit")} + onDragStart={e => this.onDragStart(e, ref)} onDragOver={e => this.onDragOver(e, ref)} onDragLeave={e => this.onDragLeave(e, ref)} onDrop={e => this.onDrop(e, ref)}> + {this.props.columnRenderer} +
+ ); + } +} + +// export function MovableColumn(columnRenderer: TableCellRenderer, columnValue: string, allColumns: string[], +// reorderColumns: (toMove: string, relativeTo: string, before: boolean, columns: string[]) => void, +// ScreenToLocalTransform: () => Transform) { +// return ; +// } + +export function MovableRow(ScreenToLocalTransform: () => Transform, addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean, moveDoc: DragManager.MoveFunction) { + return class MovableRow extends React.Component { + private _header?: React.RefObject = React.createRef(); + private _treedropDisposer?: DragManager.DragDropDisposer; + + onPointerEnter = (e: React.PointerEvent): void => { + if (e.buttons === 1 && SelectionManager.GetIsDragging()) { + this._header!.current!.className = "collectionSchema-row-wrapper"; + document.addEventListener("pointermove", this.onDragMove, true); + } + } + onPointerLeave = (e: React.PointerEvent): void => { + this._header!.current!.className = "collectionSchema-row-wrapper"; + document.removeEventListener("pointermove", this.onDragMove, true); + } + onDragMove = (e: PointerEvent): void => { + let x = ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); + let rect = this._header!.current!.getBoundingClientRect(); + let bounds = ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); + let before = x[1] < bounds[1]; + this._header!.current!.className = "collectionSchema-row-wrapper"; + if (before) this._header!.current!.className += " row-above"; + if (!before) this._header!.current!.className += " row-below"; + e.stopPropagation(); + } + + createTreeDropTarget = (ele: HTMLDivElement) => { + this._treedropDisposer && this._treedropDisposer(); + if (ele) { + this._treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.treeDrop.bind(this) } }); + } + } + + treeDrop = (e: Event, de: DragManager.DropEvent) => { + const { children = null, rowInfo } = this.props; + if (!rowInfo) return false; + + const { original } = rowInfo; + const rowDoc = FieldValue(Cast(original, Doc)); + if (!rowDoc) return false; + + let x = ScreenToLocalTransform().transformPoint(de.x, de.y); + let rect = this._header!.current!.getBoundingClientRect(); + let bounds = ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); + let before = x[1] < bounds[1]; + if (de.data instanceof DragManager.DocumentDragData) { + e.stopPropagation(); + if (de.data.draggedDocuments[0] === rowDoc) return true; + let addDocument = (doc: Doc) => addDoc(doc, rowDoc, before); + let movedDocs = de.data.draggedDocuments; //(de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments); + return (de.data.dropAction || de.data.userDropAction) ? + de.data.droppedDocuments.reduce((added: boolean, d) => addDoc(d, rowDoc, before) || added, false) + : (de.data.moveDocument) ? + movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false) + : de.data.droppedDocuments.reduce((added: boolean, d) => addDoc(d, rowDoc, before), false); + } + return false; + } + + render() { + const { children = null, rowInfo } = this.props; + if (!rowInfo) { + console.log("no rowinfo"); + return {children}; + } + + const { original } = rowInfo; + const doc = FieldValue(Cast(original, Doc)); + if (!doc) return <>; + + let reference = React.createRef(); + let onItemDown = SetupDrag(reference, () => doc, moveDoc); + + return ( +
+
+
+ + {children} + +
+
+
+ ); + } + }; +} + diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 4bc7a778c..fce1c8833 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -105,6 +105,14 @@ direction: ltr; max-height: $MAX_ROW_HEIGHT; + &:nth-child(even) { + background-color: $light-color; + } + + &:nth-child(odd) { + background-color: $light-color-secondary; + } + &:last-child { border-bottom: $intermediate-color; border-bottom-style: solid; @@ -112,6 +120,10 @@ } } + .rt-tr { + width: 100%; + } + .rt-td { border-width: 1px; border-right-color: $intermediate-color; @@ -149,6 +161,18 @@ background: $light-color; } +.collectionSchema-column-header { + height: 100%; + background-color: green; + + &.col-before { + border-left: 2px solid red; + } + &.col-after { + border-right: 2px solid red; + } +} + .collectionSchemaView-header { height: 100%; @@ -168,16 +192,8 @@ } .collectionSchema-header-menuOptions { - // position: absolute; - // top: 30px; - // left: 50%; - // transform: translateX(-50%); - // z-index: 9999; - // background-color: $light-color-secondary; color: black; - // border: 1px solid $main-accent; width: 175px; - // padding: 10px; text-align: left; .collectionSchema-headerMenu-group { @@ -235,15 +251,51 @@ } } -#preview-schema-checkbox-div { - margin-left: 20px; - font-size: 12px; +.collectionSchema-row { + height: $MAX_ROW_HEIGHT; + // display: flex; + + .row-dragger { + height: $MAX_ROW_HEIGHT; + } + + .collectionSchema-row-wrapper { + max-height: $MAX_ROW_HEIGHT; + // width: 100%; + // border: 1px solid lightgray; + + &.row-above { + border-top: 1px solid red; + } + &.row-below { + border-bottom: 1px solid red; + } + &.row-inside { + border: 1px solid red; + } + } } -.-even { - background: $light-color !important; + +.collectionSchemaView-cellWrapper { + // height: $MAX_ROW_HEIGHT; + // background-color: red; + height: 100%; + padding: 4px; + + &.focused { + // background-color: yellowgreen; + border: 2px solid yellowgreen; + + input { + outline: 0; + border: none; + background-color: yellow; + } + } } -.-odd { - background: $light-color-secondary !important; +#preview-schema-checkbox-div { + margin-left: 20px; + font-size: 12px; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 3ef58bcaf..4746e637b 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -4,7 +4,7 @@ import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; -import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, TableCellRenderer } from "react-table"; +import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, TableCellRenderer, Column } from "react-table"; import "react-table/react-table.css"; import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils"; import { Doc, DocListCast, DocListCastAsync, Field, FieldResult } from "../../../new_fields/Doc"; @@ -33,12 +33,14 @@ import { undoBatch } from "../../util/UndoManager"; import { timesSeries } from "async"; import { CollectionSchemaHeader, CollectionSchemaAddColumnHeader } from "./CollectionSchemaHeaders"; import { CellProps, CollectionSchemaCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaBooleanCell, CollectionSchemaCheckboxCell } from "./CollectionSchemaCells"; - +import { MovableColumn, MovableRow } from "./CollectionSchemaMovableTableHOC"; library.add(faCog); library.add(faPlus); // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 +// const MovableTable = CollectionSchemaMovableSchemaHOC(ReactTable); + export enum ColumnType { Any, Number, @@ -54,22 +56,6 @@ const columnTypes: Map = new Map([ ["page", ColumnType.Number], ["curPage", ColumnType.Number], ["libraryBrush", ColumnType.Boolean], ["zIndex", ColumnType.Number] ]); -// @observer -// class KeyToggle extends React.Component<{ keyName: string, checked: boolean, toggle: (key: string) => void }> { -// constructor(props: any) { -// super(props); -// } - -// render() { -// return ( -//
-// this.props.toggle(this.props.keyName)} /> -// {this.props.keyName} -//
-// ); -// } -// } - @observer export class CollectionSchemaView extends CollectionSubView(doc => doc) { private _mainCont?: HTMLDivElement; @@ -83,6 +69,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @observable _newKeyName: string = ""; @observable previewScript: string = ""; @observable _headerIsEditing: boolean = false; + @observable _cellIsEditing: boolean = false; + @observable _focusedCell: {row: number, col: number} = {row: 0, col: 0}; @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); } @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; } @@ -90,10 +78,25 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get columns() { return Cast(this.props.Document.schemaColumns, listSpec("string"), []); } set columns(columns: string[]) { this.props.Document.schemaColumns = new List(columns); } @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } - @computed get tableColumns() { + @computed get tableColumns(): Column[] { let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1); let cols = this.columns.map(col => { + let focusedRow = this._focusedCell.row; + let focusedCol = this._focusedCell.col; + let isEditable = !this._headerIsEditing; + let header = ; + return { Header: doc) { deleteColumn={this.deleteColumn} setColumnType={this.setColumnType} />, + // Header: , accessor: (doc: Doc) => doc ? doc[col] : 0, id: col, Cell: (rowProps: CellInfo) => { let row = rowProps.index; let column = this.columns.indexOf(rowProps.column.id!); - // let isFocused = focusedRow === row && focusedCol === column; - let isFocused = false; + let isFocused = focusedRow === row && focusedCol === column; let props: CellProps = { row: row, col: column, rowProps: rowProps, isFocused: isFocused, - changeFocusedCellByDirection: action(emptyFunction),//this.changeFocusedCellByDirection, - changeFocusedCellByIndex: action(emptyFunction), //this.changeFocusedCellByIndex, + changeFocusedCellByDirection: this.changeFocusedCellByDirection, + 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, moveDocument: this.props.moveDocument, - setIsEditing: action(emptyFunction), //this.setCellIsEditing, - isEditable: true //isEditable + setIsEditing: this.setCellIsEditing, + isEditable: isEditable }; let colType = this.getColumnType(col); - if (colType === ColumnType.Number) return - if (colType === ColumnType.String) return - if (colType === ColumnType.Boolean) return - if (colType === ColumnType.Checkbox) return - return + if (colType === ColumnType.Number) return ; + if (colType === ColumnType.String) return ; + if (colType === ColumnType.Boolean) return ; + if (colType === ColumnType.Checkbox) return ; + return ; } }; }) as {Header: TableCellRenderer, accessor: (doc: Doc) => FieldResult, id: string, Cell: (rowProps: CellInfo) => JSX.Element}[]; @@ -156,6 +159,19 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return cols; } + reorderColumns(toMove: string, relativeTo: string, before: boolean, columnsValues: string[]) { + let columns = [...columnsValues]; + let oldIndex = columns.indexOf(toMove); + let relIndex = columns.indexOf(relativeTo); + let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex; + + if (oldIndex === newIndex) return; + + columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]); + this.columns = columns; + } + + onHeaderDrag = (columnName: string) => { let schemaDoc = Cast(this.props.Document.schemaDoc, Doc); if (schemaDoc instanceof Doc) { @@ -170,12 +186,21 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return this.props.Document; } + componentDidMount() { + document.addEventListener("keydown", this.onKeyDown); + } + + componentWillUnmount() { + document.removeEventListener("keydown", this.onKeyDown); + } + private getTrProps: ComponentPropsGetterR = (state, rowInfo) => { const that = this; if (!rowInfo) { return {}; } return { + rowInfo, onClick: action((e: React.MouseEvent, handleOriginal: Function) => { that.props.select(e.ctrlKey); that._selectedIndex = rowInfo.index; @@ -195,27 +220,63 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { this._mainCont = ele; super.CreateDropTarget(ele); } + @action + changeFocusedCellByDirection = (direction: string): void => { + switch (direction) { + case "tab": + if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === this.childDocs.length) { + this._focusedCell = { row: 0, col: 0 }; + } else if (this._focusedCell.col + 1 === this.columns.length) { + this._focusedCell = { row: this._focusedCell.row + 1, col: 0 }; + } else { + this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col + 1 }; + } + break; + case "right": + this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col + 1 === this.columns.length ? this._focusedCell.col : this._focusedCell.col + 1 }; + break; + case "left": + this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col === 0 ? this._focusedCell.col : this._focusedCell.col - 1 }; + break; + case "up": + this._focusedCell = { row: this._focusedCell.row === 0 ? this._focusedCell.row : this._focusedCell.row - 1, col: this._focusedCell.col }; + break; + case "down": + this._focusedCell = { row: this._focusedCell.row + 1 === this.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col }; + break; + } + } @action - setHeaderIsEditing = (isEditing: boolean) => { - this._headerIsEditing = isEditing; + changeFocusedCellByIndex = (row: number, col: number): void => { + this._focusedCell = { row: row, col: col }; } @action - toggleKey = (key: string) => { - let list = Cast(this.props.Document.schemaColumns, listSpec("string")); - if (list === undefined) { - this.props.Document.schemaColumns = list = new List([key]); - } else { - const index = list.indexOf(key); - if (index === -1) { - list.push(key); - } else { - list.splice(index, 1); - } - } + setCellIsEditing = (isEditing: boolean): void => { + this._cellIsEditing = isEditing; } + @action + setHeaderIsEditing = (isEditing: boolean): void => { + this._headerIsEditing = isEditing; + } + + // @action + // toggleKey = (key: string) => { + // let list = Cast(this.props.Document.schemaColumns, listSpec("string")); + // if (list === undefined) { + // this.props.Document.schemaColumns = list = new List([key]); + // } else { + // const index = list.indexOf(key); + // if (index === -1) { + // list.push(key); + // } else { + // list.splice(index, 1); + // } + // } + // } + //toggles preview side-panel of schema @action toggleExpander = () => { @@ -262,6 +323,13 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } } + onKeyDown = (e: KeyboardEvent): void => { + if (!this._cellIsEditing && !this._headerIsEditing) { + let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : ""; + this.changeFocusedCellByDirection(direction); + } + } + @action makeDB = async () => { let csv: string = this.columns.reduce((val, col) => val + col + ",", ""); @@ -410,7 +478,31 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get reactTable() { + let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before); + let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; + + // return this.columns = columns} + // numImmovableColumns={1} + // />; + + + // // let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; return doc) { // column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }} getTrProps={this.getTrProps} sortable={false} + + TrComponent={MovableRow(this.props.ScreenToLocalTransform, addDoc, moveDoc)} />; } @@ -472,6 +566,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return (
this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}> +
TESTER
{this.reactTable} {this.dividerDragger} {!this.previewWidth() ? (null) : this.previewPanel} -- cgit v1.2.3-70-g09d2 From 8a1be635352177ba05845851289d1a67b4060708 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 18 Jul 2019 19:24:58 -0400 Subject: schema cols can be moved by dragging --- src/client/util/DragManager.ts | 13 + .../CollectionSchemaMovableTableHOC.tsx | 346 +++++++++------------ .../views/collections/CollectionSchemaView.scss | 15 +- .../views/collections/CollectionSchemaView.tsx | 63 +--- 4 files changed, 175 insertions(+), 262 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 323908302..f9f6b05c0 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -288,6 +288,15 @@ export namespace DragManager { [id: string]: any; } + // for column dragging in schema view + export class ColumnDragData { + constructor(colKey: string) { + this.colKey = colKey; + } + colKey: string; + [id: string]: any; + } + export function StartLinkDrag(ele: HTMLElement, dragData: LinkDragData, downX: number, downY: number, options?: DragOptions) { StartDrag([ele], dragData, downX, downY, options); } @@ -296,6 +305,10 @@ export namespace DragManager { StartDrag([ele], dragData, downX, downY, options); } + export function StartColumnDrag(ele: HTMLElement, dragData: ColumnDragData, downX: number, downY: number, options?:DragOptions) { + StartDrag([ele], dragData, downX, downY, options); + } + export let AbortDrag: () => void = emptyFunction; function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) { diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 44a134d31..3a61881a7 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -1,111 +1,12 @@ import React = require("react"); -import { TableProps, ReactTableDefaults, Column, TableCellRenderer, ComponentPropsGetterR, ComponentPropsGetter0 } from "react-table"; -import { ComponentType, ComponentClass } from 'react'; -import { action } from "mobx"; +import { ReactTableDefaults, TableCellRenderer, ComponentPropsGetterR, ComponentPropsGetter0 } from "react-table"; import "./CollectionSchemaView.scss"; -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faBars } from '@fortawesome/free-solid-svg-icons'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Transform } from "../../util/Transform"; import { Doc } from "../../../new_fields/Doc"; import { DragManager, SetupDrag } from "../../util/DragManager"; import { SelectionManager } from "../../util/SelectionManager"; import { Cast, FieldValue } from "../../../new_fields/Types"; -library.add(faBars); - -// export interface MovableSchemaProps { -// ScreenToLocalTransform: () => Transform; -// addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean; -// moveDoc: DragManager.MoveFunction; -// columnsValues: string[]; -// columnsList: Column[]; -// setColumnsOrder: (columns: string[]) => void; -// numImmovableColumns?: number; -// } - -// export default function CollectionSchemaMovableHOC>(WrappedComponent: ComponentType): ComponentClass { -// return class CollectionSchemaMovableSchemaHOC extends React.Component { -// constructor(props: any) { -// super(props); -// } - -// reorderColumns(toMove: string, relativeTo: string, before: boolean, columnsValues: string[], setColumnsOrder: (columns: string[]) => void) { -// let columns = [...columnsValues]; -// let oldIndex = columns.indexOf(toMove); -// let relIndex = columns.indexOf(relativeTo); -// let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex; - -// if (oldIndex === newIndex) return; - -// columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]); -// setColumnsOrder(columns); -// } - -// createColumns(columnsValues: string[], columnsList: Column[], setColumnsOrder: (columnsValues: string[]) => void, ScreenToLocalTransform: () => Transform): Column[] { -// let immovableIndex = this.props.numImmovableColumns ? columnsList.length - this.props.numImmovableColumns! : columnsList.length; -// return columnsList.map((col, index) => { -// if (index >= immovableIndex) { -// return col; -// } else { -// return ({ ...col, Header: MovableColumn(col.Header, columnsValues[index], columnsValues, setColumnsOrder, this.reorderColumns, ScreenToLocalTransform) }); -// } -// }); -// } - -// render() { -// console.log("THIS IS THE RIGHT HOC"); -// const { ScreenToLocalTransform, addDoc, moveDoc, columnsValues, columnsList, setColumnsOrder, getTrProps, ...props } = this.props; -// return ( -// -// ); -// } - -// }; -// } -// //TrComponent={MovableRow(ScreenToLocalTransform, addDoc, moveDoc)} -// //columns={this.createColumns(columnsValues, columnsList, setColumnsOrder, ScreenToLocalTransform)} - -// export function MovableSchemaHOC>(WrappedComponent: ComponentType): ComponentClass { -// return class MovableSchemaHOC extends React.Component { -// constructor(props: any) { -// super(props); -// } - -// createColumns(columnsValues: string[], columnsList: Column[], setColumnsOrder: (columnsValues: string[]) => void, ScreenToLocalTransform: () => Transform): Column[] { -// let immovableIndex = this.props.numImmovableColumns ? columnsList.length - this.props.numImmovableColumns! : columnsList.length; -// return columnsList.map((col, index) => { -// if (index >= immovableIndex) { -// return col; -// } else { -// return ({ ...col, Header: MovableColumn(col.Header, columnsValues[index], columnsValues, setColumnsOrder, this.reorderColumns, ScreenToLocalTransform) }); -// } -// }); -// } - -// reorderColumns(toMove: string, relativeTo: string, before: boolean, columnsValues: string[], setColumnsOrder: (columns: string[]) => void) { -// let columns = [...columnsValues]; -// let oldIndex = columns.indexOf(toMove); -// let relIndex = columns.indexOf(relativeTo); -// let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex; - -// if (oldIndex === newIndex) return; - -// columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]); -// setColumnsOrder(columns); -// } - -// render() { -// const { ScreenToLocalTransform, addDoc, moveDoc, columnsValues, columnsList, setColumnsOrder, getTrProps, ...props } = this.props; -// return ( -// -// ); -// } -// }; -// } - - - export interface MovableColumnProps { columnRenderer: TableCellRenderer; @@ -115,147 +16,178 @@ export interface MovableColumnProps { ScreenToLocalTransform: () => Transform; } export class MovableColumn extends React.Component { - // private _ref: React.RefObject = React.createRef(); + private _header?: React.RefObject = React.createRef(); + private _colDropDisposer?: DragManager.DragDropDisposer; - onDragStart = (e: React.DragEvent, ref: React.RefObject): void => { - console.log("drag start"); - e.dataTransfer.setData("column", this.props.columnValue); + onPointerEnter = (e: React.PointerEvent): void => { + if (e.buttons === 1 && SelectionManager.GetIsDragging()) { + this._header!.current!.className = "collectionSchema-col-wrapper"; + document.addEventListener("pointermove", this.onDragMove, true); + } } - - onDragOver = (e: React.DragEvent,ref: React.RefObject): void => { - console.log("drag over"); + onPointerLeave = (e: React.PointerEvent): void => { + this._header!.current!.className = "collectionSchema-col-wrapper"; + document.removeEventListener("pointermove", this.onDragMove, true); + } + onDragMove = (e: PointerEvent): void => { let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); - let rect = ref.current!.getBoundingClientRect(); + let rect = this._header!.current!.getBoundingClientRect(); let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + ((rect.right - rect.left) / 2), rect.top); let before = x[0] < bounds[0]; - - ref.current!.className = "collectionSchema-column-header"; - if (before) ref.current!.className += " col-before"; - if (!before) ref.current!.className += " col-after"; - // e.stopPropagation(); + this._header!.current!.className = "collectionSchema-col-wrapper"; + if (before) this._header!.current!.className += " col-before"; + if (!before) this._header!.current!.className += " col-after"; + e.stopPropagation(); } - onDragLeave = (e: React.DragEvent, ref: React.RefObject): void => { - console.log("drag leave"); - ref.current!.className = "collectionSchema-column-header"; - e.stopPropagation(); + createColDropTarget = (ele: HTMLDivElement) => { + this._colDropDisposer && this._colDropDisposer(); + if (ele) { + this._colDropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.colDrop.bind(this) } }); + } } - onDrop = (e: React.DragEvent,ref: React.RefObject): void => { - console.log("on drop"); - // TODO: get column being dropped and before/after - let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); - let rect = ref.current!.getBoundingClientRect(); + colDrop = (e: Event, de: DragManager.DropEvent) => { + document.removeEventListener("pointermove", this.onDragMove, true); + let x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y); + let rect = this._header!.current!.getBoundingClientRect(); let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + ((rect.right - rect.left) / 2), rect.top); let before = x[0] < bounds[0]; + if (de.data instanceof DragManager.ColumnDragData) { + this.props.reorderColumns(de.data.colKey, this.props.columnValue, before, this.props.allColumns); + return true; + } + return false; + } - this.props.reorderColumns(e.dataTransfer.getData("column"), this.props.columnValue, before, this.props.allColumns); - ref.current!.className = "collectionSchema-column-header"; + setupDrag (ref: React.RefObject) { + let onRowMove = (e: PointerEvent) => { + e.stopPropagation(); + e.preventDefault(); + + document.removeEventListener("pointermove", onRowMove); + document.removeEventListener('pointerup', onRowUp); + let dragData = new DragManager.ColumnDragData(this.props.columnValue); + DragManager.StartColumnDrag(ref.current!, dragData, e.x, e.y); + }; + let onRowUp = (): void => { + document.removeEventListener("pointermove", onRowMove); + document.removeEventListener('pointerup', onRowUp); + }; + let onItemDown = (e: React.PointerEvent) => { + if (e.button === 0) { + e.stopPropagation(); + document.addEventListener("pointermove", onRowMove); + document.addEventListener("pointerup", onRowUp); + } + }; + return onItemDown; } + render() { - let ref: React.RefObject = React.createRef(); + let reference = React.createRef(); + let onItemDown = this.setupDrag(reference); + return ( -
console.log("pointer down")} onPointerEnter={() => console.log("pointer enter")} onPointerOut={() => console.log("pointer exit")} - onDragStart={e => this.onDragStart(e, ref)} onDragOver={e => this.onDragOver(e, ref)} onDragLeave={e => this.onDragLeave(e, ref)} onDrop={e => this.onDrop(e, ref)}> - {this.props.columnRenderer} +
+
+
+ {this.props.columnRenderer} +
+
); } } -// export function MovableColumn(columnRenderer: TableCellRenderer, columnValue: string, allColumns: string[], -// reorderColumns: (toMove: string, relativeTo: string, before: boolean, columns: string[]) => void, -// ScreenToLocalTransform: () => Transform) { -// return ; -// } +export interface MovableRowProps { + ScreenToLocalTransform: () => Transform; + addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean; + moveDoc: DragManager.MoveFunction; +} -export function MovableRow(ScreenToLocalTransform: () => Transform, addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean, moveDoc: DragManager.MoveFunction) { - return class MovableRow extends React.Component { - private _header?: React.RefObject = React.createRef(); - private _treedropDisposer?: DragManager.DragDropDisposer; +export class MovableRow extends React.Component { + private _header?: React.RefObject = React.createRef(); + private _rowDropDisposer?: DragManager.DragDropDisposer; - onPointerEnter = (e: React.PointerEvent): void => { - if (e.buttons === 1 && SelectionManager.GetIsDragging()) { - this._header!.current!.className = "collectionSchema-row-wrapper"; - document.addEventListener("pointermove", this.onDragMove, true); - } - } - onPointerLeave = (e: React.PointerEvent): void => { - this._header!.current!.className = "collectionSchema-row-wrapper"; - document.removeEventListener("pointermove", this.onDragMove, true); - } - onDragMove = (e: PointerEvent): void => { - let x = ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); - let rect = this._header!.current!.getBoundingClientRect(); - let bounds = ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); - let before = x[1] < bounds[1]; + onPointerEnter = (e: React.PointerEvent): void => { + if (e.buttons === 1 && SelectionManager.GetIsDragging()) { this._header!.current!.className = "collectionSchema-row-wrapper"; - if (before) this._header!.current!.className += " row-above"; - if (!before) this._header!.current!.className += " row-below"; - e.stopPropagation(); + document.addEventListener("pointermove", this.onDragMove, true); } + } + onPointerLeave = (e: React.PointerEvent): void => { + this._header!.current!.className = "collectionSchema-row-wrapper"; + document.removeEventListener("pointermove", this.onDragMove, true); + } + onDragMove = (e: PointerEvent): void => { + let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); + let rect = this._header!.current!.getBoundingClientRect(); + let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); + let before = x[1] < bounds[1]; + this._header!.current!.className = "collectionSchema-row-wrapper"; + if (before) this._header!.current!.className += " row-above"; + if (!before) this._header!.current!.className += " row-below"; + e.stopPropagation(); + } - createTreeDropTarget = (ele: HTMLDivElement) => { - this._treedropDisposer && this._treedropDisposer(); - if (ele) { - this._treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.treeDrop.bind(this) } }); - } + createRowDropTarget = (ele: HTMLDivElement) => { + this._rowDropDisposer && this._rowDropDisposer(); + if (ele) { + this._rowDropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.rowDrop.bind(this) } }); } + } - treeDrop = (e: Event, de: DragManager.DropEvent) => { - const { children = null, rowInfo } = this.props; - if (!rowInfo) return false; + rowDrop = (e: Event, de: DragManager.DropEvent) => { + const { children = null, rowInfo } = this.props; + if (!rowInfo) return false; - const { original } = rowInfo; - const rowDoc = FieldValue(Cast(original, Doc)); - if (!rowDoc) return false; + const { original } = rowInfo; + const rowDoc = FieldValue(Cast(original, Doc)); + if (!rowDoc) return false; - let x = ScreenToLocalTransform().transformPoint(de.x, de.y); - let rect = this._header!.current!.getBoundingClientRect(); - let bounds = ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); - let before = x[1] < bounds[1]; - if (de.data instanceof DragManager.DocumentDragData) { - e.stopPropagation(); - if (de.data.draggedDocuments[0] === rowDoc) return true; - let addDocument = (doc: Doc) => addDoc(doc, rowDoc, before); - let movedDocs = de.data.draggedDocuments; //(de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments); - return (de.data.dropAction || de.data.userDropAction) ? - de.data.droppedDocuments.reduce((added: boolean, d) => addDoc(d, rowDoc, before) || added, false) - : (de.data.moveDocument) ? - movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false) - : de.data.droppedDocuments.reduce((added: boolean, d) => addDoc(d, rowDoc, before), false); - } - return false; + let x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y); + let rect = this._header!.current!.getBoundingClientRect(); + let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); + let before = x[1] < bounds[1]; + if (de.data instanceof DragManager.DocumentDragData) { + e.stopPropagation(); + if (de.data.draggedDocuments[0] === rowDoc) return true; + let addDocument = (doc: Doc) => this.props.addDoc(doc, rowDoc, before); + let movedDocs = de.data.draggedDocuments; //(de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments); + return (de.data.dropAction || de.data.userDropAction) ? + de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false) + : (de.data.moveDocument) ? + movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false) + : de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before), false); } + return false; + } - render() { - const { children = null, rowInfo } = this.props; - if (!rowInfo) { - console.log("no rowinfo"); - return {children}; - } + render() { + const { children = null, rowInfo } = this.props; + if (!rowInfo) { + return {children}; + } - const { original } = rowInfo; - const doc = FieldValue(Cast(original, Doc)); - if (!doc) return <>; + const { original } = rowInfo; + const doc = FieldValue(Cast(original, Doc)); + if (!doc) return <>; - let reference = React.createRef(); - let onItemDown = SetupDrag(reference, () => doc, moveDoc); + let reference = React.createRef(); + let onItemDown = SetupDrag(reference, () => doc, this.props.moveDoc); - return ( -
-
-
- - {children} - -
+ return ( +
+
+
+ + {children} +
- ); - } - }; -} - +
+ ); + } +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index fce1c8833..15dec4e44 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -161,18 +161,21 @@ background: $light-color; } -.collectionSchema-column-header { +.collectionSchema-col{ height: 100%; background-color: green; - &.col-before { - border-left: 2px solid red; - } - &.col-after { - border-right: 2px solid red; + .collectionSchema-col-wrapper { + &.col-before { + border-left: 2px solid red; + } + &.col-after { + border-right: 2px solid red; + } } } + .collectionSchemaView-header { height: 100%; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 4746e637b..b9b299e13 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -62,7 +62,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { private _startPreviewWidth = 0; private DIVIDER_WIDTH = 4; - @observable _columns: Array = ["title", "data", "author"]; + // @observable _columns: Array = ["title", "data", "author"]; @observable _selectedIndex = 0; @observable _columnsPercentage = 0; @observable _keys: string[] = []; @@ -76,7 +76,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; } @computed get tableWidth() { return this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH - this.previewWidth(); } @computed get columns() { return Cast(this.props.Document.schemaColumns, listSpec("string"), []); } - set columns(columns: string[]) { this.props.Document.schemaColumns = new List(columns); } + set columns(columns: string[]) {this.props.Document.schemaColumns = new List(columns); } @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } @computed get tableColumns(): Column[] { let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1); @@ -98,18 +98,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { />; return { - Header: , - // Header: , + Header: , accessor: (doc: Doc) => doc ? doc[col] : 0, id: col, Cell: (rowProps: CellInfo) => { @@ -159,7 +148,12 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return cols; } - reorderColumns(toMove: string, relativeTo: string, before: boolean, columnsValues: string[]) { + @action + setColumns = (columns: string[]) => { + this.columns = columns; + } + + reorderColumns = (toMove: string, relativeTo: string, before: boolean, columnsValues: string[]) => { let columns = [...columnsValues]; let oldIndex = columns.indexOf(toMove); let relIndex = columns.indexOf(relativeTo); @@ -168,7 +162,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { if (oldIndex === newIndex) return; columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]); - this.columns = columns; + this.setColumns(columns); } @@ -200,6 +194,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return {}; } return { + ScreenToLocalTransform: this.props.ScreenToLocalTransform, + addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before), + moveDoc: (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc), rowInfo, onClick: action((e: React.MouseEvent, handleOriginal: Function) => { that.props.select(e.ctrlKey); @@ -209,10 +206,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { handleOriginal(); } }), - style: { - background: rowInfo.index === this._selectedIndex ? "lightGray" : "white", - //color: rowInfo.index === this._selectedIndex ? "white" : "black" - } }; } @@ -401,7 +394,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { let newTypesDoc = new Doc(); newTypesDoc[key] = type; this.props.Document.schemaColumnTypes = newTypesDoc; - console.log("no typesDoc"); return; } else { typesDoc[key] = type; @@ -478,31 +470,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get reactTable() { - let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before); - let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; - - // return this.columns = columns} - // numImmovableColumns={1} - // />; - - - // // let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; return doc) { pageSize={this.childDocs.length} showPagination={false} columns={this.tableColumns} - // column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }} getTrProps={this.getTrProps} sortable={false} - - TrComponent={MovableRow(this.props.ScreenToLocalTransform, addDoc, moveDoc)} + TrComponent={MovableRow} />; } @@ -566,7 +532,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return (
this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}> -
TESTER
{this.reactTable} {this.dividerDragger} {!this.previewWidth() ? (null) : this.previewPanel} -- cgit v1.2.3-70-g09d2 From ae51e87874a714fdb46d4093fee513787b413ed8 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Fri, 19 Jul 2019 13:11:10 -0400 Subject: can sort columns by asc, desc --- src/client/views/EditableView.tsx | 12 +- .../views/collections/CollectionSchemaCells.tsx | 2 +- .../views/collections/CollectionSchemaHeaders.tsx | 90 ++++++--- .../views/collections/CollectionSchemaView.scss | 1 - .../views/collections/CollectionSchemaView.tsx | 204 ++++++++------------- 5 files changed, 159 insertions(+), 150 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 989fb1be9..42faedf9d 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -31,6 +31,7 @@ export interface EditableProps { oneLine?: boolean; editing?: boolean; onClick?: (e: React.MouseEvent) => boolean; + isEditingCallback?: (isEditing: boolean) => void; } /** @@ -47,6 +48,11 @@ export class EditableView extends React.Component { this._editing = this.props.editing ? true : false; } + @action + componentWillReceiveProps(nextProps: EditableProps) { + this._editing = nextProps.editing ? true : false; + } + @action onKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Tab") { @@ -55,13 +61,16 @@ export class EditableView extends React.Component { if (!e.ctrlKey) { if (this.props.SetValue(e.currentTarget.value, e.shiftKey)) { this._editing = false; + this.props.isEditingCallback && this.props.isEditingCallback(false); } } else if (this.props.OnFillDown) { this.props.OnFillDown(e.currentTarget.value); this._editing = false; + this.props.isEditingCallback && this.props.isEditingCallback(false); } } else if (e.key === "Escape") { this._editing = false; + this.props.isEditingCallback && this.props.isEditingCallback(false); } } @@ -69,6 +78,7 @@ export class EditableView extends React.Component { onClick = (e: React.MouseEvent) => { if (!this.props.onClick || !this.props.onClick(e)) { this._editing = true; + this.props.isEditingCallback && this.props.isEditingCallback(true); } e.stopPropagation(); } @@ -85,7 +95,7 @@ export class EditableView extends React.Component { render() { if (this._editing) { return this._editing = false)} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation} + onBlur={action(() => {this._editing = false; this.props.isEditingCallback && this.props.isEditingCallback(false);})} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation} style={{ display: this.props.display, fontSize: this.props.fontSize }} />; } else { return ( diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 51e9016b7..5b40032eb 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -125,7 +125,7 @@ export class CollectionSchemaCell extends React.Component {
void; deleteColumn: (column: string) => void; setColumnType: (key: string, type: ColumnType) => void; + setColumnSort: (key: string, desc: boolean) => void; + removeColumnSort: (key: string) => void; } export class CollectionSchemaHeader extends React.Component { @@ -43,6 +45,8 @@ export class CollectionSchemaHeader extends React.Component { deleteColumn={this.props.deleteColumn} onlyShowOptions={false} setColumnType={this.props.setColumnType} + setColumnSort={this.props.setColumnSort} + removeColumnSort={this.props.removeColumnSort} />
); @@ -59,18 +63,10 @@ export interface AddColumnHeaderProps { @observer export class CollectionSchemaAddColumnHeader extends React.Component { - // @observable private _creatingColumn: boolean = false; - - // @action - // onClick = (e: React.MouseEvent): void => { - // this._creatingColumn = true; - // } - render() { let addButton = ; return (
- {/* {this._creatingColumn ? <> : */}
); @@ -105,12 +103,38 @@ export interface ColumnMenuProps { deleteColumn: (column: string) => void; onlyShowOptions: boolean; setColumnType: (key: string, type: ColumnType) => void; + setColumnSort: (key: string, desc: boolean) => void; + removeColumnSort: (key: string) => void; } @observer export class CollectionSchemaColumnMenu extends React.Component { @observable private _isOpen: boolean = false; + // @observable private _node : HTMLDivElement | null = null; + @observable private _node = React.createRef(); - @action toggleIsOpen = (): void => { + componentDidMount() { + document.addEventListener("pointerdown", this.onPointerDown); + console.log("did mount", this._node); + } + + componentWillUnmount() { + document.removeEventListener("pointerdown", this.onPointerDown); + } + + onPointerDown (e: PointerEvent) { + console.log("pointer down", this._node); + if (this._node ) { + // && this._node.contains(e.target as Node) + console.log("CLICKED INSNIDE"); + } else { + console.log("CLICKED OUTSIDE"); + // console.log(this._node); + // console.log(e.target as Node); + } + } + + @action + toggleIsOpen = (): void => { this._isOpen = !this._isOpen; this.props.setIsEditing(this._isOpen); } @@ -121,6 +145,14 @@ export class CollectionSchemaColumnMenu extends React.Component this.props.setColumnType(this.props.keyValue, type); } + // @action + // setNode = (node: HTMLDivElement): void => { + // if (node) { + // this._node = node; + // console.log("set node to ", this._node); + // } + // } + renderTypes = () => { if (this.props.typeConst) return <>; return ( @@ -147,6 +179,19 @@ export class CollectionSchemaColumnMenu extends React.Component ); } + renderSorting = () => { + return ( +
+ +
+
this.props.setColumnSort(this.props.keyValue, false)}>Sort ascending
+
this.props.setColumnSort(this.props.keyValue, true)}>Sort descending
+
this.props.removeColumnSort(this.props.keyValue)}>Clear sorting
+
+
+ ); + } + renderContent = () => { return (
@@ -159,11 +204,13 @@ export class CollectionSchemaColumnMenu extends React.Component canAddNew={true} addNew={this.props.addNew} onSelect={this.props.onSelect} + setIsEditing={this.props.setIsEditing} />
{this.props.onlyShowOptions ? <> : <> {this.renderTypes()} + {this.renderSorting()}
@@ -174,24 +221,17 @@ export class CollectionSchemaColumnMenu extends React.Component } render() { + console.log("render", this._node); return ( -
+
- {/*
*/} -
{ this.props.setIsEditing(true); }}>{this.props.menuButtonContent}
- {/* {this._isOpen ? this.renderContent() : <>} */} - {/*
*/} +
this.toggleIsOpen()}>{this.props.menuButtonContent}
); } } -{/* //
- //
this.toggleIsOpen()}>{this.props.menuButtonContent}
- // {this.renderContent()} - //
*/} - interface KeysDropdownProps { keyValue: string; @@ -200,6 +240,7 @@ interface KeysDropdownProps { canAddNew: boolean; addNew: boolean; onSelect: (oldKey: string, newKey: string, addnew: boolean) => void; + setIsEditing: (isEditing: boolean) => void; } @observer class KeysDropdown extends React.Component { @@ -217,6 +258,7 @@ class KeysDropdown extends React.Component { this.props.onSelect(this._key, key, this.props.addNew); this.setKey(key); this._isOpen = false; + this.props.setIsEditing(false); } onChange = (val: string): void => { @@ -226,15 +268,15 @@ class KeysDropdown extends React.Component { @action onFocus = (e: React.FocusEvent): void => { this._isOpen = true; + this.props.setIsEditing(true); } @action onBlur = (e: React.FocusEvent): void => { - // const that = this; - if (this._canClose) this._isOpen = false; - // setTimeout(function() { // TODO: this might be too hacky lol - // that.setIsOpen(false); - // }, 100); + if (this._canClose) { + this._isOpen = false; + this.props.setIsEditing(false); + } } @action diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 15dec4e44..4ae9628a9 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -163,7 +163,6 @@ .collectionSchema-col{ height: 100%; - background-color: green; .collectionSchema-col-wrapper { &.col-before { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index b9b299e13..10b1e895d 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -39,8 +39,6 @@ library.add(faCog); library.add(faPlus); // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 -// const MovableTable = CollectionSchemaMovableSchemaHOC(ReactTable); - export enum ColumnType { Any, Number, @@ -62,7 +60,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { private _startPreviewWidth = 0; private DIVIDER_WIDTH = 4; - // @observable _columns: Array = ["title", "data", "author"]; @observable _selectedIndex = 0; @observable _columnsPercentage = 0; @observable _keys: string[] = []; @@ -71,6 +68,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @observable _headerIsEditing: boolean = false; @observable _cellIsEditing: boolean = false; @observable _focusedCell: {row: number, col: number} = {row: 0, col: 0}; + @observable _sortedColumns: Map = new Map(); @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); } @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; } @@ -80,7 +78,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } @computed get tableColumns(): Column[] { let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1); - let cols = this.columns.map(col => { let focusedRow = this._focusedCell.row; let focusedCol = this._focusedCell.col; @@ -95,6 +92,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { setIsEditing={this.setHeaderIsEditing} deleteColumn={this.deleteColumn} setColumnType={this.setColumnType} + setColumnSort={this.setColumnSort} + removeColumnSort={this.removeColumnSort} />; return { @@ -148,37 +147,19 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return cols; } - @action - setColumns = (columns: string[]) => { - this.columns = columns; - } - - reorderColumns = (toMove: string, relativeTo: string, before: boolean, columnsValues: string[]) => { - let columns = [...columnsValues]; - let oldIndex = columns.indexOf(toMove); - let relIndex = columns.indexOf(relativeTo); - let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex; - - if (oldIndex === newIndex) return; - - columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]); - this.setColumns(columns); - } - - - onHeaderDrag = (columnName: string) => { - let schemaDoc = Cast(this.props.Document.schemaDoc, Doc); - if (schemaDoc instanceof Doc) { - let columnDocs = DocListCast(schemaDoc.data); - if (columnDocs) { - let ddoc = columnDocs.find(doc => doc.title === columnName); - if (ddoc) { - return ddoc; - } - } - } - return this.props.Document; - } + // onHeaderDrag = (columnName: string) => { + // let schemaDoc = Cast(this.props.Document.schemaDoc, Doc); + // if (schemaDoc instanceof Doc) { + // let columnDocs = DocListCast(schemaDoc.data); + // if (columnDocs) { + // let ddoc = columnDocs.find(doc => doc.title === columnName); + // if (ddoc) { + // return ddoc; + // } + // } + // } + // return this.props.Document; + // } componentDidMount() { document.addEventListener("keydown", this.onKeyDown); @@ -213,37 +194,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { this._mainCont = ele; super.CreateDropTarget(ele); } - @action - changeFocusedCellByDirection = (direction: string): void => { - switch (direction) { - case "tab": - if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === this.childDocs.length) { - this._focusedCell = { row: 0, col: 0 }; - } else if (this._focusedCell.col + 1 === this.columns.length) { - this._focusedCell = { row: this._focusedCell.row + 1, col: 0 }; - } else { - this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col + 1 }; - } - break; - case "right": - this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col + 1 === this.columns.length ? this._focusedCell.col : this._focusedCell.col + 1 }; - break; - case "left": - this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col === 0 ? this._focusedCell.col : this._focusedCell.col - 1 }; - break; - case "up": - this._focusedCell = { row: this._focusedCell.row === 0 ? this._focusedCell.row : this._focusedCell.row - 1, col: this._focusedCell.col }; - break; - case "down": - this._focusedCell = { row: this._focusedCell.row + 1 === this.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col }; - break; - } - } - - @action - changeFocusedCellByIndex = (row: number, col: number): void => { - this._focusedCell = { row: row, col: col }; - } @action setCellIsEditing = (isEditing: boolean): void => { @@ -255,21 +205,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { this._headerIsEditing = isEditing; } - // @action - // toggleKey = (key: string) => { - // let list = Cast(this.props.Document.schemaColumns, listSpec("string")); - // if (list === undefined) { - // this.props.Document.schemaColumns = list = new List([key]); - // } else { - // const index = list.indexOf(key); - // if (index === -1) { - // list.push(key); - // } else { - // list.splice(index, 1); - // } - // } - // } - //toggles preview side-panel of schema @action toggleExpander = () => { @@ -323,6 +258,38 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } } + @action + changeFocusedCellByDirection = (direction: string): void => { + switch (direction) { + case "tab": + if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === this.childDocs.length) { + this._focusedCell = { row: 0, col: 0 }; + } else if (this._focusedCell.col + 1 === this.columns.length) { + this._focusedCell = { row: this._focusedCell.row + 1, col: 0 }; + } else { + this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col + 1 }; + } + break; + case "right": + this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col + 1 === this.columns.length ? this._focusedCell.col : this._focusedCell.col + 1 }; + break; + case "left": + this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col === 0 ? this._focusedCell.col : this._focusedCell.col - 1 }; + break; + case "up": + this._focusedCell = { row: this._focusedCell.row === 0 ? this._focusedCell.row : this._focusedCell.row - 1, col: this._focusedCell.col }; + break; + case "down": + this._focusedCell = { row: this._focusedCell.row + 1 === this.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col }; + break; + } + } + + @action + changeFocusedCellByIndex = (row: number, col: number): void => { + this._focusedCell = { row: row, col: col }; + } + @action makeDB = async () => { let csv: string = this.columns.reduce((val, col) => val + col + ",", ""); @@ -400,10 +367,32 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } } - // @action - // newKeyChange = (e: React.ChangeEvent) => { - // this._newKeyName = e.currentTarget.value; - // } + @action + setColumns = (columns: string[]) => { + this.columns = columns; + } + + reorderColumns = (toMove: string, relativeTo: string, before: boolean, columnsValues: string[]) => { + let columns = [...columnsValues]; + let oldIndex = columns.indexOf(toMove); + let relIndex = columns.indexOf(relativeTo); + let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex; + + if (oldIndex === newIndex) return; + + columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]); + this.setColumns(columns); + } + + @action + setColumnSort = (column: string, descending: boolean) => { + this._sortedColumns.set(column, {id: column, desc: descending}); + } + + @action + removeColumnSort = (column: string) => { + this._sortedColumns.delete(column); + } @computed get previewDocument(): Doc | undefined { @@ -430,44 +419,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return Array.from(Object.keys(keys)); } - // get documentKeysCheckList() { - // const docs = DocListCast(this.props.Document[this.props.fieldKey]); - // let keys: { [key: string]: boolean } = {}; - // // bcz: ugh. this is untracked since otherwise a large collection of documents will blast the server for all their fields. - // // then as each document's fields come back, we update the documents _proxies. Each time we do this, the whole schema will be - // // invalidated and re-rendered. This workaround will inquire all of the document fields before the options button is clicked. - // // then by the time the options button is clicked, all of the fields should be in place. If a new field is added while this menu - // // is displayed (unlikely) it won't show up until something else changes. - // //TODO Types - // untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => keys[key] = false)))); - - // this.columns.forEach(key => keys[key] = true); - // return Array.from(Object.keys(keys)).map(item => - // ()); - // } - - // get tableOptionsPanel() { - // return !this.props.active() ? (null) : - // ( - //
Options
- //
- //
Preview Window
- //
Show Preview
- //
Displayed Columns
- //
    - // {this.documentKeysCheckList} - //
- // - // - //
- //
- // }> - // - // ); - // } - @computed get reactTable() { let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; @@ -481,6 +432,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { getTrProps={this.getTrProps} sortable={false} TrComponent={MovableRow} + sorted={Array.from(this._sortedColumns.values())} />; } @@ -614,7 +566,13 @@ export class CollectionSchemaPreview extends React.Component Show Preview
+ + let input = this.props.previewScript === undefined ? (null) :
; -- cgit v1.2.3-70-g09d2 From 17f53f604e0087615c2baff6cffa344771301b5e Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Fri, 19 Jul 2019 13:49:37 -0400 Subject: fixed nto being able to edit when column menu flyout is closed bug --- .../views/collections/CollectionSchemaHeaders.tsx | 39 +++++++++++----------- .../views/collections/CollectionSchemaView.tsx | 16 ++++++--- 2 files changed, 31 insertions(+), 24 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index 6002d64ce..316b3f0ff 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -8,6 +8,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Flyout, anchorPoints } from "../DocumentDecorations"; import { ColumnType } from "./CollectionSchemaView"; import { emptyFunction } from "../../../Utils"; +import { contains } from "typescript-collections/dist/lib/arrays"; library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn); @@ -109,27 +110,25 @@ export interface ColumnMenuProps { @observer export class CollectionSchemaColumnMenu extends React.Component { @observable private _isOpen: boolean = false; - // @observable private _node : HTMLDivElement | null = null; - @observable private _node = React.createRef(); + @observable private _node : HTMLDivElement | null = null; + // @observable private _node = React.createRef(); + @observable private _test = "test"; componentDidMount() { - document.addEventListener("pointerdown", this.onPointerDown); + document.addEventListener("pointerdown", this.detectClick); console.log("did mount", this._node); } componentWillUnmount() { - document.removeEventListener("pointerdown", this.onPointerDown); + document.removeEventListener("pointerdown", this.detectClick); } - onPointerDown (e: PointerEvent) { - console.log("pointer down", this._node); - if (this._node ) { - // && this._node.contains(e.target as Node) - console.log("CLICKED INSNIDE"); + detectClick = (e: PointerEvent): void => { + console.log("click", this); + if (this._node && this._node.contains(e.target as Node)) { } else { - console.log("CLICKED OUTSIDE"); - // console.log(this._node); - // console.log(e.target as Node); + this._isOpen = false; + this.props.setIsEditing(false); } } @@ -145,13 +144,13 @@ export class CollectionSchemaColumnMenu extends React.Component this.props.setColumnType(this.props.keyValue, type); } - // @action - // setNode = (node: HTMLDivElement): void => { - // if (node) { - // this._node = node; - // console.log("set node to ", this._node); - // } - // } + @action + setNode = (node: HTMLDivElement): void => { + if (node) { + this._node = node; + console.log("set node to ", this._node); + } + } renderTypes = () => { if (this.props.typeConst) return <>; @@ -223,7 +222,7 @@ export class CollectionSchemaColumnMenu extends React.Component render() { console.log("render", this._node); return ( -
+
this.toggleIsOpen()}>{this.props.menuButtonContent}
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 10b1e895d..ffc9d7d09 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -480,10 +480,20 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { this.previewScript = script; } + @computed + get schemaToolbar() { + return ( +
+
Show Preview
+
+ ); + } + render() { return (
this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}> + {this.schemaToolbar} {this.reactTable} {this.dividerDragger} {!this.previewWidth() ? (null) : this.previewPanel} @@ -492,6 +502,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { ); } } + + interface CollectionSchemaPreviewProps { Document?: Doc; DataDocument?: Doc; @@ -569,10 +581,6 @@ export class CollectionSchemaPreview extends React.Component Show Preview
- - let input = this.props.previewScript === undefined ? (null) :
; -- cgit v1.2.3-70-g09d2 From e1b11d49cc73ae9cfe85c5225537d681bbc976cc Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Fri, 19 Jul 2019 16:10:16 -0400 Subject: changed add col button to immediately add new column --- .../views/collections/CollectionSchemaCells.tsx | 4 +- .../views/collections/CollectionSchemaHeaders.tsx | 62 +++++++++++----------- .../views/collections/CollectionSchemaView.scss | 4 ++ .../views/collections/CollectionSchemaView.tsx | 40 ++++++++++---- 4 files changed, 67 insertions(+), 43 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 5b40032eb..0307bb83e 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -31,7 +31,7 @@ export interface CellProps { renderDepth: number; addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; - isFocused: boolean; + isFocused: boolean; changeFocusedCellByDirection: (direction: string) => void; changeFocusedCellByIndex: (row: number, col: number) => void; setIsEditing: (isEditing: boolean) => void; @@ -229,4 +229,4 @@ export class CollectionSchemaDocCell extends CollectionSchemaCell {
); } -} \ No newline at end of file +} diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index 316b3f0ff..5f8037fbf 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -29,7 +29,7 @@ export interface HeaderProps { export class CollectionSchemaHeader extends React.Component { render() { let icon: IconProp = this.props.keyType === ColumnType.Number ? "hashtag" : this.props.keyType === ColumnType.String ? "font" : - this.props.keyType === ColumnType.Checkbox ? "check-square" : this.props.keyType === ColumnType.Boolean ? "toggle-on" : "align-justify"; + this.props.keyType === ColumnType.Boolean ? "check-square" : "align-justify"; return (
@@ -56,10 +56,11 @@ export class CollectionSchemaHeader extends React.Component { export interface AddColumnHeaderProps { - possibleKeys: string[]; - existingKeys: string[]; - onSelect: (oldKey: string, newKey: string, addnew: boolean) => void; - setIsEditing: (isEditing: boolean) => void; + // possibleKeys: string[]; + // existingKeys: string[]; + // onSelect: (oldKey: string, newKey: string, addnew: boolean) => void; + // setIsEditing: (isEditing: boolean) => void; + createColumn: () => void; } @observer @@ -67,24 +68,26 @@ export class CollectionSchemaAddColumnHeader extends React.Component; return ( -
- -
+ + //
+ // + //
); } } @@ -106,6 +109,7 @@ export interface ColumnMenuProps { setColumnType: (key: string, type: ColumnType) => void; setColumnSort: (key: string, desc: boolean) => void; removeColumnSort: (key: string) => void; + anchorPoint?: any; } @observer export class CollectionSchemaColumnMenu extends React.Component { @@ -116,7 +120,6 @@ export class CollectionSchemaColumnMenu extends React.Component componentDidMount() { document.addEventListener("pointerdown", this.detectClick); - console.log("did mount", this._node); } componentWillUnmount() { @@ -124,7 +127,6 @@ export class CollectionSchemaColumnMenu extends React.Component } detectClick = (e: PointerEvent): void => { - console.log("click", this); if (this._node && this._node.contains(e.target as Node)) { } else { this._isOpen = false; @@ -148,7 +150,6 @@ export class CollectionSchemaColumnMenu extends React.Component setNode = (node: HTMLDivElement): void => { if (node) { this._node = node; - console.log("set node to ", this._node); } } @@ -167,10 +168,10 @@ export class CollectionSchemaColumnMenu extends React.Component - - */} +
@@ -220,10 +221,9 @@ export class CollectionSchemaColumnMenu extends React.Component } render() { - console.log("render", this._node); return (
- +
this.toggleIsOpen()}>{this.props.menuButtonContent}
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 4ae9628a9..47947829e 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -95,6 +95,10 @@ padding: 3px 7px; font-size: 13px; text-align: center; + + &:last-child { + overflow: visible; + } } .rt-tbody { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index ffc9d7d09..02c1ec082 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -32,7 +32,7 @@ import { CollectionView } from "./CollectionView"; import { undoBatch } from "../../util/UndoManager"; import { timesSeries } from "async"; import { CollectionSchemaHeader, CollectionSchemaAddColumnHeader } from "./CollectionSchemaHeaders"; -import { CellProps, CollectionSchemaCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaBooleanCell, CollectionSchemaCheckboxCell } from "./CollectionSchemaCells"; +import { CellProps, CollectionSchemaCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaBooleanCell, CollectionSchemaCheckboxCell, CollectionSchemaDocCell } from "./CollectionSchemaCells"; import { MovableColumn, MovableRow } from "./CollectionSchemaMovableTableHOC"; library.add(faCog); @@ -44,8 +44,8 @@ export enum ColumnType { Number, String, Boolean, - // Doc, - Checkbox + Doc, + // Checkbox } // this map should be used for keys that should have a const type of value const columnTypes: Map = new Map([ @@ -125,23 +125,28 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { let colType = this.getColumnType(col); if (colType === ColumnType.Number) return ; if (colType === ColumnType.String) return ; - if (colType === ColumnType.Boolean) return ; - if (colType === ColumnType.Checkbox) return ; + // if (colType === ColumnType.Boolean) return ; + // if (colType === ColumnType.Checkbox) return ; + if (colType === ColumnType.Boolean) return ; + if (colType === ColumnType.Doc) return ; return ; } }; - }) as {Header: TableCellRenderer, accessor: (doc: Doc) => FieldResult, id: string, Cell: (rowProps: CellInfo) => JSX.Element}[]; + }) as {Header: TableCellRenderer, accessor: (doc: Doc) => FieldResult, id: string, Cell: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean}[]; cols.push({ Header: , accessor: (doc: Doc) => 0, id: "add", Cell: (rowProps: CellInfo) => <>, + width: 45, + resizable: false }); return cols; @@ -311,6 +316,21 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } } + @action + createColumn = () => { + let index = 0; + let found = this.columns.findIndex(col => col.toUpperCase() === "New field".toUpperCase()) > -1; + if (!found) { + this.columns.push("New field"); + return; + } + while (found) { + index ++; + found = this.columns.findIndex(col => col.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1; + } + this.columns.push("New field (" + index + ")"); + } + @action addColumn = () => { this.columns.push(this._newKeyName); -- cgit v1.2.3-70-g09d2 From fa37c6f8e9947b7f536d7ff7372c9f1025a3926d Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Fri, 19 Jul 2019 17:02:17 -0400 Subject: merge --- .../views/collections/CollectionSchemaCells.tsx | 2 +- .../views/collections/CollectionSchemaView.scss | 1 + .../views/collections/CollectionSchemaView.tsx | 22 ++++++++++++++++++++-- 3 files changed, 22 insertions(+), 3 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 31a9baa11..7c82ed720 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -42,7 +42,7 @@ export interface CellProps { export class CollectionSchemaCell extends React.Component { @observable protected _isEditing: boolean = false; protected _focusRef = React.createRef(); - protected _document = this.props.rowProps.original; + protected _document: Doc = this.props.rowProps.original; componentDidMount() { if (this._focusRef.current) { diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 045994751..2134362ce 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -108,6 +108,7 @@ .rt-tr-group { direction: ltr; max-height: $MAX_ROW_HEIGHT; + // for sub comp &:nth-child(even) { background-color: $light-color; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 02c1ec082..7c7309a4a 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -4,7 +4,7 @@ import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; -import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, TableCellRenderer, Column } from "react-table"; +import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, TableCellRenderer, Column, RowInfo } from "react-table"; import "react-table/react-table.css"; import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils"; import { Doc, DocListCast, DocListCastAsync, Field, FieldResult } from "../../../new_fields/Doc"; @@ -132,7 +132,20 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return ; } }; - }) as {Header: TableCellRenderer, accessor: (doc: Doc) => FieldResult, id: string, Cell: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean}[]; + }) as {Header?: TableCellRenderer, accessor?: (doc: Doc) => FieldResult, id?: string, Cell?: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean, expander?: boolean, Expander?: (rowInfo: RowInfo) => JSX.Element | null}[]; + + cols.push({ + expander: true, + Header: "", + width: 45, + Expander: (rowInfo) => { + if (rowInfo.original.type === "collection") { + return
+
; + } else { + return null; + } + } + }); cols.push({ Header: doc) { resizable: false }); + // SubComponent={row => row.original.type === "collection" &&
SUB
} + return cols; } @@ -453,7 +468,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { sortable={false} TrComponent={MovableRow} sorted={Array.from(this._sortedColumns.values())} + SubComponent={row => row.original.type === "collection" &&
this is the sub component
} />; + + } @computed -- cgit v1.2.3-70-g09d2 From e81cf9407966612e25b944addbc8d2a08300d0bb Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Mon, 22 Jul 2019 11:38:55 -0400 Subject: editing + nav on schema only occur when that schemaview is selected --- .../views/collections/CollectionSchemaCells.tsx | 3 + .../views/collections/CollectionSchemaHeaders.tsx | 8 ++- .../views/collections/CollectionSchemaView.scss | 10 ++- .../views/collections/CollectionSchemaView.tsx | 80 ++++++++++++++-------- 4 files changed, 67 insertions(+), 34 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 91bd0453e..55185e30e 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -51,6 +51,9 @@ export class CollectionSchemaCell extends React.Component { if (this._focusRef.current) { if (this.props.isFocused) { this._focusRef.current.className += " focused"; + if (!this.props.isEditable) { + this._focusRef.current.className += " inactive"; + } } else { this._focusRef.current.className = "collectionSchemaView-cellWrapper"; } diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index df078eca5..3a57cd306 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -9,8 +9,9 @@ import { Flyout, anchorPoints } from "../DocumentDecorations"; import { ColumnType } from "./CollectionSchemaView"; import { emptyFunction } from "../../../Utils"; import { contains } from "typescript-collections/dist/lib/arrays"; +import { faFile } from "@fortawesome/free-regular-svg-icons"; -library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn); +library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faFile); export interface HeaderProps { keyValue: string; @@ -29,7 +30,7 @@ export interface HeaderProps { export class CollectionSchemaHeader extends React.Component { render() { let icon: IconProp = this.props.keyType === ColumnType.Number ? "hashtag" : this.props.keyType === ColumnType.String ? "font" : - this.props.keyType === ColumnType.Boolean ? "check-square" : "align-justify"; + this.props.keyType === ColumnType.Boolean ? "check-square" : this.props.keyType === ColumnType.Doc ? "file" : "align-justify"; return (
@@ -145,6 +146,9 @@ export class CollectionSchemaColumnMenu extends React.Component +
); diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 2134362ce..e511bc1bd 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -8,8 +8,9 @@ box-sizing: border-box; position: absolute; width: 100%; - height: 100%; - overflow: hidden; + height: calc(100% - 25px); + // overflow: hidden; + overflow-x: scroll; .collectionSchemaView-previewRegion { position: relative; @@ -304,6 +305,11 @@ border: none; background-color: yellow; } + + &.inactive { + // border: 2px solid rgba(255, 255, 0, 0.4); + border: none; + } } } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 7c7309a4a..ea09926d4 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -34,6 +34,7 @@ import { timesSeries } from "async"; import { CollectionSchemaHeader, CollectionSchemaAddColumnHeader } from "./CollectionSchemaHeaders"; import { CellProps, CollectionSchemaCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaBooleanCell, CollectionSchemaCheckboxCell, CollectionSchemaDocCell } from "./CollectionSchemaCells"; import { MovableColumn, MovableRow } from "./CollectionSchemaMovableTableHOC"; +import { SelectionManager } from "../../util/SelectionManager"; library.add(faCog); library.add(faPlus); @@ -60,7 +61,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { private _startPreviewWidth = 0; private DIVIDER_WIDTH = 4; - @observable _selectedIndex = 0; + // @observable _selectedIndex = 0; @observable _columnsPercentage = 0; @observable _keys: string[] = []; @observable _newKeyName: string = ""; @@ -69,6 +70,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @observable _cellIsEditing: boolean = false; @observable _focusedCell: {row: number, col: number} = {row: 0, col: 0}; @observable _sortedColumns: Map = new Map(); + @observable private _node : HTMLDivElement | null = null; + // @observable _schemaIsFocused: boolean = @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); } @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; } @@ -81,7 +84,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { let cols = this.columns.map(col => { let focusedRow = this._focusedCell.row; let focusedCol = this._focusedCell.col; - let isEditable = !this._headerIsEditing; + let isSelected = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0].props.Document === this.props.Document : false; + let isEditable = !this._headerIsEditing && (isSelected);// || BoolCast(this.props.Document.libraryBrush)); + console.log(BoolCast(this.props.Document.libraryBrush), isSelected); + let header = doc) { if (colType === ColumnType.Boolean) return ; if (colType === ColumnType.Doc) return ; return ; - } + }, + minWidth: 200, }; - }) as {Header?: TableCellRenderer, accessor?: (doc: Doc) => FieldResult, id?: string, Cell?: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean, expander?: boolean, Expander?: (rowInfo: RowInfo) => JSX.Element | null}[]; - - cols.push({ - expander: true, - Header: "", - width: 45, - Expander: (rowInfo) => { - if (rowInfo.original.type === "collection") { - return
+
; - } else { - return null; - } - } - }); + }) as {Header?: TableCellRenderer, accessor?: (doc: Doc) => FieldResult, id?: string, Cell?: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean, expander?: boolean, Expander?: (rowInfo: RowInfo) => JSX.Element | null, minWidth?: number}[]; + + // cols.push({ + // expander: true, + // Header: "", + // width: 45, + // Expander: (rowInfo) => { + // if (rowInfo.original.type === "collection") { + // return
+
; + // } else { + // return null; + // } + // } + // }); cols.push({ Header: doc) { // } // } // } - // return this.props.Document; + // return this.props.Document; // } componentDidMount() { @@ -199,14 +206,14 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before), moveDoc: (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc), rowInfo, - onClick: action((e: React.MouseEvent, handleOriginal: Function) => { - that.props.select(e.ctrlKey); - that._selectedIndex = rowInfo.index; - - if (handleOriginal) { - handleOriginal(); - } - }), + // onClick: action((e: React.MouseEvent, handleOriginal: Function) => { + // that.props.select(e.ctrlKey); + // that._selectedIndex = rowInfo.index; + + // if (handleOriginal) { + // handleOriginal(); + // } + // }), }; } @@ -215,6 +222,14 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { super.CreateDropTarget(ele); } + // detectClick = (e: PointerEvent): void => { + // if (this._node && this._node.contains(e.target as Node)) { + // } else { + // this._isOpen = false; + // this.props.setIsEditing(false); + // } + // } + @action setCellIsEditing = (isEditing: boolean): void => { this._cellIsEditing = isEditing; @@ -272,7 +287,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } onKeyDown = (e: KeyboardEvent): void => { - if (!this._cellIsEditing && !this._headerIsEditing) { + let isSelected = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0].props.Document === this.props.Document : false; + if (!this._cellIsEditing && !this._headerIsEditing && isSelected) { let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : ""; this.changeFocusedCellByDirection(direction); } @@ -431,7 +447,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get previewDocument(): Doc | undefined { - const selected = this.childDocs.length > this._selectedIndex ? this.childDocs[this._selectedIndex] : undefined; + let selectedIndex = this._focusedCell.row; + console.log("preview", selectedIndex); + const selected = this.childDocs.length > selectedIndex ? this.childDocs[selectedIndex] : undefined; let pdc = selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined; return pdc; } @@ -468,7 +486,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { sortable={false} TrComponent={MovableRow} sorted={Array.from(this._sortedColumns.values())} - SubComponent={row => row.original.type === "collection" &&
this is the sub component
} + // SubComponent={row => row.original.type === "collection" &&
this is the sub component
} />; @@ -529,14 +547,16 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { render() { return ( + <> + {this.schemaToolbar}
this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}> - {this.schemaToolbar} {this.reactTable} {this.dividerDragger} {!this.previewWidth() ? (null) : this.previewPanel} {/* {this.tableOptionsPanel} */}
+ ); } } -- cgit v1.2.3-70-g09d2 From 8515b6957f075f8ae7e88243ab5a4c7cb8fff3b6 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Mon, 22 Jul 2019 14:49:57 -0400 Subject: removed fixed row height --- .../views/collections/CollectionSchemaCells.tsx | 103 +++++++++++---------- .../CollectionSchemaMovableTableHOC.tsx | 5 +- .../views/collections/CollectionSchemaView.scss | 67 +++++++++----- .../views/collections/CollectionSchemaView.tsx | 45 +++++---- 4 files changed, 126 insertions(+), 94 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 55185e30e..2dd3eeff4 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -20,6 +20,7 @@ import { CollectionView } from "./CollectionView"; import { NumCast, StrCast, BoolCast, FieldValue, Cast } from "../../../new_fields/Types"; import { Docs } from "../../documents/Documents"; import { DocumentContentsView } from "../nodes/DocumentContentsView"; +import { SelectionManager } from "../../util/SelectionManager"; export interface CellProps { @@ -118,6 +119,8 @@ export class CollectionSchemaCell extends React.Component { } renderCellWithType(type: string | undefined) { + let dragRef: React.RefObject = React.createRef(); + let props: FieldViewProps = { Document: this.props.rowProps.original, DataDoc: this.props.rowProps.original, @@ -136,10 +139,19 @@ export class CollectionSchemaCell extends React.Component { PanelWidth: returnZero, addDocTab: this.props.addDocTab, }; + let onItemDown = (e: React.PointerEvent) => { SetupDrag(this._focusRef, () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document, this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument, this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e); }; + let onPointerEnter = (e: React.PointerEvent): void => { + if (e.buttons === 1 && SelectionManager.GetIsDragging() && (type === "document" || type === undefined)) { + dragRef!.current!.className = "doc-drag-over"; + } + }; + let onPointerLeave = (e: React.PointerEvent): void => { + dragRef!.current!.className = ""; + }; let field = props.Document[props.fieldKey]; let contents: any = "incorrect type"; @@ -153,40 +165,42 @@ export class CollectionSchemaCell extends React.Component { } return ( -
-
- { - let field = props.Document[props.fieldKey]; - if (Field.IsField(field)) { - return Field.toScriptString(field); +
+
+
+ { + let field = props.Document[props.fieldKey]; + if (Field.IsField(field)) { + return Field.toScriptString(field); + } + return ""; } - return ""; - } - } - SetValue={(value: string) => { - let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } }); - if (!script.compiled) { - return false; } - return this.applyToDoc(props.Document, script.run); - }} - OnFillDown={async (value: string) => { - let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } }); - if (!script.compiled) { - return; - } - const run = script.run; - //TODO This should be able to be refactored to compile the script once - const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]); - val && val.forEach(doc => this.applyToDoc(doc, run)); - }} /> -
+ SetValue={(value: string) => { + let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } }); + if (!script.compiled) { + return false; + } + return this.applyToDoc(props.Document, script.run); + }} + OnFillDown={async (value: string) => { + let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } }); + if (!script.compiled) { + return; + } + const run = script.run; + //TODO This should be able to be refactored to compile the script once + const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]); + val && val.forEach(doc => this.applyToDoc(doc, run)); + }} /> +
+
); } @@ -217,6 +231,13 @@ export class CollectionSchemaStringCell extends CollectionSchemaCell { } } +@observer +export class CollectionSchemaDocCell extends CollectionSchemaCell { + render() { + return this.renderCellWithType("document"); + } +} + @observer export class CollectionSchemaCheckboxCell extends CollectionSchemaCell { @observable private _isChecked: boolean = typeof this.props.rowProps.original[this.props.rowProps.column.id as string] === "boolean" ? BoolCast(this.props.rowProps.original[this.props.rowProps.column.id as string]) : false; @@ -245,21 +266,3 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell { ); } } - -@observer -export class CollectionSchemaDocCell extends CollectionSchemaCell { - render() { - return this.renderCellWithType("document"); - // let reference = React.createRef(); - // let onItemDown = (e: React.PointerEvent) => { - // // (!this.props.CollectionView.props.isSelected() ? undefined : - // // SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); - // }; - // return ( - //
- //
- //
- //
- // ); - } -} diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 3a61881a7..8ed71d70f 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -105,6 +105,7 @@ export interface MovableRowProps { ScreenToLocalTransform: () => Transform; addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean; moveDoc: DragManager.MoveFunction; + rowFocused: boolean; } export class MovableRow extends React.Component { @@ -178,8 +179,10 @@ export class MovableRow extends React.Component { let reference = React.createRef(); let onItemDown = SetupDrag(reference, () => doc, this.props.moveDoc); + console.log("row focused", this.props.rowFocused); + return ( -
+
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index e511bc1bd..ef93e381b 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -11,6 +11,7 @@ height: calc(100% - 25px); // overflow: hidden; overflow-x: scroll; + border: none; .collectionSchemaView-previewRegion { position: relative; @@ -70,10 +71,11 @@ .rt-thead { &.-header { - background: $intermediate-color; - color: $light-color; + // background: $intermediate-color; + // color: $light-color; font-size: 12px; height: 30px; + border: 1px solid $intermediate-color; } .rt-resizable-header { @@ -89,11 +91,14 @@ height: 100%; overflow: visible; } + + .rt-th { + padding: 0; + } } .rt-th { - max-height: $MAX_ROW_HEIGHT; - padding: 3px 7px; + // max-height: $MAX_ROW_HEIGHT; font-size: 13px; text-align: center; @@ -108,16 +113,17 @@ .rt-tr-group { direction: ltr; - max-height: $MAX_ROW_HEIGHT; + flex: 0 1 auto; + // max-height: $MAX_ROW_HEIGHT; // for sub comp - &:nth-child(even) { - background-color: $light-color; - } + // &:nth-child(even) { + // background-color: $light-color; + // } - &:nth-child(odd) { - background-color: $light-color-secondary; - } + // &:nth-child(odd) { + // background-color: $light-color-secondary; + // } &:last-child { border-bottom: $intermediate-color; @@ -128,13 +134,13 @@ .rt-tr { width: 100%; - height: $MAX_ROW_HEIGHT; + // height: $MAX_ROW_HEIGHT; } .rt-td { border-width: 1px; border-right-color: $intermediate-color; - max-height: $MAX_ROW_HEIGHT; + // max-height: $MAX_ROW_HEIGHT; padding: 0; font-size: 13px; text-align: center; @@ -184,6 +190,7 @@ .collectionSchemaView-header { height: 100%; + color: $intermediate-color; .collectionSchema-header-menu { height: 100%; @@ -223,10 +230,6 @@ position: relative; max-width: 175px; - // .keys-search { - - // } - .keys-options-wrapper { width: 100%; max-height: 150px; @@ -261,17 +264,18 @@ } .collectionSchema-row { - height: $MAX_ROW_HEIGHT; - // display: flex; + // height: $MAX_ROW_HEIGHT; + + &.row-focused { + background-color: $light-color-secondary; + } .row-dragger { - height: $MAX_ROW_HEIGHT; + // height: $MAX_ROW_HEIGHT; } .collectionSchema-row-wrapper { - max-height: $MAX_ROW_HEIGHT; - // width: 100%; - // border: 1px solid lightgray; + // max-height: $MAX_ROW_HEIGHT; &.row-above { border-top: 1px solid red; @@ -287,8 +291,6 @@ .collectionSchemaView-cellWrapper { - // height: $MAX_ROW_HEIGHT; - // background-color: red; height: 100%; padding: 4px; @@ -311,6 +313,21 @@ border: none; } } + + p { + width: 100%; + height: 100%; + word-wrap: break-word; + } +} + +.doc-drag-over { + background-color: red; +} + +.collectionSchemaView-toolbar { + display: flex; + justify-content: flex-end; } #preview-schema-checkbox-div { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index ea09926d4..a1251b028 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -81,6 +81,21 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } @computed get tableColumns(): Column[] { let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1); + let columns: Column[] = [ + { + expander: true, + Header: "", + width: 45, + Expander: (rowInfo) => { + if (rowInfo.original.type === "collection") { + return
+
; + } else { + return null; + } + } + } + ]; + let cols = this.columns.map(col => { let focusedRow = this._focusedCell.row; let focusedCol = this._focusedCell.col; @@ -139,22 +154,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { }, minWidth: 200, }; - }) as {Header?: TableCellRenderer, accessor?: (doc: Doc) => FieldResult, id?: string, Cell?: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean, expander?: boolean, Expander?: (rowInfo: RowInfo) => JSX.Element | null, minWidth?: number}[]; - - // cols.push({ - // expander: true, - // Header: "", - // width: 45, - // Expander: (rowInfo) => { - // if (rowInfo.original.type === "collection") { - // return
+
; - // } else { - // return null; - // } - // } - // }); - - cols.push({ + });// as {Header?: TableCellRenderer, accessor?: (doc: Doc) => FieldResult, id?: string, Cell?: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean, expander?: boolean, Expander?: (rowInfo: RowInfo) => JSX.Element | null, minWidth?: number}[]; + columns.push(...cols); + + columns.push({ Header: doc) { // SubComponent={row => row.original.type === "collection" &&
SUB
} - return cols; + return columns; } // onHeaderDrag = (columnName: string) => { @@ -201,11 +204,17 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { if (!rowInfo) { return {}; } + let isSelected = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0].props.Document === this.props.Document : false; return { ScreenToLocalTransform: this.props.ScreenToLocalTransform, addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before), moveDoc: (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc), rowInfo, + rowFocused: !this._headerIsEditing && isSelected && rowInfo.index === this._focusedCell.row, + // style: { + // background: rowInfo.index === this._focusedCell.row ? "lightGray" : "white", + // //color: rowInfo.index === this._selectedIndex ? "white" : "black" + // } // onClick: action((e: React.MouseEvent, handleOriginal: Function) => { // that.props.select(e.ctrlKey); // that._selectedIndex = rowInfo.index; @@ -486,7 +495,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { sortable={false} TrComponent={MovableRow} sorted={Array.from(this._sortedColumns.values())} - // SubComponent={row => row.original.type === "collection" &&
this is the sub component
} + SubComponent={row => row.original.type === "collection" &&
this is the sub component
} />; -- cgit v1.2.3-70-g09d2 From d3edc59402efb5d8ada602305a95a7a3a7f0ba95 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Mon, 22 Jul 2019 17:08:46 -0400 Subject: can have expanded collection in schema --- .../CollectionSchemaMovableTableHOC.tsx | 2 - .../views/collections/CollectionSchemaView.scss | 9 ++- .../views/collections/CollectionSchemaView.tsx | 93 ++++++++++------------ 3 files changed, 51 insertions(+), 53 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 8ed71d70f..db60e657a 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -179,8 +179,6 @@ export class MovableRow extends React.Component { let reference = React.createRef(); let onItemDown = SetupDrag(reference, () => doc, this.props.moveDoc); - console.log("row focused", this.props.rowFocused); - return (
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index ef93e381b..4b20e8241 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -6,9 +6,9 @@ border-style: solid; border-radius: $border-radius; box-sizing: border-box; - position: absolute; + // position: absolute; width: 100%; - height: calc(100% - 25px); + // height: calc(100% - 25px); // overflow: hidden; overflow-x: scroll; border: none; @@ -333,4 +333,9 @@ #preview-schema-checkbox-div { margin-left: 20px; font-size: 12px; +} + +.sub { + padding: 20px; + background-color: red; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index a1251b028..25e90a25e 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -61,7 +61,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { private _startPreviewWidth = 0; private DIVIDER_WIDTH = 4; - // @observable _selectedIndex = 0; @observable _columnsPercentage = 0; @observable _keys: string[] = []; @observable _newKeyName: string = ""; @@ -70,8 +69,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @observable _cellIsEditing: boolean = false; @observable _focusedCell: {row: number, col: number} = {row: 0, col: 0}; @observable _sortedColumns: Map = new Map(); + @observable _openCollections: Array = []; @observable private _node : HTMLDivElement | null = null; - // @observable _schemaIsFocused: boolean = @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); } @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; } @@ -81,27 +80,30 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } @computed get tableColumns(): Column[] { let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1); - let columns: Column[] = [ - { - expander: true, - Header: "", - width: 45, - Expander: (rowInfo) => { - if (rowInfo.original.type === "collection") { - return
+
; - } else { - return null; + let columns: Column[] = []; + + if (this.childDocs.reduce((found, doc) => found || doc.type === "collection", false)) { + columns.push( + { + expander: true, + Header: "", + width: 45, + Expander: (rowInfo) => { + if (rowInfo.original.type === "collection") { + if (rowInfo.isExpanded) return
this.onCloseCollection(rowInfo.original)}>-
; + if (!rowInfo.isExpanded) return
this.onExpandCollection(rowInfo.original)}>+
; + } else { + return null; + } + } } - } + ); } - ]; let cols = this.columns.map(col => { let focusedRow = this._focusedCell.row; let focusedCol = this._focusedCell.col; - let isSelected = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0].props.Document === this.props.Document : false; - let isEditable = !this._headerIsEditing && (isSelected);// || BoolCast(this.props.Document.libraryBrush)); - console.log(BoolCast(this.props.Document.libraryBrush), isSelected); + let isEditable = !this._headerIsEditing && this.props.isSelected();// || BoolCast(this.props.Document.libraryBrush)); let header = doc) { let colType = this.getColumnType(col); if (colType === ColumnType.Number) return ; if (colType === ColumnType.String) return ; - // if (colType === ColumnType.Boolean) return ; - // if (colType === ColumnType.Checkbox) return ; if (colType === ColumnType.Boolean) return ; if (colType === ColumnType.Doc) return ; return ; }, minWidth: 200, }; - });// as {Header?: TableCellRenderer, accessor?: (doc: Doc) => FieldResult, id?: string, Cell?: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean, expander?: boolean, Expander?: (rowInfo: RowInfo) => JSX.Element | null, minWidth?: number}[]; + }); columns.push(...cols); columns.push({ - Header: , + Header: , accessor: (doc: Doc) => 0, id: "add", Cell: (rowProps: CellInfo) => <>, width: 45, resizable: false }); - - // SubComponent={row => row.original.type === "collection" &&
SUB
} - return columns; } @@ -204,25 +195,12 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { if (!rowInfo) { return {}; } - let isSelected = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0].props.Document === this.props.Document : false; return { ScreenToLocalTransform: this.props.ScreenToLocalTransform, addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before), moveDoc: (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc), rowInfo, - rowFocused: !this._headerIsEditing && isSelected && rowInfo.index === this._focusedCell.row, - // style: { - // background: rowInfo.index === this._focusedCell.row ? "lightGray" : "white", - // //color: rowInfo.index === this._selectedIndex ? "white" : "black" - // } - // onClick: action((e: React.MouseEvent, handleOriginal: Function) => { - // that.props.select(e.ctrlKey); - // that._selectedIndex = rowInfo.index; - - // if (handleOriginal) { - // handleOriginal(); - // } - // }), + rowFocused: !this._headerIsEditing && this.props.isSelected() && rowInfo.index === this._focusedCell.row, }; } @@ -239,6 +217,17 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { // } // } + @action + onExpandCollection = (collection: Doc): void => { + this._openCollections.push(collection); + } + + @action + onCloseCollection = (collection: Doc): void => { + let index = this._openCollections.findIndex(col => col === collection); + if (index > -1) this._openCollections.splice(index, 1); + } + @action setCellIsEditing = (isEditing: boolean): void => { this._cellIsEditing = isEditing; @@ -296,8 +285,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } onKeyDown = (e: KeyboardEvent): void => { - let isSelected = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0].props.Document === this.props.Document : false; - if (!this._cellIsEditing && !this._headerIsEditing && isSelected) { + if (!this._cellIsEditing && !this._headerIsEditing && this.props.isSelected()) { let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : ""; this.changeFocusedCellByDirection(direction); } @@ -457,7 +445,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get previewDocument(): Doc | undefined { let selectedIndex = this._focusedCell.row; - console.log("preview", selectedIndex); const selected = this.childDocs.length > selectedIndex ? this.childDocs[selectedIndex] : undefined; let pdc = selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined; return pdc; @@ -484,6 +471,11 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get reactTable() { let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; + let hasCollectionChild = this.childDocs.reduce((found, doc) => found || doc.type === "collection", false); + let expandedRowsList = this._openCollections.map(col => this.childDocs.findIndex(doc => doc === col).toString()); + let expanded = {}; + expandedRowsList.forEach(row => expanded[row] = true); + return doc) { getTrProps={this.getTrProps} sortable={false} TrComponent={MovableRow} - sorted={Array.from(this._sortedColumns.values())} - SubComponent={row => row.original.type === "collection" &&
this is the sub component
} + sorted={Array.from(this._sortedColumns.values())} + expanded={expanded} + SubComponent={hasCollectionChild ? row => row.original.type === "collection" && +
: undefined} + />; -- cgit v1.2.3-70-g09d2 From b4ef60552f226e4022fac5092ea66f1b685bb08c Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 22 Jul 2019 18:50:26 -0400 Subject: Started adding schema functionality --- src/client/util/Scripting.ts | 50 +++++++----- src/client/views/OverlayView.scss | 2 +- src/client/views/ScriptingRepl.tsx | 59 ++++++++------ .../views/collections/CollectionSchemaView.tsx | 92 ++++++++++++++++++++-- src/client/views/collections/CollectionView.tsx | 9 ++- .../collectionFreeForm/CollectionFreeFormView.tsx | 63 +++++++-------- src/client/views/nodes/DocumentView.tsx | 23 +++--- 7 files changed, 201 insertions(+), 97 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 46dc320b0..1d0916ac0 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -52,10 +52,10 @@ export namespace Scripting { } else { throw new Error("Must either register an object with a name, or give a name and an object"); } - if (scriptingGlobals.hasOwnProperty(n)) { + if (_scriptingGlobals.hasOwnProperty(n)) { throw new Error(`Global with name ${n} is already registered, choose another name`); } - scriptingGlobals[n] = obj; + _scriptingGlobals[n] = obj; } export function makeMutableGlobalsCopy(globals?: { [name: string]: any }) { @@ -188,6 +188,10 @@ class ScriptingCompilerHost { export type Traverser = (node: ts.Node, indentation: string) => boolean | void; export type TraverserParam = Traverser | { onEnter: Traverser, onLeave: Traverser }; +export type Transformer = { + transformer: ts.TransformerFactory, + getVars?: () => { capturedVariables: { [name: string]: Field } } +}; export interface ScriptOptions { requiredType?: string; addReturn?: boolean; @@ -196,7 +200,7 @@ export interface ScriptOptions { typecheck?: boolean; editable?: boolean; traverser?: TraverserParam; - transformer?: ts.TransformerFactory; + transformer?: Transformer; globals?: { [name: string]: any }; } @@ -213,6 +217,27 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp Scripting.setScriptingGlobals(options.globals); } let host = new ScriptingCompilerHost; + if (options.traverser) { + const sourceFile = ts.createSourceFile('script.ts', script, ts.ScriptTarget.ES2015, true); + const onEnter = typeof options.traverser === "object" ? options.traverser.onEnter : options.traverser; + const onLeave = typeof options.traverser === "object" ? options.traverser.onLeave : undefined; + forEachNode(sourceFile, onEnter, onLeave); + } + if (options.transformer) { + const sourceFile = ts.createSourceFile('script.ts', script, ts.ScriptTarget.ES2015, true); + const result = ts.transform(sourceFile, [options.transformer.transformer]); + if (options.transformer.getVars) { + const newCaptures = options.transformer.getVars(); + // tslint:disable-next-line: prefer-object-spread + options.capturedVariables = Object.assign(capturedVariables, newCaptures.capturedVariables) as any; + } + const transformed = result.transformed; + const printer = ts.createPrinter({ + newLine: ts.NewLineKind.LineFeed + }); + script = printer.printFile(transformed[0]); + result.dispose(); + } let paramNames: string[] = []; if ("this" in params || "this" in capturedVariables) { paramNames.push("this"); @@ -227,26 +252,11 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp }); for (const key in capturedVariables) { if (key === "this") continue; + const val = capturedVariables[key]; paramNames.push(key); - paramList.push(`${key}: ${capturedVariables[key].constructor.name}`); + paramList.push(`${key}: ${typeof val === "object" ? Object.getPrototypeOf(val).constructor.name : typeof val}`); } let paramString = paramList.join(", "); - if (options.traverser) { - const sourceFile = ts.createSourceFile('script.ts', script, ts.ScriptTarget.ES2015, true); - const onEnter = typeof options.traverser === "object" ? options.traverser.onEnter : options.traverser; - const onLeave = typeof options.traverser === "object" ? options.traverser.onLeave : undefined; - forEachNode(sourceFile, onEnter, onLeave); - } - if (options.transformer) { - const sourceFile = ts.createSourceFile('script.ts', script, ts.ScriptTarget.ES2015, true); - const result = ts.transform(sourceFile, [options.transformer]); - const transformed = result.transformed; - const printer = ts.createPrinter({ - newLine: ts.NewLineKind.LineFeed - }); - script = printer.printFile(transformed[0]); - result.dispose(); - } let funcScript = `(function(${paramString})${requiredType ? `: ${requiredType}` : ''} { ${addReturn ? `return ${script};` : script} })`; diff --git a/src/client/views/OverlayView.scss b/src/client/views/OverlayView.scss index 4d1e8cf0b..dc122497f 100644 --- a/src/client/views/OverlayView.scss +++ b/src/client/views/OverlayView.scss @@ -32,7 +32,7 @@ } .overlayWindow-resizeDragger { - background-color: red; + background-color: rgb(0, 0, 0); position: absolute; right: 0px; bottom: 0px; diff --git a/src/client/views/ScriptingRepl.tsx b/src/client/views/ScriptingRepl.tsx index 6eabc7b70..52273c357 100644 --- a/src/client/views/ScriptingRepl.tsx +++ b/src/client/views/ScriptingRepl.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { observer } from 'mobx-react'; import { observable, action } from 'mobx'; import './ScriptingRepl.scss'; -import { Scripting, CompileScript, ts } from '../util/Scripting'; +import { Scripting, CompileScript, ts, Transformer } from '../util/Scripting'; import { DocumentManager } from '../util/DocumentManager'; import { DocumentView } from './nodes/DocumentView'; import { OverlayView } from './OverlayView'; @@ -17,8 +17,11 @@ library.add(faCaretRight); export class DocumentIcon extends React.Component<{ view: DocumentView, index: number }> { render() { this.props.view.props.ScreenToLocalTransform(); - this.props.view.props.Document.width; - this.props.view.props.Document.height; + const doc = this.props.view.props.Document; + doc.width; + doc.height; + doc.x; + doc.y; const screenCoords = this.props.view.screenRect(); return ( @@ -26,7 +29,7 @@ export class DocumentIcon extends React.Component<{ view: DocumentView, index: n position: "absolute", transform: `translate(${screenCoords.left + screenCoords.width / 2}px, ${screenCoords.top}px)`, }}> -

${this.props.index}

+

${this.props.index}

); } @@ -106,31 +109,35 @@ export class ScriptingRepl extends React.Component { private args: any = {}; - getTransformer: ts.TransformerFactory = context => { - const knownVars: { [name: string]: number } = {}; - const usedDocuments: number[] = []; - Scripting.getGlobals().forEach(global => knownVars[global] = 1); - return root => { - function visit(node: ts.Node) { - node = ts.visitEachChild(node, visit, context); + getTransformer = (): Transformer => { + return { + transformer: context => { + const knownVars: { [name: string]: number } = {}; + const usedDocuments: number[] = []; + Scripting.getGlobals().forEach(global => knownVars[global] = 1); + return root => { + function visit(node: ts.Node) { + node = ts.visitEachChild(node, visit, context); - if (ts.isIdentifier(node)) { - const isntPropAccess = !ts.isPropertyAccessExpression(node.parent) || node.parent.expression === node; - const isntPropAssign = !ts.isPropertyAssignment(node.parent) || node.parent.name !== node; - if (isntPropAccess && isntPropAssign && !(node.text in knownVars) && !(node.text in globalThis)) { - const match = node.text.match(/\$([0-9]+)/); - if (match) { - const m = parseInt(match[1]); - usedDocuments.push(m); - } else { - return ts.createPropertyAccess(ts.createIdentifier("args"), node); + if (ts.isIdentifier(node)) { + const isntPropAccess = !ts.isPropertyAccessExpression(node.parent) || node.parent.expression === node; + const isntPropAssign = !ts.isPropertyAssignment(node.parent) || node.parent.name !== node; + if (isntPropAccess && isntPropAssign && !(node.text in knownVars) && !(node.text in globalThis)) { + const match = node.text.match(/\$([0-9]+)/); + if (match) { + const m = parseInt(match[1]); + usedDocuments.push(m); + } else { + return ts.createPropertyAccess(ts.createIdentifier("args"), node); + } + } } - } - } - return node; + return node; + } + return ts.visitNode(root, visit); + }; } - return ts.visitNode(root, visit); }; } @@ -142,7 +149,7 @@ export class ScriptingRepl extends React.Component { const docGlobals: { [name: string]: any } = {}; DocumentManager.Instance.DocumentViews.forEach((dv, i) => docGlobals[`$${i}`] = dv.props.Document); const globals = Scripting.makeMutableGlobalsCopy(docGlobals); - const script = CompileScript(this.commandString, { typecheck: false, addReturn: true, editable: true, params: { args: "any" }, transformer: this.getTransformer, globals }); + const script = CompileScript(this.commandString, { typecheck: false, addReturn: true, editable: true, params: { args: "any" }, transformer: this.getTransformer(), globals }); if (!script.compiled) { return; } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index f72b1aa07..479fe2b0a 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -15,7 +15,7 @@ import { Cast, FieldValue, NumCast, StrCast, BoolCast } from "../../../new_field import { Docs } from "../../documents/Documents"; import { Gateway } from "../../northstar/manager/Gateway"; import { SetupDrag, DragManager } from "../../util/DragManager"; -import { CompileScript } from "../../util/Scripting"; +import { CompileScript, ts, Transformer } from "../../util/Scripting"; import { Transform } from "../../util/Transform"; import { COLLECTION_BORDER_WIDTH, MAX_ROW_HEIGHT } from '../../views/globalCssVariables.scss'; import { ContextMenu } from "../ContextMenu"; @@ -31,6 +31,7 @@ import { CollectionVideoView } from "./CollectionVideoView"; import { CollectionView } from "./CollectionView"; import { undoBatch } from "../../util/UndoManager"; import { timesSeries } from "async"; +import { ComputedField } from "../../../new_fields/ScriptField"; library.add(faCog); @@ -97,6 +98,78 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return this.props.Document; } + getField(row: number, col?: number) { + const docs = DocListCast(this.props.Document[this.props.fieldKey]); + row = row % docs.length; + while (row < 0) row += docs.length; + const columns = this.columns; + const doc = docs[row]; + if (col === undefined) { + return doc; + } + if (col >= 0 && col < columns.length) { + const column = this.columns[col]; + return doc[column]; + } + return undefined; + } + + createTransformer = (row: number, col: number): Transformer => { + const self = this; + const captures: { [name: string]: Field } = {}; + + const transformer: ts.TransformerFactory = context => { + return root => { + function visit(node: ts.Node) { + node = ts.visitEachChild(node, visit, context); + if (ts.isIdentifier(node)) { + const isntPropAccess = !ts.isPropertyAccessExpression(node.parent) || node.parent.expression === node; + const isntPropAssign = !ts.isPropertyAssignment(node.parent) || node.parent.name !== node; + if (isntPropAccess && isntPropAssign) { + if (node.text === "$r") { + return ts.createNumericLiteral(row.toString()); + } else if (node.text === "$c") { + return ts.createNumericLiteral(col.toString()); + } else if (node.text === "$") { + if (ts.isCallExpression(node.parent)) { + captures.doc = self.props.Document; + captures.key = self.props.fieldKey; + } + } + } + } + + return node; + } + return ts.visitNode(root, visit); + }; + }; + + const getVars = () => { + return { capturedVariables: captures }; + }; + + return { transformer, getVars }; + } + + setComputed(script: string, doc: Doc, field: string, row: number, col: number): boolean { + script = + `const $ = (row:number, col?:number) => { + if(col === undefined) { + return (doc as any)[key][row + ${row}]; + } + return (doc as any)[key][row + ${row}][(doc as any).schemaColumns[col + ${col}]]; + } + return ${script}`; + const compiled = CompileScript(script, { params: { this: Doc.name }, typecheck: true, transformer: this.createTransformer(row, col) }); + if (compiled.compiled) { + doc[field] = new ComputedField(compiled); + return true; + } + + return false; + } + renderCell = (rowProps: CellInfo) => { let props: FieldViewProps = { Document: rowProps.original, @@ -122,12 +195,13 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { (!this.props.CollectionView.props.isSelected() ? undefined : SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); }; - let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { - const res = run({ this: doc }); + let applyToDoc = (doc: Doc, row: number, column: number, run: (args?: { [name: string]: any }) => any) => { + const res = run({ this: doc, $r: row, $c: column, $: (r: number = 0, c: number = 0) => this.getField(r + row, c + column) }); if (!res.success) return false; doc[props.fieldKey] = res.result; return true; }; + const colIndex = this.columns.indexOf(rowProps.column.id!); return (
doc) { return ""; }} SetValue={(value: string) => { - let script = CompileScript(value, { addReturn: true, params: { this: Doc.name } }); + if (value.startsWith(":=")) { + return this.setComputed(value.substring(2), props.Document, rowProps.column.id!, rowProps.index, colIndex); + } + let script = CompileScript(value, { addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } }); if (!script.compiled) { return false; } - return applyToDoc(props.Document, script.run); + return applyToDoc(props.Document, rowProps.index, colIndex, script.run); }} OnFillDown={async (value: string) => { - let script = CompileScript(value, { addReturn: true, params: { this: Doc.name } }); + let script = CompileScript(value, { addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } }); if (!script.compiled) { return; } const run = script.run; - //TODO This should be able to be refactored to compile the script once const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]); - val && val.forEach(doc => applyToDoc(doc, run)); + val && val.forEach((doc, i) => applyToDoc(doc, i, colIndex, run)); }}>
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 56750668d..ae99e930b 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,5 +1,5 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faProjectDiagram, faSignature, faSquare, faTh, faThList, faTree } from '@fortawesome/free-solid-svg-icons'; +import { faProjectDiagram, faSignature, faSquare, faTh, faThList, faTree, faFingerprint, faLaptopCode } from '@fortawesome/free-solid-svg-icons'; import { observer } from "mobx-react"; import * as React from 'react'; import { Doc } from '../../../new_fields/Doc'; @@ -24,6 +24,7 @@ library.add(faSquare); library.add(faProjectDiagram); library.add(faSignature); library.add(faThList); +library.add(faFingerprint); @observer export class CollectionView extends React.Component { @@ -55,6 +56,12 @@ export class CollectionView extends React.Component { subItems.push({ description: "Schema", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Schema), icon: "th-list" }); subItems.push({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree), icon: "tree" }); subItems.push({ description: "Stacking", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Stacking), icon: "th-list" }); + switch (this.props.Document.viewType) { + case CollectionViewType.Freeform: { + subItems.push({ description: "Custom", icon: "fingerprint", event: CollectionFreeFormView.AddCustomLayout(this.props.Document, this.props.fieldKey) }); + break; + } + } ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems }); ContextMenu.Instance.addItem({ description: "Apply Template", event: undoBatch(() => { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 703873681..dd577a467 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -477,43 +477,44 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { }, "arrange contents"); } }); - ContextMenu.Instance.addItem({ - description: "Add freeform arrangement", - event: () => { - let addOverlay = (key: "arrangeScript" | "arrangeInit", options: OverlayElementOptions, params?: Record, requiredType?: string) => { - let overlayDisposer: () => void = emptyFunction; - const script = this.Document[key]; - let originalText: string | undefined = undefined; - if (script) originalText = script.script.originalScript; - // tslint:disable-next-line: no-unnecessary-callback-wrapper - let scriptingBox = overlayDisposer()} onSave={(text, onError) => { - const script = CompileScript(text, { - params, - requiredType, - typecheck: false - }); - if (!script.compiled) { - onError(script.errors.map(error => error.messageText).join("\n")); - return; - } - const docs = DocListCast(this.Document[this.props.fieldKey]); - docs.map(d => d.transition = "transform 1s"); - this.Document[key] = new ScriptField(script); - overlayDisposer(); - setTimeout(() => docs.map(d => d.transition = undefined), 1200); - }} />; - overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, options); - }; - addOverlay("arrangeInit", { x: 400, y: 100, width: 400, height: 300, title: "Layout Initialization" }, { collection: "Doc", docs: "Doc[]" }, undefined); - addOverlay("arrangeScript", { x: 400, y: 500, width: 400, height: 300, title: "Layout Script" }, { doc: "Doc", index: "number", collection: "Doc", state: "any", docs: "Doc[]" }, "{x: number, y: number, width?: number, height?: number}"); - } - }); } private childViews = () => [ , ...this.views ] + + public static AddCustomLayout(doc: Doc, dataKey: string): () => void { + return () => { + let addOverlay = (key: "arrangeScript" | "arrangeInit", options: OverlayElementOptions, params?: Record, requiredType?: string) => { + let overlayDisposer: () => void = emptyFunction; + const script = Cast(doc[key], ScriptField); + let originalText: string | undefined = undefined; + if (script) originalText = script.script.originalScript; + // tslint:disable-next-line: no-unnecessary-callback-wrapper + let scriptingBox = overlayDisposer()} onSave={(text, onError) => { + const script = CompileScript(text, { + params, + requiredType, + typecheck: false + }); + if (!script.compiled) { + onError(script.errors.map(error => error.messageText).join("\n")); + return; + } + const docs = DocListCast(doc[dataKey]); + docs.map(d => d.transition = "transform 1s"); + doc[key] = new ScriptField(script); + overlayDisposer(); + setTimeout(() => docs.map(d => d.transition = undefined), 1200); + }} />; + overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, options); + }; + addOverlay("arrangeInit", { x: 400, y: 100, width: 400, height: 300, title: "Layout Initialization" }, { collection: "Doc", docs: "Doc[]" }, undefined); + addOverlay("arrangeScript", { x: 400, y: 500, width: 400, height: 300, title: "Layout Script" }, { doc: "Doc", index: "number", collection: "Doc", state: "any", docs: "Doc[]" }, "{x: number, y: number, width?: number, height?: number}"); + }; + } + render() { const easing = () => this.props.Document.panTransformType === "Ease"; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 1c03bfc81..7280dbcf6 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -37,6 +37,7 @@ import { RouteStore } from '../../../server/RouteStore'; import { FormattedTextBox } from './FormattedTextBox'; import { OverlayView } from '../OverlayView'; import { ScriptingRepl } from '../ScriptingRepl'; +import { ClientUtils } from '../../util/ClientUtils'; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? library.add(fa.faTrash); @@ -58,6 +59,7 @@ library.add(fa.faCrosshairs); library.add(fa.faDesktop); library.add(fa.faUnlock); library.add(fa.faLock); +library.add(fa.faLaptopCode); // const linkSchema = createSchema({ @@ -551,17 +553,18 @@ export class DocumentView extends DocComponent(Docu this.props.removeDocument && this.props.removeDocument(this.props.Document); }, icon: "window-restore" }); - cm.addItem({ - description: "Find aliases", event: async () => { - const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document); - this.props.addDocTab && this.props.addDocTab(Docs.Create.SchemaDocument(["title"], aliases, {}), undefined, "onRight"); // bcz: dataDoc? - }, icon: "search" - }); - cm.addItem({ description: "Add Repl", event: () => OverlayView.Instance.addWindow(, { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" }) }); - cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document, false), icon: "crosshairs" }); + // cm.addItem({ + // description: "Find aliases", event: async () => { + // const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document); + // this.props.addDocTab && this.props.addDocTab(Docs.Create.SchemaDocument(["title"], aliases, {}), undefined, "onRight"); // bcz: dataDoc? + // }, icon: "search" + // }); + cm.addItem({ description: "Add Repl", icon: "laptop-code", event: () => OverlayView.Instance.addWindow(, { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" }) }); cm.addItem({ description: "Zoom to Document", event: () => this.props.focus(this.props.Document, true), icon: "search" }); - cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "link" }); - cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" }); + if (!ClientUtils.RELEASE) { + cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "link" }); + cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" }); + } cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" }); type User = { email: string, userDocumentId: string }; let usersMenu: ContextMenuProps[] = []; -- cgit v1.2.3-70-g09d2 From e62b7a0c5c5eec2ef1431b2e2a876e2f3753ebc0 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Tue, 23 Jul 2019 15:14:35 -0400 Subject: key navigation of cells fixed when nested collections are expanded in schema --- .../views/collections/CollectionSchemaCells.tsx | 1 - .../views/collections/CollectionSchemaView.tsx | 413 +++++++++++++-------- 2 files changed, 257 insertions(+), 157 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 2dd3eeff4..abb2203a0 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -35,7 +35,6 @@ export interface CellProps { addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; isFocused: boolean; - changeFocusedCellByDirection: (direction: string) => void; changeFocusedCellByIndex: (row: number, col: number) => void; setIsEditing: (isEditing: boolean) => void; isEditable: boolean; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 25e90a25e..5546feb95 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -7,12 +7,12 @@ import { observer } from "mobx-react"; import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, TableCellRenderer, Column, RowInfo } from "react-table"; import "react-table/react-table.css"; import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils"; -import { Doc, DocListCast, DocListCastAsync, Field, FieldResult } from "../../../new_fields/Doc"; +import { Doc, DocListCast, DocListCastAsync, Field, FieldResult, Opt } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; import { Cast, FieldValue, NumCast, StrCast, BoolCast } from "../../../new_fields/Types"; -import { Docs } from "../../documents/Documents"; +import { Docs, DocumentOptions } from "../../documents/Documents"; import { Gateway } from "../../northstar/manager/Gateway"; import { SetupDrag, DragManager } from "../../util/DragManager"; import { CompileScript } from "../../util/Scripting"; @@ -35,6 +35,7 @@ import { CollectionSchemaHeader, CollectionSchemaAddColumnHeader } from "./Colle import { CellProps, CollectionSchemaCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaBooleanCell, CollectionSchemaCheckboxCell, CollectionSchemaDocCell } from "./CollectionSchemaCells"; import { MovableColumn, MovableRow } from "./CollectionSchemaMovableTableHOC"; import { SelectionManager } from "../../util/SelectionManager"; +import { DocumentManager } from "../../util/DocumentManager"; library.add(faCog); library.add(faPlus); @@ -61,10 +62,202 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { private _startPreviewWidth = 0; private DIVIDER_WIDTH = 4; - @observable _columnsPercentage = 0; - @observable _keys: string[] = []; - @observable _newKeyName: string = ""; @observable previewScript: string = ""; + @observable previewDoc: Doc | undefined = this.childDocs.length ? this.childDocs[0] : undefined; + @observable private _node : HTMLDivElement | null = null; + @observable private _focusedTable: Doc = this.props.Document; + + @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); } + @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; } + @computed get tableWidth() { return this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH - this.previewWidth(); } + @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } + + private createTarget = (ele: HTMLDivElement) => { + this._mainCont = ele; + super.CreateDropTarget(ele); + } + + // detectClick = (e: PointerEvent): void => { + // if (this._node && this._node.contains(e.target as Node)) { + // } else { + // this._isOpen = false; + // this.props.setIsEditing(false); + // } + // } + + isFocused = (doc: Doc): boolean => { + if (!this.props.isSelected()) return false; + return doc === this._focusedTable; + } + + @action + setFocused = (doc: Doc): void => { + this._focusedTable = doc; + } + + + //toggles preview side-panel of schema + @action + toggleExpander = () => { + this.props.Document.schemaPreviewWidth = this.previewWidth() === 0 ? Math.min(this.tableWidth / 3, 200) : 0; + } + + onDividerDown = (e: React.PointerEvent) => { + this._startPreviewWidth = this.previewWidth(); + e.stopPropagation(); + e.preventDefault(); + document.addEventListener("pointermove", this.onDividerMove); + document.addEventListener('pointerup', this.onDividerUp); + } + @action + onDividerMove = (e: PointerEvent): void => { + let nativeWidth = this._mainCont!.getBoundingClientRect(); + this.props.Document.schemaPreviewWidth = Math.min(nativeWidth.right - nativeWidth.left - 40, + this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]); + } + @action + onDividerUp = (e: PointerEvent): void => { + document.removeEventListener("pointermove", this.onDividerMove); + document.removeEventListener('pointerup', this.onDividerUp); + if (this._startPreviewWidth === this.previewWidth()) { + this.toggleExpander(); + } + } + + onPointerDown = (e: React.PointerEvent): void => { + if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) { + if (this.props.isSelected()) e.stopPropagation(); + } + } + + onWheel = (e: React.WheelEvent): void => { + if (this.props.active()) { + e.stopPropagation(); + } + } + + @computed + get previewDocument(): Doc | undefined { + let selected = this.previewDoc; + let pdc = selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined; + return pdc; + } + + getPreviewTransform = (): Transform => { + return this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth); + } + + @computed + get dividerDragger() { + return this.previewWidth() === 0 ? (null) : +
; + } + + @computed + get previewPanel() { + let layoutDoc = this.previewDocument ? Doc.expandTemplateLayout(this.previewDocument, this.props.DataDoc) : undefined; + return
+ +
; + } + @action + setPreviewScript = (script: string) => { + this.previewScript = script; + } + + @computed + get schemaTable() { + return ( + + ); + } + + @computed + get schemaToolbar() { + return ( +
+
Show Preview
+
+ ); + } + + render() { + + // if (SelectionManager.SelectedDocuments().length > 0) console.log(StrCast(SelectionManager.SelectedDocuments()[0].Document.title)); + // if (DocumentManager.Instance.getDocumentView(this.props.Document)) console.log(StrCast(this.props.Document.title), SelectionManager.IsSelected(DocumentManager.Instance.getDocumentView(this.props.Document)!)) + return ( + <> + {this.schemaToolbar} +
this.onDrop(e, {})} ref={this.createTarget}> + {this.schemaTable} + {this.dividerDragger} + {!this.previewWidth() ? (null) : this.previewPanel} +
+ + ); + } +} + +export interface SchemaTableProps { + Document: Doc; // child doc + PanelHeight: () => number; + PanelWidth: () => number; + childDocs: Doc[]; + CollectionView: CollectionView | CollectionPDFView | CollectionVideoView; + ContainingCollectionView: Opt; + fieldKey: string; + renderDepth: number; + moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; + ScreenToLocalTransform: () => Transform; + // CreateDropTarget: (ele: HTMLDivElement)=> void; // super createdriotarget + active: () => boolean; + onDrop: (e: React.DragEvent, options: DocumentOptions, completed?: (() => void) | undefined)=> void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; + isSelected: () => boolean; + isFocused: (document: Doc) => boolean; + setFocused: (document: Doc) => void; +} + +@observer +export class SchemaTable extends React.Component { + // private _mainCont?: HTMLDivElement; + private DIVIDER_WIDTH = 4; + @observable _headerIsEditing: boolean = false; @observable _cellIsEditing: boolean = false; @observable _focusedCell: {row: number, col: number} = {row: 0, col: 0}; @@ -81,8 +274,12 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get tableColumns(): Column[] { let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1); let columns: Column[] = []; + let tableIsFocused = this.props.isFocused(this.props.Document); + let focusedRow = this._focusedCell.row; + let focusedCol = this._focusedCell.col; + let isEditable = !this._headerIsEditing;// && this.props.isSelected(); - if (this.childDocs.reduce((found, doc) => found || doc.type === "collection", false)) { + if (this.props.childDocs.reduce((found, doc) => found || doc.type === "collection", false)) { columns.push( { expander: true, @@ -101,9 +298,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } let cols = this.columns.map(col => { - let focusedRow = this._focusedCell.row; - let focusedCol = this._focusedCell.col; - let isEditable = !this._headerIsEditing && this.props.isSelected();// || BoolCast(this.props.Document.libraryBrush)); let header = doc) { Cell: (rowProps: CellInfo) => { let row = rowProps.index; let column = this.columns.indexOf(rowProps.column.id!); - let isFocused = focusedRow === row && focusedCol === column; + let isFocused = focusedRow === row && focusedCol === column && tableIsFocused; let props: CellProps = { row: row, col: column, rowProps: rowProps, isFocused: isFocused, - changeFocusedCellByDirection: this.changeFocusedCellByDirection, 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, + renderDepth: this.props.renderDepth, + addDocTab: this.props.addDocTab, moveDocument: this.props.moveDocument, setIsEditing: this.setCellIsEditing, isEditable: isEditable @@ -200,14 +394,14 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before), moveDoc: (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc), rowInfo, - rowFocused: !this._headerIsEditing && this.props.isSelected() && rowInfo.index === this._focusedCell.row, + rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document) }; } - private createTarget = (ele: HTMLDivElement) => { - this._mainCont = ele; - super.CreateDropTarget(ele); - } + // private createTarget = (ele: HTMLDivElement) => { + // this._mainCont = ele; + // this.props.CreateDropTarget(ele); + // } // detectClick = (e: PointerEvent): void => { // if (this._node && this._node.contains(e.target as Node)) { @@ -238,35 +432,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { this._headerIsEditing = isEditing; } - //toggles preview side-panel of schema - @action - toggleExpander = () => { - this.props.Document.schemaPreviewWidth = this.previewWidth() === 0 ? Math.min(this.tableWidth / 3, 200) : 0; - } - - onDividerDown = (e: React.PointerEvent) => { - this._startPreviewWidth = this.previewWidth(); - e.stopPropagation(); - e.preventDefault(); - document.addEventListener("pointermove", this.onDividerMove); - document.addEventListener('pointerup', this.onDividerUp); - } - @action - onDividerMove = (e: PointerEvent): void => { - let nativeWidth = this._mainCont!.getBoundingClientRect(); - this.props.Document.schemaPreviewWidth = Math.min(nativeWidth.right - nativeWidth.left - 40, - this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]); - } - @action - onDividerUp = (e: PointerEvent): void => { - document.removeEventListener("pointermove", this.onDividerMove); - document.removeEventListener('pointerup', this.onDividerUp); - if (this._startPreviewWidth === this.previewWidth()) { - this.toggleExpander(); - } - } - onPointerDown = (e: React.PointerEvent): void => { + // console.log("pointer down", StrCast(this.props.Document.title)); + this.props.setFocused(this.props.Document); if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) { if (this.props.isSelected()) e.stopPropagation(); } @@ -278,14 +446,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } } - onContextMenu = (e: React.MouseEvent): void => { - if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 - ContextMenu.Instance.addItem({ description: "Make DB", event: this.makeDB }); - } - } - onKeyDown = (e: KeyboardEvent): void => { - if (!this._cellIsEditing && !this._headerIsEditing && this.props.isSelected()) { + if (!this._cellIsEditing && !this._headerIsEditing && this.props.isFocused(this.props.Document)) {// && this.props.isSelected()) { let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : ""; this.changeFocusedCellByDirection(direction); } @@ -295,7 +457,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { changeFocusedCellByDirection = (direction: string): void => { switch (direction) { case "tab": - if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === this.childDocs.length) { + if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === this.props.childDocs.length) { this._focusedCell = { row: 0, col: 0 }; } else if (this._focusedCell.col + 1 === this.columns.length) { this._focusedCell = { row: this._focusedCell.row + 1, col: 0 }; @@ -313,7 +475,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { this._focusedCell = { row: this._focusedCell.row === 0 ? this._focusedCell.row : this._focusedCell.row - 1, col: this._focusedCell.col }; break; case "down": - this._focusedCell = { row: this._focusedCell.row + 1 === this.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col }; + this._focusedCell = { row: this._focusedCell.row + 1 === this.props.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col }; break; } } @@ -321,27 +483,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action changeFocusedCellByIndex = (row: number, col: number): void => { this._focusedCell = { row: row, col: col }; - } - - @action - makeDB = async () => { - let csv: string = this.columns.reduce((val, col) => val + col + ",", ""); - csv = csv.substr(0, csv.length - 1) + "\n"; - let self = this; - DocListCast(this.props.Document.data).map(doc => { - csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "0") + ",", ""); - csv = csv.substr(0, csv.length - 1) + "\n"; - }); - csv.substring(0, csv.length - 1); - let dbName = StrCast(this.props.Document.title); - let res = await Gateway.Instance.PostSchema(csv, dbName); - if (self.props.CollectionView.props.addDocument) { - let schemaDoc = await Docs.Create.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }, { dbDoc: self.props.Document }); - if (schemaDoc) { - //self.props.CollectionView.props.addDocument(schemaDoc, false); - self.props.Document.schemaDoc = schemaDoc; - } - } + this.props.setFocused(this.props.Document); + // console.log("changed cell by index", StrCast(this.props.Document.title)); } @action @@ -359,12 +502,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { this.columns.push("New field (" + index + ")"); } - @action - addColumn = () => { - this.columns.push(this._newKeyName); - this._newKeyName = ""; - } - @action deleteColumn = (key: string) => { let list = Cast(this.props.Document.schemaColumns, listSpec("string")); @@ -442,17 +579,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { this._sortedColumns.delete(column); } - @computed - get previewDocument(): Doc | undefined { - let selectedIndex = this._focusedCell.row; - const selected = this.childDocs.length > selectedIndex ? this.childDocs[selectedIndex] : undefined; - let pdc = selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined; - return pdc; - } - - getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth); - - get documentKeys() { const docs = DocListCast(this.props.Document[this.props.fieldKey]); let keys: { [key: string]: boolean } = {}; @@ -471,16 +597,16 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get reactTable() { let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; - let hasCollectionChild = this.childDocs.reduce((found, doc) => found || doc.type === "collection", false); - let expandedRowsList = this._openCollections.map(col => this.childDocs.findIndex(doc => doc === col).toString()); + let hasCollectionChild = this.props.childDocs.reduce((found, doc) => found || doc.type === "collection", false); + let expandedRowsList = this._openCollections.map(col => this.props.childDocs.findIndex(doc => doc === col).toString()); let expanded = {}; expandedRowsList.forEach(row => expanded[row] = true); return doc) { TrComponent={MovableRow} sorted={Array.from(this._sortedColumns.values())} expanded={expanded} - SubComponent={hasCollectionChild ? row => row.original.type === "collection" && -
: undefined} + SubComponent={hasCollectionChild ? + row => { + if (row.original.type === "collection") { + let childDocs = DocListCast(row.original[this.props.fieldKey]); + return
; + } + } + : undefined} />; - - } - @computed - get dividerDragger() { - return this.previewWidth() === 0 ? (null) : -
; + onContextMenu = (e: React.MouseEvent): void => { + if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + ContextMenu.Instance.addItem({ description: "Make DB", event: this.makeDB }); + } } - - @computed - get previewPanel() { - // let layoutDoc = this.previewDocument; - // let resolvedDataDoc = (layoutDoc !== this.props.DataDoc) ? this.props.DataDoc : undefined; - // if (layoutDoc && !(Cast(layoutDoc.layout, Doc) instanceof Doc) && - // resolvedDataDoc && resolvedDataDoc !== layoutDoc) { - // // ... so change the layout to be an expanded view of the template layout. This allows the view override the template's properties and be referenceable as its own document. - // layoutDoc = Doc.expandTemplateLayout(layoutDoc, resolvedDataDoc); - // } - - let layoutDoc = this.previewDocument ? Doc.expandTemplateLayout(this.previewDocument, this.props.DataDoc) : undefined; - return
- -
; - } @action - setPreviewScript = (script: string) => { - this.previewScript = script; - } - - @computed - get schemaToolbar() { - return ( -
-
Show Preview
-
- ); + makeDB = async () => { + let csv: string = this.columns.reduce((val, col) => val + col + ",", ""); + csv = csv.substr(0, csv.length - 1) + "\n"; + let self = this; + DocListCast(this.props.Document.data).map(doc => { + csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "0") + ",", ""); + csv = csv.substr(0, csv.length - 1) + "\n"; + }); + csv.substring(0, csv.length - 1); + let dbName = StrCast(this.props.Document.title); + let res = await Gateway.Instance.PostSchema(csv, dbName); + if (self.props.CollectionView.props.addDocument) { + let schemaDoc = await Docs.Create.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }, { dbDoc: self.props.Document }); + if (schemaDoc) { + //self.props.CollectionView.props.addDocument(schemaDoc, false); + self.props.Document.schemaDoc = schemaDoc; + } + } } render() { + if (this.props.isFocused(this.props.Document)) console.log(StrCast(this.props.Document.title), "IS FOCUSED"); + // if (SelectionManager.SelectedDocuments().length > 0) console.log(StrCast(SelectionManager.SelectedDocuments()[0].Document.title)); + // if (DocumentManager.Instance.getDocumentView(this.props.Document)) console.log(StrCast(this.props.Document.title), SelectionManager.IsSelected(DocumentManager.Instance.getDocumentView(this.props.Document)!)) return ( - <> - {this.schemaToolbar} -
this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}> +
this.props.onDrop(e, {})} onContextMenu={this.onContextMenu} > {this.reactTable} - {this.dividerDragger} - {!this.previewWidth() ? (null) : this.previewPanel} - {/* {this.tableOptionsPanel} */}
- ); } } -- cgit v1.2.3-70-g09d2 From 7d9958f23b2b69f59bb108b33ec014b52ad41c99 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Tue, 23 Jul 2019 19:11:17 -0400 Subject: merge --- .../collections/CollectionSchemaMovableTableHOC.tsx | 10 ++++++---- .../views/collections/CollectionSchemaView.tsx | 21 +++++++++++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index db60e657a..6fc04849c 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -5,7 +5,7 @@ import { Transform } from "../../util/Transform"; import { Doc } from "../../../new_fields/Doc"; import { DragManager, SetupDrag } from "../../util/DragManager"; import { SelectionManager } from "../../util/SelectionManager"; -import { Cast, FieldValue } from "../../../new_fields/Types"; +import { Cast, FieldValue, StrCast } from "../../../new_fields/Types"; export interface MovableColumnProps { @@ -152,15 +152,17 @@ export class MovableRow extends React.Component { let rect = this._header!.current!.getBoundingClientRect(); let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); let before = x[1] < bounds[1]; + if (de.data instanceof DragManager.DocumentDragData) { e.stopPropagation(); if (de.data.draggedDocuments[0] === rowDoc) return true; let addDocument = (doc: Doc) => this.props.addDoc(doc, rowDoc, before); let movedDocs = de.data.draggedDocuments; //(de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments); - return (de.data.dropAction || de.data.userDropAction) ? + return (de.data.dropAction || de.data.userDropAction) ? de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false) : (de.data.moveDocument) ? - movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false) + movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false) + // movedDocs.reduce((added: boolean, d) => this.props.moveDoc(d, rowDoc, addDocument) || added, false) : de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before), false); } return false; @@ -177,7 +179,7 @@ export class MovableRow extends React.Component { if (!doc) return <>; let reference = React.createRef(); - let onItemDown = SetupDrag(reference, () => doc, this.props.moveDoc); + let onItemDown = SetupDrag(reference, () => doc); return (
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 5546feb95..6d71823c2 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -95,6 +95,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { this._focusedTable = doc; } + @action + setPreviewDoc = (doc: Doc): void => { + this.previewDoc = doc; + } //toggles preview side-panel of schema @action @@ -384,6 +388,16 @@ export class SchemaTable extends React.Component { document.removeEventListener("keydown", this.onKeyDown); } + tableAddDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => { + console.log("table add doc"); + return Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before); + } + + tableMoveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => { + console.log("SCHEMA MOVE"); + this.props.moveDocument(d, target, addDoc); + } + private getTrProps: ComponentPropsGetterR = (state, rowInfo) => { const that = this; if (!rowInfo) { @@ -391,8 +405,8 @@ export class SchemaTable extends React.Component { } return { ScreenToLocalTransform: this.props.ScreenToLocalTransform, - addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before), - moveDoc: (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc), + addDoc: this.tableAddDoc, + moveDoc: this.tableMoveDoc, rowInfo, rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document) }; @@ -654,7 +668,6 @@ export class SchemaTable extends React.Component { } render() { - if (this.props.isFocused(this.props.Document)) console.log(StrCast(this.props.Document.title), "IS FOCUSED"); // if (SelectionManager.SelectedDocuments().length > 0) console.log(StrCast(SelectionManager.SelectedDocuments()[0].Document.title)); // if (DocumentManager.Instance.getDocumentView(this.props.Document)) console.log(StrCast(this.props.Document.title), SelectionManager.IsSelected(DocumentManager.Instance.getDocumentView(this.props.Document)!)) return ( @@ -669,7 +682,7 @@ export class SchemaTable extends React.Component { interface CollectionSchemaPreviewProps { Document?: Doc; - DataDocument?: Doc; + DataDocument?: Doc; childDocs?: Doc[]; renderDepth: number; fitToBox?: boolean; -- cgit v1.2.3-70-g09d2 From 40b7197fb9b4748a63845bb664fa9ab02ad6915a Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Tue, 23 Jul 2019 22:07:55 -0400 Subject: minor styling --- src/client/views/EditableView.tsx | 13 ++-- .../views/collections/CollectionSchemaHeaders.tsx | 38 +++++------ .../views/collections/CollectionSchemaView.scss | 29 ++++++-- .../views/collections/CollectionSchemaView.tsx | 79 +++++++++++----------- 4 files changed, 92 insertions(+), 67 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 5cbecf2c9..31e4557be 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -39,7 +39,7 @@ export interface EditableProps { oneLine?: boolean; editing?: boolean; onClick?: (e: React.MouseEvent) => boolean; - isEditingCallback?: (isEditing: boolean) => void; + isEditingCallback?: (isEditing: boolean) => void; } /** @@ -58,7 +58,12 @@ export class EditableView extends React.Component { @action componentWillReceiveProps(nextProps: EditableProps) { - this._editing = nextProps.editing ? true : false; + // this is done because when autosuggest is turned on, the suggestions are passed in as a prop, + // so when the suggestions are passed in, and no editing prop is passed in, it used to set it + // to false. this will no longer do so -syip + if (nextProps.editing && nextProps.editing !== this._editing) { + this._editing = nextProps.editing; + } } @action @@ -88,7 +93,7 @@ export class EditableView extends React.Component { if (!this.props.onClick || !this.props.onClick(e)) { this._editing = true; this.props.isEditingCallback && this.props.isEditingCallback(true); - } + } e.stopPropagation(); } @@ -119,7 +124,7 @@ export class EditableView extends React.Component { }} /> : {this._editing = false; this.props.isEditingCallback && this.props.isEditingCallback(false);})} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation} + onBlur={action(() => { this._editing = false; this.props.isEditingCallback && this.props.isEditingCallback(false); })} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation} style={{ display: this.props.display, fontSize: this.props.fontSize }} />; } else { if (this.props.autosuggestProps) this.props.autosuggestProps.resetValue(); diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index 3a57cd306..d1d0674c4 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -30,7 +30,7 @@ export interface HeaderProps { export class CollectionSchemaHeader extends React.Component { render() { let icon: IconProp = this.props.keyType === ColumnType.Number ? "hashtag" : this.props.keyType === ColumnType.String ? "font" : - this.props.keyType === ColumnType.Boolean ? "check-square" : this.props.keyType === ColumnType.Doc ? "file" : "align-justify"; + this.props.keyType === ColumnType.Boolean ? "check-square" : this.props.keyType === ColumnType.Doc ? "file" : "align-justify"; return (
@@ -64,7 +64,7 @@ export interface AddColumnHeaderProps { export class CollectionSchemaAddColumnHeader extends React.Component { render() { return ( - + ); } } @@ -91,7 +91,7 @@ export interface ColumnMenuProps { @observer export class CollectionSchemaColumnMenu extends React.Component { @observable private _isOpen: boolean = false; - @observable private _node : HTMLDivElement | null = null; + @observable private _node: HTMLDivElement | null = null; componentDidMount() { document.addEventListener("pointerdown", this.detectClick); @@ -109,7 +109,7 @@ export class CollectionSchemaColumnMenu extends React.Component } } - @action + @action toggleIsOpen = (): void => { this._isOpen = !this._isOpen; this.props.setIsEditing(this._isOpen); @@ -133,19 +133,19 @@ export class CollectionSchemaColumnMenu extends React.Component return (
-
+
+ + + + @@ -183,13 +183,13 @@ export class CollectionSchemaColumnMenu extends React.Component />
{this.props.onlyShowOptions ? <> : - <> - {this.renderTypes()} - {this.renderSorting()} -
- -
- + <> + {this.renderTypes()} + {this.renderSorting()} +
+ +
+ }
); @@ -225,7 +225,7 @@ class KeysDropdown extends React.Component { @action setSearchTerm = (value: string): void => { this._searchTerm = value; }; @action setKey = (key: string): void => { this._key = key; }; - @action setIsOpen = (isOpen: boolean): void => {this._isOpen = isOpen;}; + @action setIsOpen = (isOpen: boolean): void => { this._isOpen = isOpen; }; @action onSelect = (key: string): void => { @@ -253,7 +253,7 @@ class KeysDropdown extends React.Component { } } - @action + @action onPointerEnter = (e: React.PointerEvent): void => { this._canClose = false; } @@ -278,7 +278,7 @@ class KeysDropdown extends React.Component { if (!exactFound && this._searchTerm !== "" && this.props.canAddNew) { options.push(
{ this.onSelect(this._searchTerm); this.setSearchTerm(""); }}> - Create "{this._searchTerm}" key
); + Create "{this._searchTerm}" key
); } return options; diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 4b20e8241..38d14c2de 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -57,7 +57,7 @@ .ReactTable { width: 100%; height: 100%; - background: $light-color; + background: white; box-sizing: border-box; border: none !important; @@ -76,6 +76,7 @@ font-size: 12px; height: 30px; border: 1px solid $intermediate-color; + box-shadow: none; } .rt-resizable-header { @@ -101,6 +102,7 @@ // max-height: $MAX_ROW_HEIGHT; font-size: 13px; text-align: center; + background-color: $light-color-secondary; &:last-child { overflow: visible; @@ -114,6 +116,7 @@ .rt-tr-group { direction: ltr; flex: 0 1 auto; + min-height: 30px; // max-height: $MAX_ROW_HEIGHT; // for sub comp @@ -134,6 +137,7 @@ .rt-tr { width: 100%; + min-height: 30px; // height: $MAX_ROW_HEIGHT; } @@ -144,6 +148,7 @@ padding: 0; font-size: 13px; text-align: center; + white-space: normal; .imageBox-cont { position: relative; @@ -190,7 +195,9 @@ .collectionSchemaView-header { height: 100%; - color: $intermediate-color; + color: gray; + letter-spacing: 2px; + text-transform: uppercase; .collectionSchema-header-menu { height: 100%; @@ -204,9 +211,18 @@ margin-right: 4px; } } + + div[class*="css"] { + width: 100%; + height: 100%; + } } } +button.add-column { + width: 28px; +} + .collectionSchema-header-menuOptions { color: black; width: 175px; @@ -265,6 +281,7 @@ .collectionSchema-row { // height: $MAX_ROW_HEIGHT; + height: 100%; &.row-focused { background-color: $light-color-secondary; @@ -317,7 +334,7 @@ p { width: 100%; height: 100%; - word-wrap: break-word; + // word-wrap: break-word; } } @@ -337,5 +354,9 @@ .sub { padding: 20px; - background-color: red; + background-color: $intermediate-color; +} + +.collectionSchemaView-expander { + height: 100%; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index febf95dc7..0e2d37a9e 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -1,6 +1,6 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; -import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons'; +import { faCog, faPlus, faSortUp, faSortDown } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; @@ -40,8 +40,7 @@ import { ImageBox } from "../nodes/ImageBox"; import { ComputedField } from "../../../new_fields/ScriptField"; -library.add(faCog); -library.add(faPlus); +library.add(faCog, faPlus, faSortUp, faSortDown); // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 export enum ColumnType { @@ -67,7 +66,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @observable previewScript: string = ""; @observable previewDoc: Doc | undefined = this.childDocs.length ? this.childDocs[0] : undefined; - @observable private _node : HTMLDivElement | null = null; + @observable private _node: HTMLDivElement | null = null; @observable private _focusedTable: Doc = this.props.Document; @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); } @@ -192,7 +191,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get schemaTable() { return ( - Transform; // CreateDropTarget: (ele: HTMLDivElement)=> void; // super createdriotarget active: () => boolean; - onDrop: (e: React.DragEvent, options: DocumentOptions, completed?: (() => void) | undefined)=> void; + onDrop: (e: React.DragEvent, options: DocumentOptions, completed?: (() => void) | undefined) => void; addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; isSelected: () => boolean; isFocused: (document: Doc) => boolean; @@ -267,16 +266,16 @@ export class SchemaTable extends React.Component { @observable _headerIsEditing: boolean = false; @observable _cellIsEditing: boolean = false; - @observable _focusedCell: {row: number, col: number} = {row: 0, col: 0}; - @observable _sortedColumns: Map = new Map(); + @observable _focusedCell: { row: number, col: number } = { row: 0, col: 0 }; + @observable _sortedColumns: Map = new Map(); @observable _openCollections: Array = []; - @observable private _node : HTMLDivElement | null = null; + @observable private _node: HTMLDivElement | null = null; @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); } @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; } @computed get tableWidth() { return this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH - this.previewWidth(); } @computed get columns() { return Cast(this.props.Document.schemaColumns, listSpec("string"), []); } - set columns(columns: string[]) {this.props.Document.schemaColumns = new List(columns); } + set columns(columns: string[]) { this.props.Document.schemaColumns = new List(columns); } @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } @computed get tableColumns(): Column[] { let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1); @@ -294,8 +293,8 @@ export class SchemaTable extends React.Component { width: 45, Expander: (rowInfo) => { if (rowInfo.original.type === "collection") { - if (rowInfo.isExpanded) return
this.onCloseCollection(rowInfo.original)}>-
; - if (!rowInfo.isExpanded) return
this.onExpandCollection(rowInfo.original)}>+
; + if (rowInfo.isExpanded) return
this.onCloseCollection(rowInfo.original)}>
; + if (!rowInfo.isExpanded) return
this.onExpandCollection(rowInfo.original)}>
; } else { return null; } @@ -303,10 +302,10 @@ export class SchemaTable extends React.Component { } ); } - + let cols = this.columns.map(col => { - let header = { ContainingCollection: this.props.ContainingCollectionView, Document: this.props.Document, fieldKey: this.props.fieldKey, - renderDepth: this.props.renderDepth, + renderDepth: this.props.renderDepth, addDocTab: this.props.addDocTab, moveDocument: this.props.moveDocument, setIsEditing: this.setCellIsEditing, @@ -347,11 +346,11 @@ export class SchemaTable extends React.Component { }; let colType = this.getColumnType(col); - if (colType === ColumnType.Number) return ; - if (colType === ColumnType.String) return ; + if (colType === ColumnType.Number) return ; + if (colType === ColumnType.String) return ; if (colType === ColumnType.Boolean) return ; if (colType === ColumnType.Doc) return ; - return ; + return ; }, minWidth: 200, }; @@ -363,7 +362,7 @@ export class SchemaTable extends React.Component { accessor: (doc: Doc) => 0, id: "add", Cell: (rowProps: CellInfo) => <>, - width: 45, + width: 28, resizable: false }); return columns; @@ -397,7 +396,7 @@ export class SchemaTable extends React.Component { } tableMoveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => { - console.log("SCHEMA MOVE"); + console.log("SCHEMA MOVE"); this.props.moveDocument(d, target, addDoc); } @@ -410,7 +409,7 @@ export class SchemaTable extends React.Component { ScreenToLocalTransform: this.props.ScreenToLocalTransform, addDoc: this.tableAddDoc, moveDoc: this.tableMoveDoc, - rowInfo, + rowInfo, rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document) }; } @@ -505,7 +504,7 @@ export class SchemaTable extends React.Component { } @action - createColumn = () => { + createColumn = () => { let index = 0; let found = this.columns.findIndex(col => col.toUpperCase() === "New field".toUpperCase()) > -1; if (!found) { @@ -513,7 +512,7 @@ export class SchemaTable extends React.Component { return; } while (found) { - index ++; + index++; found = this.columns.findIndex(col => col.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1; } this.columns.push("New field (" + index + ")"); @@ -562,7 +561,7 @@ export class SchemaTable extends React.Component { if (!typesDoc) { let newTypesDoc = new Doc(); newTypesDoc[key] = type; - this.props.Document.schemaColumnTypes = newTypesDoc; + this.props.Document.schemaColumnTypes = newTypesDoc; return; } else { typesDoc[key] = type; @@ -588,13 +587,13 @@ export class SchemaTable extends React.Component { @action setColumnSort = (column: string, descending: boolean) => { - this._sortedColumns.set(column, {id: column, desc: descending}); + this._sortedColumns.set(column, { id: column, desc: descending }); } @action removeColumnSort = (column: string) => { this._sortedColumns.delete(column); - } + } get documentKeys() { const docs = DocListCast(this.props.Document[this.props.fieldKey]); @@ -619,27 +618,27 @@ export class SchemaTable extends React.Component { let expanded = {}; expandedRowsList.forEach(row => expanded[row] = true); - return { - if (row.original.type === "collection") { + if (row.original.type === "collection") { let childDocs = DocListCast(row.original[this.props.fieldKey]); - return
; + return
; } } - : undefined} - + : undefined} + />; } @@ -685,7 +684,7 @@ export class SchemaTable extends React.Component { interface CollectionSchemaPreviewProps { Document?: Doc; - DataDocument?: Doc; + DataDocument?: Doc; childDocs?: Doc[]; renderDepth: number; fitToBox?: boolean; @@ -762,7 +761,7 @@ export class CollectionSchemaPreview extends React.Component Date: Wed, 24 Jul 2019 12:28:17 -0400 Subject: can text wrap row via context menu --- .../CollectionSchemaMovableTableHOC.tsx | 34 +++++++++++++++------- .../views/collections/CollectionSchemaView.scss | 8 ++++- .../views/collections/CollectionSchemaView.tsx | 28 ++++++++++++++---- 3 files changed, 53 insertions(+), 17 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 6fc04849c..beae739ec 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -1,11 +1,12 @@ import React = require("react"); -import { ReactTableDefaults, TableCellRenderer, ComponentPropsGetterR, ComponentPropsGetter0 } from "react-table"; +import { ReactTableDefaults, TableCellRenderer, ComponentPropsGetterR, ComponentPropsGetter0, RowInfo } from "react-table"; import "./CollectionSchemaView.scss"; import { Transform } from "../../util/Transform"; import { Doc } from "../../../new_fields/Doc"; import { DragManager, SetupDrag } from "../../util/DragManager"; import { SelectionManager } from "../../util/SelectionManager"; import { Cast, FieldValue, StrCast } from "../../../new_fields/Types"; +import { ContextMenu } from "../ContextMenu"; export interface MovableColumnProps { @@ -60,7 +61,7 @@ export class MovableColumn extends React.Component { return false; } - setupDrag (ref: React.RefObject) { + setupDrag(ref: React.RefObject) { let onRowMove = (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); @@ -102,10 +103,13 @@ export class MovableColumn extends React.Component { } export interface MovableRowProps { + rowInfo: RowInfo; ScreenToLocalTransform: () => Transform; addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean; moveDoc: DragManager.MoveFunction; rowFocused: boolean; + textWrapRow: (doc: Doc) => void; + rowWrapped: boolean; } export class MovableRow extends React.Component { @@ -141,11 +145,10 @@ export class MovableRow extends React.Component { } rowDrop = (e: Event, de: DragManager.DropEvent) => { - const { children = null, rowInfo } = this.props; - if (!rowInfo) return false; + // const { children = null, rowInfo } = this.props; + // if (!rowInfo) return false; - const { original } = rowInfo; - const rowDoc = FieldValue(Cast(original, Doc)); + const rowDoc = FieldValue(Cast(this.props.rowInfo.original, Doc)); if (!rowDoc) return false; let x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y); @@ -158,16 +161,23 @@ export class MovableRow extends React.Component { if (de.data.draggedDocuments[0] === rowDoc) return true; let addDocument = (doc: Doc) => this.props.addDoc(doc, rowDoc, before); let movedDocs = de.data.draggedDocuments; //(de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments); - return (de.data.dropAction || de.data.userDropAction) ? + return (de.data.dropAction || de.data.userDropAction) ? de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false) : (de.data.moveDocument) ? - movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false) + movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false) // movedDocs.reduce((added: boolean, d) => this.props.moveDoc(d, rowDoc, addDocument) || added, false) : de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before), false); } return false; } + onRowContextMenu = (e: React.MouseEvent): void => { + // const { rowInfo } = this.props; + // const { textWrapRow, original } = rowInfo; + let description = this.props.rowWrapped ? "Unwrap text on row" : "Text wrap row"; + ContextMenu.Instance.addItem({ description: description, event: () => this.props.textWrapRow(this.props.rowInfo.original) }); + } + render() { const { children = null, rowInfo } = this.props; if (!rowInfo) { @@ -179,10 +189,14 @@ export class MovableRow extends React.Component { if (!doc) return <>; let reference = React.createRef(); - let onItemDown = SetupDrag(reference, () => doc); + let onItemDown = SetupDrag(reference, () => doc, this.props.moveDoc); + + let className = "collectionSchema-row"; + if (this.props.rowFocused) className += " row-focused"; + if (this.props.rowWrapped) className += " row-wrapped"; return ( -
+
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 38d14c2de..410790197 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -148,7 +148,7 @@ padding: 0; font-size: 13px; text-align: center; - white-space: normal; + // white-space: normal; .imageBox-cont { position: relative; @@ -287,6 +287,12 @@ button.add-column { background-color: $light-color-secondary; } + &.row-wrapped { + .rt-td { + white-space: normal; + } + } + .row-dragger { // height: $MAX_ROW_HEIGHT; } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 0e2d37a9e..62e4ceb54 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -53,6 +53,7 @@ export enum ColumnType { } // this map should be used for keys that should have a const type of value const columnTypes: Map = new Map([ + ["title", ColumnType.String], ["x", ColumnType.Number], ["y", ColumnType.Number], ["width", ColumnType.Number], ["height", ColumnType.Number], ["nativeWidth", ColumnType.Number], ["nativeHeight", ColumnType.Number], ["isPrototype", ColumnType.Boolean], ["page", ColumnType.Number], ["curPage", ColumnType.Number], ["libraryBrush", ColumnType.Boolean], ["zIndex", ColumnType.Number] @@ -268,7 +269,8 @@ export class SchemaTable extends React.Component { @observable _cellIsEditing: boolean = false; @observable _focusedCell: { row: number, col: number } = { row: 0, col: 0 }; @observable _sortedColumns: Map = new Map(); - @observable _openCollections: Array = []; + @observable _openCollections: Array = []; + @observable _textWrappedRows: Array = []; @observable private _node: HTMLDivElement | null = null; @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); } @@ -396,7 +398,7 @@ export class SchemaTable extends React.Component { } tableMoveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => { - console.log("SCHEMA MOVE"); + console.log("SCHEMA MOVE", StrCast(d.title), StrCast(target.title)); this.props.moveDocument(d, target, addDoc); } @@ -410,7 +412,9 @@ export class SchemaTable extends React.Component { addDoc: this.tableAddDoc, moveDoc: this.tableMoveDoc, rowInfo, - rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document) + rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document), + textWrapRow: this.textWrapRow, + rowWrapped: this._textWrappedRows.findIndex(id => rowInfo.original[Id] === id) > -1 }; } @@ -429,12 +433,12 @@ export class SchemaTable extends React.Component { @action onExpandCollection = (collection: Doc): void => { - this._openCollections.push(collection); + this._openCollections.push(collection[Id]); } @action onCloseCollection = (collection: Doc): void => { - let index = this._openCollections.findIndex(col => col === collection); + let index = this._openCollections.findIndex(col => col === collection[Id]); if (index > -1) this._openCollections.splice(index, 1); } @@ -610,13 +614,25 @@ export class SchemaTable extends React.Component { return Array.from(Object.keys(keys)); } + @action + textWrapRow = (doc: Doc): void => { + let index = this._textWrappedRows.findIndex(id => doc[Id] === id); + if (index > -1) { + this._textWrappedRows.splice(index, 1); + } else { + this._textWrappedRows.push(doc[Id]); + } + + } + @computed get reactTable() { let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; let hasCollectionChild = this.props.childDocs.reduce((found, doc) => found || doc.type === "collection", false); - let expandedRowsList = this._openCollections.map(col => this.props.childDocs.findIndex(doc => doc === col).toString()); + let expandedRowsList = this._openCollections.map(col => this.props.childDocs.findIndex(doc => doc[Id] === col).toString()); let expanded = {}; expandedRowsList.forEach(row => expanded[row] = true); + console.log(...[...this._textWrappedRows]); // TODO: get component to rerender on text wrap change without needign to console.log :(((( return Date: Wed, 24 Jul 2019 17:48:11 -0400 Subject: can move rows within expanded collection --- src/client/util/DragManager.ts | 4 +-- .../views/collections/CollectionSchemaCells.tsx | 42 ++++++++++++---------- .../CollectionSchemaMovableTableHOC.tsx | 18 +++++----- .../views/collections/CollectionSchemaView.scss | 24 ++++++------- .../views/collections/CollectionSchemaView.tsx | 17 +++++---- src/new_fields/Doc.ts | 9 ++++- 6 files changed, 64 insertions(+), 50 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index f9f6b05c0..0299b1d90 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,6 +1,6 @@ import { action, runInAction } from "mobx"; import { Doc } from "../../new_fields/Doc"; -import { Cast } from "../../new_fields/Types"; +import { Cast, StrCast } from "../../new_fields/Types"; import { URLField } from "../../new_fields/URLField"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; @@ -305,7 +305,7 @@ export namespace DragManager { StartDrag([ele], dragData, downX, downY, options); } - export function StartColumnDrag(ele: HTMLElement, dragData: ColumnDragData, downX: number, downY: number, options?:DragOptions) { + export function StartColumnDrag(ele: HTMLElement, dragData: ColumnDragData, downX: number, downY: number, options?: DragOptions) { StartDrag([ele], dragData, downX, downY, options); } diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index abb2203a0..bc84da140 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -34,7 +34,7 @@ export interface CellProps { renderDepth: number; addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; - isFocused: boolean; + isFocused: boolean; changeFocusedCellByIndex: (row: number, col: number) => void; setIsEditing: (isEditing: boolean) => void; isEditable: boolean; @@ -42,22 +42,22 @@ export interface CellProps { @observer export class CollectionSchemaCell extends React.Component { - @observable protected _isEditing: boolean = false; + @observable protected _isEditing: boolean = this.props.isEditing ? true : false; protected _focusRef = React.createRef(); protected _document = this.props.rowProps.original; private _dropDisposer?: DragManager.DragDropDisposer; componentDidMount() { - if (this._focusRef.current) { - if (this.props.isFocused) { - this._focusRef.current.className += " focused"; - if (!this.props.isEditable) { - this._focusRef.current.className += " inactive"; - } - } else { - this._focusRef.current.className = "collectionSchemaView-cellWrapper"; - } - } + // if (this._focusRef.current) { + // if (this.props.isFocused) { + // this._focusRef.current.className += " focused"; + // if (!this.props.isEditable) { + // this._focusRef.current.className += " inactive"; + // } + // } else { + // this._focusRef.current.className = "collectionSchemaView-cellWrapper"; + // } + // } document.addEventListener("keydown", this.onKeyDown); @@ -69,6 +69,7 @@ export class CollectionSchemaCell extends React.Component { @action onKeyDown = (e: KeyboardEvent): void => { + console.log("CELL keydown"); if (this.props.isFocused && this.props.isEditable) { document.removeEventListener("keydown", this.onKeyDown); this._isEditing = true; @@ -139,10 +140,10 @@ export class CollectionSchemaCell extends React.Component { addDocTab: this.props.addDocTab, }; - let onItemDown = (e: React.PointerEvent) => { - SetupDrag(this._focusRef, () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document, - this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument, this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e); - }; + // let onItemDown = (e: React.PointerEvent) => { + // SetupDrag(this._focusRef, () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document, + // this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument, this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e); + // }; let onPointerEnter = (e: React.PointerEvent): void => { if (e.buttons === 1 && SelectionManager.GetIsDragging() && (type === "document" || type === undefined)) { dragRef!.current!.className = "doc-drag-over"; @@ -163,10 +164,15 @@ export class CollectionSchemaCell extends React.Component { contents = typeof field === "object" ? doc ? StrCast(doc.title) === "" ? "--" : StrCast(doc.title) : `--${typeof field}--` : `--${typeof field}--`; } + let className = "collectionSchemaView-cellWrapper"; + if (this._isEditing) className += " editing"; + if (this.props.isFocused && this.props.isEditable) className += " focused"; + if (this.props.isFocused && !this.props.isEditable) className += " inactive"; + return (
-
-
+
+
Transform; addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean; - moveDoc: DragManager.MoveFunction; + removeDoc: (doc: Doc) => boolean; rowFocused: boolean; textWrapRow: (doc: Doc) => void; rowWrapped: boolean; @@ -145,9 +146,6 @@ export class MovableRow extends React.Component { } rowDrop = (e: Event, de: DragManager.DropEvent) => { - // const { children = null, rowInfo } = this.props; - // if (!rowInfo) return false; - const rowDoc = FieldValue(Cast(this.props.rowInfo.original, Doc)); if (!rowDoc) return false; @@ -160,24 +158,26 @@ export class MovableRow extends React.Component { e.stopPropagation(); if (de.data.draggedDocuments[0] === rowDoc) return true; let addDocument = (doc: Doc) => this.props.addDoc(doc, rowDoc, before); - let movedDocs = de.data.draggedDocuments; //(de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments); + let movedDocs = de.data.draggedDocuments; return (de.data.dropAction || de.data.userDropAction) ? de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false) : (de.data.moveDocument) ? movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false) - // movedDocs.reduce((added: boolean, d) => this.props.moveDoc(d, rowDoc, addDocument) || added, false) : de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before), false); } return false; } onRowContextMenu = (e: React.MouseEvent): void => { - // const { rowInfo } = this.props; - // const { textWrapRow, original } = rowInfo; let description = this.props.rowWrapped ? "Unwrap text on row" : "Text wrap row"; ContextMenu.Instance.addItem({ description: description, event: () => this.props.textWrapRow(this.props.rowInfo.original) }); } + @action + move: DragManager.MoveFunction = (doc: Doc, target: Doc, addDoc) => { + return doc !== target && this.props.removeDoc(doc) && addDoc(doc); + } + render() { const { children = null, rowInfo } = this.props; if (!rowInfo) { @@ -189,7 +189,7 @@ export class MovableRow extends React.Component { if (!doc) return <>; let reference = React.createRef(); - let onItemDown = SetupDrag(reference, () => doc, this.props.moveDoc); + let onItemDown = SetupDrag(reference, () => doc, this.move); let className = "collectionSchema-row"; if (this.props.rowFocused) className += " row-focused"; diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 410790197..c2b0d8f42 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -148,7 +148,7 @@ padding: 0; font-size: 13px; text-align: center; - // white-space: normal; + white-space: normal; .imageBox-cont { position: relative; @@ -196,8 +196,6 @@ .collectionSchemaView-header { height: 100%; color: gray; - letter-spacing: 2px; - text-transform: uppercase; .collectionSchema-header-menu { height: 100%; @@ -206,16 +204,18 @@ width: 100%; height: 100%; padding: 4px; + letter-spacing: 2px; + text-transform: uppercase; svg { margin-right: 4px; } } - div[class*="css"] { - width: 100%; - height: 100%; - } + // div[class*="css"] { + // width: 100%; + // height: 100%; + // } } } @@ -287,12 +287,6 @@ button.add-column { background-color: $light-color-secondary; } - &.row-wrapped { - .rt-td { - white-space: normal; - } - } - .row-dragger { // height: $MAX_ROW_HEIGHT; } @@ -309,6 +303,10 @@ button.add-column { &.row-inside { border: 1px solid red; } + + .row-dragging { + background-color: blue; + } } } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 62e4ceb54..a7e435ac6 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -344,7 +344,7 @@ export class SchemaTable extends React.Component { addDocTab: this.props.addDocTab, moveDocument: this.props.moveDocument, setIsEditing: this.setCellIsEditing, - isEditable: isEditable + isEditable: isEditable, }; let colType = this.getColumnType(col); @@ -393,13 +393,16 @@ export class SchemaTable extends React.Component { } tableAddDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => { - console.log("table add doc"); return Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before); } - tableMoveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => { - console.log("SCHEMA MOVE", StrCast(d.title), StrCast(target.title)); - this.props.moveDocument(d, target, addDoc); + tableRemoveDoc = (document: Doc): boolean => { + let index = this.props.childDocs.findIndex(d => d === document); + if (index !== -1) { + this.props.childDocs.splice(index, 1); + return true; + } + return false; } private getTrProps: ComponentPropsGetterR = (state, rowInfo) => { @@ -410,7 +413,7 @@ export class SchemaTable extends React.Component { return { ScreenToLocalTransform: this.props.ScreenToLocalTransform, addDoc: this.tableAddDoc, - moveDoc: this.tableMoveDoc, + removeDoc: this.tableRemoveDoc, rowInfo, rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document), textWrapRow: this.textWrapRow, @@ -467,6 +470,7 @@ export class SchemaTable extends React.Component { } onKeyDown = (e: KeyboardEvent): void => { + console.log("schema keydown", !this._cellIsEditing, !this._headerIsEditing, this.props.isFocused(this.props.Document)); if (!this._cellIsEditing && !this._headerIsEditing && this.props.isFocused(this.props.Document)) {// && this.props.isSelected()) { let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : ""; this.changeFocusedCellByDirection(direction); @@ -504,7 +508,6 @@ export class SchemaTable extends React.Component { changeFocusedCellByIndex = (row: number, col: number): void => { this._focusedCell = { row: row, col: col }; this.props.setFocused(this.props.Document); - // console.log("changed cell by index", StrCast(this.props.Document.title)); } @action diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 5ae0753d8..eba1d4f04 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -267,21 +267,28 @@ export namespace Doc { export function AddDocToList(target: Doc, key: string, doc: Doc, relativeTo?: Doc, before?: boolean, first?: boolean, allowDuplicates?: boolean) { if (target[key] === undefined) { + console.log("target key undefined"); Doc.GetProto(target)[key] = new List(); } let list = Cast(target[key], listSpec(Doc)); if (list) { + console.log("has list"); if (allowDuplicates !== true) { let pind = list.reduce((l, d, i) => d instanceof Doc && Doc.AreProtosEqual(d, doc) ? i : l, -1); if (pind !== -1) { list.splice(pind, 1); } } - if (first) list.splice(0, 0, doc); + if (first) { + console.log("is first"); + list.splice(0, 0, doc); + } else { + console.log("not first"); let ind = relativeTo ? list.indexOf(relativeTo) : -1; if (ind === -1) list.push(doc); else list.splice(before ? ind : ind + 1, 0, doc); + console.log("index", ind); } } return true; -- cgit v1.2.3-70-g09d2 From 779938dd613d81bfb773f14cd4e43362f0aa8b24 Mon Sep 17 00:00:00 2001 From: Fawn Date: Wed, 24 Jul 2019 22:08:31 -0400 Subject: minor schema stylign --- .../views/collections/CollectionSchemaCells.tsx | 20 +++------------ .../views/collections/CollectionSchemaView.scss | 29 ++++++++++++++++------ .../views/collections/CollectionSchemaView.tsx | 24 +++++++++++++++--- 3 files changed, 46 insertions(+), 27 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index bc84da140..d453fed47 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -42,23 +42,12 @@ export interface CellProps { @observer export class CollectionSchemaCell extends React.Component { - @observable protected _isEditing: boolean = this.props.isEditing ? true : false; + @observable protected _isEditing: boolean = false; protected _focusRef = React.createRef(); protected _document = this.props.rowProps.original; private _dropDisposer?: DragManager.DragDropDisposer; componentDidMount() { - // if (this._focusRef.current) { - // if (this.props.isFocused) { - // this._focusRef.current.className += " focused"; - // if (!this.props.isEditable) { - // this._focusRef.current.className += " inactive"; - // } - // } else { - // this._focusRef.current.className = "collectionSchemaView-cellWrapper"; - // } - // } - document.addEventListener("keydown", this.onKeyDown); } @@ -69,7 +58,6 @@ export class CollectionSchemaCell extends React.Component { @action onKeyDown = (e: KeyboardEvent): void => { - console.log("CELL keydown"); if (this.props.isFocused && this.props.isEditable) { document.removeEventListener("keydown", this.onKeyDown); this._isEditing = true; @@ -146,11 +134,11 @@ export class CollectionSchemaCell extends React.Component { // }; let onPointerEnter = (e: React.PointerEvent): void => { if (e.buttons === 1 && SelectionManager.GetIsDragging() && (type === "document" || type === undefined)) { - dragRef!.current!.className = "doc-drag-over"; + dragRef!.current!.className = "collectionSchemaView-cellContainer doc-drag-over"; } }; let onPointerLeave = (e: React.PointerEvent): void => { - dragRef!.current!.className = ""; + dragRef!.current!.className = "collectionSchemaView-cellContainer"; }; let field = props.Document[props.fieldKey]; @@ -170,7 +158,7 @@ export class CollectionSchemaCell extends React.Component { if (this.props.isFocused && !this.props.isEditable) className += " inactive"; return ( -
+
{ { expander: true, Header: "", - width: 45, + width: 30, Expander: (rowInfo) => { if (rowInfo.original.type === "collection") { if (rowInfo.isExpanded) return
this.onCloseCollection(rowInfo.original)}>
; @@ -421,6 +421,25 @@ export class SchemaTable extends React.Component { }; } + private getTdProps: ComponentPropsGetterR = (state, rowInfo, column, instance) => { + if (!rowInfo) return {}; + if (!column) return {}; + + let row = rowInfo.index; + let col = this.columns.indexOf(column.id); + // let col = column ? this.columns.indexOf(column!) : -1; + let isFocused = this._focusedCell.row === row && this._focusedCell.col === col && this.props.isFocused(this.props.Document); + // let column = this.columns.indexOf(column.id!); + + console.log("td style", row, col, this._focusedCell.row, this._focusedCell.col); + + return { + style: { + border: !this._headerIsEditing && isFocused ? "2px solid black" : "1px solid #f1efeb" + } + }; + } + // private createTarget = (ele: HTMLDivElement) => { // this._mainCont = ele; // this.props.CreateDropTarget(ele); @@ -456,7 +475,6 @@ export class SchemaTable extends React.Component { } onPointerDown = (e: React.PointerEvent): void => { - // console.log("pointer down", StrCast(this.props.Document.title)); this.props.setFocused(this.props.Document); if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) { if (this.props.isSelected()) e.stopPropagation(); @@ -470,7 +488,6 @@ export class SchemaTable extends React.Component { } onKeyDown = (e: KeyboardEvent): void => { - console.log("schema keydown", !this._cellIsEditing, !this._headerIsEditing, this.props.isFocused(this.props.Document)); if (!this._cellIsEditing && !this._headerIsEditing && this.props.isFocused(this.props.Document)) {// && this.props.isSelected()) { let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : ""; this.changeFocusedCellByDirection(direction); @@ -645,6 +662,7 @@ export class SchemaTable extends React.Component { showPagination={false} columns={this.tableColumns} getTrProps={this.getTrProps} + getTdProps={this.getTdProps} sortable={false} TrComponent={MovableRow} sorted={Array.from(this._sortedColumns.values())} -- cgit v1.2.3-70-g09d2 From 2d62ca0060c9ef7d3932e8681deb09cc3acf6d48 Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 25 Jul 2019 11:47:23 -0400 Subject: schema stylign --- .../CollectionSchemaMovableTableHOC.tsx | 10 +-- .../views/collections/CollectionSchemaView.scss | 82 +++++++++++++++++----- .../views/collections/CollectionSchemaView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 2 +- 4 files changed, 73 insertions(+), 23 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 290958cd0..70d6fbc7b 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -9,10 +9,10 @@ import { Cast, FieldValue, StrCast } from "../../../new_fields/Types"; import { ContextMenu } from "../ContextMenu"; import { action } from "mobx"; import { library } from '@fortawesome/fontawesome-svg-core'; -import { faGripVertical } from '@fortawesome/free-solid-svg-icons'; +import { faGripVertical, faTrash } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -library.add(faGripVertical); +library.add(faGripVertical, faTrash); export interface MovableColumnProps { columnRenderer: TableCellRenderer; @@ -198,13 +198,15 @@ export class MovableRow extends React.Component { let className = "collectionSchema-row"; if (this.props.rowFocused) className += " row-focused"; if (this.props.rowWrapped) className += " row-wrapped"; + // if (!this.props.rowWrapped) className += " row-unwrapped"; return (
-
- +
+
this.props.removeDoc(this.props.rowInfo.original)}>
+
{children} diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 22d8a5cb6..9ad52db4c 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -8,7 +8,7 @@ box-sizing: border-box; // position: absolute; width: 100%; - // height: calc(100% - 25px); + height: calc(100% - 50px); // overflow: hidden; overflow-x: scroll; border: none; @@ -55,7 +55,7 @@ } .ReactTable { - width: 100%; + width: 100% !important; height: 100%; background: white; box-sizing: border-box; @@ -70,8 +70,8 @@ } .rt-thead { - width: calc(100% - 30px); - margin-left: 30px; + width: calc(100% - 50px); + margin-left: 50px; &.-header { // background: $intermediate-color; @@ -118,6 +118,7 @@ .rt-tbody { direction: rtl; + overflow: visible; } .rt-tr-group { @@ -139,12 +140,12 @@ // background-color: $light-color-secondary; // } - &:first-child { - border-top: 1px solid $light-color-secondary !important; - } - &:last-child { - border-bottom: 1px solid $light-color-secondary !important; - } + // &:first-child { + // border-top: 1px solid $light-color-secondary !important; + // } + // &:last-child { + // border-bottom: 1px solid $light-color-secondary !important; + // } } .rt-tr { @@ -162,7 +163,8 @@ padding: 0; font-size: 13px; text-align: center; - white-space: normal; + + // white-space: normal; .imageBox-cont { position: relative; @@ -296,17 +298,46 @@ button.add-column { .collectionSchema-row { // height: $MAX_ROW_HEIGHT; height: 100%; + background-color: white; &.row-focused { - background-color: rgb(253, 191, 191);//$light-color-secondary; + background-color: rgb(255, 246, 246);//$light-color-secondary; + } + + &.row-wrapped { + white-space: normal; } .row-dragger { + display: flex; + justify-content: space-evenly; // height: $MAX_ROW_HEIGHT; - width: 30px; + flex: 50 0 auto; + width: 50px; + max-width: 50px; height: 100%; - padding: 10px; - color: gray; + min-height: 30px; + // padding: 5px 5px 5px 0; + color: lightgray; + background-color: white; + transition: color 0.1s ease; + + // &:hover { + // color: lightgray; + // } + + .row-option { + // padding: 5px; + cursor: pointer; + transition: color 0.1s ease; + display: flex; + flex-direction: column; + justify-content: center; + + &:hover { + color: gray; + } + } } .collectionSchema-row-wrapper { @@ -369,6 +400,7 @@ button.add-column { } .collectionSchemaView-toolbar { + height: 50px; display: flex; justify-content: flex-end; } @@ -379,8 +411,24 @@ button.add-column { } .sub { - padding: 20px; - background-color: $intermediate-color; + padding: 10px 30px; + // padding-left: 80px; + background-color: rgb(252, 252, 252); + width: calc(100% - 50px); + margin-left: 50px; + + .rt-table { + overflow-x: hidden; // todo; this shouldnt be like this :(( + overflow-y: visible; + } // TODO fix + + .row-dragger { + background-color: rgb(252, 252, 252); + } + + .rt-table { + background-color: rgb(252, 252, 252); + } } .collectionSchemaView-expander { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 87a4a0c6a..a8692ee95 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -435,7 +435,7 @@ export class SchemaTable extends React.Component { return { style: { - border: !this._headerIsEditing && isFocused ? "2px solid black" : "1px solid #f1efeb" + border: !this._headerIsEditing && isFocused ? "2px solid rgb(255, 160, 160)" : "1px solid #f1efeb" } }; } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 62d721868..df8a1ebc1 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -62,7 +62,7 @@ export class CollectionView extends React.Component { } else { return [ - (), + // (), this.SubViewHelper(type, renderProps) ]; } -- cgit v1.2.3-70-g09d2 From d583b473181c9e97b4626c302dc9a167fa64a17c Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 25 Jul 2019 12:43:24 -0400 Subject: some preview stuff --- .../views/collections/CollectionSchemaView.scss | 32 ++++++++++++++++------ .../views/collections/CollectionSchemaView.tsx | 19 +++++++++---- 2 files changed, 37 insertions(+), 14 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 9ad52db4c..98ec971ef 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -40,22 +40,23 @@ .collectionSchemaView-dividerDragger { position: relative; - background: black; float: left; - height: 37px; + height: 100%; width: 20px; z-index: 20; right: 0; top: 0; - background: $main-accent; - box-sizing: border-box; - border-left: 1px solid $intermediate-color; - border-right: 1px solid $intermediate-color; + background: gray; + cursor: col-resize; + // background: $main-accent; + // box-sizing: border-box; + // border-left: 1px solid $intermediate-color; + // border-right: 1px solid $intermediate-color; } } .ReactTable { - width: 100% !important; + width: 100%; height: 100%; background: white; box-sizing: border-box; @@ -400,9 +401,16 @@ button.add-column { } .collectionSchemaView-toolbar { - height: 50px; + height: 30px; display: flex; justify-content: flex-end; + padding: 0 10px; + + .collectionSchemaView-toolbar-item { + display: flex; + flex-direction: column; + justify-content: center; + } } #preview-schema-checkbox-div { @@ -410,6 +418,10 @@ button.add-column { font-size: 12px; } +.collectionSchemaView-table { + width: calc(100% - 7px); +} + .sub { padding: 10px 30px; // padding-left: 80px; @@ -429,6 +441,10 @@ button.add-column { .rt-table { background-color: rgb(252, 252, 252); } + + .collectionSchemaView-table { + width: 100%; + } } .collectionSchemaView-expander { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index a8692ee95..ed2c88f19 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -66,7 +66,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { private DIVIDER_WIDTH = 4; @observable previewScript: string = ""; - @observable previewDoc: Doc | undefined = this.childDocs.length ? this.childDocs[0] : undefined; + @observable previewDoc: Doc | undefined = undefined; @observable private _node: HTMLDivElement | null = null; @observable private _focusedTable: Doc = this.props.Document; @@ -100,6 +100,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action setPreviewDoc = (doc: Doc): void => { + console.log("set"); this.previewDoc = doc; } @@ -147,6 +148,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { get previewDocument(): Doc | undefined { let selected = this.previewDoc; let pdc = selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined; + console.log("preview document", pdc); return pdc; } @@ -209,6 +211,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { isSelected={this.props.isSelected} isFocused={this.isFocused} setFocused={this.setFocused} + setPreviewDoc={this.setPreviewDoc} /> ); } @@ -217,7 +220,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { get schemaToolbar() { return (
-
Show Preview
+
+
Show Preview
+
); } @@ -258,6 +263,7 @@ export interface SchemaTableProps { isSelected: () => boolean; isFocused: (document: Doc) => boolean; setFocused: (document: Doc) => void; + setPreviewDoc: (document: Doc) => void; } @observer @@ -430,9 +436,6 @@ export class SchemaTable extends React.Component { // let col = column ? this.columns.indexOf(column!) : -1; let isFocused = this._focusedCell.row === row && this._focusedCell.col === col && this.props.isFocused(this.props.Document); // let column = this.columns.indexOf(column.id!); - - console.log("td style", row, col, this._focusedCell.row, this._focusedCell.col); - return { style: { border: !this._headerIsEditing && isFocused ? "2px solid rgb(255, 160, 160)" : "1px solid #f1efeb" @@ -519,12 +522,16 @@ export class SchemaTable extends React.Component { this._focusedCell = { row: this._focusedCell.row + 1 === this.props.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col }; break; } + let doc = this.props.childDocs[this._focusedCell.row]; + this.props.setPreviewDoc(doc); } @action changeFocusedCellByIndex = (row: number, col: number): void => { this._focusedCell = { row: row, col: col }; this.props.setFocused(this.props.Document); + let doc = this.props.childDocs[this._focusedCell.row]; + this.props.setPreviewDoc(doc); } @action @@ -647,7 +654,7 @@ export class SchemaTable extends React.Component { @computed get reactTable() { - let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; + let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; let hasCollectionChild = this.props.childDocs.reduce((found, doc) => found || doc.type === "collection", false); let expandedRowsList = this._openCollections.map(col => this.props.childDocs.findIndex(doc => doc[Id] === col).toString()); let expanded = {}; -- cgit v1.2.3-70-g09d2 From db560a8c43f77b9342e55a48dd96f695813b32ef Mon Sep 17 00:00:00 2001 From: yipstanley Date: Thu, 25 Jul 2019 12:53:09 -0400 Subject: oof a lot of stuff here --- .../views/collections/CollectionSchemaView.scss | 1 + .../views/collections/CollectionSchemaView.tsx | 2 + .../views/collections/CollectionStackingView.tsx | 5 +- .../views/collections/CollectionTreeView.scss | 27 ++- .../views/collections/CollectionTreeView.tsx | 2 + src/client/views/collections/CollectionView.tsx | 18 +- .../views/collections/CollectionViewChromes.scss | 258 +++++++++++---------- .../views/collections/CollectionViewChromes.tsx | 137 ++++++----- .../authentication/models/current_user_utils.ts | 4 + 9 files changed, 251 insertions(+), 203 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 186e006f3..1e6d1fe99 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -12,6 +12,7 @@ width: 100%; height: 100%; overflow: hidden; + transition: top 0.5s; .collectionSchemaView-cellContents { height: $MAX_ROW_HEIGHT; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 2cf50e551..bdcedea10 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -69,6 +69,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @observable _newKeyName: string = ""; @observable previewScript: string = ""; + @computed get chromeCollapsed() { return this.props.chromeCollapsed; } @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); } @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; } @computed get tableWidth() { return this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH - this.previewWidth(); } @@ -390,6 +391,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { render() { return (
this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}> {this.reactTable} {this.dividerDragger} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 31ec80d76..b5c0fb3d6 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -21,8 +21,6 @@ import { List } from "../../../new_fields/List"; import { EditableView } from "../EditableView"; import { CollectionViewProps } from "./CollectionBaseView"; -let valuesCreated = 1; - @observer export class CollectionStackingView extends CollectionSubView(doc => doc) { _masonryGridRef: HTMLDivElement | null = null; @@ -33,7 +31,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { _columnStart: number = 0; @observable private cursor: CursorProperty = "grab"; get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); } - get chromeCollapsed() { return this.props.chromeCollapsed; } + @computed get chromeCollapsed() { return this.props.chromeCollapsed; } @computed get xMargin() { return NumCast(this.props.Document.xMargin, 2 * this.gridGap); } @computed get yMargin() { return NumCast(this.props.Document.yMargin, 2 * this.gridGap); } @computed get gridGap() { return NumCast(this.props.Document.gridGap, 10); } @@ -84,7 +82,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { () => StrCast(this.props.Document.sectionFilter), () => { this.props.Document.sectionHeaders = new List(); - valuesCreated = 1; } ) } diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index 5205f4313..db3652ff6 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -31,6 +31,7 @@ margin-top: 4px; transform: scale(1.3, 1.3); } + .editableView-container { font-weight: bold; } @@ -43,18 +44,20 @@ display: inline; } - .editableView-input, .editableView-container-editing { + .editableView-input, + .editableView-container-editing { display: block; text-overflow: ellipsis; font-size: 24px; white-space: nowrap; } } + .collectionTreeView-keyHeader { font-style: italic; font-size: 8pt; margin-left: 3px; - display:none; + display: none; background: lightgray; } @@ -72,28 +75,31 @@ // width:100%;//width: max-content; } + .treeViewItem-openRight { display: none; } .treeViewItem-border { - display:inherit; + display: inherit; border-left: dashed 1px #00000042; } .treeViewItem-header:hover { .collectionTreeView-keyHeader { - display:inherit; + display: inherit; } + .treeViewItem-openRight { display: inline-block; - height:13px; - margin-top:2px; + height: 13px; + margin-top: 2px; margin-left: 5px; + // display: inline; svg { - display:block; - padding:0px; + display: block; + padding: 0px; margin: 0px; } } @@ -101,14 +107,17 @@ .treeViewItem-header { border: transparent 1px solid; - display:flex; + display: flex; } + .treeViewItem-header-above { border-top: black 1px solid; } + .treeViewItem-header-below { border-bottom: black 1px solid; } + .treeViewItem-header-inside { border: black 1px solid; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index d05cc375e..cbf32c667 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -456,6 +456,8 @@ export class CollectionTreeView extends CollectionSubView(Document) { private treedropDisposer?: DragManager.DragDropDisposer; private _mainEle?: HTMLDivElement; + @computed get chromeCollapsed() { return this.props.chromeCollapsed; } + protected createTreeDropTarget = (ele: HTMLDivElement) => { this.treedropDisposer && this.treedropDisposer(); if (this._mainEle = ele) { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index e2f652908..1c6dd661d 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -18,7 +18,7 @@ import { CollectionTreeView } from "./CollectionTreeView"; import { StrCast, PromiseValue } from '../../../new_fields/Types'; import { DocumentType } from '../../documents/Documents'; import { CollectionStackingViewChrome, CollectionViewBaseChrome } from './CollectionViewChromes'; -import { observable } from 'mobx'; +import { observable, action, runInAction } from 'mobx'; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh); @@ -37,11 +37,20 @@ export class CollectionView extends React.Component { public static LayoutString(fieldStr: string = "data", fieldExt: string = "") { return FieldView.LayoutString(CollectionView, fieldStr, fieldExt); } + componentDidMount = () => { + // chrome status is one of disabled, collapsed, or visible. this determines initial state from document + let chromeStatus = this.props.Document.chromeStatus; + if (chromeStatus && (chromeStatus === "disabled" || chromeStatus === "collapsed")) { + runInAction(() => this._collapsed = true); + } + } + private SubViewHelper = (type: CollectionViewType, renderProps: CollectionRenderProps) => { let props = { ...this.props, ...renderProps }; switch (this.isAnnotationOverlay ? CollectionViewType.Freeform : type) { case CollectionViewType.Schema: return (); - case CollectionViewType.Docking: return (); + // currently cant think of a reason for collection docking view to have a chrome. mind may change if we ever have nested docking views -syip + case CollectionViewType.Docking: return (); case CollectionViewType.Tree: return (); case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } @@ -52,12 +61,15 @@ export class CollectionView extends React.Component { return (null); } + @action private collapse = (value: boolean) => { this._collapsed = value; + this.props.Document.chromeStatus = value ? "collapsed" : "visible"; } private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => { - if (this.isAnnotationOverlay || this.props.Document === CurrentUserUtils.UserDocument.sidebar) { + // currently cant think of a reason for collection docking view to have a chrome. mind may change if we ever have nested docking views -syip + if (this.isAnnotationOverlay || this.props.Document.chromeStatus === "disabled" || type === CollectionViewType.Docking) { return [(null), this.SubViewHelper(type, renderProps)]; } else { diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index d37228bde..0faca0607 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -1,167 +1,171 @@ @import "../globalCssVariables"; @import '~js-datepicker/dist/datepicker.min.css'; -.collectionViewChrome { - display: grid; - grid-template-columns: 1fr auto; - padding-bottom: 10px; - border-bottom: .5px solid lightgrey; - margin: 10px; +.collectionViewChrome-cont { position: relative; z-index: 9001; transition: top .5s; + background: rgb(238, 238, 238); + padding: 10px; - .collectionViewBaseChrome { - display: flex; + .collectionViewChrome { + display: grid; + grid-template-columns: 1fr auto; + padding-bottom: 10px; + border-bottom: .5px solid lightgrey; - .collectionViewBaseChrome-viewPicker { - font-size: 75%; - text-transform: uppercase; - letter-spacing: 2px; - background: rgb(238, 238, 238); - color: grey; - outline-color: black; - border: none; - padding: 12px 10px 11px 10px; - margin-left: 50px; - } - - .collectionViewBaseChrome-viewPicker:active { - outline-color: black; - } - - .collectionViewBaseChrome-collapse { - transition: all .5s; - position: absolute; - width: 40px; - } - - .collectionViewBaseChrome-viewSpecs { - margin-left: 10px; - display: grid; + .collectionViewBaseChrome { + display: flex; - .collectionViewBaseChrome-viewSpecsInput { - padding: 12px 10px 11px 10px; - border: 0px; - color: grey; - text-align: center; + .collectionViewBaseChrome-viewPicker { + font-size: 75%; text-transform: uppercase; letter-spacing: 2px; - outline-color: black; - font-size: 75%; background: rgb(238, 238, 238); - height: 100%; - width: 150px; + color: grey; + outline-color: black; + border: none; + padding: 12px 10px 11px 10px; + margin-left: 50px; + } + + .collectionViewBaseChrome-viewPicker:active { + outline-color: black; } - .collectionViewBaseChrome-viewSpecsMenu { - overflow: hidden; - transition: height .5s, display .5s; + .collectionViewBaseChrome-collapse { + transition: all .5s; position: absolute; - top: 60px; - z-index: 100; - display: flex; - flex-direction: column; - background: rgb(238, 238, 238); - box-shadow: grey 2px 2px 4px; + width: 40px; + } - .qs-datepicker { - left: unset; - right: 0; + .collectionViewBaseChrome-viewSpecs { + margin-left: 10px; + display: grid; + + .collectionViewBaseChrome-viewSpecsInput { + padding: 12px 10px 11px 10px; + border: 0px; + color: grey; + text-align: center; + text-transform: uppercase; + letter-spacing: 2px; + outline-color: black; + font-size: 75%; + background: rgb(238, 238, 238); + height: 100%; + width: 150px; } - .collectionViewBaseChrome-viewSpecsMenu-row { - display: grid; - grid-template-columns: 150px 200px 150px; - margin-top: 10px; - margin-right: 10px; - - .collectionViewBaseChrome-viewSpecsMenu-rowLeft, - .collectionViewBaseChrome-viewSpecsMenu-rowMiddle, - .collectionViewBaseChrome-viewSpecsMenu-rowRight { - font-size: 75%; - letter-spacing: 2px; - color: grey; - margin-left: 10px; - padding: 5px; - border: none; - outline-color: black; + .collectionViewBaseChrome-viewSpecsMenu { + overflow: hidden; + transition: height .5s, display .5s; + position: absolute; + top: 60px; + z-index: 100; + display: flex; + flex-direction: column; + background: rgb(238, 238, 238); + box-shadow: grey 2px 2px 4px; + + .qs-datepicker { + left: unset; + right: 0; } - } - .collectionViewBaseChrome-viewSpecsMenu-lastRow { - display: grid; - grid-template-columns: 1fr 1fr; - grid-gap: 10px; - margin: 10px; + .collectionViewBaseChrome-viewSpecsMenu-row { + display: grid; + grid-template-columns: 150px 200px 150px; + margin-top: 10px; + margin-right: 10px; + + .collectionViewBaseChrome-viewSpecsMenu-rowLeft, + .collectionViewBaseChrome-viewSpecsMenu-rowMiddle, + .collectionViewBaseChrome-viewSpecsMenu-rowRight { + font-size: 75%; + letter-spacing: 2px; + color: grey; + margin-left: 10px; + padding: 5px; + border: none; + outline-color: black; + } + } + + .collectionViewBaseChrome-viewSpecsMenu-lastRow { + display: grid; + grid-template-columns: 1fr 1fr; + grid-gap: 10px; + margin: 10px; + } } } } - } - .collectionStackingViewChrome-cont { - display: flex; - justify-content: space-between; - } + .collectionStackingViewChrome-cont { + display: flex; + justify-content: space-between; + } - .collectionStackingViewChrome-sort { - display: flex; - align-items: center; - justify-content: space-between; + .collectionStackingViewChrome-sort { + display: flex; + align-items: center; + justify-content: space-between; - .collectionStackingViewChrome-sortIcon { - transition: transform .5s; - margin-left: 10px; + .collectionStackingViewChrome-sortIcon { + transition: transform .5s; + margin-left: 10px; + } } - } - - button:hover { - transform: scale(1); - } + button:hover { + transform: scale(1); + } - .collectionStackingViewChrome-sectionFilter-cont { - justify-self: right; - display: flex; - font-size: 75%; - text-transform: uppercase; - letter-spacing: 2px; - .collectionStackingViewChrome-sectionFilter-label { - vertical-align: center; - padding: 10px; - } + .collectionStackingViewChrome-sectionFilter-cont { + justify-self: right; + display: flex; + font-size: 75%; + text-transform: uppercase; + letter-spacing: 2px; - .collectionStackingViewChrome-sectionFilter { - color: white; - width: 100px; - text-align: center; - background: rgb(238, 238, 238); + .collectionStackingViewChrome-sectionFilter-label { + vertical-align: center; + padding: 10px; + } - .editable-view-input, - input, - .editableView-container-editing-oneLine, - .editableView-container-editing { - padding: 12px 10px 11px 10px; - border: 0px; - color: grey; + .collectionStackingViewChrome-sectionFilter { + color: white; + width: 100px; text-align: center; - text-transform: uppercase; - letter-spacing: 2px; - outline-color: black; - height: 100%; - } + background: rgb(238, 238, 238); - .react-autosuggest__container { - margin: 0; - color: grey; - padding: 0px; + .editable-view-input, + input, + .editableView-container-editing-oneLine, + .editableView-container-editing { + padding: 12px 10px 11px 10px; + border: 0px; + color: grey; + text-align: center; + text-transform: uppercase; + letter-spacing: 2px; + outline-color: black; + height: 100%; + } + + .react-autosuggest__container { + margin: 0; + color: grey; + padding: 0px; + } } } - } - .collectionStackingViewChrome-sectionFilter:hover { - cursor: text; + .collectionStackingViewChrome-sectionFilter:hover { + cursor: text; + } } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 24d13d5cb..4129781f7 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -47,6 +47,20 @@ export class CollectionViewBaseChrome extends React.Component { this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[0][1] = value)} />, ""]); this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[1][1] = value)} />, ""]); + + // chrome status is one of disabled, collapsed, or visible. this determines initial state from document + let chromeStatus = this.props.CollectionView.props.Document.chromeStatus; + if (chromeStatus) { + if (chromeStatus === "disabled") { + throw new Error("how did you get here, if chrome status is 'disabled' on a collection, a chrome shouldn't even be instantiated!"); + } + else if (chromeStatus === "collapsed") { + this._collapsed = true; + if (this.props.collapse) { + this.props.collapse(true); + } + } + } }); } @@ -130,11 +144,12 @@ export class CollectionViewBaseChrome extends React.Component { this._collapsed = !this._collapsed; - this.props.collapse(this._collapsed); + if (this.props.collapse) { + this.props.collapse(this._collapsed); + } } subChrome = () => { - switch (this.props.type) { case CollectionViewType.Stacking: return ( -
- - -
- -
- {this._keyRestrictions.map(i => i[0])} -
-
- CREATED WITHIN: -
- - +
+
+
+ + +
+ +
+ {this._keyRestrictions.map(i => i[0])} +
+
+ CREATED WITHIN:
-
-
+
+ - +
+ {this.subChrome()}
- {this.subChrome()}
) } diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 1c52a3f11..41eb1aa0c 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -50,6 +50,7 @@ export class CurrentUserUtils { if (doc.workspaces === undefined) { const workspaces = Docs.Create.TreeDocument([], { title: "Workspaces", height: 100 }); workspaces.excludeFromLibrary = true; + workspaces.chromeStatus = "disabled"; workspaces.workspaceLibrary = true; workspaces.boxShadow = "0 0"; doc.workspaces = workspaces; @@ -57,6 +58,7 @@ export class CurrentUserUtils { if (doc.recentlyClosed === undefined) { const recentlyClosed = Docs.Create.TreeDocument([], { title: "Recently Closed", height: 75 }); recentlyClosed.excludeFromLibrary = true; + recentlyClosed.chromeStatus = "disabled"; recentlyClosed.boxShadow = "0 0"; doc.recentlyClosed = recentlyClosed; } @@ -65,11 +67,13 @@ export class CurrentUserUtils { sidebar.excludeFromLibrary = true; sidebar.gridGap = 5; sidebar.xMargin = 5; + sidebar.chromeStatus = "disabled"; sidebar.yMargin = 5; Doc.GetProto(sidebar).backgroundColor = "#aca3a6"; sidebar.boxShadow = "1 1 3"; doc.sidebar = sidebar; } + doc.chromeStatus = "disabled"; StrCast(doc.title).indexOf("@") !== -1 && (doc.title = StrCast(doc.title).split("@")[0] + "'s Library"); } -- cgit v1.2.3-70-g09d2 From bf5911a4de0b6f7e3d73b91b747bfeec89ff4b94 Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 25 Jul 2019 12:58:26 -0400 Subject: minor updates --- src/client/views/collections/CollectionSchemaMovableTableHOC.tsx | 6 +++++- src/client/views/collections/CollectionSchemaView.tsx | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 70d6fbc7b..f45575143 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -90,6 +90,10 @@ export class MovableColumn extends React.Component { return onItemDown; } + // onColDrag = (e: React.DragEvent, ref: React.RefObject) => { + // this.setupDrag(reference); + // } + render() { let reference = React.createRef(); @@ -98,7 +102,7 @@ export class MovableColumn extends React.Component { return (
-
+
{this.props.columnRenderer}
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index ed2c88f19..ab1c85416 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -212,6 +212,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { isFocused={this.isFocused} setFocused={this.setFocused} setPreviewDoc={this.setPreviewDoc} + deleteDocument={this.props.removeDocument} /> ); } @@ -254,6 +255,7 @@ export interface SchemaTableProps { ContainingCollectionView: Opt; fieldKey: string; renderDepth: number; + deleteDocument: (document: Doc) => boolean; moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; ScreenToLocalTransform: () => Transform; // CreateDropTarget: (ele: HTMLDivElement)=> void; // super createdriotarget -- cgit v1.2.3-70-g09d2 From 344e2563477fc4524cb287b55a9d5f29d64d4e14 Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 25 Jul 2019 15:56:18 -0400 Subject: deletign docs is fine in schema --- .../views/collections/CollectionSchemaView.tsx | 52 ++++++++++++++-------- 1 file changed, 34 insertions(+), 18 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index ab1c85416..aa36b8584 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -198,7 +198,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { Document={this.props.Document} // child doc PanelHeight={this.props.PanelHeight} PanelWidth={this.props.PanelWidth} - childDocs={this.childDocs} + // childDocs={this.childDocs} CollectionView={this.props.CollectionView} ContainingCollectionView={this.props.ContainingCollectionView} fieldKey={this.props.fieldKey} // might just be this. @@ -213,6 +213,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { setFocused={this.setFocused} setPreviewDoc={this.setPreviewDoc} deleteDocument={this.props.removeDocument} + dataDoc={this.props.DataDoc} /> ); } @@ -248,9 +249,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { export interface SchemaTableProps { Document: Doc; // child doc + dataDoc?: Doc; PanelHeight: () => number; PanelWidth: () => number; - childDocs: Doc[]; + // childDocs: Doc[]; CollectionView: CollectionView | CollectionPDFView | CollectionVideoView; ContainingCollectionView: Opt; fieldKey: string; @@ -295,7 +297,10 @@ export class SchemaTable extends React.Component { let focusedCol = this._focusedCell.col; let isEditable = !this._headerIsEditing;// && this.props.isSelected(); - if (this.props.childDocs.reduce((found, doc) => found || doc.type === "collection", false)) { + let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + let children = DocListCast(cdoc[this.props.fieldKey]); + + if (children.reduce((found, doc) => found || doc.type === "collection", false)) { columns.push( { expander: true, @@ -405,9 +410,10 @@ export class SchemaTable extends React.Component { } tableRemoveDoc = (document: Doc): boolean => { - let index = this.props.childDocs.findIndex(d => d === document); - if (index !== -1) { - this.props.childDocs.splice(index, 1); + let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + if (children.indexOf(document) !== -1) { + children.splice(children.indexOf(document), 1); return true; } return false; @@ -422,6 +428,7 @@ export class SchemaTable extends React.Component { ScreenToLocalTransform: this.props.ScreenToLocalTransform, addDoc: this.tableAddDoc, removeDoc: this.tableRemoveDoc, + // removeDoc: this.props.deleteDocument, rowInfo, rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document), textWrapRow: this.textWrapRow, @@ -501,9 +508,11 @@ export class SchemaTable extends React.Component { @action changeFocusedCellByDirection = (direction: string): void => { + let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); switch (direction) { case "tab": - if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === this.props.childDocs.length) { + if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === children.length) { this._focusedCell = { row: 0, col: 0 }; } else if (this._focusedCell.col + 1 === this.columns.length) { this._focusedCell = { row: this._focusedCell.row + 1, col: 0 }; @@ -521,19 +530,23 @@ export class SchemaTable extends React.Component { this._focusedCell = { row: this._focusedCell.row === 0 ? this._focusedCell.row : this._focusedCell.row - 1, col: this._focusedCell.col }; break; case "down": - this._focusedCell = { row: this._focusedCell.row + 1 === this.props.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col }; + this._focusedCell = { row: this._focusedCell.row + 1 === children.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col }; break; } - let doc = this.props.childDocs[this._focusedCell.row]; - this.props.setPreviewDoc(doc); + const pdoc = FieldValue(children[this._focusedCell.row]); + pdoc && this.props.setPreviewDoc(pdoc); } @action changeFocusedCellByIndex = (row: number, col: number): void => { + let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + this._focusedCell = { row: row, col: col }; this.props.setFocused(this.props.Document); - let doc = this.props.childDocs[this._focusedCell.row]; - this.props.setPreviewDoc(doc); + + const fdoc = FieldValue(children[this._focusedCell.row]); + fdoc && this.props.setPreviewDoc(fdoc); } @action @@ -656,18 +669,21 @@ export class SchemaTable extends React.Component { @computed get reactTable() { + let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + let children = DocListCast(cdoc[this.props.fieldKey]); + let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; - let hasCollectionChild = this.props.childDocs.reduce((found, doc) => found || doc.type === "collection", false); - let expandedRowsList = this._openCollections.map(col => this.props.childDocs.findIndex(doc => doc[Id] === col).toString()); + let hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false); + let expandedRowsList = this._openCollections.map(col => children.findIndex(doc => doc[Id] === col).toString()); let expanded = {}; expandedRowsList.forEach(row => expanded[row] = true); console.log(...[...this._textWrappedRows]); // TODO: get component to rerender on text wrap change without needign to console.log :(((( return { SubComponent={hasCollectionChild ? row => { if (row.original.type === "collection") { - let childDocs = DocListCast(row.original[this.props.fieldKey]); - return
; + // let childDocs = DocListCast(row.original[this.props.fieldKey]); + return
; } } : undefined} -- cgit v1.2.3-70-g09d2 From d7444d7de920a0081a54042db32702273c91865e Mon Sep 17 00:00:00 2001 From: Fawn Date: Fri, 26 Jul 2019 17:58:11 -0400 Subject: clicking cell will focus table --- src/client/views/collections/CollectionSchemaView.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 60644b741..c6550560a 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -101,7 +101,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action setPreviewDoc = (doc: Doc): void => { - console.log("set"); this.previewDoc = doc; } @@ -136,6 +135,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { onPointerDown = (e: React.PointerEvent): void => { if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) { if (this.props.isSelected()) e.stopPropagation(); + else { + this.props.select(false); + } } } @@ -149,7 +151,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { get previewDocument(): Doc | undefined { let selected = this.previewDoc; let pdc = selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined; - console.log("preview document", pdc); return pdc; } @@ -231,7 +232,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } render() { - // if (SelectionManager.SelectedDocuments().length > 0) console.log(StrCast(SelectionManager.SelectedDocuments()[0].Document.title)); // if (DocumentManager.Instance.getDocumentView(this.props.Document)) console.log(StrCast(this.props.Document.title), SelectionManager.IsSelected(DocumentManager.Instance.getDocumentView(this.props.Document)!)) return ( @@ -549,7 +549,6 @@ export class SchemaTable extends React.Component { } createRow = () => { - console.log("creating row"); let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); @@ -679,6 +678,7 @@ export class SchemaTable extends React.Component { @computed get reactTable() { + let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; let children = DocListCast(cdoc[this.props.fieldKey]); -- cgit v1.2.3-70-g09d2 From eb24b07405b902f34f9b335ef86f5ec2c6d7d062 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Fri, 26 Jul 2019 22:16:57 -0400 Subject: ui improvements --- src/client/views/ContextMenu.scss | 48 +++++++++++++++++----- src/client/views/ContextMenu.tsx | 4 +- src/client/views/ContextMenuItem.tsx | 6 +-- src/client/views/MainView.tsx | 2 +- .../views/collections/CollectionSchemaView.tsx | 6 +-- .../views/collections/CollectionTreeView.tsx | 8 ++-- src/client/views/collections/CollectionView.tsx | 5 ++- src/client/views/nodes/DocumentView.tsx | 23 +++++++---- src/client/views/nodes/FormattedTextBox.tsx | 6 +-- src/client/views/nodes/IconBox.tsx | 10 +++-- src/client/views/nodes/VideoBox.tsx | 6 ++- src/client/views/search/SearchItem.tsx | 7 ++-- 12 files changed, 85 insertions(+), 46 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 254163b53..195304b2c 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -6,6 +6,9 @@ z-index: $contextMenu-zindex; box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw; flex-direction: column; + background: whitesmoke; + padding-bottom: 10px; + border-radius: 15px; } // .contextMenu-item:first-child { @@ -33,7 +36,7 @@ .contextMenu-item { // width: 11vw; //10vw height: 30px; //2vh - background: #DDDDDD; + background: whitesmoke; display: flex; //comment out to allow search icon to be inline with search text justify-content: left; align-items: center; @@ -44,13 +47,22 @@ -ms-user-select: none; user-select: none; transition: all .1s; + border-style: none; + // padding: 10px 0px 10px 0px; + white-space: nowrap; + font-size: 13px; + color: grey; + letter-spacing: 2px; + text-transform: uppercase; + padding-right: 10px; +} + +.contextMenu-item:hover { border-width: .11px; border-style: none; border-color: $intermediate-color; // rgb(187, 186, 186); border-bottom-style: solid; - // padding: 10px 0px 10px 0px; - white-space: nowrap; - font-size: 20px; + border-top-style: solid; } .contextMenu-itemSelected { @@ -60,7 +72,7 @@ .contextMenu-group { // width: 11vw; //10vw height: 30px; //2vh - background: rgb(200, 200, 200); + background: lightgoldenrodyellow; display: flex; //comment out to allow search icon to be inline with search text justify-content: left; align-items: center; @@ -74,27 +86,41 @@ border-width: .11px; border-style: none; border-color: $intermediate-color; // rgb(187, 186, 186); - border-bottom-style: solid; // padding: 10px 0px 10px 0px; white-space: nowrap; - font-size: 20px; + font-size: 13px; + text-transform: uppercase; + letter-spacing: 2px; + padding-left: 5px; } .contextMenu-item:hover { - transition: all 0.1s; + transition: all 0.1s ease; background: $lighter-alt-accent; } .contextMenu-description { - font-size: 20px; + margin-left: 5px; text-align: left; display: inline; //need this? } +.search-icon { + margin: 10px; +} + +.search { + margin-left: 10px; + padding-left: 10px; + border: solid black 1px; + border-radius: 5px; +} + .icon-background { pointer-events: none; - background-color: #DDDDDD; + background-color: transparent; width: 35px; text-align: center; - font-size: 22px; + font-size: 20px; + margin-left: 5px; } \ No newline at end of file diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index c163c56a0..5caf27327 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -165,11 +165,11 @@ export class ContextMenu extends React.Component { const contents = ( <> - + - + {this.menuItems} diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 9bbb97d7e..4a7cd309d 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -10,14 +10,14 @@ library.add(faAngleRight); export interface OriginalMenuProps { description: string; event: () => void; - icon?: IconProp; //maybe should be optional (icon?) + icon: IconProp; //maybe should be optional (icon?) closeMenu?: () => void; } export interface SubmenuProps { description: string; subitems: ContextMenuProps[]; - icon?: IconProp; //maybe should be optional (icon?) + icon: IconProp; //maybe should be optional (icon?) closeMenu?: () => void; } @@ -94,7 +94,7 @@ export class ContextMenuItem extends React.Component {this.props.description} - +
{submenu}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 61a013963..8606b52b3 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -390,7 +390,7 @@ export class MainView extends React.Component { ]; if (!ClientUtils.RELEASE) btns.unshift([React.createRef(), "cat", "Add Cat Image", addImageNode]); - return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 5 }} > + return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 20, bottom: 20 }} > diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 119aa7c19..91137f841 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -1,6 +1,6 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; -import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons'; +import { faCog, faPlus, faTable } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; @@ -34,7 +34,7 @@ import { ComputedField } from "../../../new_fields/ScriptField"; library.add(faCog); -library.add(faPlus); +library.add(faPlus, faTable); // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 @@ -321,7 +321,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { onContextMenu = (e: React.MouseEvent): void => { if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 - ContextMenu.Instance.addItem({ description: "Make DB", event: this.makeDB }); + ContextMenu.Instance.addItem({ description: "Make DB", event: this.makeDB, icon: "table" }); } } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index a1697f9b4..1c7fe4bee 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -1,5 +1,5 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faAngleRight, faCamera, faExpand, faTrash, faBell, faCaretDown, faCaretRight, faArrowsAltH, faCaretSquareDown, faCaretSquareRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; +import { faAngleRight, faCamera, faExpand, faTrash, faBell, faCaretDown, faCaretRight, faArrowsAltH, faCaretSquareDown, faCaretSquareRight, faTrashAlt, faPlus, faMinus } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; @@ -61,7 +61,7 @@ library.add(faCaretRight); library.add(faCaretSquareDown); library.add(faCaretSquareRight); library.add(faArrowsAltH); - +library.add(faPlus, faMinus); @observer /** * Component that takes in a document prop and a boolean whether it's collapsed or not. @@ -520,8 +520,8 @@ export class CollectionTreeView extends CollectionSubView(Document) { onContextMenu = (e: React.MouseEvent): void => { // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout if (!e.isPropagationStopped() && this.props.Document.workspaceLibrary) { // excludeFromLibrary means this is the user document - ContextMenu.Instance.addItem({ description: "Create Workspace", event: undoBatch(() => MainView.Instance.createNewWorkspace()) }); - ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.remove(this.props.Document)) }); + ContextMenu.Instance.addItem({ description: "Create Workspace", event: undoBatch(() => MainView.Instance.createNewWorkspace()), icon: "plus" }); + ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.remove(this.props.Document)), icon: "minus" }); e.stopPropagation(); e.preventDefault(); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 7781b26d9..0695029c7 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -17,6 +17,7 @@ import { CollectionStackingView } from './CollectionStackingView'; import { CollectionTreeView } from "./CollectionTreeView"; import { StrCast, PromiseValue } from '../../../new_fields/Types'; import { DocumentType } from '../../documents/Documents'; +import { faEye } from '@fortawesome/free-regular-svg-icons'; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh); @@ -28,7 +29,7 @@ library.add(faThList); library.add(faFingerprint); library.add(faColumns); library.add(faEllipsisV); -library.add(faImage); +library.add(faImage, faEye); @observer export class CollectionView extends React.Component { @@ -68,7 +69,7 @@ export class CollectionView extends React.Component { break; } } - ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems }); + ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems, icon: "eye" }); ContextMenu.Instance.addItem({ description: "Apply Template", event: undoBatch(() => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight")), icon: "project-diagram" }); } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index bae0b5b96..da72f212c 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -39,6 +39,7 @@ import { OverlayView } from '../OverlayView'; import { ScriptingRepl } from '../ScriptingRepl'; import { ClientUtils } from '../../util/ClientUtils'; import { EditableView } from '../EditableView'; +import { faHandPointer, faHandPointRight } from '@fortawesome/free-regular-svg-icons'; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? library.add(fa.faTrash); @@ -60,7 +61,7 @@ library.add(fa.faCrosshairs); library.add(fa.faDesktop); library.add(fa.faUnlock); library.add(fa.faLock); -library.add(fa.faLaptopCode); +library.add(fa.faLaptopCode, fa.faMale, fa.faCopy, faHandPointRight); // const linkSchema = createSchema({ @@ -547,11 +548,12 @@ export class DocumentView extends DocComponent(Docu subitems.push({ description: "Open Fields", event: this.fieldsClicked, icon: "layer-group" }); cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" }); cm.addItem({ description: BoolCast(this.props.Document.ignoreAspect, false) || !this.props.Document.nativeWidth || !this.props.Document.nativeHeight ? "Freeze" : "Unfreeze", event: this.freezeNativeDimensions, icon: "edit" }); - cm.addItem({ description: "Pin to Pres", event: () => PresentationView.Instance.PinDoc(this.props.Document), icon: "map-pin" }); - cm.addItem({ description: BoolCast(this.props.Document.lockedPosition) ? "Unlock Pos" : "Lock Pos", event: this.toggleLockPosition, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" }); - cm.addItem({ description: "Make Background", event: this.makeBackground, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" }); - cm.addItem({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeBtnClicked, icon: "concierge-bell" }); - cm.addItem({ + cm.addItem({ description: "Pin to Presentation", event: () => PresentationView.Instance.PinDoc(this.props.Document), icon: "map-pin" }); + cm.addItem({ description: BoolCast(this.props.Document.lockedPosition) ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" }); + let makes: ContextMenuProps[] = []; + makes.push({ description: "Make Background", event: this.makeBackground, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" }); + makes.push({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeBtnClicked, icon: "concierge-bell" }); + makes.push({ description: "Make Portal", event: () => { let portal = Docs.Create.FreeformDocument([], { width: this.props.Document[WidthSym]() + 10, height: this.props.Document[HeightSym](), title: this.props.Document.title + ".portal" }); Doc.GetProto(this.props.Document).subBulletDocs = new List([portal]); @@ -562,6 +564,7 @@ export class DocumentView extends DocComponent(Docu this.props.removeDocument && this.props.removeDocument(this.props.Document); }, icon: "window-restore" }); + cm.addItem({ description: "Make...", subitems: makes, icon: "hand-point-right" }); // cm.addItem({ // description: "Find aliases", event: async () => { // const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document); @@ -575,8 +578,10 @@ export class DocumentView extends DocComponent(Docu cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document, false), icon: "crosshairs" }); cm.addItem({ description: "Zoom to Document", event: () => this.props.focus(this.props.Document, true), icon: "search" }); if (!ClientUtils.RELEASE) { - cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "link" }); - cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" }); + let copies: ContextMenuProps[] = []; + copies.push({ description: "Copy URL", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "link" }); + copies.push({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" }); + cm.addItem({ description: "Copy...", subitems: copies, icon: "copy" }); } cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" }); type User = { email: string, userDocumentId: string }; @@ -600,7 +605,7 @@ export class DocumentView extends DocComponent(Docu notifDoc.data = new List([sharedDoc]); } } - } + }, icon: "male" })); } catch { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 0a79677e2..febb567e1 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -1,5 +1,5 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faEdit, faSmile } from '@fortawesome/free-solid-svg-icons'; +import { faEdit, faSmile, faTextHeight } from '@fortawesome/free-solid-svg-icons'; import { action, IReactionDisposer, observable, reaction, runInAction, computed, trace } from "mobx"; import { observer } from "mobx-react"; import { baseKeymap } from "prosemirror-commands"; @@ -38,7 +38,7 @@ import { thisExpression } from 'babel-types'; import { Utils } from '../../../Utils'; library.add(faEdit); -library.add(faSmile); +library.add(faSmile, faTextHeight); // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document // @@ -462,7 +462,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe description: BoolCast(this.props.Document.autoHeight, false) ? "Manual Height" : "Auto Height", event: action(() => Doc.GetProto(this.props.Document).autoHeight = !BoolCast(this.props.Document.autoHeight, false)), icon: "expand-arrows-alt" }); - ContextMenu.Instance.addItem({ description: "Text Funcs...", subitems: subitems }); + ContextMenu.Instance.addItem({ description: "Text Funcs...", subitems: subitems, icon: "text-height" }); } render() { let self = this; diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx index d6ab2a34a..64d869ecf 100644 --- a/src/client/views/nodes/IconBox.tsx +++ b/src/client/views/nodes/IconBox.tsx @@ -1,6 +1,6 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; -import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons'; +import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faTag, faTextHeight } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; @@ -18,7 +18,7 @@ library.add(faCaretUp); library.add(faObjectGroup); library.add(faStickyNote); library.add(faFilePdf); -library.add(faFilm); +library.add(faFilm, faTag, faTextHeight); @observer export class IconBox extends React.Component { @@ -47,13 +47,15 @@ export class IconBox extends React.Component { specificContextMenu = (): void => { ContextMenu.Instance.addItem({ description: BoolCast(this.props.Document.hideLabel) ? "Show label with icon" : "Remove label from icon", - event: this.setLabelField + event: this.setLabelField, + icon: "tag" }); let maxDocs = DocListCast(this.props.Document.maximizedDocs); if (maxDocs.length === 1 && !BoolCast(this.props.Document.hideLabel)) { ContextMenu.Instance.addItem({ description: BoolCast(this.props.Document.useOwnTitle) ? "Use target title for label" : "Use own title label", - event: this.setUseOwnTitleField + event: this.setUseOwnTitleField, + icon: "text-height" }); } } diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 30ad75000..34cb47b20 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -19,10 +19,14 @@ import { positionSchema } from "./DocumentView"; import { FieldView, FieldViewProps } from './FieldView'; import { pageSchema } from "./ImageBox"; import "./VideoBox.scss"; +import { library } from "@fortawesome/fontawesome-svg-core"; +import { faVideo } from "@fortawesome/free-solid-svg-icons"; type VideoDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>; const VideoDocument = makeInterface(positionSchema, pageSchema); +library.add(faVideo); + @observer export class VideoBox extends DocComponent(VideoDocument) { private _reactionDisposer?: IReactionDisposer; @@ -179,7 +183,7 @@ export class VideoBox extends DocComponent(VideoD }, icon: "expand-arrows-alt" }); - ContextMenu.Instance.addItem({ description: "Video Funcs...", subitems: subitems }); + ContextMenu.Instance.addItem({ description: "Video Funcs...", subitems: subitems, icon: "video" }); } } diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index 5c2ced2eb..562594210 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -1,6 +1,6 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; -import { faCaretUp, faChartBar, faFilePdf, faFilm, faGlobeAsia, faImage, faLink, faMusic, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons'; +import { faCaretUp, faChartBar, faFilePdf, faFilm, faGlobeAsia, faImage, faLink, faMusic, faObjectGroup, faStickyNote, faFingerprint } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; @@ -38,7 +38,7 @@ library.add(faFilm); library.add(faMusic); library.add(faLink); library.add(faChartBar); -library.add(faGlobeAsia); +library.add(faGlobeAsia, faFingerprint); @observer export class SelectorContextMenu extends React.Component { @@ -223,7 +223,8 @@ export class SearchItem extends React.Component { ContextMenu.Instance.addItem({ description: "Copy ID", event: () => { Utils.CopyText(this.props.doc[Id]); - } + }, + icon: "fingerprint" }); ContextMenu.Instance.displayMenu(e.clientX, e.clientY); } -- cgit v1.2.3-70-g09d2 From cc806ebbe8d48d1c5a4c3c49231a5d38d6f39943 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 27 Jul 2019 04:12:07 -0400 Subject: fixed a bunch of template and stacking view issues among others. --- src/client/views/DocumentDecorations.tsx | 4 +- src/client/views/GlobalKeyHandler.ts | 1 + src/client/views/MainView.tsx | 2 +- .../views/collections/CollectionDockingView.tsx | 39 +++++-------- .../views/collections/CollectionSchemaView.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 68 +++++++++------------- src/client/views/collections/CollectionView.tsx | 2 - .../collectionFreeForm/CollectionFreeFormView.tsx | 22 +++---- .../views/nodes/CollectionFreeFormDocumentView.tsx | 16 +---- src/client/views/nodes/DocumentView.tsx | 14 +++-- src/new_fields/Doc.ts | 13 ++++- 11 files changed, 75 insertions(+), 108 deletions(-) (limited to 'src/client/views/collections/CollectionSchemaView.tsx') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 255855b45..c08a84742 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -533,7 +533,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> proto.nativeHeight = nheight = doc.height || 0; proto.ignoreAspect = true; } - if (nwidth > 0 && nheight > 0) { + if (nwidth > 0 && nheight > 0 && !BoolCast(proto.ignoreAspect)) { if (Math.abs(dW) > Math.abs(dH)) { if (!fixedAspect) { Doc.SetInPlace(element.props.Document, "nativeWidth", actualdW / (doc.width || 1) * (doc.nativeWidth || 0), true); @@ -553,7 +553,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } else { dW && (doc.width = actualdW); dH && (doc.height = actualdH); - Doc.SetInPlace(element.props.Document, "autoHeight", undefined, true); + dH && Doc.SetInPlace(element.props.Document, "autoHeight", undefined, true); } } }); diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 7477c5b4f..5050f34ab 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -67,6 +67,7 @@ export default class KeyManager { } } MainView.Instance.toggleColorPicker(true); + SelectionManager.DeselectAll(); break; case "delete": case "backspace": diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 61a013963..bfb50bc75 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -407,7 +407,7 @@ export class MainView extends React.Component {
)}
  • -