From f1cb6a2212b11ba6d18dfa2e800b2c8e4ad94a88 Mon Sep 17 00:00:00 2001 From: fawn Date: Mon, 29 Jul 2019 14:28:25 -0400 Subject: made hit box on col resizer smaller and hit box on coll expander bigger --- .../views/collections/CollectionSchemaCells.tsx | 2 +- .../views/collections/CollectionSchemaView.scss | 39 +++++++++++++++------- .../views/collections/CollectionSchemaView.tsx | 6 ++-- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- 4 files changed, 32 insertions(+), 17 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 194765880..e06a5c66b 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -108,7 +108,7 @@ export class CollectionSchemaCell extends React.Component { this._document[fieldKey] = de.data.draggedDocuments[0]; } else { - let coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title")], de.data.draggedDocuments, {}); + let coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title", "f1efeb")], de.data.draggedDocuments, {}); this._document[fieldKey] = coll; } e.stopPropagation(); diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 053d6452c..749b9a364 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -97,15 +97,6 @@ // margin-right: -30px; } - .rt-resizable-header { - padding: 0; - height: 30px; - - &:last-child { - overflow: visible; - } - } - .rt-resizable-header-content { height: 100%; overflow: visible; @@ -198,8 +189,22 @@ } .rt-resizer { - width: 20px; - right: -10px; + width: 8px; + right: -4px; + } + + .rt-resizable-header { + padding: 0; + height: 30px; + } + + .rt-resizable-header:last-child { + overflow: visible; + border: 3px solid red !important; + + .rt-resizer { + width: 5px !important; + } } } @@ -318,7 +323,7 @@ button.add-column { input[type="radio"] { display: none; } - + .columnMenu-colorPicker { width: 20px; height: 20px; @@ -497,4 +502,14 @@ button.add-column { .collectionSchemaView-expander { height: 100%; + min-height: 30px; + position: relative; + color: gray; + + svg { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 53dd9523b..ece638ec7 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -635,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, "f1efeb")]); + this.props.Document.schemaColumns = list = new List([new SchemaHeaderField(newKey, "#f1efeb")]); } else { console.log("change column"); if (addNew) { - this.columns.push(new SchemaHeaderField(newKey, "f1efeb")); + 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, "f1efeb"); + list[index] = new SchemaHeaderField(newKey, "#f1efeb"); } } } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 1c767e012..7decadbe9 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -135,7 +135,7 @@ export class MarqueeView extends React.Component doc.width = 200; docList.push(doc); } - 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 }); + let newCol = Docs.Create.SchemaDocument([...(groupAttr ? [new SchemaHeaderField("_group", "#f1efeb")] : []), ...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); } -- cgit v1.2.3-70-g09d2 From 1190dc51c66cb48d48c16988f14100fd9a7004e2 Mon Sep 17 00:00:00 2001 From: fawn Date: Mon, 29 Jul 2019 17:34:57 -0400 Subject: color + type on schemaheaderfields fixed and schemas can toggle textwrapping --- .../views/collections/CollectionSchemaCells.tsx | 4 +- .../views/collections/CollectionSchemaHeaders.tsx | 82 +++++----- .../views/collections/CollectionSchemaView.scss | 13 +- .../views/collections/CollectionSchemaView.tsx | 175 ++++++++++----------- .../views/collections/CollectionViewChromes.tsx | 33 ++++ .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/new_fields/SchemaHeaderField.ts | 11 +- 7 files changed, 183 insertions(+), 137 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index e06a5c66b..17dfd317d 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -108,7 +108,7 @@ export class CollectionSchemaCell extends React.Component { this._document[fieldKey] = de.data.draggedDocuments[0]; } else { - let coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title", "f1efeb")], de.data.draggedDocuments, {}); + let coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title", "#f1efeb")], de.data.draggedDocuments, {}); this._document[fieldKey] = coll; } e.stopPropagation(); @@ -284,7 +284,7 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell { 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); + this.applyToDoc(this._document, this.props.row, this.props.col, script.run); } } diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index 387107c55..088ad7ecd 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -23,23 +23,25 @@ export interface HeaderProps { onSelect: (oldKey: string, newKey: string, addnew: boolean) => void; setIsEditing: (isEditing: boolean) => void; deleteColumn: (column: string) => void; - setColumnType: (key: string, type: ColumnType) => void; + setColumnType: (column: SchemaHeaderField, type: ColumnType) => void; setColumnSort: (key: string, desc: boolean) => void; removeColumnSort: (key: string) => void; + setColumnColor: (column: SchemaHeaderField, color: string) => 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.Boolean ? "check-square" : this.props.keyType === ColumnType.Doc ? "file" : "align-justify"; - return (
{this.props.keyValue.heading}
} addNew={false} @@ -50,6 +52,7 @@ export class CollectionSchemaHeader extends React.Component { setColumnType={this.props.setColumnType} setColumnSort={this.props.setColumnSort} removeColumnSort={this.props.removeColumnSort} + setColumnColor={this.props.setColumnColor} /> ); @@ -73,10 +76,11 @@ export class CollectionSchemaAddColumnHeader extends React.Component void; deleteColumn: (column: string) => void; onlyShowOptions: boolean; - setColumnType: (key: string, type: ColumnType) => void; + setColumnType: (column: SchemaHeaderField, type: ColumnType) => void; setColumnSort: (key: string, desc: boolean) => void; removeColumnSort: (key: string) => void; anchorPoint?: any; + setColumnColor: (column: SchemaHeaderField, color: string) => void; } @observer export class CollectionSchemaColumnMenu extends React.Component { @@ -110,16 +115,21 @@ export class CollectionSchemaColumnMenu extends React.Component } } + setNewColor = (color: string): void => { + this.changeColumnType(ColumnType.Any); + console.log("change color", this.props.columnField.heading); + this.props.setColumnColor(this.props.columnField, color); + } + @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); + changeColumnType = (type: ColumnType): void => { + console.log("change type", this.props.columnField.heading); + // this.props.setColumnType(this.props.columnField, type); } @action @@ -129,33 +139,29 @@ export class CollectionSchemaColumnMenu extends React.Component } } - changeColumnColor = (color: string): void => { - - } - renderTypes = () => { if (this.props.typeConst) return <>; return (
- - - - -
-
+ ); } @@ -164,9 +170,9 @@ export class CollectionSchemaColumnMenu extends React.Component
-
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
+
this.props.setColumnSort(this.props.columnField.heading, false)}>Sort ascending
+
this.props.setColumnSort(this.props.columnField.heading, true)}>Sort descending
+
this.props.removeColumnSort(this.props.columnField.heading)}>Clear sorting
); @@ -177,29 +183,29 @@ export class CollectionSchemaColumnMenu extends React.Component
- this.changeColumnColor("#FFB4E8")} /> + this.setNewColor("#FFB4E8")} /> - this.changeColumnColor("#b28dff")} /> + this.setNewColor("#b28dff")} /> - this.changeColumnColor("#afcbff")} /> + this.setNewColor("#afcbff")} /> - this.changeColumnColor("#f3ffe3")} /> + this.setNewColor("#fff5ba")} /> - this.changeColumnColor("#ffc9de")} /> + this.setNewColor("#ffabab")} /> - this.changeColumnColor("#f1efeb")} /> + this.setNewColor("#f1efeb")} />
@@ -212,7 +218,7 @@ export class CollectionSchemaColumnMenu extends React.Component
<> {this.renderTypes()} {this.renderSorting()} - {this.renderColors()} + {/* {this.renderColors()} */}
- +
} diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 749b9a364..487907c1c 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -167,8 +167,8 @@ padding: 0; font-size: 13px; text-align: center; - // white-space: normal; + white-space: nowrap; .imageBox-cont { position: relative; @@ -318,15 +318,19 @@ button.add-column { } .columnMenu-colors { - + display: flex; + justify-content: space-between; + flex-wrap: wrap; input[type="radio"] { display: none; } .columnMenu-colorPicker { + cursor: pointer; width: 20px; height: 20px; + border-radius: 10px; } } } @@ -335,13 +339,16 @@ button.add-column { // height: $MAX_ROW_HEIGHT; height: 100%; background-color: white; + // white-space: nowrap; &.row-focused .rt-tr { background-color: rgb(255, 246, 246);//$light-color-secondary; } &.row-wrapped { - white-space: normal; + .rt-td { + white-space: normal; + } } .row-dragger { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index ece638ec7..2ce6f1be3 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -280,16 +280,20 @@ export class SchemaTable extends React.Component { @observable _focusedCell: { row: number, col: number } = { row: 0, col: 0 }; @observable _sortedColumns: Map = new Map(); @observable _openCollections: Array = []; - @observable _textWrappedRows: Array = []; + // @observable _textWrappedRows: Array = []; @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() { - console.log("columns"); return Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField), []); } + set columns(columns: SchemaHeaderField[]) { + this.props.Document.schemaColumns = new List(columns); + } + @computed get childDocs() { if (this.props.childDocs) return this.props.childDocs; @@ -300,7 +304,14 @@ export class SchemaTable extends React.Component { 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 textWrappedRows() { + return Cast(this.props.Document.textwrappedSchemaRows, listSpec("string"), []); + } + set textWrappedRows(textWrappedRows: string[]) { + this.props.Document.textwrappedSchemaRows = new List(textWrappedRows); + } + @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); @@ -345,6 +356,7 @@ export class SchemaTable extends React.Component { setColumnType={this.setColumnType} setColumnSort={this.setColumnSort} removeColumnSort={this.removeColumnSort} + setColumnColor={this.setColumnColor} />; return { @@ -399,19 +411,6 @@ export class SchemaTable extends React.Component { return 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; - // } constructor(props: SchemaTableProps) { super(props); // convert old schema columns (list of strings) into new schema columns (list of schema header fields) @@ -436,8 +435,7 @@ 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; if (children.indexOf(document) !== -1) { children.splice(children.indexOf(document), 1); @@ -456,11 +454,10 @@ 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, - rowWrapped: this._textWrappedRows.findIndex(id => rowInfo.original[Id] === id) > -1 + textWrapRow: this.toggleTextWrapRow, + rowWrapped: this.textWrappedRows.findIndex(id => rowInfo.original[Id] === id) > -1 }; } @@ -471,9 +468,7 @@ export class SchemaTable extends React.Component { let row = rowInfo.index; //@ts-ignore 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!); return { style: { border: !this._headerIsEditing && isFocused ? "2px solid rgb(255, 160, 160)" : "1px solid #f1efeb" @@ -481,19 +476,6 @@ export class SchemaTable extends React.Component { }; } - // 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)) { - // } else { - // this._isOpen = false; - // this.props.setIsEditing(false); - // } - // } - @action onExpandCollection = (collection: Doc): void => { this._openCollections.push(collection[Id]); @@ -533,8 +515,6 @@ 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; const pdoc = FieldValue(children[this._focusedCell.row]); pdoc && this.props.setPreviewDoc(pdoc); @@ -543,8 +523,6 @@ 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; switch (direction) { case "tab": @@ -569,81 +547,74 @@ 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); } @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); - - // const fdoc = FieldValue(children[this._focusedCell.row]); - // fdoc && this.props.setPreviewDoc(fdoc); } 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 newDoc = Docs.Create.TextDocument({ width: 100, height: 30 }); let proto = Doc.GetProto(newDoc); proto.title = ""; children.push(newDoc); + this.childDocs = children; } @action createColumn = () => { let index = 0; - let found = this.columns.findIndex(col => col.heading.toUpperCase() === "New field".toUpperCase()) > -1; + let columns = this.columns; + let found = columns.findIndex(col => col.heading.toUpperCase() === "New field".toUpperCase()) > -1; if (!found) { - console.log("create column found"); - this.columns.push(new SchemaHeaderField("New field", "#f1efeb")); + columns.push(new SchemaHeaderField("New field", "#f1efeb")); + this.columns = columns; return; } while (found) { index++; - found = this.columns.findIndex(col => col.heading.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1; + found = columns.findIndex(col => col.heading.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1; } - console.log("create column new"); - this.columns.push(new SchemaHeaderField("New field (" + index + ")", "#f1efeb")); + columns.push(new SchemaHeaderField("New field (" + index + ")", "#f1efeb")); + this.columns = columns; } @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([]); + let columns = this.columns; + // let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField)); + if (columns === undefined) { + this.columns = new List([]); } else { - const index = list.map(c => c.heading).indexOf(key); + const index = columns.map(c => c.heading).indexOf(key); if (index > -1) { - list.splice(index, 1); + columns.splice(index, 1); + this.columns = columns; } } } @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, "#f1efeb")]); + // let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField)); + let columns = this.columns; + if (columns === undefined) { + // console.log("change columns new"); + this.columns = new List([new SchemaHeaderField(newKey, "f1efeb")]); } else { - console.log("change column"); if (addNew) { - this.columns.push(new SchemaHeaderField(newKey, "#f1efeb")); + columns.push(new SchemaHeaderField(newKey, "f1efeb")); + this.columns = columns; } else { - const index = list.map(c => c.heading).indexOf(oldKey); + const index = columns.map(c => c.heading).indexOf(oldKey); if (index > -1) { - list[index] = new SchemaHeaderField(newKey, "#f1efeb"); + columns[index] = new SchemaHeaderField(newKey, columns[index].color); + this.columns = columns; } } } @@ -667,16 +638,39 @@ export class SchemaTable extends React.Component { return NumCast(typesDoc[column.heading]); } - 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; + setColumnType = (columnField: SchemaHeaderField, type: ColumnType): void => { + if (columnTypes.get(columnField.heading)) return; + + let columns = this.columns; + let index = columns.indexOf(columnField); + if (index > -1) { + // let column = columns[index]; + columnField.type = NumCast(type); + columns[index] = columnField; + this.columns = columns; + } + + // 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; + // } + } + + setColumnColor = (columnField: SchemaHeaderField, color: string): void => { + // console.log("setting color", key); + let columns = this.columns; + let index = columns.indexOf(columnField); + if (index > -1) { + // let column = columns[index]; + columnField.color = color; + columns[index] = columnField; + this.columns = columns; + console.log(columnField, this.columns[index]); } } @@ -694,7 +688,8 @@ export class SchemaTable extends React.Component { if (oldIndex === newIndex) return; columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]); - this.setColumns(columns); + this.columns = columns; + // this.setColumns(columns); } @action @@ -725,14 +720,18 @@ export class SchemaTable extends React.Component { } @action - textWrapRow = (doc: Doc): void => { - let index = this._textWrappedRows.findIndex(id => doc[Id] === id); + toggleTextWrapRow = (doc: Doc): void => { + let textWrapped = this.textWrappedRows; + let index = textWrapped.findIndex(id => doc[Id] === id); + console.log("toggle text wrap", index); + if (index > -1) { - this._textWrappedRows.splice(index, 1); + textWrapped.splice(index, 1); } else { - this._textWrappedRows.push(doc[Id]); + textWrapped.push(doc[Id]); } + this.textWrappedRows = textWrapped; } @computed @@ -748,7 +747,7 @@ export class SchemaTable extends React.Component { let expanded = {}; //@ts-ignore expandedRowsList.forEach(row => expanded[row] = true); - console.log(...[...this._textWrappedRows]); // TODO: get component to rerender on text wrap change without needign to console.log :(((( + console.log("text wrapped rows", ...[...this.textWrappedRows]); // TODO: get component to rerender on text wrap change without needign to console.log :(((( return { + // private _textwrapAllRows: boolean = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0; togglePreview = () => { let dividerWidth = 4; @@ -373,14 +377,43 @@ export class CollectionSchemaViewChrome extends React.Component { + console.log("toggle text wrap"); + let textwrappedRows = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []); + if (textwrappedRows.length) { + console.log("unwrap"); + this.props.CollectionView.props.Document.textwrappedSchemaRows = new List([]); + } else { + console.log("wrap"); + 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) { + let allRows = [docs[Id]]; + console.log(...[...allRows]); + this.props.CollectionView.props.Document.textwrappedSchemaRows = new List(allRows); + } else { + let allRows = docs.map(doc => doc[Id]); + console.log(...[...allRows]); + this.props.CollectionView.props.Document.textwrappedSchemaRows = new List(allRows); + } + } } render() { let previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth); + let textWrapped = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0; + return (
+
Textwrap
Show Preview
); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 7decadbe9..476a0f957 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -135,7 +135,7 @@ export class MarqueeView extends React.Component doc.width = 200; docList.push(doc); } - let newCol = Docs.Create.SchemaDocument([...(groupAttr ? [new SchemaHeaderField("_group", "#f1efeb")] : []), ...columns.filter(c => c).map(c => new SchemaHeaderField(c))], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 }); + let newCol = Docs.Create.SchemaDocument([...(groupAttr ? [new SchemaHeaderField("_group", "#f1efeb")] : []), ...columns.filter(c => c).map(c => new SchemaHeaderField(c, "#f1efeb"))], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 }); this.props.addDocument(newCol, false); } diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts index 475296d5c..9f716bf9f 100644 --- a/src/new_fields/SchemaHeaderField.ts +++ b/src/new_fields/SchemaHeaderField.ts @@ -6,7 +6,7 @@ import { scriptingGlobal, Scripting } from "../client/util/Scripting"; import { ColumnType } from "../client/views/collections/CollectionSchemaView"; export const PastelSchemaPalette = new Map([ - ["pink1", "#FFB4E8"], + // ["pink1", "#FFB4E8"], ["pink2", "#ff9cee"], ["pink3", "#ffccf9"], ["pink4", "#fcc2ff"], @@ -32,7 +32,7 @@ export const PastelSchemaPalette = new Map([ ["yellow2", "#e7ffac"], ["yellow3", "#ffffd1"], ["yellow4", "#fff5ba"], - ["red1", "#ffc9de"], + // ["red1", "#ffc9de"], ["red2", "#ffabab"], ["red3", "#ffbebc"], ["red4", "#ffcbc1"], @@ -45,15 +45,16 @@ export const RandomPastel = () => Array.from(PastelSchemaPalette.values())[Math. export class SchemaHeaderField extends ObjectField { @serializable(primitive()) heading: string; + @serializable(primitive()) color: string; + @serializable(primitive()) type: number; - constructor(heading: string = "", color: string, type?: ColumnType) { - console.log("CREATING SCHEMA HEADER FIELD"); + constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType) { super(); this.heading = heading; - this.color = color === undefined ? "#000" : color; + this.color = color; if (type) { this.type = type; } -- cgit v1.2.3-70-g09d2 From 09d8f7925962d120d66d467b60d872bef51f8846 Mon Sep 17 00:00:00 2001 From: fawn Date: Mon, 29 Jul 2019 18:05:38 -0400 Subject: can press enter to change column key --- .../views/collections/CollectionSchemaHeaders.tsx | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index 088ad7ecd..12323fa0d 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -129,7 +129,7 @@ export class CollectionSchemaColumnMenu extends React.Component changeColumnType = (type: ColumnType): void => { console.log("change type", this.props.columnField.heading); - // this.props.setColumnType(this.props.columnField, type); + this.props.setColumnType(this.props.columnField, type); } @action @@ -265,9 +265,10 @@ interface KeysDropdownProps { @observer class KeysDropdown extends React.Component { @observable private _key: string = this.props.keyValue; - @observable private _searchTerm: string = ""; + @observable private _searchTerm: string = this.props.keyValue; @observable private _isOpen: boolean = false; @observable private _canClose: boolean = true; + @observable private _inputRef: React.RefObject = React.createRef(); @action setSearchTerm = (value: string): void => { this._searchTerm = value; }; @action setKey = (key: string): void => { this._key = key; }; @@ -281,6 +282,21 @@ class KeysDropdown extends React.Component { this.props.setIsEditing(false); } + @action + onKeyDown = (e: React.KeyboardEvent): void => { + if (e.key === "Enter") { + 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; + + if (!exactFound && this._searchTerm !== "" && this.props.canAddNew) { + this.onSelect(this._searchTerm); + } else { + this._searchTerm = this._key; + } + } + } + onChange = (val: string): void => { this.setSearchTerm(val); } @@ -333,7 +349,7 @@ class KeysDropdown extends React.Component { render() { return (
- this.onChange(e.target.value)} onFocus={this.onFocus} onBlur={this.onBlur}>
{this.renderOptions()} -- cgit v1.2.3-70-g09d2 From 596e756ded016c6bef56f6b74dcd3a717838d614 Mon Sep 17 00:00:00 2001 From: fawn Date: Mon, 29 Jul 2019 18:52:24 -0400 Subject: schema scrolling when there are too many rows/cols is ok, and column menus aren't hidden --- .../views/collections/CollectionSchemaView.scss | 25 ++++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 487907c1c..c1d25f437 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -13,7 +13,8 @@ // overflow: hidden; // overflow-x: scroll; // border: none; - overflow: hidden; + overflow: scroll; + // overflow-y: scroll; transition: top 0.5s; // .collectionSchemaView-cellContents { @@ -69,21 +70,22 @@ .ReactTable { width: 100%; - height: 100%; + // height: 100%; background: white; box-sizing: border-box; border: none !important; .rt-table { - overflow-y: auto; - overflow-x: auto; + // overflow-y: auto; + // overflow-x: auto; height: 100%; display: -webkit-inline-box; direction: ltr; + overflow: visible; } .rt-thead { - width: calc(100% - 50px); + width: calc(100% - 52px); margin-left: 50px; &.-header { @@ -121,6 +123,7 @@ } .rt-tbody { + width: calc(100% - 2px); direction: rtl; overflow: visible; } @@ -480,6 +483,9 @@ button.add-column { .collectionSchemaView-table { width: calc(100% - 7px); + height: 100%; + // overflow-y: scroll; + overflow: visible; } .sub { @@ -489,10 +495,11 @@ button.add-column { width: calc(100% - 50px); margin-left: 50px; - .rt-table { - overflow-x: hidden; // todo; this shouldnt be like this :(( - overflow-y: visible; - } // TODO fix + // .rt-table { + // // overflow-x: hidden; // todo; this shouldnt be like this :(( + // // overflow-y: visible; + // // overflow: visible; + // } // TODO fix .row-dragger { background-color: rgb(252, 252, 252); -- cgit v1.2.3-70-g09d2 From 5d1135faa9506ed136b2fa0d298e23fd07ca8c1f Mon Sep 17 00:00:00 2001 From: fawn Date: Mon, 29 Jul 2019 21:41:56 -0400 Subject: schema preview in right position again --- .../views/collections/CollectionSchemaView.scss | 27 ++++++++++-- .../views/collections/CollectionSchemaView.tsx | 48 ++++++++-------------- 2 files changed, 41 insertions(+), 34 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index c1d25f437..dc6ca060d 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -13,9 +13,12 @@ // overflow: hidden; // overflow-x: scroll; // border: none; - overflow: scroll; + // overflow: scroll; // overflow-y: scroll; transition: top 0.5s; + display: flex; + justify-content: space-between; + flex-wrap: nowrap; // .collectionSchemaView-cellContents { // height: $MAX_ROW_HEIGHT; @@ -26,10 +29,16 @@ // } // } + .collectionSchemaView-tableContainer { + width: 100%; + height: 100%; + overflow: scroll; + } + .collectionSchemaView-previewRegion { position: relative; background: $light-color; - float: left; + // float: left; height: 100%; .collectionSchemaView-previewDoc { @@ -53,7 +62,7 @@ .collectionSchemaView-dividerDragger { position: relative; - float: left; + // float: left; height: 100%; width: 20px; z-index: 20; @@ -74,6 +83,7 @@ background: white; box-sizing: border-box; border: none !important; + float: none !important; .rt-table { // overflow-y: auto; @@ -526,4 +536,15 @@ button.add-column { left: 50%; transform: translate(-50%, -50%); } +} + +.collectionSchemaView-addRow { + color: gray; + letter-spacing: 2px; + text-transform: uppercase; + cursor: pointer; + font-size: 10.5px; + padding: 10px; + margin-left: 50px; + margin-top: 10px; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 2ce6f1be3..0f9c9ca51 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -122,8 +122,14 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @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]); + console.log("divider", nativeWidth.right - nativeWidth.left, this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]); + let minWidth = 40; + let maxWidth = 1000; + let movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]; + let width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth; + this.props.Document.schemaPreviewWidth = width; + // 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 => { @@ -237,9 +243,10 @@ 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.schemaTable} +
+
this.onDrop(e, {})} ref={this.createTarget}> + {this.schemaTable} +
{this.dividerDragger} {!this.previewWidth() ? (null) : this.previewPanel}
@@ -280,8 +287,6 @@ export class SchemaTable extends React.Component { @observable _focusedCell: { row: number, col: number } = { row: 0, col: 0 }; @observable _sortedColumns: Map = new Map(); @observable _openCollections: Array = []; - // @observable _textWrappedRows: Array = []; - @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; } @@ -321,8 +326,6 @@ 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; if (children.reduce((found, doc) => found || doc.type === "collection", false)) { @@ -587,7 +590,6 @@ export class SchemaTable extends React.Component { @action deleteColumn = (key: string) => { let columns = this.columns; - // let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField)); if (columns === undefined) { this.columns = new List([]); } else { @@ -601,10 +603,8 @@ export class SchemaTable extends React.Component { @action changeColumns = (oldKey: string, newKey: string, addNew: boolean) => { - // let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField)); let columns = this.columns; if (columns === undefined) { - // console.log("change columns new"); this.columns = new List([new SchemaHeaderField(newKey, "f1efeb")]); } else { if (addNew) { @@ -689,7 +689,6 @@ export class SchemaTable extends React.Component { columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]); this.columns = columns; - // this.setColumns(columns); } @action @@ -703,9 +702,7 @@ export class SchemaTable extends React.Component { } get documentKeys() { - const docs = DocListCast(this.props.Document[this.props.fieldKey]); - - // let docs = this.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 @@ -736,12 +733,10 @@ 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 previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; + console.log(previewWidth); 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 = {}; @@ -750,7 +745,7 @@ export class SchemaTable extends React.Component { console.log("text wrapped rows", ...[...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
; } } @@ -785,8 +779,6 @@ 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; - let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; - // 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"; @@ -804,11 +796,7 @@ 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 docs = this.childDocs; row = row % docs.length; while (row < 0) row += docs.length; @@ -880,13 +868,11 @@ export class SchemaTable extends React.Component { } 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.props.onDrop(e, {})} onContextMenu={this.onContextMenu} > {this.reactTable} - +
this.createRow()}>+ new
); } -- cgit v1.2.3-70-g09d2 From 6efe31636305bf5120d472f456b69d1b699b2ae8 Mon Sep 17 00:00:00 2001 From: fawn Date: Mon, 29 Jul 2019 22:48:31 -0400 Subject: styled toggle buttons on schema chrome --- .../views/collections/CollectionSchemaView.scss | 3 +- .../views/collections/CollectionSchemaView.tsx | 6 --- .../views/collections/CollectionViewChromes.scss | 51 ++++++++++++++++++++++ .../views/collections/CollectionViewChromes.tsx | 29 ++++++++---- 4 files changed, 73 insertions(+), 16 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index dc6ca060d..e826ff63a 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -492,7 +492,8 @@ button.add-column { } .collectionSchemaView-table { - width: calc(100% - 7px); + // width: calc(100% - 7px); + width: 100%; height: 100%; // overflow-y: scroll; overflow: visible; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 0f9c9ca51..26b19474a 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -122,7 +122,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action onDividerMove = (e: PointerEvent): void => { let nativeWidth = this._mainCont!.getBoundingClientRect(); - console.log("divider", nativeWidth.right - nativeWidth.left, this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]); let minWidth = 40; let maxWidth = 1000; let movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]; @@ -240,8 +239,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 (
this.onDrop(e, {})} ref={this.createTarget}> @@ -419,7 +416,6 @@ export class SchemaTable extends React.Component { // 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 && typeof oldSchemaColumns[0] !== "object") { - console.log("REMAKING COLUMNs"); let newSchemaColumns = oldSchemaColumns.map(i => typeof i === "string" ? new SchemaHeaderField(i, "#f1efeb") : i); this.props.Document.schemaColumns = new List(newSchemaColumns); } @@ -720,7 +716,6 @@ export class SchemaTable extends React.Component { toggleTextWrapRow = (doc: Doc): void => { let textWrapped = this.textWrappedRows; let index = textWrapped.findIndex(id => doc[Id] === id); - console.log("toggle text wrap", index); if (index > -1) { textWrapped.splice(index, 1); @@ -736,7 +731,6 @@ export class SchemaTable extends React.Component { let children = this.childDocs; let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; - console.log(previewWidth); 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 = {}; diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index f9f3ce473..933ba7411 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -165,4 +165,55 @@ cursor: text; } } +} + +.collectionSchemaViewChrome-cont { + display: flex; + font-size: 10.5px; + + .collectionSchemaViewChrome-toggle { + display: flex; + margin-left: 10px; + } + + .collectionSchemaViewChrome-label { + text-transform: uppercase; + letter-spacing: 2px; + margin-right: 5px; + display: flex; + flex-direction: column; + justify-content: center; + } + + .collectionSchemaViewChrome-toggler { + width: 100px; + height: 41px; + background-color: black; + position: relative; + } + + .collectionSchemaViewChrome-togglerButton { + width: 47px; + height: 35px; + background-color: lightgray; + // position: absolute; + transition: all 0.5s ease; + // top: 3px; + margin-top: 3px; + color: gray; + letter-spacing: 2px; + text-transform: uppercase; + display: flex; + flex-direction: column; + justify-content: center; + text-align: center; + + &.on { + margin-left: 3px; + } + + &.off { + margin-left: 50px; + } + } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 8691bea8a..92afb3888 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -20,6 +20,7 @@ import { COLLECTION_BORDER_WIDTH } from "../globalCssVariables.scss"; import { listSpec } from "../../../new_fields/Schema"; import { List } from "../../../new_fields/List"; import { Id } from "../../../new_fields/FieldSymbols"; +import { threadId } from "worker_threads"; const datepicker = require('js-datepicker'); interface CollectionViewChromeProps { @@ -381,13 +382,10 @@ export class CollectionSchemaViewChrome extends React.Component { - console.log("toggle text wrap"); let textwrappedRows = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []); if (textwrappedRows.length) { - console.log("unwrap"); this.props.CollectionView.props.Document.textwrappedSchemaRows = new List([]); } else { - console.log("wrap"); 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") { @@ -396,11 +394,9 @@ export class CollectionSchemaViewChrome extends React.Component(allRows); } else { let allRows = docs.map(doc => doc[Id]); - console.log(...[...allRows]); this.props.CollectionView.props.Document.textwrappedSchemaRows = new List(allRows); } } @@ -412,10 +408,25 @@ export class CollectionSchemaViewChrome extends React.Component 0; return ( -
-
Textwrap
-
Show Preview
-
+
+
+
Wrap Text:
+
+
+ {textWrapped ? "on" : "off"} +
+
+
+ +
+
Show Preview:
+
+
+ {previewWidth !== 0 ? "on" : "off"} +
+
+
+
); } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From f9dbc263048bc269f8f128bacabe1fcbd868bd10 Mon Sep 17 00:00:00 2001 From: fawn Date: Mon, 29 Jul 2019 23:58:54 -0400 Subject: can pick colors on schema columns git add -Agit add -A! --- .../views/collections/CollectionSchemaHeaders.tsx | 48 ++++++---------------- .../views/collections/CollectionSchemaView.scss | 30 ++++++++++++-- .../views/collections/CollectionViewChromes.scss | 2 +- 3 files changed, 41 insertions(+), 39 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index 12323fa0d..84132ef2e 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -10,7 +10,7 @@ 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"; +import { SchemaHeaderField, RandomPastel, PastelSchemaPalette } from "../../../new_fields/SchemaHeaderField"; library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faFile); @@ -73,8 +73,6 @@ export class CollectionSchemaAddColumnHeader extends React.Component } } - setNewColor = (color: string): void => { - this.changeColumnType(ColumnType.Any); - console.log("change color", this.props.columnField.heading); - this.props.setColumnColor(this.props.columnField, color); - } - @action toggleIsOpen = (): void => { this._isOpen = !this._isOpen; @@ -128,10 +120,13 @@ export class CollectionSchemaColumnMenu extends React.Component } changeColumnType = (type: ColumnType): void => { - console.log("change type", this.props.columnField.heading); this.props.setColumnType(this.props.columnField, type); } + changeColumnColor = (color: string): void => { + this.props.setColumnColor(this.props.columnField, color); + } + @action setNode = (node: HTMLDivElement): void => { if (node) { @@ -179,34 +174,17 @@ export class CollectionSchemaColumnMenu extends React.Component } renderColors = () => { + let selected = this.props.columnField.color; return (
- this.setNewColor("#FFB4E8")} /> - - this.setNewColor("#b28dff")} /> - - this.setNewColor("#afcbff")} /> - - this.setNewColor("#fff5ba")} /> - - this.setNewColor("#ffabab")} /> - - this.setNewColor("#f1efeb")} /> - +
this.changeColumnColor("#FFB4E8")}>
+
this.changeColumnColor("#b28dff")}>
+
this.changeColumnColor("#afcbff")}>
+
this.changeColumnColor("#fff5ba")}>
+
this.changeColumnColor("#ffabab")}>
+
this.changeColumnColor("#f1efeb")}>
); @@ -231,7 +209,7 @@ export class CollectionSchemaColumnMenu extends React.Component <> {this.renderTypes()} {this.renderSorting()} - {/* {this.renderColors()} */} + {this.renderColors()}
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index e826ff63a..ca2684ba2 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -327,6 +327,18 @@ button.add-column { button { border-radius: 20px; + width: 22px; + height: 22px; + text-align: center; + display: flex; + justify-content: center; + flex-direction: column; + padding: 0; + + &.active { + border: 2px solid white; + box-shadow: 0 0 0 2px lightgray; + } } } @@ -335,15 +347,27 @@ button.add-column { justify-content: space-between; flex-wrap: wrap; - input[type="radio"] { - display: none; - } + // input[type="radio"] { + // display: none; + // } + + // input[type="radio"]:checked + label { + // .columnMenu-colorPicker { + // border: 2px solid white; + // box-shadow: 0 0 0 2px lightgray; + // } + // } .columnMenu-colorPicker { cursor: pointer; width: 20px; height: 20px; border-radius: 10px; + + &.active { + border: 2px solid white; + box-shadow: 0 0 0 2px lightgray; + } } } } diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index 933ba7411..0d476e234 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -195,7 +195,7 @@ .collectionSchemaViewChrome-togglerButton { width: 47px; height: 35px; - background-color: lightgray; + background-color: $light-color-secondary; // position: absolute; transition: all 0.5s ease; // top: 3px; -- cgit v1.2.3-70-g09d2 From ed85a99f138c1c4609f4465f242185ecd3886eb7 Mon Sep 17 00:00:00 2001 From: fawn Date: Tue, 30 Jul 2019 12:26:43 -0400 Subject: schema column dragging has slight delay --- .../CollectionSchemaMovableTableHOC.tsx | 37 +++++++++++++++------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 7342ede7a..2e4f276bf 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -26,6 +26,9 @@ export interface MovableColumnProps { export class MovableColumn extends React.Component { private _header?: React.RefObject = React.createRef(); private _colDropDisposer?: DragManager.DragDropDisposer; + private _startDragPosition: { x: number, y: number } = { x: 0, y: 0 }; + private _sensitivity: number = 16; + private _dragRef: React.RefObject = React.createRef(); onPointerEnter = (e: React.PointerEvent): void => { if (e.buttons === 1 && SelectionManager.GetIsDragging()) { @@ -36,6 +39,7 @@ export class MovableColumn extends React.Component { onPointerLeave = (e: React.PointerEvent): void => { this._header!.current!.className = "collectionSchema-col-wrapper"; document.removeEventListener("pointermove", this.onDragMove, true); + document.removeEventListener("pointermove", this.onPointerMove); } onDragMove = (e: PointerEvent): void => { let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); @@ -68,7 +72,7 @@ export class MovableColumn extends React.Component { return false; } - setupDrag(ref: React.RefObject) { + onPointerMove = (e: PointerEvent) => { let onRowMove = (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); @@ -76,35 +80,46 @@ export class MovableColumn extends React.Component { 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); + DragManager.StartColumnDrag(this._dragRef.current!, dragData, e.x, e.y); + console.log("SETUP DRAG"); }; let onRowUp = (): void => { document.removeEventListener("pointermove", onRowMove); document.removeEventListener('pointerup', onRowUp); }; - let onItemDown = (e: React.PointerEvent) => { - if (e.button === 0) { + if (e.buttons === 1) { + let [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y); + console.log("moving this much", Math.abs(dx), Math.abs(dy)); + if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) { + document.removeEventListener("pointermove", this.onPointerMove); e.stopPropagation(); + document.addEventListener("pointermove", onRowMove); document.addEventListener("pointerup", onRowUp); } - }; - return onItemDown; + } } - // onColDrag = (e: React.DragEvent, ref: React.RefObject) => { - // this.setupDrag(reference); - // } + onPointerUp = (e: React.PointerEvent) => { + document.removeEventListener("pointermove", this.onPointerMove); + } + + @action + onPointerDown = (e: React.PointerEvent, ref: React.RefObject) => { + this._dragRef = ref; + let [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX, e.clientY); + this._startDragPosition = { x: dx, y: dy }; + document.addEventListener("pointermove", this.onPointerMove); + } render() { let reference = React.createRef(); - let onItemDown = this.setupDrag(reference); return (
-
+
this.onPointerDown(e, reference)} onPointerUp={this.onPointerUp}> {this.props.columnRenderer}
-- cgit v1.2.3-70-g09d2 From 1d8c80a366c743479a8eb1c8c21ecad21942da73 Mon Sep 17 00:00:00 2001 From: fawn Date: Tue, 30 Jul 2019 12:45:57 -0400 Subject: stacking column dragging has slight delay --- .../views/collections/CollectionStackingView.tsx | 5 ++- .../CollectionStackingViewFieldColumn.tsx | 42 ++++++++++++++-------- 2 files changed, 31 insertions(+), 16 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index f647da8f0..089cd3866 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -248,7 +248,10 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { docList={docList} parent={this} type={type} - createDropTarget={this.createDropTarget} />; + createDropTarget={this.createDropTarget} + screenToLocalTransform={this.props.ScreenToLocalTransform} + />; + } @action diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 387e189e7..6edfe55e5 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -19,6 +19,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { ScriptField } from "../../../new_fields/ScriptField"; import { CompileScript } from "../../util/Scripting"; import { RichTextField } from "../../../new_fields/RichTextField"; +import { Transform } from "../../util/Transform"; interface CSVFieldColumnProps { @@ -30,6 +31,7 @@ interface CSVFieldColumnProps { parent: CollectionStackingView; type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined; createDropTarget: (ele: HTMLDivElement) => void; + screenToLocalTransform: () => Transform; } @observer @@ -39,6 +41,8 @@ export class CollectionStackingViewFieldColumn extends React.Component = React.createRef(); + private _startDragPosition: { x: number, y: number } = { x: 0, y: 0 }; + private _sensitivity: number = 16; @observable _heading = this.props.headingObject ? this.props.headingObject.heading : this.props.heading; @@ -159,6 +163,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { this._background = "white"; + document.removeEventListener("pointermove", this.startDrag); } @action @@ -180,22 +185,26 @@ 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); - } + let [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y); + if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) { + console.log("start stack drag"); + 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); + e.stopPropagation(); + document.removeEventListener("pointermove", this.startDrag); + document.removeEventListener("pointerup", this.pointerUp); + } } pointerUp = (e: PointerEvent) => { @@ -210,6 +219,9 @@ export class CollectionStackingViewFieldColumn extends React.Component Date: Tue, 30 Jul 2019 13:15:19 -0400 Subject: schema column widths get saved --- .../CollectionSchemaMovableTableHOC.tsx | 2 - .../views/collections/CollectionSchemaView.tsx | 44 ++++++++++++++-------- .../CollectionStackingViewFieldColumn.tsx | 1 - src/new_fields/SchemaHeaderField.ts | 5 ++- 4 files changed, 32 insertions(+), 20 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 2e4f276bf..483463c2b 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -81,7 +81,6 @@ export class MovableColumn extends React.Component { document.removeEventListener('pointerup', onRowUp); let dragData = new DragManager.ColumnDragData(this.props.columnValue); DragManager.StartColumnDrag(this._dragRef.current!, dragData, e.x, e.y); - console.log("SETUP DRAG"); }; let onRowUp = (): void => { document.removeEventListener("pointermove", onRowMove); @@ -89,7 +88,6 @@ export class MovableColumn extends React.Component { }; if (e.buttons === 1) { let [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y); - console.log("moving this much", Math.abs(dx), Math.abs(dy)); if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) { document.removeEventListener("pointermove", this.onPointerMove); e.stopPropagation(); diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 26b19474a..722d8b1f9 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -4,10 +4,10 @@ import { faCog, faPlus, faTable, faSortUp, faSortDown } from '@fortawesome/free- 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, RowInfo } from "react-table"; +import ReactTable, { CellInfo, ComponentPropsGetterR, Column, RowInfo, ResizedChangeFunction, Resize } from "react-table"; import "react-table/react-table.css"; -import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils"; -import { Doc, DocListCast, DocListCastAsync, Field, FieldResult, Opt } from "../../../new_fields/Doc"; +import { emptyFunction, returnOne } from "../../../Utils"; +import { Doc, DocListCast, Field, Opt } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; @@ -17,28 +17,21 @@ import { Gateway } from "../../northstar/manager/Gateway"; import { SetupDrag, DragManager } from "../../util/DragManager"; import { CompileScript, ts, Transformer } from "../../util/Scripting"; import { Transform } from "../../util/Transform"; -import { COLLECTION_BORDER_WIDTH, MAX_ROW_HEIGHT } from '../../views/globalCssVariables.scss'; +import { COLLECTION_BORDER_WIDTH } from '../../views/globalCssVariables.scss'; import { ContextMenu } from "../ContextMenu"; -import { anchorPoints, Flyout } from "../DocumentDecorations"; import '../DocumentDecorations.scss'; -import { EditableView } from "../EditableView"; import { DocumentView } from "../nodes/DocumentView"; -import { FieldView, FieldViewProps } from "../nodes/FieldView"; import { CollectionPDFView } from "./CollectionPDFView"; import "./CollectionSchemaView.scss"; import { CollectionSubView } from "./CollectionSubView"; 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, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaBooleanCell, CollectionSchemaCheckboxCell, CollectionSchemaDocCell } from "./CollectionSchemaCells"; import { MovableColumn, MovableRow } from "./CollectionSchemaMovableTableHOC"; -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"; +import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; library.add(faCog, faPlus, faSortUp, faSortDown); @@ -314,6 +307,16 @@ export class SchemaTable extends React.Component { this.props.Document.textwrappedSchemaRows = new List(textWrappedRows); } + @computed get resized(): { "id": string, "value": number }[] { + let columns = this.columns; + return columns.reduce((resized, shf) => { + if (shf.width > -1) { + resized.push({ "id": shf.heading, "value": shf.width }); + } + return resized; + }, [] as { "id": string, "value": number }[]); + } + @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); @@ -658,15 +661,12 @@ export class SchemaTable extends React.Component { } setColumnColor = (columnField: SchemaHeaderField, color: string): void => { - // console.log("setting color", key); let columns = this.columns; let index = columns.indexOf(columnField); if (index > -1) { - // let column = columns[index]; columnField.color = color; columns[index] = columnField; this.columns = columns; - console.log(columnField, this.columns[index]); } } @@ -730,7 +730,7 @@ export class SchemaTable extends React.Component { get reactTable() { let children = this.childDocs; - let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; + // let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; 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 = {}; @@ -751,6 +751,8 @@ export class SchemaTable extends React.Component { TrComponent={MovableRow} sorted={Array.from(this._sortedColumns.values())} expanded={expanded} + resized={this.resized} + onResizedChange={this.onResizedChange} SubComponent={hasCollectionChild ? row => { if (row.original.type === "collection") { @@ -762,6 +764,16 @@ export class SchemaTable extends React.Component { />; } + onResizedChange = (newResized: Resize[], event: any) => { + let columns = this.columns; + newResized.forEach(resized => { + let index = columns.findIndex(c => c.heading === resized.id); + let column = columns[index]; + column.width = resized.value; + }); + this.columns = columns; + } + 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, icon: "table" }); diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 6edfe55e5..01938a3b4 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -187,7 +187,6 @@ export class CollectionStackingViewFieldColumn extends React.Component { let [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y); if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) { - console.log("start stack drag"); let alias = Doc.MakeAlias(this.props.parent.props.Document); let key = StrCast(this.props.parent.props.Document.sectionFilter); let value = this.getValue(this._heading); diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts index 9f716bf9f..15b497759 100644 --- a/src/new_fields/SchemaHeaderField.ts +++ b/src/new_fields/SchemaHeaderField.ts @@ -49,8 +49,10 @@ export class SchemaHeaderField extends ObjectField { color: string; @serializable(primitive()) type: number; + @serializable(primitive()) + width: number; - constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType) { + constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType, width?: number) { super(); this.heading = heading; @@ -61,6 +63,7 @@ export class SchemaHeaderField extends ObjectField { else { this.type = 0; } + this.width = width ? width : -1; } setHeading(heading: string) { -- cgit v1.2.3-70-g09d2 From f03f94accabc2336d1c143fcb80bb0c3f5b70d99 Mon Sep 17 00:00:00 2001 From: kimdahey Date: Tue, 30 Jul 2019 13:29:27 -0400 Subject: added toggle button --- package.json | 2 + .../views/collections/CollectionStackingView.scss | 53 +++++++++++++++++++++- .../views/collections/CollectionStackingView.tsx | 21 ++++++++- .../CollectionStackingViewFieldColumn.tsx | 8 ++-- .../views/collections/CollectionViewChromes.tsx | 4 +- 5 files changed, 78 insertions(+), 10 deletions(-) (limited to 'src/client/views/collections') diff --git a/package.json b/package.json index 37052fde3..ae3a9d964 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,7 @@ "@types/prosemirror-transform": "^1.1.0", "@types/prosemirror-view": "^1.3.1", "@types/pug": "^2.0.4", + "@types/rc-switch": "^1.8.0", "@types/react": "^16.8.7", "@types/react-autosuggest": "^9.3.9", "@types/react-color": "^2.14.1", @@ -170,6 +171,7 @@ "pug": "^2.0.3", "query-string": "^6.8.1", "raw-loader": "^1.0.0", + "rc-switch": "^1.9.0", "react": "^16.8.4", "react-anime": "^2.2.0", "react-autosuggest": "^9.4.3", diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 0cb01dc9d..3fcec265f 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -79,8 +79,8 @@ .collectionStackingView-sectionHeader { text-align: center; - margin-left: 5px; - margin-right: 5px; + margin-left: 2px; + margin-right: 2px; margin-top: 10px; overflow: hidden; @@ -102,6 +102,7 @@ font-size: 75%; transition: transform 0.2s; position: relative; + width: 98%; .editableView-container-editing-oneLine, .editableView-container-editing { @@ -184,4 +185,52 @@ letter-spacing: 2px; height: fit-content; } + + .rc-switch { + position: absolute; + display: inline-block; + bottom: 15px; + right: 15px; + width: 125px; + height: 54px; + border-radius: 40px 40px; + } + + .rc-switch:after { + position: absolute; + width: 36px; + height: 36px; + left: 7px; + top: 9px; + border-radius: 50% 50%; + background-color: #fff; + content: " "; + cursor: pointer; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26); + -webkit-transform: scale(1); + transform: scale(1); + transition: left 0.3s cubic-bezier(0.35, 0, 0.25, 1); + -webkit-animation-timing-function: cubic-bezier(0.35, 0, 0.25, 1); + animation-timing-function: cubic-bezier(0.35, 0, 0.25, 1); + -webkit-animation-duration: 0.3s; + animation-duration: 0.3s; + } + + .rc-switch-checked:after { + left: 80px; + } + + .rc-switch-inner { + color: #fff; + font-size: 22px; + position: absolute; + left: 50px; + top: 14px; + } + + .rc-switch-checked .rc-switch-inner { + left: 17px; + } + + } \ No newline at end of file diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index bcf3a85d7..c6e889bb5 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -20,6 +20,7 @@ import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeade import { List } from "../../../new_fields/List"; import { EditableView } from "../EditableView"; import { CollectionViewProps } from "./CollectionBaseView"; +import Switch from 'rc-switch'; @observer export class CollectionStackingView extends CollectionSubView(doc => doc) { @@ -29,6 +30,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { _sectionFilterDisposer?: IReactionDisposer; _docXfs: any[] = []; _columnStart: number = 0; + _toggleTitle: string = "author mode"; @observable private cursor: CursorProperty = "grab"; get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); } @computed get chromeCollapsed() { return this.props.chromeCollapsed; } @@ -269,6 +271,14 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { return firstEntry[0].heading > secondEntry[0].heading ? 1 : -1; } + onToggle = (checked: Boolean) => { + if (checked) { + this.props.CollectionView.props.Document.chromeStatus = 'collapsed'; + } else { + this.props.CollectionView.props.Document.chromeStatus = 'view-mode'; + } + } + render() { let headings = Array.from(this.Sections.keys()); let editableViewProps = { @@ -289,11 +299,18 @@ 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.Document.sectionFilter && this.props.CollectionView.props.Document.chromeStatus !== 'view-mode') ?
+ style={{ width: (this.columnWidth / (headings.length + (this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' ? 1 : 0))) - 10, marginTop: 10 }}>
: null} + {this.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? : null}
); } diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index d8bed7e88..4f7de0c24 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -242,7 +242,7 @@ 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. */} @@ -265,7 +265,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') ? + {(this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode') ?
+ style={{ width: style.columnWidth / (uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' ? 1 : 0)) }}>
: null}
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 2bffe3cc0..9c751c4df 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 c3dcf252e53584b097e3bb2261c72c78786ab16c Mon Sep 17 00:00:00 2001 From: kimdahey Date: Tue, 30 Jul 2019 13:32:24 -0400 Subject: added description of view-mode for chrome status in collectionview --- src/client/views/collections/CollectionView.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index b7ac8768f..186b612d0 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -45,6 +45,7 @@ export class CollectionView extends React.Component { this._reactionDisposer = reaction(() => StrCast(this.props.Document.chromeStatus), () => { // chrome status is one of disabled, collapsed, or visible. this determines initial state from document + // chrome status may also be view-mode, in reference to stacking view's toggle mode. it is essentially disabled mode, but prevents the toggle button from showing up on the left sidebar. let chromeStatus = this.props.Document.chromeStatus; if (chromeStatus && (chromeStatus === "disabled" || chromeStatus === "collapsed")) { runInAction(() => this._collapsed = true); -- cgit v1.2.3-70-g09d2 From 6957339025bcc89482fac0fc7ca803966ff3ca6d Mon Sep 17 00:00:00 2001 From: kimdahey Date: Tue, 30 Jul 2019 13:47:44 -0400 Subject: small fixes --- src/client/views/collections/CollectionStackingView.scss | 1 - 1 file changed, 1 deletion(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 3fcec265f..dfb13f9de 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -102,7 +102,6 @@ font-size: 75%; transition: transform 0.2s; position: relative; - width: 98%; .editableView-container-editing-oneLine, .editableView-container-editing { -- cgit v1.2.3-70-g09d2 From 36ac0409b2a7a752727eaf2fc289d8cc72487619 Mon Sep 17 00:00:00 2001 From: kimdahey Date: Tue, 30 Jul 2019 13:49:09 -0400 Subject: small fixes --- src/client/views/collections/CollectionStackingView.tsx | 1 - 1 file changed, 1 deletion(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index c6e889bb5..fb31989a5 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -30,7 +30,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { _sectionFilterDisposer?: IReactionDisposer; _docXfs: any[] = []; _columnStart: number = 0; - _toggleTitle: string = "author mode"; @observable private cursor: CursorProperty = "grab"; get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); } @computed get chromeCollapsed() { return this.props.chromeCollapsed; } -- cgit v1.2.3-70-g09d2 From dd5d7503e05962fa9a22baa9f5fa00373393ac11 Mon Sep 17 00:00:00 2001 From: fawn Date: Tue, 30 Jul 2019 15:52:32 -0400 Subject: schema column menu stylign --- .../views/collections/CollectionSchemaHeaders.tsx | 68 +++++++++++------ .../views/collections/CollectionSchemaView.scss | 85 +++++++++++++--------- .../views/collections/CollectionSchemaView.tsx | 11 +-- src/new_fields/SchemaHeaderField.ts | 2 +- 4 files changed, 103 insertions(+), 63 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index 84132ef2e..62762962e 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -2,7 +2,7 @@ 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, faToggleOn } from '@fortawesome/free-solid-svg-icons'; +import { faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faSortAmountDown, faSortAmountUp, faTimes } 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"; @@ -12,7 +12,7 @@ import { contains } from "typescript-collections/dist/lib/arrays"; import { faFile } from "@fortawesome/free-regular-svg-icons"; import { SchemaHeaderField, RandomPastel, PastelSchemaPalette } from "../../../new_fields/SchemaHeaderField"; -library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faFile); +library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faFile, faSortAmountDown, faSortAmountUp, faTimes); export interface HeaderProps { keyValue: SchemaHeaderField; @@ -136,25 +136,32 @@ export class CollectionSchemaColumnMenu extends React.Component renderTypes = () => { if (this.props.typeConst) return <>; + + let type = this.props.columnField.type; return (
- -
+
this.changeColumnType(ColumnType.Number)}> - -
+
this.changeColumnType(ColumnType.String)}> - -
+
this.changeColumnType(ColumnType.Boolean)}> - -
+
this.changeColumnType(ColumnType.Doc)}> - + Document +
); @@ -165,9 +172,18 @@ export class CollectionSchemaColumnMenu extends React.Component
-
this.props.setColumnSort(this.props.columnField.heading, false)}>Sort ascending
-
this.props.setColumnSort(this.props.columnField.heading, true)}>Sort descending
-
this.props.removeColumnSort(this.props.columnField.heading)}>Clear sorting
+
this.props.setColumnSort(this.props.columnField.heading, true)}> + + Sort descending +
+
this.props.setColumnSort(this.props.columnField.heading, false)}> + + Sort ascending +
+
this.props.removeColumnSort(this.props.columnField.heading)}> + + Clear sorting +
); @@ -175,16 +191,24 @@ export class CollectionSchemaColumnMenu extends React.Component renderColors = () => { let selected = this.props.columnField.color; + + let pink = PastelSchemaPalette.get("pink2"); + let purple = PastelSchemaPalette.get("purple2"); + let blue = PastelSchemaPalette.get("bluegreen1"); + let yellow = PastelSchemaPalette.get("yellow4"); + let red = PastelSchemaPalette.get("red2"); + let gray = "#f1efeb"; + return (
-
this.changeColumnColor("#FFB4E8")}>
-
this.changeColumnColor("#b28dff")}>
-
this.changeColumnColor("#afcbff")}>
-
this.changeColumnColor("#fff5ba")}>
-
this.changeColumnColor("#ffabab")}>
-
this.changeColumnColor("#f1efeb")}>
+
this.changeColumnColor(pink!)}>
+
this.changeColumnColor(purple!)}>
+
this.changeColumnColor(blue!)}>
+
this.changeColumnColor(yellow!)}>
+
this.changeColumnColor(red!)}>
+
this.changeColumnColor(gray)}>
); @@ -193,8 +217,8 @@ export class CollectionSchemaColumnMenu extends React.Component renderContent = () => { return (
-
+ { } else { const index = columns.map(c => c.heading).indexOf(oldKey); if (index > -1) { - columns[index] = new SchemaHeaderField(newKey, columns[index].color); + let column = columns[index]; + column.setHeading(newKey); + columns[index] = column; this.columns = columns; } } @@ -643,8 +645,7 @@ export class SchemaTable extends React.Component { let columns = this.columns; let index = columns.indexOf(columnField); if (index > -1) { - // let column = columns[index]; - columnField.type = NumCast(type); + columnField.setType(NumCast(type)); columns[index] = columnField; this.columns = columns; } @@ -664,9 +665,9 @@ export class SchemaTable extends React.Component { let columns = this.columns; let index = columns.indexOf(columnField); if (index > -1) { - columnField.color = color; + columnField.setColor(color); columns[index] = columnField; - this.columns = columns; + this.columns = columns; // need to set the columns to trigger rerender } } diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts index 15b497759..bccf82a9e 100644 --- a/src/new_fields/SchemaHeaderField.ts +++ b/src/new_fields/SchemaHeaderField.ts @@ -15,7 +15,7 @@ export const PastelSchemaPalette = new Map([ ["purple2", "#c5a3ff"], ["purple3", "#d5aaff"], ["purple4", "#ecd4ff"], - ["purple5", "#fb34ff"], + // ["purple5", "#fb34ff"], ["purple6", "#dcd3ff"], ["purple7", "#a79aff"], ["purple8", "#b5b9ff"], -- cgit v1.2.3-70-g09d2 From 26086ee95a9a16486d637aa43c96638b6154379f Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 30 Jul 2019 16:02:42 -0400 Subject: Added document export and import --- package.json | 4 + .../collectionFreeForm/CollectionFreeFormView.tsx | 39 +++++- src/client/views/nodes/DocumentView.tsx | 10 ++ src/scraping/buxton/scraper.py | 2 + src/server/database.ts | 37 +++++- src/server/index.ts | 142 +++++++++++++++++---- 6 files changed, 202 insertions(+), 32 deletions(-) (limited to 'src/client/views/collections') diff --git a/package.json b/package.json index 37052fde3..b29355738 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,9 @@ "@hig/theme-context": "^2.1.3", "@hig/theme-data": "^2.3.3", "@trendmicro/react-dropdown": "^1.3.0", + "@types/adm-zip": "^0.4.32", "@types/animejs": "^2.0.2", + "@types/archiver": "^3.0.0", "@types/async": "^2.4.1", "@types/bcrypt-nodejs": "0.0.30", "@types/bluebird": "^3.5.25", @@ -105,6 +107,8 @@ "@types/uuid": "^3.4.4", "@types/webpack": "^4.4.25", "@types/youtube": "0.0.38", + "adm-zip": "^0.4.13", + "archiver": "^3.0.3", "async": "^2.6.2", "babel-runtime": "^6.26.0", "bcrypt-nodejs": "0.0.3", diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 8dac785e1..cbab14976 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -5,7 +5,7 @@ import { Id } from "../../../../new_fields/FieldSymbols"; import { InkField, StrokeData } from "../../../../new_fields/InkField"; import { createSchema, makeInterface } from "../../../../new_fields/Schema"; import { BoolCast, Cast, FieldValue, NumCast, StrCast } from "../../../../new_fields/Types"; -import { emptyFunction, returnOne } from "../../../../Utils"; +import { emptyFunction, returnOne, Utils } from "../../../../Utils"; import { DocumentManager } from "../../../util/DocumentManager"; import { DragManager } from "../../../util/DragManager"; import { HistoryUtil } from "../../../util/History"; @@ -34,12 +34,14 @@ 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, faCompass } from "@fortawesome/free-solid-svg-icons"; +import { faTable, faPaintBrush, faAsterisk, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload } from "@fortawesome/free-solid-svg-icons"; import { undo } from "prosemirror-history"; import { number } from "prop-types"; import { ContextMenu } from "../../ContextMenu"; +import { RouteStore } from "../../../../server/RouteStore"; +import { DocServer } from "../../../DocServer"; -library.add(faEye, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass); +library.add(faEye, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload); export const panZoomSchema = createSchema({ panX: "number", @@ -516,7 +518,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY)); } - onContextMenu = () => { + onContextMenu = (e: React.MouseEvent) => { let layoutItems: ContextMenuProps[] = []; layoutItems.push({ description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`, @@ -561,6 +563,35 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { CognitiveServices.Inking.Manager.analyzer(this.fieldExtensionDoc, relevantKeys, data.inkData); }, icon: "paint-brush" }); + ContextMenu.Instance.addItem({ + description: "Import document", icon: "upload", event: () => { + const input = document.createElement("input"); + input.type = "file"; + input.accept = ".zip"; + input.onchange = async _e => { + const files = input.files; + if (!files) return; + const file = files[0]; + let formData = new FormData(); + formData.append('file', file); + formData.append('remap', "true"); + const upload = Utils.prepend("/uploadDoc"); + const response = await fetch(upload, { method: "POST", body: formData }); + const json = await response.json(); + if (json === "error") { + return; + } + const doc = await DocServer.GetRefField(json); + if (!doc || !(doc instanceof Doc)) { + return; + } + const [x, y] = this.props.ScreenToLocalTransform().transformPoint(e.pageX, e.pageY); + doc.x = x, doc.y = y; + this.addDocument(doc, false); + }; + input.click(); + } + }); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 4b5cf3a43..58e2443c2 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -45,6 +45,7 @@ const JsxParser = require('react-jsx-parser').default; //TODO Why does this need library.add(fa.faTrash); library.add(fa.faShare); +library.add(fa.faDownload); library.add(fa.faExpandArrowsAlt); library.add(fa.faCompressArrowsAlt); library.add(fa.faLayerGroup); @@ -597,6 +598,15 @@ export class DocumentView extends DocComponent(Docu 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: "Download document", icon: "download", event: () => { + const a = document.createElement("a"); + const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`); + a.href = url; + a.download = `DocExport-${this.props.Document[Id]}.zip`; + a.click(); + } + }); cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" }); type User = { email: string, userDocumentId: string }; let usersMenu: ContextMenuProps[] = []; diff --git a/src/scraping/buxton/scraper.py b/src/scraping/buxton/scraper.py index 1ff0e3b31..8ff7cb223 100644 --- a/src/scraping/buxton/scraper.py +++ b/src/scraping/buxton/scraper.py @@ -236,6 +236,8 @@ def parse_document(file_name: str): view_guids.append(write_image(pure_name, image)) copyfile(dir_path + "/" + image, dir_path + "/" + image.replace(".", "_o.", 1)) + copyfile(dir_path + "/" + image, dir_path + + "/" + image) os.rename(dir_path + "/" + image, dir_path + "/" + image.replace(".", "_m.", 1)) print(f"extracted {count} images...") diff --git a/src/server/database.ts b/src/server/database.ts index acb6ce751..a7254fb0c 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -17,7 +17,7 @@ export class Database { }); } - public update(id: string, value: any, callback: () => void, upsert = true, collectionName = Database.DocumentsCollection) { + public update(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateWriteOpResult) => void, upsert = true, collectionName = Database.DocumentsCollection) { if (this.db) { let collection = this.db.collection(collectionName); const prom = this.currentWrites[id]; @@ -30,7 +30,7 @@ export class Database { delete this.currentWrites[id]; } resolve(); - callback(); + callback(err, res); }); }); }; @@ -41,6 +41,30 @@ export class Database { } } + public replace(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateWriteOpResult) => void, upsert = true, collectionName = Database.DocumentsCollection) { + if (this.db) { + let collection = this.db.collection(collectionName); + const prom = this.currentWrites[id]; + let newProm: Promise; + const run = (): Promise => { + return new Promise(resolve => { + collection.replaceOne({ _id: id }, value, { upsert } + , (err, res) => { + if (this.currentWrites[id] === newProm) { + delete this.currentWrites[id]; + } + resolve(); + callback(err, res); + }); + }); + }; + newProm = prom ? prom.then(run) : run(); + this.currentWrites[id] = newProm; + } else { + this.onConnect.push(() => this.replace(id, value, callback, upsert, collectionName)); + } + } + public delete(query: any, collectionName?: string): Promise; public delete(id: string, collectionName?: string): Promise; public delete(id: any, collectionName = Database.DocumentsCollection) { @@ -126,7 +150,7 @@ export class Database { } } - public async visit(ids: string[], fn: (result: any) => string[], collectionName = "newDocuments") { + public async visit(ids: string[], fn: (result: any) => string[], collectionName = "newDocuments"): Promise { if (this.db) { const visited = new Set(); while (ids.length) { @@ -145,7 +169,12 @@ export class Database { } } else { - this.onConnect.push(() => this.visit(ids, fn, collectionName)); + return new Promise(res => { + this.onConnect.push(() => { + this.visit(ids, fn, collectionName); + res(); + }); + }); } } diff --git a/src/server/index.ts b/src/server/index.ts index 230c574cf..2fa5132d0 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -27,6 +27,7 @@ import { Client } from './Client'; import { Database } from './database'; import { MessageStore, Transferable, Types, Diff, Message } from "./Message"; import { RouteStore } from './RouteStore'; +import v4 = require('uuid/v4'); const app = express(); const config = require('../../webpack.config'); import { createCanvas, loadImage, Canvas } from "canvas"; @@ -39,7 +40,10 @@ import c = require("crypto"); import { Search } from './Search'; import { debug } from 'util'; import _ = require('lodash'); +import * as Archiver from 'archiver'; +import * as AdmZip from 'adm-zip'; import { Response } from 'express-serve-static-core'; +import { DocComponent } from '../client/views/DocComponent'; const MongoStore = require('connect-mongo')(session); const mongoose = require('mongoose'); const probe = require("probe-image-size"); @@ -177,16 +181,21 @@ function msToTime(duration: number) { return hoursS + ":" + minutesS + ":" + secondsS + "." + milliseconds; } -app.get("/serializeDoc/:docId", async (req, res) => { - const files: { [name: string]: string[] } = {}; +async function getDocs(id: string) { + const files = new Set(); const docs: { [id: string]: any } = {}; const fn = (doc: any): string[] => { + const id = doc.id; + if (typeof id === "string" && id.endsWith("Proto")) { + //Skip protos + return []; + } const ids: string[] = []; - for (const key in doc) { - if (!doc.hasOwnProperty(key)) { + for (const key in doc.fields) { + if (!doc.fields.hasOwnProperty(key)) { continue; } - const field = doc[key]; + const field = doc.fields[key]; if (field === undefined || field === null) { continue; } @@ -194,7 +203,7 @@ app.get("/serializeDoc/:docId", async (req, res) => { if (field.__type === "proxy" || field.__type === "prefetch_proxy") { ids.push(field.fieldId); } else if (field.__type === "list") { - ids.push(...fn(field.fields)); + ids.push(...fn(field)); } else if (typeof field === "string") { const re = /"(?:dataD|d)ocumentId"\s*:\s*"([\w\-]*)"/g; let match: string[] | null; @@ -215,35 +224,120 @@ app.get("/serializeDoc/:docId", async (req, res) => { while ((match = re2.exec(field.Data)) !== null) { const urlString = match[1]; const pathname = new URL(urlString).pathname; - const ext = path.extname(pathname); - const fileName = path.basename(pathname, ext); - let exts = files[fileName]; - if (!exts) { - files[fileName] = exts = []; - } - exts.push(ext); + files.add(pathname); } } else if (["audio", "image", "video", "pdf", "web"].includes(field.__type)) { const url = new URL(field.url); const pathname = url.pathname; - const ext = path.extname(pathname); - const fileName = path.basename(pathname, ext); - let exts = files[fileName]; - if (!exts) { - files[fileName] = exts = []; - } - exts.push(ext); + files.add(pathname); } } - docs[doc.id] = doc; + if (doc.id) { + docs[doc.id] = doc; + } return ids; }; - Database.Instance.visit([req.params.docId], fn); + await Database.Instance.visit([id], fn); + return { id, docs, files }; +} +app.get("/serializeDoc/:docId", async (req, res) => { + const { docs, files } = await getDocs(req.params.docId); + res.send({ docs, files: Array.from(files) }); }); -app.get("/downloadId/:docId", (req, res) => { - res.download(`/serializeDoc/${req.params.docId}`, `DocumentExport.zip`); +app.get("/downloadId/:docId", async (req, res) => { + res.set('Content-disposition', `attachment;`); + res.set('Content-Type', "application/zip"); + const { id, docs, files } = await getDocs(req.params.docId); + const docString = JSON.stringify({ id, docs }); + const zip = Archiver('zip'); + zip.pipe(res); + zip.append(docString, { name: "doc.json" }); + files.forEach(val => { + zip.file(__dirname + RouteStore.public + val, { name: val.substring(1) }); + }); + zip.finalize(); +}); + +app.post("/uploadDoc", (req, res) => { + let form = new formidable.IncomingForm(); + form.keepExtensions = true; + // let path = req.body.path; + const ids: { [id: string]: string } = {}; + let remap = true; + const getId = (id: string): string => { + if (!remap) return id; + if (id.endsWith("Proto")) return id; + if (id in ids) { + return ids[id]; + } else { + return ids[id] = v4(); + } + }; + const mapFn = (doc: any) => { + if (doc.id) { + doc.id = getId(doc.id); + } + for (const key in doc.fields) { + if (!doc.fields.hasOwnProperty(key)) { + continue; + } + const field = doc.fields[key]; + if (field === undefined || field === null) { + continue; + } + + if (field.__type === "proxy" || field.__type === "prefetch_proxy") { + field.fieldId = getId(field.fieldId); + } else if (field.__type === "list") { + mapFn(field); + } else if (typeof field === "string") { + const re = /("(?:dataD|d)ocumentId"\s*:\s*")([\w\-]*)"/g; + doc.fields[key] = (field as any).replace(re, (match: any, p1: string, p2: string) => { + return `${p1}${getId(p2)}"`; + }); + } else if (field.__type === "RichTextField") { + const re = /("href"\s*:\s*")(.*?)"/g; + field.Data = field.Data.replace(re, (match: any, p1: string, p2: string) => { + return `${p1}${getId(p2)}"`; + }); + } + } + }; + form.parse(req, async (err, fields, files) => { + remap = fields.remap !== "false"; + let id: string = ""; + try { + for (const name in files) { + const path = files[name].path; + const zip = new AdmZip(path); + zip.getEntries().forEach(entry => { + if (!entry.name.startsWith("files/")) return; + zip.extractEntryTo(entry.name, __dirname + RouteStore.public, true, false); + }); + const json = zip.getEntry("doc.json"); + let docs: any; + try { + let data = JSON.parse(json.getData().toString("utf8")); + docs = data.docs; + id = data.id; + docs = Object.keys(docs).map(key => docs[key]); + docs.forEach(mapFn); + await Promise.all(docs.map((doc: any) => new Promise(res => Database.Instance.replace(doc.id, doc, (err, r) => { + err && console.log(err); + res(); + }, true, "newDocuments")))); + } catch (e) { console.log(e); } + fs.unlink(path, () => { }); + } + if (id) { + res.send(JSON.stringify(getId(id))); + } else { + res.send(JSON.stringify("error")); + } + } catch (e) { console.log(e); } + }); }); app.get("/whosOnline", (req, res) => { -- cgit v1.2.3-70-g09d2 From 78999b8b35267db9236bbb69e7e90e8691c59ba9 Mon Sep 17 00:00:00 2001 From: fawn Date: Tue, 30 Jul 2019 16:21:54 -0400 Subject: sorting saves on schema columns --- .../views/collections/CollectionSchemaHeaders.tsx | 18 ++++++------ .../views/collections/CollectionSchemaView.tsx | 33 +++++++++++++--------- src/new_fields/SchemaHeaderField.ts | 22 ++++++++++----- 3 files changed, 45 insertions(+), 28 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index 62762962e..4f0681f6c 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -24,8 +24,7 @@ export interface HeaderProps { setIsEditing: (isEditing: boolean) => void; deleteColumn: (column: string) => void; setColumnType: (column: SchemaHeaderField, type: ColumnType) => void; - setColumnSort: (key: string, desc: boolean) => void; - removeColumnSort: (key: string) => void; + setColumnSort: (column: SchemaHeaderField, desc: boolean | undefined) => void; setColumnColor: (column: SchemaHeaderField, color: string) => void; } @@ -51,7 +50,6 @@ export class CollectionSchemaHeader extends React.Component { onlyShowOptions={false} setColumnType={this.props.setColumnType} setColumnSort={this.props.setColumnSort} - removeColumnSort={this.props.removeColumnSort} setColumnColor={this.props.setColumnColor} />
@@ -87,8 +85,7 @@ export interface ColumnMenuProps { deleteColumn: (column: string) => void; onlyShowOptions: boolean; setColumnType: (column: SchemaHeaderField, type: ColumnType) => void; - setColumnSort: (key: string, desc: boolean) => void; - removeColumnSort: (key: string) => void; + setColumnSort: (column: SchemaHeaderField, desc: boolean | undefined) => void; anchorPoint?: any; setColumnColor: (column: SchemaHeaderField, color: string) => void; } @@ -123,6 +120,10 @@ export class CollectionSchemaColumnMenu extends React.Component this.props.setColumnType(this.props.columnField, type); } + changeColumnSort = (desc: boolean | undefined): void => { + this.props.setColumnSort(this.props.columnField, desc); + } + changeColumnColor = (color: string): void => { this.props.setColumnColor(this.props.columnField, color); } @@ -168,19 +169,20 @@ export class CollectionSchemaColumnMenu extends React.Component } renderSorting = () => { + let sort = this.props.columnField.desc; return (
-
this.props.setColumnSort(this.props.columnField.heading, true)}> +
this.changeColumnSort(true)}> Sort descending
-
this.props.setColumnSort(this.props.columnField.heading, false)}> +
this.changeColumnSort(false)}> Sort ascending
-
this.props.removeColumnSort(this.props.columnField.heading)}> +
this.changeColumnSort(undefined)}> Clear sorting
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 86d3d01ef..84f8ec505 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -275,7 +275,6 @@ 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 _openCollections: Array = []; @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); } @@ -308,8 +307,7 @@ export class SchemaTable extends React.Component { } @computed get resized(): { "id": string, "value": number }[] { - let columns = this.columns; - return columns.reduce((resized, shf) => { + return this.columns.reduce((resized, shf) => { if (shf.width > -1) { resized.push({ "id": shf.heading, "value": shf.width }); } @@ -317,6 +315,15 @@ export class SchemaTable extends React.Component { }, [] as { "id": string, "value": number }[]); } + @computed get sorted(): { "id": string, "desc": boolean }[] { + return this.columns.reduce((sorted, shf) => { + if (shf.desc) { + sorted.push({ "id": shf.heading, "desc": shf.desc }); + } + return sorted; + }, [] as { "id": string, "desc": boolean }[]); + } + @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); @@ -358,7 +365,6 @@ export class SchemaTable extends React.Component { deleteColumn={this.deleteColumn} setColumnType={this.setColumnType} setColumnSort={this.setColumnSort} - removeColumnSort={this.removeColumnSort} setColumnColor={this.setColumnColor} />; @@ -689,13 +695,13 @@ export class SchemaTable extends React.Component { } @action - setColumnSort = (column: string, descending: boolean) => { - this._sortedColumns.set(column, { id: column, desc: descending }); - } - - @action - removeColumnSort = (column: string) => { - this._sortedColumns.delete(column); + setColumnSort = (columnField: SchemaHeaderField, descending: boolean | undefined) => { + let columns = this.columns; + let index = columns.findIndex(c => c.heading === columnField.heading); + let column = columns[index]; + column.setDesc(descending); + columns[index] = column; + this.columns = columns; } get documentKeys() { @@ -750,7 +756,7 @@ export class SchemaTable extends React.Component { getTdProps={this.getTdProps} sortable={false} TrComponent={MovableRow} - sorted={Array.from(this._sortedColumns.values())} + sorted={this.sorted} expanded={expanded} resized={this.resized} onResizedChange={this.onResizedChange} @@ -770,7 +776,8 @@ export class SchemaTable extends React.Component { newResized.forEach(resized => { let index = columns.findIndex(c => c.heading === resized.id); let column = columns[index]; - column.width = resized.value; + column.setWidth(resized.value); + columns[index] = column; }); this.columns = columns; } diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts index bccf82a9e..0c19d211a 100644 --- a/src/new_fields/SchemaHeaderField.ts +++ b/src/new_fields/SchemaHeaderField.ts @@ -51,19 +51,17 @@ export class SchemaHeaderField extends ObjectField { type: number; @serializable(primitive()) width: number; + @serializable(primitive()) + desc: boolean | undefined; // boolean determines sort order, undefined when no sort - constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType, width?: number) { + constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType, width?: number, desc?: boolean) { super(); this.heading = heading; this.color = color; - if (type) { - this.type = type; - } - else { - this.type = 0; - } + this.type = type ? type : 0; this.width = width ? width : -1; + this.desc = desc; } setHeading(heading: string) { @@ -81,6 +79,16 @@ export class SchemaHeaderField extends ObjectField { this[OnUpdate](); } + setWidth(width: number) { + this.width = width; + this[OnUpdate](); + } + + setDesc(desc: boolean | undefined) { + this.desc = desc; + this[OnUpdate](); + } + [Copy]() { return new SchemaHeaderField(this.heading, this.color, this.type); } -- cgit v1.2.3-70-g09d2 From 7c3b56a2e4552308014aa011493b33e3b054be94 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Tue, 30 Jul 2019 16:33:27 -0400 Subject: fixed some scripting stuff on view specs --- src/client/views/collections/CollectionSubView.tsx | 3 +++ src/client/views/collections/CollectionViewChromes.scss | 3 ++- src/client/views/collections/CollectionViewChromes.tsx | 9 +++++++-- src/client/views/collections/KeyRestrictionRow.tsx | 6 +++++- 4 files changed, 17 insertions(+), 4 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index a15ed8f94..7386eaba6 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -66,6 +66,9 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { if (res.success) { return res.result; } + else { + console.log(res.error); + } }); } return docs; diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index 989315194..c062c3261 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -37,9 +37,10 @@ } .collectionViewBaseChrome-collapse { - transition: all .5s; + transition: all .5s opacity 0.2s; position: absolute; width: 40px; + transform-origin: top left; } .collectionViewBaseChrome-viewSpecs { diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 2bffe3cc0..0827cfef9 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -142,7 +142,7 @@ export class CollectionViewBaseChrome extends React.Component
diff --git a/src/client/views/collections/KeyRestrictionRow.tsx b/src/client/views/collections/KeyRestrictionRow.tsx index 9baa250a6..1b59547d8 100644 --- a/src/client/views/collections/KeyRestrictionRow.tsx +++ b/src/client/views/collections/KeyRestrictionRow.tsx @@ -2,6 +2,7 @@ import * as React from "react"; import { observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { PastelSchemaPalette } from "../../../new_fields/SchemaHeaderField"; +import { Doc } from "../../../new_fields/Doc"; interface IKeyRestrictionProps { contains: boolean; @@ -23,7 +24,10 @@ export default class KeyRestrictionRow extends React.Component Date: Tue, 30 Jul 2019 16:33:37 -0400 Subject: object field scripting --- src/client/views/collections/CollectionViewChromes.scss | 2 +- src/new_fields/ObjectField.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index c062c3261..1738ac227 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -37,7 +37,7 @@ } .collectionViewBaseChrome-collapse { - transition: all .5s opacity 0.2s; + transition: all .5s, opacity 0.3s; position: absolute; width: 40px; transform-origin: top left; diff --git a/src/new_fields/ObjectField.ts b/src/new_fields/ObjectField.ts index 5f4a6f8fb..65ada91c0 100644 --- a/src/new_fields/ObjectField.ts +++ b/src/new_fields/ObjectField.ts @@ -1,6 +1,7 @@ import { Doc } from "./Doc"; import { RefField } from "./RefField"; import { OnUpdate, Parent, Copy, ToScriptString } from "./FieldSymbols"; +import { Scripting } from "../client/util/Scripting"; export abstract class ObjectField { protected [OnUpdate](diff?: any) { } @@ -15,3 +16,5 @@ export namespace ObjectField { return field[Copy](); } } + +Scripting.addGlobal(ObjectField); \ No newline at end of file -- cgit v1.2.3-70-g09d2 From c953c50fee4eaa578e74249dab0f40af3f268802 Mon Sep 17 00:00:00 2001 From: fawn Date: Tue, 30 Jul 2019 17:49:36 -0400 Subject: added color picker to stacking view columns --- .../views/collections/CollectionStackingView.scss | 39 ++++++++++++++- .../CollectionStackingViewFieldColumn.tsx | 58 ++++++++++++++++++++-- src/new_fields/SchemaHeaderField.ts | 3 +- 3 files changed, 95 insertions(+), 5 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 0cb01dc9d..669b3170a 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -82,7 +82,7 @@ margin-left: 5px; margin-right: 5px; margin-top: 10px; - overflow: hidden; + // overflow: hidden; overflow is visible so the color menu isn't hidden -ftong .editableView-input { color: black; @@ -125,6 +125,43 @@ } } + .collectionStackingView-sectionColor { + position: absolute; + left: 0; + top: 0; + height: 100%; + + [class*="css"] { + max-width: 102px; + } + + .collectionStackingView-sectionColorButton { + height: 35px; + } + + .collectionStackingView-colorPicker { + width: 78px; + + .colorOptions { + display: flex; + flex-wrap: wrap; + } + + .colorPicker { + cursor: pointer; + width: 20px; + height: 20px; + border-radius: 10px; + margin: 3px; + + &.active { + border: 2px solid white; + box-shadow: 0 0 0 2px lightgray; + } + } + } + } + .collectionStackingView-sectionDelete { position: absolute; right: 0; diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 38cc7fc50..668ba901b 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -14,12 +14,17 @@ 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 { SchemaHeaderField, PastelSchemaPalette } 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"; import { Transform } from "../../util/Transform"; +import { Flyout, anchorPoints } from "../DocumentDecorations"; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { faPalette } from '@fortawesome/free-solid-svg-icons'; + +library.add(faPalette); interface CSVFieldColumnProps { @@ -45,6 +50,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { this._dropRef = ele; @@ -153,6 +159,14 @@ export class CollectionStackingViewFieldColumn extends React.Component { + if (this.props.headingObject) { + this.props.headingObject.setColor(color); + this._color = color; + } + } + @action pointerEntered = () => { if (SelectionManager.GetIsDragging()) { @@ -227,6 +241,36 @@ export class CollectionStackingViewFieldColumn extends React.Component { + let selected = this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; + + let pink = PastelSchemaPalette.get("pink2"); + let purple = PastelSchemaPalette.get("purple4"); + let blue = PastelSchemaPalette.get("bluegreen1"); + let yellow = PastelSchemaPalette.get("yellow4"); + let red = PastelSchemaPalette.get("red2"); + let green = PastelSchemaPalette.get("bluegreen7"); + let cyan = PastelSchemaPalette.get("bluegreen5"); + let orange = PastelSchemaPalette.get("orange1"); + let gray = "#f1efeb"; + + return ( +
+
+
this.changeColumnColor(pink!)}>
+
this.changeColumnColor(purple!)}>
+
this.changeColumnColor(blue!)}>
+
this.changeColumnColor(yellow!)}>
+
this.changeColumnColor(red!)}>
+
this.changeColumnColor(gray)}>
+
this.changeColumnColor(green!)}>
+
this.changeColumnColor(cyan!)}>
+
this.changeColumnColor(orange!)}>
+
+
+ ); + } + render() { let cols = this.props.cols(); let key = StrCast(this.props.parent.props.Document.sectionFilter); @@ -262,11 +306,19 @@ export class CollectionStackingViewFieldColumn extends React.Component + {evContents === `NO ${key.toUpperCase()} VALUE` ? (null) : +
+ + + +
+ } {evContents === `NO ${key.toUpperCase()} VALUE` ? (null) :
; } + + @undoBatch @action setPreviewScript = (script: string) => { this.previewScript = script; @@ -552,6 +554,7 @@ export class SchemaTable extends React.Component { this.props.setFocused(this.props.Document); } + @undoBatch createRow = () => { let children = this.childDocs; @@ -563,6 +566,7 @@ export class SchemaTable extends React.Component { this.childDocs = children; } + @undoBatch @action createColumn = () => { let index = 0; @@ -581,6 +585,7 @@ export class SchemaTable extends React.Component { this.columns = columns; } + @undoBatch @action deleteColumn = (key: string) => { let columns = this.columns; @@ -595,6 +600,7 @@ export class SchemaTable extends React.Component { } } + @undoBatch @action changeColumns = (oldKey: string, newKey: string, addNew: boolean) => { let columns = this.columns; @@ -634,6 +640,7 @@ export class SchemaTable extends React.Component { return NumCast(typesDoc[column.heading]); } + @undoBatch setColumnType = (columnField: SchemaHeaderField, type: ColumnType): void => { if (columnTypes.get(columnField.heading)) return; @@ -656,6 +663,7 @@ export class SchemaTable extends React.Component { // } } + @undoBatch setColumnColor = (columnField: SchemaHeaderField, color: string): void => { let columns = this.columns; let index = columns.indexOf(columnField); @@ -671,6 +679,7 @@ export class SchemaTable extends React.Component { this.columns = columns; } + @undoBatch reorderColumns = (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columnsValues: SchemaHeaderField[]) => { let columns = [...columnsValues]; let oldIndex = columns.indexOf(toMove); @@ -683,6 +692,7 @@ export class SchemaTable extends React.Component { this.columns = columns; } + @undoBatch @action setColumnSort = (columnField: SchemaHeaderField, descending: boolean | undefined) => { let columns = this.columns; diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index bf1f35a92..ecf78b8c1 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -377,6 +377,7 @@ export class CollectionStackingViewChrome extends React.Component { // private _textwrapAllRows: boolean = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0; + @undoBatch togglePreview = () => { let dividerWidth = 4; let borderWidth = Number(COLLECTION_BORDER_WIDTH); @@ -386,6 +387,7 @@ export class CollectionSchemaViewChrome extends React.Component { let textwrappedRows = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []); -- cgit v1.2.3-70-g09d2 From f953ab92c8e0d4bf54f90a6b7f22a86cf5985c38 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 30 Jul 2019 22:39:52 -0400 Subject: removed chrome (scrollbar) of collectionChrome when collapsed. fixed make background. --- src/client/views/collections/CollectionView.tsx | 14 ++++++-------- src/client/views/collections/CollectionViewChromes.scss | 1 + src/client/views/collections/CollectionViewChromes.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 6 +++++- .../views/collections/collectionFreeForm/MarqueeView.tsx | 16 +++++++++++++--- src/client/views/nodes/DocumentView.tsx | 9 +++++---- 6 files changed, 31 insertions(+), 17 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 376aaf53f..34adc5840 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,11 +1,13 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faProjectDiagram, faSignature, faColumns, faSquare, faTh, faImage, faThList, faTree, faEllipsisV, faFingerprint, faLaptopCode } from '@fortawesome/free-solid-svg-icons'; +import { faEye } from '@fortawesome/free-regular-svg-icons'; +import { faColumns, faEllipsisV, faFingerprint, faImage, faProjectDiagram, faSignature, faSquare, faTh, faThList, faTree } from '@fortawesome/free-solid-svg-icons'; +import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from "mobx-react"; import * as React from 'react'; -import { Doc, DocListCast, WidthSym, HeightSym } from '../../../new_fields/Doc'; +import { Doc } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; +import { StrCast } from '../../../new_fields/Types'; import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; -import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from '../ContextMenuItem'; import { FieldView, FieldViewProps } from '../nodes/FieldView'; @@ -15,11 +17,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'; -import { DocumentType } from '../../documents/Documents'; -import { CollectionStackingViewChrome, CollectionViewBaseChrome } from './CollectionViewChromes'; -import { observable, action, runInAction, IReactionDisposer, reaction } from 'mobx'; -import { faEye } from '@fortawesome/free-regular-svg-icons'; +import { CollectionViewBaseChrome } from './CollectionViewChromes'; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh); diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index 0c2665b1c..793cb7a8b 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -14,6 +14,7 @@ grid-template-columns: 1fr auto; padding-bottom: 10px; border-bottom: .5px solid rgb(180, 180, 180); + overflow: hidden; .collectionViewBaseChrome { display: flex; diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index ecf78b8c1..1b2561953 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -213,7 +213,7 @@ export class CollectionViewBaseChrome extends React.ComponentStacking View -
+
{ } - bringToFront = (doc: Doc) => { + bringToFront = (doc: Doc, sendToBack?: boolean) => { + if (sendToBack) { + doc.zIndex = 0; + return; + } const docs = this.childDocs; docs.slice().sort((doc1, doc2) => { if (doc1 === doc) return 1; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 07d06d053..b9ee588dd 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -370,15 +370,25 @@ export class MarqueeView extends React.Component let selRect = this.Bounds; let selection: 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); - var w = NumCast(doc.width) / z; - var h = NumCast(doc.height) / z; + var w = NumCast(doc.width); + var h = NumCast(doc.height); if (this.intersectRect({ left: x, top: y, width: w, height: h }, selRect)) { selection.push(doc); } }); + if (!selection.length) { + this.props.activeDocuments().map(doc => { + var x = NumCast(doc.x); + var y = NumCast(doc.y); + var w = NumCast(doc.width); + var h = NumCast(doc.height); + if (this.intersectRect({ left: x, top: y, width: w, height: h }, selRect)) { + selection.push(doc); + } + }); + } return selection; } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 51662274d..14f0b5a5a 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -96,7 +96,7 @@ export interface DocumentViewProps { selectOnLoad: boolean; parentActive: () => boolean; whenActiveChanged: (isActive: boolean) => void; - bringToFront: (doc: Doc) => void; + bringToFront: (doc: Doc, sendToBack?: boolean) => void; addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => void; collapseToPoint?: (scrpt: number[], expandedDocs: Doc[] | undefined) => void; zoomToScale: (scale: number) => void; @@ -529,7 +529,8 @@ export class DocumentView extends DocComponent(Docu @undoBatch @action makeBackground = (): void => { - this.props.Document.isBackground = true; + this.props.Document.isBackground = !this.props.Document.isBackground; + this.props.Document.isBackground && this.props.bringToFront(this.props.Document, true); } @undoBatch @@ -568,7 +569,7 @@ export class DocumentView extends DocComponent(Docu cm.addItem({ description: BoolCast(this.props.Document.lockedPosition) ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" }); cm.addItem({ description: "Transcribe Speech", event: this.listen, icon: "microphone" }); 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.isBackground ? "Remove Background" : "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: () => { @@ -708,7 +709,7 @@ export class DocumentView extends DocComponent(Docu
Date: Tue, 30 Jul 2019 23:52:44 -0400 Subject: fixed collection chrome with tree views. fixed fitToBounds calculation --- .../views/collections/CollectionTreeView.scss | 3 ++ .../collectionFreeForm/CollectionFreeFormView.tsx | 37 +++++++++++----------- 2 files changed, 21 insertions(+), 19 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index db3652ff6..990979109 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -7,6 +7,9 @@ border-radius: inherit; box-sizing: border-box; height: 100%; + width:100%; + position: absolute; + top:0; padding-top: 20px; padding-left: 10px; padding-right: 0px; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 3cead34e6..a1b1871fe 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,25 +1,35 @@ -import { action, computed, trace } from "mobx"; +import { library } from "@fortawesome/fontawesome-svg-core"; +import { faEye } from "@fortawesome/free-regular-svg-icons"; +import { faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faPaintBrush, faTable, faUpload } from "@fortawesome/free-solid-svg-icons"; +import { action, computed } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCastAsync, HeightSym, WidthSym, DocListCast } from "../../../../new_fields/Doc"; +import { Doc, DocListCastAsync, HeightSym, WidthSym } from "../../../../new_fields/Doc"; import { Id } from "../../../../new_fields/FieldSymbols"; import { InkField, StrokeData } from "../../../../new_fields/InkField"; import { createSchema, makeInterface } from "../../../../new_fields/Schema"; +import { ScriptField } from "../../../../new_fields/ScriptField"; import { BoolCast, Cast, FieldValue, NumCast, StrCast } from "../../../../new_fields/Types"; import { emptyFunction, returnOne, Utils } from "../../../../Utils"; +import { CognitiveServices } from "../../../cognitive_services/CognitiveServices"; +import { DocServer } from "../../../DocServer"; import { DocumentManager } from "../../../util/DocumentManager"; import { DragManager } from "../../../util/DragManager"; import { HistoryUtil } from "../../../util/History"; +import { CompileScript } from "../../../util/Scripting"; 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 { SubmenuProps, ContextMenuProps } from "../../ContextMenuItem"; +import { ContextMenu } from "../../ContextMenu"; +import { ContextMenuProps } from "../../ContextMenuItem"; import { InkingCanvas } from "../../InkingCanvas"; import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView"; import { DocumentContentsView } from "../../nodes/DocumentContentsView"; import { DocumentViewProps, positionSchema } from "../../nodes/DocumentView"; import { pageSchema } from "../../nodes/ImageBox"; +import { OverlayElementOptions, OverlayView } from "../../OverlayView"; import PDFMenu from "../../pdf/PDFMenu"; +import { ScriptBox } from "../../ScriptBox"; import { CollectionSubView } from "../CollectionSubView"; import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView"; import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors"; @@ -27,19 +37,6 @@ import "./CollectionFreeFormView.scss"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); import v5 = require("uuid/v5"); -import { ScriptField } from "../../../../new_fields/ScriptField"; -import { OverlayView, OverlayElementOptions } from "../../OverlayView"; -import { ScriptBox } from "../../ScriptBox"; -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, faCompass, faUpload } from "@fortawesome/free-solid-svg-icons"; -import { undo } from "prosemirror-history"; -import { number } from "prop-types"; -import { ContextMenu } from "../../ContextMenu"; -import { RouteStore } from "../../../../server/RouteStore"; -import { DocServer } from "../../../DocServer"; library.add(faEye, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload); @@ -81,11 +78,13 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @computed get contentBounds() { let bounds = this.fitToBox && !this.isAnnotationOverlay ? this.ComputeContentBounds(this.elements.filter(e => e.bounds).map(e => e.bounds!)) : undefined; - return { + let res = { 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.parentScaling }; + if (res.scale === 0) res.scale = 1; + return res; } @computed get fitToBox() { return this.props.fitToBox || this.props.Document.fitToBox; } @@ -492,11 +491,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } 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 }) : {}; + const pos = script ? this.getCalculatedPositions(script, { doc, index: prev.length, collection: this.Document, docs, state }) : + { x: Cast(doc.x, "number"), y: Cast(doc.y, "number"), width: Cast(doc.width, "number"), height: Cast(doc.height, "number") }; state = pos.state === undefined ? state : pos.state; prev.push({ ele: , -- cgit v1.2.3-70-g09d2 From a268800c9d743e94c9395dc1d34809bb55c3ceab Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 31 Jul 2019 00:05:39 -0400 Subject: added alt-drag-drop for applying template to items in a collection --- src/client/views/collections/CollectionSubView.tsx | 15 ++++++++++----- src/client/views/nodes/ImageBox.tsx | 12 +----------- src/new_fields/Doc.ts | 13 +++++++++++++ 3 files changed, 24 insertions(+), 16 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 7386eaba6..077f3f941 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -1,13 +1,15 @@ import { action, computed } from "mobx"; import * as rp from 'request-promise'; import CursorField from "../../../new_fields/CursorField"; -import { Doc, DocListCast, Opt } from "../../../new_fields/Doc"; +import { Doc, DocListCast } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; +import { ScriptField } from "../../../new_fields/ScriptField"; import { BoolCast, Cast } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { RouteStore } from "../../../server/RouteStore"; +import { Utils } from "../../../Utils"; import { DocServer } from "../../DocServer"; import { Docs, DocumentOptions, DocumentType } from "../../documents/Documents"; import { DragManager } from "../../util/DragManager"; @@ -19,10 +21,6 @@ import { CollectionPDFView } from "./CollectionPDFView"; import { CollectionVideoView } from "./CollectionVideoView"; import { CollectionView } from "./CollectionView"; import React = require("react"); -import { MainView } from "../MainView"; -import { Utils } from "../../../Utils"; -import { ScriptField } from "../../../new_fields/ScriptField"; -import { CompileScript } from "../../util/Scripting"; export interface CollectionViewProps extends FieldViewProps { addDocument: (document: Doc, allowDuplicates?: boolean) => boolean; @@ -115,6 +113,13 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { @action protected drop(e: Event, de: DragManager.DropEvent): boolean { if (de.data instanceof DragManager.DocumentDragData) { + if (de.mods === "AltKey" && de.data.draggedDocuments.length) { + this.childDocs.map(doc => + Doc.ApplyTemplateTo(de.data.draggedDocuments[0], doc, undefined) + ); + e.stopPropagation(); + return true; + } let added = false; if (de.data.dropAction || de.data.userDropAction) { added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false); diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index dbe545048..b60ef41fd 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -93,17 +93,7 @@ export class ImageBox extends DocComponent(ImageD if (de.data instanceof DragManager.DocumentDragData) { de.data.droppedDocuments.forEach(action((drop: Doc) => { 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; - if (this.props.DataDoc && this.props.DataDoc.layout === this.props.Document) { - this.props.DataDoc.layout = temp; - } else { - this.props.Document.layout = temp; - } + Doc.ApplyTemplateTo(drop, this.props.Document, this.props.DataDoc); 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/new_fields/Doc.ts b/src/new_fields/Doc.ts index 59314783b..dab0f9070 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -462,6 +462,19 @@ export namespace Doc { otherdoc.type = DocumentType.TEMPLATE; return otherdoc; } + export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetData?: Doc) { + let temp = Doc.MakeDelegate(templateDoc); + target.nativeWidth = Doc.GetProto(target).nativeWidth = undefined; + target.nativeHeight = Doc.GetProto(target).nativeHeight = undefined; + target.width = templateDoc.width; + target.height = templateDoc.height; + Doc.GetProto(target).type = DocumentType.TEMPLATE; + if (targetData && targetData.layout === target) { + targetData.layout = temp; + } else { + target.layout = temp; + } + } export function MakeTemplate(fieldTemplate: Doc, metaKey: string, templateDataDoc: Doc) { // move data doc fields to layout doc as needed (nativeWidth/nativeHeight, data, ??) -- cgit v1.2.3-70-g09d2 From b6fa309cea934d250fe992e70e1e268f344659b5 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 31 Jul 2019 00:19:13 -0400 Subject: fixed transitions on drag --- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index a1b1871fe..33a584c6f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -498,7 +498,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { { x: Cast(doc.x, "number"), y: Cast(doc.y, "number"), width: Cast(doc.width, "number"), height: Cast(doc.height, "number") }; state = pos.state === undefined ? state : pos.state; prev.push({ - ele: , + 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 }); } -- cgit v1.2.3-70-g09d2 From cf32a37355e1d4a55e276e2ee25ef9cd89e0cd16 Mon Sep 17 00:00:00 2001 From: kimdahey Date: Wed, 31 Jul 2019 11:16:35 -0400 Subject: disabled does not show ADD NEW / GROUP buttons --- src/client/views/collections/CollectionStackingView.tsx | 4 ++-- .../views/collections/CollectionStackingViewFieldColumn.tsx | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 5cfcc3d4b..9741b9e89 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -301,9 +301,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 !== 'view-mode') ? + {(this.props.Document.sectionFilter && (this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.CollectionView.props.Document.chromeStatus !== 'disabled')) ?
+ style={{ width: (this.columnWidth / (headings.length + ((this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0))) - 10, marginTop: 10 }}>
: null} {this.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? {/* 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. */} @@ -328,7 +328,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 !== 'view-mode') ? + {(this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
+ style={{ width: style.columnWidth / (uniqueHeadings.length + ((this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0)) }}>
: null}
-- cgit v1.2.3-70-g09d2 From 023c08d621488dfaa18a61f50611c612b2a6feb5 Mon Sep 17 00:00:00 2001 From: kimdahey Date: Wed, 31 Jul 2019 11:37:03 -0400 Subject: some QoL css changes --- .../views/collections/CollectionStackingView.scss | 31 +++++++++++----------- .../CollectionStackingViewFieldColumn.tsx | 2 +- 2 files changed, 17 insertions(+), 16 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 14c7f5edd..015955816 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -141,7 +141,7 @@ .collectionStackingView-colorPicker { width: 78px; - + .colorOptions { display: flex; flex-wrap: wrap; @@ -153,7 +153,7 @@ height: 20px; border-radius: 10px; margin: 3px; - + &.active { border: 2px solid white; box-shadow: 0 0 0 2px lightgray; @@ -225,19 +225,20 @@ .rc-switch { position: absolute; display: inline-block; - bottom: 15px; - right: 15px; - width: 125px; - height: 54px; + bottom: 4px; + right: 4px; + width: 70px; + height: 30px; border-radius: 40px 40px; + background-color: lightslategrey; } .rc-switch:after { position: absolute; - width: 36px; - height: 36px; - left: 7px; - top: 9px; + width: 22px; + height: 22px; + left: 3px; + top: 4px; border-radius: 50% 50%; background-color: #fff; content: " "; @@ -253,19 +254,19 @@ } .rc-switch-checked:after { - left: 80px; + left: 44px; } .rc-switch-inner { color: #fff; - font-size: 22px; + font-size: 12px; position: absolute; - left: 50px; - top: 14px; + left: 28px; + top: 8px; } .rc-switch-checked .rc-switch-inner { - left: 17px; + left: 8px; } diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 36c8c8a8d..df03da376 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -348,7 +348,7 @@ export class CollectionStackingViewFieldColumn extends React.Component {(this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
+ style={{ width: style.columnWidth / (uniqueHeadings.length + 1) }}>
: null}
-- cgit v1.2.3-70-g09d2 From a75f6fb17a4cbb4643cff0d347eb812138957c95 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 31 Jul 2019 11:48:29 -0400 Subject: fixed some css and creating text links. --- src/client/views/collections/CollectionSchemaView.scss | 8 ++++---- src/client/views/collections/CollectionSchemaView.tsx | 1 + src/client/views/collections/CollectionView.tsx | 3 +++ src/new_fields/Doc.ts | 8 ++++++-- 4 files changed, 14 insertions(+), 6 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 3c4279eea..01744fb34 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -56,6 +56,10 @@ background: gray; cursor: col-resize; } + + .documentView-node:first-child { + background: $light-color; + } } .ReactTable { @@ -171,10 +175,6 @@ display: inline-block; } -.documentView-node:first-child { - background: $light-color; -} - .collectionSchema-col { height: 100%; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 4d6bf437f..9efd0d3ec 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -980,6 +980,7 @@ export class CollectionSchemaPreview extends React.Component { } ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems, icon: "eye" }); ContextMenu.Instance.addItem({ description: "Apply Template", event: () => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" }); + ContextMenu.Instance.addItem({ + description: this.props.Document.chromeStatus !== "disabled" ? "Hide Chrome" : "Show Chrome", event: () => this.props.Document.chromeStatus = (this.props.Document.chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" + }); } } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 5f9df786e..84b8589dd 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -197,8 +197,12 @@ export namespace Doc { } export function Get(doc: Doc, key: string, ignoreProto: boolean = false): FieldResult { - const self = doc[Self]; - return getField(self, key, ignoreProto); + try { + const self = doc[Self]; + return getField(self, key, ignoreProto); + } catch { + return doc; + } } export function GetT(doc: Doc, key: string, ctor: ToConstructor, ignoreProto: boolean = false): FieldResult { return Cast(Get(doc, key, ignoreProto), ctor) as FieldResult; -- cgit v1.2.3-70-g09d2 From d1debe4de37edfcafdd3446c4918488521af3a84 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 31 Jul 2019 19:26:22 -0400 Subject: fixed treeview omitting documents --- .../views/collections/CollectionTreeView.tsx | 46 +++++++++------------- 1 file changed, 19 insertions(+), 27 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index b1e6eada0..fa75c680a 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -70,30 +70,16 @@ class TreeView extends React.Component { private _header?: React.RefObject = React.createRef(); private _treedropDisposer?: DragManager.DragDropDisposer; private _dref = React.createRef(); - @computed get treeViewExpandedView() { return StrCast(this.props.document.treeViewExpandedView, "data"); } + @computed get treeViewExpandedView() { return StrCast(this.props.document.treeViewExpandedView, this.fieldKey); } @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.document.maxEmbedHeight, 300); } @observable _collapsed: boolean = true; @computed get fieldKey() { - let target = this.props.document; - let keys = Array.from(Object.keys(target)); // bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set - if (target.proto instanceof Doc) { - let arr = Array.from(Object.keys(target.proto));// bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set - keys.push(...arr); - while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1); - } - let keyList: string[] = []; - keys.map(key => { - let docList = Cast(this.dataDoc[key], listSpec(Doc)); - if (docList && docList.length > 0) { - keyList.push(key); - } - }); let layout = StrCast(this.props.document.layout); - if (layout.indexOf("fieldKey={\"") !== -1 && layout.indexOf("fieldExt=") === -1) { + if (layout.indexOf("fieldKey={\"") !== -1) { return layout.split("fieldKey={\"")[1].split("\"")[0]; } - return keyList.length ? keyList[0] : "data"; + return "data"; } @computed get dataDoc() { return this.resolvedDataDoc ? this.resolvedDataDoc : this.props.document; } @@ -104,7 +90,7 @@ class TreeView extends React.Component { // this document as the data document for the layout. return this.props.document; } - return this.props.dataDoc ? this.props.dataDoc : undefined; + return this.props.dataDoc; } protected createTreeDropTarget = (ele: HTMLDivElement) => { @@ -202,8 +188,8 @@ class TreeView extends React.Component { let headerElements = ( { - this.props.document.treeViewExpandedView = this.treeViewExpandedView === "data" ? "fields" : - this.treeViewExpandedView === "fields" && this.props.document.layout ? "layout" : "data"; + this.props.document.treeViewExpandedView = this.treeViewExpandedView === this.fieldKey ? "fields" : + this.treeViewExpandedView === "fields" && this.props.document.layout ? "layout" : this.fieldKey; this._collapsed = false; })}> {this.treeViewExpandedView} @@ -382,17 +368,20 @@ class TreeView extends React.Component { render() { let contentElement: (JSX.Element | null) = null; - let docList = Cast(this.dataDoc[this.fieldKey], listSpec(Doc)); let remDoc = (doc: Doc) => this.remove(doc, this.fieldKey); let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc, addBefore, before); if (!this._collapsed) { - if (this.treeViewExpandedView === "data") { - let doc = Cast(this.props.document[this.fieldKey], Doc); + if (this.treeViewExpandedView === this.fieldKey) { + let layout = this.props.document.layout as Doc; + let childDocs = (this.props.dataDoc ? Cast(this.props.dataDoc[this.fieldKey], listSpec(Doc)) : undefined) || + (layout ? Cast(layout[this.fieldKey], listSpec(Doc)) : undefined) || + Cast(this.props.document[this.fieldKey], listSpec(Doc)); contentElement =
    {this.fieldKey === "links" ? this.renderLinks() : - TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, this.props.document, this.resolvedDataDoc, this.fieldKey, 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)} + !childDocs ? (null) : + TreeView.GetChildElements(childDocs as Doc[], this.props.treeViewId, layout, this.resolvedDataDoc, this.fieldKey, 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 if (this.treeViewExpandedView === "fields") { contentElement =
    @@ -454,6 +443,8 @@ class TreeView extends React.Component { let docList = docs.filter(child => !child.excludeFromLibrary); let rowWidth = () => panelWidth() - 20; return docList.map((child, i) => { + let pair = Doc.GetLayoutDataDocPair(containingCollection, dataDoc, key, child); + let indent = i === 0 ? undefined : () => { if (StrCast(docList[i - 1].layout).indexOf("CollectionView") !== -1) { let fieldKeysub = StrCast(docList[i - 1].layout).split("fieldKey")[1]; @@ -470,8 +461,8 @@ class TreeView extends React.Component { return aspect ? Math.min(child[WidthSym](), rowWidth()) / aspect : child[HeightSym](); }; return Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before); -- cgit v1.2.3-70-g09d2 From d4accdd22cabdd78fc7bd76dd7ce3cb59e4b102f Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 1 Aug 2019 00:31:50 -0400 Subject: more treeview cleanup and fixes. --- src/client/util/SelectionManager.ts | 1 + src/client/views/DocumentDecorations.tsx | 4 +- .../views/collections/CollectionTreeView.tsx | 340 +++++++++------------ .../authentication/models/current_user_utils.ts | 2 +- 4 files changed, 145 insertions(+), 202 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 9efef888d..ee623d082 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -4,6 +4,7 @@ import { DocumentView } from "../views/nodes/DocumentView"; import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; import { NumCast, StrCast } from "../../new_fields/Types"; import { InkingControl } from "../views/InkingControl"; +import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils"; export namespace SelectionManager { diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 40f2c3da9..eccfc7c30 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -29,6 +29,7 @@ import { LinkManager } from '../util/LinkManager'; import { ObjectField } from '../../new_fields/ObjectField'; import { MetadataEntryMenu } from './MetadataEntryMenu'; import { ImageBox } from './nodes/ImageBox'; +import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -144,7 +145,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> @computed get Bounds(): { x: number, y: number, b: number, r: number } { return SelectionManager.SelectedDocuments().reduce((bounds, documentView) => { - if (documentView.props.renderDepth === 0) { + if (documentView.props.renderDepth === 0 || + Doc.AreProtosEqual(documentView.props.Document, CurrentUserUtils.UserDocument)) { return bounds; } let transform = (documentView.props.ScreenToLocalTransform().scale(documentView.props.ContentScaling())).inverse(); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index fa75c680a..7f5d78313 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -25,7 +25,6 @@ import { CollectionSchemaPreview } from './CollectionSchemaView'; import { CollectionSubView } from "./CollectionSubView"; import "./CollectionTreeView.scss"; import React = require("react"); -import { LinkManager } from '../../util/LinkManager'; import { ComputedField } from '../../../new_fields/ScriptField'; import { KeyValueBox } from '../nodes/KeyValueBox'; @@ -67,22 +66,24 @@ library.add(faPlus, faMinus); * Component that takes in a document prop and a boolean whether it's collapsed or not. */ class TreeView extends React.Component { + static loadId = ""; private _header?: React.RefObject = React.createRef(); private _treedropDisposer?: DragManager.DragDropDisposer; private _dref = React.createRef(); - @computed get treeViewExpandedView() { return StrCast(this.props.document.treeViewExpandedView, this.fieldKey); } - @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.document.maxEmbedHeight, 300); } @observable _collapsed: boolean = true; - + @computed get treeViewExpandedView() { return StrCast(this.props.document.treeViewExpandedView, "fields"); } + @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.document.maxEmbedHeight, 300); } + @computed get dataDoc() { return this.resolvedDataDoc ? this.resolvedDataDoc : this.props.document; } @computed get fieldKey() { - let layout = StrCast(this.props.document.layout); - if (layout.indexOf("fieldKey={\"") !== -1) { - return layout.split("fieldKey={\"")[1].split("\"")[0]; - } - return "data"; + let splits = StrCast(this.props.document.layout).split("fieldKey={\""); + return splits.length > 1 ? splits[1].split("\"")[0] : "data"; + } + @computed get childDocs() { + let layout = this.props.document.layout as Doc; + return (this.props.dataDoc ? Cast(this.props.dataDoc[this.fieldKey], listSpec(Doc)) : undefined) || + (layout ? Cast(layout[this.fieldKey], listSpec(Doc)) : undefined) || + Cast(this.props.document[this.fieldKey], listSpec(Doc)); } - - @computed get dataDoc() { return this.resolvedDataDoc ? this.resolvedDataDoc : this.props.document; } @computed get resolvedDataDoc() { if (this.props.dataDoc === undefined && this.props.document.layout instanceof Doc) { // if there is no dataDoc (ie, we're not rendering a template layout), but this document @@ -92,16 +93,30 @@ class TreeView extends React.Component { } return this.props.dataDoc; } + @computed get boundsOfCollectionDocument() { + return StrCast(this.props.document.type).indexOf(DocumentType.COL) === -1 ? undefined : + Doc.ComputeContentBounds(DocListCast(this.props.document.data)); + } - protected createTreeDropTarget = (ele: HTMLDivElement) => { - this._treedropDisposer && this._treedropDisposer(); - if (ele) { - this._treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.treeDrop.bind(this) } }); + @undoBatch delete = () => this.props.deleteDoc(this.dataDoc); + @undoBatch openRight = () => this.props.addDocTab(this.props.document, undefined, "onRight"); + @undoBatch indent = () => this.props.addDocument(this.props.document) && this.delete(); + @undoBatch move = (doc: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => { + return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc); + } + @undoBatch @action remove = (document: Document, key: string): boolean => { + let children = Cast(this.dataDoc[key], listSpec(Doc), []); + if (children.indexOf(document) !== -1) { + children.splice(children.indexOf(document), 1); + return true; } + return false; } - @undoBatch delete = () => this.props.deleteDoc(this.dataDoc); - @undoBatch openRight = async () => this.props.addDocTab(this.props.document, undefined, "onRight"); + protected createTreeDropTarget = (ele: HTMLDivElement) => { + this._treedropDisposer && this._treedropDisposer(); + ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.treeDrop.bind(this) } })); + } onPointerDown = (e: React.PointerEvent) => e.stopPropagation(); onPointerEnter = (e: React.PointerEvent): void => { @@ -130,34 +145,6 @@ class TreeView extends React.Component { e.stopPropagation(); } - @action - remove = (document: Document, key: string): boolean => { - let children = Cast(this.dataDoc[key], listSpec(Doc), []); - if (children.indexOf(document) !== -1) { - children.splice(children.indexOf(document), 1); - return true; - } - return false; - } - - @action - move: DragManager.MoveFunction = (doc: Doc, target: Doc, addDoc) => { - return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc); - } - @action - indent = () => this.props.addDocument(this.props.document) && this.delete() - - renderBullet() { - let docList = Cast(this.dataDoc[this.fieldKey], listSpec(Doc)); - let doc = Cast(this.dataDoc[this.fieldKey], Doc); - let isDoc = doc instanceof Doc || docList; - let c; - return
    this._collapsed = !this._collapsed)} style={{ color: StrCast(this.props.document.color, "black"), opacity: 0.4 }}> - {} -
    ; - } - - static loadId = ""; editableView = (key: string, style?: string) => ( { OnTab={() => this.props.indentDocument && this.props.indentDocument()} />) - /** - * Renders the EditableView title element for placement into the tree. - */ - renderTitle() { - let reference = React.createRef(); - let onItemDown = SetupDrag(reference, () => this.dataDoc, this.move, this.props.dropAction, this.props.treeViewId, true); - - let headerElements = ( - { - this.props.document.treeViewExpandedView = this.treeViewExpandedView === this.fieldKey ? "fields" : - this.treeViewExpandedView === "fields" && this.props.document.layout ? "layout" : this.fieldKey; - this._collapsed = false; - })}> - {this.treeViewExpandedView} - ); - let dataDocs = CollectionDockingView.Instance ? Cast(CollectionDockingView.Instance.props.Document[this.fieldKey], listSpec(Doc), []) : []; - let openRight = dataDocs && dataDocs.indexOf(this.dataDoc) !== -1 ? (null) : ( -
    - -
    ); - return <> -
    - {this.editableView("title")} - {/* {
    } */} -
    - {headerElements} - {openRight} - ; - } - onWorkspaceContextMenu = (e: React.MouseEvent): void => { if (!e.isPropagationStopped()) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 if (NumCast(this.props.document.viewType) !== CollectionViewType.Docking) { @@ -275,39 +225,6 @@ class TreeView extends React.Component { let finalXf = this.props.ScreenToLocalTransform().translate(offset[0], offset[1]); return finalXf; } - - renderLinks = () => { - let ele: JSX.Element[] = []; - let remDoc = (doc: Doc) => this.remove(doc, this.fieldKey); - let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.props.document, this.fieldKey, doc, addBefore, before); - let groups = LinkManager.Instance.getRelatedGroupedLinks(this.props.document); - groups.forEach((groupLinkDocs, groupType) => { - // let destLinks = groupLinkDocs.map(d => LinkManager.Instance.getOppositeAnchor(d, this.props.document)); - let destLinks: Doc[] = []; - groupLinkDocs.forEach((doc) => { - let opp = LinkManager.Instance.getOppositeAnchor(doc, this.props.document); - if (opp) { - destLinks.push(opp); - } - }); - ele.push( -
    -
    {groupType}:
    - { - TreeView.GetChildElements(destLinks, this.props.treeViewId, this.props.document, this.props.dataDoc, "treeviewlink-" + groupType, 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) - } -
    - ); - }); - return ele; - } - - @computed get boundsOfCollectionDocument() { - if (StrCast(this.props.document.type).indexOf(DocumentType.COL) === -1) return undefined; - let layoutDoc = this.props.document; - return Doc.ComputeContentBounds(DocListCast(layoutDoc.data)); - } docWidth = () => { let aspect = NumCast(this.props.document.nativeHeight) / NumCast(this.props.document.nativeWidth); if (aspect) return Math.min(this.props.document[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.panelWidth() - 5)); @@ -323,39 +240,29 @@ class TreeView extends React.Component { })()); } - noOverlays = (doc: Doc) => ({ title: "", caption: "" }); - - expandedField = (doc?: Doc) => { - if (!doc) return
    ; - let realDoc = doc; - + expandedField = (doc: Doc) => { let ids: { [key: string]: string } = {}; - Object.keys(doc).forEach(key => { - if (!(key in ids) && realDoc[key] !== ComputedField.undefined) { - ids[key] = key; - } - }); + doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)); let rows: JSX.Element[] = []; for (let key of Object.keys(ids).sort()) { - let contents = realDoc[key] ? realDoc[key] : undefined; + let contents = doc[key]; let contentElement: JSX.Element[] | JSX.Element = []; if (contents instanceof Doc || Cast(contents, listSpec(Doc))) { - let docList = contents; 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] : 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); + contentElement = TreeView.GetChildElements(contents instanceof Doc ? [contents] : + DocListCast(contents), this.props.treeViewId, doc, 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 = Field.toKeyValueString(realDoc, key)} - SetValue={(value: string) => KeyValueBox.SetField(realDoc, key, value)} />; + GetValue={() => Field.toKeyValueString(doc, key)} + SetValue={(value: string) => KeyValueBox.SetField(doc, key, value)} />; } rows.push(
    {key + ":"} @@ -366,59 +273,100 @@ class TreeView extends React.Component { return rows; } - render() { - let contentElement: (JSX.Element | null) = null; - let remDoc = (doc: Doc) => this.remove(doc, this.fieldKey); - let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc, addBefore, before); + noOverlays = (doc: Doc) => ({ title: "", caption: "" }); - if (!this._collapsed) { - if (this.treeViewExpandedView === this.fieldKey) { - let layout = this.props.document.layout as Doc; - let childDocs = (this.props.dataDoc ? Cast(this.props.dataDoc[this.fieldKey], listSpec(Doc)) : undefined) || - (layout ? Cast(layout[this.fieldKey], listSpec(Doc)) : undefined) || - Cast(this.props.document[this.fieldKey], listSpec(Doc)); - contentElement =
      - {this.fieldKey === "links" ? this.renderLinks() : - !childDocs ? (null) : - TreeView.GetChildElements(childDocs as Doc[], this.props.treeViewId, layout, this.resolvedDataDoc, this.fieldKey, 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 if (this.treeViewExpandedView === "fields") { - contentElement =
      - {this.expandedField(this.dataDoc)} -
    ; - } else { - let layoutDoc = this.props.document; - contentElement =
    - - -
    ; - } + @computed get renderContent() { + if (this.treeViewExpandedView === this.fieldKey) { + let remDoc = (doc: Doc) => this.remove(doc, this.fieldKey); + let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc, addBefore, before); + return
      + {!this.childDocs ? (null) : + TreeView.GetChildElements(this.childDocs as Doc[], this.props.treeViewId, this.props.document.layout as Doc, + this.resolvedDataDoc, this.fieldKey, 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 if (this.treeViewExpandedView === "fields") { + return
      + {this.dataDoc ? this.expandedField(this.dataDoc) : (null)} +
    ; + } else { + let layoutDoc = this.props.document; + return
    + + +
    ; } + } + + @computed + get renderBullet() { + return
    this._collapsed = !this._collapsed)} style={{ color: StrCast(this.props.document.color, "black"), opacity: 0.4 }}> + {} +
    ; + } + /** + * Renders the EditableView title element for placement into the tree. + */ + @computed + get renderTitle() { + let reference = React.createRef(); + let onItemDown = SetupDrag(reference, () => this.dataDoc, this.move, this.props.dropAction, this.props.treeViewId, true); + + let headerElements = ( + { + this.props.document.treeViewExpandedView = this.treeViewExpandedView === this.fieldKey ? "fields" : + this.treeViewExpandedView === "fields" && this.props.document.layout ? "layout" : + this.childDocs ? this.fieldKey : "fields"; + this._collapsed = false; + })}> + {this.treeViewExpandedView} + ); + let dataDocs = CollectionDockingView.Instance ? Cast(CollectionDockingView.Instance.props.Document[this.fieldKey], listSpec(Doc), []) : []; + let openRight = dataDocs && dataDocs.indexOf(this.dataDoc) !== -1 ? (null) : ( +
    + +
    ); + return <> +
    + {this.editableView("title")} +
    + {headerElements} + {openRight} + ; + } + + render() { return
  • - {this.renderBullet()} - {this.renderTitle()} + {this.renderBullet} + {this.renderTitle}
    - {contentElement} + {this._collapsed ? (null) : this.renderContent}
  • ; @@ -488,7 +436,9 @@ export class CollectionTreeView extends CollectionSubView(Document) { private treedropDisposer?: DragManager.DragDropDisposer; private _mainEle?: HTMLDivElement; - @computed get chromeCollapsed() { return this.props.chromeCollapsed; } + @observable static NotifsCol: Opt; + + @computed get resolvedDataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; } protected createTreeDropTarget = (ele: HTMLDivElement) => { this.treedropDisposer && this.treedropDisposer(); @@ -520,21 +470,15 @@ export class CollectionTreeView extends CollectionSubView(Document) { ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); } } - - @computed get resolvedDataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; } - outerXf = () => Utils.GetScreenTransform(this._mainEle!); onTreeDrop = (e: React.DragEvent) => this.onDrop(e, {}); - - - @observable static NotifsCol: Opt; - openNotifsCol = () => { if (CollectionTreeView.NotifsCol && CollectionDockingView.Instance) { CollectionDockingView.Instance.AddRightSplit(CollectionTreeView.NotifsCol, undefined); } } - @computed get notifsButton() { + + @computed get renderNotifsButton() { const length = CollectionTreeView.NotifsCol ? DocListCast(CollectionTreeView.NotifsCol.data).length : 0; const notifsRef = React.createRef(); const dragNotifs = action(() => CollectionTreeView.NotifsCol!); @@ -550,20 +494,16 @@ export class CollectionTreeView extends CollectionSubView(Document) {
    ; } - @computed get clearButton() { + @computed get renderClearButton() { return
    -
    - -
    +
    ; } - render() { - console.log("DTITLE + " + this.props.Document.title); Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey); let dropAction = StrCast(this.props.Document.dropAction) as dropActionType; let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before); @@ -588,8 +528,8 @@ export class CollectionTreeView extends CollectionSubView(Document) { TreeView.loadId = doc[Id]; Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, this.childDocs.length ? this.childDocs[0] : undefined, true); }} /> - {this.props.Document.workspaceLibrary ? this.notifsButton : (null)} - {this.props.Document.allowClear ? this.clearButton : (null)} + {this.props.Document.workspaceLibrary ? this.renderNotifsButton : (null)} + {this.props.Document.allowClear ? this.renderClearButton : (null)}
      { TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.Document, this.props.DataDoc, this.props.fieldKey, addDoc, this.remove, diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 1c52a3f11..91d7ba87d 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -71,7 +71,7 @@ export class CurrentUserUtils { doc.sidebar = sidebar; } StrCast(doc.title).indexOf("@") !== -1 && (doc.title = StrCast(doc.title).split("@")[0] + "'s Library"); - + doc.width = 100; } public static loadCurrentUser() { -- cgit v1.2.3-70-g09d2 From a4000aa57c9934ff3a68ba17474936836a5f235e Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 1 Aug 2019 10:35:02 -0400 Subject: tweaks --- src/client/views/ContextMenu.tsx | 2 +- src/client/views/DocumentDecorations.tsx | 1 - .../collections/collectionFreeForm/CollectionFreeFormView.tsx | 11 +++++------ src/client/views/nodes/DocumentView.tsx | 6 ------ 4 files changed, 6 insertions(+), 14 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 98025ac31..1bf6e383d 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -42,7 +42,7 @@ export class ContextMenu extends React.Component { return this._items.find(menuItem => { let reference = menuItem.description; toLowerCase && (reference = reference.toLowerCase()); - reference === target; + return reference === target; }); } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index eccfc7c30..15471371a 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -541,7 +541,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (fixedAspect && (!nwidth || !nheight)) { proto.nativeWidth = nwidth = doc.width || 0; proto.nativeHeight = nheight = doc.height || 0; - proto.ignoreAspect = true; } if (nwidth > 0 && nheight > 0 && !BoolCast(proto.ignoreAspect)) { if (Math.abs(dW) > Math.abs(dH)) { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 33a584c6f..29f9b1429 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -131,10 +131,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @action drop = (e: Event, de: DragManager.DropEvent) => { let xf = this.getTransform(); + let [xp, yp] = xf.transformPoint(de.x, de.y); if (super.drop(e, de)) { if (de.data instanceof DragManager.DocumentDragData) { if (de.data.droppedDocuments.length) { - 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); @@ -157,7 +157,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { else if (de.data instanceof DragManager.AnnotationDragData) { if (de.data.dropDocument) { let dragDoc = de.data.dropDocument; - let [xp, yp] = this.getTransform().transformPoint(de.x, de.y); let x = xp - de.data.xOffset; let y = yp - de.data.yOffset; let dropX = NumCast(de.data.dropDocument.x); @@ -224,10 +223,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { this._pheight / this.zoomScaling()); let panelwidth = panelDim[0]; let panelheight = panelDim[1]; - // if (ranges[0][0] - dx > (this.panX() + panelwidth / 2)) x = ranges[0][1] + panelwidth / 2; - // if (ranges[0][1] - dx < (this.panX() - panelwidth / 2)) x = ranges[0][0] - panelwidth / 2; - // if (ranges[1][0] - dy > (this.panY() + panelheight / 2)) y = ranges[1][1] + panelheight / 2; - // if (ranges[1][1] - dy < (this.panY() - panelheight / 2)) y = ranges[1][0] - panelheight / 2; + if (ranges[0][0] - dx > (this.panX() + panelwidth / 2)) x = ranges[0][1] + panelwidth / 2; + if (ranges[0][1] - dx < (this.panX() - panelwidth / 2)) x = ranges[0][0] - panelwidth / 2; + if (ranges[1][0] - dy > (this.panY() + panelheight / 2)) y = ranges[1][1] + panelheight / 2; + if (ranges[1][1] - dy < (this.panY() - panelheight / 2)) y = ranges[1][0] - panelheight / 2; } this.setPan(x - dx, y - dy); this._lastX = e.pageX; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 14f0b5a5a..d4adcfca1 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -586,12 +586,6 @@ export class DocumentView extends DocComponent(Docu }, 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); - // 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: () => Doc.ToggleDetailLayout(this.props.Document), icon: "image" }); } -- cgit v1.2.3-70-g09d2 From 6f3d4a7015e15e0523fc194f7f911f6d45259165 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 1 Aug 2019 13:57:59 -0400 Subject: added floating docs --- src/client/util/DragManager.ts | 7 +++- src/client/views/TemplateMenu.tsx | 44 ++++++++++++++++++++- .../collectionFreeForm/CollectionFreeFormView.scss | 1 + .../collectionFreeForm/CollectionFreeFormView.tsx | 46 +++++++++++++++------- .../views/nodes/CollectionFreeFormDocumentView.tsx | 1 + src/client/views/nodes/DocumentView.tsx | 42 +++++++++----------- 6 files changed, 100 insertions(+), 41 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index abcc3a4e1..0b5c785a4 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -10,6 +10,7 @@ import { LinkManager } from "./LinkManager"; import { SelectionManager } from "./SelectionManager"; import { SchemaHeaderField } from "../../new_fields/SchemaHeaderField"; import { DocumentDecorations } from "../views/DocumentDecorations"; +import { NumberLiteralType } from "typescript"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag( @@ -140,6 +141,10 @@ export namespace DragManager { dragHasStarted?: () => void; withoutShiftDrag?: boolean; + + offsetX?: number; + + offsetY?: number; } export interface DragDropDisposer { @@ -423,7 +428,7 @@ export namespace DragManager { lastX = e.pageX; lastY = e.pageY; dragElements.map((dragElement, i) => (dragElement.style.transform = - `translate(${(xs[i] += moveX)}px, ${(ys[i] += moveY)}px) scale(${scaleXs[i]}, ${scaleYs[i]})`) + `translate(${(xs[i] += moveX) + (options ? (options.offsetX || 0) : 0)}px, ${(ys[i] += moveY) + (options ? (options.offsetY || 0) : 0)}px) scale(${scaleXs[i]}, ${scaleYs[i]})`) ); }; diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 1b32f0ddd..c413650f0 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -7,6 +7,10 @@ import { DocumentView } from "./nodes/DocumentView"; import { Template } from "./Templates"; import React = require("react"); import { undoBatch } from "../util/UndoManager"; +import { DocumentManager } from "../util/DocumentManager"; +import { NumCast } from "../../new_fields/Types"; +import { DragManager } from "../util/DragManager"; +import { SelectionManager } from "../util/SelectionManager"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -35,11 +39,46 @@ export interface TemplateMenuProps { @observer export class TemplateMenu extends React.Component { @observable private _hidden: boolean = true; + dragRef = React.createRef(); constructor(props: TemplateMenuProps) { super(props); } + toggleFloat = (e: React.MouseEvent): void => { + SelectionManager.DeselectAll(); + let topDocView = this.props.docs[0]; + let topDoc = topDocView.props.Document; + let xf = topDocView.props.ScreenToLocalTransform(); + let ex = e.clientX; + let ey = e.clientY; + undoBatch(action(() => topDoc.z = topDoc.z ? 0 : 1))(); + if (!topDoc.z) { + setTimeout(() => { + let newDocView = DocumentManager.Instance.getDocumentView(topDoc); + if (newDocView) { + let de = new DragManager.DocumentDragData([topDoc], [undefined]); + de.moveDocument = topDocView.props.moveDocument; + let xf = newDocView.ContentDiv!.getBoundingClientRect(); + console.log("ex = " + ex + " " + xf.left + " " + (ex - xf.left)); + DragManager.StartDocumentDrag([newDocView.ContentDiv!], de, ex, ey, { + offsetX: (ex - xf.left), offsetY: (ey - xf.top), + handlers: { + dragComplete: () => { }, + }, + hideSource: false + }); + } + }, 10); + } else if (topDocView.props.ContainingCollectionView) { + let collView = topDocView.props.ContainingCollectionView!; + let [sx, sy] = xf.inverse().transformPoint(0, 0); + let [x, y] = collView.props.ScreenToLocalTransform().transformPoint(sx, sy); + topDoc.x = x; + topDoc.y = y; + } + } + @undoBatch @action toggleTemplate = (event: React.ChangeEvent, template: Template): void => { @@ -89,9 +128,10 @@ export class TemplateMenu extends React.Component { return (
      this.toggleTemplateActivity()}>+
      -
        +
          {templateMenu} - + +
      ); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index cca199afa..c4311fa52 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -46,6 +46,7 @@ border-radius: inherit; box-sizing: border-box; position: absolute; + overflow: hidden; .marqueeView { overflow: hidden; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 29f9b1429..9cbc652b9 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -77,7 +77,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } @computed get contentBounds() { - let bounds = this.fitToBox && !this.isAnnotationOverlay ? this.ComputeContentBounds(this.elements.filter(e => e.bounds).map(e => e.bounds!)) : undefined; + let bounds = this.fitToBox && !this.isAnnotationOverlay ? this.ComputeContentBounds(this.elements.filter(e => e.bounds && !e.bounds.z).map(e => e.bounds!)) : undefined; let res = { panX: bounds ? (bounds.x + bounds.r) / 2 : this.Document.panX || 0, panY: bounds ? (bounds.y + bounds.b) / 2 : this.Document.panY || 0, @@ -98,6 +98,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { 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 getTransformOverlay = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth + 1, -this.borderWidth + 1); 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()); private addLiveTextBox = (newBox: Doc) => { @@ -131,12 +132,15 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @action drop = (e: Event, de: DragManager.DropEvent) => { let xf = this.getTransform(); + let xfo = this.getTransformOverlay(); let [xp, yp] = xf.transformPoint(de.x, de.y); + let [xpo, ypo] = xfo.transformPoint(de.x, de.y); if (super.drop(e, de)) { if (de.data instanceof DragManager.DocumentDragData) { if (de.data.droppedDocuments.length) { - let x = xp - de.data.xOffset; - let y = yp - de.data.yOffset; + let z = NumCast(de.data.draggedDocuments[0].z); + let x = (z ? xpo : xp) - de.data.xOffset; + let y = (z ? ypo : yp) - de.data.yOffset; let dropX = NumCast(de.data.droppedDocuments[0].x); let dropY = NumCast(de.data.droppedDocuments[0].y); de.data.droppedDocuments.forEach(d => { @@ -292,8 +296,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { const newPanY = Math.min((1 - 1 / scale) * this.nativeHeight, Math.max(0, panY)); this.props.Document.panX = this.isAnnotationOverlay ? newPanX : panX; this.props.Document.panY = this.isAnnotationOverlay && StrCast(this.props.Document.backgroundLayout).indexOf("PDFBox") === -1 ? newPanY : panY; - // this.props.Document.panX = panX; - // this.props.Document.panY = panY; if (this.props.Document.scrollY) { this.props.Document.scrollY = panY - scale * this.props.Document[HeightSym](); } @@ -396,7 +398,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { addDocument: this.props.addDocument, removeDocument: this.props.removeDocument, moveDocument: this.props.moveDocument, - ScreenToLocalTransform: this.getTransform, + ScreenToLocalTransform: pair.layout.z ? this.getTransformOverlay : this.getTransform, renderDepth: this.props.renderDepth + 1, selectOnLoad: pair.layout[Id] === this._selectOnLoaded, PanelWidth: pair.layout[WidthSym], @@ -436,23 +438,25 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { }; } - getCalculatedPositions(script: ScriptField, params: { doc: Doc, index: number, collection: Doc, docs: Doc[], state: any }): { x?: number, y?: number, width?: number, height?: number, state?: any } { + getCalculatedPositions(script: ScriptField, params: { doc: Doc, index: number, collection: Doc, docs: Doc[], state: any }): { x?: number, y?: number, z?: number, width?: number, height?: number, state?: any } { const result = script.script.run(params); if (!result.success) { return {}; } - return result.result === undefined ? {} : result.result; + let doc = params.doc; + return result.result === undefined ? { x: Cast(doc.x, "number"), y: Cast(doc.y, "number"), z: Cast(doc.z, "number"), width: Cast(doc.width, "number"), height: Cast(doc.height, "number") } : result.result; } - private viewDefToJSX(viewDef: any): { ele: JSX.Element, bounds?: { x: number, y: number, width: number, height: number } } | undefined { + private viewDefToJSX(viewDef: any): { ele: JSX.Element, bounds?: { x: number, y: number, z?: number, width: number, height: number } } | undefined { if (viewDef.type === "text") { const text = Cast(viewDef.text, "string"); const x = Cast(viewDef.x, "number"); const y = Cast(viewDef.y, "number"); + const z = Cast(viewDef.z, "number"); const width = Cast(viewDef.width, "number"); const height = Cast(viewDef.height, "number"); const fontSize = Cast(viewDef.fontSize, "number"); - if ([text, x, y, width, height].some(val => val === undefined)) { + if ([text, x, y, z, width, height].some(val => val === undefined)) { return undefined; } @@ -460,7 +464,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { ele:
      {text}
      , bounds: { x: x!, y: y!, width: width!, height: height! } + }}>{text}
    , bounds: { x: x!, y: y!, z: z, width: width!, height: height! } }; } } @@ -472,7 +476,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { const script = this.Document.arrangeScript; let state: any = undefined; const docs = this.childDocs; - let elements: { ele: JSX.Element, bounds?: { x: number, y: number, width: number, height: number } }[] = []; + let elements: { ele: JSX.Element, bounds?: { x: number, y: number, z?: number, width: number, height: number } }[] = []; if (initScript) { const initResult = initScript.script.run({ docs, collection: this.Document }); if (initResult.success) { @@ -494,13 +498,13 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { let minim = BoolCast(doc.isMinimized); if (minim === undefined || !minim) { const pos = script ? this.getCalculatedPositions(script, { doc, index: prev.length, collection: this.Document, docs, state }) : - { x: Cast(doc.x, "number"), y: Cast(doc.y, "number"), width: Cast(doc.width, "number"), height: Cast(doc.height, "number") }; + { x: Cast(doc.x, "number"), y: Cast(doc.y, "number"), z: Cast(doc.z, "number"), width: Cast(doc.width, "number"), height: Cast(doc.height, "number") }; state = pos.state === undefined ? state : pos.state; 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 + bounds: (pos.x !== undefined && pos.y !== undefined && pos.width !== undefined && pos.height !== undefined) ? { x: pos.x, y: pos.y, z: pos.z, width: pos.width, height: pos.height } : undefined }); } } @@ -514,8 +518,13 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @computed.struct get views() { - return this.elements.map(ele => ele.ele); + return this.elements.filter(ele => ele.bounds && !ele.bounds.z).map(ele => ele.ele); } + @computed.struct + get overlayViews() { + return this.elements.filter(ele => ele.bounds && ele.bounds.z).map(ele => ele.ele); + } + @action onCursorMove = (e: React.PointerEvent) => { @@ -603,6 +612,12 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { , ...this.views ] + private overlayChildViews = () => { + console.log(this.overlayViews.length); + return [ + ...this.overlayViews + ]; + } public static AddCustomLayout(doc: Doc, dataKey: string): () => void { return () => { @@ -651,6 +666,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { + {this.overlayChildViews()}
); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 7ffd760e0..3b6c443c2 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -77,6 +77,7 @@ export class CollectionFreeFormDocumentView extends DocComponent; -- cgit v1.2.3-70-g09d2