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/CollectionSchemaCells.tsx | 440 +++++++++++++++++++++ .../views/collections/CollectionSchemaHeaders.tsx | 238 +++++++++++ .../views/collections/CollectionSchemaView.scss | 21 + .../views/collections/CollectionSchemaView.tsx | 286 +++++++++----- 4 files changed, 880 insertions(+), 105 deletions(-) create mode 100644 src/client/views/collections/CollectionSchemaCells.tsx create mode 100644 src/client/views/collections/CollectionSchemaHeaders.tsx (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx new file mode 100644 index 000000000..f15734df6 --- /dev/null +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -0,0 +1,440 @@ +import React = require("react"); +import { action, computed, observable, trace, untracked, toJS } from "mobx"; +import { observer } from "mobx-react"; +import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, Column } from "react-table"; +import "react-table/react-table.css"; +import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils"; +import { Doc, DocListCast, DocListCastAsync, Field, Opt } from "../../../new_fields/Doc"; +import { Id } from "../../../new_fields/FieldSymbols"; +import { SetupDrag, DragManager } from "../../util/DragManager"; +import { CompileScript } from "../../util/Scripting"; +import { Transform } from "../../util/Transform"; +import { COLLECTION_BORDER_WIDTH, MAX_ROW_HEIGHT } from '../globalCssVariables.scss'; +import '../DocumentDecorations.scss'; +import { EditableView } from "../EditableView"; +import { FieldView, FieldViewProps } from "../nodes/FieldView"; +import { CollectionPDFView } from "./CollectionPDFView"; +import "./CollectionSchemaView.scss"; +import { CollectionVideoView } from "./CollectionVideoView"; +import { CollectionView } from "./CollectionView"; +import { NumCast, StrCast, BoolCast } from "../../../new_fields/Types"; + + +export interface CellProps { + row: number; + col: number; + rowProps: CellInfo; + CollectionView: CollectionView | CollectionPDFView | CollectionVideoView; + ContainingCollection: Opt; + Document: Doc; + fieldKey: string; + renderDepth: number; + 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; +} + +@observer +export class CollectionSchemaCell extends React.Component { + @observable protected _isEditing: boolean = false; + protected _focusRef = React.createRef(); + protected _document = this.props.rowProps.original; + + componentDidMount() { + if (this._focusRef.current) { + if (this.props.isFocused) { + this._focusRef.current.className += " focused"; + } else { + this._focusRef.current.className = "collectionSchemaView-cellWrapper"; + } + } + + document.addEventListener("keydown", this.onKeyDown); + } + + componentWillUnmount() { + document.removeEventListener("keydown", this.onKeyDown); + } + + @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); + } + } + + @action + isEditingCallback = (isEditing: boolean): void => { + document.addEventListener("keydown", this.onKeyDown); + this._isEditing = isEditing; + this.props.setIsEditing(isEditing); + } + + @action + onPointerDown = (e: React.PointerEvent): void => { + 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, + 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 = type === undefined ? : type === "number" ? NumCast(field) : type === "boolean" ? (BoolCast(field) ? "true" : "false") : "incorrect type"; + // let contents = typeof field === "number" ? NumCast(field) : "incorrect type"; + + 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)); + }} /> +
+
+ ); + } + + render() { + return this.renderCell(this.props.rowProps); + } +} + +@observer +export class CollectionSchemaNumberCell extends CollectionSchemaCell { + render() { + return this.renderCellWithType("number"); + } +} + +@observer +export class CollectionSchemaBooleanCell extends CollectionSchemaCell { + render() { + return this.renderCellWithType("boolean"); + } +} + +@observer +export class CollectionSchemaStringCell extends CollectionSchemaCell { + render() { + return this.renderCellWithType("string"); + } +} + +@observer +export class CollectionSchemaCheckboxCell extends CollectionSchemaCell { + 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 diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx new file mode 100644 index 000000000..a9d4a0170 --- /dev/null +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -0,0 +1,238 @@ +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 { 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); + +export interface HeaderProps { + keyValue: string; + possibleKeys: string[]; + existingKeys: string[]; + keyType: ColumnType; + typeConst: boolean; + onSelect: (oldKey: string, newKey: string, addnew: boolean) => void; + setIsEditing: (isEditing: boolean) => void; + deleteColumn: (column: string) => void; + setColumnType: (key: string, type: ColumnType) => void; +} + +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"; + + return ( +
+ {this.props.keyValue}
} + addNew={false} + onSelect={this.props.onSelect} + setIsEditing={this.props.setIsEditing} + deleteColumn={this.props.deleteColumn} + onlyShowOptions={false} + setColumnType={this.props.setColumnType} + /> + + ); + } +} + + +export interface AddColumnHeaderProps { + possibleKeys: string[]; + existingKeys: string[]; + onSelect: (oldKey: string, newKey: string, addnew: boolean) => void; + setIsEditing: (isEditing: boolean) => void; +} + +@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 ? <> : */} + +
+ ); + } +} + + + +export interface ColumnMenuProps { + keyValue: string; + possibleKeys: string[]; + existingKeys: string[]; + keyType: ColumnType; + menuButtonContent: JSX.Element; + addNew: boolean; + onSelect: (oldKey: string, newKey: string, addnew: boolean) => void; + setIsEditing: (isEditing: boolean) => void; + deleteColumn: (column: string) => void; + onlyShowOptions: boolean; + setColumnType: (key: string, type: ColumnType) => void; +} +@observer +export class CollectionSchemaColumnMenu extends React.Component { + @observable private _isOpen: boolean = false; + + @action toggleIsOpen = (): void => { + this._isOpen = !this._isOpen; + this.props.setIsEditing(this._isOpen); + } + + setColumnType = (oldKey: string, newKey: string, addnew: boolean) => { + let typeStr = newKey as keyof typeof ColumnType; + let type = ColumnType[typeStr]; + 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); + } + + if (this._isOpen) { + if (this.props.onlyShowOptions) { + return ( +
+ +
+ ); + } else { + return ( +
+ + + +
+ ); + } + } + } + + render() { + return ( + // {this.renderContent()}}> + //
{ this.props.setIsEditing(true); console.log("clicked anchor"); }}>{this.props.menuButton}
+ // +
+
this.toggleIsOpen()}>{this.props.menuButtonContent}
+ {this.renderContent()} +
+ ); + } +} + + +interface KeysDropdownProps { + keyValue: string; + possibleKeys: string[]; + existingKeys: string[]; + 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 = ""; + + @action setSearchTerm = (value: string): void => { this._searchTerm = value; }; + @action setKey = (key: string): void => { this._key = key; }; + + @action + onSelect = (key: string): void => { + this.props.onSelect(this._key, key, this.props.addNew); + this.setKey(key); + } + + onChange = (val: string): void => { + this.setSearchTerm(val); + } + + renderOptions = (): JSX.Element[] | JSX.Element => { + 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; + + let options = keyOptions.map(key => { + return
{ this.onSelect(key); this.setSearchTerm(""); }}>{key}
; + }); + + // 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
); + } + + return options; + } + + render() { + return ( +
+ this.onChange(e.target.value)} > +
+ {this.renderOptions()} +
+
+ ); + } +} diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 186e006f3..4ab38b9d9 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -187,6 +187,27 @@ .documentView-node:first-child { background: $light-color; } + + .ReactTable .rt-thead .rt-resizable-header:last-child { + overflow: visible; + } +} + +.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; + + input { + color: black; + width: 100%; + } } //options menu styling 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') 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') 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 0a39ac7f93f2035115aa929c77ad0e8b797f9fb1 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 18 Jul 2019 01:20:58 -0400 Subject: stackingViewwithSections --- .../views/collections/CollectionStackingView.scss | 10 ++++ .../views/collections/CollectionStackingView.tsx | 57 ++++++++++++++-------- src/client/views/nodes/DocumentView.tsx | 7 ++- 3 files changed, 53 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 7e886304d..b6ad47813 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -1,6 +1,7 @@ @import "../globalCssVariables"; .collectionStackingView { overflow-y: auto; + height: 100%; .collectionStackingView-docView-container { width: 45%; @@ -71,4 +72,13 @@ grid-column-end: span 1; height: 100%; } + .collectionStackingView-sectionHeader { + width: 90%; + background: gray; + text-align: center; + margin-left: 5%; + margin-right: 5%; + color: white; + margin-top: 10px; + } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 6d9e942c9..2f26846af 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -4,7 +4,7 @@ import { action, computed, IReactionDisposer, reaction, untracked, observable, r import { observer } from "mobx-react"; import { Doc, HeightSym, WidthSym } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; -import { BoolCast, NumCast, Cast } from "../../../new_fields/Types"; +import { BoolCast, NumCast, Cast, StrCast } from "../../../new_fields/Types"; import { emptyFunction, Utils } from "../../../Utils"; import { ContextMenu } from "../ContextMenu"; import { CollectionSchemaPreview } from "./CollectionSchemaView"; @@ -15,6 +15,7 @@ import { DragManager } from "../../util/DragManager"; import { DocumentType } from "../../documents/Documents"; import { Transform } from "../../util/Transform"; import { CursorProperty } from "csstype"; +import { string } from "prop-types"; @observer export class CollectionStackingView extends CollectionSubView(doc => doc) { @@ -104,10 +105,9 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { return this.offsetTransform(doc, translate[0], translate[1]); } - @computed - get children() { + children(docs: Doc[]) { this._docXfs.length = 0; - return this.filteredChildren.map((d, i) => { + return docs.map((d, i) => { let layoutDoc = Doc.expandTemplateLayout(d, this.props.DataDoc); let width = () => d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth; let height = () => this.getDocHeight(layoutDoc); @@ -219,28 +219,45 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } }); } - render() { + section(heading: string, docList: Doc[]) { let cols = this.singleColumn ? 1 : Math.max(1, Math.min(this.filteredChildren.length, Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap)))); let templatecols = ""; for (let i = 0; i < cols; i++) templatecols += `${this.columnWidth}px `; + return <> + {heading ?
{heading}
: (null)} +
+ {this.children(docList)} + {this.singleColumn ? (null) : this.columnDragger} +
; + } + render() { + let sectionFilter = StrCast(this.props.Document.sectionFilter); + let fields = new Map(); + sectionFilter && this.filteredChildren.map(d => { + if (!fields.has(d[sectionFilter] as object)) fields.set(d[sectionFilter] as object, [d]); + else fields.get(d[sectionFilter] as object)!.push(d); + }); return (
e.stopPropagation()} > -
- {this.children} - {this.singleColumn ? (null) : this.columnDragger} -
+ {/* {sectionFilter as boolean ? [ + ["width > height", this.filteredChildren.filter(f => f[WidthSym]() >= 1 + f[HeightSym]())], + ["width = height", this.filteredChildren.filter(f => Math.abs(f[WidthSym]() - f[HeightSym]()) < 1)], + ["height > width", this.filteredChildren.filter(f => f[WidthSym]() + 1 <= f[HeightSym]())]]. */} + {sectionFilter ? Array.from(fields.entries()). + map(section => this.section(section[0].toString(), section[1] as Doc[])) : + this.section("", this.filteredChildren)}
); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 01db40fc7..feded711c 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -608,7 +608,12 @@ export class DocumentView extends DocComponent(Docu @computed get nativeWidth() { return this.Document.nativeWidth || 0; } @computed get nativeHeight() { return this.Document.nativeHeight || 0; } @computed get contents() { - return (); + return (); } render() { -- cgit v1.2.3-70-g09d2 From 123027bf525bfb6d635cf2304d01490bccb4abff Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 18 Jul 2019 02:22:27 -0400 Subject: fixes for single column layouts not contained in a free form view. --- .../views/collections/CollectionBaseView.tsx | 3 +-- .../views/collections/CollectionStackingView.tsx | 27 ++++++++++++++++------ 2 files changed, 21 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index eba69b448..2603dc60b 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -78,7 +78,6 @@ export class CollectionBaseView extends React.Component { @action.bound addDocument(doc: Doc, allowDuplicates: boolean = false): boolean { - let self = this; var curPage = NumCast(this.props.Document.curPage, -1); Doc.GetProto(doc).page = curPage; if (curPage >= 0) { @@ -146,7 +145,7 @@ export class CollectionBaseView extends React.Component { const viewtype = this.collectionViewType; return (
{viewtype !== undefined ? this.props.children(viewtype, props) : (null)} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 2f26846af..c42a423c1 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -34,9 +34,18 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { componentDidMount() { this._heightDisposer = reaction(() => [this.yMargin, this.gridGap, this.columnWidth, this.childDocs.map(d => [d.height, d.width, d.zoomBasis, d.nativeHeight, d.nativeWidth, d.isMinimized])], - () => this.singleColumn && - (this.props.Document.height = this.filteredChildren.reduce((height, d, i) => - height + this.getDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap), this.yMargin)) + () => { + if (this.singleColumn) { + let sectionFilter = StrCast(this.props.Document.sectionFilter); + let fields = new Map(); + sectionFilter && this.filteredChildren.map(d => { + if (!fields.has(d[sectionFilter] as object)) fields.set(d[sectionFilter] as object, [d]); + else fields.get(d[sectionFilter] as object)!.push(d); + }); + (this.props.Document.height = fields.size * 50 + this.filteredChildren.reduce((height, d, i) => + height + this.getDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap), this.yMargin)); + } + } , { fireImmediately: true }); } componentWillUnmount() { @@ -112,10 +121,11 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let width = () => d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth; let height = () => this.getDocHeight(layoutDoc); if (this.singleColumn) { + //have to add the height of all previous single column sections or the doc decorations will be in the wrong place. let dxf = () => this.getSingleDocTransform(layoutDoc, i, width()); - let rowHgtPcnt = height() / (this.props.Document[HeightSym]() - 2 * this.yMargin) * 100; + let rowHgtPcnt = height(); this._docXfs.push({ dxf: dxf, width: width, height: height }); - return
+ return
{this.getDisplayDoc(layoutDoc, d, dxf)}
; } else { @@ -231,7 +241,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { padding: this.singleColumn ? `${this.yMargin}px ${this.xMargin}px ${this.yMargin}px ${this.xMargin}px` : `${this.yMargin}px ${this.xMargin}px`, margin: "auto", width: this.singleColumn ? undefined : `${cols * (this.columnWidth + this.gridGap) + 2 * this.xMargin - this.gridGap}px`, - height: this.singleColumn ? "100%" : 'max-content', + height: 'max-content', position: "relative", gridGap: this.gridGap, gridTemplateColumns: this.singleColumn ? undefined : templatecols, @@ -250,7 +260,10 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { else fields.get(d[sectionFilter] as object)!.push(d); }); return ( -
e.stopPropagation()} > +
e.stopPropagation()} > {/* {sectionFilter as boolean ? [ ["width > height", this.filteredChildren.filter(f => f[WidthSym]() >= 1 + f[HeightSym]())], ["width = height", this.filteredChildren.filter(f => Math.abs(f[WidthSym]() - f[HeightSym]()) < 1)], -- cgit v1.2.3-70-g09d2 From 5b69b2cba13f104471dc08e110148704fdc2acca Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 18 Jul 2019 12:45:28 -0400 Subject: fixes for templating miniLayout and detailedLayouts --- src/client/views/DocumentDecorations.tsx | 10 ++++++++-- src/client/views/collections/CollectionView.tsx | 9 ++++++--- src/client/views/nodes/DocumentView.tsx | 11 +++++++++++ src/new_fields/Doc.ts | 10 +++++----- 4 files changed, 30 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index fb5104915..2f7bea365 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -28,6 +28,7 @@ import { RichTextField } from '../../new_fields/RichTextField'; import { LinkManager } from '../util/LinkManager'; import { ObjectField } from '../../new_fields/ObjectField'; import { MetadataEntryMenu } from './MetadataEntryMenu'; +import { ImageBox } from './nodes/ImageBox'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -85,8 +86,13 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> SelectionManager.DeselectAll(); let fieldTemplate = fieldTemplateView.props.Document; let docTemplate = fieldTemplateView.props.ContainingCollectionView!.props.Document; - let metaKey = text.slice(1, text.length); - Doc.MakeTemplate(fieldTemplate, metaKey, Doc.GetProto(docTemplate)); + let metaKey = text.startsWith(">>") ? text.slice(2, text.length) : text.slice(1, text.length); + let proto = Doc.GetProto(docTemplate); + Doc.MakeTemplate(fieldTemplate, metaKey, proto); + if (text.startsWith(">>")) { + proto.detailedLayout = proto.layout; + proto.miniLayout = ImageBox.LayoutString(metaKey); + } } else { if (SelectionManager.SelectedDocuments().length > 0) { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 56750668d..377a46535 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,11 +1,10 @@ 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, faImage, faThList, faTree } from '@fortawesome/free-solid-svg-icons'; import { observer } from "mobx-react"; import * as React from 'react'; -import { Doc } from '../../../new_fields/Doc'; +import { Doc, DocListCast } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; -import { Docs } from '../../documents/Documents'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from '../ContextMenuItem'; @@ -16,6 +15,7 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionStackingView } from './CollectionStackingView'; import { CollectionTreeView } from "./CollectionTreeView"; +import { StrCast, PromiseValue } from '../../../new_fields/Types'; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh); @@ -24,6 +24,7 @@ library.add(faSquare); library.add(faProjectDiagram); library.add(faSignature); library.add(faThList); +library.add(faImage); @observer export class CollectionView extends React.Component { @@ -63,6 +64,8 @@ export class CollectionView extends React.Component { otherdoc.height = 50; Doc.GetProto(otherdoc).title = "applied(" + this.props.Document.title + ")"; Doc.GetProto(otherdoc).layout = Doc.MakeDelegate(this.props.Document); + Doc.GetProto(otherdoc).miniLayout = StrCast(this.props.Document.miniLayout); + Doc.GetProto(otherdoc).detailedLayout = Doc.GetProto(otherdoc).layout; this.props.addDocTab && this.props.addDocTab(otherdoc, undefined, "onRight"); }), icon: "project-diagram" }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index feded711c..899c47cb3 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -291,6 +291,7 @@ export class DocumentView extends DocComponent(Docu if (this._doubleTap && this.props.renderDepth) { let fullScreenAlias = Doc.MakeAlias(this.props.Document); fullScreenAlias.templates = new List(); + if (this.props.Document.layout === this.props.Document.miniLayout) fullScreenAlias.layout = this.props.Document.detailedLayout instanceof Doc ? this.props.Document.detailedLayout : StrCast(this.props.Document.detailedLayout); this.props.addDocTab(fullScreenAlias, this.dataDoc, "inTab"); SelectionManager.DeselectAll(); this.props.Document.libraryBrush = undefined; @@ -555,6 +556,16 @@ export class DocumentView extends DocComponent(Docu this.props.addDocTab && this.props.addDocTab(Docs.Create.SchemaDocument(["title"], aliases, {}), undefined, "onRight"); // bcz: dataDoc? }, icon: "search" }); + if (this.props.Document.detailedLayout && !this.props.Document.isTemplate) { + cm.addItem({ + description: "Toggle detail", event: async () => { + let d = this.props.Document; + let miniLayout = await PromiseValue(d.miniLayout); + let detailLayout = await PromiseValue(d.detailedLayout); + d.layout !== miniLayout ? miniLayout && (d.layout = d.miniLayout) : detailLayout && (d.layout = detailLayout); + }, icon: "image" + }); + } 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" }); cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])), icon: "link" }); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 769c6aa73..7180564ea 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -385,12 +385,12 @@ export namespace Doc { export function MakeDelegate(doc: Doc, id?: string): Doc; export function MakeDelegate(doc: Opt, id?: string): Opt; export function MakeDelegate(doc: Opt, id?: string): Opt { - if (!doc) { - return undefined; + if (doc) { + const delegate = new Doc(id, true); + delegate.proto = doc; + return delegate; } - const delegate = new Doc(id, true); - delegate.proto = doc; - return delegate; + return undefined; } export function MakeTemplate(fieldTemplate: Doc, metaKey: string, proto: Doc) { -- cgit v1.2.3-70-g09d2 From 922c418f1207c43150c499e075a9c1be34719b58 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 18 Jul 2019 17:36:37 -0400 Subject: fixes for stacking view and added detailedLayout --- src/client/views/collections/CollectionStackingView.scss | 5 +++-- src/client/views/collections/CollectionStackingView.tsx | 8 ++++---- src/client/views/collections/CollectionView.tsx | 3 ++- src/client/views/nodes/DocumentView.tsx | 13 ++++--------- src/new_fields/Doc.ts | 11 +++++++++-- 5 files changed, 22 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index b6ad47813..7ebf5f77c 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -1,8 +1,9 @@ @import "../globalCssVariables"; .collectionStackingView { - overflow-y: auto; height: 100%; - + width: 100%; + position: absolute; + overflow-y: auto; .collectionStackingView-docView-container { width: 45%; margin: 5% 2.5%; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index c42a423c1..4424cffe1 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -15,6 +15,7 @@ import { DragManager } from "../../util/DragManager"; import { DocumentType } from "../../documents/Documents"; import { Transform } from "../../util/Transform"; import { CursorProperty } from "csstype"; +import { COLLECTION_BORDER_WIDTH } from "../../views/globalCssVariables.scss"; import { string } from "prop-types"; @observer @@ -107,6 +108,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let { scale, translateX, translateY } = Utils.GetScreenTransform(dref); return this.offsetTransform(doc, translateX, translateY); } + getSingleDocTransform(doc: Doc, ind: number, width: number) { let localY = this.filteredChildren.reduce((height, d, i) => height + (i < ind ? this.getDocHeight(Doc.expandTemplateLayout(d, this.props.DataDoc)) + this.gridGap : 0), this.yMargin); @@ -234,7 +236,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap)))); let templatecols = ""; for (let i = 0; i < cols; i++) templatecols += `${this.columnWidth}px `; - return <> + return
{heading ?
{heading}
: (null)}
doc) { > {this.children(docList)} {this.singleColumn ? (null) : this.columnDragger} -
; +
; } render() { let sectionFilter = StrCast(this.props.Document.sectionFilter); @@ -261,8 +263,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { }); return (
e.stopPropagation()} > {/* {sectionFilter as boolean ? [ ["width > height", this.filteredChildren.filter(f => f[WidthSym]() >= 1 + f[HeightSym]())], diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 377a46535..1b85a0cdb 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -46,6 +46,7 @@ export class CollectionView extends React.Component { get isAnnotationOverlay() { return this.props.fieldExt ? true : false; } + static _applyCount: number = 0; onContextMenu = (e: React.MouseEvent): void => { if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 let subItems: ContextMenuProps[] = []; @@ -62,7 +63,7 @@ export class CollectionView extends React.Component { let otherdoc = new Doc(); otherdoc.width = 100; otherdoc.height = 50; - Doc.GetProto(otherdoc).title = "applied(" + this.props.Document.title + ")"; + Doc.GetProto(otherdoc).title = this.props.Document.title + "(..." + CollectionView._applyCount++ + ")"; // previously "applied" Doc.GetProto(otherdoc).layout = Doc.MakeDelegate(this.props.Document); Doc.GetProto(otherdoc).miniLayout = StrCast(this.props.Document.miniLayout); Doc.GetProto(otherdoc).detailedLayout = Doc.GetProto(otherdoc).layout; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 899c47cb3..76b8658a5 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -291,7 +291,9 @@ export class DocumentView extends DocComponent(Docu if (this._doubleTap && this.props.renderDepth) { let fullScreenAlias = Doc.MakeAlias(this.props.Document); fullScreenAlias.templates = new List(); - if (this.props.Document.layout === this.props.Document.miniLayout) fullScreenAlias.layout = this.props.Document.detailedLayout instanceof Doc ? this.props.Document.detailedLayout : StrCast(this.props.Document.detailedLayout); + if (this.props.Document.layout === this.props.Document.miniLayout) { + Doc.ToggleDetailLayout(fullScreenAlias); + } this.props.addDocTab(fullScreenAlias, this.dataDoc, "inTab"); SelectionManager.DeselectAll(); this.props.Document.libraryBrush = undefined; @@ -557,14 +559,7 @@ export class DocumentView extends DocComponent(Docu }, icon: "search" }); if (this.props.Document.detailedLayout && !this.props.Document.isTemplate) { - cm.addItem({ - description: "Toggle detail", event: async () => { - let d = this.props.Document; - let miniLayout = await PromiseValue(d.miniLayout); - let detailLayout = await PromiseValue(d.detailedLayout); - d.layout !== miniLayout ? miniLayout && (d.layout = d.miniLayout) : detailLayout && (d.layout = detailLayout); - }, icon: "image" - }); + cm.addItem({ description: "Toggle detail", event: () => Doc.ToggleDetailLayout(this.props.Document), icon: "image" }); } 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" }); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 7180564ea..9a4b817d3 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -316,7 +316,7 @@ export namespace Doc { if (extensionDoc === undefined) { setTimeout(() => { let docExtensionForField = new Doc(doc[Id] + fieldKey, true); - docExtensionForField.title = "Extension of " + doc.title + "'s field:" + fieldKey; + docExtensionForField.title = doc.title + ":" + fieldKey + ".ext"; docExtensionForField.extendsDoc = doc; let proto: Doc | undefined = doc; while (proto && !Doc.IsPrototype(proto)) { @@ -351,7 +351,7 @@ export namespace Doc { if (expandedTemplateLayout === undefined && BoolCast(templateLayoutDoc.isTemplate)) { setTimeout(() => { templateLayoutDoc["_expanded_" + dataDoc[Id]] = Doc.MakeDelegate(templateLayoutDoc); - (templateLayoutDoc["_expanded_" + dataDoc[Id]] as Doc).title = templateLayoutDoc.title + " applied to " + dataDoc.title; + (templateLayoutDoc["_expanded_" + dataDoc[Id]] as Doc).title = templateLayoutDoc.title + "[" + StrCast(dataDoc.title).match(/\.\.\.[0-9]*/) + "]"; // previously: "applied to" (templateLayoutDoc["_expanded_" + dataDoc[Id]] as Doc).isExpandedTemplate = templateLayoutDoc; }, 0); } @@ -420,4 +420,11 @@ export namespace Doc { fieldTemplate.showTitle = "title"; setTimeout(() => fieldTemplate.proto = proto); } + + export async function ToggleDetailLayout(d: Doc) { + let miniLayout = await PromiseValue(d.miniLayout); + let detailLayout = await PromiseValue(d.detailedLayout); + d.layout !== miniLayout ? miniLayout && (d.layout = d.miniLayout) : detailLayout && (d.layout = detailLayout); + if (d.layout === detailLayout) Doc.GetProto(d).nativeWidth = Doc.GetProto(d).nativeHeight = undefined; + } } \ No newline at end of file -- 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') 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') 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 2b98b5484b942361ab5e271fe9e09d09dc83fa60 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 19 Jul 2019 00:51:15 -0400 Subject: more cleanup for templates --- src/client/views/collections/CollectionView.tsx | 6 +++--- .../collectionFreeForm/CollectionFreeFormView.tsx | 3 +-- src/client/views/nodes/WebBox.tsx | 16 ---------------- src/new_fields/Doc.ts | 14 +++++++++----- 4 files changed, 13 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 1b85a0cdb..b6b690e26 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -2,7 +2,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faProjectDiagram, faSignature, faSquare, faTh, faImage, faThList, faTree } from '@fortawesome/free-solid-svg-icons'; import { observer } from "mobx-react"; import * as React from 'react'; -import { Doc, DocListCast } from '../../../new_fields/Doc'; +import { Doc, DocListCast, WidthSym, HeightSym } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; import { undoBatch } from '../../util/UndoManager'; @@ -61,8 +61,8 @@ export class CollectionView extends React.Component { ContextMenu.Instance.addItem({ description: "Apply Template", event: undoBatch(() => { let otherdoc = new Doc(); - otherdoc.width = 100; - otherdoc.height = 50; + otherdoc.width = this.props.Document[WidthSym](); + otherdoc.height = this.props.Document[HeightSym](); Doc.GetProto(otherdoc).title = this.props.Document.title + "(..." + CollectionView._applyCount++ + ")"; // previously "applied" Doc.GetProto(otherdoc).layout = Doc.MakeDelegate(this.props.Document); Doc.GetProto(otherdoc).miniLayout = StrCast(this.props.Document.miniLayout); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 58218e641..1997a6a4d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,4 +1,4 @@ -import { action, computed } from "mobx"; +import { action, computed, trace } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCastAsync, HeightSym, WidthSym, DocListCast } from "../../../../new_fields/Doc"; import { Id } from "../../../../new_fields/FieldSymbols"; @@ -516,7 +516,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { ] render() { const easing = () => this.props.Document.panTransformType === "Ease"; - Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey); return (
{ diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 9a4b817d3..7bf1dec53 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -10,6 +10,7 @@ import { RefField, FieldId } from "./RefField"; import { ToScriptString, SelfProxy, Parent, OnUpdate, Self, HandleUpdate, Update, Id } from "./FieldSymbols"; import { scriptingGlobal } from "../client/util/Scripting"; import { List } from "./List"; +import { string } from "prop-types"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -344,20 +345,23 @@ export namespace Doc { // ... which means we 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. - let expandedTemplateLayout = templateLayoutDoc["_expanded_" + dataDoc[Id]]; + let expandedTemplateLayout = dataDoc[templateLayoutDoc[Id]]; if (expandedTemplateLayout instanceof Doc) { return expandedTemplateLayout; } if (expandedTemplateLayout === undefined && BoolCast(templateLayoutDoc.isTemplate)) { setTimeout(() => { - templateLayoutDoc["_expanded_" + dataDoc[Id]] = Doc.MakeDelegate(templateLayoutDoc); - (templateLayoutDoc["_expanded_" + dataDoc[Id]] as Doc).title = templateLayoutDoc.title + "[" + StrCast(dataDoc.title).match(/\.\.\.[0-9]*/) + "]"; // previously: "applied to" - (templateLayoutDoc["_expanded_" + dataDoc[Id]] as Doc).isExpandedTemplate = templateLayoutDoc; + let expandedDoc = Doc.MakeDelegate(templateLayoutDoc); + expandedDoc.title = templateLayoutDoc.title + "[" + StrCast(dataDoc.title).match(/\.\.\.[0-9]*/) + "]"; + expandedDoc.isExpandedTemplate = templateLayoutDoc; + dataDoc[templateLayoutDoc[Id]] = expandedDoc; }, 0); } - return templateLayoutDoc; + return templateLayoutDoc; // use the templateLayout when it's not a template or the expandedTemplate is pending. } + let _pendingExpansions: Map = new Map(); + export function MakeCopy(doc: Doc, copyProto: boolean = false): Doc { const copy = new Doc; Object.keys(doc).forEach(key => { -- 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') 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') 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 ae07ba8fb410752ea98702219247ce5f89d1758b Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 19 Jul 2019 14:42:39 -0400 Subject: fixes for templates and stacking views --- src/client/documents/Documents.ts | 3 ++- src/client/views/collections/CollectionStackingView.tsx | 5 +++-- src/new_fields/Doc.ts | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 3c248760b..11df6c152 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -55,7 +55,8 @@ export enum DocumentType { ICON = "icon", IMPORT = "import", LINK = "link", - LINKDOC = "linkdoc" + LINKDOC = "linkdoc", + TEMPLATE = "template" } export interface DocumentOptions { diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 4424cffe1..039bd7b3a 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -258,8 +258,9 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let sectionFilter = StrCast(this.props.Document.sectionFilter); let fields = new Map(); sectionFilter && this.filteredChildren.map(d => { - if (!fields.has(d[sectionFilter] as object)) fields.set(d[sectionFilter] as object, [d]); - else fields.get(d[sectionFilter] as object)!.push(d); + let sectionValue = (d[sectionFilter] ? d[sectionFilter] : "-undefined-") as object; + if (!fields.has(sectionValue)) fields.set(sectionValue, [d]); + else fields.get(sectionValue)!.push(d); }); return (
fieldTemplate.proto = proto); } -- cgit v1.2.3-70-g09d2 From 64de59fc4250eff5284380ca2743030aa453fce7 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 19 Jul 2019 14:51:36 -0400 Subject: gave templates a type ... but is it the right one? --- src/client/views/collections/CollectionView.tsx | 10 ++++++---- src/new_fields/Doc.ts | 1 - 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index b6b690e26..7e9d35d3d 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -16,6 +16,7 @@ import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionStackingView } from './CollectionStackingView'; import { CollectionTreeView } from "./CollectionTreeView"; import { StrCast, PromiseValue } from '../../../new_fields/Types'; +import { DocumentType } from '../../documents/Documents'; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh); @@ -63,10 +64,11 @@ export class CollectionView extends React.Component { let otherdoc = new Doc(); otherdoc.width = this.props.Document[WidthSym](); otherdoc.height = this.props.Document[HeightSym](); - Doc.GetProto(otherdoc).title = this.props.Document.title + "(..." + CollectionView._applyCount++ + ")"; // previously "applied" - Doc.GetProto(otherdoc).layout = Doc.MakeDelegate(this.props.Document); - Doc.GetProto(otherdoc).miniLayout = StrCast(this.props.Document.miniLayout); - Doc.GetProto(otherdoc).detailedLayout = Doc.GetProto(otherdoc).layout; + otherdoc.title = this.props.Document.title + "(..." + CollectionView._applyCount++ + ")"; // previously "applied" + otherdoc.layout = Doc.MakeDelegate(this.props.Document); + otherdoc.miniLayout = StrCast(this.props.Document.miniLayout); + otherdoc.detailedLayout = otherdoc.layout; + otherdoc.type = DocumentType.TEMPLATE; this.props.addDocTab && this.props.addDocTab(otherdoc, undefined, "onRight"); }), icon: "project-diagram" }); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index c6b364d8e..2ad6ae5f0 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -423,7 +423,6 @@ export namespace Doc { fieldTemplate.nativeHeight = nh; fieldTemplate.isTemplate = true; fieldTemplate.showTitle = "title"; - fieldTemplate.type = DocumentType.TEMPLATE; setTimeout(() => fieldTemplate.proto = proto); } -- cgit v1.2.3-70-g09d2 From 5e9bcf2e35415fd0ab4dec4f0141511cd4d312d0 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 19 Jul 2019 16:03:09 -0400 Subject: split masonry collection view into its own view type. --- src/client/documents/Documents.ts | 4 ++ .../views/collections/CollectionBaseView.tsx | 3 +- .../views/collections/CollectionStackingView.tsx | 58 +++++++--------------- src/client/views/collections/CollectionView.tsx | 10 ++-- 4 files changed, 32 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 11df6c152..47ed33adf 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -410,6 +410,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Stacking }); } + export function MasonryDocument(documents: Array, options: DocumentOptions) { + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Masonry }); + } + export function DockDocument(documents: Array, config: string, options: DocumentOptions, id?: string) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id); } diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 2603dc60b..72faf52c4 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -18,7 +18,8 @@ export enum CollectionViewType { Schema, Docking, Tree, - Stacking + Stacking, + Masonry } export interface CollectionRenderProps { diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 039bd7b3a..0e5f9a321 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -6,7 +6,6 @@ import { Doc, HeightSym, WidthSym } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { BoolCast, NumCast, Cast, StrCast } from "../../../new_fields/Types"; import { emptyFunction, Utils } from "../../../Utils"; -import { ContextMenu } from "../ContextMenu"; import { CollectionSchemaPreview } from "./CollectionSchemaView"; import "./CollectionStackingView.scss"; import { CollectionSubView } from "./CollectionSubView"; @@ -15,16 +14,14 @@ import { DragManager } from "../../util/DragManager"; import { DocumentType } from "../../documents/Documents"; import { Transform } from "../../util/Transform"; import { CursorProperty } from "csstype"; -import { COLLECTION_BORDER_WIDTH } from "../../views/globalCssVariables.scss"; -import { string } from "prop-types"; @observer export class CollectionStackingView extends CollectionSubView(doc => doc) { _masonryGridRef: HTMLDivElement | null = null; _draggerRef = React.createRef(); _heightDisposer?: IReactionDisposer; - _gridSize = 1; _docXfs: any[] = []; + _columnStart: number = 0; @observable private cursor: CursorProperty = "grab"; @computed get xMargin() { return NumCast(this.props.Document.xMargin, 2 * this.gridGap); } @computed get yMargin() { return NumCast(this.props.Document.yMargin, 2 * this.gridGap); } @@ -33,24 +30,25 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @computed get columnWidth() { return this.singleColumn ? (this.props.PanelWidth() / (this.props as any).ContentScaling() - 2 * this.xMargin) : Math.min(this.props.PanelWidth() - 2 * this.xMargin, NumCast(this.props.Document.columnWidth, 250)); } @computed get filteredChildren() { return this.childDocs.filter(d => !d.isMinimized); } + @computed get Sections() { + let sectionFilter = StrCast(this.props.Document.sectionFilter); + let fields = new Map(); + sectionFilter && this.filteredChildren.map(d => { + let sectionValue = (d[sectionFilter] ? d[sectionFilter] : "-undefined-") as object; + if (!fields.has(sectionValue)) fields.set(sectionValue, [d]); + else fields.get(sectionValue)!.push(d); + }); + return fields; + } componentDidMount() { this._heightDisposer = reaction(() => [this.yMargin, this.gridGap, this.columnWidth, this.childDocs.map(d => [d.height, d.width, d.zoomBasis, d.nativeHeight, d.nativeWidth, d.isMinimized])], - () => { - if (this.singleColumn) { - let sectionFilter = StrCast(this.props.Document.sectionFilter); - let fields = new Map(); - sectionFilter && this.filteredChildren.map(d => { - if (!fields.has(d[sectionFilter] as object)) fields.set(d[sectionFilter] as object, [d]); - else fields.get(d[sectionFilter] as object)!.push(d); - }); - (this.props.Document.height = fields.size * 50 + this.filteredChildren.reduce((height, d, i) => - height + this.getDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap), this.yMargin)); - } - } + () => this.singleColumn && + (this.props.Document.height = this.Sections.size * 50 + this.filteredChildren.reduce((height, d, i) => + height + this.getDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap), this.yMargin)) , { fireImmediately: true }); } componentWillUnmount() { - if (this._heightDisposer) this._heightDisposer(); + this._heightDisposer && this._heightDisposer(); } @action @@ -98,7 +96,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { return (nw && nh) ? wid * aspect : d[HeightSym](); } - offsetTransform(doc: Doc, translateX: number, translateY: number) { let outerXf = Utils.GetScreenTransform(this._masonryGridRef!); let offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); @@ -133,7 +130,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } else { let dref = React.createRef(); let dxf = () => this.getDocTransform(layoutDoc, dref.current!); - let rowSpan = Math.ceil((height() + this.gridGap) / (this._gridSize + this.gridGap)); + let rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap); this._docXfs.push({ dxf: dxf, width: width, height: height }); return
{this.getDisplayDoc(layoutDoc, d, dxf)} @@ -142,7 +139,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { }); } - _columnStart: number = 0; columnDividerDown = (e: React.PointerEvent) => { e.stopPropagation(); e.preventDefault(); @@ -156,7 +152,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let dragPos = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0]; let delta = dragPos - this._columnStart; this._columnStart = dragPos; - this.props.Document.columnWidth = this.columnWidth + delta; } @@ -172,14 +167,6 @@ export class CollectionStackingView 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: "Toggle multi-column", - event: () => this.props.Document.singleColumn = !BoolCast(this.props.Document.singleColumn, true), icon: "file-pdf" - }); - } - } @undoBatch @action @@ -247,7 +234,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { position: "relative", gridGap: this.gridGap, gridTemplateColumns: this.singleColumn ? undefined : templatecols, - gridAutoRows: this.singleColumn ? undefined : `${this._gridSize}px` + gridAutoRows: this.singleColumn ? undefined : "0px" }} > {this.children(docList)} @@ -255,21 +242,14 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
; } render() { - let sectionFilter = StrCast(this.props.Document.sectionFilter); - let fields = new Map(); - sectionFilter && this.filteredChildren.map(d => { - let sectionValue = (d[sectionFilter] ? d[sectionFilter] : "-undefined-") as object; - if (!fields.has(sectionValue)) fields.set(sectionValue, [d]); - else fields.get(sectionValue)!.push(d); - }); return (
e.stopPropagation()} > + ref={this.createRef} onDrop={this.onDrop.bind(this)} onWheel={(e: React.WheelEvent) => e.stopPropagation()} > {/* {sectionFilter as boolean ? [ ["width > height", this.filteredChildren.filter(f => f[WidthSym]() >= 1 + f[HeightSym]())], ["width = height", this.filteredChildren.filter(f => Math.abs(f[WidthSym]() - f[HeightSym]()) < 1)], ["height > width", this.filteredChildren.filter(f => f[WidthSym]() + 1 <= f[HeightSym]())]]. */} - {sectionFilter ? Array.from(fields.entries()). + {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()). map(section => this.section(section[0].toString(), section[1] as Doc[])) : this.section("", this.filteredChildren)}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 7e9d35d3d..045c8531e 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, faImage, faThList, faTree } from '@fortawesome/free-solid-svg-icons'; +import { faProjectDiagram, faSignature, faColumns, faSquare, faTh, faImage, faThList, faTree, faEllipsisV } from '@fortawesome/free-solid-svg-icons'; import { observer } from "mobx-react"; import * as React from 'react'; import { Doc, DocListCast, WidthSym, HeightSym } from '../../../new_fields/Doc'; @@ -25,6 +25,8 @@ library.add(faSquare); library.add(faProjectDiagram); library.add(faSignature); library.add(faThList); +library.add(faColumns); +library.add(faEllipsisV); library.add(faImage); @observer @@ -37,7 +39,8 @@ export class CollectionView extends React.Component { case CollectionViewType.Schema: return (); case CollectionViewType.Docking: return (); case CollectionViewType.Tree: return (); - case CollectionViewType.Stacking: return (); + case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } + case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } case CollectionViewType.Freeform: default: return (); @@ -57,7 +60,8 @@ 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" }); + subItems.push({ description: "Stacking", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Stacking), icon: "ellipsis-v" }); + subItems.push({ description: "Masonry", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Masonry), icon: "columns" }); ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems }); ContextMenu.Instance.addItem({ description: "Apply Template", event: undoBatch(() => { -- 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') 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 5da4de27c45e4f40c88b710be64f0129e9be7088 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Fri, 19 Jul 2019 16:21:19 -0400 Subject: focused cell styling + click editable view changes focuses on that cell --- src/client/views/EditableView.tsx | 2 +- .../views/collections/CollectionSchemaCells.tsx | 1 + .../views/collections/CollectionSchemaHeaders.tsx | 29 ---------------------- .../views/collections/CollectionSchemaView.scss | 7 +++++- 4 files changed, 8 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 42faedf9d..9471ae98a 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -79,7 +79,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(); } diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 0307bb83e..31a9baa11 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -74,6 +74,7 @@ export class CollectionSchemaCell extends React.Component { document.addEventListener("keydown", this.onKeyDown); this._isEditing = isEditing; this.props.setIsEditing(isEditing); + this.props.changeFocusedCellByIndex(this.props.row, this.props.col); } @action diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index 5f8037fbf..df078eca5 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -56,38 +56,14 @@ 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; createColumn: () => void; } @observer export class CollectionSchemaAddColumnHeader extends React.Component { render() { - let addButton = ; return ( - //
- // - //
); } } @@ -115,8 +91,6 @@ export interface ColumnMenuProps { export class CollectionSchemaColumnMenu extends React.Component { @observable private _isOpen: boolean = false; @observable private _node : HTMLDivElement | null = null; - // @observable private _node = React.createRef(); - @observable private _test = "test"; componentDidMount() { document.addEventListener("pointerdown", this.detectClick); @@ -168,9 +142,6 @@ export class CollectionSchemaColumnMenu extends React.Component - {/* */} diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 47947829e..045994751 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -126,13 +126,14 @@ .rt-tr { width: 100%; + height: $MAX_ROW_HEIGHT; } .rt-td { border-width: 1px; border-right-color: $intermediate-color; max-height: $MAX_ROW_HEIGHT; - padding: 3px 7px; + padding: 0; font-size: 13px; text-align: center; @@ -289,6 +290,10 @@ height: 100%; padding: 4px; + &:focus { + outline: none; + } + &.focused { // background-color: yellowgreen; border: 2px solid yellowgreen; -- cgit v1.2.3-70-g09d2 From e4ef3a04e3bd0bb20ed70181d51a9c419a00613f Mon Sep 17 00:00:00 2001 From: yipstanley Date: Fri, 19 Jul 2019 16:57:09 -0400 Subject: documents are now droppable and draggable --- .../views/collections/CollectionSchemaCells.tsx | 71 +++++++++++++++------- 1 file changed, 50 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 1bb661f88..72d993b5a 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -17,7 +17,9 @@ import { CollectionPDFView } from "./CollectionPDFView"; import "./CollectionSchemaView.scss"; import { CollectionVideoView } from "./CollectionVideoView"; import { CollectionView } from "./CollectionView"; -import { NumCast, StrCast, BoolCast } from "../../../new_fields/Types"; +import { NumCast, StrCast, BoolCast, FieldValue, Cast } from "../../../new_fields/Types"; +import { Docs } from "../../documents/Documents"; +import { DocumentContentsView } from "../nodes/DocumentContentsView"; export interface CellProps { @@ -43,6 +45,7 @@ export class CollectionSchemaCell extends React.Component { @observable protected _isEditing: boolean = false; protected _focusRef = React.createRef(); protected _document = this.props.rowProps.original; + private _dropDisposer?: DragManager.DragDropDisposer; componentDidMount() { if (this._focusRef.current) { @@ -54,6 +57,7 @@ export class CollectionSchemaCell extends React.Component { } document.addEventListener("keydown", this.onKeyDown); + } componentWillUnmount() { @@ -88,6 +92,27 @@ export class CollectionSchemaCell extends React.Component { return true; } + private drop = (e: Event, de: DragManager.DropEvent) => { + if (de.data instanceof DragManager.DocumentDragData) { + let fieldKey = this.props.rowProps.column.id as string; + if (de.data.draggedDocuments.length === 1) { + this._document[fieldKey] = de.data.draggedDocuments[0]; + } + else { + let coll = Docs.Create.SchemaDocument(["title"], de.data.draggedDocuments, {}); + this._document[fieldKey] = coll; + } + e.stopPropagation(); + } + } + + private dropRef = (ele: HTMLElement) => { + this._dropDisposer && this._dropDisposer(); + if (ele) { + this._dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + } + } + renderCellWithType(type: string | undefined) { let props: FieldViewProps = { Document: this.props.rowProps.original, @@ -107,22 +132,25 @@ export class CollectionSchemaCell extends React.Component { 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)); + SetupDrag(this._focusRef, () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document, + (doc: Doc, target: Doc, addDoc: (newDoc: Doc) => any) => addDoc(doc), this._document[props.fieldKey] instanceof Doc ? "alias" : undefined)(e); }; let field = props.Document[props.fieldKey]; let contents: any = "incorrect type"; - if (type === undefined) contents = ; + 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 + "--"; + if (type === "document") { + let doc = FieldValue(Cast(field, Doc)); + contents = typeof field === "object" ? doc ? StrCast(doc.title) === "" ? "--" : StrCast(doc.title) : `--${typeof field}--` : `--${typeof field}--`; + } return (
-
+
) => { 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._document, script.run); - } + if (script.compiled) { + this.applyToDoc(this._document, script.run); + } } render() { @@ -207,7 +235,7 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell { return (
- +
); @@ -217,16 +245,17 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell { @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 ( -
-
-
-
- ); + 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 ( + //
+ //
+ //
+ //
+ // ); } } \ No newline at end of file -- 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') 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') 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') 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') 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 6f8f9bd2eaba36dc64e7335dee53a372542bad46 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Mon, 22 Jul 2019 17:17:09 -0400 Subject: basic stuff working, column headers don tmatch add group button --- src/client/views/MetadataEntryMenu.tsx | 1 + .../views/collections/CollectionStackingView.scss | 55 ++++-- .../views/collections/CollectionStackingView.tsx | 113 +++++------- .../CollectionStackingViewFieldColumn.tsx | 202 +++++++++++++++++++++ src/client/views/nodes/DocumentView.tsx | 3 - 5 files changed, 286 insertions(+), 88 deletions(-) create mode 100644 src/client/views/collections/CollectionStackingViewFieldColumn.tsx (limited to 'src') diff --git a/src/client/views/MetadataEntryMenu.tsx b/src/client/views/MetadataEntryMenu.tsx index bd5a307b3..7fce3dd0c 100644 --- a/src/client/views/MetadataEntryMenu.tsx +++ b/src/client/views/MetadataEntryMenu.tsx @@ -74,6 +74,7 @@ export class MetadataEntryMenu extends React.Component{ this.userModified = e.target.value.trim() !== ""; } + @action onValueKeyDown = async (e: React.KeyboardEvent) => { if (e.key === "Enter") { const script = KeyValueBox.CompileKVPScript(this._currentValue); diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 7ebf5f77c..3e389225a 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -1,9 +1,12 @@ @import "../globalCssVariables"; + .collectionStackingView { height: 100%; width: 100%; position: absolute; + display: flex; overflow-y: auto; + .collectionStackingView-docView-container { width: 45%; margin: 5% 2.5%; @@ -18,21 +21,23 @@ align-items: center; } - .collectionStackingView-masonrySingle, .collectionStackingView-masonryGrid { - width:100%; - height:100%; + .collectionStackingView-masonrySingle, + .collectionStackingView-masonryGrid { + width: 100%; + height: 100%; position: absolute; - display:grid; + display: grid; top: 0; left: 0; width: 100%; position: absolute; } + .collectionStackingView-masonrySingle { - width:100%; - height:100%; + width: 100%; + height: 100%; position: absolute; - display:flex; + display: flex; flex-direction: column; top: 0; left: 0; @@ -52,34 +57,50 @@ } .collectionStackingView-columnDragger { - width: 15; - height: 15; + width: 15; + height: 15; position: absolute; margin-left: -5; } - .collectionStackingView-columnDoc{ + .collectionStackingView-columnDoc { display: inline-block; } - .collectionStackingView-columnDoc, + .collectionStackingView-columnDoc, .collectionStackingView-masonryDoc { margin-left: auto; margin-right: auto; } - + .collectionStackingView-masonryDoc { transform-origin: top left; grid-column-end: span 1; height: 100%; } - .collectionStackingView-sectionHeader { - width: 90%; + + .collectionStackingView-sectionHeader { background: gray; text-align: center; - margin-left: 5%; - margin-right: 5%; - color: white; + margin-left: 10px; + margin-right: 10px; margin-top: 10px; + color: $light-color; + text-transform: uppercase; + letter-spacing: 2px; + padding: 10px; + + .editableView-input { + color: black; + } + } + + .collectionStackingView-addDocumentButton, + .collectionStackingView-addGroupButton { + display: inline-block; + margin: 0 10px; + overflow: hidden; + width: 90%; + color: lightgrey; } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 0e5f9a321..0ddd5528b 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -14,6 +14,7 @@ import { DragManager } from "../../util/DragManager"; import { DocumentType } from "../../documents/Documents"; import { Transform } from "../../util/Transform"; import { CursorProperty } from "csstype"; +import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn"; @observer export class CollectionStackingView extends CollectionSubView(doc => doc) { @@ -35,8 +36,13 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let fields = new Map(); sectionFilter && this.filteredChildren.map(d => { let sectionValue = (d[sectionFilter] ? d[sectionFilter] : "-undefined-") as object; - if (!fields.has(sectionValue)) fields.set(sectionValue, [d]); - else fields.get(sectionValue)!.push(d); + let parsed = parseInt(sectionValue.toString()); + let castedSectionValue: any = sectionValue; + if (!isNaN(parsed)) { + castedSectionValue = parsed; + } + if (!fields.has(castedSectionValue)) fields.set(castedSectionValue, [d]); + else fields.get(castedSectionValue)!.push(d); }); return fields; } @@ -66,7 +72,9 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { getDisplayDoc(layoutDoc: Doc, d: Doc, dxf: () => Transform) { let resolvedDataDoc = !this.props.Document.isTemplate && this.props.DataDoc !== this.props.Document ? this.props.DataDoc : undefined; - let width = () => d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth; + let headings = Array.from(this.Sections.keys()); + let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); + let width = () => (d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth) / (uniqueHeadings.length + 1); let height = () => this.getDocHeight(layoutDoc); let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]()); return doc) { return (nw && nh) ? wid * aspect : d[HeightSym](); } - offsetTransform(doc: Doc, translateX: number, translateY: number) { - let outerXf = Utils.GetScreenTransform(this._masonryGridRef!); - let offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); - return this.props.ScreenToLocalTransform().translate(offset[0], offset[1]).scale(NumCast(doc.width, 1) / this.columnWidth); - } - getDocTransform(doc: Doc, dref: HTMLDivElement) { - let { scale, translateX, translateY } = Utils.GetScreenTransform(dref); - return this.offsetTransform(doc, translateX, translateY); - } - - getSingleDocTransform(doc: Doc, ind: number, width: number) { - let localY = this.filteredChildren.reduce((height, d, i) => - height + (i < ind ? this.getDocHeight(Doc.expandTemplateLayout(d, this.props.DataDoc)) + this.gridGap : 0), this.yMargin); - let translate = this.props.ScreenToLocalTransform().inverse().transformPoint((this.props.PanelWidth() - width) / 2, localY); - return this.offsetTransform(doc, translate[0], translate[1]); - } - - children(docs: Doc[]) { - this._docXfs.length = 0; - return docs.map((d, i) => { - let layoutDoc = Doc.expandTemplateLayout(d, this.props.DataDoc); - let width = () => d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth; - let height = () => this.getDocHeight(layoutDoc); - if (this.singleColumn) { - //have to add the height of all previous single column sections or the doc decorations will be in the wrong place. - let dxf = () => this.getSingleDocTransform(layoutDoc, i, width()); - let rowHgtPcnt = height(); - this._docXfs.push({ dxf: dxf, width: width, height: height }); - return
- {this.getDisplayDoc(layoutDoc, d, dxf)} -
; - } else { - let dref = React.createRef(); - let dxf = () => this.getDocTransform(layoutDoc, dref.current!); - let rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap); - this._docXfs.push({ dxf: dxf, width: width, height: height }); - return
- {this.getDisplayDoc(layoutDoc, d, dxf)} -
; - } - }); - } - columnDividerDown = (e: React.PointerEvent) => { e.stopPropagation(); e.preventDefault(); @@ -218,30 +183,37 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } }); } - section(heading: string, docList: Doc[]) { - let cols = this.singleColumn ? 1 : Math.max(1, Math.min(this.filteredChildren.length, + section = (heading: string, docList: Doc[]) => { + let key = StrCast(this.props.Document.sectionFilter); + let types = docList.map(d => typeof d[key]); + let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined; + if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) { + type = types[0]; + } + let parsed = parseInt(heading); + if (!isNaN(parsed)) { + heading = parsed.toString(); + } + let cols = () => this.singleColumn ? 1 : Math.max(1, Math.min(this.filteredChildren.length, Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap)))); - let templatecols = ""; - for (let i = 0; i < cols; i++) templatecols += `${this.columnWidth}px `; - return
- {heading ?
{heading}
: (null)} -
- {this.children(docList)} - {this.singleColumn ? (null) : this.columnDragger} -
; + return Array.from(this.Sections.keys())} + heading={heading} + docList={docList} + parent={this} + type={type} + createDropTarget={this.createDropTarget} />; + } + + @action + addGroup = () => { + } + render() { + let headings = Array.from(this.Sections.keys()); + let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); return (
e.stopPropagation()} > @@ -249,9 +221,14 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { ["width > height", this.filteredChildren.filter(f => f[WidthSym]() >= 1 + f[HeightSym]())], ["width = height", this.filteredChildren.filter(f => Math.abs(f[WidthSym]() - f[HeightSym]()) < 1)], ["height > width", this.filteredChildren.filter(f => f[WidthSym]() + 1 <= f[HeightSym]())]]. */} - {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()). + {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()).sort((a, b) => a[0].toString() > b[0].toString() ? 1 : -1). map(section => this.section(section[0].toString(), section[1] as Doc[])) : this.section("", this.filteredChildren)} + {this.props.Document.sectionFilter ? +
+ +
: null}
); } diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx new file mode 100644 index 000000000..9f64a4e93 --- /dev/null +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -0,0 +1,202 @@ +import React = require("react"); +import { observer } from "mobx-react"; +import { number } from "prop-types"; +import { Doc, WidthSym } from "../../../new_fields/Doc"; +import { CollectionStackingView } from "./CollectionStackingView"; +import { Id } from "../../../new_fields/FieldSymbols"; +import { Utils } from "../../../Utils"; +import { NumCast, StrCast } from "../../../new_fields/Types"; +import { EditableView } from "../EditableView"; +import { action, observable } from "mobx"; +import { undoBatch } from "../../util/UndoManager"; +import { DragManager } from "../../util/DragManager"; +import { DocumentManager } from "../../util/DocumentManager"; +import { SelectionManager } from "../../util/SelectionManager"; +import "./CollectionStackingView.scss"; +import { Docs } from "../../documents/Documents"; + + +interface CSVFieldColumnProps { + cols: () => number; + headings: () => object[]; + heading: string; + docList: Doc[]; + parent: CollectionStackingView; + type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined; + createDropTarget: (ele: HTMLDivElement) => void; +} + +@observer +export class CollectionStackingViewFieldColumn extends React.Component { + @observable private _background = "white"; + + private _dropRef: HTMLDivElement | null = null; + private dropDisposer?: DragManager.DragDropDisposer; + + createColumnDropRef = (ele: HTMLDivElement | null) => { + this._dropRef = ele; + this.dropDisposer && this.dropDisposer(); + if (ele) { + this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.columnDrop.bind(this) } }); + } + } + + @undoBatch + @action + columnDrop = (e: Event, de: DragManager.DropEvent) => { + if (de.data instanceof DragManager.DocumentDragData) { + let key = StrCast(this.props.parent.props.Document.sectionFilter); + let castedValue = this.getValue(this.props.heading); + if (castedValue) { + de.data.droppedDocuments.forEach(d => d[key] = castedValue); + } + this.props.parent.drop(e, de); + e.stopPropagation(); + } + } + + children(docs: Doc[]) { + let style = this.props.parent; + this.props.parent._docXfs.length = 0; + return docs.map((d, i) => { + let layoutDoc = Doc.expandTemplateLayout(d, this.props.parent.props.DataDoc); + let headings = this.props.headings(); + let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); + let width = () => (d.nativeWidth ? Math.min(layoutDoc[WidthSym](), style.columnWidth) : style.columnWidth) / (uniqueHeadings.length + 1); + let height = () => this.props.parent.getDocHeight(layoutDoc); + if (style.singleColumn) { + let dxf; + let dref = React.createRef(); + if (uniqueHeadings.length > 0) { + dxf = () => this.getDocTransform(layoutDoc, dref.current!); + this.props.parent._docXfs.push({ dxf: dxf, width: width, height: height }); + } + else { + //have to add the height of all previous single column sections or the doc decorations will be in the wrong place. + dxf = () => this.getSingleDocTransform(layoutDoc, i, width()); + this.props.parent._docXfs.push({ dxf: dxf, width: width, height: height }); + } + let rowHgtPcnt = height(); + return
+ {this.props.parent.getDisplayDoc(layoutDoc, d, dxf)} +
; + } else { + let dref = React.createRef(); + let dxf = () => this.getDocTransform(layoutDoc, dref.current!); + let rowSpan = Math.ceil((height() + style.gridGap) / style.gridGap); + this.props.parent._docXfs.push({ dxf: dxf, width: width, height: height }); + return
+ {this.props.parent.getDisplayDoc(layoutDoc, d, dxf)} +
; + } + }); + } + + getSingleDocTransform(doc: Doc, ind: number, width: number) { + let localY = this.props.parent.filteredChildren.reduce((height, d, i) => + height + (i < ind ? this.props.parent.getDocHeight(Doc.expandTemplateLayout(d, this.props.parent.props.DataDoc)) + this.props.parent.gridGap : 0), this.props.parent.yMargin); + let translate = this.props.parent.props.ScreenToLocalTransform().inverse().transformPoint((this.props.parent.props.PanelWidth() - width) / 2, localY); + return this.offsetTransform(doc, translate[0], translate[1]); + } + + offsetTransform(doc: Doc, translateX: number, translateY: number) { + let outerXf = Utils.GetScreenTransform(this.props.parent._masonryGridRef!); + let offset = this.props.parent.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); + return this.props.parent.props.ScreenToLocalTransform().translate(offset[0], offset[1]).scale(NumCast(doc.width, 1) / this.props.parent.columnWidth); + } + + getDocTransform(doc: Doc, dref: HTMLDivElement) { + let { scale, translateX, translateY } = Utils.GetScreenTransform(dref); + return this.offsetTransform(doc, translateX, translateY); + } + + getValue = (value: string): any => { + let parsed = parseInt(value); + if (!isNaN(parsed)) { + return parsed; + } + if (value.toLowerCase().indexOf("true") > -1) { + return true; + } + if (value.toLowerCase().indexOf("false") > -1) { + return false; + } + return value; + } + + headingChanged = (value: string, shiftDown?: boolean) => { + let key = StrCast(this.props.parent.props.Document.sectionFilter); + let castedValue = this.getValue(value); + if (castedValue) { + this.props.docList.forEach(d => d[key] = castedValue); + return true; + } + return false; + } + + @action + pointerEntered = () => { + if (SelectionManager.GetIsDragging()) { + this._background = "#b4b4b4"; + } + } + + @action + pointerLeave = () => { + this._background = "white"; + } + + @action + addDocument = () => { + let key = StrCast(this.props.parent.props.Document.sectionFilter); + let newDoc = Docs.Create.TextDocument({ height: 18, title: "new text document" }); + newDoc[key] = this.getValue(this.props.heading); + this.props.parent.props.addDocument(newDoc); + } + + render() { + let cols = this.props.cols(); + let templatecols = ""; + let headings = this.props.headings(); + let heading = this.props.heading; + let style = this.props.parent; + let singleColumn = style.singleColumn; + let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); + let editableViewProps = { + GetValue: () => heading, + SetValue: this.headingChanged, + contents: heading, + } + let headingView = heading ? +
+ +
: (null); + for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth}px `; + return ( +
+ {headingView} +
+ {this.children(this.props.docList)} + {singleColumn ? (null) : this.props.parent.columnDragger} +
+
+ +
+
+ ); + } +} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index f4052c2c3..0d766cded 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -565,10 +565,7 @@ export class DocumentView extends DocComponent(Docu if (this.props.Document.detailedLayout && !this.props.Document.isTemplate) { cm.addItem({ description: "Toggle detail", event: () => Doc.ToggleDetailLayout(this.props.Document), icon: "image" }); } -<<<<<<< HEAD -======= cm.addItem({ description: "Add Repl", event: () => OverlayView.Instance.addWindow(, { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" }) }); ->>>>>>> fc1dbb1327d10bd1832d33a87d18cff1e836ecfb 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" }); cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "link" }); -- cgit v1.2.3-70-g09d2 From fd22f29e70e542b834884b01aac101190eb8c355 Mon Sep 17 00:00:00 2001 From: kimdahey Date: Tue, 23 Jul 2019 13:15:03 -0400 Subject: title will not change after being given a custom title --- src/client/views/DocumentDecorations.tsx | 1 + src/client/views/nodes/FormattedTextBox.tsx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 2f7bea365..1c12add27 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -96,6 +96,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } else { if (SelectionManager.SelectedDocuments().length > 0) { + SelectionManager.SelectedDocuments()[0].props.Document.customTitle = true; let field = SelectionManager.SelectedDocuments()[0].props.Document[this._fieldKey]; if (typeof field === "number") { SelectionManager.SelectedDocuments().forEach(d => { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 0a79677e2..899b8d568 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -139,7 +139,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe this.dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON())); this._applyingChange = false; let title = StrCast(this.dataDoc.title); - if (title && title.startsWith("-") && this._editorView) { + if (title && title.startsWith("-") && this._editorView && !this.Document.customTitle) { let str = this._editorView.state.doc.textContent; let titlestr = str.substr(0, Math.min(40, str.length)); this.dataDoc.title = "-" + titlestr + (str.length > 40 ? "..." : ""); @@ -422,7 +422,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe // stop propagation doesn't seem to stop propagation of native keyboard events. // so we set a flag on the native event that marks that the event's been handled. (e.nativeEvent as any).DASHFormattedTextBoxHandled = true; - if (StrCast(this.dataDoc.title).startsWith("-") && this._editorView) { + if (StrCast(this.dataDoc.title).startsWith("-") && this._editorView && !this.Document.customTitle) { let str = this._editorView.state.doc.textContent; let titlestr = str.substr(0, Math.min(40, str.length)); this.dataDoc.title = "-" + titlestr + (str.length > 40 ? "..." : ""); -- cgit v1.2.3-70-g09d2 From de9b03ca6c7116949952bc428e8d9257959ad974 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Tue, 23 Jul 2019 13:58:45 -0400 Subject: implemented most of the board functionality --- .../views/collections/CollectionStackingView.scss | 99 +++++++++++++++--- .../views/collections/CollectionStackingView.tsx | 115 ++++++++++++++------- .../CollectionStackingViewFieldColumn.tsx | 64 ++++++++++-- src/new_fields/SchemaHeaderField.ts | 46 +++++++++ 4 files changed, 266 insertions(+), 58 deletions(-) create mode 100644 src/new_fields/SchemaHeaderField.ts (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 3e389225a..e0ced8af4 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -6,6 +6,7 @@ position: absolute; display: flex; overflow-y: auto; + flex-wrap: wrap; .collectionStackingView-docView-container { width: 45%; @@ -67,12 +68,6 @@ display: inline-block; } - .collectionStackingView-columnDoc, - .collectionStackingView-masonryDoc { - margin-left: auto; - margin-right: auto; - } - .collectionStackingView-masonryDoc { transform-origin: top left; grid-column-end: span 1; @@ -80,27 +75,103 @@ } .collectionStackingView-sectionHeader { - background: gray; text-align: center; - margin-left: 10px; - margin-right: 10px; + margin-left: 5px; + margin-right: 5px; margin-top: 10px; - color: $light-color; - text-transform: uppercase; - letter-spacing: 2px; - padding: 10px; + overflow: hidden; .editableView-input { color: black; } + + .editableView-input:hover, + .editableView-container-editing:hover, + .editableView-container-editing-oneLine:hover { + cursor: text + } + + .collectionStackingView-sectionHeader-subCont { + outline: none; + border: 0px; + color: $light-color; + text-transform: uppercase; + letter-spacing: 2px; + font-size: 75%; + transition: transform 0.2s; + position: relative; + + .editableView-container-editing-oneLine, + .editableView-container-editing { + color: grey; + padding: 10px; + } + + .editableView-input:hover, + .editableView-container-editing:hover, + .editableView-container-editing-oneLine:hover { + cursor: text + } + + .editableView-input { + padding: 12px 10px 11px 10px; + border: 0px; + color: grey; + // font-size: 75%; + text-align: center; + text-transform: uppercase; + letter-spacing: 2px; + outline-color: black; + } + } + + .collectionStackingView-sectionDelete { + position: absolute; + right: 0; + top: 0; + height: 100%; + } } .collectionStackingView-addDocumentButton, .collectionStackingView-addGroupButton { display: inline-block; - margin: 0 10px; + margin: 0 5px; overflow: hidden; width: 90%; color: lightgrey; + overflow: ellipses; + } + + .collectionStackingView-addGroupButton { + background: rgb(238, 238, 238); + font-size: 75%; + text-align: center; + text-transform: uppercase; + letter-spacing: 2px; + height: fit-content; + + .editableView-container-editing-oneLine, + .editableView-container-editing { + color: grey; + padding: 10px; + } + + .editableView-input:hover, + .editableView-container-editing:hover, + .editableView-container-editing-oneLine:hover { + cursor: text + } + + .editableView-input { + padding: 12px 10px 11px 10px; + border: 0px; + color: grey; + // font-size: 75%; + text-align: center; + text-transform: uppercase; + letter-spacing: 2px; + outline-color: black; + } } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 0ddd5528b..e4e6f92e3 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -2,9 +2,9 @@ import React = require("react"); import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, IReactionDisposer, reaction, untracked, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, HeightSym, WidthSym } from "../../../new_fields/Doc"; +import { Doc, HeightSym, WidthSym, DocListCast } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; -import { BoolCast, NumCast, Cast, StrCast } from "../../../new_fields/Types"; +import { BoolCast, NumCast, Cast, StrCast, FieldValue } from "../../../new_fields/Types"; import { emptyFunction, Utils } from "../../../Utils"; import { CollectionSchemaPreview } from "./CollectionSchemaView"; import "./CollectionStackingView.scss"; @@ -15,46 +15,80 @@ import { DocumentType } from "../../documents/Documents"; import { Transform } from "../../util/Transform"; import { CursorProperty } from "csstype"; import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn"; +import { listSpec } from "../../../new_fields/Schema"; +import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; +import { List } from "../../../new_fields/List"; +import { EditableView } from "../EditableView"; + +let valuesCreated = 1; @observer export class CollectionStackingView extends CollectionSubView(doc => doc) { _masonryGridRef: HTMLDivElement | null = null; _draggerRef = React.createRef(); _heightDisposer?: IReactionDisposer; + _sectionFilterDisposer?: IReactionDisposer; _docXfs: any[] = []; _columnStart: number = 0; @observable private cursor: CursorProperty = "grab"; + get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); } @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); } @computed get singleColumn() { return BoolCast(this.props.Document.singleColumn, true); } @computed get columnWidth() { return this.singleColumn ? (this.props.PanelWidth() / (this.props as any).ContentScaling() - 2 * this.xMargin) : Math.min(this.props.PanelWidth() - 2 * this.xMargin, NumCast(this.props.Document.columnWidth, 250)); } @computed get filteredChildren() { return this.childDocs.filter(d => !d.isMinimized); } - - @computed get Sections() { + get Sections() { let sectionFilter = StrCast(this.props.Document.sectionFilter); - let fields = new Map(); - sectionFilter && this.filteredChildren.map(d => { - let sectionValue = (d[sectionFilter] ? d[sectionFilter] : "-undefined-") as object; - let parsed = parseInt(sectionValue.toString()); - let castedSectionValue: any = sectionValue; - if (!isNaN(parsed)) { - castedSectionValue = parsed; - } - if (!fields.has(castedSectionValue)) fields.set(castedSectionValue, [d]); - else fields.get(castedSectionValue)!.push(d); - }); + let sectionHeaders = this.sectionHeaders; + if (!sectionHeaders) { + this.props.Document.sectionHeaders = sectionHeaders = new List(); + } + let fields = new Map(sectionHeaders.map(sh => [sh, []])); + if (sectionFilter) { + this.filteredChildren.map(d => { + let sectionValue = (d[sectionFilter] ? d[sectionFilter] : `No ${sectionFilter} value`) as object; + // the next five lines ensures that floating point rounding errors don't create more than one section -syip + let parsed = parseInt(sectionValue.toString()); + let castedSectionValue: any = sectionValue; + if (!isNaN(parsed)) { + castedSectionValue = parsed; + } + + // look for if header exists already + let existingHeader = sectionHeaders!.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `No ${sectionFilter} value`)); + if (existingHeader) { + fields.get(existingHeader)!.push(d); + } + else { + let newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `No ${sectionFilter} value`); + fields.set(newSchemaHeader, [d]); + sectionHeaders!.push(newSchemaHeader); + } + }); + } return fields; } componentDidMount() { - this._heightDisposer = reaction(() => [this.yMargin, this.gridGap, this.columnWidth, this.childDocs.map(d => [d.height, d.width, d.zoomBasis, d.nativeHeight, d.nativeWidth, d.isMinimized])], - () => this.singleColumn && - (this.props.Document.height = this.Sections.size * 50 + this.filteredChildren.reduce((height, d, i) => - height + this.getDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap), this.yMargin)) - , { fireImmediately: true }); + // is there any reason this needs to exist? -syip + // this._heightDisposer = reaction(() => [this.yMargin, this.gridGap, this.columnWidth, this.childDocs.map(d => [d.height, d.width, d.zoomBasis, d.nativeHeight, d.nativeWidth, d.isMinimized])], + // () => this.singleColumn && + // (this.props.Document.height = this.Sections.size * 50 + this.filteredChildren.reduce((height, d, i) => + // height + this.getDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap), this.yMargin)) + // , { fireImmediately: true }); + + // reset section headers when a new filter is inputted + this._sectionFilterDisposer = reaction( + () => StrCast(this.props.Document.sectionFilter), + () => { + this.props.Document.sectionHeaders = new List(); + valuesCreated = 1; + } + ) } componentWillUnmount() { this._heightDisposer && this._heightDisposer(); + this._sectionFilterDisposer && this._sectionFilterDisposer(); } @action @@ -73,8 +107,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { getDisplayDoc(layoutDoc: Doc, d: Doc, dxf: () => Transform) { let resolvedDataDoc = !this.props.Document.isTemplate && this.props.DataDoc !== this.props.Document ? this.props.DataDoc : undefined; let headings = Array.from(this.Sections.keys()); - let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); - let width = () => (d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth) / (uniqueHeadings.length + 1); + // let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); + let width = () => (d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth) / (headings.length + 1); let height = () => this.getDocHeight(layoutDoc); let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]()); return doc) { } }); } - section = (heading: string, docList: Doc[]) => { + section = (heading: SchemaHeaderField | undefined, docList: Doc[]) => { let key = StrCast(this.props.Document.sectionFilter); - let types = docList.map(d => typeof d[key]); let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined; + let types = docList.length ? docList.map(d => typeof d[key]) : this.childDocs.map(d => typeof d[key]); if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) { type = types[0]; } - let parsed = parseInt(heading); - if (!isNaN(parsed)) { - heading = parsed.toString(); - } let cols = () => this.singleColumn ? 1 : Math.max(1, Math.min(this.filteredChildren.length, Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap)))); return Array.from(this.Sections.keys())} - heading={heading} + heading={heading ? heading.heading : ""} + headingObject={heading} docList={docList} parent={this} type={type} @@ -207,13 +239,24 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } @action - addGroup = () => { - + addGroup = (value: string) => { + if (value) { + if (this.sectionHeaders) { + this.sectionHeaders.push(new SchemaHeaderField(value)); + return true; + } + } + return false; } render() { let headings = Array.from(this.Sections.keys()); - let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); + let editableViewProps = { + GetValue: () => "", + SetValue: this.addGroup, + contents: "+ Add a Group" + } + // let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); return (
e.stopPropagation()} > @@ -222,12 +265,12 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { ["width = height", this.filteredChildren.filter(f => Math.abs(f[WidthSym]() - f[HeightSym]()) < 1)], ["height > width", this.filteredChildren.filter(f => f[WidthSym]() + 1 <= f[HeightSym]())]]. */} {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()).sort((a, b) => a[0].toString() > b[0].toString() ? 1 : -1). - map(section => this.section(section[0].toString(), section[1] as Doc[])) : - this.section("", this.filteredChildren)} + map(section => this.section(section[0], section[1] as Doc[])) : + this.section(undefined, this.filteredChildren)} {this.props.Document.sectionFilter ?
- + style={{ width: (this.columnWidth / (headings.length + 1)) - 10, marginTop: 10 }}> +
: null}
); diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 9f64a4e93..fe24c63c7 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -7,19 +7,22 @@ import { Id } from "../../../new_fields/FieldSymbols"; import { Utils } from "../../../Utils"; import { NumCast, StrCast } from "../../../new_fields/Types"; import { EditableView } from "../EditableView"; -import { action, observable } from "mobx"; +import { action, observable, computed } from "mobx"; import { undoBatch } from "../../util/UndoManager"; import { DragManager } from "../../util/DragManager"; import { DocumentManager } from "../../util/DocumentManager"; import { SelectionManager } from "../../util/SelectionManager"; import "./CollectionStackingView.scss"; import { Docs } from "../../documents/Documents"; +import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; interface CSVFieldColumnProps { cols: () => number; headings: () => object[]; heading: string; + headingObject: SchemaHeaderField | undefined; docList: Doc[]; parent: CollectionStackingView; type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined; @@ -33,6 +36,8 @@ export class CollectionStackingViewFieldColumn extends React.Component { this._dropRef = ele; this.dropDisposer && this.dropDisposer(); @@ -46,10 +51,13 @@ export class CollectionStackingViewFieldColumn extends React.Component { if (de.data instanceof DragManager.DocumentDragData) { let key = StrCast(this.props.parent.props.Document.sectionFilter); - let castedValue = this.getValue(this.props.heading); + let castedValue = this.getValue(this._heading); if (castedValue) { de.data.droppedDocuments.forEach(d => d[key] = castedValue); } + else { + de.data.droppedDocuments.forEach(d => d[key] = undefined); + } this.props.parent.drop(e, de); e.stopPropagation(); } @@ -124,11 +132,21 @@ export class CollectionStackingViewFieldColumn extends React.Component { let key = StrCast(this.props.parent.props.Document.sectionFilter); let castedValue = this.getValue(value); if (castedValue) { + if (this.props.parent.sectionHeaders) { + if (this.props.parent.sectionHeaders.map(i => i.heading).indexOf(castedValue.toString()) > -1) { + return false; + } + } this.props.docList.forEach(d => d[key] = castedValue); + if (this.props.headingObject) { + this.props.headingObject.setHeading(castedValue.toString()); + this._heading = this.props.headingObject.heading; + } return true; } return false; @@ -154,23 +172,53 @@ export class CollectionStackingViewFieldColumn extends React.Component { + let key = StrCast(this.props.parent.props.Document.sectionFilter); + this.props.docList.forEach(d => d[key] = undefined); + if (this.props.parent.sectionHeaders && this.props.headingObject) { + let index = this.props.parent.sectionHeaders.indexOf(this.props.headingObject); + this.props.parent.sectionHeaders.splice(index, 1); + } + } + render() { let cols = this.props.cols(); + let key = StrCast(this.props.parent.props.Document.sectionFilter); let templatecols = ""; let headings = this.props.headings(); - let heading = this.props.heading; + let heading = this._heading; let style = this.props.parent; let singleColumn = style.singleColumn; let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); + let evContents = heading ? heading : this.props.type && this.props.type === "number" ? "0" : `No ${key} value`; let editableViewProps = { - GetValue: () => heading, + GetValue: () => evContents, SetValue: this.headingChanged, - contents: heading, + contents: evContents, + oneLine: true } - let headingView = heading ? + let headingView = this.props.headingObject ?
- + {/* the default bucket (no key value) has a tooltip that describes what it is. + Further, it does not have a color and cannot be deleted. */} +
+ + {evContents === `No ${key} value` ? + (null) : + } +
: (null); for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth}px `; return ( @@ -180,7 +228,7 @@ export class CollectionStackingViewFieldColumn extends React.Component([ + ["purple", "#f5b5fc"], + ["green", "#96F7D2"], + ["yellow", "#F0F696"], + ["red", "#FCB1B1"] +]) + +@scriptingGlobal +@Deserializable("schemaheader") +export class SchemaHeaderField extends ObjectField { + @serializable(primitive()) + heading: string; + color: string; + + constructor(heading: string = "", color: string = Array.from(PastelSchemaPalette.values())[Math.floor(Math.random() * 4)]) { + super(); + + this.heading = heading; + this.color = color; + } + + setHeading(heading: string) { + this.heading = heading; + this[OnUpdate](); + } + + setColor(color: string) { + this.color = color; + this[OnUpdate](); + } + + [Copy]() { + return new SchemaHeaderField(this.heading, this.color); + } + + [ToScriptString]() { + return `invalid`; + } +} + -- 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') 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 3b740e1c1ac74e7aac45c136ec9df1b37e2dbc16 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Tue, 23 Jul 2019 16:32:43 -0400 Subject: pretty ui for changing section fitler and added base for colletion chromes --- src/client/views/EditableView.scss | 10 +- src/client/views/EditableView.tsx | 30 +++- .../views/collections/CollectionBaseView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 34 ++++- .../views/collections/CollectionViewChromes.scss | 54 ++++++++ .../views/collections/CollectionViewChromes.tsx | 152 +++++++++++++++++++++ 6 files changed, 268 insertions(+), 14 deletions(-) create mode 100644 src/client/views/collections/CollectionViewChromes.scss create mode 100644 src/client/views/collections/CollectionViewChromes.tsx (limited to 'src') diff --git a/src/client/views/EditableView.scss b/src/client/views/EditableView.scss index a5150cd66..19512362e 100644 --- a/src/client/views/EditableView.scss +++ b/src/client/views/EditableView.scss @@ -1,20 +1,24 @@ -.editableView-container-editing, .editableView-container-editing-oneLine { +.editableView-container-editing, +.editableView-container-editing-oneLine { overflow-wrap: break-word; word-wrap: break-word; hyphens: auto; overflow: hidden; } + .editableView-container-editing-oneLine { span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - display:block; + display: block; } + input { - display:block; + display: block; } } + .editableView-input { width: 100%; background: inherit; diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index f2cdffd38..a5bb40243 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -2,6 +2,7 @@ import React = require('react'); import { observer } from 'mobx-react'; import { observable, action, trace } from 'mobx'; import "./EditableView.scss"; +import * as Autosuggest from 'react-autosuggest'; export interface EditableProps { /** @@ -28,6 +29,13 @@ export interface EditableProps { fontSize?: number; height?: number; display?: string; + autosuggestProps?: { + resetValue: () => void; + value: string, + onChange: (e: React.ChangeEvent, { newValue }: { newValue: string }) => void, + autosuggestProps: Autosuggest.AutosuggestProps + + }; oneLine?: boolean; editing?: boolean; onClick?: (e: React.MouseEvent) => boolean; @@ -85,10 +93,26 @@ export class EditableView extends React.Component { render() { if (this._editing) { - return this._editing = false)} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation} - style={{ display: this.props.display, fontSize: this.props.fontSize }} />; + return this.props.autosuggestProps + ? this._editing = false), + onPointerDown: this.stopPropagation, + onClick: this.stopPropagation, + onPointerUp: this.stopPropagation, + value: this.props.autosuggestProps.value, + onChange: this.props.autosuggestProps.onChange + }} + /> + : this._editing = 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(); return (
void; - children: (type: CollectionViewType, props: CollectionRenderProps) => JSX.Element | JSX.Element[] | null; + children: (type: CollectionViewType, props: CollectionRenderProps) => JSX.Element | JSX.Element[] | null | (JSX.Element | null)[]; className?: string; contentRef?: React.Ref; } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 045c8531e..ba9780c24 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 { CollectionStackingViewChrome } from './CollectionViewChromes'; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh); @@ -33,21 +34,40 @@ library.add(faImage); export class CollectionView extends React.Component { public static LayoutString(fieldStr: string = "data", fieldExt: string = "") { return FieldView.LayoutString(CollectionView, fieldStr, fieldExt); } - private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => { + 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 (); - case CollectionViewType.Tree: return (); - case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } - case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } + case CollectionViewType.Schema: return (); + 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 (); } case CollectionViewType.Freeform: default: - return (); + return (); } return (null); } + private Chrome = (type: CollectionViewType) => { + if (this.isAnnotationOverlay || this.props.Document === CurrentUserUtils.UserDocument.sidebar) { + return (null); + } + + switch (type) { + case CollectionViewType.Stacking: return (); + default: + return null; + } + } + + private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => { + return [ + this.Chrome(type), + this.SubViewHelper(type, renderProps) + ] + } + get isAnnotationOverlay() { return this.props.fieldExt ? true : false; } static _applyCount: number = 0; diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss new file mode 100644 index 000000000..e5cb1b546 --- /dev/null +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -0,0 +1,54 @@ +@import "../globalCssVariables"; + +.collectionStackingViewChrome { + display: grid; + grid-template-columns: 1fr 1fr; + padding-bottom: 10px; + border-bottom: .5px solid lightgrey; + margin: 10px; + + .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 { + color: white; + width: fit-content; + text-align: center; + background: rgb(238, 238, 238); + height: 37px; + + .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; + } +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx new file mode 100644 index 000000000..ca1480ff2 --- /dev/null +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -0,0 +1,152 @@ +import * as React from "react"; +import { CollectionView } from "./CollectionView"; +import "./CollectionViewChromes.scss"; +import { CollectionViewType } from "./CollectionBaseView"; +import { undoBatch } from "../../util/UndoManager"; +import { action, observable, runInAction, computed } from "mobx"; +import { observer } from "mobx-react"; +import { Doc, DocListCast } from "../../../new_fields/Doc"; +import { DocLike } from "../MetadataEntryMenu"; +const higflyout = require("@hig/flyout"); +export const Flyout = higflyout.default; +import * as Autosuggest from 'react-autosuggest'; +import { EditableView } from "../EditableView"; +import { StrCast } from "../../../new_fields/Types"; + +interface CollectionViewChromeProps { + CollectionView: CollectionView; +} + +class CollectionViewBaseChrome extends React.Component { + @undoBatch + viewChanged = (e: React.ChangeEvent) => { + //@ts-ignore + switch (e.target.selectedOptions[0].value) { + case "freeform": + this.props.CollectionView.props.Document.viewType = CollectionViewType.Freeform; + break; + case "schema": + this.props.CollectionView.props.Document.viewType = CollectionViewType.Schema; + break; + case "treeview": + this.props.CollectionView.props.Document.viewType = CollectionViewType.Tree; + break; + case "stacking": + this.props.CollectionView.props.Document.viewType = CollectionViewType.Stacking; + break; + case "masonry": + this.props.CollectionView.props.Document.viewType = CollectionViewType.Masonry; + break; + default: + break; + } + } + + render() { + return ( +
+ +
+ ) + } +} + +@observer +export class CollectionStackingViewChrome extends React.Component { + @observable private _currentKey: string = ""; + @observable private suggestions: string[] = []; + + @computed get sectionFilter() { return StrCast(this.props.CollectionView.props.Document.sectionFilter); } + + getKeySuggestions = async (value: string): Promise => { + value = value.toLowerCase(); + let docs: Doc | Doc[] | Promise | Promise | (() => DocLike) + = () => DocListCast(this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldExt ? this.props.CollectionView.props.fieldExt : this.props.CollectionView.props.fieldKey]); + if (typeof docs === "function") { + docs = docs(); + } + docs = await docs; + if (docs instanceof Doc) { + return Object.keys(docs).filter(key => key.toLowerCase().startsWith(value)); + } else { + const keys = new Set(); + docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key))); + return Array.from(keys).filter(key => key.toLowerCase().startsWith(value)); + } + } + + @action + onKeyChange = (e: React.ChangeEvent, { newValue }: { newValue: string }) => { + this._currentKey = newValue; + } + + getSuggestionValue = (suggestion: string) => suggestion; + + renderSuggestion = (suggestion: string) => { + return

{suggestion}

; + } + + onSuggestionFetch = async ({ value }: { value: string }) => { + const sugg = await this.getKeySuggestions(value); + runInAction(() => { + this.suggestions = sugg; + }); + } + + @action + onSuggestionClear = () => { + this.suggestions = []; + } + + setValue = (value: string) => { + this.props.CollectionView.props.Document.sectionFilter = value; + return true; + } + + @action resetValue = () => { this._currentKey = this.sectionFilter; } + + render() { + return ( +
+ +
+
+ Group items by: +
+
+ this.sectionFilter} + autosuggestProps={ + { + resetValue: this.resetValue, + value: this._currentKey, + onChange: this.onKeyChange, + autosuggestProps: { + inputProps: + { + value: this._currentKey, + onChange: this.onKeyChange + }, + getSuggestionValue: this.getSuggestionValue, + suggestions: this.suggestions, + alwaysRenderSuggestions: true, + renderSuggestion: this.renderSuggestion, + onSuggestionsFetchRequested: this.onSuggestionFetch, + onSuggestionsClearRequested: this.onSuggestionClear + } + }} + SetValue={this.setValue} + contents={this.sectionFilter ? this.sectionFilter : "N/A"} + /> +
+
+
+ ) + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 0ebcadb80a89e7fe4f8f2a8a47570b19fd2f8711 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Tue, 23 Jul 2019 17:05:07 -0400 Subject: i need a breakkk --- src/client/views/collections/CollectionViewChromes.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index ca1480ff2..52fee26bf 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -109,7 +109,7 @@ export class CollectionStackingViewChrome extends React.Component { this._currentKey = this.sectionFilter; } + @action resetValue = () => { this._currentKey = this.sectionFilter; }; render() { return ( -- 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') 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') 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') 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:18:15 -0400 Subject: view specsss --- package.json | 1 + src/client/views/EditableView.tsx | 2 +- src/client/views/MainView.tsx | 4 +- .../views/collections/CollectionStackingView.tsx | 9 +- .../CollectionStackingViewFieldColumn.tsx | 44 +++- src/client/views/collections/CollectionSubView.tsx | 15 +- .../views/collections/CollectionViewChromes.scss | 113 ++++++++- .../views/collections/CollectionViewChromes.tsx | 261 ++++++++++++++++----- src/client/views/collections/KeyRestrictionRow.tsx | 45 ++++ 9 files changed, 428 insertions(+), 66 deletions(-) create mode 100644 src/client/views/collections/KeyRestrictionRow.tsx (limited to 'src') diff --git a/package.json b/package.json index 4a15cbb2f..37052fde3 100644 --- a/package.json +++ b/package.json @@ -136,6 +136,7 @@ "image-size": "^0.7.4", "imagesloaded": "^4.1.4", "jquery-awesome-cursor": "^0.3.1", + "js-datepicker": "^4.6.6", "jsonwebtoken": "^8.5.0", "jsx-to-string": "^1.4.0", "lodash": "^4.17.11", diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index a5bb40243..bd00d47b9 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -116,7 +116,7 @@ export class EditableView extends React.Component { return (
+ onClick={this.onClick}> {this.props.contents}
); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 94a4835a1..69602deed 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,5 +1,5 @@ import { IconName, library } from '@fortawesome/fontawesome-svg-core'; -import { faArrowDown, faCloudUploadAlt, faArrowUp, faClone, faCheck, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faPortrait, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt, faCat } from '@fortawesome/free-solid-svg-icons'; +import { faArrowDown, faCaretUp, faLongArrowAltRight, faCloudUploadAlt, faArrowUp, faClone, faCheck, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faPortrait, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt, faCat } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, runInAction, reaction, trace } from 'mobx'; import { observer } from 'mobx-react'; @@ -127,7 +127,9 @@ export class MainView extends React.Component { library.add(faCut); library.add(faCommentAlt); library.add(faThumbtack); + library.add(faLongArrowAltRight); library.add(faCheck); + library.add(faCaretUp); library.add(faArrowDown); library.add(faArrowUp); library.add(faCloudUploadAlt); diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index e4e6f92e3..a78a47ffb 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -249,6 +249,13 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { return false; } + sortFunc = (a: [SchemaHeaderField, Doc[]], b: [SchemaHeaderField, Doc[]]): 1 | -1 => { + let descending = BoolCast(this.props.Document.stackingHeadersSortDescending); + let firstEntry = descending ? b : a; + let secondEntry = descending ? a : b; + return firstEntry[0].heading > secondEntry[0].heading ? 1 : -1; + } + render() { let headings = Array.from(this.Sections.keys()); let editableViewProps = { @@ -264,7 +271,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { ["width > height", this.filteredChildren.filter(f => f[WidthSym]() >= 1 + f[HeightSym]())], ["width = height", this.filteredChildren.filter(f => Math.abs(f[WidthSym]() - f[HeightSym]()) < 1)], ["height > width", this.filteredChildren.filter(f => f[WidthSym]() + 1 <= f[HeightSym]())]]. */} - {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()).sort((a, b) => a[0].toString() > b[0].toString() ? 1 : -1). + {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc). map(section => this.section(section[0], section[1] as Doc[])) : this.section(undefined, this.filteredChildren)} {this.props.Document.sectionFilter ? diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index fe24c63c7..582adc418 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -16,6 +16,8 @@ import "./CollectionStackingView.scss"; import { Docs } from "../../documents/Documents"; import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { ScriptField } from "../../../new_fields/ScriptField"; +import { CompileScript } from "../../util/Scripting"; interface CSVFieldColumnProps { @@ -35,6 +37,7 @@ export class CollectionStackingViewFieldColumn extends React.Component = React.createRef(); @observable _heading = this.props.headingObject ? this.props.headingObject.heading : this.props.heading; @@ -182,6 +185,43 @@ export class CollectionStackingViewFieldColumn extends React.Component { + let alias = Doc.MakeAlias(this.props.parent.props.Document); + let key = StrCast(this.props.parent.props.Document.sectionFilter); + let value = this.getValue(this._heading); + value = typeof value === "string" ? `"${value}"` : value; + let script = `return doc.${key} === ${value}`; + let compiled = CompileScript(script, { params: { doc: Doc.name } }); + if (compiled.compiled) { + let scriptField = new ScriptField(compiled); + alias.viewSpecScript = scriptField; + let dragData = new DragManager.DocumentDragData([alias], [alias.proto]); + DragManager.StartDocumentDrag([this._headerRef.current!], dragData, e.clientX, e.clientY); + } + + e.stopPropagation(); + document.removeEventListener("pointermove", this.startDrag); + document.removeEventListener("pointerup", this.pointerUp); + } + + pointerUp = (e: PointerEvent) => { + e.stopPropagation(); + e.preventDefault(); + + document.removeEventListener("pointermove", this.startDrag); + document.removeEventListener("pointerup", this.pointerUp); + } + + headerDown = (e: React.PointerEvent) => { + e.stopPropagation(); + e.preventDefault(); + + document.removeEventListener("pointermove", this.startDrag); + document.addEventListener("pointermove", this.startDrag); + document.removeEventListener("pointerup", this.pointerUp); + document.addEventListener("pointerup", this.pointerUp); + } + render() { let cols = this.props.cols(); let key = StrCast(this.props.parent.props.Document.sectionFilter); @@ -199,11 +239,11 @@ export class CollectionStackingViewFieldColumn extends React.Component {/* the default bucket (no key value) has a tooltip that describes what it is. Further, it does not have a color and cannot be deleted. */} -
boolean; @@ -54,7 +56,18 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { let self = this; //TODO tfs: This might not be what we want? //This linter error can't be fixed because of how js arguments work, so don't switch this to filter(FieldValue) - return DocListCast(this.extensionDoc[this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey]); + let docs = DocListCast(this.extensionDoc[this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey]); + let viewSpecScript = Cast(this.props.Document.viewSpecScript, ScriptField); + if (viewSpecScript) { + let script = viewSpecScript.script; + docs = docs.filter(d => { + let res = script.run({ doc: d }); + if (res.success) { + return res.result; + } + }); + } + return docs; } get childDocList() { //TODO tfs: This might not be what we want? diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index e5cb1b546..3103cd309 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -1,12 +1,120 @@ @import "../globalCssVariables"; +@import '~js-datepicker/dist/datepicker.min.css'; + +.collectionViewBaseChrome { + display: flex; + + .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; + } + + .collectionViewBaseChrome-viewPicker:active { + outline-color: black; + } + + .collectionViewBaseChrome-collapse { + margin-right: 10px; + transition: all .5s; + } + + .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 { + 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-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 { display: grid; - grid-template-columns: 1fr 1fr; + grid-template-columns: 1fr auto; padding-bottom: 10px; border-bottom: .5px solid lightgrey; margin: 10px; + .collectionStackingViewChrome-cont { + display: flex; + justify-content: space-between; + } + + .collectionStackingViewChrome-sort { + display: flex; + align-items: center; + justify-content: space-between; + + .collectionStackingViewChrome-sortIcon { + transition: transform .5s; + margin-left: 10px; + } + } + + button:hover { + transform: scale(1); + } + + .collectionStackingViewChrome-sectionFilter-cont { justify-self: right; display: flex; @@ -21,10 +129,9 @@ .collectionStackingViewChrome-sectionFilter { color: white; - width: fit-content; + width: 100px; text-align: center; background: rgb(238, 238, 238); - height: 37px; .editable-view-input, input, diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 52fee26bf..2edac384d 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -3,55 +3,189 @@ import { CollectionView } from "./CollectionView"; import "./CollectionViewChromes.scss"; import { CollectionViewType } from "./CollectionBaseView"; import { undoBatch } from "../../util/UndoManager"; -import { action, observable, runInAction, computed } from "mobx"; +import { action, observable, runInAction, computed, IObservable, IObservableValue } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast } from "../../../new_fields/Doc"; import { DocLike } from "../MetadataEntryMenu"; -const higflyout = require("@hig/flyout"); -export const Flyout = higflyout.default; import * as Autosuggest from 'react-autosuggest'; import { EditableView } from "../EditableView"; -import { StrCast } from "../../../new_fields/Types"; +import { StrCast, NumCast, BoolCast, Cast } from "../../../new_fields/Types"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Utils } from "../../../Utils"; +import KeyRestrictionRow from "./KeyRestrictionRow"; +import { CompileScript } from "../../util/Scripting"; +import { ScriptField } from "../../../new_fields/ScriptField"; +const datepicker = require('js-datepicker'); interface CollectionViewChromeProps { CollectionView: CollectionView; } +let stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation(); + +@observer class CollectionViewBaseChrome extends React.Component { + @observable private _viewSpecsOpen: boolean = false; + @observable private _dateWithinValue: string = ""; + @observable private _dateValue: Date = new Date(); + @observable private _keyRestrictions: [JSX.Element, string][] = []; + @computed private get filterValue() { return Cast(this.props.CollectionView.props.Document.viewSpecScript, ScriptField); } + + private _picker: any; + private _datePickerElGuid = Utils.GenerateGuid(); + + componentDidMount = () => { + this._picker = datepicker("#" + this._datePickerElGuid, { + disabler: (date: Date) => date > new Date(), + onSelect: (instance: any, date: Date) => runInAction(() => this._dateValue = date), + dateSelected: new Date() + }); + + runInAction(() => { + this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[0][1] = value)} />, ""]); + this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[1][1] = value)} />, ""]); + }); + } + @undoBatch viewChanged = (e: React.ChangeEvent) => { //@ts-ignore - switch (e.target.selectedOptions[0].value) { - case "freeform": - this.props.CollectionView.props.Document.viewType = CollectionViewType.Freeform; - break; - case "schema": - this.props.CollectionView.props.Document.viewType = CollectionViewType.Schema; - break; - case "treeview": - this.props.CollectionView.props.Document.viewType = CollectionViewType.Tree; - break; - case "stacking": - this.props.CollectionView.props.Document.viewType = CollectionViewType.Stacking; - break; - case "masonry": - this.props.CollectionView.props.Document.viewType = CollectionViewType.Masonry; - break; - default: - break; + this.props.CollectionView.props.Document.viewType = parseInt(e.target.selectedOptions[0].value); + } + + @action + openViewSpecs = (e: React.SyntheticEvent) => { + this._viewSpecsOpen = true; + + //@ts-ignore + if (!e.target.classList[0].startsWith("qs")) { + this.closeDatePicker(); + } + + e.stopPropagation(); + document.removeEventListener("pointerdown", this.closeViewSpecs); + document.addEventListener("pointerdown", this.closeViewSpecs); + } + + @action closeViewSpecs = () => { this._viewSpecsOpen = false; document.removeEventListener("pointerdown", this.closeViewSpecs); }; + + @action + openDatePicker = (e: React.PointerEvent) => { + this.openViewSpecs(e); + if (this._picker) { + this._picker.alwaysShow = true; + this._picker.show(); + // TODO: calendar is offset when zoomed in/out + // this._picker.calendar.style.position = "absolute"; + // let transform = this.props.CollectionView.props.ScreenToLocalTransform(); + // let x = parseInt(this._picker.calendar.style.left) / transform.Scale; + // let y = parseInt(this._picker.calendar.style.top) / transform.Scale; + // this._picker.calendar.style.left = x; + // this._picker.calendar.style.top = y; + + e.stopPropagation(); } } + @action + addKeyRestriction = (e: React.MouseEvent) => { + let index = this._keyRestrictions.length; + this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[index][1] = value)} />, ""]); + + this.openViewSpecs(e); + } + + @action + applyFilter = (e: React.MouseEvent) => { + this.openViewSpecs(e); + + let keyRestrictionScript = `${this._keyRestrictions.map(i => i[1]) + .reduce((acc: string, value: string, i: number) => value ? `${acc} && ${value}` : acc)}`; + let yearOffset = this._dateWithinValue[1] === 'y' ? 1 : 0; + let monthOffset = this._dateWithinValue[1] === 'm' ? parseInt(this._dateWithinValue[0]) : 0; + let weekOffset = this._dateWithinValue[1] === 'w' ? parseInt(this._dateWithinValue[0]) : 0; + let dayOffset = (this._dateWithinValue[1] === 'd' ? parseInt(this._dateWithinValue[0]) : 0) + weekOffset * 7; + let lowerBound = new Date(this._dateValue.getFullYear() - yearOffset, this._dateValue.getMonth() - monthOffset, this._dateValue.getDate() - dayOffset); + let upperBound = new Date(this._dateValue.getFullYear() + yearOffset, this._dateValue.getMonth() + monthOffset, this._dateValue.getDate() + dayOffset + 1); + let dateRestrictionScript = `((doc.creationDate as any).date >= ${lowerBound.valueOf()} && (doc.creationDate as any).date <= ${upperBound.valueOf()})`; + let fullScript = `return ${dateRestrictionScript} && ${keyRestrictionScript}`; + let compiled = CompileScript(fullScript, { params: { doc: Doc.name } }); + if (compiled.compiled) { + this.props.CollectionView.props.Document.viewSpecScript = new ScriptField(compiled); + } + } + + @action + closeDatePicker = () => { + if (this._picker) { + this._picker.alwaysShow = false; + this._picker.hide(); + } + document.removeEventListener("pointerdown", this.closeDatePicker); + } + render() { return (
- + + + + + +
+ +
+ {this._keyRestrictions.map(i => i[0])} +
+
+ CREATED WITHIN: +
+ + +
+
+ + +
+
+
) } @@ -62,6 +196,7 @@ export class CollectionStackingViewChrome extends React.Component => { @@ -109,41 +244,53 @@ export class CollectionStackingViewChrome extends React.Component { this.props.CollectionView.props.Document.stackingHeadersSortDescending = !this.props.CollectionView.props.Document.stackingHeadersSortDescending; } @action resetValue = () => { this._currentKey = this.sectionFilter; }; render() { return (
-
-
- Group items by: -
-
- this.sectionFilter} - autosuggestProps={ - { - resetValue: this.resetValue, - value: this._currentKey, - onChange: this.onKeyChange, - autosuggestProps: { - inputProps: - { - value: this._currentKey, - onChange: this.onKeyChange - }, - getSuggestionValue: this.getSuggestionValue, - suggestions: this.suggestions, - alwaysRenderSuggestions: true, - renderSuggestion: this.renderSuggestion, - onSuggestionsFetchRequested: this.onSuggestionFetch, - onSuggestionsClearRequested: this.onSuggestionClear - } - }} - SetValue={this.setValue} - contents={this.sectionFilter ? this.sectionFilter : "N/A"} - /> +
+ +
+
+ Group items by: +
+
+ this.sectionFilter} + autosuggestProps={ + { + resetValue: this.resetValue, + value: this._currentKey, + onChange: this.onKeyChange, + autosuggestProps: { + inputProps: + { + value: this._currentKey, + onChange: this.onKeyChange + }, + getSuggestionValue: this.getSuggestionValue, + suggestions: this.suggestions, + alwaysRenderSuggestions: true, + renderSuggestion: this.renderSuggestion, + onSuggestionsFetchRequested: this.onSuggestionFetch, + onSuggestionsClearRequested: this.onSuggestionClear + } + }} + oneLine + SetValue={this.setValue} + contents={this.sectionFilter ? this.sectionFilter : "N/A"} + /> +
diff --git a/src/client/views/collections/KeyRestrictionRow.tsx b/src/client/views/collections/KeyRestrictionRow.tsx new file mode 100644 index 000000000..8051a8359 --- /dev/null +++ b/src/client/views/collections/KeyRestrictionRow.tsx @@ -0,0 +1,45 @@ +import * as React from "react"; +import { observable, runInAction } from "mobx"; +import { observer } from "mobx-react"; +import { PastelSchemaPalette } from "../../../new_fields/SchemaHeaderField"; + +interface IKeyRestrictionProps { + contains: boolean; + script: (value: string) => void; +} + +@observer +export default class KeyRestrictionRow extends React.Component { + @observable private _key = ""; + @observable private _value = ""; + @observable private _contains = this.props.contains; + + render() { + if (this._key && this._value) { + let parsedValue: string | number = `"${this._value}"`; + let parsed = parseInt(this._value); + if (!isNaN(parsed)) { + parsedValue = parsed; + } + let scriptText = `(doc.${this._key} ${this._contains ? "===" : "!=="} ${parsedValue})`; + this.props.script(scriptText); + } + return ( +
+ runInAction(() => this._key = e.target.value)} + placeholder="KEY" /> + + runInAction(() => this._value = e.target.value)} + placeholder="VALUE" /> +
+ ) + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 75070c4c2188823ed9a09816861d4f873574c9db Mon Sep 17 00:00:00 2001 From: Fawn 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') 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') 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 ede0719d96cc2551490398caf3e1f41fe7992931 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Wed, 24 Jul 2019 22:27:37 -0400 Subject: view specs almost entirely done, refactored some chrome impl --- .../views/collections/CollectionStackingView.scss | 1 + .../views/collections/CollectionStackingView.tsx | 6 +- src/client/views/collections/CollectionSubView.tsx | 1 + src/client/views/collections/CollectionView.tsx | 42 ++-- .../views/collections/CollectionViewChromes.scss | 156 +++++++-------- .../views/collections/CollectionViewChromes.tsx | 214 ++++++++++++--------- 6 files changed, 227 insertions(+), 193 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index e0ced8af4..f43340967 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -7,6 +7,7 @@ display: flex; overflow-y: auto; flex-wrap: wrap; + transition: top .5s; .collectionStackingView-docView-container { width: 45%; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index a78a47ffb..31ec80d76 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -8,7 +8,7 @@ import { BoolCast, NumCast, Cast, StrCast, FieldValue } from "../../../new_field import { emptyFunction, Utils } from "../../../Utils"; import { CollectionSchemaPreview } from "./CollectionSchemaView"; import "./CollectionStackingView.scss"; -import { CollectionSubView } from "./CollectionSubView"; +import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView"; import { undoBatch } from "../../util/UndoManager"; import { DragManager } from "../../util/DragManager"; import { DocumentType } from "../../documents/Documents"; @@ -19,6 +19,7 @@ import { listSpec } from "../../../new_fields/Schema"; import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { List } from "../../../new_fields/List"; import { EditableView } from "../EditableView"; +import { CollectionViewProps } from "./CollectionBaseView"; let valuesCreated = 1; @@ -32,6 +33,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 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); } @@ -265,7 +267,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } // let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); return ( -
e.stopPropagation()} > {/* {sectionFilter as boolean ? [ ["width > height", this.filteredChildren.filter(f => f[WidthSym]() >= 1 + f[HeightSym]())], diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 24c8adb35..98447e824 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -30,6 +30,7 @@ export interface CollectionViewProps extends FieldViewProps { moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; PanelWidth: () => number; PanelHeight: () => number; + chromeCollapsed: boolean; } export interface SubCollectionViewProps extends CollectionViewProps { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index ba9780c24..e2f652908 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -17,7 +17,8 @@ import { CollectionStackingView } from './CollectionStackingView'; import { CollectionTreeView } from "./CollectionTreeView"; import { StrCast, PromiseValue } from '../../../new_fields/Types'; import { DocumentType } from '../../documents/Documents'; -import { CollectionStackingViewChrome } from './CollectionViewChromes'; +import { CollectionStackingViewChrome, CollectionViewBaseChrome } from './CollectionViewChromes'; +import { observable } from 'mobx'; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh); @@ -32,40 +33,39 @@ library.add(faImage); @observer export class CollectionView extends React.Component { + @observable private _collapsed = false; + public static LayoutString(fieldStr: string = "data", fieldExt: string = "") { return FieldView.LayoutString(CollectionView, fieldStr, fieldExt); } 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 (); - case CollectionViewType.Tree: return (); - case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } - case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } + case CollectionViewType.Schema: return (); + 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 (); } case CollectionViewType.Freeform: default: - return (); + return (); } return (null); } - private Chrome = (type: CollectionViewType) => { - if (this.isAnnotationOverlay || this.props.Document === CurrentUserUtils.UserDocument.sidebar) { - return (null); - } - - switch (type) { - case CollectionViewType.Stacking: return (); - default: - return null; - } + private collapse = (value: boolean) => { + this._collapsed = value; } private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => { - return [ - this.Chrome(type), - this.SubViewHelper(type, renderProps) - ] + if (this.isAnnotationOverlay || this.props.Document === CurrentUserUtils.UserDocument.sidebar) { + return [(null), this.SubViewHelper(type, renderProps)]; + } + else { + return [ + (), + this.SubViewHelper(type, renderProps) + ]; + } } get isAnnotationOverlay() { return this.props.fieldExt ? true : false; } diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index 3103cd309..d37228bde 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -1,98 +1,104 @@ @import "../globalCssVariables"; @import '~js-datepicker/dist/datepicker.min.css'; -.collectionViewBaseChrome { - display: flex; - - .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; - } - - .collectionViewBaseChrome-viewPicker:active { - outline-color: black; - } - - .collectionViewBaseChrome-collapse { - margin-right: 10px; - transition: all .5s; - } +.collectionViewChrome { + display: grid; + grid-template-columns: 1fr auto; + padding-bottom: 10px; + border-bottom: .5px solid lightgrey; + margin: 10px; + position: relative; + z-index: 9001; + transition: top .5s; - .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-viewSpecsMenu { - overflow: hidden; - transition: height .5s, display .5s; + .collectionViewBaseChrome-viewPicker:active { + outline-color: black; + } + + .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; + } + + .collectionViewBaseChrome-viewSpecs { + margin-left: 10px; + display: grid; - .qs-datepicker { - left: unset; - right: 0; + .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-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; + .collectionViewBaseChrome-viewSpecsMenu-lastRow { + display: grid; + grid-template-columns: 1fr 1fr; + grid-gap: 10px; + margin: 10px; + } } } } -} -.collectionStackingViewChrome { - display: grid; - grid-template-columns: 1fr auto; - padding-bottom: 10px; - border-bottom: .5px solid lightgrey; - margin: 10px; .collectionStackingViewChrome-cont { display: flex; diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 2edac384d..24d13d5cb 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -19,16 +19,19 @@ const datepicker = require('js-datepicker'); interface CollectionViewChromeProps { CollectionView: CollectionView; + type: CollectionViewType; + collapse?: (value: boolean) => any; } let stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation(); @observer -class CollectionViewBaseChrome extends React.Component { +export class CollectionViewBaseChrome extends React.Component { @observable private _viewSpecsOpen: boolean = false; @observable private _dateWithinValue: string = ""; @observable private _dateValue: Date = new Date(); @observable private _keyRestrictions: [JSX.Element, string][] = []; + @observable private _collapsed: boolean = false; @computed private get filterValue() { return Cast(this.props.CollectionView.props.Document.viewSpecScript, ScriptField); } private _picker: any; @@ -124,68 +127,92 @@ class CollectionViewBaseChrome extends React.Component { + this._collapsed = !this._collapsed; + this.props.collapse(this._collapsed); + } + + subChrome = () => { + + switch (this.props.type) { + case CollectionViewType.Stacking: return ( + ); + default: + return null; + } + } + render() { return ( -
- - -
- -
- {this._keyRestrictions.map(i => i[0])} -
-
- CREATED WITHIN: +
+
+ + +
+ +
+ {this._keyRestrictions.map(i => i[0])} +
+
+ CREATED WITHIN:
- - -
-
-
+
+ - +
+ {this.subChrome()}
) } @@ -249,48 +276,45 @@ export class CollectionStackingViewChrome extends React.Component - -
- -
-
- Group items by: -
-
- this.sectionFilter} - autosuggestProps={ - { - resetValue: this.resetValue, - value: this._currentKey, - onChange: this.onKeyChange, - autosuggestProps: { - inputProps: - { - value: this._currentKey, - onChange: this.onKeyChange - }, - getSuggestionValue: this.getSuggestionValue, - suggestions: this.suggestions, - alwaysRenderSuggestions: true, - renderSuggestion: this.renderSuggestion, - onSuggestionsFetchRequested: this.onSuggestionFetch, - onSuggestionsClearRequested: this.onSuggestionClear - } - }} - oneLine - SetValue={this.setValue} - contents={this.sectionFilter ? this.sectionFilter : "N/A"} - /> +
+ +
+ +
+
+ Group items by:
+
+ this.sectionFilter} + autosuggestProps={ + { + resetValue: this.resetValue, + value: this._currentKey, + onChange: this.onKeyChange, + autosuggestProps: { + inputProps: + { + value: this._currentKey, + onChange: this.onKeyChange + }, + getSuggestionValue: this.getSuggestionValue, + suggestions: this.suggestions, + alwaysRenderSuggestions: true, + renderSuggestion: this.renderSuggestion, + onSuggestionsFetchRequested: this.onSuggestionFetch, + onSuggestionsClearRequested: this.onSuggestionClear + } + }} + oneLine + SetValue={this.setValue} + contents={this.sectionFilter ? this.sectionFilter : "N/A"} + />
-- cgit v1.2.3-70-g09d2 From f8f3ee8df596758ca6f5f7e735fb1296a676f5b6 Mon Sep 17 00:00:00 2001 From: Fawn Date: Wed, 24 Jul 2019 22:31:45 -0400 Subject: merge --- .../views/collections/CollectionSchemaMovableTableHOC.tsx | 15 ++++++++++----- src/client/views/collections/CollectionSchemaView.scss | 9 +++++++++ src/client/views/collections/CollectionViewChromes.tsx | 6 +++--- 3 files changed, 22 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 6d388bb40..290958cd0 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -8,7 +8,11 @@ import { SelectionManager } from "../../util/SelectionManager"; 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 { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +library.add(faGripVertical); export interface MovableColumnProps { columnRenderer: TableCellRenderer; @@ -198,11 +202,12 @@ export class MovableRow extends React.Component { return (
-
- - {children} - -
+ +
+ +
+ {children} +
); diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 3bc1bc060..22d8a5cb6 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -70,6 +70,9 @@ } .rt-thead { + width: calc(100% - 30px); + margin-left: 30px; + &.-header { // background: $intermediate-color; // color: $light-color; @@ -77,6 +80,8 @@ height: 30px; // border: 1px solid $intermediate-color; box-shadow: none; + // width: calc(100% - 30px); + // margin-right: -30px; } .rt-resizable-header { @@ -298,6 +303,10 @@ button.add-column { .row-dragger { // height: $MAX_ROW_HEIGHT; + width: 30px; + height: 100%; + padding: 10px; + color: gray; } .collectionSchema-row-wrapper { diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 52fee26bf..03676fe86 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -53,7 +53,7 @@ class CollectionViewBaseChrome extends React.ComponentMasonry View
- ) + ); } } @@ -147,6 +147,6 @@ export class CollectionStackingViewChrome extends React.Component
- ) + ); } -} \ No newline at end of file +} -- 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') 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') 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') 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') 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') 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 0baefb4e0b133df60f42d894733113c961740af3 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Thu, 25 Jul 2019 19:30:44 -0400 Subject: almost done --- .../views/collections/CollectionStackingView.scss | 42 ++++++++++++---------- .../views/collections/CollectionStackingView.tsx | 8 ++--- .../CollectionStackingViewFieldColumn.tsx | 26 ++++++++------ .../views/collections/CollectionViewChromes.scss | 5 +-- .../views/collections/CollectionViewChromes.tsx | 6 ++-- 5 files changed, 48 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index f43340967..9dbe4ccb8 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -96,7 +96,6 @@ outline: none; border: 0px; color: $light-color; - text-transform: uppercase; letter-spacing: 2px; font-size: 75%; transition: transform 0.2s; @@ -118,9 +117,7 @@ padding: 12px 10px 11px 10px; border: 0px; color: grey; - // font-size: 75%; text-align: center; - text-transform: uppercase; letter-spacing: 2px; outline-color: black; } @@ -142,15 +139,6 @@ width: 90%; color: lightgrey; overflow: ellipses; - } - - .collectionStackingView-addGroupButton { - background: rgb(238, 238, 238); - font-size: 75%; - text-align: center; - text-transform: uppercase; - letter-spacing: 2px; - height: fit-content; .editableView-container-editing-oneLine, .editableView-container-editing { @@ -165,14 +153,32 @@ } .editableView-input { - padding: 12px 10px 11px 10px; - border: 0px; - color: grey; - // font-size: 75%; - text-align: center; - text-transform: uppercase; + outline-color: black; letter-spacing: 2px; + color: grey; + border: 0px; + padding: 12px 10px 11px 10px; + } + } + + .collectionStackingView-addDocumentButton { + font-size: 75%; + letter-spacing: 2px; + + .editableView-input { outline-color: black; + letter-spacing: 2px; + color: grey; + border: 0px; + padding: 12px 10px 11px 10px; } } + + .collectionStackingView-addGroupButton { + background: rgb(238, 238, 238); + font-size: 75%; + text-align: center; + letter-spacing: 2px; + height: fit-content; + } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index b5c0fb3d6..7c93201fe 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -47,7 +47,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let fields = new Map(sectionHeaders.map(sh => [sh, []])); if (sectionFilter) { this.filteredChildren.map(d => { - let sectionValue = (d[sectionFilter] ? d[sectionFilter] : `No ${sectionFilter} value`) as object; + let sectionValue = (d[sectionFilter] ? d[sectionFilter] : `NO ${sectionFilter.toUpperCase()} VALUE`) as object; // the next five lines ensures that floating point rounding errors don't create more than one section -syip let parsed = parseInt(sectionValue.toString()); let castedSectionValue: any = sectionValue; @@ -56,12 +56,12 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } // look for if header exists already - let existingHeader = sectionHeaders!.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `No ${sectionFilter} value`)); + let existingHeader = sectionHeaders!.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${sectionFilter.toUpperCase()} VALUE`)); if (existingHeader) { fields.get(existingHeader)!.push(d); } else { - let newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `No ${sectionFilter} value`); + let newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${sectionFilter.toUpperCase()} VALUE`); fields.set(newSchemaHeader, [d]); sectionHeaders!.push(newSchemaHeader); } @@ -260,7 +260,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let editableViewProps = { GetValue: () => "", SetValue: this.addGroup, - contents: "+ Add a Group" + contents: "+ ADD A GROUP" } // let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); return ( diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 582adc418..ea2a302ff 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -18,6 +18,7 @@ import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { ScriptField } from "../../../new_fields/ScriptField"; import { CompileScript } from "../../util/Scripting"; +import { RichTextField } from "../../../new_fields/RichTextField"; interface CSVFieldColumnProps { @@ -168,11 +169,11 @@ export class CollectionStackingViewFieldColumn extends React.Component { + addDocument = (value: string, shiftDown?: boolean) => { let key = StrCast(this.props.parent.props.Document.sectionFilter); - let newDoc = Docs.Create.TextDocument({ height: 18, title: "new text document" }); + let newDoc = Docs.Create.TextDocument({ height: 18, width: 200, title: value }); newDoc[key] = this.getValue(this.props.heading); - this.props.parent.props.addDocument(newDoc); + return this.props.parent.props.addDocument(newDoc); } @action @@ -231,29 +232,34 @@ export class CollectionStackingViewFieldColumn extends React.Component headings.indexOf(i) === idx); - let evContents = heading ? heading : this.props.type && this.props.type === "number" ? "0" : `No ${key} value`; - let editableViewProps = { + let evContents = heading ? heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`; + let headerEditableViewProps = { GetValue: () => evContents, SetValue: this.headingChanged, contents: evContents, oneLine: true } + let newEditableViewProps = { + GetValue: () => "", + SetValue: this.addDocument, + contents: "+ NEW" + } let headingView = this.props.headingObject ?
{/* the default bucket (no key value) has a tooltip that describes what it is. Further, it does not have a color and cannot be deleted. */}
- - {evContents === `No ${key} value` ? + + {evContents === `NO ${key.toUpperCase()} VALUE` ? (null) : +
); diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index 0faca0607..6525f3b07 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -5,7 +5,7 @@ position: relative; z-index: 9001; transition: top .5s; - background: rgb(238, 238, 238); + background: lightslategray; padding: 10px; .collectionViewChrome { @@ -48,7 +48,6 @@ border: 0px; color: grey; text-align: center; - text-transform: uppercase; letter-spacing: 2px; outline-color: black; font-size: 75%; @@ -128,7 +127,6 @@ justify-self: right; display: flex; font-size: 75%; - text-transform: uppercase; letter-spacing: 2px; .collectionStackingViewChrome-sectionFilter-label { @@ -150,7 +148,6 @@ border: 0px; color: grey; text-align: center; - text-transform: uppercase; letter-spacing: 2px; outline-color: black; height: 100%; diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 4129781f7..78ceaad86 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -180,11 +180,11 @@ export class CollectionViewBaseChrome extends React.ComponentSchema View - +
- Group items by: + GROUP ITEMS BY:
Date: Thu, 25 Jul 2019 19:44:40 -0400 Subject: merge --- src/client/views/collections/CollectionSchemaCells.tsx | 4 ++-- src/client/views/collections/CollectionSchemaView.scss | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index d453fed47..4a618a436 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -158,8 +158,8 @@ export class CollectionSchemaCell extends React.Component { if (this.props.isFocused && !this.props.isEditable) className += " inactive"; return ( -
-
+
+
Date: Thu, 25 Jul 2019 20:41:06 -0400 Subject: expand treeview when switching modes --- src/client/views/collections/CollectionTreeView.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index ff3221ada..eba78e772 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -201,7 +201,11 @@ class TreeView extends React.Component { let headerElements = ( this.props.document.treeViewExpandedView = this.treeViewExpandedView === "data" ? "fields" : this.treeViewExpandedView === "fields" && this.props.document.layout ? "layout" : "data")}> + onPointerDown={action(() => { + this.props.document.treeViewExpandedView = this.treeViewExpandedView === "data" ? "fields" : + this.treeViewExpandedView === "fields" && this.props.document.layout ? "layout" : "data"; + this._collapsed = false; + })}> {this.treeViewExpandedView} ); let dataDocs = CollectionDockingView.Instance ? Cast(CollectionDockingView.Instance.props.Document[this.fieldKey], listSpec(Doc), []) : []; -- cgit v1.2.3-70-g09d2 From 0416f5686f44f6de349a99ecdce4de550b703dea Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 25 Jul 2019 21:22:54 -0400 Subject: fixed script loading --- src/new_fields/ScriptField.ts | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts index 00b4dec2c..6d52525b8 100644 --- a/src/new_fields/ScriptField.ts +++ b/src/new_fields/ScriptField.ts @@ -26,6 +26,7 @@ const optionsSchema = createSimpleSchema({ requiredType: true, addReturn: true, typecheck: true, + editable: true, readonly: true, params: optional(map(primitive())) }); -- cgit v1.2.3-70-g09d2 From 3ee8a9ebc760e3049b692efad0d6edfb877342cf Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 25 Jul 2019 22:27:26 -0400 Subject: fixed dragging annotaitons on images. fixed border rounding of buttons. fixed dropping to ignore document titles. --- src/client/util/DragManager.ts | 3 ++- src/client/views/collections/CollectionBaseView.tsx | 2 +- src/client/views/nodes/ButtonBox.scss | 2 ++ src/client/views/nodes/DocumentView.tsx | 3 ++- src/client/views/nodes/ImageBox.tsx | 2 -- 5 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 323908302..5271f2f5d 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -412,7 +412,6 @@ export namespace DragManager { }; let hideDragElements = () => { - SelectionManager.SetIsDragging(false); dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement)); eles.map(ele => (ele.hidden = false)); }; @@ -426,11 +425,13 @@ export namespace DragManager { AbortDrag = () => { hideDragElements(); + SelectionManager.SetIsDragging(false); endDrag(); }; const upHandler = (e: PointerEvent) => { hideDragElements(); dispatchDrag(eles, e, dragData, options, finishDrag); + SelectionManager.SetIsDragging(false); endDrag(); }; document.addEventListener("pointermove", moveHandler, true); diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 72faf52c4..c39caec24 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -124,7 +124,7 @@ export class CollectionBaseView extends React.Component { @action.bound moveDocument(doc: Doc, targetCollection: Doc, addDocument: (doc: Doc) => boolean): boolean { let self = this; - let targetDataDoc = this.props.fieldExt || this.props.Document.isTemplate ? this.extensionDoc : this.props.Document; + let targetDataDoc = this.props.Document; if (Doc.AreProtosEqual(targetDataDoc, targetCollection)) { //if (Doc.AreProtosEqual(this.extensionDoc, targetCollection)) { return true; diff --git a/src/client/views/nodes/ButtonBox.scss b/src/client/views/nodes/ButtonBox.scss index 97cc91128..92beafa15 100644 --- a/src/client/views/nodes/ButtonBox.scss +++ b/src/client/views/nodes/ButtonBox.scss @@ -2,9 +2,11 @@ width: 100%; height: 100%; pointer-events: all; + border-radius: inherit; } .buttonBox-mainButton { width: 100%; height: 100%; + border-radius: inherit; } \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b5e64ed19..4a5e20533 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -298,6 +298,7 @@ export class DocumentView extends DocComponent(Docu let fullScreenAlias = Doc.MakeAlias(this.props.Document); fullScreenAlias.templates = new List(); Doc.UseDetailLayout(fullScreenAlias); + fullScreenAlias.showCaption = true; this.props.addDocTab(fullScreenAlias, this.dataDoc, "inTab"); SelectionManager.DeselectAll(); this.props.Document.libraryBrush = false; @@ -673,7 +674,7 @@ export class DocumentView extends DocComponent(Docu {!showTitle ? (null) :
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 6541007d0..ea167286b 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -104,8 +104,6 @@ export class ImageBox extends DocComponent(ImageD e.stopPropagation(); } } - } else if (!this.props.isSelected()) { - e.stopPropagation(); } })); // de.data.removeDocument() bcz: need to implement -- cgit v1.2.3-70-g09d2 From 7d468c19c28a48314ea993d84e5995364e88fa86 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 26 Jul 2019 02:21:09 -0400 Subject: added a MakeBackground and FitToBox menu items. fixed problems with fitToBox and frozen dimensions. fixed issue with drop() on free forms. --- .../views/collections/CollectionBaseView.scss | 2 +- .../views/collections/CollectionBaseView.tsx | 6 ++-- src/client/views/collections/CollectionSubView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 32 +++++++++++++++------- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/client/views/nodes/DocumentView.scss | 1 - src/client/views/nodes/DocumentView.tsx | 7 +++++ src/client/views/nodes/ImageBox.tsx | 2 +- 8 files changed, 37 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionBaseView.scss b/src/client/views/collections/CollectionBaseView.scss index 34bcb705e..583e6f6ca 100644 --- a/src/client/views/collections/CollectionBaseView.scss +++ b/src/client/views/collections/CollectionBaseView.scss @@ -6,7 +6,7 @@ border-radius: 0 0 $border-radius $border-radius; box-sizing: border-box; border-radius: inherit; - pointer-events: all; width:100%; height:100%; + overflow: auto; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index c39caec24..67112ae7c 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -126,7 +126,6 @@ export class CollectionBaseView extends React.Component { let self = this; let targetDataDoc = this.props.Document; if (Doc.AreProtosEqual(targetDataDoc, targetCollection)) { - //if (Doc.AreProtosEqual(this.extensionDoc, targetCollection)) { return true; } if (this.removeDocument(doc)) { @@ -146,7 +145,10 @@ export class CollectionBaseView extends React.Component { const viewtype = this.collectionViewType; return (
{viewtype !== undefined ? this.props.children(viewtype, props) : (null)} diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 2ddefb3c0..cbc9e61eb 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -104,7 +104,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { } else if (de.data.moveDocument) { let movedDocs = de.data.options === this.props.Document[Id] ? de.data.draggedDocuments : de.data.droppedDocuments; added = movedDocs.reduce((added: boolean, d) => - de.data.moveDocument(d, /*this.props.DataDoc ? this.props.DataDoc :*/ this.props.Document, this.props.addDocument) || added, false); + de.data.moveDocument(d, this.props.Document, this.props.addDocument) || added, false); } else { added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 6500b3273..9c4275388 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -34,9 +34,11 @@ import { CompileScript } from "../../../util/Scripting"; import { CognitiveServices } from "../../../cognitive_services/CognitiveServices"; import { library } from "@fortawesome/fontawesome-svg-core"; import { faEye } from "@fortawesome/free-regular-svg-icons"; -import { faTable, faPaintBrush, faAsterisk } from "@fortawesome/free-solid-svg-icons"; +import { faTable, faPaintBrush, faAsterisk, faExpandArrowsAlt, faCompressArrowsAlt } from "@fortawesome/free-solid-svg-icons"; +import { undo } from "prosemirror-history"; +import { number } from "prop-types"; -library.add(faEye, faTable, faPaintBrush); +library.add(faEye, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt); export const panZoomSchema = createSchema({ panX: "number", @@ -58,24 +60,29 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { private get _pheight() { return this.props.PanelHeight(); } private inkKey = "ink"; + get prevScaling() { + return (this.props as any).ContentScaling && this.Document.nativeWidth && this.fitToBox ? (this.props as any).ContentScaling() : 1; + } + @computed get contentBounds() { - let bounds = this.props.fitToBox && !NumCast(this.nativeWidth) ? Doc.ComputeContentBounds(DocListCast(this.props.Document.data)) : undefined; + let bounds = (this.fitToBox) && !this.nativeWidth ? Doc.ComputeContentBounds(DocListCast(this.props.Document.data)) : undefined; return { panX: bounds ? (bounds.x + bounds.r) / 2 : this.Document.panX || 0, panY: bounds ? (bounds.y + bounds.b) / 2 : this.Document.panY || 0, - scale: bounds ? Math.min(this.props.PanelHeight() / (bounds.b - bounds.y), this.props.PanelWidth() / (bounds.r - bounds.x)) : this.Document.scale || 1 + scale: (bounds ? Math.min(this.props.PanelHeight() / (bounds.b - bounds.y), this.props.PanelWidth() / (bounds.r - bounds.x)) : this.Document.scale || 1) / this.prevScaling }; } - @computed get nativeWidth() { return this.Document.nativeWidth || 0; } - @computed get nativeHeight() { return this.Document.nativeHeight || 0; } + @computed get fitToBox() { return this.props.fitToBox || this.props.Document.fitToBox; } + @computed get nativeWidth() { return this.fitToBox ? 0 : this.Document.nativeWidth || 0; } + @computed get nativeHeight() { return this.fitToBox ? 0 : this.Document.nativeHeight || 0; } public get isAnnotationOverlay() { return this.props.fieldExt ? true : false; } // fieldExt will be "" or "annotation". should maybe generalize this, or make it more specific (ie, 'annotation' instead of 'fieldExt') private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; } private panX = () => this.contentBounds.panX; private panY = () => this.contentBounds.panY; private zoomScaling = () => this.contentBounds.scale; - private centeringShiftX = () => !this.nativeWidth ? this._pwidth / 2 : 0; // shift so pan position is at center of window for non-overlay collections - private centeringShiftY = () => !this.nativeHeight ? this._pheight / 2 : 0;// shift so pan position is at center of window for non-overlay collections + private centeringShiftX = () => !this.nativeWidth ? this._pwidth / 2 / this.prevScaling : 0; // shift so pan position is at center of window for non-overlay collections + private centeringShiftY = () => !this.nativeHeight ? this._pheight / 2 / this.prevScaling : 0;// shift so pan position is at center of window for non-overlay collections private getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth + 1, -this.borderWidth + 1).translate(-this.centeringShiftX(), -this.centeringShiftY()).transform(this.getLocalTransform()); private getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth); private getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.zoomScaling()).translate(this.panX(), this.panY()); @@ -109,11 +116,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @undoBatch @action drop = (e: Event, de: DragManager.DropEvent) => { + let xf = this.getTransform(); if (super.drop(e, de)) { if (de.data instanceof DragManager.DocumentDragData) { if (de.data.droppedDocuments.length) { - let dragDoc = de.data.droppedDocuments[0]; - let [xp, yp] = this.getTransform().transformPoint(de.x, de.y); + let [xp, yp] = xf.transformPoint(de.x, de.y); let x = xp - de.data.xOffset; let y = yp - de.data.yOffset; let dropX = NumCast(de.data.droppedDocuments[0].x); @@ -491,6 +498,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } onContextMenu = () => { + ContextMenu.Instance.addItem({ + description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`, + event: undoBatch(async () => this.props.Document.fitToBox = !this.fitToBox), + icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" + }); ContextMenu.Instance.addItem({ description: "Arrange contents in grid", icon: "table", diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index b765517a2..d96e93aeb 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -365,7 +365,7 @@ export class MarqueeView extends React.Component marqueeSelect() { let selRect = this.Bounds; let selection: Doc[] = []; - this.props.activeDocuments().map(doc => { + this.props.activeDocuments().filter(doc => !doc.isBackground).map(doc => { var z = NumCast(doc.zoomBasis, 1); var x = NumCast(doc.x); var y = NumCast(doc.y); diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index 3a4b46b7e..7c72fb6e6 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -4,7 +4,6 @@ position: inherit; top: 0; left:0; - pointer-events: all; // background: $light-color; //overflow: hidden; transform-origin: left top; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 4a5e20533..9d2dd3121 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -514,6 +514,11 @@ export class DocumentView extends DocComponent(Docu } proto.ignoreAspect = !BoolCast(proto.ignoreAspect, false); } + @undoBatch + @action + makeBackground = (): void => { + this.props.Document.isBackground = true; + } @undoBatch @action @@ -544,6 +549,7 @@ export class DocumentView extends DocComponent(Docu 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({ description: "Make Portal", event: () => { @@ -648,6 +654,7 @@ export class DocumentView extends DocComponent(Docu
(ImageD if (field instanceof ImageField) paths = [this.choosePath(field.url)]; paths.push(...altpaths); // } - let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; + let interactive = InkingControl.Instance.selectedTool || this.props.Document.isBackground ? "" : "-interactive"; let rotation = NumCast(this.dataDoc.rotation, 0); let aspect = (rotation % 180) ? this.dataDoc[HeightSym]() / this.dataDoc[WidthSym]() : 1; let shift = (rotation % 180) ? (nativeHeight - nativeWidth / aspect) / 2 : 0; -- cgit v1.2.3-70-g09d2 From 04030194e690764a2d1a58b25568511a3c6dcb98 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 26 Jul 2019 09:14:06 -0400 Subject: fixed fitToBox layout issue --- .../collectionFreeForm/CollectionFreeFormView.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 9c4275388..5d61aefc7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -60,16 +60,16 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { private get _pheight() { return this.props.PanelHeight(); } private inkKey = "ink"; - get prevScaling() { - return (this.props as any).ContentScaling && this.Document.nativeWidth && this.fitToBox ? (this.props as any).ContentScaling() : 1; + get parentScaling() { + return (this.props as any).ContentScaling && this.Document.nativeWidth && this.fitToBox && !this.isAnnotationOverlay ? (this.props as any).ContentScaling() : 1; } @computed get contentBounds() { - let bounds = (this.fitToBox) && !this.nativeWidth ? Doc.ComputeContentBounds(DocListCast(this.props.Document.data)) : undefined; + let bounds = this.fitToBox && !this.nativeWidth && !this.isAnnotationOverlay ? Doc.ComputeContentBounds(DocListCast(this.props.Document.data)) : undefined; return { panX: bounds ? (bounds.x + bounds.r) / 2 : this.Document.panX || 0, panY: bounds ? (bounds.y + bounds.b) / 2 : this.Document.panY || 0, - scale: (bounds ? Math.min(this.props.PanelHeight() / (bounds.b - bounds.y), this.props.PanelWidth() / (bounds.r - bounds.x)) : this.Document.scale || 1) / this.prevScaling + scale: (bounds ? Math.min(this.props.PanelHeight() / (bounds.b - bounds.y), this.props.PanelWidth() / (bounds.r - bounds.x)) : this.Document.scale || 1) / this.parentScaling }; } @@ -81,8 +81,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { private panX = () => this.contentBounds.panX; private panY = () => this.contentBounds.panY; private zoomScaling = () => this.contentBounds.scale; - private centeringShiftX = () => !this.nativeWidth ? this._pwidth / 2 / this.prevScaling : 0; // shift so pan position is at center of window for non-overlay collections - private centeringShiftY = () => !this.nativeHeight ? this._pheight / 2 / this.prevScaling : 0;// shift so pan position is at center of window for non-overlay collections + private centeringShiftX = () => !this.nativeWidth && !this.isAnnotationOverlay ? this._pwidth / 2 / this.parentScaling : 0; // shift so pan position is at center of window for non-overlay collections + private centeringShiftY = () => !this.nativeHeight && !this.isAnnotationOverlay ? this._pheight / 2 / this.parentScaling : 0;// shift so pan position is at center of window for non-overlay collections private getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth + 1, -this.borderWidth + 1).translate(-this.centeringShiftX(), -this.centeringShiftY()).transform(this.getLocalTransform()); private getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth); private getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.zoomScaling()).translate(this.panX(), this.panY()); -- cgit v1.2.3-70-g09d2 From e189378e5ce01eedd1373172fbd8d8dabf2ad197 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 26 Jul 2019 16:07:26 -0400 Subject: fixes for templates fo stacking things. --- src/client/views/DocumentDecorations.tsx | 3 +- src/client/views/InkingControl.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 36 ++++++++++++++-------- .../views/collections/CollectionTreeView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 31 +++++++++++-------- 5 files changed, 45 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 6fecbd3a7..255855b45 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -346,7 +346,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> onRadiusMove = (e: PointerEvent): void => { let dist = Math.sqrt((e.clientX - this._radiusDown[0]) * (e.clientX - this._radiusDown[0]) + (e.clientY - this._radiusDown[1]) * (e.clientY - this._radiusDown[1])); - SelectionManager.SelectedDocuments().map(dv => dv.props.Document.borderRounding = Doc.GetProto(dv.props.Document).borderRounding = `${Math.min(100, dist)}%`); + SelectionManager.SelectedDocuments().map(dv => dv.props.Document.layout instanceof Doc ? dv.props.Document.layout : dv.props.Document.isTemplate ? dv.props.Document : Doc.GetProto(dv.props.Document)). + map(d => d.borderRounding = `${Math.min(100, dist)}%`); e.stopPropagation(); e.preventDefault(); } diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index da388e532..58c83915b 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -47,7 +47,7 @@ export class InkingControl extends React.Component { if (MainOverlayTextBox.Instance.SetColor(color.hex)) return; let selected = SelectionManager.SelectedDocuments(); let oldColors = selected.map(view => { - let targetDoc = view.props.Document.isTemplate ? view.props.Document : Doc.GetProto(view.props.Document); + let targetDoc = view.props.Document.layout instanceof Doc ? view.props.Document.layout : view.props.Document.isTemplate ? view.props.Document : Doc.GetProto(view.props.Document); let oldColor = StrCast(targetDoc.backgroundColor); targetDoc.backgroundColor = this._selectedColor; return { diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 213aa981d..5a123bf65 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -23,15 +23,20 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { _docXfs: any[] = []; _columnStart: number = 0; @observable private cursor: CursorProperty = "grab"; - @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); } - @computed get singleColumn() { return BoolCast(this.props.Document.singleColumn, true); } - @computed get columnWidth() { return this.singleColumn ? (this.props.PanelWidth() / (this.props as any).ContentScaling() - 2 * this.xMargin) : Math.min(this.props.PanelWidth() - 2 * this.xMargin, NumCast(this.props.Document.columnWidth, 250)); } + @computed get xMargin() { return NumCast(this.layoutDoc.xMargin, 2 * this.gridGap); } + @computed get yMargin() { return NumCast(this.layoutDoc.yMargin, 2 * this.gridGap); } + @computed get gridGap() { return NumCast(this.layoutDoc.gridGap, 10); } + @computed get singleColumn() { return BoolCast(this.layoutDoc.singleColumn, true); } + @computed get columnWidth() { return this.singleColumn ? (this.props.PanelWidth() / (this.props as any).ContentScaling() - 2 * this.xMargin) : Math.min(this.props.PanelWidth() - 2 * this.xMargin, NumCast(this.layoutDoc.columnWidth, 250)); } @computed get filteredChildren() { return this.childDocs.filter(d => !d.isMinimized); } + get layoutDoc() { + // if this document's layout field contains a document (ie, a rendering template), then we will use that + // to determine the render JSX string, otherwise the layout field should directly contain a JSX layout string. + return this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document; + } @computed get Sections() { - let sectionFilter = StrCast(this.props.Document.sectionFilter); + let sectionFilter = StrCast(this.layoutDoc.sectionFilter); let fields = new Map(); sectionFilter && this.filteredChildren.map(d => { let sectionValue = (d[sectionFilter] ? d[sectionFilter] : "-undefined-") as object; @@ -42,10 +47,15 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } componentDidMount() { this._heightDisposer = reaction(() => [this.yMargin, this.gridGap, this.columnWidth, this.childDocs.map(d => [d.height, d.width, d.zoomBasis, d.nativeHeight, d.nativeWidth, d.isMinimized])], - () => this.singleColumn && - (this.props.Document.height = this.Sections.size * 50 + this.filteredChildren.reduce((height, d, i) => - height + this.getDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap), this.yMargin)) - , { fireImmediately: true }); + () => { + if (this.singleColumn) { + let hgt = this.Sections.size * 50 + this.filteredChildren.reduce((height, d, i) => { + let xhgt = height + this.getDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap); + return xhgt; + }, this.yMargin); + this.layoutDoc.height = hgt; + } + }, { fireImmediately: true }); } componentWillUnmount() { this._heightDisposer && this._heightDisposer(); @@ -65,7 +75,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } getDisplayDoc(layoutDoc: Doc, d: Doc, dxf: () => Transform) { - let resolvedDataDoc = !this.props.Document.isTemplate && this.props.DataDoc !== this.props.Document ? this.props.DataDoc : undefined; + let resolvedDataDoc = !this.layoutDoc.isTemplate && this.props.DataDoc !== this.layoutDoc ? this.props.DataDoc : undefined; let width = () => d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth; let height = () => this.getDocHeight(layoutDoc); let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]()); @@ -153,7 +163,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let dragPos = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0]; let delta = dragPos - this._columnStart; this._columnStart = dragPos; - this.props.Document.columnWidth = this.columnWidth + delta; + this.layoutDoc.columnWidth = this.columnWidth + delta; } @action @@ -250,7 +260,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { ["width > height", this.filteredChildren.filter(f => f[WidthSym]() >= 1 + f[HeightSym]())], ["width = height", this.filteredChildren.filter(f => Math.abs(f[WidthSym]() - f[HeightSym]()) < 1)], ["height > width", this.filteredChildren.filter(f => f[WidthSym]() + 1 <= f[HeightSym]())]]. */} - {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()). + {this.layoutDoc.sectionFilter ? Array.from(this.Sections.entries()). map(section => this.section(section[0].toString(), section[1])) : this.section("", this.filteredChildren)}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index eba78e772..a1697f9b4 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -360,7 +360,7 @@ class TreeView extends React.Component { let remDoc = (doc: Doc) => this.remove(doc, key); let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before); contentElement = key === "links" ? this.renderLinks() : - TreeView.GetChildElements(docList instanceof Doc ? [docList as Doc] : DocListCast(docList), this.props.treeViewId, realDoc, undefined, key, addDoc, remDoc, this.move, + TreeView.GetChildElements(docList instanceof Doc ? [docList] : DocListCast(docList), this.props.treeViewId, realDoc, undefined, key, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.renderDepth); } else { contentElement = (Docu return (); } + get layoutDoc() { + // if this document's layout field contains a document (ie, a rendering template), then we will use that + // to determine the render JSX string, otherwise the layout field should directly contain a JSX layout string. + return this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document; + } render() { if (this.Document.hidden) { return null; } let self = this; - let backgroundColor = this.props.Document.layout instanceof Doc ? StrCast(this.props.Document.layout.backgroundColor) : this.Document.backgroundColor; - let foregroundColor = StrCast(this.props.Document.layout instanceof Doc ? this.props.Document.layout.color : this.props.Document.color); + let backgroundColor = StrCast(this.layoutDoc.backgroundColor); + let foregroundColor = StrCast(this.layoutDoc.color); var nativeWidth = this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%"; var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; - let showOverlays = this.props.showOverlays ? this.props.showOverlays(this.props.Document) : undefined; - let showTitle = showOverlays && showOverlays.title !== "undefined" ? showOverlays.title : StrCast(this.props.Document.showTitle); - let showCaption = showOverlays && showOverlays.caption !== "undefined" ? showOverlays.caption : StrCast(this.props.Document.showCaption); - let templates = Cast(this.props.Document.templates, listSpec("string")); + let showOverlays = this.props.showOverlays ? this.props.showOverlays(this.layoutDoc) : undefined; + let showTitle = showOverlays && showOverlays.title !== "undefined" ? showOverlays.title : StrCast(this.layoutDoc.showTitle); + let showCaption = showOverlays && showOverlays.caption !== "undefined" ? showOverlays.caption : StrCast(this.layoutDoc.showCaption); + let templates = Cast(this.layoutDoc.templates, listSpec("string")); if (!showOverlays && templates instanceof List) { templates.map(str => { if (str.indexOf("{props.Document.title}") !== -1) showTitle = "title"; if (str.indexOf("fieldKey={\"caption\"}") !== -1) showCaption = "caption"; }); } - let showTextTitle = showTitle && StrCast(this.props.Document.layout).startsWith("(Docu transformOrigin: "top left", transform: `scale(${1 / this.props.ContentScaling()})` }}> StrCast(this.props.Document[showTitle!])} - SetValue={(value: string) => (Doc.GetProto(this.props.Document)[showTitle!] = value) ? true : true} + GetValue={() => StrCast(this.layoutDoc[showTitle!])} + SetValue={(value: string) => (Doc.GetProto(this.layoutDoc)[showTitle!] = value) ? true : true} />
} -- cgit v1.2.3-70-g09d2 From 5b70c7f5562821231665c4058d788bbf3b41ff04 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Fri, 26 Jul 2019 17:46:11 -0400 Subject: Changed render depth for overlay and background layouts --- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 6500b3273..c711b5204 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -400,7 +400,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { removeDocument: this.props.removeDocument, moveDocument: this.props.moveDocument, ScreenToLocalTransform: this.getTransform, - renderDepth: this.props.renderDepth + 1, + renderDepth: this.props.renderDepth, selectOnLoad: layoutDoc[Id] === this._selectOnLoaded, PanelWidth: layoutDoc[WidthSym], PanelHeight: layoutDoc[HeightSym], diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 6541007d0..c691754ea 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -248,7 +248,7 @@ export class ImageBox extends DocComponent(ImageD return url.href; } let ext = path.extname(url.href); - const suffix = this.props.renderDepth <= 1 ? "_o" : this._curSuffix; + const suffix = this.props.renderDepth < 1 ? "_o" : this._curSuffix; return url.href.replace(ext, suffix + ext); } -- 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') 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 4c8d0e0cf2422bffe26fcddd91eca9e8f3145e1a Mon Sep 17 00:00:00 2001 From: Fawn Date: Fri, 26 Jul 2019 18:08:26 -0400 Subject: collection cannot be moved to inside itself in schema --- src/client/views/collections/CollectionSchemaMovableTableHOC.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index f45575143..0ddd56180 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -11,6 +11,7 @@ import { action } from "mobx"; import { library } from '@fortawesome/fontawesome-svg-core'; import { faGripVertical, faTrash } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { DocumentManager } from "../../util/DocumentManager"; library.add(faGripVertical, faTrash); @@ -183,6 +184,14 @@ export class MovableRow extends React.Component { @action move: DragManager.MoveFunction = (doc: Doc, target: Doc, addDoc) => { + let targetView = DocumentManager.Instance.getDocumentView(target); + if (targetView) { + let targetContainingColl = targetView.props.ContainingCollectionView; //.props.ContainingCollectionView.props.Document; + if (targetContainingColl) { + let targetContCollDoc = targetContainingColl.props.Document; + return doc !== target && doc !== targetContCollDoc && this.props.removeDoc(doc) && addDoc(doc); + } + } return doc !== target && this.props.removeDoc(doc) && addDoc(doc); } -- cgit v1.2.3-70-g09d2 From a53d76d28750b03744727f2646313bccb120dbcb Mon Sep 17 00:00:00 2001 From: Fawn Date: Fri, 26 Jul 2019 19:13:39 -0400 Subject: moved schema toolbar into collection chrome --- .../views/collections/CollectionViewChromes.tsx | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 1ad9e47ce..de1d01ef0 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -16,6 +16,7 @@ import KeyRestrictionRow from "./KeyRestrictionRow"; import { CompileScript } from "../../util/Scripting"; import { ScriptField } from "../../../new_fields/ScriptField"; import { CollectionSchemaView } from "./CollectionSchemaView"; +import { COLLECTION_BORDER_WIDTH } from "../globalCssVariables.scss"; const datepicker = require('js-datepicker'); interface CollectionViewChromeProps { @@ -346,16 +347,26 @@ export class CollectionStackingViewChrome extends React.Component { +export class CollectionSchemaViewChrome extends React.Component { + + togglePreview = () => { + let dividerWidth = 4; + let borderWidth = Number(COLLECTION_BORDER_WIDTH); + let panelWidth = this.props.CollectionView.props.PanelWidth(); + let previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth); + let tableWidth = panelWidth - 2 * borderWidth - dividerWidth - previewWidth; + this.props.CollectionView.props.Document.schemaPreviewWidth = previewWidth === 0 ? Math.min(tableWidth / 3, 200) : 0; + + } + + render() { + let previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth); return (
- {this.props.toolbar} +
Show Preview
); } -- 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') 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') 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 {
)}
  • -
  • diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 5d61aefc7..790c312fa 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -13,7 +13,7 @@ import { SelectionManager } from "../../../util/SelectionManager"; import { Transform } from "../../../util/Transform"; import { undoBatch, UndoManager } from "../../../util/UndoManager"; import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss"; -import { ContextMenu } from "../../ContextMenu"; +import { SubmenuProps, ContextMenuProps } from "../../ContextMenuItem"; import { InkingCanvas } from "../../InkingCanvas"; import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView"; import { DocumentContentsView } from "../../nodes/DocumentContentsView"; @@ -34,11 +34,12 @@ import { CompileScript } from "../../../util/Scripting"; import { CognitiveServices } from "../../../cognitive_services/CognitiveServices"; import { library } from "@fortawesome/fontawesome-svg-core"; import { faEye } from "@fortawesome/free-regular-svg-icons"; -import { faTable, faPaintBrush, faAsterisk, faExpandArrowsAlt, faCompressArrowsAlt } from "@fortawesome/free-solid-svg-icons"; +import { faTable, faPaintBrush, faAsterisk, faExpandArrowsAlt, faCompressArrowsAlt, faCompass } from "@fortawesome/free-solid-svg-icons"; import { undo } from "prosemirror-history"; import { number } from "prop-types"; +import { ContextMenu } from "../../ContextMenu"; -library.add(faEye, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt); +library.add(faEye, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass); export const panZoomSchema = createSchema({ panX: "number", @@ -498,12 +499,13 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } onContextMenu = () => { - ContextMenu.Instance.addItem({ + let layoutItems: ContextMenuProps[] = []; + layoutItems.push({ description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`, event: undoBatch(async () => this.props.Document.fitToBox = !this.fitToBox), icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" }); - ContextMenu.Instance.addItem({ + layoutItems.push({ description: "Arrange contents in grid", icon: "table", event: async () => { @@ -530,6 +532,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { }, "arrange contents"); } }); + ContextMenu.Instance.addItem({ description: "Layout...", subitems: layoutItems, icon: "compass" }); ContextMenu.Instance.addItem({ description: "Analyze Strokes", event: async () => { let data = Cast(this.fieldExtensionDoc[this.inkKey], InkField); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index da72f212c..392faf3e9 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -61,8 +61,7 @@ library.add(fa.faCrosshairs); library.add(fa.faDesktop); library.add(fa.faUnlock); library.add(fa.faLock); -library.add(fa.faLaptopCode, fa.faMale, fa.faCopy, faHandPointRight); - +library.add(fa.faLaptopCode, fa.faMale, fa.faCopy, fa.faHandPointRight, fa.faCompass, fa.faSnowflake); // const linkSchema = createSchema({ // title: "string", @@ -547,7 +546,7 @@ export class DocumentView extends DocComponent(Docu subitems.push({ description: "Open Right Alias", event: () => this.props.addDocTab && this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.dataDoc, "onRight"), icon: "caret-square-right" }); 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: BoolCast(this.props.Document.ignoreAspect, false) || !this.props.Document.nativeWidth || !this.props.Document.nativeHeight ? "Freeze" : "Unfreeze", event: this.freezeNativeDimensions, icon: "snowflake" }); 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[] = []; @@ -575,8 +574,11 @@ export class DocumentView extends DocComponent(Docu cm.addItem({ description: "Toggle detail", event: () => Doc.ToggleDetailLayout(this.props.Document), icon: "image" }); } 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: "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" }); + let existing = ContextMenu.Instance.findByDescription("Layout..."); + let layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : []; + layoutItems.push({ description: "Center View", event: () => this.props.focus(this.props.Document, false), icon: "crosshairs" }); + layoutItems.push({ description: "Zoom to Document", event: () => this.props.focus(this.props.Document, true), icon: "search" }); + !existing && cm.addItem({ description: "Layout...", subitems: layoutItems, icon: "compass" }); if (!ClientUtils.RELEASE) { let copies: ContextMenuProps[] = []; copies.push({ description: "Copy URL", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "link" }); -- cgit v1.2.3-70-g09d2 From 7cc90b9f84e1cd21d371364b402d3e60fdc8d67b Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sat, 27 Jul 2019 10:49:16 -0400 Subject: margin tweak --- src/client/views/ContextMenuItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 097cb2c12..badb9cf19 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -94,7 +94,7 @@ export class ContextMenuItem extends React.Component {this.props.description} - +
    {submenu}
    -- cgit v1.2.3-70-g09d2 From 3afca3819bf5ea4975f9cfeee5e4be86968f42b8 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sat, 27 Jul 2019 10:55:48 -0400 Subject: added border --- src/client/views/ContextMenu.scss | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index e39b1034a..a8a866c2f 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -9,6 +9,7 @@ background: whitesmoke; padding-bottom: 10px; border-radius: 15px; + border: solid #BBBBBBBB 1px; } // .contextMenu-item:first-child { -- cgit v1.2.3-70-g09d2 From c360dc0adb468ae3aaa1c2d943606993d01a5a52 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 27 Jul 2019 11:08:44 -0400 Subject: fixed handling of keyboard events to avoid triggering global key events. made BoolCast default to false. fixed templating to deal with conflict between field fields and template fields --- src/client/util/DocumentManager.ts | 16 +++++++-------- src/client/views/EditableView.tsx | 3 +++ src/client/views/MainView.tsx | 1 - src/client/views/MetadataEntryMenu.tsx | 1 + .../views/collections/CollectionSchemaView.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 3 ++- .../CollectionFreeFormLinkView.tsx | 8 ++++---- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 8 ++++---- src/client/views/nodes/FormattedTextBox.tsx | 4 ++-- src/client/views/nodes/IconBox.tsx | 2 +- src/client/views/nodes/KeyValueBox.tsx | 3 ++- src/client/views/nodes/LinkMenuItem.tsx | 2 +- src/client/views/pdf/Page.tsx | 22 ++++++++------------ .../views/presentationview/PresentationElement.tsx | 24 ++++++++++------------ .../views/presentationview/PresentationView.tsx | 2 +- src/new_fields/Doc.ts | 19 +++++++++-------- src/new_fields/Types.ts | 2 +- 18 files changed, 62 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 262194a40..32f728c71 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,16 +1,14 @@ -import { computed, observable, action } from 'mobx'; -import { DocumentView } from '../views/nodes/DocumentView'; -import { Doc, DocListCast, Opt } from '../../new_fields/Doc'; -import { FieldValue, Cast, NumCast, BoolCast, StrCast } from '../../new_fields/Types'; -import { listSpec } from '../../new_fields/Schema'; -import { undoBatch, UndoManager } from './UndoManager'; +import { action, computed, observable } from 'mobx'; +import { Doc } from '../../new_fields/Doc'; +import { Id } from '../../new_fields/FieldSymbols'; +import { BoolCast, Cast, NumCast } from '../../new_fields/Types'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; -import { CollectionView } from '../views/collections/CollectionView'; import { CollectionPDFView } from '../views/collections/CollectionPDFView'; import { CollectionVideoView } from '../views/collections/CollectionVideoView'; -import { Id } from '../../new_fields/FieldSymbols'; +import { CollectionView } from '../views/collections/CollectionView'; +import { DocumentView } from '../views/nodes/DocumentView'; import { LinkManager } from './LinkManager'; -import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; +import { undoBatch, UndoManager } from './UndoManager'; export class DocumentManager { diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index c66a92f48..7cabebddd 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -50,8 +50,10 @@ export class EditableView extends React.Component { @action onKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Tab") { + e.stopPropagation(); this.props.OnTab && this.props.OnTab(); } else if (e.key === "Enter") { + e.stopPropagation(); if (!e.ctrlKey) { if (this.props.SetValue(e.currentTarget.value, e.shiftKey)) { this._editing = false; @@ -61,6 +63,7 @@ export class EditableView extends React.Component { this._editing = false; } } else if (e.key === "Escape") { + e.stopPropagation(); this._editing = false; } } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index bfb50bc75..8b7eb8856 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -7,7 +7,6 @@ import "normalize.css"; import * as React from 'react'; import { SketchPicker } from 'react-color'; import Measure from 'react-measure'; -import * as request from 'request'; import { Doc, DocListCast, Opt, HeightSym } from '../../new_fields/Doc'; import { Id } from '../../new_fields/FieldSymbols'; import { InkTool } from '../../new_fields/InkField'; diff --git a/src/client/views/MetadataEntryMenu.tsx b/src/client/views/MetadataEntryMenu.tsx index bd5a307b3..c50e02f0d 100644 --- a/src/client/views/MetadataEntryMenu.tsx +++ b/src/client/views/MetadataEntryMenu.tsx @@ -76,6 +76,7 @@ export class MetadataEntryMenu extends React.Component{ onValueKeyDown = async (e: React.KeyboardEvent) => { if (e.key === "Enter") { + e.stopPropagation(); const script = KeyValueBox.CompileKVPScript(this._currentValue); if (!script) return; let doc = this.props.docs; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 8ce3b40e5..0f67c47aa 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -11,7 +11,7 @@ import { Doc, DocListCast, DocListCastAsync, Field } from "../../../new_fields/D 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 { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; import { Docs } from "../../documents/Documents"; import { Gateway } from "../../northstar/manager/Gateway"; import { SetupDrag, DragManager } from "../../util/DragManager"; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 3da13bff5..d5a7b90da 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -53,7 +53,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let xhgt = height + this.getDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap); return xhgt; }, this.yMargin); - this.layoutDoc.height = hgt * (this.props as any).ContentScaling(); + (this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc) + .height = hgt * (this.props as any).ContentScaling(); } }, { fireImmediately: true }); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index b546d1b78..6af87b138 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -21,10 +21,10 @@ export class CollectionFreeFormLinkView extends React.Component { // let width = l[WidthSym](); // l.x = (x1 + x2) / 2 - width / 2; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index f83d02271..eaad43c10 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -471,7 +471,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { if (!(doc instanceof Doc)) return prev; var page = NumCast(doc.page, -1); if ((Math.abs(Math.round(page) - Math.round(curPage)) < 3) || page === -1) { - let minim = BoolCast(doc.isMinimized, false); + let minim = BoolCast(doc.isMinimized); if (minim === undefined || !minim) { const pos = script ? this.getCalculatedPositions(script, { doc, index: prev.length, collection: this.Document, docs, state }) : {}; state = pos.state === undefined ? state : pos.state; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 3152d6a2a..bc2af2ae8 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -275,7 +275,7 @@ export class DocumentView extends DocComponent(Docu let iconAnimating = Cast(maximizedDoc.isIconAnimating, List); if (!iconAnimating || (Date.now() - iconAnimating[2] > 1000)) { if (isMinimized === undefined) { - isMinimized = BoolCast(maximizedDoc.isMinimized, false); + isMinimized = BoolCast(maximizedDoc.isMinimized); } maximizedDoc.willMaximize = isMinimized; maximizedDoc.isMinimized = false; @@ -308,7 +308,7 @@ export class DocumentView extends DocComponent(Docu Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { SelectionManager.SelectDoc(this, e.ctrlKey); let isExpander = (e.target as any).id === "isExpander"; - if (BoolCast(this.props.Document.isButton, false) || isExpander) { + if (BoolCast(this.props.Document.isButton) || isExpander) { SelectionManager.DeselectAll(); let subBulletDocs = await DocListCastAsync(this.props.Document.subBulletDocs); let maximizedDocs = await DocListCastAsync(this.props.Document.maximizedDocs); @@ -326,7 +326,7 @@ export class DocumentView extends DocComponent(Docu maxLocation = this.props.Document.maximizeLocation = (ctrlKey ? maxLocation : (maxLocation === "inPlace" || !maxLocation ? "inTab" : "inPlace")); if (!maxLocation || maxLocation === "inPlace") { let hadView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView); - let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !BoolCast(d.IsMinimized, false), false); + let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !BoolCast(d.IsMinimized), false); expandedDocs.forEach(maxDoc => Doc.GetProto(maxDoc).isMinimized = false); let hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView); if (!hasView) { @@ -409,7 +409,7 @@ export class DocumentView extends DocComponent(Docu @undoBatch makeBtnClicked = (): void => { let doc = Doc.GetProto(this.props.Document); - doc.isButton = !BoolCast(doc.isButton, false); + doc.isButton = !BoolCast(doc.isButton); if (doc.isButton) { if (!doc.nativeWidth) { doc.nativeWidth = this.props.Document[WidthSym](); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 0a79677e2..bd0fd8301 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -459,8 +459,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe specificContextMenu = (e: React.MouseEvent): void => { let subitems: ContextMenuProps[] = []; subitems.push({ - 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" + description: BoolCast(this.props.Document.autoHeight) ? "Manual Height" : "Auto Height", + event: action(() => Doc.GetProto(this.props.Document).autoHeight = !BoolCast(this.props.Document.autoHeight)), icon: "expand-arrows-alt" }); ContextMenu.Instance.addItem({ description: "Text Funcs...", subitems: subitems }); } diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx index d6ab2a34a..6f50033a4 100644 --- a/src/client/views/nodes/IconBox.tsx +++ b/src/client/views/nodes/IconBox.tsx @@ -64,7 +64,7 @@ export class IconBox extends React.Component { let hideLabel = BoolCast(this.props.Document.hideLabel); let maxDocs = DocListCast(this.props.Document.maximizedDocs); let firstDoc = maxDocs.length ? maxDocs[0] : undefined; - let label = hideLabel ? "" : (firstDoc && labelField && !BoolCast(this.props.Document.useOwnTitle, false) ? firstDoc[labelField] : this.props.Document.title); + let label = hideLabel ? "" : (firstDoc && labelField && !BoolCast(this.props.Document.useOwnTitle) ? firstDoc[labelField] : this.props.Document.title); return (
    {this.minimizedIcon} diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 9fc0f2080..77824b4ff 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -46,6 +46,7 @@ export class KeyValueBox extends React.Component { @action onEnterKey = (e: React.KeyboardEvent): void => { if (e.key === 'Enter') { + e.stopPropagation(); if (this._keyInput && this._valueInput && this.fieldDocToLayout) { if (KeyValueBox.SetField(this.fieldDocToLayout, this._keyInput, this._valueInput)) { this._keyInput = ""; @@ -153,7 +154,7 @@ export class KeyValueBox extends React.Component { - + ) diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx index a0c37a719..d4c92c9f2 100644 --- a/src/client/views/nodes/LinkMenuItem.tsx +++ b/src/client/views/nodes/LinkMenuItem.tsx @@ -7,7 +7,7 @@ import { undoBatch } from "../../util/UndoManager"; import './LinkMenu.scss'; import React = require("react"); import { Doc } from '../../../new_fields/Doc'; -import { StrCast, Cast, BoolCast, FieldValue, NumCast } from '../../../new_fields/Types'; +import { StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types'; import { observable, action } from 'mobx'; import { LinkManager } from '../../util/LinkManager'; import { DragLinkAsDocument } from '../../util/DragManager'; diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx index c9d442fe5..a6864e0f3 100644 --- a/src/client/views/pdf/Page.tsx +++ b/src/client/views/pdf/Page.tsx @@ -1,22 +1,18 @@ +import { action, IReactionDisposer, observable } from "mobx"; import { observer } from "mobx-react"; -import React = require("react"); -import { observable, action, runInAction, IReactionDisposer, reaction } from "mobx"; import * as Pdfjs from "pdfjs-dist"; -import { Opt, Doc, FieldResult, Field, DocListCast, WidthSym, HeightSym, DocListCastAsync } from "../../../new_fields/Doc"; -import "./PDFViewer.scss"; import "pdfjs-dist/web/pdf_viewer.css"; -import { PDFBox } from "../nodes/PDFBox"; -import { DragManager } from "../../util/DragManager"; -import { Docs, DocUtils } from "../../documents/Documents"; +import { Doc, DocListCastAsync, Opt, WidthSym } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; -import { emptyFunction } from "../../../Utils"; -import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types"; import { listSpec } from "../../../new_fields/Schema"; -import { menuBar } from "prosemirror-menu"; -import { AnnotationTypes, PDFViewer, scale } from "./PDFViewer"; +import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; +import { Docs, DocUtils } from "../../documents/Documents"; +import { DragManager } from "../../util/DragManager"; +import { PDFBox } from "../nodes/PDFBox"; import PDFMenu from "./PDFMenu"; -import { UndoManager } from "../../util/UndoManager"; -import { copy } from "typescript-collections/dist/lib/arrays"; +import { scale } from "./PDFViewer"; +import "./PDFViewer.scss"; +import React = require("react"); interface IPageProps { diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 329630875..36f1178f1 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -1,21 +1,19 @@ -import { observer } from "mobx-react"; -import React = require("react"); -import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; -import { NumCast, BoolCast, StrCast, Cast } from "../../../new_fields/Types"; -import { Id } from "../../../new_fields/FieldSymbols"; -import { observable, action, computed, runInAction } from "mobx"; -import "./PresentationView.scss"; -import { Utils } from "../../../Utils"; import { library } from '@fortawesome/fontawesome-svg-core'; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faFile as fileSolid, faFileDownload, faLocationArrow, faArrowUp, faSearch } from '@fortawesome/free-solid-svg-icons'; import { faFile as fileRegular } from '@fortawesome/free-regular-svg-icons'; +import { faArrowUp, faFile as fileSolid, faFileDownload, faLocationArrow, faSearch } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { action, computed, observable, runInAction } from "mobx"; +import { observer } from "mobx-react"; +import { Doc } from "../../../new_fields/Doc"; +import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; -import { DragManager, SetupDrag, dropActionType } from "../../util/DragManager"; +import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types"; +import { Utils } from "../../../Utils"; +import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager"; import { SelectionManager } from "../../util/SelectionManager"; -import { indexOf } from "typescript-collections/dist/lib/arrays"; -import { map } from "bluebird"; +import "./PresentationView.scss"; +import React = require("react"); library.add(faArrowUp); library.add(fileSolid); diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index f2fef7f16..e25725275 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -171,7 +171,7 @@ export class PresentationView extends React.Component { //storing the presentation status,ie. whether it was stopped or playing - let presStatusBackUp = BoolCast(this.curPresentation.presStatus, null); + let presStatusBackUp = BoolCast(this.curPresentation.presStatus); runInAction(() => this.presStatus = presStatusBackUp); } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index dbb0dc505..b5708e97b 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -455,7 +455,7 @@ export namespace Doc { return otherdoc; } - export function MakeTemplate(fieldTemplate: Doc, metaKey: string, proto: Doc) { + export function MakeTemplate(fieldTemplate: Doc, metaKey: string, templateDataDoc: Doc) { // move data doc fields to layout doc as needed (nativeWidth/nativeHeight, data, ??) let backgroundLayout = StrCast(fieldTemplate.backgroundLayout); let fieldLayoutDoc = fieldTemplate; @@ -466,21 +466,24 @@ export namespace Doc { if (backgroundLayout) { backgroundLayout = backgroundLayout.replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metaKey}"}`); } - let nw = Cast(fieldTemplate.nativeWidth, "number"); - let nh = Cast(fieldTemplate.nativeHeight, "number"); let layoutDelegate = fieldTemplate.layout instanceof Doc ? fieldLayoutDoc : fieldTemplate; layoutDelegate.layout = layout; - fieldTemplate.title = metaKey; fieldTemplate.templateField = metaKey; + fieldTemplate.title = metaKey; + fieldTemplate.isTemplate = true; fieldTemplate.layout = layoutDelegate !== fieldTemplate ? layoutDelegate : layout; fieldTemplate.backgroundLayout = backgroundLayout; - fieldTemplate.nativeWidth = nw; - fieldTemplate.nativeHeight = nh; - fieldTemplate.isTemplate = true; + /* move certain layout properties from the original data doc to the template layout to avoid + inheriting them from the template's data doc which may also define these fields for its own use. + */ + fieldTemplate.ignoreAspect = BoolCast(fieldTemplate.ignoreAspect); + fieldTemplate.singleColumn = BoolCast(fieldTemplate.singleColumn); + fieldTemplate.nativeWidth = Cast(fieldTemplate.nativeWidth, "number"); + fieldTemplate.nativeHeight = Cast(fieldTemplate.nativeHeight, "number"); fieldTemplate.showTitle = "title"; - setTimeout(() => fieldTemplate.proto = proto); + setTimeout(() => fieldTemplate.proto = templateDataDoc); } export async function ToggleDetailLayout(d: Doc) { diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts index f8a4a30b4..565ae2ee3 100644 --- a/src/new_fields/Types.ts +++ b/src/new_fields/Types.ts @@ -78,7 +78,7 @@ export function StrCast(field: FieldResult, defaultVal: string | null = "") { return Cast(field, "string", defaultVal); } -export function BoolCast(field: FieldResult, defaultVal: boolean | null = null) { +export function BoolCast(field: FieldResult, defaultVal: boolean | null = false) { return Cast(field, "boolean", defaultVal); } export function DateCast(field: FieldResult) { -- cgit v1.2.3-70-g09d2 From 9e32981434b5a47e0002c304b511f4f2435c46a1 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sat, 27 Jul 2019 11:16:56 -0400 Subject: final menufix --- src/client/views/ContextMenu.scss | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index a8a866c2f..e2c0de8af 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -33,6 +33,10 @@ box-shadow: #AAAAAA .2vw .2vw .4vw; flex-direction: column; border: 1px solid #BBBBBBBB; + border-radius: 15px; + padding-top: 10px; + padding-bottom: 10px; + background: whitesmoke; } .contextMenu-item { -- cgit v1.2.3-70-g09d2 From 0d32cf945d610898d9ff993b5b7e9775e84da68d Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 27 Jul 2019 12:29:46 -0400 Subject: added ctrl drop on images to set template. fixed stacking view autoHeight computation --- src/client/views/collections/CollectionStackingView.tsx | 4 ++-- src/client/views/nodes/ImageBox.tsx | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index d5a7b90da..dab03f052 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -50,8 +50,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { () => { if (this.singleColumn && BoolCast(this.props.Document.autoHeight)) { let hgt = this.Sections.size * 50 + this.filteredChildren.reduce((height, d, i) => { - let xhgt = height + this.getDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap); - return xhgt; + let pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d); + return height + this.getDocHeight(pair.layout) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap); }, this.yMargin); (this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc) .height = hgt * (this.props as any).ContentScaling(); diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index a36885616..7e0d57e23 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -21,7 +21,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import "./ImageBox.scss"; import React = require("react"); import { RouteStore } from '../../../server/RouteStore'; -import { Docs } from '../../documents/Documents'; +import { Docs, DocumentType } from '../../documents/Documents'; import { DocServer } from '../../DocServer'; import { Font } from '@react-pdf/renderer'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -85,10 +85,20 @@ export class ImageBox extends DocComponent(ImageD @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(this.dataDoc, this.props.fieldKey, "Alternates"); } @undoBatch + @action drop = (e: Event, de: DragManager.DropEvent) => { if (de.data instanceof DragManager.DocumentDragData) { de.data.droppedDocuments.forEach(action((drop: Doc) => { - if (de.mods === "AltKey" && /*this.dataDoc !== this.props.Document &&*/ drop.data instanceof ImageField) { + if (de.mods === "CtrlKey") { + let temp = Doc.MakeDelegate(drop); + this.props.Document.nativeWidth = Doc.GetProto(this.props.Document).nativeWidth = undefined; + this.props.Document.nativeHeight = Doc.GetProto(this.props.Document).nativeHeight = undefined; + this.props.Document.width = drop.width; + this.props.Document.height = drop.height; + Doc.GetProto(this.props.Document).type = DocumentType.TEMPLATE; + this.props.Document.layout = temp; + e.stopPropagation(); + } else if (de.mods === "AltKey" && /*this.dataDoc !== this.props.Document &&*/ drop.data instanceof ImageField) { Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new ImageField(drop.data.url); e.stopPropagation(); } else if (de.mods === "CtrlKey") { -- cgit v1.2.3-70-g09d2 From 18508ce86517b798e8eff2696dfe1a832837b442 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 27 Jul 2019 14:38:04 -0400 Subject: Made scripting repl work better with anonymous functions --- src/client/views/ScriptingRepl.tsx | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/ScriptingRepl.tsx b/src/client/views/ScriptingRepl.tsx index 9e538cf1b..0cff145b6 100644 --- a/src/client/views/ScriptingRepl.tsx +++ b/src/client/views/ScriptingRepl.tsx @@ -95,6 +95,7 @@ export class ScriptingValueDisplay extends React.Component<{ scrollToBottom: () @observer export class ScriptingRepl extends React.Component { @observable private commands: { command: string, result: any }[] = []; + private commandsHistory: string[] = []; @observable private commandString: string = ""; private commandBuffer: string = ""; @@ -113,12 +114,21 @@ export class ScriptingRepl extends React.Component { Scripting.getGlobals().forEach(global => knownVars[global] = 1); return root => { function visit(node: ts.Node) { + let skip = false; + if (ts.isIdentifier(node)) { + if (ts.isParameter(node.parent)) { + skip = true; + knownVars[node.text] = 1; + } + } 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)) { + if (ts.isParameter(node.parent)) { + // delete knownVars[node.text]; + } else 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]); @@ -147,13 +157,16 @@ export class ScriptingRepl extends React.Component { const globals = Scripting.makeMutableGlobalsCopy(docGlobals); const script = CompileScript(this.commandString, { typecheck: false, addReturn: true, editable: true, params: { args: "any" }, transformer: this.getTransformer(), globals }); if (!script.compiled) { + this.commands.push({ command: this.commandString, result: script.errors }); return; } const result = script.run({ args: this.args }); if (!result.success) { + this.commands.push({ command: this.commandString, result: result.error.toString() }); return; } this.commands.push({ command: this.commandString, result: result.result }); + this.commandsHistory.push(this.commandString); this.maybeScrollToBottom(); @@ -168,7 +181,7 @@ export class ScriptingRepl extends React.Component { if (this.historyIndex === 0) { this.commandBuffer = this.commandString; } - this.commandString = this.commands[this.commands.length - 1 - this.historyIndex].command; + this.commandString = this.commandsHistory[this.commands.length - 1 - this.historyIndex]; } break; } @@ -179,7 +192,7 @@ export class ScriptingRepl extends React.Component { this.commandString = this.commandBuffer; this.commandBuffer = ""; } else { - this.commandString = this.commands[this.commands.length - 1 - this.historyIndex].command; + this.commandString = this.commandsHistory[this.commands.length - 1 - this.historyIndex]; } } break; -- cgit v1.2.3-70-g09d2 From c1377587f27044d89ec84befa9953de627d49873 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 27 Jul 2019 14:38:53 -0400 Subject: Fixed up buxton scraper to get fullscreen images and remove bad images --- src/scraping/buxton/scraper.py | 3 +++ .../buxton/source/Bill_Notes_Bill_Notes_CyKey.docx | Bin 1675500 -> 1561425 bytes .../buxton/source/Bill_Notes_Braun_T3.docx | Bin 1671968 -> 1510917 bytes .../buxton/source/Bill_Notes_CasioC801.docx | Bin 574664 -> 413861 bytes .../buxton/source/Bill_Notes_Casio_Mini.docx | Bin 581069 -> 467304 bytes .../source/Bill_Notes_FingerWorks_Prototype.docx | Bin 585090 -> 423384 bytes .../source/Bill_Notes_Fingerworks_TouchStream.docx | Bin 1722555 -> 1558473 bytes src/scraping/buxton/source/Bill_Notes_FrogPad.docx | Bin 840173 -> 679241 bytes .../buxton/source/Bill_Notes_Gavilan_SC.docx | Bin 1695290 -> 1531689 bytes .../source/Bill_Notes_Grandjean_Stenotype.docx | Bin 2094142 -> 1933004 bytes src/scraping/buxton/source/Bill_Notes_Matias.docx | Bin 590407 -> 476141 bytes .../buxton/source/Bill_Notes_MousePen.docx | Bin 505322 -> 344083 bytes src/scraping/buxton/source/Bill_Notes_NewO.docx | Bin 2264571 -> 2150143 bytes src/scraping/buxton/source/Bill_Notes_OLPC.docx | Bin 6883659 -> 6721592 bytes src/scraping/buxton/source/Bill_Notes_PARCkbd.docx | Bin 631959 -> 517484 bytes .../source/Bill_Notes_Philco_Mystery_Control.docx | Bin 1994439 -> 1880816 bytes .../buxton/source/Bill_Notes_TASA_Kbd.docx | Bin 461199 -> 347612 bytes src/scraping/buxton/source/Bill_Notes_The_Tap.docx | Bin 711321 -> 597382 bytes 18 files changed, 3 insertions(+) (limited to 'src') diff --git a/src/scraping/buxton/scraper.py b/src/scraping/buxton/scraper.py index 48b8fe3fa..182b22a1a 100644 --- a/src/scraping/buxton/scraper.py +++ b/src/scraping/buxton/scraper.py @@ -1,4 +1,5 @@ import os +from shutil import copyfile import docx2txt from docx import Document from docx.opc.constants import RELATIONSHIP_TYPE as RT @@ -233,6 +234,8 @@ def parse_document(file_name: str): for image in os.listdir(dir_path): count += 1 view_guids.append(write_image(pure_name, image)) + copyfile(dir_path + "/" + image, dir_path + + "/" + image.replace(".", "_o.", 1)) os.rename(dir_path + "/" + image, dir_path + "/" + image.replace(".", "_m.", 1)) print(f"extracted {count} images...") diff --git a/src/scraping/buxton/source/Bill_Notes_Bill_Notes_CyKey.docx b/src/scraping/buxton/source/Bill_Notes_Bill_Notes_CyKey.docx index 06094b4d3..649d636e3 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_Bill_Notes_CyKey.docx and b/src/scraping/buxton/source/Bill_Notes_Bill_Notes_CyKey.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_Braun_T3.docx b/src/scraping/buxton/source/Bill_Notes_Braun_T3.docx index 356697092..b00080e08 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_Braun_T3.docx and b/src/scraping/buxton/source/Bill_Notes_Braun_T3.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_CasioC801.docx b/src/scraping/buxton/source/Bill_Notes_CasioC801.docx index cd89fb97b..510a006e0 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_CasioC801.docx and b/src/scraping/buxton/source/Bill_Notes_CasioC801.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_Casio_Mini.docx b/src/scraping/buxton/source/Bill_Notes_Casio_Mini.docx index a503cddfc..cea9e7b69 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_Casio_Mini.docx and b/src/scraping/buxton/source/Bill_Notes_Casio_Mini.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_FingerWorks_Prototype.docx b/src/scraping/buxton/source/Bill_Notes_FingerWorks_Prototype.docx index 4d13a8cf5..f53402a06 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_FingerWorks_Prototype.docx and b/src/scraping/buxton/source/Bill_Notes_FingerWorks_Prototype.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_Fingerworks_TouchStream.docx b/src/scraping/buxton/source/Bill_Notes_Fingerworks_TouchStream.docx index 578a1be08..0eec89949 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_Fingerworks_TouchStream.docx and b/src/scraping/buxton/source/Bill_Notes_Fingerworks_TouchStream.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_FrogPad.docx b/src/scraping/buxton/source/Bill_Notes_FrogPad.docx index d01e1bf5c..ba80c1959 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_FrogPad.docx and b/src/scraping/buxton/source/Bill_Notes_FrogPad.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_Gavilan_SC.docx b/src/scraping/buxton/source/Bill_Notes_Gavilan_SC.docx index 7bd28b376..8558a4e13 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_Gavilan_SC.docx and b/src/scraping/buxton/source/Bill_Notes_Gavilan_SC.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_Grandjean_Stenotype.docx b/src/scraping/buxton/source/Bill_Notes_Grandjean_Stenotype.docx index 0615c4953..09e17f971 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_Grandjean_Stenotype.docx and b/src/scraping/buxton/source/Bill_Notes_Grandjean_Stenotype.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_Matias.docx b/src/scraping/buxton/source/Bill_Notes_Matias.docx index 547603256..d2d014bbe 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_Matias.docx and b/src/scraping/buxton/source/Bill_Notes_Matias.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_MousePen.docx b/src/scraping/buxton/source/Bill_Notes_MousePen.docx index 4e1056636..cd0b3eab3 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_MousePen.docx and b/src/scraping/buxton/source/Bill_Notes_MousePen.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_NewO.docx b/src/scraping/buxton/source/Bill_Notes_NewO.docx index a514926d2..2f4a04e81 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_NewO.docx and b/src/scraping/buxton/source/Bill_Notes_NewO.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_OLPC.docx b/src/scraping/buxton/source/Bill_Notes_OLPC.docx index bfca0a9bb..7a636e2d6 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_OLPC.docx and b/src/scraping/buxton/source/Bill_Notes_OLPC.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_PARCkbd.docx b/src/scraping/buxton/source/Bill_Notes_PARCkbd.docx index c0cf6ba9a..3038de363 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_PARCkbd.docx and b/src/scraping/buxton/source/Bill_Notes_PARCkbd.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_Philco_Mystery_Control.docx b/src/scraping/buxton/source/Bill_Notes_Philco_Mystery_Control.docx index ad06903f3..af72fa662 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_Philco_Mystery_Control.docx and b/src/scraping/buxton/source/Bill_Notes_Philco_Mystery_Control.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_TASA_Kbd.docx b/src/scraping/buxton/source/Bill_Notes_TASA_Kbd.docx index e4c659de9..5c2eb8d7f 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_TASA_Kbd.docx and b/src/scraping/buxton/source/Bill_Notes_TASA_Kbd.docx differ diff --git a/src/scraping/buxton/source/Bill_Notes_The_Tap.docx b/src/scraping/buxton/source/Bill_Notes_The_Tap.docx index 8ceebc71e..c9ee2eaea 100644 Binary files a/src/scraping/buxton/source/Bill_Notes_The_Tap.docx and b/src/scraping/buxton/source/Bill_Notes_The_Tap.docx differ -- cgit v1.2.3-70-g09d2 From ccc10aab91f2b8d01a93277796ff0fbf603ff631 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 27 Jul 2019 14:50:21 -0400 Subject: Changed title display to try to use data doc first --- src/client/views/nodes/DocumentView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index bc2af2ae8..a7c285c1b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -695,7 +695,7 @@ export class DocumentView extends DocComponent(Docu transformOrigin: "top left", transform: `scale(${1 / this.props.ContentScaling()})` }}> Date: Sat, 27 Jul 2019 15:04:15 -0400 Subject: Added cors proxy to ImageBox --- src/client/views/nodes/ImageBox.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 4aee3f68c..2115024a1 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -30,7 +30,7 @@ import FaceRectangles from './FaceRectangles'; import { faEye } from '@fortawesome/free-regular-svg-icons'; var requestImageSize = require('../../util/request-image-size'); var path = require('path'); -const { Howl, Howler } = require('howler'); +const { Howl } = require('howler'); library.add(faImage, faEye, faPaintBrush); @@ -252,8 +252,12 @@ export class ImageBox extends DocComponent(ImageD choosePath(url: URL) { const lower = url.href.toLowerCase(); - if (url.protocol === "data" || url.href.indexOf(window.location.origin) === -1 || !(lower.endsWith(".png") || lower.endsWith(".jpg") || lower.endsWith(".jpeg"))) { + if (url.protocol === "data") { return url.href; + } else if (url.href.indexOf(window.location.origin) === -1) { + return Utils.CorsProxy(url.href); + } else if (!(lower.endsWith(".png") || lower.endsWith(".jpg") || lower.endsWith(".jpeg"))) { + return url.href;//Why is this here } let ext = path.extname(url.href); const suffix = this.props.renderDepth < 1 ? "_o" : this._curSuffix; -- cgit v1.2.3-70-g09d2 From 60aa214501f7932e5efee68fd878ef367fc2a31b Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 27 Jul 2019 16:18:24 -0400 Subject: switch Make Portal to act more like a prezi portal. added scale paramter to focus() --- .../collectionFreeForm/CollectionFreeFormView.tsx | 10 +++++----- src/client/views/nodes/DocumentView.tsx | 22 +++++++++++++++------- 2 files changed, 20 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index eaad43c10..cd071fb4d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -303,7 +303,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { doc.zIndex = docs.length + 1; } - focusDocument = (doc: Doc, willZoom: boolean) => { + focusDocument = (doc: Doc, willZoom: boolean, scale?: number) => { const panX = this.Document.panX; const panY = this.Document.panY; const id = this.Document[Id]; @@ -335,20 +335,20 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { this.props.Document.panTransformType = "Ease"; this.props.focus(this.props.Document); if (willZoom) { - this.setScaleToZoom(doc); + this.setScaleToZoom(doc, scale); } } - setScaleToZoom = (doc: Doc) => { + setScaleToZoom = (doc: Doc, scale: number = 0.5) => { let p = this.props; let PanelHeight = p.PanelHeight(); let panelWidth = p.PanelWidth(); let docHeight = NumCast(doc.height); let docWidth = NumCast(doc.width); - let targetHeight = 0.5 * PanelHeight; - let targetWidth = 0.5 * panelWidth; + let targetHeight = scale * PanelHeight; + let targetWidth = scale * panelWidth; let maxScaleX: number = targetWidth / docWidth; let maxScaleY: number = targetHeight / docHeight; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index bc2af2ae8..f60be0a6a 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -88,7 +88,7 @@ export interface DocumentViewProps { ContentScaling: () => number; PanelWidth: () => number; PanelHeight: () => number; - focus: (doc: Doc, willZoom: boolean) => void; + focus: (doc: Doc, willZoom: boolean, scale?: number) => void; selectOnLoad: boolean; parentActive: () => boolean; whenActiveChanged: (isActive: boolean) => void; @@ -359,7 +359,12 @@ export class DocumentView extends DocComponent(Docu if (!linkedFwdDocs.some(l => l instanceof Promise)) { let maxLocation = StrCast(linkedFwdDocs[0].maximizeLocation, "inTab"); let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined; - DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false, document => this.props.addDocTab(document, undefined, maxLocation), linkedFwdPage[altKey ? 1 : 0], targetContext); + DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false, document => { + this.props.focus(this.props.Document, true, 1); + setTimeout(() => + this.props.addDocTab(document, undefined, maxLocation), 1000); + } + , linkedFwdPage[altKey ? 1 : 0], targetContext); } } } @@ -554,12 +559,15 @@ export class DocumentView extends DocComponent(Docu cm.addItem({ 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]); + //Doc.GetProto(this.props.Document).subBulletDocs = new List([portal]); //summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight" - Doc.GetProto(this.props.Document).templates = new List([Templates.Bullet.Layout]); - let coll = Docs.Create.StackingDocument([this.props.Document, portal], { x: NumCast(this.props.Document.x), y: NumCast(this.props.Document.y), width: this.props.Document[WidthSym]() + 10, height: this.props.Document[HeightSym](), title: this.props.Document.title + ".cont" }); - this.props.addDocument && this.props.addDocument(coll); - this.props.removeDocument && this.props.removeDocument(this.props.Document); + //Doc.GetProto(this.props.Document).templates = new List([Templates.Bullet.Layout]); + //let coll = Docs.Create.StackingDocument([this.props.Document, portal], { x: NumCast(this.props.Document.x), y: NumCast(this.props.Document.y), width: this.props.Document[WidthSym]() + 10, height: this.props.Document[HeightSym](), title: this.props.Document.title + ".cont" }); + //this.props.addDocument && this.props.addDocument(coll); + //this.props.removeDocument && this.props.removeDocument(this.props.Document); + DocUtils.MakeLink(this.props.Document, portal, undefined, this.props.Document.title + ".portal"); + this.makeBtnClicked(); + }, icon: "window-restore" }); // cm.addItem({ -- cgit v1.2.3-70-g09d2 From d009df0c7142c04947193fb5670974017919bd05 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sat, 27 Jul 2019 16:38:55 -0400 Subject: undo for link dragging, image rotation and cognitive services --- src/client/cognitive_services/CognitiveServices.ts | 5 ++++ src/client/util/DragManager.ts | 2 ++ src/client/views/DocumentDecorations.tsx | 10 ++++++++ src/client/views/nodes/DocumentView.tsx | 1 + src/client/views/nodes/ImageBox.tsx | 29 +++++++++++----------- 5 files changed, 33 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts index d69378d0e..bbc438a9b 100644 --- a/src/client/cognitive_services/CognitiveServices.ts +++ b/src/client/cognitive_services/CognitiveServices.ts @@ -9,6 +9,7 @@ import { Utils } from "../../Utils"; import { CompileScript } from "../util/Scripting"; import { ComputedField } from "../../new_fields/ScriptField"; import { InkData } from "../../new_fields/InkField"; +import { undoBatch, UndoManager } from "../util/UndoManager"; type APIManager = { converter: BodyConverter, requester: RequestExecutor, analyzer: AnalysisApplier }; type RequestExecutor = (apiKey: string, body: string, service: Service) => Promise; @@ -103,6 +104,7 @@ export namespace CognitiveServices { }, analyzer: async (target: Doc, keys: string[], service: Service, converter: Converter) => { + let batch = UndoManager.StartBatch("Image Analysis"); let imageData = Cast(target.data, ImageField); let storageKey = keys[0]; if (!imageData || await Cast(target[storageKey], Doc)) { @@ -120,6 +122,7 @@ export namespace CognitiveServices { } } target[storageKey] = toStore; + batch.end(); } }; @@ -205,6 +208,7 @@ export namespace CognitiveServices { }, analyzer: async (target: Doc, keys: string[], inkData: InkData) => { + let batch = UndoManager.StartBatch("Ink Analysis"); let results = await executeQuery(Service.Handwriting, Manager, inkData); if (results) { results.recognitionUnits && (results = results.recognitionUnits); @@ -213,6 +217,7 @@ export namespace CognitiveServices { let individualWords = recognizedText.filter((text: string) => text && text.split(" ").length === 1); target[keys[1]] = individualWords.join(" "); } + batch.end(); } }; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 5271f2f5d..95416cd53 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -8,6 +8,7 @@ import * as globalCssVariables from "../views/globalCssVariables.scss"; import { DocumentManager } from "./DocumentManager"; import { LinkManager } from "./LinkManager"; import { SelectionManager } from "./SelectionManager"; +import { DocumentDecorations } from "../views/DocumentDecorations"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag( @@ -421,6 +422,7 @@ export namespace DragManager { if (options) { options.handlers.dragComplete({}); } + DocumentDecorations.Instance.endLinkDragBatch(); }; AbortDrag = () => { diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 255855b45..c4d958338 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -54,6 +54,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> private _downY = 0; private _iconDoc?: Doc = undefined; private _resizeUndo?: UndoManager.Batch; + private _linkDrag?: UndoManager.Batch; @observable private _minimizedX = 0; @observable private _minimizedY = 0; @observable private _title: string = ""; @@ -376,7 +377,16 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } } + endLinkDragBatch = () => { + if (!this._linkDrag) { + return; + } + this._linkDrag.end(); + this._linkDrag = undefined; + } + onLinkerButtonDown = (e: React.PointerEvent): void => { + this._linkDrag = UndoManager.StartBatch("Drag Link"); e.stopPropagation(); document.removeEventListener("pointermove", this.onLinkerButtonMoved); document.addEventListener("pointermove", this.onLinkerButtonMoved); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 392faf3e9..ebb2da506 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -40,6 +40,7 @@ import { ScriptingRepl } from '../ScriptingRepl'; import { ClientUtils } from '../../util/ClientUtils'; import { EditableView } from '../EditableView'; import { faHandPointer, faHandPointRight } from '@fortawesome/free-regular-svg-icons'; +import { DocumentDecorations } from '../DocumentDecorations'; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? library.add(fa.faTrash); diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index a36885616..bdb50bcf0 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -192,6 +192,20 @@ export class ImageBox extends DocComponent(ImageD }); } + @undoBatch + rotate = action(() => { + let proto = Doc.GetProto(this.props.Document); + let nw = this.props.Document.nativeWidth; + let nh = this.props.Document.nativeHeight; + let w = this.props.Document.width; + let h = this.props.Document.height; + proto.rotation = (NumCast(this.props.Document.rotation) + 90) % 360; + proto.nativeWidth = nh; + proto.nativeHeight = nw; + this.props.Document.width = h; + this.props.Document.height = w; + }); + specificContextMenu = (e: React.MouseEvent): void => { let field = Cast(this.Document[this.props.fieldKey], ImageField); if (field) { @@ -199,20 +213,7 @@ export class ImageBox extends DocComponent(ImageD let funcs: ContextMenuProps[] = []; funcs.push({ description: "Copy path", event: () => Utils.CopyText(url), icon: "expand-arrows-alt" }); funcs.push({ description: "Record 1sec audio", event: this.recordAudioAnnotation, icon: "expand-arrows-alt" }); - funcs.push({ - description: "Rotate", event: action(() => { - let proto = Doc.GetProto(this.props.Document); - let nw = this.props.Document.nativeWidth; - let nh = this.props.Document.nativeHeight; - let w = this.props.Document.width; - let h = this.props.Document.height; - proto.rotation = (NumCast(this.props.Document.rotation) + 90) % 360; - proto.nativeWidth = nh; - proto.nativeHeight = nw; - this.props.Document.width = h; - this.props.Document.height = w; - }), icon: "expand-arrows-alt" - }); + funcs.push({ description: "Rotate", event: this.rotate, icon: "expand-arrows-alt" }); let modes: ContextMenuProps[] = []; let dataDoc = Doc.GetProto(this.props.Document); -- cgit v1.2.3-70-g09d2 From d53ad748d90ca1c863a7ef52d0835573ce967a54 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sat, 27 Jul 2019 16:49:07 -0400 Subject: init --- src/client/util/TooltipTextMenu.tsx | 6 +++++- src/client/views/GlobalKeyHandler.ts | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 30 ++++++++++++++++++++++++++++- src/client/views/nodes/PDFBox.tsx | 14 ++++++++++++++ src/client/views/pdf/Page.tsx | 11 ++++++++--- 5 files changed, 57 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index a4c053de2..6214b568c 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -1,6 +1,6 @@ import { action } from "mobx"; import { Dropdown, MenuItem, icons, } from "prosemirror-menu"; //no import css -import { EditorState, NodeSelection, TextSelection } from "prosemirror-state"; +import { EditorState, NodeSelection, TextSelection, Transaction } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { schema } from "./RichTextSchema"; import { Schema, NodeType, MarkType, Mark, ResolvedPos } from "prosemirror-model"; @@ -321,6 +321,10 @@ export class TooltipTextMenu { } } + makeLinkWithState = (state: EditorState, target: string, location: string) => { + let link = state.schema.mark(state.schema.marks.link, { href: target, location: location }); + } + makeLink = (target: string, location: string) => { let node = this.view.state.selection.$from.nodeAfter; let link = this.view.state.schema.mark(this.view.state.schema.marks.link, { href: target, location: location }); diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 7477c5b4f..6c80c7645 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -151,9 +151,9 @@ export default class KeyManager { stopPropagation = false; break; case "a": - case "c": case "v": case "x": + case "c": stopPropagation = false; preventDefault = false; break; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 0a79677e2..cf913a4c7 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -6,7 +6,7 @@ import { baseKeymap } from "prosemirror-commands"; import { history } from "prosemirror-history"; import { keymap } from "prosemirror-keymap"; import { NodeType } from 'prosemirror-model'; -import { EditorState, Plugin, Transaction } from "prosemirror-state"; +import { EditorState, Plugin, Transaction, Selection } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { Doc, Opt } from "../../../new_fields/Doc"; import { Id, Copy } from '../../../new_fields/FieldSymbols'; @@ -123,12 +123,40 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (this.props.isOverlay) { DragManager.StartDragFunctions.push(() => FormattedTextBox.InputBoxOverlay = undefined); } + + document.addEventListener("paste", this.paste); } @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(this.dataDoc, this.props.fieldKey, "dummy"); } @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : Doc.GetProto(this.props.Document); } + paste = (e: ClipboardEvent) => { + if (e.clipboardData && this._editorView) { + let pdfPasteText = `${Utils.GenerateDeterministicGuid("pdf paste")}`; + for (let i = 0; i < e.clipboardData.items.length; i++) { + let item = e.clipboardData.items.item(i); + if (item.type === "text/plain") { + item.getAsString((text) => { + let pdfPasteIndex = text.indexOf(pdfPasteText); + if (pdfPasteIndex > -1) { + let insertText = text.substr(0, pdfPasteIndex); + const tx = this._editorView!.state.tr.insertText(insertText); + // tx.setSelection(new Selection(tx.)) + const state = this._editorView!.state; + this._editorView!.dispatch(tx); + if (this._toolTipTextMenu) { + // this._toolTipTextMenu.makeLinkWithState(state) + } + e.stopPropagation(); + e.preventDefault(); + } + }); + } + } + } + } + dispatchTransaction = (tx: Transaction) => { if (this._editorView) { const state = this._editorView.state.apply(tx); diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 5a5e6e6dd..282312dca 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -24,6 +24,8 @@ import { Flyout, anchorPoints } from '../DocumentDecorations'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { ScriptField } from '../../../new_fields/ScriptField'; import { KeyCodes } from '../../northstar/utils/KeyCodes'; +import { Utils } from '../../../Utils'; +import { Id } from '../../../new_fields/FieldSymbols'; type PdfDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>; const PdfDocument = makeInterface(positionSchema, pageSchema); @@ -32,6 +34,7 @@ export const handleBackspace = (e: React.KeyboardEvent) => { if (e.keyCode === K @observer export class PDFBox extends DocComponent(PdfDocument) { public static LayoutString() { return FieldView.LayoutString(PDFBox); } + public selectionText: string = ""; @observable private _alt = false; @observable private _scrollY: number = 0; @@ -63,6 +66,8 @@ export class PDFBox extends DocComponent(PdfDocumen this._keyRef = React.createRef(); this._valueRef = React.createRef(); this._scriptRef = React.createRef(); + + document.addEventListener("keydown", this.onKeyDown); } componentDidMount() { @@ -73,6 +78,14 @@ export class PDFBox extends DocComponent(PdfDocumen this._reactionDisposer && this._reactionDisposer(); } + onKeyDown = (e: KeyboardEvent) => { + if (e.ctrlKey && e.keyCode === KeyCodes.C) { + let text = this.selectionText; + text += `${Utils.GenerateDeterministicGuid("pdf paste")}/${this.props.Document[Id]}`; + navigator.clipboard.writeText(text); + } + } + public GetPage() { return Math.floor(NumCast(this.props.Document.scrollY) / NumCast(this.dataDoc.pdfHeight)) + 1; } @@ -241,6 +254,7 @@ export class PDFBox extends DocComponent(PdfDocumen let classname = "pdfBox-cont" + (this.props.active() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : ""); return (
    { else { let sel = window.getSelection(); if (sel && sel.type === "Range") { - this.createTextAnnotation(sel); + let selRange = sel.getRangeAt(0); + this.createTextAnnotation(sel, selRange); PDFMenu.Instance.jumpTo(e.clientX, e.clientY); } } @@ -375,8 +376,8 @@ export default class Page extends React.Component { } @action - createTextAnnotation = (sel: Selection) => { - let clientRects = sel.getRangeAt(0).getClientRects(); + createTextAnnotation = (sel: Selection, selRange: Range) => { + let clientRects = selRange.getClientRects(); if (this._textLayer.current) { let boundingRect = this._textLayer.current.getBoundingClientRect(); for (let i = 0; i < clientRects.length; i++) { @@ -393,6 +394,10 @@ export default class Page extends React.Component { } } } + let text = selRange.extractContents().textContent; + if (text) { + this.props.parent.selectionText = text; + } // clear selection if (sel.empty) { // Chrome sel.empty(); -- cgit v1.2.3-70-g09d2 From 905d77804bf9a810822e5e43f0cd06019aef7620 Mon Sep 17 00:00:00 2001 From: Fawn Date: Sat, 27 Jul 2019 17:03:20 -0400 Subject: schema headers changed to schemaheaderfields, a bug with udpating the headers (in CollectionSchemaView>ChangeColumn) --- src/client/documents/Documents.ts | 13 +-- src/client/util/DragManager.ts | 5 +- src/client/views/MainView.tsx | 3 +- .../views/collections/CollectionSchemaCells.tsx | 30 +++++- .../views/collections/CollectionSchemaHeaders.tsx | 9 +- .../CollectionSchemaMovableTableHOC.tsx | 7 +- .../views/collections/CollectionSchemaView.scss | 15 +++ .../views/collections/CollectionSchemaView.tsx | 103 +++++++++++++-------- .../views/collections/CollectionStackingView.tsx | 2 +- .../collections/collectionFreeForm/MarqueeView.tsx | 3 +- src/client/views/nodes/LinkEditor.tsx | 3 +- src/client/views/nodes/LinkMenuGroup.tsx | 3 +- src/new_fields/SchemaHeaderField.ts | 55 +++++++++-- 13 files changed, 186 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 76ac34d85..e6fe1b8b3 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -39,6 +39,7 @@ import { DocumentManager } from "../util/DocumentManager"; import DirectoryImportBox from "../util/Import & Export/DirectoryImportBox"; import { Scripting } from "../util/Scripting"; import { ButtonBox } from "../views/nodes/ButtonBox"; +import { SchemaHeaderField, RandomPastel } from "../../new_fields/SchemaHeaderField"; var requestImageSize = require('../util/request-image-size'); var path = require('path'); @@ -84,7 +85,7 @@ export interface DocumentOptions { curPage?: number; documentText?: string; borderRounding?: string; - schemaColumns?: List; + schemaColumns?: List; dockingConfig?: string; dbDoc?: Doc; // [key: string]: Opt; @@ -403,23 +404,23 @@ export namespace Docs { } export function FreeformDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Freeform }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Freeform }); } - export function SchemaDocument(schemaColumns: string[], documents: Array, options: DocumentOptions) { + export function SchemaDocument(schemaColumns: SchemaHeaderField[], documents: Array, options: DocumentOptions) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema }); } export function TreeDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Tree }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Tree }); } export function StackingDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Stacking }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Stacking }); } export function MasonryDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Masonry }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Masonry }); } export function ButtonDocument(options?: DocumentOptions) { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 0299b1d90..47d3c313d 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -8,6 +8,7 @@ import * as globalCssVariables from "../views/globalCssVariables.scss"; import { DocumentManager } from "./DocumentManager"; import { LinkManager } from "./LinkManager"; import { SelectionManager } from "./SelectionManager"; +import { SchemaHeaderField } from "../../new_fields/SchemaHeaderField"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag( @@ -290,10 +291,10 @@ export namespace DragManager { // for column dragging in schema view export class ColumnDragData { - constructor(colKey: string) { + constructor(colKey: SchemaHeaderField) { this.colKey = colKey; } - colKey: string; + colKey: SchemaHeaderField; [id: string]: any; } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 0e04b5e7e..282db244e 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -39,6 +39,7 @@ import { PreviewCursor } from './PreviewCursor'; import { FilterBox } from './search/FilterBox'; import { CollectionTreeView } from './collections/CollectionTreeView'; import { ClientUtils } from '../util/ClientUtils'; +import { SchemaHeaderField, RandomPastel } from '../../new_fields/SchemaHeaderField'; @observer export class MainView extends React.Component { @@ -375,7 +376,7 @@ export class MainView extends React.Component { let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"; // let addDockingNode = action(() => Docs.Create.StandardCollectionDockingDocument([{ doc: addColNode(), initialWidth: 200 }], { width: 200, height: 200, title: "a nested docking freeform collection" })); - let addSchemaNode = action(() => Docs.Create.SchemaDocument(["title"], [], { width: 200, height: 200, title: "a schema collection" })); + let addSchemaNode = action(() => Docs.Create.SchemaDocument([new SchemaHeaderField("title")], [], { width: 200, height: 200, title: "a schema collection" })); //let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" })); // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy" })); let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" })); diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 4a618a436..c91f1017b 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -21,7 +21,12 @@ import { NumCast, StrCast, BoolCast, FieldValue, Cast } from "../../../new_field import { Docs } from "../../documents/Documents"; import { DocumentContentsView } from "../nodes/DocumentContentsView"; import { SelectionManager } from "../../util/SelectionManager"; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { faExpand } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField"; +library.add(faExpand); export interface CellProps { row: number; @@ -38,6 +43,7 @@ export interface CellProps { changeFocusedCellByIndex: (row: number, col: number) => void; setIsEditing: (isEditing: boolean) => void; isEditable: boolean; + setPreviewDoc: (doc: Doc) => void; } @observer @@ -92,7 +98,7 @@ export class CollectionSchemaCell extends React.Component { this._document[fieldKey] = de.data.draggedDocuments[0]; } else { - let coll = Docs.Create.SchemaDocument(["title"], de.data.draggedDocuments, {}); + let coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title")], de.data.draggedDocuments, {}); this._document[fieldKey] = coll; } e.stopPropagation(); @@ -106,6 +112,18 @@ export class CollectionSchemaCell extends React.Component { } } + expandDoc = (e: React.PointerEvent) => { + let field = this.props.rowProps.original[this.props.rowProps.column.id as string]; + let doc = FieldValue(Cast(field, Doc)); + + console.log("Expanding doc", StrCast(doc!.title)); + this.props.setPreviewDoc(doc!); + + // this.props.changeFocusedCellByIndex(this.props.row, this.props.col); + + e.stopPropagation(); + } + renderCellWithType(type: string | undefined) { let dragRef: React.RefObject = React.createRef(); @@ -157,6 +175,15 @@ export class CollectionSchemaCell extends React.Component { if (this.props.isFocused && this.props.isEditable) className += " focused"; if (this.props.isFocused && !this.props.isEditable) className += " inactive"; + let doc = FieldValue(Cast(field, Doc)); + if (type === "document") console.log("doc", typeof field); + let fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc); + let docExpander = ( +
    + +
    + ); + return (
    @@ -193,6 +220,7 @@ export class CollectionSchemaCell extends React.Component { val && val.forEach(doc => this.applyToDoc(doc, run)); }} />
    + {fieldIsDoc ? docExpander : null}
    ); diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index d1d0674c4..9fc28eafa 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -10,11 +10,12 @@ import { ColumnType } from "./CollectionSchemaView"; import { emptyFunction } from "../../../Utils"; import { contains } from "typescript-collections/dist/lib/arrays"; import { faFile } from "@fortawesome/free-regular-svg-icons"; +import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faFile); export interface HeaderProps { - keyValue: string; + keyValue: SchemaHeaderField; possibleKeys: string[]; existingKeys: string[]; keyType: ColumnType; @@ -33,14 +34,14 @@ export class CollectionSchemaHeader extends React.Component { this.props.keyType === ColumnType.Boolean ? "check-square" : this.props.keyType === ColumnType.Doc ? "file" : "align-justify"; return ( -
    +
    {this.props.keyValue}
    } + menuButtonContent={
    {this.props.keyValue.heading}
    } addNew={false} onSelect={this.props.onSelect} setIsEditing={this.props.setIsEditing} diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 0ddd56180..2349e42ca 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -12,14 +12,15 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faGripVertical, faTrash } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { DocumentManager } from "../../util/DocumentManager"; +import { PastelSchemaPalette, SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; library.add(faGripVertical, faTrash); export interface MovableColumnProps { columnRenderer: TableCellRenderer; - columnValue: string; - allColumns: string[]; - reorderColumns: (toMove: string, relativeTo: string, before: boolean, columns: string[]) => void; + columnValue: SchemaHeaderField; + allColumns: SchemaHeaderField[]; + reorderColumns: (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columns: SchemaHeaderField[]) => void; ScreenToLocalTransform: () => Transform; } export class MovableColumn extends React.Component { diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 91c6e8b3c..e0de76247 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -379,6 +379,7 @@ button.add-column { .collectionSchemaView-cellWrapper { height: 100%; padding: 4px; + position: relative; &:focus { outline: none; @@ -405,6 +406,20 @@ button.add-column { height: 100%; // word-wrap: break-word; } + + &:hover .collectionSchemaView-cellContents-docExpander { + display: block; + } +} + +.collectionSchemaView-cellContents-docExpander { + height: 30px; + width: 30px; + display: none; + position: absolute; + top: 0; + right: 0; + background-color: lightgray; } .doc-drag-over { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index c6550560a..176872503 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -38,6 +38,7 @@ import { SelectionManager } from "../../util/SelectionManager"; import { DocumentManager } from "../../util/DocumentManager"; import { ImageBox } from "../nodes/ImageBox"; import { ComputedField } from "../../../new_fields/ScriptField"; +import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField"; library.add(faCog, faPlus, faSortUp, faSortDown); @@ -284,11 +285,13 @@ export class SchemaTable extends React.Component { @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 columns() { + return Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField), []); + } + set columns(columns: SchemaHeaderField[]) { 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); + let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.heading.toUpperCase() === key.toUpperCase()) === -1); let columns: Column[] = []; let tableIsFocused = this.props.isFocused(this.props.Document); let focusedRow = this._focusedCell.row; @@ -321,9 +324,9 @@ export class SchemaTable extends React.Component { let header = c.heading)} keyType={this.getColumnType(col)} - typeConst={columnTypes.get(col) !== undefined} + typeConst={col.type !== undefined || columnTypes.get(col.heading) !== undefined} onSelect={this.changeColumns} setIsEditing={this.setHeaderIsEditing} deleteColumn={this.deleteColumn} @@ -334,16 +337,16 @@ export class SchemaTable extends React.Component { return { Header: , - accessor: (doc: Doc) => doc ? doc[col] : 0, - id: col, + accessor: (doc: Doc) => doc ? doc[col.heading] : 0, + id: col.heading, Cell: (rowProps: CellInfo) => { - let row = rowProps.index; - let column = this.columns.indexOf(rowProps.column.id!); - let isFocused = focusedRow === row && focusedCol === column && tableIsFocused; + let rowIndex = rowProps.index; + let columnIndex = this.columns.map(c => c.heading).indexOf(rowProps.column.id!); + let isFocused = focusedRow === rowIndex && focusedCol === columnIndex && tableIsFocused; let props: CellProps = { - row: row, - col: column, + row: rowIndex, + col: columnIndex, rowProps: rowProps, isFocused: isFocused, changeFocusedCellByIndex: this.changeFocusedCellByIndex, @@ -356,6 +359,7 @@ export class SchemaTable extends React.Component { moveDocument: this.props.moveDocument, setIsEditing: this.setCellIsEditing, isEditable: isEditable, + setPreviewDoc: this.props.setPreviewDoc }; let colType = this.getColumnType(col); @@ -394,6 +398,15 @@ export class SchemaTable extends React.Component { // } // return this.props.Document; // } + constructor(props: SchemaTableProps) { + super(props); + // convert old schema columns (list of strings) into new schema columns (list of schema header fields) + let oldSchemaColumns = Cast(this.props.Document.schemaColumns, listSpec("string"), []); + if (oldSchemaColumns && oldSchemaColumns.length) { + let newSchemaColumns = oldSchemaColumns.map(i => typeof i === "string" ? new SchemaHeaderField(i) : i); + this.props.Document.schemaColumns = new List(newSchemaColumns); + } + } componentDidMount() { document.addEventListener("keydown", this.onKeyDown); @@ -440,7 +453,7 @@ export class SchemaTable extends React.Component { let row = rowInfo.index; //@ts-ignore - let col = this.columns.indexOf(column!.id); + let col = this.columns.map(c => c.heading).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!); @@ -502,6 +515,11 @@ export class SchemaTable extends React.Component { 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); + + let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + const pdoc = FieldValue(children[this._focusedCell.row]); + pdoc && this.props.setPreviewDoc(pdoc); } } @@ -532,8 +550,8 @@ export class SchemaTable extends React.Component { this._focusedCell = { row: this._focusedCell.row + 1 === children.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col }; break; } - const pdoc = FieldValue(children[this._focusedCell.row]); - pdoc && this.props.setPreviewDoc(pdoc); + // const pdoc = FieldValue(children[this._focusedCell.row]); + // pdoc && this.props.setPreviewDoc(pdoc); } @action @@ -544,8 +562,8 @@ export class SchemaTable extends React.Component { this._focusedCell = { row: row, col: col }; this.props.setFocused(this.props.Document); - const fdoc = FieldValue(children[this._focusedCell.row]); - fdoc && this.props.setPreviewDoc(fdoc); + // const fdoc = FieldValue(children[this._focusedCell.row]); + // fdoc && this.props.setPreviewDoc(fdoc); } createRow = () => { @@ -561,25 +579,25 @@ export class SchemaTable extends React.Component { @action createColumn = () => { let index = 0; - let found = this.columns.findIndex(col => col.toUpperCase() === "New field".toUpperCase()) > -1; + let found = this.columns.findIndex(col => col.heading.toUpperCase() === "New field".toUpperCase()) > -1; if (!found) { - this.columns.push("New field"); + this.columns.push(new SchemaHeaderField("New field")); return; } while (found) { index++; - found = this.columns.findIndex(col => col.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1; + found = this.columns.findIndex(col => col.heading.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1; } - this.columns.push("New field (" + index + ")"); + this.columns.push(new SchemaHeaderField("New field (" + index + ")")); } @action deleteColumn = (key: string) => { - let list = Cast(this.props.Document.schemaColumns, listSpec("string")); + let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField)); if (list === undefined) { - this.props.Document.schemaColumns = list = new List([]); + this.props.Document.schemaColumns = list = new List([]); } else { - const index = list.indexOf(key); + const index = list.map(c => c.heading).indexOf(key); if (index > -1) { list.splice(index, 1); } @@ -588,26 +606,37 @@ export class SchemaTable extends React.Component { @action changeColumns = (oldKey: string, newKey: string, addNew: boolean) => { - let list = Cast(this.props.Document.schemaColumns, listSpec("string")); + let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField)); if (list === undefined) { - this.props.Document.schemaColumns = list = new List([newKey]); + this.props.Document.schemaColumns = list = new List([new SchemaHeaderField(newKey)]); } else { if (addNew) { - this.columns.push(newKey); + this.columns.push(new SchemaHeaderField(newKey)); } else { - const index = list.indexOf(oldKey); + const index = list.map(c => c.heading).indexOf(oldKey); if (index > -1) { - list[index] = newKey; + list[index] = new SchemaHeaderField(newKey); } } } } - getColumnType = (key: string): ColumnType => { - if (columnTypes.get(key)) return columnTypes.get(key)!; + getColumnType = (column: SchemaHeaderField): ColumnType => { + // added functionality to convert old column type stuff to new column type stuff -syip + if (column.type && column.type !== 0) { + return column.type; + } + if (columnTypes.get(column.heading)) { + column.type = columnTypes.get(column.heading)!; + return columnTypes.get(column.heading)!; + } const typesDoc = FieldValue(Cast(this.props.Document.schemaColumnTypes, Doc)); - if (!typesDoc) return ColumnType.Any; - return NumCast(typesDoc[key]); + if (!typesDoc) { + column.type = ColumnType.Any; + return ColumnType.Any; + } + column.type = NumCast(typesDoc[column.heading]); + return NumCast(typesDoc[column.heading]); } setColumnType = (key: string, type: ColumnType): void => { @@ -624,11 +653,11 @@ export class SchemaTable extends React.Component { } @action - setColumns = (columns: string[]) => { + setColumns = (columns: SchemaHeaderField[]) => { this.columns = columns; } - reorderColumns = (toMove: string, relativeTo: string, before: boolean, columnsValues: string[]) => { + reorderColumns = (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columnsValues: SchemaHeaderField[]) => { let columns = [...columnsValues]; let oldIndex = columns.indexOf(toMove); let relIndex = columns.indexOf(relativeTo); @@ -661,7 +690,7 @@ export class SchemaTable extends React.Component { //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); + this.columns.forEach(key => keys[key.heading] = true); return Array.from(Object.keys(keys)); } @@ -727,7 +756,7 @@ export class SchemaTable extends React.Component { 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 += self.columns.reduce((val, col) => val + (doc[col.heading] ? doc[col.heading]!.toString() : "0") + ",", ""); csv = csv.substr(0, csv.length - 1) + "\n"; }); csv.substring(0, csv.length - 1); diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 7677f53c1..e897c5676 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -16,7 +16,7 @@ import { Transform } from "../../util/Transform"; import { CursorProperty } from "csstype"; import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn"; import { listSpec } from "../../../new_fields/Schema"; -import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; +import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField"; import { List } from "../../../new_fields/List"; import { EditableView } from "../EditableView"; import { CollectionViewProps } from "./CollectionBaseView"; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index b765517a2..2e54a9736 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -19,6 +19,7 @@ import { CollectionViewType } from "../CollectionBaseView"; import { CollectionFreeFormView } from "./CollectionFreeFormView"; import "./MarqueeView.scss"; import React = require("react"); +import { SchemaHeaderField, RandomPastel } from "../../../../new_fields/SchemaHeaderField"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -134,7 +135,7 @@ export class MarqueeView extends React.Component doc.width = 200; docList.push(doc); } - let newCol = Docs.Create.SchemaDocument([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 }); + let newCol = Docs.Create.SchemaDocument([...(groupAttr ? [new SchemaHeaderField("_group")] : []), ...columns.filter(c => c).map(c => new SchemaHeaderField(c))], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 }); this.props.addDocument(newCol, false); } diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index afde85b69..0ea948c81 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -11,6 +11,7 @@ import { faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTim import { library } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { SetupDrag } from "../../util/DragManager"; +import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField"; library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus); @@ -289,7 +290,7 @@ export class LinkGroupEditor extends React.Component { let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); let index = keys.indexOf(""); if (index > -1) keys.splice(index, 1); - let cols = ["anchor1", "anchor2", ...[...keys]]; + let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c)); let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType); let createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" })); let ref = React.createRef(); diff --git a/src/client/views/nodes/LinkMenuGroup.tsx b/src/client/views/nodes/LinkMenuGroup.tsx index ae97bed2f..3637807ad 100644 --- a/src/client/views/nodes/LinkMenuGroup.tsx +++ b/src/client/views/nodes/LinkMenuGroup.tsx @@ -14,6 +14,7 @@ import { Docs } from "../../documents/Documents"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { UndoManager } from "../../util/UndoManager"; import { StrCast } from "../../../new_fields/Types"; +import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField"; interface LinkMenuGroupProps { sourceDoc: Doc; @@ -70,7 +71,7 @@ export class LinkMenuGroup extends React.Component { let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); let index = keys.indexOf(""); if (index > -1) keys.splice(index, 1); - let cols = ["anchor1", "anchor2", ...[...keys]]; + let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c)); let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType); let createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" })); let ref = React.createRef(); diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts index 284de3023..a6df31e81 100644 --- a/src/new_fields/SchemaHeaderField.ts +++ b/src/new_fields/SchemaHeaderField.ts @@ -3,13 +3,42 @@ import { serializable, createSimpleSchema, primitive } from "serializr"; import { ObjectField } from "./ObjectField"; import { Copy, ToScriptString, OnUpdate } from "./FieldSymbols"; import { scriptingGlobal, Scripting } from "../client/util/Scripting"; +import { ColumnType } from "../client/views/collections/CollectionSchemaView"; export const PastelSchemaPalette = new Map([ - ["purple", "#f5b5fc"], - ["green", "#96F7D2"], - ["yellow", "#F0F696"], - ["red", "#FCB1B1"] -]) + ["pink1", "#FFB4E8"], + ["pink2", "#ff9cee"], + ["pink3", "#ffccf9"], + ["pink4", "#fcc2ff"], + ["pink5", "#f6a6ff"], + ["purple1", "#b28dff"], + ["purple2", "#c5a3ff"], + ["purple3", "#d5aaff"], + ["purple4", "#ecd4ff"], + ["purple5", "#fb34ff"], + ["purple6", "#dcd3ff"], + ["purple7", "#a79aff"], + ["purple8", "#b5b9ff"], + ["purple9", "#97a2ff"], + ["bluegreen1", "#afcbff"], + ["bluegreen2", "#aff8db"], + ["bluegreen3", "#c4faf8"], + ["bluegreen4", "#85e3ff"], + ["bluegreen5", "#ace7ff"], + ["bluegreen6", "#6eb5ff"], + ["bluegreen7", "#bffcc6"], + ["bluegreen8", "#dbffd6"], + ["yellow1", "#f3ffe3"], + ["yellow2", "#e7ffac"], + ["yellow3", "#ffffd1"], + ["yellow4", "#fff5ba"], + ["red1", "#ffc9de"], + ["red2", "#ffabab"], + ["red3", "#ffbebc"], + ["red4", "#ffcbc1"], +]); + +export const RandomPastel = () => Array.from(PastelSchemaPalette.values())[Math.floor(Math.random() * PastelSchemaPalette.size)]; @scriptingGlobal @Deserializable("schemaheader") @@ -17,12 +46,19 @@ export class SchemaHeaderField extends ObjectField { @serializable(primitive()) heading: string; color: string; + type: number; - constructor(heading: string = "", color: string = Array.from(PastelSchemaPalette.values())[Math.floor(Math.random() * 4)]) { + constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType) { super(); this.heading = heading; this.color = color; + if (type) { + this.type = type; + } + else { + this.type = 0; + } } setHeading(heading: string) { @@ -35,8 +71,13 @@ export class SchemaHeaderField extends ObjectField { this[OnUpdate](); } + setType(type: ColumnType) { + this.type = type; + this[OnUpdate](); + } + [Copy]() { - return new SchemaHeaderField(this.heading, this.color); + return new SchemaHeaderField(this.heading, this.color, this.type); } [ToScriptString]() { -- cgit v1.2.3-70-g09d2 From 3b0af6ff470539fd0a25b2ab975195ff9e269b4a Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 27 Jul 2019 17:16:13 -0400 Subject: Changed link undoing --- src/client/util/DragManager.ts | 1 - src/client/views/DocumentDecorations.tsx | 17 +++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 95416cd53..a898175b8 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -422,7 +422,6 @@ export namespace DragManager { if (options) { options.handlers.dragComplete({}); } - DocumentDecorations.Instance.endLinkDragBatch(); }; AbortDrag = () => { diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index ee16938ff..a34c47fdf 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -378,16 +378,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } } - endLinkDragBatch = () => { - if (!this._linkDrag) { - return; - } - this._linkDrag.end(); - this._linkDrag = undefined; - } - onLinkerButtonDown = (e: React.PointerEvent): void => { - this._linkDrag = UndoManager.StartBatch("Drag Link"); e.stopPropagation(); document.removeEventListener("pointermove", this.onLinkerButtonMoved); document.addEventListener("pointermove", this.onLinkerButtonMoved); @@ -424,9 +415,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let container = selDoc.props.ContainingCollectionView ? selDoc.props.ContainingCollectionView.props.Document.proto : undefined; let dragData = new DragManager.LinkDragData(selDoc.props.Document, container ? [container] : []); FormattedTextBox.InputBoxOverlay = undefined; + this._linkDrag = UndoManager.StartBatch("Drag Link"); DragManager.StartLinkDrag(this._linkerButton.current, dragData, e.pageX, e.pageY, { handlers: { - dragComplete: action(emptyFunction), + dragComplete: () => { + if (this._linkDrag) { + this._linkDrag.end(); + this._linkDrag = undefined; + } + }, }, hideSource: false }); -- cgit v1.2.3-70-g09d2 From 3661d710d153f6c9fb4b11d45f3b72afb493a5a1 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 27 Jul 2019 18:31:52 -0400 Subject: Made copying out of formatted text work better --- src/client/views/nodes/FormattedTextBox.tsx | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 5ac4af0bb..180fc1e2b 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -5,7 +5,7 @@ import { observer } from "mobx-react"; import { baseKeymap } from "prosemirror-commands"; import { history } from "prosemirror-history"; import { keymap } from "prosemirror-keymap"; -import { NodeType } from 'prosemirror-model'; +import { NodeType, Slice } from 'prosemirror-model'; import { EditorState, Plugin, Transaction } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { Doc, Opt } from "../../../new_fields/Doc"; @@ -251,6 +251,23 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe this.setupEditor(config, this.dataDoc, this.props.fieldKey); } + clipboardTextSerializer = (slice: Slice): string => { + let text = "", separated = true; + const from = 0, to = slice.content.size; + slice.content.nodesBetween(from, to, (node, pos) => { + if (node.isText) { + text += node.text!.slice(Math.max(from, pos) - pos, to - pos); + separated = false; + } else if (!separated && node.isBlock) { + text += "\n"; + separated = true; + } else if (node.type.name === "hard_break") { + text += "\n"; + } + }, 0); + return text; + } + private setupEditor(config: any, doc: Doc, fieldKey: string) { let field = doc ? Cast(doc[fieldKey], RichTextField) : undefined; let startup = StrCast(doc.documentText); @@ -270,7 +287,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe nodeViews: { image(node, view, getPos) { return new ImageResizeView(node, view, getPos); }, star(node, view, getPos) { return new SummarizedView(node, view, getPos); } - } + }, + clipboardTextSerializer: this.clipboardTextSerializer }); if (startup) { Doc.GetProto(doc).documentText = undefined; -- cgit v1.2.3-70-g09d2 From 73fcf938eb817ae9b4dfdcefd5f04502079c153e Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 27 Jul 2019 18:38:09 -0400 Subject: Fixed linter errors --- src/client/views/collections/CollectionStackingViewFieldColumn.tsx | 6 +++--- src/client/views/collections/CollectionViewChromes.tsx | 2 +- src/client/views/collections/KeyRestrictionRow.tsx | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 1a5d203f9..cf6079196 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -74,7 +74,7 @@ export class CollectionStackingViewFieldColumn extends React.Component headings.indexOf(i) === idx); - let pair = Doc.GetLayoutDataDocPair(parent.props.Document, parent.props.DataDoc, parent.props.fieldKey, d) + let pair = Doc.GetLayoutDataDocPair(parent.props.Document, parent.props.DataDoc, parent.props.fieldKey, d); let width = () => (d.nativeWidth && !BoolCast(d.ignoreAspect) ? Math.min(pair.layout[WidthSym](), parent.columnWidth) : parent.columnWidth) / (uniqueHeadings.length + 1); let height = () => parent.getDocHeight(pair.layout); if (parent.singleColumn) { @@ -243,12 +243,12 @@ export class CollectionStackingViewFieldColumn extends React.Component "", SetValue: this.addDocument, contents: "+ NEW" - } + }; let headingView = this.props.headingObject ?
    diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index de1d01ef0..bf643347f 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -296,7 +296,7 @@ export class CollectionStackingViewChrome extends React.Component { this.props.CollectionView.props.Document.stackingHeadersSortDescending = !this.props.CollectionView.props.Document.stackingHeadersSortDescending; } + @action toggleSort = () => { this.props.CollectionView.props.Document.stackingHeadersSortDescending = !this.props.CollectionView.props.Document.stackingHeadersSortDescending; }; @action resetValue = () => { this._currentKey = this.sectionFilter; }; render() { diff --git a/src/client/views/collections/KeyRestrictionRow.tsx b/src/client/views/collections/KeyRestrictionRow.tsx index 8051a8359..f292557b5 100644 --- a/src/client/views/collections/KeyRestrictionRow.tsx +++ b/src/client/views/collections/KeyRestrictionRow.tsx @@ -40,6 +40,6 @@ export default class KeyRestrictionRow extends React.Component runInAction(() => this._value = e.target.value)} placeholder="VALUE" />
    - ) + ); } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 2065186202404a2bb70f45da7ae842297da3c14c Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sat, 27 Jul 2019 18:45:28 -0400 Subject: fixes --- src/client/views/collections/CollectionPDFView.tsx | 2 +- src/client/views/collections/CollectionSchemaMovableTableHOC.tsx | 2 +- src/client/views/collections/CollectionVideoView.tsx | 2 +- src/server/authentication/models/current_user_utils.ts | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx index 9074854d6..70010819a 100644 --- a/src/client/views/collections/CollectionPDFView.tsx +++ b/src/client/views/collections/CollectionPDFView.tsx @@ -78,7 +78,7 @@ export class CollectionPDFView extends React.Component { let props = { ...this.props, ...renderProps }; return ( <> - + {renderProps.active() ? this.uIButtons : (null)} ); diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 2349e42ca..7342ede7a 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -180,7 +180,7 @@ export class MovableRow extends React.Component { onRowContextMenu = (e: React.MouseEvent): void => { 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) }); + ContextMenu.Instance.addItem({ description: description, event: () => this.props.textWrapRow(this.props.rowInfo.original), icon: "file-pdf" }); } @action diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx index 31a8a93e0..a264cc402 100644 --- a/src/client/views/collections/CollectionVideoView.tsx +++ b/src/client/views/collections/CollectionVideoView.tsx @@ -89,7 +89,7 @@ export class CollectionVideoView extends React.Component { private subView = (_type: CollectionViewType, renderProps: CollectionRenderProps) => { let props = { ...this.props, ...renderProps }; return (<> - + {this.props.isSelected() ? this.uIButtons : (null)} ); } diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 41eb1aa0c..1693d2f48 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -50,7 +50,6 @@ 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; @@ -58,7 +57,6 @@ 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; } @@ -67,12 +65,14 @@ 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; } + (Cast(doc.workspaces, Doc) as Doc).chromeStatus = "disabled"; + (Cast(doc.recentlyClosed, Doc) as Doc).chromeStatus = "disabled"; + (Cast(doc.sidebar, Doc) as Doc).chromeStatus = "disabled"; doc.chromeStatus = "disabled"; StrCast(doc.title).indexOf("@") !== -1 && (doc.title = StrCast(doc.title).split("@")[0] + "'s Library"); -- cgit v1.2.3-70-g09d2 From 4cab6e0d15ee27c68c358b59ecc3f7e0a89b514f Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sat, 27 Jul 2019 19:05:23 -0400 Subject: fixed updating user doc stuff --- src/client/views/Main.tsx | 5 +++++ src/server/authentication/models/current_user_utils.ts | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 86578af3e..1cf13aa74 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -33,6 +33,11 @@ let swapDocs = async () => { DocServer.init(window.location.protocol, window.location.hostname, 4321, info.email); await Docs.Prototypes.initialize(); await CurrentUserUtils.loadUserDocument(info); + // updates old user documents to prevent chrome on tree view. + (await Cast(CurrentUserUtils.UserDocument.workspaces, Doc))!.chromeStatus = "disabled"; + (await Cast(CurrentUserUtils.UserDocument.recentlyClosed, Doc))!.chromeStatus = "disabled"; + (await Cast(CurrentUserUtils.UserDocument.sidebar, Doc))!.chromeStatus = "disabled"; + CurrentUserUtils.UserDocument.chromeStatus = "disabled"; await swapDocs(); ReactDOM.render(, document.getElementById('root')); })(); \ No newline at end of file diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 1693d2f48..1c52a3f11 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -70,10 +70,6 @@ export class CurrentUserUtils { sidebar.boxShadow = "1 1 3"; doc.sidebar = sidebar; } - (Cast(doc.workspaces, Doc) as Doc).chromeStatus = "disabled"; - (Cast(doc.recentlyClosed, Doc) as Doc).chromeStatus = "disabled"; - (Cast(doc.sidebar, Doc) as Doc).chromeStatus = "disabled"; - doc.chromeStatus = "disabled"; StrCast(doc.title).indexOf("@") !== -1 && (doc.title = StrCast(doc.title).split("@")[0] + "'s Library"); } -- cgit v1.2.3-70-g09d2 From 31fafa54bd85cb292a5facd12d7c8f0ed13d1ea9 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sat, 27 Jul 2019 19:24:54 -0400 Subject: small timeout thing --- src/client/views/collections/CollectionViewChromes.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index bf643347f..044d5336a 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -40,11 +40,11 @@ export class CollectionViewBaseChrome extends React.Component { - this._picker = datepicker("#" + this._datePickerElGuid, { + setTimeout(() => this._picker = datepicker("#" + this._datePickerElGuid, { disabler: (date: Date) => date > new Date(), onSelect: (instance: any, date: Date) => runInAction(() => this._dateValue = date), dateSelected: new Date() - }); + }), 1000); runInAction(() => { this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[0][1] = value)} />, ""]); -- cgit v1.2.3-70-g09d2 From 1dd24847a8dc2940bb53af3e42f715edec5f43b2 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 27 Jul 2019 20:10:45 -0400 Subject: Added paste handler to prose mirror --- src/client/views/nodes/FormattedTextBox.tsx | 39 ++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 180fc1e2b..d5f539194 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -5,7 +5,7 @@ import { observer } from "mobx-react"; import { baseKeymap } from "prosemirror-commands"; import { history } from "prosemirror-history"; import { keymap } from "prosemirror-keymap"; -import { NodeType, Slice } from 'prosemirror-model'; +import { NodeType, Slice, Node, Fragment } from 'prosemirror-model'; import { EditorState, Plugin, Transaction } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { Doc, Opt } from "../../../new_fields/Doc"; @@ -34,7 +34,6 @@ import { FieldView, FieldViewProps } from "./FieldView"; import "./FormattedTextBox.scss"; import React = require("react"); import { DateField } from '../../../new_fields/DateField'; -import { thisExpression } from 'babel-types'; import { Utils } from '../../../Utils'; library.add(faEdit); @@ -268,6 +267,39 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe return text; } + sliceSingleNode(slice: Slice) { + return slice.openStart === 0 && slice.openEnd === 0 && slice.content.childCount === 1 ? slice.content.firstChild : null; + } + + handlePaste = (view: EditorView, event: Event, slice: Slice): boolean => { + return false; + function addMarkToFrag(frag: Fragment) { + const nodes: Node[] = []; + frag.forEach(node => nodes.push(addLinkMark(node))); + return Fragment.fromArray(nodes); + } + function addLinkMark(node: Node) { + if (!node.isText) { + const content = addMarkToFrag(node.content); + return node.copy(content); + } + const marks = [...node.marks]; + const linkIndex = marks.findIndex(mark => mark.type.name === "link"); + const link = view.state.schema.mark(view.state.schema.marks.link, { href: "http://localhost:1050/doc/[link document id]", location: "onRight" }); + if (linkIndex !== -1) { + marks.splice(linkIndex, 1, link); + } else { + marks.push(link); + } + return node.mark(marks); + } + let frag = addMarkToFrag(slice.content); + slice = new Slice(frag, slice.openStart, slice.openEnd); + var tr = view.state.tr.replaceSelection(slice); + view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste")); + return true; + } + private setupEditor(config: any, doc: Doc, fieldKey: string) { let field = doc ? Cast(doc[fieldKey], RichTextField) : undefined; let startup = StrCast(doc.documentText); @@ -288,7 +320,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe image(node, view, getPos) { return new ImageResizeView(node, view, getPos); }, star(node, view, getPos) { return new SummarizedView(node, view, getPos); } }, - clipboardTextSerializer: this.clipboardTextSerializer + clipboardTextSerializer: this.clipboardTextSerializer, + handlePaste: this.handlePaste, }); if (startup) { Doc.GetProto(doc).documentText = undefined; -- cgit v1.2.3-70-g09d2 From 92b848b79eaf90235fed550bc96b6ca982bd07df Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sat, 27 Jul 2019 21:23:12 -0400 Subject: asdfkjlsdafds --- src/client/documents/Documents.ts | 6 ++--- src/client/views/nodes/FormattedTextBox.tsx | 38 +++++++++++++++++++++++------ src/client/views/nodes/PDFBox.tsx | 18 ++++++++------ src/client/views/pdf/PDFViewer.tsx | 29 +++++++++++++++++++--- 4 files changed, 70 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e6fe1b8b3..ee1b9fd0d 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -582,12 +582,12 @@ export namespace Docs { export namespace DocUtils { export function MakeLink(source: Doc, target: Doc, targetContext?: Doc, title: string = "", description: string = "", tags: string = "Default", sourceContext?: Doc) { - if (LinkManager.Instance.doesLinkExist(source, target)) return; + if (LinkManager.Instance.doesLinkExist(source, target)) return undefined; let sv = DocumentManager.Instance.getDocumentView(source); if (sv && sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === target) return; - if (target === CurrentUserUtils.UserDocument) return; + if (target === CurrentUserUtils.UserDocument) return undefined; - let linkDoc; + let linkDoc: Doc | undefined; UndoManager.RunInBatch(() => { linkDoc = Docs.Create.TextDocument({ width: 100, height: 30, borderRounding: "100%" }); linkDoc.type = DocumentType.LINK; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index e982cdfdd..364dc1c83 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -15,7 +15,7 @@ import { RichTextField } from "../../../new_fields/RichTextField"; import { createSchema, listSpec, makeInterface } from "../../../new_fields/Schema"; import { BoolCast, Cast, NumCast, StrCast, DateCast } from "../../../new_fields/Types"; import { DocServer } from "../../DocServer"; -import { Docs } from '../../documents/Documents'; +import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager } from "../../util/DragManager"; import buildKeymap from "../../util/ProsemirrorExampleTransfer"; @@ -300,7 +300,34 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } handlePaste = (view: EditorView, event: Event, slice: Slice): boolean => { - return false; + let cbe = event as ClipboardEvent; + let docId: string; + if (!cbe.clipboardData) { + return false; + } + let linkId: string; + docId = cbe.clipboardData.getData("dash/pdfOrigin"); + if (!docId) { + return false; + } + + DocServer.GetRefField(docId).then(doc => { + if (!(doc instanceof Doc)) { + return; + } + let link = DocUtils.MakeLink(this.props.Document, doc); + if (link) { + cbe.clipboardData!.setData("dash/linkDoc", link[Id]); + linkId = link[Id]; + let frag = addMarkToFrag(slice.content); + slice = new Slice(frag, slice.openStart, slice.openEnd); + var tr = view.state.tr.replaceSelection(slice); + view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste")); + } + }); + + return true; + function addMarkToFrag(frag: Fragment) { const nodes: Node[] = []; frag.forEach(node => nodes.push(addLinkMark(node))); @@ -313,7 +340,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } const marks = [...node.marks]; const linkIndex = marks.findIndex(mark => mark.type.name === "link"); - const link = view.state.schema.mark(view.state.schema.marks.link, { href: "http://localhost:1050/doc/[link document id]", location: "onRight" }); + const link = view.state.schema.mark(view.state.schema.marks.link, { href: `http://localhost:1050/doc/${linkId}`, location: "onRight" }); if (linkIndex !== -1) { marks.splice(linkIndex, 1, link); } else { @@ -321,11 +348,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } return node.mark(marks); } - let frag = addMarkToFrag(slice.content); - slice = new Slice(frag, slice.openStart, slice.openEnd); - var tr = view.state.tr.replaceSelection(slice); - view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste")); - return true; } private setupEditor(config: any, doc: Doc, fieldKey: string) { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 282312dca..72d835fce 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -66,23 +66,28 @@ export class PDFBox extends DocComponent(PdfDocumen this._keyRef = React.createRef(); this._valueRef = React.createRef(); this._scriptRef = React.createRef(); - - document.addEventListener("keydown", this.onKeyDown); } componentDidMount() { if (this.props.setPdfBox) this.props.setPdfBox(this); + + document.removeEventListener("copy", this.copy); + document.addEventListener("copy", this.copy); } componentWillUnmount() { this._reactionDisposer && this._reactionDisposer(); + document.removeEventListener("copy", this.copy); } - onKeyDown = (e: KeyboardEvent) => { - if (e.ctrlKey && e.keyCode === KeyCodes.C) { + private copy = (e: ClipboardEvent) => { + if (this.props.active()) { let text = this.selectionText; - text += `${Utils.GenerateDeterministicGuid("pdf paste")}/${this.props.Document[Id]}`; - navigator.clipboard.writeText(text); + if (e.clipboardData) { + e.clipboardData.setData("text/plain", text); + e.clipboardData.setData("dash/pdfOrigin", this.props.Document[Id]); + e.preventDefault(); + } } } @@ -254,7 +259,6 @@ export class PDFBox extends DocComponent(PdfDocumen let classname = "pdfBox-cont" + (this.props.active() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : ""); return (
    { if (this._mainCont.current) { this._dropDisposer = this._mainCont.current && DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } }); } + + document.removeEventListener("paste", this.paste); + document.addEventListener("paste", this.paste); } componentWillUnmount = () => { @@ -163,6 +167,25 @@ export class Viewer extends React.Component { this._annotationReactionDisposer && this._annotationReactionDisposer(); this._filterReactionDisposer && this._filterReactionDisposer(); this._dropDisposer && this._dropDisposer(); + document.removeEventListener("paste", this.paste); + } + + paste = (e: ClipboardEvent) => { + if (e.clipboardData) { + if (e.clipboardData.getData("dash/pdfOrigin") === this.props.parent.props.Document[Id]) { + let linkDocId = e.clipboardData.getData("dash/linkDoc"); + if (linkDocId) { + DocServer.GetRefField(linkDocId).then(async (link) => { + if (!(link instanceof Doc)) { + return; + } + let proto = Doc.GetProto(link); + let source = await Cast(proto.anchor1, Doc); + proto.anchor2 = this.makeAnnotationDocument(source, 0, "#0390fc", false); + }); + } + } + } } scrollTo(y: number) { @@ -213,7 +236,7 @@ export class Viewer extends React.Component { } @action - makeAnnotationDocument = (sourceDoc: Doc | undefined, s: number, color: string): Doc => { + makeAnnotationDocument = (sourceDoc: Doc | undefined, s: number, color: string, createLink: boolean = true): Doc => { let annoDocs: Doc[] = []; let mainAnnoDoc = Docs.Create.InstanceFromProto(new Doc(), "", {}); @@ -242,7 +265,7 @@ export class Viewer extends React.Component { mainAnnoDoc.y = Math.max(minY, 0); mainAnnoDoc.annotations = new List(annoDocs); - if (sourceDoc) { + if (sourceDoc && createLink) { DocUtils.MakeLink(sourceDoc, mainAnnoDoc, undefined, `Annotation from ${StrCast(this.props.parent.Document.title)}`, "", StrCast(this.props.parent.Document.title)); } this._savedAnnotations.clear(); @@ -611,7 +634,7 @@ export class Viewer extends React.Component {
    {this._visibleElements}
    -
    +
    console.log("gello world")} style={{ transform: "scale(1.5)", transformOrigin: "top left" }} />
    Date: Sat, 27 Jul 2019 21:48:05 -0400 Subject: hold ctrl to open in current tab --- src/client/views/DocumentDecorations.tsx | 1 + src/client/views/nodes/LinkMenu.tsx | 9 ++++++++- src/client/views/nodes/LinkMenuGroup.tsx | 2 ++ src/client/views/nodes/LinkMenuItem.tsx | 28 ++++++++++++++++++---------- 4 files changed, 29 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index a34c47fdf..40f2c3da9 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -676,6 +676,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> linkButton = (}>
    {linkCount}
    ); diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index 1eda7d1fb..1a4af04f8 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -19,6 +19,7 @@ import { DocumentType } from "../../documents/Documents"; interface Props { docView: DocumentView; changeFlyout: () => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; } @observer @@ -39,7 +40,13 @@ export class LinkMenu extends React.Component { let linkItems: Array = []; groups.forEach((group, groupType) => { linkItems.push( - this._editingLink = linkDoc)} /> + this._editingLink = linkDoc)} + addDocTab={this.props.addDocTab} /> ); }); diff --git a/src/client/views/nodes/LinkMenuGroup.tsx b/src/client/views/nodes/LinkMenuGroup.tsx index 3637807ad..0cb216aa6 100644 --- a/src/client/views/nodes/LinkMenuGroup.tsx +++ b/src/client/views/nodes/LinkMenuGroup.tsx @@ -21,6 +21,7 @@ interface LinkMenuGroupProps { group: Doc[]; groupType: string; showEditor: (linkDoc: Doc) => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; } @observer @@ -83,6 +84,7 @@ export class LinkMenuGroup extends React.Component { let destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc); if (destination && this.props.sourceDoc) { return ; } }); diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx index d4c92c9f2..c8f616ce0 100644 --- a/src/client/views/nodes/LinkMenuItem.tsx +++ b/src/client/views/nodes/LinkMenuItem.tsx @@ -12,6 +12,7 @@ import { observable, action } from 'mobx'; import { LinkManager } from '../../util/LinkManager'; import { DragLinkAsDocument } from '../../util/DragManager'; import { CollectionDockingView } from '../collections/CollectionDockingView'; +import { SelectionManager } from '../../util/SelectionManager'; library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); @@ -21,6 +22,7 @@ interface LinkMenuItemProps { sourceDoc: Doc; destinationDoc: Doc; showEditor: (linkDoc: Doc) => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; } @observer @@ -42,18 +44,24 @@ export class LinkMenuItem extends React.Component { let targetContext = await Cast(proto.targetContext, Doc); let sourceContext = await Cast(proto.sourceContext, Doc); let self = this; - if (DocumentManager.Instance.getDocumentView(jumpToDoc)) { + + let dockingFunc = (document: Doc) => CollectionDockingView.Instance.AddRightSplit(document, undefined); + + if (e.ctrlKey) { + dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; + } + + if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) { + DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(targetContext!)); + } + else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) { + DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(sourceContext!)); + } + else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) { DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, undefined, undefined, NumCast((this.props.destinationDoc === self.props.linkDoc.anchor2 ? self.props.linkDoc.anchor2Page : self.props.linkDoc.anchor1Page))); } - else if (!((this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) || (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext))) { - DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => CollectionDockingView.Instance.AddRightSplit(document, undefined)); - } else { - if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) { - DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => CollectionDockingView.Instance.AddRightSplit(targetContext!, undefined)); - } - else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) { - DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => CollectionDockingView.Instance.AddRightSplit(sourceContext!, undefined)); - } + else { + DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, dockingFunc); } } -- cgit v1.2.3-70-g09d2 From 73d30f20e5d38104424c47845a28e860070e4159 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sat, 27 Jul 2019 21:59:51 -0400 Subject: swapped ctrlkey --- src/client/views/nodes/LinkMenuItem.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx index c8f616ce0..1d4fcad69 100644 --- a/src/client/views/nodes/LinkMenuItem.tsx +++ b/src/client/views/nodes/LinkMenuItem.tsx @@ -45,10 +45,10 @@ export class LinkMenuItem extends React.Component { let sourceContext = await Cast(proto.sourceContext, Doc); let self = this; - let dockingFunc = (document: Doc) => CollectionDockingView.Instance.AddRightSplit(document, undefined); + let dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; if (e.ctrlKey) { - dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; + dockingFunc = (document: Doc) => CollectionDockingView.Instance.AddRightSplit(document, undefined); } if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) { -- cgit v1.2.3-70-g09d2 From 8f4e803171bbf355e584fad6daa40d498253087f Mon Sep 17 00:00:00 2001 From: Fawn Date: Sat, 27 Jul 2019 22:27:23 -0400 Subject: can script in any schema cell --- src/client/views/EditableView.tsx | 2 +- .../views/collections/CollectionSchemaCells.tsx | 26 ++++--- .../views/collections/CollectionSchemaView.tsx | 82 +++++++++++++++++++++- 3 files changed, 96 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 373b63282..c3612fee9 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -134,7 +134,7 @@ export class EditableView extends React.Component { return (
    + onClick={this.onClick}> {this.props.contents}
    ); diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index c91f1017b..e00142c91 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -24,7 +24,7 @@ import { SelectionManager } from "../../util/SelectionManager"; import { library } from '@fortawesome/fontawesome-svg-core'; import { faExpand } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField"; +import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; library.add(faExpand); @@ -44,6 +44,8 @@ export interface CellProps { setIsEditing: (isEditing: boolean) => void; isEditable: boolean; setPreviewDoc: (doc: Doc) => void; + setComputed: (script: string, doc: Doc, field: string, row: number, col: number) => boolean; + getField: (row: number, col?: number) => void; } @observer @@ -84,9 +86,11 @@ 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 }); + applyToDoc = (doc: Doc, row: number, col: number, run: (args?: { [name: string]: any }) => any) => { + const res = run({ this: doc, $r: row, $c: col, $: (r: number = 0, c: number = 0) => this.props.getField(r + row, c + col) }); if (!res.success) return false; + // doc[this.props.fieldKey] = res.result; + // return true; doc[this.props.rowProps.column.id as string] = res.result; return true; } @@ -176,7 +180,6 @@ export class CollectionSchemaCell extends React.Component { if (this.props.isFocused && !this.props.isEditable) className += " inactive"; let doc = FieldValue(Cast(field, Doc)); - if (type === "document") console.log("doc", typeof field); let fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc); let docExpander = (
    @@ -203,22 +206,25 @@ export class CollectionSchemaCell extends React.Component { } } SetValue={(value: string) => { - let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } }); + if (value.startsWith(":=")) { + return this.props.setComputed(value.substring(2), props.Document, this.props.rowProps.column.id!, this.props.row, this.props.col); + } + let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } }); if (!script.compiled) { return false; } - return this.applyToDoc(props.Document, script.run); + return this.applyToDoc(props.Document, this.props.row, this.props.col, script.run); }} OnFillDown={async (value: string) => { - let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } }); + let script = CompileScript(value, { requiredType: type, 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 => this.applyToDoc(doc, run)); - }} /> + val && val.forEach((doc, i) => this.applyToDoc(doc, i, this.props.col, run)); + }} + />
    {fieldIsDoc ? docExpander : null}
    diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index d504f9799..42843ad30 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -321,13 +321,12 @@ export class SchemaTable extends React.Component { } let cols = this.columns.map(col => { - let header = c.heading)} keyType={this.getColumnType(col)} - typeConst={col.type !== undefined || columnTypes.get(col.heading) !== undefined} + typeConst={columnTypes.get(col.heading) !== undefined} onSelect={this.changeColumns} setIsEditing={this.setHeaderIsEditing} deleteColumn={this.deleteColumn} @@ -360,7 +359,9 @@ export class SchemaTable extends React.Component { moveDocument: this.props.moveDocument, setIsEditing: this.setCellIsEditing, isEditable: isEditable, - setPreviewDoc: this.props.setPreviewDoc + setPreviewDoc: this.props.setPreviewDoc, + setComputed: this.setComputed, + getField: this.getField, }; let colType = this.getColumnType(col); @@ -772,6 +773,81 @@ export class SchemaTable extends React.Component { } } + getField = (row: number, col?: number) => { + // const docs = DocListCast(this.props.Document[this.props.fieldKey]); + + let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + const docs = DocListCast(cdoc[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].heading; + 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}].heading]; + } + return ${script}`; + const compiled = CompileScript(script, { params: { this: Doc.name }, capturedVariables: { doc: this.props.Document, key: this.props.fieldKey }, typecheck: true, transformer: this.createTransformer(row, col) }); + if (compiled.compiled) { + doc[field] = new ComputedField(compiled); + return true; + } + return false; + } + 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)!)) -- cgit v1.2.3-70-g09d2 From 1353c41b9e7c2e2bca2aea7fe9f2450a4b017ebf Mon Sep 17 00:00:00 2001 From: Fawn Date: Sat, 27 Jul 2019 22:53:19 -0400 Subject: can drag doc field out of schema --- .../views/collections/CollectionSchemaCells.tsx | 29 +++++++++++++--------- 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index e00142c91..d9291826c 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -84,6 +84,11 @@ export class CollectionSchemaCell extends React.Component { @action onPointerDown = (e: React.PointerEvent): void => { this.props.changeFocusedCellByIndex(this.props.row, this.props.col); + this.props.setPreviewDoc(this.props.rowProps.original); + + let field = this.props.rowProps.original[this.props.rowProps.column.id!]; + let doc = FieldValue(Cast(field, Doc)); + if (typeof field === "object" && doc) this.props.setPreviewDoc(doc); } applyToDoc = (doc: Doc, row: number, col: number, run: (args?: { [name: string]: any }) => any) => { @@ -150,10 +155,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 = "collectionSchemaView-cellContainer doc-drag-over"; @@ -181,16 +186,16 @@ export class CollectionSchemaCell extends React.Component { let doc = FieldValue(Cast(field, Doc)); let fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc); - let docExpander = ( -
    - -
    - ); + // let docExpander = ( + //
    + // + //
    + // ); return ( -
    +
    -
    +
    { }} />
    - {fieldIsDoc ? docExpander : null} + {/* {fieldIsDoc ? docExpander : null} */}
    ); -- cgit v1.2.3-70-g09d2 From 160ca6c2673b96b8cfe9dfd5bd887a3637a1a45f Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sat, 27 Jul 2019 22:58:01 -0400 Subject: finisheddd --- src/client/views/nodes/FormattedTextBox.tsx | 42 +++++++++++++++++++---------- src/client/views/nodes/PDFBox.tsx | 2 -- src/client/views/pdf/PDFViewer.tsx | 30 ++++++++++++++++++--- src/client/views/pdf/Page.tsx | 3 ++- 4 files changed, 56 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 364dc1c83..f019868aa 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -8,7 +8,7 @@ import { keymap } from "prosemirror-keymap"; import { EditorState, Plugin, Transaction, Selection } from "prosemirror-state"; import { NodeType, Slice, Node, Fragment } from 'prosemirror-model'; import { EditorView } from "prosemirror-view"; -import { Doc, Opt } from "../../../new_fields/Doc"; +import { Doc, Opt, DocListCast } from "../../../new_fields/Doc"; import { Id, Copy } from '../../../new_fields/FieldSymbols'; import { List } from '../../../new_fields/List'; import { RichTextField } from "../../../new_fields/RichTextField"; @@ -302,28 +302,42 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe handlePaste = (view: EditorView, event: Event, slice: Slice): boolean => { let cbe = event as ClipboardEvent; let docId: string; + let regionId: string; if (!cbe.clipboardData) { return false; } let linkId: string; docId = cbe.clipboardData.getData("dash/pdfOrigin"); - if (!docId) { + regionId = cbe.clipboardData.getData("dash/pdfRegion"); + if (!docId || !regionId) { return false; } DocServer.GetRefField(docId).then(doc => { - if (!(doc instanceof Doc)) { - return; - } - let link = DocUtils.MakeLink(this.props.Document, doc); - if (link) { - cbe.clipboardData!.setData("dash/linkDoc", link[Id]); - linkId = link[Id]; - let frag = addMarkToFrag(slice.content); - slice = new Slice(frag, slice.openStart, slice.openEnd); - var tr = view.state.tr.replaceSelection(slice); - view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste")); - } + DocServer.GetRefField(regionId).then(region => { + if (!(doc instanceof Doc) || !(region instanceof Doc)) { + return; + } + + let annotations = DocListCast(region.annotations); + annotations.forEach(anno => anno.target = this.props.Document); + let fieldExtDoc = Doc.resolvedFieldDataDoc(doc, "data", "true"); + let targetAnnotations = DocListCast(fieldExtDoc.annotations); + if (targetAnnotations) { + targetAnnotations.push(region); + fieldExtDoc.annotations = new List(targetAnnotations); + } + + let link = DocUtils.MakeLink(this.props.Document, region); + if (link) { + cbe.clipboardData!.setData("dash/linkDoc", link[Id]); + linkId = link[Id]; + let frag = addMarkToFrag(slice.content); + slice = new Slice(frag, slice.openStart, slice.openEnd); + var tr = view.state.tr.replaceSelection(slice); + view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste")); + } + }); }); return true; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 72d835fce..f527c0595 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -34,7 +34,6 @@ export const handleBackspace = (e: React.KeyboardEvent) => { if (e.keyCode === K @observer export class PDFBox extends DocComponent(PdfDocument) { public static LayoutString() { return FieldView.LayoutString(PDFBox); } - public selectionText: string = ""; @observable private _alt = false; @observable private _scrollY: number = 0; @@ -82,7 +81,6 @@ export class PDFBox extends DocComponent(PdfDocumen private copy = (e: ClipboardEvent) => { if (this.props.active()) { - let text = this.selectionText; if (e.clipboardData) { e.clipboardData.setData("text/plain", text); e.clipboardData.setData("dash/pdfOrigin", this.props.Document[Id]); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index db2d49f0f..6fef8a4de 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -92,6 +92,7 @@ export class Viewer extends React.Component { // private _textContent: Pdfjs.TextContent[] = []; private _pdfFindController: any; private _searchString: string = ""; + private _selectionText: string = ""; constructor(props: IViewerProps) { super(props); @@ -102,6 +103,10 @@ export class Viewer extends React.Component { this._mainCont = React.createRef(); } + setSelectionText = (text: string) => { + this._selectionText = text; + } + componentDidUpdate = (prevProps: IViewerProps) => { if (this.scrollY !== prevProps.scrollY) { this.renderPages(); @@ -158,8 +163,8 @@ export class Viewer extends React.Component { this._dropDisposer = this._mainCont.current && DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } }); } - document.removeEventListener("paste", this.paste); - document.addEventListener("paste", this.paste); + document.removeEventListener("copy", this.copy); + document.addEventListener("copy", this.copy); } componentWillUnmount = () => { @@ -167,7 +172,24 @@ export class Viewer extends React.Component { this._annotationReactionDisposer && this._annotationReactionDisposer(); this._filterReactionDisposer && this._filterReactionDisposer(); this._dropDisposer && this._dropDisposer(); - document.removeEventListener("paste", this.paste); + document.removeEventListener("copy", this.copy); + } + + private copy = (e: ClipboardEvent) => { + if (this.props.parent.props.active()) { + let text = this._selectionText; + if (e.clipboardData) { + e.clipboardData.setData("text/plain", text); + e.clipboardData.setData("dash/pdfOrigin", this.props.parent.props.Document[Id]); + let annoDoc = this.makeAnnotationDocument(undefined, 0, "#0390fc"); + e.clipboardData.setData("dash/pdfRegion", annoDoc[Id]); + e.preventDefault(); + } + } + // let targetAnnotations = DocListCast(this.props.parent.fieldExtensionDoc.annotations); + // if (targetAnnotations) { + // targetAnnotations.push(destDoc); + // } } paste = (e: ClipboardEvent) => { @@ -281,7 +303,6 @@ export class Viewer extends React.Component { let targetAnnotations = DocListCast(this.props.parent.fieldExtensionDoc.annotations); if (targetAnnotations) { targetAnnotations.push(destDoc); - this.props.parent.fieldExtensionDoc.annotations = new List(targetAnnotations); } else { this.props.parent.fieldExtensionDoc.annotations = new List([destDoc]); @@ -315,6 +336,7 @@ export class Viewer extends React.Component { this._isPage[page] = "page"; this._visibleElements[page] = ( void; makeAnnotationDocuments: (doc: Doc | undefined, scale: number, color: string, linkTo: boolean) => Doc; getScrollFromPage: (page: number) => number; + setSelectionText: (text: string) => void; } @observer @@ -392,7 +393,7 @@ export default class Page extends React.Component { } let text = selRange.extractContents().textContent; if (text) { - this.props.parent.selectionText = text; + this.props.setSelectionText(text); } // clear selection if (sel.empty) { // Chrome -- cgit v1.2.3-70-g09d2 From cf4da743cc82357b4018184d026a07f715f61ad5 Mon Sep 17 00:00:00 2001 From: Fawn Date: Sat, 27 Jul 2019 23:38:29 -0400 Subject: minor fixes to doc field draggign on schema cell --- src/client/views/collections/CollectionSchemaCells.tsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index d9291826c..f1e013edd 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -155,9 +155,15 @@ export class CollectionSchemaCell extends React.Component { addDocTab: this.props.addDocTab, }; + let field = props.Document[props.fieldKey]; + let doc = FieldValue(Cast(field, Doc)); + let fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc); + 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); + if (fieldIsDoc) { + 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)) { @@ -168,7 +174,6 @@ export class CollectionSchemaCell extends React.Component { dragRef!.current!.className = "collectionSchemaView-cellContainer"; }; - let field = props.Document[props.fieldKey]; let contents: any = "incorrect type"; if (type === undefined) contents = ; if (type === "number") contents = typeof field === "number" ? NumCast(field) : "--" + typeof field + "--"; @@ -184,8 +189,7 @@ export class CollectionSchemaCell extends React.Component { if (this.props.isFocused && this.props.isEditable) className += " focused"; if (this.props.isFocused && !this.props.isEditable) className += " inactive"; - let doc = FieldValue(Cast(field, Doc)); - let fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc); + // let docExpander = ( //
    // @@ -194,8 +198,8 @@ export class CollectionSchemaCell extends React.Component { return (
    -
    -
    +
    +
    Date: Sun, 28 Jul 2019 00:20:16 -0400 Subject: Added PrefetchProxy class --- src/new_fields/Proxy.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/new_fields/Proxy.ts b/src/new_fields/Proxy.ts index 14f08814e..b3e8d6467 100644 --- a/src/new_fields/Proxy.ts +++ b/src/new_fields/Proxy.ts @@ -6,6 +6,7 @@ import { DocServer } from "../client/DocServer"; import { RefField } from "./RefField"; import { ObjectField } from "./ObjectField"; import { Id, Copy, ToScriptString } from "./FieldSymbols"; +import { scriptingGlobal } from "../client/util/Scripting"; @Deserializable("proxy") export class ProxyField extends ObjectField { @@ -66,3 +67,12 @@ export class ProxyField extends ObjectField { return this.promise as any; } } + +function prefetchValue(proxy: PrefetchProxy) { + return proxy.value() as any; +} + +@scriptingGlobal +@Deserializable("prefetch_proxy", prefetchValue) +export class PrefetchProxy extends ProxyField { +} -- cgit v1.2.3-70-g09d2 From 239e8b0a354b68a700181af3c4e9deb77fc8c009 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sun, 28 Jul 2019 14:22:41 -0400 Subject: schema view now uses child docs --- src/client/views/collections/CollectionSchemaView.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 42843ad30..7da5665f3 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -202,7 +202,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. @@ -252,7 +252,7 @@ export interface SchemaTableProps { dataDoc?: Doc; PanelHeight: () => number; PanelWidth: () => number; - // childDocs: Doc[]; + childDocs: Doc[]; CollectionView: CollectionView | CollectionPDFView | CollectionVideoView; ContainingCollectionView: Opt; fieldKey: string; @@ -299,8 +299,9 @@ export class SchemaTable extends React.Component { let focusedCol = this._focusedCell.col; let isEditable = !this._headerIsEditing;// && this.props.isSelected(); - let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - let children = DocListCast(cdoc[this.props.fieldKey]); + // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + // let children = DocListCast(cdoc[this.props.fieldKey]); + let children = this.props.childDocs; if (children.reduce((found, doc) => found || doc.type === "collection", false)) { columns.push( -- cgit v1.2.3-70-g09d2 From 6b50ec0f33c30b6100165d50811f4fa72657b66e Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sun, 28 Jul 2019 14:41:45 -0400 Subject: schemas now actually use view specs --- .../views/collections/CollectionSchemaView.tsx | 25 ++++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 7da5665f3..77ed2d8dc 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -425,7 +425,8 @@ export class SchemaTable extends React.Component { tableRemoveDoc = (document: Doc): boolean => { let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + let children = this.props.childDocs; if (children.indexOf(document) !== -1) { children.splice(children.indexOf(document), 1); return true; @@ -520,7 +521,8 @@ export class SchemaTable extends React.Component { this.changeFocusedCellByDirection(direction); let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + let children = this.props.childDocs; const pdoc = FieldValue(children[this._focusedCell.row]); pdoc && this.props.setPreviewDoc(pdoc); } @@ -529,7 +531,8 @@ 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), []); + // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + let children = this.props.childDocs; switch (direction) { case "tab": if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === children.length) { @@ -560,7 +563,7 @@ export class SchemaTable extends React.Component { @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), []); + // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); this._focusedCell = { row: row, col: col }; this.props.setFocused(this.props.Document); @@ -571,7 +574,8 @@ export class SchemaTable extends React.Component { createRow = () => { let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + let children = this.props.childDocs; let newDoc = Docs.Create.TextDocument({ width: 100, height: 30 }); let proto = Doc.GetProto(newDoc); @@ -683,7 +687,8 @@ export class SchemaTable extends React.Component { } get documentKeys() { - const docs = DocListCast(this.props.Document[this.props.fieldKey]); + // const docs = DocListCast(this.props.Document[this.props.fieldKey]); + let docs = this.props.childDocs; 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 @@ -712,7 +717,8 @@ export class SchemaTable extends React.Component { get reactTable() { let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - let children = DocListCast(cdoc[this.props.fieldKey]); + // let children = DocListCast(cdoc[this.props.fieldKey]); + let children = this.props.childDocs; let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; let hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false); @@ -758,7 +764,7 @@ export class SchemaTable extends React.Component { 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 => { + this.props.childDocs.map(doc => { csv += self.columns.reduce((val, col) => val + (doc[col.heading] ? doc[col.heading]!.toString() : "0") + ",", ""); csv = csv.substr(0, csv.length - 1) + "\n"; }); @@ -778,7 +784,8 @@ export class SchemaTable extends React.Component { // const docs = DocListCast(this.props.Document[this.props.fieldKey]); let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - const docs = DocListCast(cdoc[this.props.fieldKey]); + // const docs = DocListCast(cdoc[this.props.fieldKey]); + let docs = this.props.childDocs; row = row % docs.length; while (row < 0) row += docs.length; -- cgit v1.2.3-70-g09d2 From 902709d953fd00deb124862519fa00215cadc26f Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sun, 28 Jul 2019 15:12:59 -0400 Subject: view specs now correctly handles (not) contains --- src/client/views/collections/KeyRestrictionRow.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/KeyRestrictionRow.tsx b/src/client/views/collections/KeyRestrictionRow.tsx index f292557b5..4f3d82114 100644 --- a/src/client/views/collections/KeyRestrictionRow.tsx +++ b/src/client/views/collections/KeyRestrictionRow.tsx @@ -18,10 +18,12 @@ export default class KeyRestrictionRow extends React.Component - {this.props.parent.getDisplayDoc(layoutDoc, d, dxf, width)} -
    ; - } else { - let dref = React.createRef(); - let dxf = () => this.getDocTransform(layoutDoc, dref.current!); - this.props.parent._docXfs.push({ dxf: dxf, width: width, height: height }); - let rowHgtPcnt = height(); - let rowSpan = Math.ceil((height() + parent.gridGap) / parent.gridGap); - let divStyle = parent.singleColumn ? { width: width(), marginTop: i === 0 ? 0 : parent.gridGap, height: `${rowHgtPcnt}` } : { gridRowEnd: `span ${rowSpan}` }; - return
    - {this.props.parent.getDisplayDoc(layoutDoc, d, dxf, width)} -
    ; - } + let dref = React.createRef(); + // if (uniqueHeadings.length > 0) { + let dxf = () => this.getDocTransform(pair.layout, dref.current!); + this.props.parent._docXfs.push({ dxf: dxf, width: width, height: height }); + // } + // else { + // //have to add the height of all previous single column sections or the doc decorations will be in the wrong place. + // let dxf = () => this.getDocTransform(layoutDoc, i, width()); + // this.props.parent._docXfs.push({ dxf: dxf, width: width, height: height }); + // } + let rowHgtPcnt = height(); + let rowSpan = Math.ceil((height() + parent.gridGap) / parent.gridGap); + let style = parent.singleColumn ? { width: width(), marginTop: i === 0 ? 0 : parent.gridGap, height: `${rowHgtPcnt}` } : { gridRowEnd: `span ${rowSpan}` }; + return
    + {this.props.parent.getDisplayDoc(pair.layout, pair.data, dxf, width)} +
    ; + // } else { + // let dref = React.createRef(); + // let dxf = () => this.getDocTransform(layoutDoc, dref.current!); + // this.props.parent._docXfs.push({ dxf: dxf, width: width, height: height }); + // let rowHgtPcnt = height(); + // let rowSpan = Math.ceil((height() + parent.gridGap) / parent.gridGap); + // let divStyle = parent.singleColumn ? { width: width(), marginTop: i === 0 ? 0 : parent.gridGap, height: `${rowHgtPcnt}` } : { gridRowEnd: `span ${rowSpan}` }; + // return
    + // {this.props.parent.getDisplayDoc(layoutDoc, d, dxf, width)} + //
    ; + // } }); } - getSingleDocTransform(doc: Doc, ind: number, width: number) { - let localY = this.props.parent.filteredChildren.reduce((height, d, i) => - height + (i < ind ? this.props.parent.getDocHeight(Doc.expandTemplateLayout(d, this.props.parent.props.DataDoc)) + this.props.parent.gridGap : 0), this.props.parent.yMargin); - let translate = this.props.parent.props.ScreenToLocalTransform().inverse().transformPoint((this.props.parent.props.PanelWidth() - width) / 2, localY); - return this.offsetTransform(doc, translate[0], translate[1]); - } - - offsetTransform(doc: Doc, translateX: number, translateY: number) { - let outerXf = Utils.GetScreenTransform(this.props.parent._masonryGridRef!); - let offset = this.props.parent.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); - return this.props.parent.props.ScreenToLocalTransform().translate(offset[0], offset[1]).scale(NumCast(doc.width, 1) / this.props.parent.columnWidth); - } - getDocTransform(doc: Doc, dref: HTMLDivElement) { let { scale, translateX, translateY } = Utils.GetScreenTransform(dref); let outerXf = Utils.GetScreenTransform(this.props.parent._masonryGridRef!); let offset = this.props.parent.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); - return this.props.parent.props.ScreenToLocalTransform().translate(offset[0], offset[1]).scale(NumCast(doc.width, 1) / this.props.parent.columnWidth); + return this.props.parent.props.ScreenToLocalTransform(). + translate(offset[0], offset[1] - (this.props.parent.chromeCollapsed ? 0 : 100)). + scale(NumCast(doc.width, 1) / this.props.parent.columnWidth); } getValue = (value: string): any => { -- cgit v1.2.3-70-g09d2 From cb2347347c8d9d2a0f1531479c73ecbcb3008128 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sun, 28 Jul 2019 16:51:07 -0400 Subject: padding on text boxes --- src/client/views/nodes/FormattedTextBox.scss | 70 ++++++++++++++++------------ 1 file changed, 39 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index d3045ae2f..a24abb32e 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -1,34 +1,37 @@ @import "../globalCssVariables"; + .ProseMirror { - width: 100%; - height: 100%; - min-height: 100%; - font-family: $serif; + width: 100%; + height: 100%; + min-height: 100%; + font-family: $serif; } .ProseMirror:focus { - outline: none !important; + outline: none !important; } -.formattedTextBox-cont-scroll, .formattedTextBox-cont-hidden { - background: inherit; - padding: 0; - border-width: 0px; - border-radius: inherit; - border-color: $intermediate-color; - box-sizing: border-box; - background-color: inherit; - border-style: solid; - overflow-y: auto; - overflow-x: hidden; - color: initial; - height: 100%; - pointer-events: all; +.formattedTextBox-cont-scroll, +.formattedTextBox-cont-hidden { + background: inherit; + padding: 0; + border-width: 0px; + border-radius: inherit; + border-color: $intermediate-color; + box-sizing: border-box; + background-color: inherit; + border-style: solid; + overflow-y: auto; + overflow-x: hidden; + color: initial; + height: 100%; + pointer-events: all; } .formattedTextBox-cont-hidden { pointer-events: none; } + .formattedTextBox-inner-rounded { height: calc(100% - 25px); width: calc(100% - 40px); @@ -38,23 +41,28 @@ left: 20; } +.formattedTextBox-inner-rounded div, +.formattedTextBox-inner div { + padding: 10px; +} + .menuicon { - display: inline-block; - border-right: 1px solid rgba(0, 0, 0, 0.2); - color: #888; - line-height: 1; - padding: 0 7px; - margin: 1px; - cursor: pointer; - text-align: center; - min-width: 1.4em; + display: inline-block; + border-right: 1px solid rgba(0, 0, 0, 0.2); + color: #888; + line-height: 1; + padding: 0 7px; + margin: 1px; + cursor: pointer; + text-align: center; + min-width: 1.4em; } .strong, .heading { - font-weight: bold; + font-weight: bold; } .em { - font-style: italic; -} + font-style: italic; +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 1acc70319c038cd8566035fbc5fec5c0b441b083 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sun, 28 Jul 2019 17:11:06 -0400 Subject: undoable prop for context menu commands --- src/client/views/ContextMenuItem.tsx | 9 ++++++++- src/client/views/collections/CollectionStackingView.tsx | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index badb9cf19..4ff0fe388 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -4,12 +4,14 @@ import { observer } from "mobx-react"; import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; import { faAngleRight } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { UndoManager } from "../util/UndoManager"; library.add(faAngleRight); export interface OriginalMenuProps { description: string; event: () => void; + undoable?: boolean; icon: IconProp; //maybe should be optional (icon?) closeMenu?: () => void; } @@ -37,7 +39,12 @@ export class ContextMenuItem extends React.Component) => { if ("event" in this.props) { + let batch: UndoManager.Batch | undefined; + if (this.props.undoable !== false) { + batch = UndoManager.StartBatch(`Context menu event: ${this.props.description}`); + } this.props.event(); + batch && batch.end(); this.props.closeMenu && this.props.closeMenu(); } } @@ -94,7 +101,7 @@ export class ContextMenuItem extends React.Component {this.props.description} - +
    {submenu}
    diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index dab03f052..e166c145d 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -119,7 +119,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { children(docs: Doc[]) { this._docXfs.length = 0; return docs.map((d, i) => { - let pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d) + let pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d); let width = () => d.nativeWidth && !BoolCast(d.ignoreAspect) ? Math.min(pair.layout[WidthSym](), this.columnWidth) : this.columnWidth; let height = () => this.getDocHeight(pair.layout); let dref = React.createRef(); -- cgit v1.2.3-70-g09d2 From 7098f381f3f93e77880f3589427c81e61a5ee25a Mon Sep 17 00:00:00 2001 From: Fawn Date: Sun, 28 Jul 2019 17:56:59 -0400 Subject: started fixing schemaheaderfield bug --- src/client/views/collections/CollectionSchemaView.scss | 9 +++++++-- src/client/views/collections/CollectionSchemaView.tsx | 13 +++++++++++-- src/new_fields/SchemaHeaderField.ts | 1 + 3 files changed, 19 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index e0de76247..2e0ec20db 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -161,7 +161,7 @@ } .rt-tr { - width: 100%; + // width: 100%; min-height: 30px; // height: $MAX_ROW_HEIGHT; } @@ -195,6 +195,11 @@ height: 100%; } } + + .rt-resizer { + width: 20px; + right: -10px; + } } .documentView-node-topmost { @@ -312,7 +317,7 @@ button.add-column { height: 100%; background-color: white; - &.row-focused { + &.row-focused .rt-tr { background-color: rgb(255, 246, 246);//$light-color-secondary; } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 42843ad30..31de4e146 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -287,9 +287,10 @@ export class SchemaTable extends React.Component { @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() { + console.log("columns"); return Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField), []); } - set columns(columns: SchemaHeaderField[]) { this.props.Document.schemaColumns = new List(columns); } + set columns(columns: SchemaHeaderField[]) { console.log("setting columns"); 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.heading.toUpperCase() === key.toUpperCase()) === -1); @@ -404,7 +405,8 @@ export class SchemaTable extends React.Component { super(props); // convert old schema columns (list of strings) into new schema columns (list of schema header fields) let oldSchemaColumns = Cast(this.props.Document.schemaColumns, listSpec("string"), []); - if (oldSchemaColumns && oldSchemaColumns.length) { + if (oldSchemaColumns && oldSchemaColumns.length && typeof oldSchemaColumns[0] !== "object") { + console.log("REMAKING COLUMNs"); let newSchemaColumns = oldSchemaColumns.map(i => typeof i === "string" ? new SchemaHeaderField(i) : i); this.props.Document.schemaColumns = new List(newSchemaColumns); } @@ -583,6 +585,7 @@ export class SchemaTable extends React.Component { let index = 0; let found = this.columns.findIndex(col => col.heading.toUpperCase() === "New field".toUpperCase()) > -1; if (!found) { + console.log("create column found"); this.columns.push(new SchemaHeaderField("New field")); return; } @@ -590,13 +593,16 @@ export class SchemaTable extends React.Component { index++; found = this.columns.findIndex(col => col.heading.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1; } + console.log("create column new"); this.columns.push(new SchemaHeaderField("New field (" + index + ")")); } @action deleteColumn = (key: string) => { + console.log("deleting columnnn"); let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField)); if (list === undefined) { + console.log("delete column"); this.props.Document.schemaColumns = list = new List([]); } else { const index = list.map(c => c.heading).indexOf(key); @@ -608,10 +614,13 @@ export class SchemaTable extends React.Component { @action changeColumns = (oldKey: string, newKey: string, addNew: boolean) => { + console.log("changingin columnsdfhs"); let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField)); if (list === undefined) { + console.log("change columns new"); this.props.Document.schemaColumns = list = new List([new SchemaHeaderField(newKey)]); } else { + console.log("change column"); if (addNew) { this.columns.push(new SchemaHeaderField(newKey)); } else { diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts index a6df31e81..84d9ae20e 100644 --- a/src/new_fields/SchemaHeaderField.ts +++ b/src/new_fields/SchemaHeaderField.ts @@ -49,6 +49,7 @@ export class SchemaHeaderField extends ObjectField { type: number; constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType) { + console.log("CREATING SCHEMA HEADER FIELD"); super(); this.heading = heading; -- cgit v1.2.3-70-g09d2 From be1e6e967a60f49eec1cb1d404912b0736812323 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 28 Jul 2019 17:59:00 -0400 Subject: Added ability to capture documents in button scripts --- src/client/views/ScriptBox.tsx | 23 +++++++- src/client/views/ScriptingRepl.tsx | 31 +---------- .../views/collections/CollectionDockingView.tsx | 1 - src/client/views/nodes/ButtonBox.tsx | 6 +- src/client/views/nodes/DocumentIcon.tsx | 65 ++++++++++++++++++++++ 5 files changed, 94 insertions(+), 32 deletions(-) create mode 100644 src/client/views/nodes/DocumentIcon.tsx (limited to 'src') diff --git a/src/client/views/ScriptBox.tsx b/src/client/views/ScriptBox.tsx index fa236c2da..d073945e5 100644 --- a/src/client/views/ScriptBox.tsx +++ b/src/client/views/ScriptBox.tsx @@ -3,11 +3,15 @@ import { observer } from "mobx-react"; import { observable, action } from "mobx"; import "./ScriptBox.scss"; +import { OverlayView } from "./OverlayView"; +import { DocumentIconContainer } from "./nodes/DocumentIcon"; +import { Opt } from "../../new_fields/Doc"; export interface ScriptBoxProps { onSave: (text: string, onError: (error: string) => void) => void; onCancel?: () => void; initialText?: string; + showDocumentIcons?: boolean; } @observer @@ -30,14 +34,31 @@ export class ScriptBox extends React.Component { console.log(error); } + overlayDisposer?: () => void; + onFocus = () => { + if (this.overlayDisposer) { + this.overlayDisposer(); + } + this.overlayDisposer = OverlayView.Instance.addElement(, { x: 0, y: 0 }); + } + + onBlur = () => { + this.overlayDisposer && this.overlayDisposer(); + } + render() { + let onFocus: Opt<() => void> = undefined, onBlur: Opt<() => void> = undefined; + if (this.props.showDocumentIcons) { + onFocus = this.onFocus; + onBlur = this.onBlur; + } return (
    - +
    ); } diff --git a/src/client/views/ScriptingRepl.tsx b/src/client/views/ScriptingRepl.tsx index 0cff145b6..e05195ca0 100644 --- a/src/client/views/ScriptingRepl.tsx +++ b/src/client/views/ScriptingRepl.tsx @@ -4,40 +4,15 @@ import { observable, action } from 'mobx'; import './ScriptingRepl.scss'; import { Scripting, CompileScript, ts, Transformer } from '../util/Scripting'; import { DocumentManager } from '../util/DocumentManager'; -import { DocumentView } from './nodes/DocumentView'; import { OverlayView } from './OverlayView'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { library } from '@fortawesome/fontawesome-svg-core'; import { faCaretDown, faCaretRight } from '@fortawesome/free-solid-svg-icons'; +import { DocumentIconContainer } from './nodes/DocumentIcon'; library.add(faCaretDown); library.add(faCaretRight); -@observer -export class DocumentIcon extends React.Component<{ view: DocumentView, index: number }> { - render() { - const view = this.props.view; - const transform = view.props.ScreenToLocalTransform().scale(view.props.ContentScaling()).inverse(); - const { x, y, width, height } = transform.transformBounds(0, 0, view.props.PanelWidth(), view.props.PanelHeight()); - - return ( -
    -

    ${this.props.index}

    -
    - ); - } -} - -@observer -export class DocumentIconContainer extends React.Component { - render() { - return DocumentManager.Instance.DocumentViews.map((dv, i) => ); - } -} - @observer export class ScriptingObjectDisplay extends React.Component<{ scrollToBottom: () => void, value: { [key: string]: any }, name?: string }> { @observable collapsed = true; @@ -129,7 +104,7 @@ export class ScriptingRepl extends React.Component { if (ts.isParameter(node.parent)) { // delete knownVars[node.text]; } else if (isntPropAccess && isntPropAssign && !(node.text in knownVars) && !(node.text in globalThis)) { - const match = node.text.match(/\$([0-9]+)/); + const match = node.text.match(/\d([0-9]+)/); if (match) { const m = parseInt(match[1]); usedDocuments.push(m); @@ -153,7 +128,7 @@ export class ScriptingRepl extends React.Component { switch (e.key) { case "Enter": { const docGlobals: { [name: string]: any } = {}; - DocumentManager.Instance.DocumentViews.forEach((dv, i) => docGlobals[`$${i}`] = dv.props.Document); + DocumentManager.Instance.DocumentViews.forEach((dv, i) => docGlobals[`d${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 }); if (!script.compiled) { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 0865058be..1859ebee7 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -577,7 +577,6 @@ export class DockedFrameRenderer extends React.Component { return (null); } let resolvedDataDoc = this._document.layout instanceof Doc ? this._document : this._dataDoc; - console.log("pw = " + this.panelWidth() + "," + this.panelHeight() + " " + this.contentScaling()); return (Butt const script = CompileScript(text, { params: { this: Doc.name }, typecheck: false, - editable: true + editable: true, + transformer: DocumentIconContainer.getTransformer() }); if (!script.compiled) { onError(script.errors.map(error => error.messageText).join("\n")); @@ -59,7 +61,7 @@ export class ButtonBox extends DocComponent(Butt } this.Document.onClick = new ScriptField(script); overlayDisposer(); - }} />; + }} showDocumentIcons />; overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, { x: 400, y: 200, width: 500, height: 400, title: `${this.Document.title || ""} OnClick` }); } }); diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx new file mode 100644 index 000000000..f56f5e829 --- /dev/null +++ b/src/client/views/nodes/DocumentIcon.tsx @@ -0,0 +1,65 @@ +import { observer } from "mobx-react"; +import * as React from "react"; +import { DocumentView } from "./DocumentView"; +import { DocumentManager } from "../../util/DocumentManager"; +import { Transformer, Scripting, ts } from "../../util/Scripting"; +import { Field } from "../../../new_fields/Doc"; + +@observer +export class DocumentIcon extends React.Component<{ view: DocumentView, index: number }> { + render() { + const view = this.props.view; + const transform = view.props.ScreenToLocalTransform().scale(view.props.ContentScaling()).inverse(); + const { x, y, width, height } = transform.transformBounds(0, 0, view.props.PanelWidth(), view.props.PanelHeight()); + + return ( +
    +

    d{this.props.index}

    +
    + ); + } +} + +@observer +export class DocumentIconContainer extends React.Component { + public static getTransformer(): Transformer { + const usedDocuments = new Set(); + return { + transformer: 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; + const isntParameter = !ts.isParameter(node.parent); + if (isntPropAccess && isntPropAssign && isntParameter && !(node.text in globalThis)) { + const match = node.text.match(/d([0-9]+)/); + if (match) { + const m = parseInt(match[1]); + usedDocuments.add(m); + } + } + } + + return node; + } + return ts.visitNode(root, visit); + }; + }, + getVars() { + const docs = DocumentManager.Instance.DocumentViews; + const capturedVariables: { [name: string]: Field } = {}; + usedDocuments.forEach(index => capturedVariables[`d${index}`] = docs[index].props.Document); + return { capturedVariables }; + } + }; + } + render() { + return DocumentManager.Instance.DocumentViews.map((dv, i) => ); + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 3f54bd76fd806ac3e7b2380fe45e71549ea65955 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sun, 28 Jul 2019 18:02:58 -0400 Subject: only enter wlil trigger the editable view in schema cells --- src/client/views/collections/CollectionSchemaCells.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index f1e013edd..194765880 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -25,6 +25,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faExpand } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; +import { KeyCodes } from "../../northstar/utils/KeyCodes"; library.add(faExpand); @@ -66,7 +67,7 @@ export class CollectionSchemaCell extends React.Component { @action onKeyDown = (e: KeyboardEvent): void => { - if (this.props.isFocused && this.props.isEditable) { + if (this.props.isFocused && this.props.isEditable && e.keyCode === KeyCodes.ENTER) { document.removeEventListener("keydown", this.onKeyDown); this._isEditing = true; this.props.setIsEditing(true); -- cgit v1.2.3-70-g09d2 From 6d6ceb1f0c0ebc18fd52783baca6da28b3f75ec0 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sun, 28 Jul 2019 18:20:28 -0400 Subject: ctrl backpsace now works when editing text --- src/client/views/GlobalKeyHandler.ts | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index d52c05b2f..e31b44514 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -133,6 +133,13 @@ export default class KeyManager { } MainView.Instance.mainFreeform && CollectionDockingView.Instance.CloseRightSplit(MainView.Instance.mainFreeform); break; + case "backspace": + if (document.activeElement) { + if (document.activeElement.tagName === "INPUT" || document.activeElement.tagName === "TEXTAREA") { + return { stopPropagation: false, preventDefault: false }; + } + } + break; case "f": MainView.Instance.isSearchVisible = !MainView.Instance.isSearchVisible; break; -- cgit v1.2.3-70-g09d2 From 22955412de5b0c5634343cfc45bbe09a91bbbdde Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sun, 28 Jul 2019 18:20:44 -0400 Subject: improvements to view specs box --- .../views/collections/CollectionViewChromes.tsx | 27 +++++++++++++++++----- src/client/views/collections/KeyRestrictionRow.tsx | 3 +++ 2 files changed, 24 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 044d5336a..9c751c4df 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -31,7 +31,7 @@ let stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation(); export class CollectionViewBaseChrome extends React.Component { @observable private _viewSpecsOpen: boolean = false; @observable private _dateWithinValue: string = ""; - @observable private _dateValue: Date = new Date(); + @observable private _dateValue: Date | string = ""; @observable private _keyRestrictions: [JSX.Element, string][] = []; @observable private _collapsed: boolean = false; @computed private get filterValue() { return Cast(this.props.CollectionView.props.Document.viewSpecScript, ScriptField); } @@ -124,10 +124,24 @@ export class CollectionViewBaseChrome extends React.Component= ${lowerBound.valueOf()} && (doc.creationDate as any).date <= ${upperBound.valueOf()})`; - let fullScript = `return ${dateRestrictionScript} && ${keyRestrictionScript}`; + let dateRestrictionScript = ""; + if (this._dateValue instanceof Date) { + let lowerBound = new Date(this._dateValue.getFullYear() - yearOffset, this._dateValue.getMonth() - monthOffset, this._dateValue.getDate() - dayOffset); + let upperBound = new Date(this._dateValue.getFullYear() + yearOffset, this._dateValue.getMonth() + monthOffset, this._dateValue.getDate() + dayOffset + 1); + dateRestrictionScript = `((doc.creationDate as any).date >= ${lowerBound.valueOf()} && (doc.creationDate as any).date <= ${upperBound.valueOf()})`; + } + else { + let createdDate = new Date(this._dateValue); + if (!isNaN(createdDate.getTime())) { + let lowerBound = new Date(createdDate.getFullYear() - yearOffset, createdDate.getMonth() - monthOffset, createdDate.getDate() - dayOffset); + let upperBound = new Date(createdDate.getFullYear() + yearOffset, createdDate.getMonth() + monthOffset, createdDate.getDate() + dayOffset + 1); + dateRestrictionScript = `((doc.creationDate as any).date >= ${lowerBound.valueOf()} && (doc.creationDate as any).date <= ${upperBound.valueOf()})`; + } + } + let fullScript = dateRestrictionScript.length || keyRestrictionScript.length ? dateRestrictionScript.length ? + `return ${dateRestrictionScript} ${keyRestrictionScript.length ? "&&" : ""} ${keyRestrictionScript}` : + `return ${keyRestrictionScript} ${dateRestrictionScript.length ? "&&" : ""} ${dateRestrictionScript}` : + "return true"; let compiled = CompileScript(fullScript, { params: { doc: Doc.name } }); if (compiled.compiled) { this.props.CollectionView.props.Document.viewSpecScript = new ScriptField(compiled); @@ -221,7 +235,8 @@ export class CollectionViewBaseChrome extends React.Component runInAction(() => this._dateValue = e.target.value)} onPointerDown={this.openDatePicker} placeholder="Value" />
    diff --git a/src/client/views/collections/KeyRestrictionRow.tsx b/src/client/views/collections/KeyRestrictionRow.tsx index 4f3d82114..9c3c9c07c 100644 --- a/src/client/views/collections/KeyRestrictionRow.tsx +++ b/src/client/views/collections/KeyRestrictionRow.tsx @@ -26,6 +26,9 @@ export default class KeyRestrictionRow extends React.Component Date: Sun, 28 Jul 2019 18:27:52 -0400 Subject: fixed moving and deleting documents --- .../views/collections/CollectionSchemaView.tsx | 23 +++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 77ed2d8dc..8436b22a4 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -289,6 +289,7 @@ export class SchemaTable extends React.Component { @computed get columns() { return Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField), []); } + @computed get childDocs() { return this.props.childDocs; } set columns(columns: SchemaHeaderField[]) { this.props.Document.schemaColumns = new List(columns); } @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } @computed get tableColumns(): Column[] { @@ -301,7 +302,7 @@ export class SchemaTable extends React.Component { // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; // let children = DocListCast(cdoc[this.props.fieldKey]); - let children = this.props.childDocs; + let children = this.childDocs; if (children.reduce((found, doc) => found || doc.type === "collection", false)) { columns.push( @@ -425,8 +426,8 @@ export class SchemaTable extends React.Component { tableRemoveDoc = (document: Doc): boolean => { let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); - let children = this.props.childDocs; + let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + // let children = this.childDocs; if (children.indexOf(document) !== -1) { children.splice(children.indexOf(document), 1); return true; @@ -522,7 +523,7 @@ export class SchemaTable extends React.Component { let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); - let children = this.props.childDocs; + let children = this.childDocs; const pdoc = FieldValue(children[this._focusedCell.row]); pdoc && this.props.setPreviewDoc(pdoc); } @@ -532,7 +533,7 @@ export class SchemaTable extends React.Component { changeFocusedCellByDirection = (direction: string): void => { let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); - let children = this.props.childDocs; + let children = this.childDocs; switch (direction) { case "tab": if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === children.length) { @@ -575,7 +576,7 @@ export class SchemaTable extends React.Component { createRow = () => { let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); - let children = this.props.childDocs; + let children = this.childDocs; let newDoc = Docs.Create.TextDocument({ width: 100, height: 30 }); let proto = Doc.GetProto(newDoc); @@ -688,7 +689,7 @@ export class SchemaTable extends React.Component { get documentKeys() { // const docs = DocListCast(this.props.Document[this.props.fieldKey]); - let docs = this.props.childDocs; + let docs = this.childDocs; 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 @@ -718,7 +719,7 @@ export class SchemaTable extends React.Component { let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; // let children = DocListCast(cdoc[this.props.fieldKey]); - let children = this.props.childDocs; + let children = this.childDocs; let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; let hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false); @@ -730,7 +731,7 @@ export class SchemaTable extends React.Component { return { let csv: string = this.columns.reduce((val, col) => val + col + ",", ""); csv = csv.substr(0, csv.length - 1) + "\n"; let self = this; - this.props.childDocs.map(doc => { + this.childDocs.map(doc => { csv += self.columns.reduce((val, col) => val + (doc[col.heading] ? doc[col.heading]!.toString() : "0") + ",", ""); csv = csv.substr(0, csv.length - 1) + "\n"; }); @@ -785,7 +786,7 @@ export class SchemaTable extends React.Component { let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; // const docs = DocListCast(cdoc[this.props.fieldKey]); - let docs = this.props.childDocs; + let docs = this.childDocs; row = row % docs.length; while (row < 0) row += docs.length; -- cgit v1.2.3-70-g09d2 From 99ab639f4de270eb1f7b497b6386cb8d5a1f7e5f Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sun, 28 Jul 2019 20:31:11 -0400 Subject: fixed next and prev annotation scorlling --- src/client/views/nodes/PDFBox.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index f527c0595..4973340df 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -167,7 +167,7 @@ export class PDFBox extends DocComponent(PdfDocumen scrollTo(y: number) { if (this._mainCont.current) { - this._mainCont.current.scrollTo({ top: y, behavior: "auto" }); + this._mainCont.current.scrollTo({ top: Math.max(y - (this._mainCont.current!.offsetHeight / 2), 0), behavior: "auto" }); } } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 6fef8a4de..5eb02a6da 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -212,7 +212,7 @@ export class Viewer extends React.Component { scrollTo(y: number) { if (this.props.mainCont.current) { - this.props.parent.scrollTo(y - this.props.mainCont.current.clientHeight); + this.props.parent.scrollTo(y); } } -- cgit v1.2.3-70-g09d2 From 27cafb6eebd1c6229c3377187a5c0043db25ba0a Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sun, 28 Jul 2019 22:58:32 -0400 Subject: templating fixes, context menu undo streamlining --- src/.DS_Store | Bin 6148 -> 6148 bytes src/client/documents/Documents.ts | 5 ++--- src/client/views/ContextMenuItem.tsx | 4 ++-- src/client/views/collections/CollectionTreeView.tsx | 10 +++++----- src/client/views/collections/CollectionView.tsx | 14 +++++++------- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/KeyValueBox.tsx | 17 ++++++++++++----- src/scraping/buxton/scraper.py | 4 ++-- 8 files changed, 31 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/.DS_Store b/src/.DS_Store index 071dafa1e..c544bc837 100644 Binary files a/src/.DS_Store and b/src/.DS_Store differ diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 3859f2255..30a114e33 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -163,7 +163,6 @@ export namespace Docs { [DocumentType.LINKDOC, { data: new List(), layout: { view: EmptyBox }, - options: {} }], [DocumentType.BUTTON, { layout: { view: ButtonBox }, @@ -414,8 +413,8 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Tree }); } - export function StackingDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Stacking }); + export function StackingDocument(documents: Array, options: DocumentOptions, viewType: CollectionViewType = CollectionViewType.Stacking) { + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: viewType }); } export function ButtonDocument(options?: DocumentOptions) { diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 4ff0fe388..a1787e78f 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -37,13 +37,13 @@ export class ContextMenuItem extends React.Component) => { + handleEvent = async (e: React.MouseEvent) => { if ("event" in this.props) { let batch: UndoManager.Batch | undefined; if (this.props.undoable !== false) { batch = UndoManager.StartBatch(`Context menu event: ${this.props.description}`); } - this.props.event(); + await this.props.event(); batch && batch.end(); this.props.closeMenu && this.props.closeMenu(); } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 1c7fe4bee..3eab109bc 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -237,10 +237,10 @@ class TreeView extends React.Component { if (DocumentManager.Instance.getDocumentViews(this.dataDoc).length) { ContextMenu.Instance.addItem({ description: "Focus", event: () => DocumentManager.Instance.getDocumentViews(this.dataDoc).map(view => view.props.focus(this.props.document, true)), icon: "camera" }); } - ContextMenu.Instance.addItem({ description: "Delete Item", event: undoBatch(() => this.props.deleteDoc(this.props.document)), icon: "trash-alt" }); + ContextMenu.Instance.addItem({ description: "Delete Item", event: () => this.props.deleteDoc(this.props.document), icon: "trash-alt" }); } else { - ContextMenu.Instance.addItem({ description: "Open as Workspace", event: undoBatch(() => MainView.Instance.openWorkspace(this.dataDoc)), icon: "caret-square-right" }); - ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.props.deleteDoc(this.props.document)), icon: "trash-alt" }); + ContextMenu.Instance.addItem({ description: "Open as Workspace", event: () => MainView.Instance.openWorkspace(this.dataDoc), icon: "caret-square-right" }); + ContextMenu.Instance.addItem({ description: "Delete Workspace", event: () => this.props.deleteDoc(this.props.document), icon: "trash-alt" }); } ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { let kvp = Docs.Create.KVPDocument(this.props.document, { width: 300, height: 300 }); this.props.addDocTab(kvp, this.props.dataDoc ? this.props.dataDoc : kvp, "onRight"); }, icon: "layer-group" }); ContextMenu.Instance.displayMenu(e.pageX > 156 ? e.pageX - 156 : 0, e.pageY - 15); @@ -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()), icon: "plus" }); - ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.remove(this.props.Document)), icon: "minus" }); + ContextMenu.Instance.addItem({ description: "Create Workspace", event: () => MainView.Instance.createNewWorkspace(), icon: "plus" }); + ContextMenu.Instance.addItem({ description: "Delete Workspace", event: () => 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 b4f29755c..e3f5d1eb8 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -53,14 +53,14 @@ export class CollectionView extends React.Component { onContextMenu = (e: React.MouseEvent): void => { if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 let subItems: ContextMenuProps[] = []; - subItems.push({ description: "Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Freeform), icon: "signature" }); + subItems.push({ description: "Freeform", event: () => this.props.Document.viewType = CollectionViewType.Freeform, icon: "signature" }); if (CollectionBaseView.InSafeMode()) { - ContextMenu.Instance.addItem({ description: "Test Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Invalid), icon: "project-diagram" }); + ContextMenu.Instance.addItem({ description: "Test Freeform", event: () => this.props.Document.viewType = CollectionViewType.Invalid, icon: "project-diagram" }); } - 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: "ellipsis-v" }); - subItems.push({ description: "Masonry", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Masonry), icon: "columns" }); + subItems.push({ description: "Schema", event: () => this.props.Document.viewType = CollectionViewType.Schema, icon: "th-list" }); + subItems.push({ description: "Treeview", event: () => this.props.Document.viewType = CollectionViewType.Tree, icon: "tree" }); + subItems.push({ description: "Stacking", event: () => this.props.Document.viewType = CollectionViewType.Stacking, icon: "ellipsis-v" }); + subItems.push({ description: "Masonry", event: () => this.props.Document.viewType = CollectionViewType.Masonry, icon: "columns" }); switch (this.props.Document.viewType) { case CollectionViewType.Freeform: { subItems.push({ description: "Custom", icon: "fingerprint", event: CollectionFreeFormView.AddCustomLayout(this.props.Document, this.props.fieldKey) }); @@ -68,7 +68,7 @@ export class CollectionView extends React.Component { } } 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" }); + ContextMenu.Instance.addItem({ description: "Apply Template", event: () => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" }); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d07fc7f80..a6152e1b7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -496,7 +496,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { let layoutItems: ContextMenuProps[] = []; layoutItems.push({ description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`, - event: undoBatch(async () => this.props.Document.fitToBox = !this.fitToBox), + event: async () => this.props.Document.fitToBox = !this.fitToBox, icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" }); layoutItems.push({ diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 77824b4ff..b0fcc4202 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -20,6 +20,7 @@ import { RichTextField } from "../../../new_fields/RichTextField"; import { ImageField } from "../../../new_fields/URLField"; import { SelectionManager } from "../../util/SelectionManager"; import { listSpec } from "../../../new_fields/Schema"; +import { CollectionViewType } from "../collections/CollectionBaseView"; export type KVPScript = { script: CompiledScript; @@ -195,6 +196,9 @@ export class KeyValueBox extends React.Component { } let fieldTemplate = await this.inferType(sourceDoc[metaKey], metaKey); + if (!fieldTemplate) { + return; + } let previousViewType = fieldTemplate.viewType; Doc.MakeTemplate(fieldTemplate, metaKey, Doc.GetProto(parentStackingDoc)); previousViewType && (fieldTemplate.viewType = previousViewType); @@ -211,14 +215,17 @@ export class KeyValueBox extends React.Component { return Docs.Create.StackingDocument([], options); } let first = await Cast(data[0], Doc); - if (!first) { + if (!first || !first.data) { return Docs.Create.StackingDocument([], options); } - switch (first.type) { - case "image": - return Docs.Create.StackingDocument([], options); - case "text": + switch (first.data.constructor) { + case RichTextField: return Docs.Create.TreeDocument([], options); + case ImageField: + return Docs.Create.StackingDocument([], options, CollectionViewType.Masonry); + default: + console.log(`Template for ${first.data.constructor} not supported!`); + return undefined; } } else if (data instanceof ImageField) { return Docs.Create.ImageDocument("https://image.flaticon.com/icons/png/512/23/23765.png", options); diff --git a/src/scraping/buxton/scraper.py b/src/scraping/buxton/scraper.py index 182b22a1a..1ff0e3b31 100644 --- a/src/scraping/buxton/scraper.py +++ b/src/scraping/buxton/scraper.py @@ -139,7 +139,7 @@ def write_text_doc(content): data_doc = { "_id": data_doc_guid, "fields": { - "proto": protofy("commonImportProto"), + "proto": protofy("textProto"), "data": { "Data": '{"doc":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + content + '"}]}]},"selection":{"type":"text","anchor":1,"head":1}' + '}', "__type": "RichTextField" @@ -235,7 +235,7 @@ def parse_document(file_name: str): count += 1 view_guids.append(write_image(pure_name, image)) copyfile(dir_path + "/" + image, dir_path + - "/" + image.replace(".", "_o.", 1)) + "/" + image.replace(".", "_o.", 1)) os.rename(dir_path + "/" + image, dir_path + "/" + image.replace(".", "_m.", 1)) print(f"extracted {count} images...") -- cgit v1.2.3-70-g09d2 From e7ea2028f54787d6c92fb22b789f17b7268d3793 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 29 Jul 2019 08:37:53 -0400 Subject: some layout adjustments for stacking views --- src/client/views/collections/CollectionStackingView.tsx | 4 ++-- .../views/collections/CollectionStackingViewFieldColumn.tsx | 10 +++++----- src/client/views/nodes/DocumentView.tsx | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index b96b1f8c8..f647da8f0 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -140,12 +140,12 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { previewScript={undefined}> ; } - getDocHeight(d: Doc) { + getDocHeight(d: Doc, columnScale: number = 1) { let nw = NumCast(d.nativeWidth); let nh = NumCast(d.nativeHeight); if (!BoolCast(d.ignoreAspect) && nw && nh) { let aspect = nw && nh ? nh / nw : 1; - let wid = Math.min(d[WidthSym](), this.columnWidth); + let wid = Math.min(d[WidthSym](), this.columnWidth / columnScale); return wid * aspect; } return d[HeightSym](); diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index cf5bc451a..387e189e7 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -74,8 +74,8 @@ export class CollectionStackingViewFieldColumn extends React.Component headings.indexOf(i) === idx); let pair = Doc.GetLayoutDataDocPair(parent.props.Document, parent.props.DataDoc, parent.props.fieldKey, d); - let width = () => (d.nativeWidth && !BoolCast(d.ignoreAspect) ? Math.min(pair.layout[WidthSym](), parent.columnWidth) : parent.columnWidth) / (uniqueHeadings.length + 1); - let height = () => parent.getDocHeight(pair.layout); + let width = () => (d.nativeWidth && !BoolCast(d.ignoreAspect) ? Math.min(pair.layout[WidthSym](), parent.columnWidth / (uniqueHeadings.length + 1)) : parent.columnWidth / (uniqueHeadings.length + 1));/// (uniqueHeadings.length + 1); + let height = () => parent.getDocHeight(pair.layout, uniqueHeadings.length + 1);// / (d.nativeWidth && !BoolCast(d.ignoreAspect) ? uniqueHeadings.length + 1 : 1); let dref = React.createRef(); // if (uniqueHeadings.length > 0) { let dxf = () => this.getDocTransform(pair.layout, dref.current!); @@ -88,7 +88,7 @@ export class CollectionStackingViewFieldColumn extends React.Component {this.props.parent.getDisplayDoc(pair.layout, pair.data, dxf, width)}
    ; @@ -267,8 +267,8 @@ export class CollectionStackingViewFieldColumn extends React.Component(Docu transformOrigin: "top left", transform: `scale(${1 / this.props.ContentScaling()})` }}> Date: Mon, 29 Jul 2019 11:51:17 -0400 Subject: fixed schema view vertical overflow scrolling + collection chrome collapsing --- src/client/views/collections/CollectionSchemaView.scss | 3 ++- src/client/views/collections/CollectionSchemaView.tsx | 4 ++-- src/client/views/collections/CollectionViewChromes.scss | 2 +- src/client/views/collections/CollectionViewChromes.tsx | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 3c3708a30..c1f53f159 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -8,7 +8,8 @@ box-sizing: border-box; // position: absolute; width: 100%; - height: calc(100% - 70px); + transition: height .5s; + height: 100%; // overflow: hidden; // overflow-x: scroll; // border: none; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 7bd0b5965..7463429e0 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -237,8 +237,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { // 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.onDrop(e, {})} ref={this.createTarget}> +
    this.onDrop(e, {})} ref={this.createTarget}> {this.schemaTable} {this.dividerDragger} {!this.previewWidth() ? (null) : this.previewPanel} diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index 6525f3b07..f9f3ce473 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -4,7 +4,7 @@ .collectionViewChrome-cont { position: relative; z-index: 9001; - transition: top .5s; + transition: margin-top .5s; background: lightslategray; padding: 10px; diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 9c751c4df..2bffe3cc0 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -185,11 +185,11 @@ export class CollectionViewBaseChrome extends React.Component +
    -- cgit v1.2.3-70-g09d2 From 5aa5bded4e90ec29bccac221ec115f5cd2f30791 Mon Sep 17 00:00:00 2001 From: Fawn Date: Mon, 29 Jul 2019 11:58:25 -0400 Subject: reverted schematable childdocs back since tables won't rerender on change otherwise --- .../views/collections/CollectionSchemaView.tsx | 60 +++++++++++----------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 7463429e0..bb620cd63 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -290,10 +290,10 @@ export class SchemaTable extends React.Component { console.log("columns"); return Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField), []); } - @computed get childDocs() { - let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - return DocListCast(doc[this.props.fieldKey]); - } + // @computed get childDocs() { + // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + // return DocListCast(doc[this.props.fieldKey]); + // } set columns(columns: SchemaHeaderField[]) { this.props.Document.schemaColumns = new List(columns); } @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } @computed get tableColumns(): Column[] { @@ -304,9 +304,8 @@ export class SchemaTable extends React.Component { let focusedCol = this._focusedCell.col; let isEditable = !this._headerIsEditing;// && this.props.isSelected(); - // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - // let children = DocListCast(cdoc[this.props.fieldKey]); - let children = this.childDocs; + 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( @@ -430,9 +429,9 @@ export class SchemaTable extends React.Component { } tableRemoveDoc = (document: Doc): boolean => { - // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); - let children = this.childDocs; + let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + // let children = this.childDocs; if (children.indexOf(document) !== -1) { children.splice(children.indexOf(document), 1); return true; @@ -526,9 +525,9 @@ export class SchemaTable extends React.Component { 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); - // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); - let children = this.childDocs; + let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + // let children = this.childDocs; const pdoc = FieldValue(children[this._focusedCell.row]); pdoc && this.props.setPreviewDoc(pdoc); } @@ -536,9 +535,9 @@ 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), []); - let children = this.childDocs; + let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + // let children = this.childDocs; switch (direction) { case "tab": if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === children.length) { @@ -579,9 +578,9 @@ export class SchemaTable extends React.Component { } createRow = () => { - // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); - let children = this.childDocs; + let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + // let children = this.childDocs; let newDoc = Docs.Create.TextDocument({ width: 100, height: 30 }); let proto = Doc.GetProto(newDoc); @@ -700,8 +699,9 @@ export class SchemaTable extends React.Component { } get documentKeys() { - // const docs = DocListCast(this.props.Document[this.props.fieldKey]); - let docs = this.childDocs; + const docs = DocListCast(this.props.Document[this.props.fieldKey]); + + // let docs = this.childDocs; 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 @@ -729,9 +729,9 @@ 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 children = this.childDocs; + let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + let children = DocListCast(cdoc[this.props.fieldKey]); + // let children = this.childDocs; let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; let hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false); @@ -743,7 +743,7 @@ export class SchemaTable extends React.Component { return { let csv: string = this.columns.reduce((val, col) => val + col + ",", ""); csv = csv.substr(0, csv.length - 1) + "\n"; let self = this; - this.childDocs.map(doc => { + let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + let children = DocListCast(cdoc[this.props.fieldKey]); + children.map(doc => { csv += self.columns.reduce((val, col) => val + (doc[col.heading] ? doc[col.heading]!.toString() : "0") + ",", ""); csv = csv.substr(0, csv.length - 1) + "\n"; }); @@ -796,9 +798,9 @@ export class SchemaTable extends React.Component { getField = (row: number, col?: number) => { // const docs = DocListCast(this.props.Document[this.props.fieldKey]); - // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - // const docs = DocListCast(cdoc[this.props.fieldKey]); - let docs = this.childDocs; + let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + const docs = DocListCast(cdoc[this.props.fieldKey]); + // let docs = this.childDocs; row = row % docs.length; while (row < 0) row += docs.length; -- cgit v1.2.3-70-g09d2 From c361a566b2a3ce134bbb7e5906c23492c7012c7b Mon Sep 17 00:00:00 2001 From: Fawn Date: Mon, 29 Jul 2019 13:00:59 -0400 Subject: really fixed childdocs on schema --- .../views/collections/CollectionSchemaHeaders.tsx | 39 +++++++++++ .../views/collections/CollectionSchemaView.scss | 13 ++++ .../views/collections/CollectionSchemaView.tsx | 75 ++++++++++++---------- src/new_fields/SchemaHeaderField.ts | 4 +- 4 files changed, 96 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index 9fc28eafa..387107c55 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -129,6 +129,10 @@ export class CollectionSchemaColumnMenu extends React.Component } } + changeColumnColor = (color: string): void => { + + } + renderTypes = () => { if (this.props.typeConst) return <>; return ( @@ -168,6 +172,40 @@ export class CollectionSchemaColumnMenu extends React.Component ); } + renderColors = () => { + return ( +
    + +
    + this.changeColumnColor("#FFB4E8")} /> + + this.changeColumnColor("#b28dff")} /> + + this.changeColumnColor("#afcbff")} /> + + this.changeColumnColor("#f3ffe3")} /> + + this.changeColumnColor("#ffc9de")} /> + + this.changeColumnColor("#f1efeb")} /> + +
    +
    + ); + } + renderContent = () => { return (
    @@ -187,6 +225,7 @@ export class CollectionSchemaColumnMenu extends React.Component <> {this.renderTypes()} {this.renderSorting()} + {this.renderColors()}
    diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index c1f53f159..053d6452c 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -311,6 +311,19 @@ button.add-column { border-radius: 20px; } } + + .columnMenu-colors { + + + input[type="radio"] { + display: none; + } + + .columnMenu-colorPicker { + width: 20px; + height: 20px; + } + } } .collectionSchema-row { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index bb620cd63..53dd9523b 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -202,7 +202,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { Document={this.props.Document} 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} @@ -252,7 +252,7 @@ export interface SchemaTableProps { dataDoc?: Doc; PanelHeight: () => number; PanelWidth: () => number; - // childDocs: Doc[]; + childDocs?: Doc[]; CollectionView: CollectionView | CollectionPDFView | CollectionVideoView; ContainingCollectionView: Opt; fieldKey: string; @@ -290,10 +290,16 @@ export class SchemaTable extends React.Component { console.log("columns"); return Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField), []); } - // @computed get childDocs() { - // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - // return DocListCast(doc[this.props.fieldKey]); - // } + @computed get childDocs() { + if (this.props.childDocs) return this.props.childDocs; + + let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + return DocListCast(doc[this.props.fieldKey]); + } + set childDocs(docs: Doc[]) { + let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + doc[this.props.fieldKey] = new List(docs); + } set columns(columns: SchemaHeaderField[]) { this.props.Document.schemaColumns = new List(columns); } @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } @computed get tableColumns(): Column[] { @@ -304,8 +310,9 @@ export class SchemaTable extends React.Component { let focusedCol = this._focusedCell.col; let isEditable = !this._headerIsEditing;// && this.props.isSelected(); - let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - let children = DocListCast(cdoc[this.props.fieldKey]); + // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + // let children = DocListCast(cdoc[this.props.fieldKey]); + let children = this.childDocs; if (children.reduce((found, doc) => found || doc.type === "collection", false)) { columns.push( @@ -411,7 +418,7 @@ export class SchemaTable extends React.Component { let oldSchemaColumns = Cast(this.props.Document.schemaColumns, listSpec("string"), []); if (oldSchemaColumns && oldSchemaColumns.length && typeof oldSchemaColumns[0] !== "object") { console.log("REMAKING COLUMNs"); - let newSchemaColumns = oldSchemaColumns.map(i => typeof i === "string" ? new SchemaHeaderField(i) : i); + let newSchemaColumns = oldSchemaColumns.map(i => typeof i === "string" ? new SchemaHeaderField(i, "#f1efeb") : i); this.props.Document.schemaColumns = new List(newSchemaColumns); } } @@ -429,11 +436,12 @@ export class SchemaTable extends React.Component { } tableRemoveDoc = (document: Doc): boolean => { - let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); - // let children = this.childDocs; + // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + let children = this.childDocs; if (children.indexOf(document) !== -1) { children.splice(children.indexOf(document), 1); + this.childDocs = children; return true; } return false; @@ -525,9 +533,9 @@ export class SchemaTable extends React.Component { 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); - let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); - // let children = this.childDocs; + // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + let children = this.childDocs; const pdoc = FieldValue(children[this._focusedCell.row]); pdoc && this.props.setPreviewDoc(pdoc); } @@ -535,9 +543,9 @@ 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), []); - // let children = this.childDocs; + // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + let children = this.childDocs; switch (direction) { case "tab": if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === children.length) { @@ -567,7 +575,7 @@ export class SchemaTable extends React.Component { @action changeFocusedCellByIndex = (row: number, col: number): void => { - let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + // 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 }; @@ -578,14 +586,15 @@ export class SchemaTable extends React.Component { } createRow = () => { - let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); - // let children = this.childDocs; + // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []); + let children = this.childDocs; let newDoc = Docs.Create.TextDocument({ width: 100, height: 30 }); let proto = Doc.GetProto(newDoc); proto.title = ""; children.push(newDoc); + this.childDocs = children; } @action @@ -594,7 +603,7 @@ export class SchemaTable extends React.Component { let found = this.columns.findIndex(col => col.heading.toUpperCase() === "New field".toUpperCase()) > -1; if (!found) { console.log("create column found"); - this.columns.push(new SchemaHeaderField("New field")); + this.columns.push(new SchemaHeaderField("New field", "#f1efeb")); return; } while (found) { @@ -602,7 +611,7 @@ export class SchemaTable extends React.Component { found = this.columns.findIndex(col => col.heading.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1; } console.log("create column new"); - this.columns.push(new SchemaHeaderField("New field (" + index + ")")); + this.columns.push(new SchemaHeaderField("New field (" + index + ")", "#f1efeb")); } @action @@ -626,15 +635,15 @@ export class SchemaTable extends React.Component { let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField)); if (list === undefined) { console.log("change columns new"); - this.props.Document.schemaColumns = list = new List([new SchemaHeaderField(newKey)]); + this.props.Document.schemaColumns = list = new List([new SchemaHeaderField(newKey, "f1efeb")]); } else { console.log("change column"); if (addNew) { - this.columns.push(new SchemaHeaderField(newKey)); + this.columns.push(new SchemaHeaderField(newKey, "f1efeb")); } else { const index = list.map(c => c.heading).indexOf(oldKey); if (index > -1) { - list[index] = new SchemaHeaderField(newKey); + list[index] = new SchemaHeaderField(newKey, "f1efeb"); } } } @@ -729,9 +738,9 @@ 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 children = this.childDocs; + // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + // let children = DocListCast(cdoc[this.props.fieldKey]); + let children = this.childDocs; let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; let hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false); @@ -758,7 +767,7 @@ export class SchemaTable extends React.Component { row => { if (row.original.type === "collection") { // let childDocs = DocListCast(row.original[this.props.fieldKey]); - return
    ; + return
    ; } } : undefined} @@ -778,8 +787,8 @@ export class SchemaTable extends React.Component { csv = csv.substr(0, csv.length - 1) + "\n"; let self = this; let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - let children = DocListCast(cdoc[this.props.fieldKey]); - children.map(doc => { + // let children = DocListCast(cdoc[this.props.fieldKey]); + this.childDocs.map(doc => { csv += self.columns.reduce((val, col) => val + (doc[col.heading] ? doc[col.heading]!.toString() : "0") + ",", ""); csv = csv.substr(0, csv.length - 1) + "\n"; }); diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts index 84d9ae20e..d124a3907 100644 --- a/src/new_fields/SchemaHeaderField.ts +++ b/src/new_fields/SchemaHeaderField.ts @@ -48,12 +48,12 @@ export class SchemaHeaderField extends ObjectField { color: string; type: number; - constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType) { + constructor(heading: string = "", color?: string, type?: ColumnType) { console.log("CREATING SCHEMA HEADER FIELD"); super(); this.heading = heading; - this.color = color; + this.color = color === "" || color === undefined ? RandomPastel() : color; if (type) { this.type = type; } -- cgit v1.2.3-70-g09d2 From 1c5c84c91742ff7822194519f536338bf96e6453 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Mon, 29 Jul 2019 13:58:36 -0400 Subject: fixed things to chrome and stacking view styling --- .../views/collections/CollectionSchemaView.scss | 27 +++++++++++++--------- .../views/collections/CollectionSchemaView.tsx | 1 - .../views/collections/CollectionStackingView.scss | 1 + .../views/collections/CollectionStackingView.tsx | 2 +- .../CollectionStackingViewFieldColumn.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 21 ++++++++++++----- .../views/collections/CollectionViewChromes.scss | 5 ++-- 7 files changed, 37 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index e0de76247..2697b482f 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -6,14 +6,14 @@ border-style: solid; border-radius: $border-radius; box-sizing: border-box; - // position: absolute; + position: absolute; + top: 0; width: 100%; height: calc(100% - 50px); // overflow: hidden; // overflow-x: scroll; // border: none; overflow: hidden; - transition: top 0.5s; // .collectionSchemaView-cellContents { // height: $MAX_ROW_HEIGHT; @@ -78,7 +78,7 @@ overflow-x: auto; height: 100%; display: -webkit-inline-box; - direction: ltr; + direction: ltr; } .rt-thead { @@ -122,7 +122,7 @@ font-size: 13px; text-align: center; background-color: $light-color-secondary; - + &:last-child { overflow: visible; } @@ -147,7 +147,7 @@ // &:nth-child(even) { // background-color: $light-color; // } - + // &:nth-child(odd) { // background-color: $light-color-secondary; // } @@ -175,7 +175,7 @@ padding: 0; font-size: 13px; text-align: center; - + // white-space: normal; .imageBox-cont { @@ -207,18 +207,19 @@ background: $light-color; } -.collectionSchema-col{ +.collectionSchema-col { height: 100%; .collectionSchema-col-wrapper { &.col-before { border-left: 2px solid red; } + &.col-after { border-right: 2px solid red; } } -} +} .collectionSchemaView-header { @@ -285,7 +286,7 @@ button.add-column { background-color: $light-color; border: 1px solid $light-color-secondary; padding: 2px 3px; - + &:not(:last-child) { border-top: 0; } @@ -313,7 +314,7 @@ button.add-column { background-color: white; &.row-focused { - background-color: rgb(255, 246, 246);//$light-color-secondary; + background-color: rgb(255, 246, 246); //$light-color-secondary; } &.row-wrapped { @@ -358,9 +359,11 @@ button.add-column { &.row-above { border-top: 1px solid red; } + &.row-below { border-bottom: 1px solid red; } + &.row-inside { border: 1px solid red; } @@ -461,7 +464,9 @@ button.add-column { .rt-table { overflow-x: hidden; // todo; this shouldnt be like this :(( overflow-y: visible; - } // TODO fix + } + + // TODO fix .row-dragger { background-color: rgb(252, 252, 252); diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 8436b22a4..8fe66a949 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -72,7 +72,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @observable private _node: HTMLDivElement | null = null; @observable private _focusedTable: Doc = this.props.Document; - @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(); } diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 9dbe4ccb8..004b57eff 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -5,6 +5,7 @@ width: 100%; position: absolute; display: flex; + top: 0; overflow-y: auto; flex-wrap: wrap; transition: top .5s; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index f647da8f0..287c8a461 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -278,7 +278,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { }; // let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); return ( -
    e.stopPropagation()} > {/* {sectionFilter as boolean ? [ ["width > height", this.filteredChildren.filter(f => f[WidthSym]() >= 1 + f[HeightSym]())], diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 387e189e7..c45b0c60a 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -266,7 +266,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { @observable private _collapsed = false; + private _reactionDisposer: IReactionDisposer | undefined; + 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); - } + this._reactionDisposer = reaction(() => StrCast(this.props.Document.chromeStatus), + () => { + // 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); + } + }); + } + + componentWillUnmount = () => { + this._reactionDisposer && this._reactionDisposer(); } private SubViewHelper = (type: CollectionViewType, renderProps: CollectionRenderProps) => { diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index 6525f3b07..731333ff5 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -3,16 +3,17 @@ .collectionViewChrome-cont { position: relative; + opacity: 0.9; z-index: 9001; transition: top .5s; - background: lightslategray; + background: lightgrey; padding: 10px; .collectionViewChrome { display: grid; grid-template-columns: 1fr auto; padding-bottom: 10px; - border-bottom: .5px solid lightgrey; + border-bottom: .5px solid rgb(180, 180, 180); .collectionViewBaseChrome { display: flex; -- cgit v1.2.3-70-g09d2 From b6591b8403e83d836d3d74ce43739c5fc4a7d671 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 29 Jul 2019 14:08:31 -0400 Subject: Made extension docs be prefetched --- src/new_fields/Doc.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index da4f459e2..59314783b 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -12,6 +12,7 @@ import { scriptingGlobal } from "../client/util/Scripting"; import { List } from "./List"; import { DocumentType } from "../client/documents/Documents"; import { ComputedField } from "./ScriptField"; +import { PrefetchProxy } from "./Proxy"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -348,7 +349,7 @@ export namespace Doc { while (proto && !Doc.IsPrototype(proto)) { proto = proto.proto; } - (proto ? proto : doc)[fieldKey + "_ext"] = docExtensionForField; + (proto ? proto : doc)[fieldKey + "_ext"] = new PrefetchProxy(docExtensionForField); }, 0); } else if (doc instanceof Doc) { // backward compatibility -- add fields for docs that don't have them already docExtensionForField.extendsDoc === undefined && setTimeout(() => docExtensionForField.extendsDoc = doc, 0); -- cgit v1.2.3-70-g09d2 From bb607ecb02a7ecb8fe782d60e10ebf5bdedd790b Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 29 Jul 2019 14:08:46 -0400 Subject: Fixed bad headers crashing cors proxy on server --- src/server/index.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/index.ts b/src/server/index.ts index 40c0e7981..adf218be6 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -437,8 +437,22 @@ app.post(RouteStore.forgot, postForgot); app.get(RouteStore.reset, getReset); app.post(RouteStore.reset, postReset); -app.use(RouteStore.corsProxy, (req, res) => - req.pipe(request(decodeURIComponent(req.url.substring(1)))).pipe(res)); +const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/; +app.use(RouteStore.corsProxy, (req, res) => { + req.pipe(request(decodeURIComponent(req.url.substring(1)))).on("response", res => { + const headers = Object.keys(res.headers); + headers.forEach(headerName => { + const header = res.headers[headerName]; + if (Array.isArray(header)) { + res.headers[headerName] = header.filter(h => !headerCharRegex.test(h)); + } else if (header) { + if (headerCharRegex.test(header as any)) { + delete res.headers[headerName]; + } + } + }); + }).pipe(res); +}); app.get(RouteStore.delete, (req, res) => { if (release) { -- cgit v1.2.3-70-g09d2 From 5fff8155b3102e76feb718c4f67c6e85050aab6e Mon Sep 17 00:00:00 2001 From: yipstanley Date: Mon, 29 Jul 2019 14:50:43 -0400 Subject: stacking view background color to inherit --- src/client/views/collections/CollectionStackingViewFieldColumn.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index c45b0c60a..30177ebd7 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -34,7 +34,7 @@ interface CSVFieldColumnProps { @observer export class CollectionStackingViewFieldColumn extends React.Component { - @observable private _background = "white"; + @observable private _background = "inherit"; private _dropRef: HTMLDivElement | null = null; private dropDisposer?: DragManager.DragDropDisposer; @@ -158,7 +158,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { - this._background = "white"; + this._background = "inherit"; } @action -- cgit v1.2.3-70-g09d2 From 93df48fe22f4152878e3a74e0366668fbbab895e Mon Sep 17 00:00:00 2001 From: yipstanley Date: Mon, 29 Jul 2019 14:51:50 -0400 Subject: fixed document decorations when chrome expanded on stacking view --- src/client/views/collections/CollectionStackingViewFieldColumn.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 30177ebd7..aa86d9a54 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -111,7 +111,7 @@ export class CollectionStackingViewFieldColumn extends React.Component Date: Mon, 29 Jul 2019 14:56:05 -0400 Subject: + ADD / ADD GROUP does not show if chromeStatus is disabled --- src/client/views/collections/CollectionStackingView.tsx | 2 +- .../views/collections/CollectionStackingViewFieldColumn.tsx | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 287c8a461..85aa322a2 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -287,7 +287,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc). map(section => this.section(section[0], section[1])) : this.section(undefined, this.filteredChildren)} - {this.props.Document.sectionFilter ? + {(this.props.Document.sectionFilter && this.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
    diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index c45b0c60a..6b94efb1c 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -279,10 +279,11 @@ export class CollectionStackingViewFieldColumn extends React.Component -
    - -
    + {(this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? +
    + +
    : null}
    ); } -- cgit v1.2.3-70-g09d2 From c19fc89ebbaec30ff284988b7234815d822bbe0a Mon Sep 17 00:00:00 2001 From: kimdahey Date: Mon, 29 Jul 2019 15:40:30 -0400 Subject: fixed column width not adjusting with omitted + ADD NEW / NEW GROUP --- src/client/views/collections/CollectionStackingView.tsx | 4 ++-- src/client/views/collections/CollectionStackingViewFieldColumn.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 85aa322a2..5e4d8bda5 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -287,9 +287,9 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc). map(section => this.section(section[0], section[1])) : this.section(undefined, this.filteredChildren)} - {(this.props.Document.sectionFilter && this.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? + {this.props.CollectionView.props.Document.chromeStatus !== 'disabled' ?
    + style={{ width: (this.columnWidth / (headings.length + (this.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0))) - 10, marginTop: 10 }}>
    : null}
    diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 6b94efb1c..9e39d5383 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -261,7 +261,7 @@ export class CollectionStackingViewFieldColumn extends React.Component : (null); for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth}px `; return ( -
    {headingView}
    {(this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
    + style={{ width: style.columnWidth / (uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0)) }}>
    : null}
    -- cgit v1.2.3-70-g09d2 From 6079237a6a18bf63d18a9f471baadc9b48d9f105 Mon Sep 17 00:00:00 2001 From: kimdahey Date: Mon, 29 Jul 2019 15:46:27 -0400 Subject: fixed column width not adjusting with omitted + ADD NEW / NEW GROUP --- src/client/views/collections/CollectionStackingViewFieldColumn.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 9e39d5383..7727a23c7 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -239,7 +239,7 @@ export class CollectionStackingViewFieldColumn extends React.Component + style={{ width: (style.columnWidth) / (uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0)) }}> {/* the default bucket (no key value) has a tooltip that describes what it is. Further, it does not have a color and cannot be deleted. */}
    Date: Mon, 29 Jul 2019 15:59:47 -0400 Subject: re-added in sectionFilter check --- src/client/views/collections/CollectionStackingView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 5e4d8bda5..6e1968774 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -287,7 +287,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc). map(section => this.section(section[0], section[1])) : this.section(undefined, this.filteredChildren)} - {this.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? + {(this.props.Document.sectionFilter && this.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
    -- cgit v1.2.3-70-g09d2 From a560acaf539c058a2918a12e5de5061cca4b19e2 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 29 Jul 2019 16:10:13 -0400 Subject: Bunch of fixes --- src/client/views/MainOverlayTextBox.tsx | 6 ++++-- src/client/views/collections/CollectionSchemaCells.tsx | 3 ++- src/client/views/nodes/DocumentView.tsx | 16 ++++++++++++---- src/client/views/nodes/FieldView.tsx | 2 ++ src/client/views/nodes/FormattedTextBox.tsx | 4 +++- src/client/views/nodes/ImageBox.tsx | 6 +++++- src/client/views/nodes/KeyValuePair.tsx | 3 ++- src/client/views/nodes/PDFBox.tsx | 14 -------------- 8 files changed, 30 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index 126efd11c..8e2d7be85 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -4,7 +4,7 @@ import "normalize.css"; import * as React from 'react'; import { Doc } from '../../new_fields/Doc'; import { BoolCast } from '../../new_fields/Types'; -import { emptyFunction, returnTrue, returnZero, Utils } from '../../Utils'; +import { emptyFunction, returnTrue, returnZero, Utils, returnOne } from '../../Utils'; import { DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; import { CollectionDockingView } from './collections/CollectionDockingView'; @@ -29,6 +29,7 @@ export class MainOverlayTextBox extends React.Component private _outerdiv: HTMLElement | null = null; private _textBox: FormattedTextBox | undefined; private _tooltip?: HTMLElement; + ChromeHeight?: () => number; @observable public TextDoc?: Doc; @observable public TextDataDoc?: Doc; @@ -49,6 +50,7 @@ export class MainOverlayTextBox extends React.Component (box?: FormattedTextBox) => { this._textBox = box; if (box) { + this.ChromeHeight = box.props.ChromeHeight; this.TextDoc = box.props.Document; this.TextDataDoc = box.props.DataDoc; let xf = () => { @@ -140,7 +142,7 @@ export class MainOverlayTextBox extends React.Component Document={FormattedTextBox.InputBoxOverlay.props.Document} DataDoc={FormattedTextBox.InputBoxOverlay.props.DataDoc} isSelected={returnTrue} select={emptyFunction} renderDepth={0} selectOnLoad={true} - ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue} + ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue} ContentScaling={returnOne} ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyFunction} addDocTab={this.addDocTab} outer_div={(tooltip: HTMLElement) => { this._tooltip = tooltip; this.updateTooltip(); }} />
    diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 194765880..fdf0896ac 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -115,7 +115,7 @@ export class CollectionSchemaCell extends React.Component { } } - private dropRef = (ele: HTMLElement) => { + private dropRef = (ele: HTMLElement | null) => { this._dropDisposer && this._dropDisposer(); if (ele) { this._dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); @@ -154,6 +154,7 @@ export class CollectionSchemaCell extends React.Component { PanelHeight: returnZero, PanelWidth: returnZero, addDocTab: this.props.addDocTab, + ContentScaling: returnOne }; let field = props.Document[props.fieldKey]; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index f101222ae..9f0945c6b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -99,6 +99,7 @@ export interface DocumentViewProps { zoomToScale: (scale: number) => void; getScale: () => number; animateBetweenIcon?: (iconPos: number[], startTime: number, maximizing: boolean) => void; + ChromeHeight?: () => number; } const schema = createSchema({ @@ -644,6 +645,7 @@ export class DocumentView extends DocComponent(Docu @computed get nativeHeight() { return this.Document.nativeHeight || 0; } @computed get contents() { return ((Docu DataDoc={this.dataDoc} />); } + chromeHeight = () => { + let showOverlays = this.props.showOverlays ? this.props.showOverlays(this.layoutDoc) : undefined; + let showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : StrCast(this.layoutDoc.showTitle); + return showTitle ? 25 : 0; + } + get layoutDoc() { // if this document's layout field contains a document (ie, a rendering template), then we will use that // to determine the render JSX string, otherwise the layout field should directly contain a JSX layout string. @@ -666,8 +674,8 @@ export class DocumentView extends DocComponent(Docu var nativeWidth = this.nativeWidth > 0 && !BoolCast(this.props.Document.ignoreAspect) ? `${this.nativeWidth}px` : "100%"; var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; let showOverlays = this.props.showOverlays ? this.props.showOverlays(this.layoutDoc) : undefined; - let showTitle = showOverlays && showOverlays.title !== "undefined" ? showOverlays.title : StrCast(this.layoutDoc.showTitle); - let showCaption = showOverlays && showOverlays.caption !== "undefined" ? showOverlays.caption : StrCast(this.layoutDoc.showCaption); + let showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : StrCast(this.layoutDoc.showTitle); + let showCaption = showOverlays && "caption" in showOverlays ? showOverlays.caption : StrCast(this.layoutDoc.showCaption); let templates = Cast(this.layoutDoc.templates, listSpec("string")); if (!showOverlays && templates instanceof List) { templates.map(str => { @@ -716,11 +724,11 @@ export class DocumentView extends DocComponent(Docu transformOrigin: "top left", transform: `scale(${1 / this.props.ContentScaling()})` }}> StrCast(this.layoutDoc[showTitle!])} + GetValue={() => StrCast((this.layoutDoc.isTemplate || !this.dataDoc ? this.layoutDoc : this.dataDoc)[showTitle!])} SetValue={(value: string) => (Doc.GetProto(this.layoutDoc)[showTitle!] = value) ? true : true} />
    diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index ffaee8042..da54ecc3a 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -48,6 +48,8 @@ export interface FieldViewProps { PanelHeight: () => number; setVideoBox?: (player: VideoBox) => void; setPdfBox?: (player: PDFBox) => void; + ContentScaling: () => number; + ChromeHeight?: () => number; } @observer diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index f019868aa..0f51ca2ce 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -35,6 +35,7 @@ import "./FormattedTextBox.scss"; import React = require("react"); import { DateField } from '../../../new_fields/DateField'; import { Utils } from '../../../Utils'; +import { MainOverlayTextBox } from '../MainOverlayTextBox'; library.add(faEdit); library.add(faSmile, faTextHeight); @@ -557,7 +558,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let nh = NumCast(this.dataDoc.nativeHeight, 0); let dh = NumCast(this.props.Document.height, 0); let sh = scrBounds.height; - this.props.Document.height = nh ? dh / nh * sh : sh; + const ChromeHeight = MainOverlayTextBox.Instance.ChromeHeight; + this.props.Document.height = (nh ? dh / nh * sh : sh) + (ChromeHeight ? ChromeHeight() : 0); this.dataDoc.nativeHeight = nh ? sh : undefined; } } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 29a76b0c8..82af4b4ca 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -96,7 +96,11 @@ export class ImageBox extends DocComponent(ImageD this.props.Document.width = drop.width; this.props.Document.height = drop.height; Doc.GetProto(this.props.Document).type = DocumentType.TEMPLATE; - this.props.Document.layout = temp; + if (this.props.DataDoc && this.props.DataDoc.layout === this.props.Document) { + this.props.DataDoc.layout = temp; + } else { + this.props.Document.layout = temp; + } e.stopPropagation(); } else if (de.mods === "AltKey" && /*this.dataDoc !== this.props.Document &&*/ drop.data instanceof ImageField) { Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new ImageField(drop.data.url); diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 064f3edcc..4abf87b9f 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -1,7 +1,7 @@ import { action, observable } from 'mobx'; import { observer } from "mobx-react"; import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app -import { emptyFunction, returnFalse, returnZero, returnTrue } from '../../../Utils'; +import { emptyFunction, returnFalse, returnZero, returnTrue, returnOne } from '../../../Utils'; import { CompileScript, CompiledScript, ScriptOptions } from "../../util/Scripting"; import { Transform } from '../../util/Transform'; import { EditableView } from "../EditableView"; @@ -70,6 +70,7 @@ export class KeyValuePair extends React.Component { PanelWidth: returnZero, PanelHeight: returnZero, addDocTab: returnZero, + ContentScaling: returnOne }; let contents = ; // let fieldKey = Object.keys(props.Document).indexOf(props.fieldKey) !== -1 ? props.fieldKey : "(" + props.fieldKey + ")"; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 4973340df..fa072aecf 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -69,24 +69,10 @@ export class PDFBox extends DocComponent(PdfDocumen componentDidMount() { if (this.props.setPdfBox) this.props.setPdfBox(this); - - document.removeEventListener("copy", this.copy); - document.addEventListener("copy", this.copy); } componentWillUnmount() { this._reactionDisposer && this._reactionDisposer(); - document.removeEventListener("copy", this.copy); - } - - private copy = (e: ClipboardEvent) => { - if (this.props.active()) { - if (e.clipboardData) { - e.clipboardData.setData("text/plain", text); - e.clipboardData.setData("dash/pdfOrigin", this.props.Document[Id]); - e.preventDefault(); - } - } } public GetPage() { -- cgit v1.2.3-70-g09d2 From d87020047c1953b212257236a25036df3903dd47 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Mon, 29 Jul 2019 16:20:20 -0400 Subject: chrome default to collapsed --- src/client/documents/Documents.ts | 11 ++++++----- src/client/views/collections/CollectionView.tsx | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 18709499a..d1b3071ed 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -82,6 +82,7 @@ export interface DocumentOptions { backgroundColor?: string; dropAction?: dropActionType; backgroundLayout?: string; + chromeStatus?: string; curPage?: number; documentText?: string; borderRounding?: string; @@ -403,23 +404,23 @@ export namespace Docs { } export function FreeformDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Freeform }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Freeform }); } export function SchemaDocument(schemaColumns: SchemaHeaderField[], documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema }); } export function TreeDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Tree }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Tree }); } export function StackingDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Stacking }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Stacking }); } export function MasonryDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Masonry }); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Masonry }); } export function ButtonDocument(options?: DocumentOptions) { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 55e014c66..b7ac8768f 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -35,7 +35,7 @@ library.add(faImage, faEye); @observer export class CollectionView extends React.Component { - @observable private _collapsed = false; + @observable private _collapsed = true; private _reactionDisposer: IReactionDisposer | undefined; -- cgit v1.2.3-70-g09d2 From 06dfb537826e8b1642783a9c4ab2514fd7da2fe3 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 29 Jul 2019 16:53:52 -0400 Subject: More fixes --- src/client/views/collections/CollectionDockingView.tsx | 2 +- src/client/views/collections/CollectionStackingView.scss | 1 + src/client/views/collections/CollectionStackingViewFieldColumn.tsx | 4 ++-- src/client/views/nodes/ImageBox.tsx | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 1859ebee7..d7b5262b1 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -561,7 +561,7 @@ export class DockedFrameRenderer extends React.Component { } return Transform.Identity(); } - get previewPanelCenteringOffset() { return this.nativeWidth && !BoolCast(this._document!.ignoreAspect) ? (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2 : 0; } + get previewPanelCenteringOffset() { return this.nativeWidth && !BoolCast(this._document!.ignoreAspect) ? (this._panelWidth - this.nativeWidth()) / 2 : 0; } addDocTab = (doc: Doc, dataDoc: Doc | undefined, location: string) => { if (doc.dockingConfig) { diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 004b57eff..2bb36c825 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -74,6 +74,7 @@ transform-origin: top left; grid-column-end: span 1; height: 100%; + margin: auto; } .collectionStackingView-sectionHeader { diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 71c4d9f0c..b5dbc1a22 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -239,7 +239,7 @@ export class CollectionStackingViewFieldColumn extends React.Component + style={{ width: (style.columnWidth) / ((uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0)) || 1) }}> {/* the default bucket (no key value) has a tooltip that describes what it is. Further, it does not have a color and cannot be deleted. */}
    : (null); for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth}px `; return ( -
    {headingView}
    (ImageD let aspect = size.height / size.width; let rotation = NumCast(this.dataDoc.rotation) % 180; if (rotation === 90 || rotation === 270) aspect = 1 / aspect; - if (Math.abs(layoutdoc[HeightSym]() / layoutdoc[WidthSym]() - aspect) > 0.01) { + if (Math.abs(NumCast(layoutdoc.height) - size.height) > 1 || Math.abs(NumCast(layoutdoc.width) - size.width) > 1) { setTimeout(action(() => { layoutdoc.height = layoutdoc[WidthSym]() * aspect; layoutdoc.nativeHeight = size.height; -- cgit v1.2.3-70-g09d2 From ad00d760b364c3d3478be5c0f12b3eb6b6afaf5b Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Mon, 29 Jul 2019 16:58:34 -0400 Subject: fixed escape to close full screen --- src/client/views/MainView.tsx | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f5a6715e5..91c8fe57c 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -92,6 +92,8 @@ export class MainView extends React.Component { componentWillUnMount() { window.removeEventListener("keydown", KeyManager.Instance.handle); + window.removeEventListener("pointerdown", this.globalPointerDown); + window.removeEventListener("pointerup", this.globalPointerUp); } constructor(props: Readonly<{}>) { @@ -138,18 +140,23 @@ export class MainView extends React.Component { this.initAuthenticationRouters(); } + globalPointerDown = action((e: PointerEvent) => { + this.isPointerDown = true; + const targets = document.elementsFromPoint(e.x, e.y); + if (targets && targets.length && targets[0].className.toString().indexOf("contextMenu") === -1) { + ContextMenu.Instance.closeMenu(); + } + }); + + globalPointerUp = () => this.isPointerDown = false; + initEventListeners = () => { // window.addEventListener("pointermove", (e) => this.reportLocation(e)) window.addEventListener("drop", (e) => e.preventDefault(), false); // drop event handler window.addEventListener("dragover", (e) => e.preventDefault(), false); // drag event handler // click interactions for the context menu - document.addEventListener("pointerdown", action((e: PointerEvent) => { - this.isPointerDown = true; - const targets = document.elementsFromPoint(e.x, e.y); - if (targets && targets.length && targets[0].className.toString().indexOf("contextMenu") === -1) { - ContextMenu.Instance.closeMenu(); - } - }), true); + document.addEventListener("pointerdown", this.globalPointerDown); + document.addEventListener("pointerup", this.globalPointerUp); } initAuthenticationRouters = async () => { @@ -292,7 +299,6 @@ export class MainView extends React.Component { } @action onPointerUp = (e: PointerEvent) => { - this.isPointerDown = false; if (Math.abs(e.clientX - this._downsize) < 4) { if (this.flyoutWidth < 5) this.flyoutWidth = 250; else this.flyoutWidth = 0; -- cgit v1.2.3-70-g09d2 From 3d5e8b4cfff2bc0385d455587934538d5b82bee9 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 29 Jul 2019 17:41:56 -0400 Subject: Added some undos --- src/client/views/MetadataEntryMenu.tsx | 2 ++ src/client/views/nodes/KeyValueBox.tsx | 2 ++ src/client/views/nodes/KeyValuePair.tsx | 5 +++-- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/MetadataEntryMenu.tsx b/src/client/views/MetadataEntryMenu.tsx index 652e0e91a..36c240dd8 100644 --- a/src/client/views/MetadataEntryMenu.tsx +++ b/src/client/views/MetadataEntryMenu.tsx @@ -5,6 +5,7 @@ import { observable, action, runInAction, trace } from 'mobx'; import { KeyValueBox } from './nodes/KeyValueBox'; import { Doc, Field } from '../../new_fields/Doc'; import * as Autosuggest from 'react-autosuggest'; +import { undoBatch } from '../util/UndoManager'; export type DocLike = Doc | Doc[] | Promise | Promise; export interface MetadataEntryProps { @@ -74,6 +75,7 @@ export class MetadataEntryMenu extends React.Component{ this.userModified = e.target.value.trim() !== ""; } + @undoBatch @action onValueKeyDown = async (e: React.KeyboardEvent) => { if (e.key === "Enter") { diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index e8075d076..f10079169 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -21,6 +21,7 @@ import { ImageField } from "../../../new_fields/URLField"; import { SelectionManager } from "../../util/SelectionManager"; import { listSpec } from "../../../new_fields/Schema"; import { CollectionViewType } from "../collections/CollectionBaseView"; +import { undoBatch } from "../../util/UndoManager"; export type KVPScript = { script: CompiledScript; @@ -90,6 +91,7 @@ export class KeyValueBox extends React.Component { return false; } + @undoBatch public static SetField(doc: Doc, key: string, value: string) { const script = this.CompileKVPScript(value); if (!script) return false; diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 4abf87b9f..3775f0f47 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -16,6 +16,7 @@ import { DragManager, SetupDrag } from '../../util/DragManager'; import { ContextMenu } from '../ContextMenu'; import { Docs } from '../../documents/Documents'; import { CollectionDockingView } from '../collections/CollectionDockingView'; +import { undoBatch } from '../../util/UndoManager'; // Represents one row in a key value plane @@ -92,12 +93,12 @@ export class KeyValuePair extends React.Component { this.isPointerOver = true)} onPointerLeave={action(() => this.isPointerOver = false)}>
    - Date: Mon, 29 Jul 2019 19:17:29 -0400 Subject: Made AddTab be able to accept no stack --- src/client/views/collections/CollectionDockingView.tsx | 15 ++++++++++++++- src/new_fields/SchemaHeaderField.ts | 1 - 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index d7b5262b1..ab4d1aa62 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -211,7 +211,20 @@ export class CollectionDockingView extends React.Component Date: Mon, 29 Jul 2019 19:22:02 -0400 Subject: fixed templates with stacking and other nested views. --- src/client/views/collections/CollectionSchemaView.tsx | 1 + src/client/views/collections/CollectionStackingView.tsx | 2 ++ src/client/views/collections/CollectionTreeView.tsx | 1 + 3 files changed, 4 insertions(+) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 996118c00..08ab22725 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -233,6 +233,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } render() { + Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey); // 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 ( diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 6e1968774..bcf3a85d7 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -276,6 +276,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { SetValue: this.addGroup, contents: "+ ADD A GROUP" }; + Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey); + // let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); return (
    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); -- cgit v1.2.3-70-g09d2 From 378849b4423017d8af675ceb9992e186a5407f8f Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 29 Jul 2019 19:41:48 -0400 Subject: made summaries go back to having no chrome. --- src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 1c767e012..4d659392c 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -293,14 +293,14 @@ export class MarqueeView extends React.Component d.page = -1; return d; }); + newCollection.chromeStatus = "disabled"; let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" }); newCollection.proto!.summaryDoc = summary; selected = [newCollection]; newCollection.x = bounds.left + bounds.width; summary.proto!.subBulletDocs = new List(selected); - //summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight" summary.templates = new List([Templates.Bullet.Layout]); - let container = Docs.Create.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, title: "-summary-" }); + let container = Docs.Create.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, chromeStatus: "disabled", title: "-summary-" }); container.viewType = CollectionViewType.Stacking; this.props.addLiveTextDocument(container); // }); @@ -312,6 +312,7 @@ export class MarqueeView extends React.Component d.page = -1; return d; }); + newCollection.chromeStatus = "disabled"; let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" }); newCollection.proto!.summaryDoc = summary; selected = [newCollection]; -- cgit v1.2.3-70-g09d2 From 2514917040d24c04a489905c7a1fe4d10013fd31 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 29 Jul 2019 20:50:04 -0400 Subject: not elegant, but should compute bounds for computed layouts --- .../collectionFreeForm/CollectionFreeFormView.tsx | 36 +++++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 0780320d6..d2c95532e 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -65,8 +65,20 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return (this.props as any).ContentScaling && this.fitToBox && !this.isAnnotationOverlay ? (this.props as any).ContentScaling() : 1; } + ComputeContentBounds(boundsList: { x: number, y: number, width: number, height: number }[]) { + let bounds = boundsList.reduce((bounds, b) => { + var [sptX, sptY] = [b.x, b.y]; + let [bptX, bptY] = [sptX + b.width, sptY + b.height]; + return { + x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y), + r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b) + }; + }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: -Number.MAX_VALUE, b: -Number.MAX_VALUE }); + return bounds; + } + @computed get contentBounds() { - let bounds = this.fitToBox && !this.isAnnotationOverlay ? Doc.ComputeContentBounds(DocListCast(this.props.Document.data)) : undefined; + let bounds = this.fitToBox && !this.isAnnotationOverlay ? this.ComputeContentBounds(this.elements.filter(e => e.bounds).map(e => e.bounds!)) : undefined; return { panX: bounds ? (bounds.x + bounds.r) / 2 : this.Document.panX || 0, panY: bounds ? (bounds.y + bounds.b) / 2 : this.Document.panY || 0, @@ -446,13 +458,13 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } @computed.struct - get views() { + get elements() { let curPage = FieldValue(this.Document.curPage, -1); const initScript = this.Document.arrangeInit; const script = this.Document.arrangeScript; let state: any = undefined; const docs = this.childDocs; - let elements: JSX.Element[] = []; + let elements: { ele: JSX.Element, bounds?: { x: number, y: number, width: number, height: number } }[] = []; if (initScript) { const initResult = initScript.script.run({ docs, collection: this.Document }); if (initResult.success) { @@ -460,23 +472,26 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { const { state: scriptState, views } = result; state = scriptState; if (Array.isArray(views)) { - elements = views.reduce((prev, ele) => { + elements = views.reduce((prev, ele) => { const jsx = this.viewDefToJSX(ele); - jsx && prev.push(jsx); + jsx && prev.push({ ele: jsx }); return prev; }, elements); } } } - let docviews = docs.reduce((prev, doc) => { - if (!(doc instanceof Doc)) return prev; + let docviews = docs.filter(doc => doc instanceof Doc).reduce((prev, doc) => { var page = NumCast(doc.page, -1); + let bounds: { x?: number, y?: number, width?: number, height?: number }; if ((Math.abs(Math.round(page) - Math.round(curPage)) < 3) || page === -1) { let minim = BoolCast(doc.isMinimized); if (minim === undefined || !minim) { const pos = script ? this.getCalculatedPositions(script, { doc, index: prev.length, collection: this.Document, docs, state }) : {}; state = pos.state === undefined ? state : pos.state; - prev.push(); + prev.push({ + ele: , + bounds: (pos.x !== undefined && pos.y !== undefined && pos.width !== undefined && pos.height !== undefined) ? { x: pos.x, y: pos.y, width: pos.width, height: pos.height } : undefined + }); } } return prev; @@ -487,6 +502,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return docviews; } + @computed.struct + get views() { + return this.elements.map(ele => ele.ele); + } + @action onCursorMove = (e: React.PointerEvent) => { super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY)); -- cgit v1.2.3-70-g09d2 From e042f916375fbe4f23288ece0dcec5b61ef2fbed Mon Sep 17 00:00:00 2001 From: yipstanley Date: Mon, 29 Jul 2019 21:20:51 -0400 Subject: annotations now open the target context --- src/client/util/DragManager.ts | 1 + .../collectionFreeForm/CollectionFreeFormView.tsx | 2 ++ src/client/views/nodes/DocumentView.tsx | 4 +++- src/client/views/pdf/Annotation.tsx | 12 +++++++++--- src/client/views/pdf/Page.tsx | 2 +- 5 files changed, 16 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 9221ef274..abcc3a4e1 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -216,6 +216,7 @@ export namespace DragManager { this.annotationDocument = annotationDoc; this.xOffset = this.yOffset = 0; } + targetContext: Doc | undefined; dragDocument: Doc; annotationDocument: Doc; dropDocument: Doc; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 0780320d6..179a65739 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -151,6 +151,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { let dropY = NumCast(de.data.dropDocument.y); dragDoc.x = x + NumCast(dragDoc.x) - dropX; dragDoc.y = y + NumCast(dragDoc.y) - dropY; + de.data.targetContext = this.props.Document; + dragDoc.targetContext = this.props.Document; this.bringToFront(dragDoc); } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index f101222ae..b37485e62 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -439,7 +439,9 @@ export class DocumentView extends DocComponent(Docu e.stopPropagation(); let annotationDoc = de.data.annotationDocument; annotationDoc.linkedToDoc = true; + de.data.targetContext = this.props.ContainingCollectionView!.props.Document; let targetDoc = this.props.Document; + targetDoc.targetContext = de.data.targetContext; let annotations = await DocListCastAsync(annotationDoc.annotations); if (annotations) { annotations.forEach(anno => { @@ -448,7 +450,7 @@ export class DocumentView extends DocComponent(Docu } let pdfDoc = await Cast(annotationDoc.pdfDoc, Doc); if (pdfDoc) { - DocUtils.MakeLink(annotationDoc, targetDoc, undefined, `Annotation from ${StrCast(pdfDoc.title)}`, "", StrCast(pdfDoc.title)); + DocUtils.MakeLink(annotationDoc, targetDoc, this.props.ContainingCollectionView!.props.Document, `Annotation from ${StrCast(pdfDoc.title)}`, "", StrCast(pdfDoc.title)); } } if (de.data instanceof DragManager.LinkDragData) { diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index ed7081b1d..e8d1da94b 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -9,6 +9,8 @@ import { List } from "../../../new_fields/List"; import PDFMenu from "./PDFMenu"; import { DocumentManager } from "../../util/DocumentManager"; import { PresentationView } from "../presentationview/PresentationView"; +import { LinkManager } from "../../util/LinkManager"; +import { CollectionDockingView } from "../collections/CollectionDockingView"; interface IAnnotationProps { anno: Doc; @@ -110,11 +112,15 @@ class RegionAnnotation extends React.Component { } @action - onPointerDown = (e: React.PointerEvent) => { + onPointerDown = async (e: React.PointerEvent) => { if (e.button === 0) { - let targetDoc = Cast(this.props.document.target, Doc, null); + let targetDoc = await Cast(this.props.document.target, Doc); if (targetDoc) { - DocumentManager.Instance.jumpToDocument(targetDoc, false); + let context = await Cast(targetDoc.targetContext, Doc); + if (context) { + DocumentManager.Instance.jumpToDocument(targetDoc, false, undefined, + ((doc) => this.props.parent.props.parent.props.addDocTab(context, context.proto, e.ctrlKey ? "onRight" : "inTab"))); + } } } if (e.button === 2) { diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx index c205617b4..c5b2a1dda 100644 --- a/src/client/views/pdf/Page.tsx +++ b/src/client/views/pdf/Page.tsx @@ -175,7 +175,7 @@ export default class Page extends React.Component { } let pdfDoc = await Cast(annotationDoc.pdfDoc, Doc); if (pdfDoc) { - DocUtils.MakeLink(annotationDoc, targetDoc, undefined, `Annotation from ${StrCast(pdfDoc.title)}`, "", StrCast(pdfDoc.title)); + DocUtils.MakeLink(annotationDoc, targetDoc, dragData.targetContext, `Annotation from ${StrCast(pdfDoc.title)}`, "", StrCast(pdfDoc.title)); } } } -- cgit v1.2.3-70-g09d2 From 1723fed27c615ced10b5bf9648f86f923cf61a42 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 29 Jul 2019 21:23:26 -0400 Subject: added button titles. made summary's autoHeight --- src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 2 ++ src/client/views/nodes/ButtonBox.tsx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 4d659392c..67bed284f 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -302,6 +302,7 @@ export class MarqueeView extends React.Component summary.templates = new List([Templates.Bullet.Layout]); let container = Docs.Create.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, chromeStatus: "disabled", title: "-summary-" }); container.viewType = CollectionViewType.Stacking; + container.autoHeight = true; this.props.addLiveTextDocument(container); // }); } else if (e.key === "S") { @@ -320,6 +321,7 @@ export class MarqueeView extends React.Component //this.props.addDocument(newCollection, false); summary.proto!.summarizedDocs = new List(selected); summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight" + summary.autoHeight = true; this.props.addLiveTextDocument(summary); } diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx index d2c23fdab..e2c559c9a 100644 --- a/src/client/views/nodes/ButtonBox.tsx +++ b/src/client/views/nodes/ButtonBox.tsx @@ -70,7 +70,7 @@ export class ButtonBox extends DocComponent(Butt render() { return (
    - +
    ); } -- cgit v1.2.3-70-g09d2 From 8f8e942a648f36e480af18457a86c413e2cbdf0e Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 29 Jul 2019 21:43:53 -0400 Subject: fixed pasted pdf links to contain pdf context. --- src/client/views/nodes/FormattedTextBox.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 0f51ca2ce..fc0cc98aa 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -329,7 +329,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe fieldExtDoc.annotations = new List(targetAnnotations); } - let link = DocUtils.MakeLink(this.props.Document, region); + let link = DocUtils.MakeLink(this.props.Document, region, doc); if (link) { cbe.clipboardData!.setData("dash/linkDoc", link[Id]); linkId = link[Id]; @@ -443,6 +443,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } if (targetContext) { DocumentManager.Instance.jumpToDocument(targetContext, ctrlKey, false, document => this.props.addDocTab(document, undefined, location ? location : "inTab")); + } else if (jumpToDoc) { + DocumentManager.Instance.jumpToDocument(jumpToDoc, ctrlKey, false, document => this.props.addDocTab(document, undefined, location ? location : "inTab")); + } } }); -- cgit v1.2.3-70-g09d2 From f6583e4b504a4a60f4aefc68c7a60692a92869dd Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 29 Jul 2019 22:33:35 -0400 Subject: Included extra ui elements in bounds calculation --- .../collectionFreeForm/CollectionFreeFormView.tsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 2b2f0bcd5..8dac785e1 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -440,7 +440,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return result.result === undefined ? {} : result.result; } - private viewDefToJSX(viewDef: any): JSX.Element | undefined { + private viewDefToJSX(viewDef: any): { ele: JSX.Element, bounds?: { x: number, y: number, width: number, height: number } } | undefined { if (viewDef.type === "text") { const text = Cast(viewDef.text, "string"); const x = Cast(viewDef.x, "number"); @@ -448,14 +448,16 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { const width = Cast(viewDef.width, "number"); const height = Cast(viewDef.height, "number"); const fontSize = Cast(viewDef.fontSize, "number"); - if ([text, x, y].some(val => val === undefined)) { + if ([text, x, y, width, height].some(val => val === undefined)) { return undefined; } - return
    {text}
    ; + return { + ele:
    {text}
    , bounds: { x: x!, y: y!, width: width!, height: height! } + }; } } @@ -474,9 +476,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { const { state: scriptState, views } = result; state = scriptState; if (Array.isArray(views)) { - elements = views.reduce((prev, ele) => { + elements = views.reduce((prev, ele) => { const jsx = this.viewDefToJSX(ele); - jsx && prev.push({ ele: jsx }); + jsx && prev.push(jsx); return prev; }, elements); } -- cgit v1.2.3-70-g09d2 From ba2c6a9f3cd6d68bcf28ff3dc880b4f8b4635747 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Mon, 29 Jul 2019 23:48:35 -0400 Subject: styling changes to stacking --- src/client/views/collections/CollectionStackingView.scss | 5 +++-- .../views/collections/CollectionStackingViewFieldColumn.tsx | 8 ++++++-- src/client/views/pdf/Annotation.tsx | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 2bb36c825..0cb01dc9d 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -135,9 +135,9 @@ .collectionStackingView-addDocumentButton, .collectionStackingView-addGroupButton { - display: inline-block; - margin: 0 5px; + display: flex; overflow: hidden; + margin: auto; width: 90%; color: lightgrey; overflow: ellipses; @@ -146,6 +146,7 @@ .editableView-container-editing { color: grey; padding: 10px; + width: 100%; } .editableView-input:hover, diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index b5dbc1a22..d8bed7e88 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -239,7 +239,11 @@ export class CollectionStackingViewFieldColumn extends React.Component + style={{ + width: (style.columnWidth) / + ((uniqueHeadings.length + + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0)) || 1) + }}> {/* the default bucket (no key value) has a tooltip that describes what it is. Further, it does not have a color and cannot be deleted. */}
    { let context = await Cast(targetDoc.targetContext, Doc); if (context) { DocumentManager.Instance.jumpToDocument(targetDoc, false, undefined, - ((doc) => this.props.parent.props.parent.props.addDocTab(context, context.proto, e.ctrlKey ? "onRight" : "inTab"))); + ((doc) => this.props.parent.props.parent.props.addDocTab(context!, context!.proto, e.ctrlKey ? "onRight" : "inTab"))); } } } -- cgit v1.2.3-70-g09d2 From 2468ab85d642b954e47a560e2d0739dba9674f88 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Tue, 30 Jul 2019 00:02:21 -0400 Subject: put back contains/not contains colors --- src/client/views/collections/KeyRestrictionRow.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/KeyRestrictionRow.tsx b/src/client/views/collections/KeyRestrictionRow.tsx index 9c3c9c07c..9baa250a6 100644 --- a/src/client/views/collections/KeyRestrictionRow.tsx +++ b/src/client/views/collections/KeyRestrictionRow.tsx @@ -29,6 +29,7 @@ export default class KeyRestrictionRow extends React.Component runInAction(() => this._key = e.target.value)} placeholder="KEY" /> -- cgit v1.2.3-70-g09d2 From 5248a770123e312e1684d7147ecb7118dd6ef1e7 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Tue, 30 Jul 2019 01:24:37 -0400 Subject: tag generation and faces on extensionDoc --- src/client/cognitive_services/CognitiveServices.ts | 40 ++++-------------- src/client/views/nodes/FaceRectangles.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 49 +++++++++++++++++++--- 3 files changed, 54 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts index bbc438a9b..076907f09 100644 --- a/src/client/cognitive_services/CognitiveServices.ts +++ b/src/client/cognitive_services/CognitiveServices.ts @@ -42,7 +42,7 @@ export enum Confidence { */ export namespace CognitiveServices { - const executeQuery = async (service: Service, manager: APIManager, data: D): Promise> => { + const ExecuteQuery = async (service: Service, manager: APIManager, data: D): Promise> => { return fetch(Utils.prepend(`${RouteStore.cognitiveServices}/${service}`)).then(async response => { let apiKey = await response.text(); if (!apiKey) { @@ -103,15 +103,15 @@ export namespace CognitiveServices { return request.post(options); }, - analyzer: async (target: Doc, keys: string[], service: Service, converter: Converter) => { + analyzer: async (target: Doc, keys: string[], url: string, service: Service, converter: Converter) => { let batch = UndoManager.StartBatch("Image Analysis"); - let imageData = Cast(target.data, ImageField); + let storageKey = keys[0]; - if (!imageData || await Cast(target[storageKey], Doc)) { + if (!url || await Cast(target[storageKey], Doc)) { return; } let toStore: any; - let results = await executeQuery(service, Manager, imageData.url.href); + let results = await ExecuteQuery(service, Manager, url); if (!results) { toStore = "Cognitive Services could not process the given image URL."; } else { @@ -122,6 +122,7 @@ export namespace CognitiveServices { } } target[storageKey] = toStore; + batch.end(); } @@ -129,31 +130,6 @@ export namespace CognitiveServices { export type Face = { faceAttributes: any, faceId: string, faceRectangle: Rectangle }; - export const generateMetadata = async (target: Doc, threshold: Confidence = Confidence.Excellent) => { - let converter = (results: any) => { - let tagDoc = new Doc; - results.tags.map((tag: Tag) => { - let sanitized = tag.name.replace(" ", "_"); - let script = `return (${tag.confidence} >= this.confidence) ? ${tag.confidence} : "${ComputedField.undefined}"`; - let computed = CompileScript(script, { params: { this: "Doc" } }); - computed.compiled && (tagDoc[sanitized] = new ComputedField(computed)); - }); - tagDoc.title = "Generated Tags"; - tagDoc.confidence = threshold; - return tagDoc; - }; - Manager.analyzer(target, ["generatedTags"], Service.ComputerVision, converter); - }; - - export const extractFaces = async (target: Doc) => { - let converter = (results: any) => { - let faceDocs = new List(); - results.map((face: Face) => faceDocs.push(Docs.Get.DocumentHierarchyFromJson(face, `Face: ${face.faceId}`)!)); - return faceDocs; - }; - Manager.analyzer(target, ["faces"], Service.Face, converter); - }; - } export namespace Inking { @@ -209,7 +185,8 @@ export namespace CognitiveServices { analyzer: async (target: Doc, keys: string[], inkData: InkData) => { let batch = UndoManager.StartBatch("Ink Analysis"); - let results = await executeQuery(Service.Handwriting, Manager, inkData); + + let results = await ExecuteQuery(Service.Handwriting, Manager, inkData); if (results) { results.recognitionUnits && (results = results.recognitionUnits); target[keys[0]] = Docs.Get.DocumentHierarchyFromJson(results, "Ink Analysis"); @@ -217,6 +194,7 @@ export namespace CognitiveServices { let individualWords = recognizedText.filter((text: string) => text && text.split(" ").length === 1); target[keys[1]] = individualWords.join(" "); } + batch.end(); } diff --git a/src/client/views/nodes/FaceRectangles.tsx b/src/client/views/nodes/FaceRectangles.tsx index 3570531b2..acf1aced3 100644 --- a/src/client/views/nodes/FaceRectangles.tsx +++ b/src/client/views/nodes/FaceRectangles.tsx @@ -20,7 +20,7 @@ export interface RectangleTemplate { export default class FaceRectangles extends React.Component { render() { - let faces = DocListCast(Doc.GetProto(this.props.document).faces); + let faces = DocListCast(this.props.document.faces); let templates: RectangleTemplate[] = faces.map(faceDoc => { let rectangle = Cast(faceDoc.faceRectangle, Doc) as Doc; let style = { diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 29a76b0c8..5554475ec 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -25,9 +25,12 @@ import { Docs, DocumentType } from '../../documents/Documents'; import { DocServer } from '../../DocServer'; import { Font } from '@react-pdf/renderer'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { CognitiveServices } from '../../cognitive_services/CognitiveServices'; +import { CognitiveServices, Service, Tag, Confidence } from '../../cognitive_services/CognitiveServices'; import FaceRectangles from './FaceRectangles'; import { faEye } from '@fortawesome/free-regular-svg-icons'; +import { ComputedField } from '../../../new_fields/ScriptField'; +import { CompileScript } from '../../util/Scripting'; +import { thisExpression } from 'babel-types'; var requestImageSize = require('../../util/request-image-size'); var path = require('path'); const { Howl } = require('howler'); @@ -226,20 +229,56 @@ export class ImageBox extends DocComponent(ImageD funcs.push({ description: "Rotate", event: this.rotate, icon: "expand-arrows-alt" }); let modes: ContextMenuProps[] = []; - let dataDoc = Doc.GetProto(this.props.Document); - modes.push({ description: "Generate Tags", event: () => CognitiveServices.Image.generateMetadata(dataDoc), icon: "tag" }); - modes.push({ description: "Find Faces", event: () => CognitiveServices.Image.extractFaces(dataDoc), icon: "camera" }); + modes.push({ description: "Generate Tags", event: this.generateMetadata, icon: "tag" }); + modes.push({ description: "Find Faces", event: this.extractFaces, icon: "camera" }); ContextMenu.Instance.addItem({ description: "Image Funcs...", subitems: funcs, icon: "asterisk" }); ContextMenu.Instance.addItem({ description: "Analyze...", subitems: modes, icon: "eye" }); } } + extractFaces = () => { + let converter = (results: any) => { + let faceDocs = new List(); + results.map((face: CognitiveServices.Image.Face) => faceDocs.push(Docs.Get.DocumentHierarchyFromJson(face, `Face: ${face.faceId}`)!)); + return faceDocs; + }; + CognitiveServices.Image.Manager.analyzer(this.extensionDoc, ["faces"], this.url, Service.Face, converter); + } + + generateMetadata = (threshold: Confidence = Confidence.Excellent) => { + let converter = (results: any) => { + let tagDoc = new Doc; + let tagsList = new List(); + results.tags.map((tag: Tag) => { + tagsList.push(tag.name); + let sanitized = tag.name.replace(" ", "_"); + let script = `return (${tag.confidence} >= this.confidence) ? ${tag.confidence} : "${ComputedField.undefined}"`; + let computed = CompileScript(script, { params: { this: "Doc" } }); + computed.compiled && (tagDoc[sanitized] = new ComputedField(computed)); + }); + this.extensionDoc.generatedTags = tagsList; + tagDoc.title = "Generated Tags Doc"; + tagDoc.confidence = threshold; + return tagDoc; + }; + CognitiveServices.Image.Manager.analyzer(this.extensionDoc, ["generatedTagsDoc"], this.url, Service.ComputerVision, converter); + } + @action onDotDown(index: number) { this.Document.curPage = index; } + @computed get fieldExtensionDoc() { + return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, "true"); + } + + @computed private get url() { + let data = Cast(Doc.GetProto(this.props.Document).data, ImageField); + return data ? data.url.href : undefined; + } + dots(paths: string[]) { let nativeWidth = FieldValue(this.Document.nativeWidth, 1); let dist = Math.min(nativeWidth / paths.length, 40); @@ -394,7 +433,7 @@ export class ImageBox extends DocComponent(ImageD style={{ color: [DocListCast(this.extensionDoc.audioAnnotations).length ? "blue" : "gray", "green", "red"][this._audioState] }} icon={faFileAudio} size="sm" />
    {/* {this.lightbox(paths)} */} - +
    ); } } \ No newline at end of file -- cgit v1.2.3-70-g09d2