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 5b455e2aaf119c7db1fe9ef22d71a3accf55a8e2 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 30 Jul 2019 10:27:42 -0400 Subject: tweaks. --- src/client/apis/youtube/YoutubeBox.tsx | 22 +++++++++------------- src/client/views/collections/CollectionView.tsx | 2 +- .../views/collections/CollectionViewChromes.tsx | 1 + 3 files changed, 11 insertions(+), 14 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/apis/youtube/YoutubeBox.tsx b/src/client/apis/youtube/YoutubeBox.tsx index 019d191bc..7f9a3ad70 100644 --- a/src/client/apis/youtube/YoutubeBox.tsx +++ b/src/client/apis/youtube/YoutubeBox.tsx @@ -1,20 +1,16 @@ -import "../../views/nodes/WebBox.scss"; -import React = require("react"); -import { FieldViewProps, FieldView } from "../../views/nodes/FieldView"; -import { HtmlField } from "../../../new_fields/HtmlField"; -import { WebField } from "../../../new_fields/URLField"; +import { action, observable, runInAction } from 'mobx'; import { observer } from "mobx-react"; -import { computed, reaction, IReactionDisposer, observable, action, runInAction } from 'mobx'; -import { DocumentDecorations } from "../../views/DocumentDecorations"; -import { InkingControl } from "../../views/InkingControl"; +import { Doc, DocListCastAsync } from "../../../new_fields/Doc"; +import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; import { Utils } from "../../../Utils"; import { DocServer } from "../../DocServer"; -import { NumCast, Cast, StrCast } from "../../../new_fields/Types"; -import "./YoutubeBox.scss"; import { Docs } from "../../documents/Documents"; -import { Doc, DocListCastAsync } from "../../../new_fields/Doc"; -import { listSpec } from "../../../new_fields/Schema"; -import { List } from "../../../new_fields/List"; +import { DocumentDecorations } from "../../views/DocumentDecorations"; +import { InkingControl } from "../../views/InkingControl"; +import { FieldView, FieldViewProps } from "../../views/nodes/FieldView"; +import "../../views/nodes/WebBox.scss"; +import "./YoutubeBox.scss"; +import React = require("react"); interface VideoTemplate { thumbnailUrl: string; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index b7ac8768f..212cc5477 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -85,7 +85,7 @@ export class CollectionView extends React.Component { } else { return [ - (), + (), this.SubViewHelper(type, renderProps) ]; } diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 2bffe3cc0..38aafd3cc 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -208,6 +208,7 @@ export class CollectionViewBaseChrome extends React.Component { }} onPointerDown={this.openViewSpecs} />
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 937af0cd2b2c01e7971c1edf120567ee15a4d5b9 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 30 Jul 2019 13:43:02 -0400 Subject: fixed snapshots for youtube videos. --- src/client/views/MainView.tsx | 3 +- .../views/collections/CollectionVideoView.scss | 9 ++ .../views/collections/CollectionVideoView.tsx | 24 +++-- src/client/views/nodes/VideoBox.tsx | 101 +++++++++++---------- 4 files changed, 80 insertions(+), 57 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ababbe949..88a636784 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,5 +1,5 @@ import { IconName, library } from '@fortawesome/fontawesome-svg-core'; -import { faArrowDown, faCloudUploadAlt, faArrowUp, faClone, faCheck, faPlay, faCaretUp, faLongArrowAltRight, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faPortrait, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt, faCat, faBolt } from '@fortawesome/free-solid-svg-icons'; +import { faArrowDown, faCloudUploadAlt, faArrowUp, faClone, faCheck, faPlay, faPause, faCaretUp, faLongArrowAltRight, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faPortrait, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt, faCat, faBolt } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, runInAction, reaction, trace } from 'mobx'; import { observer } from 'mobx-react'; @@ -126,6 +126,7 @@ export class MainView extends React.Component { library.add(faMusic); library.add(faTree); library.add(faPlay); + library.add(faPause); library.add(faClone); library.add(faCut); library.add(faCommentAlt); diff --git a/src/client/views/collections/CollectionVideoView.scss b/src/client/views/collections/CollectionVideoView.scss index 9d2c23d3e..509851ebb 100644 --- a/src/client/views/collections/CollectionVideoView.scss +++ b/src/client/views/collections/CollectionVideoView.scss @@ -6,6 +6,7 @@ top: 0; left:0; z-index: -1; + display:inline-table; } .collectionVideoView-time{ color : white; @@ -15,6 +16,14 @@ background-color: rgba(50, 50, 50, 0.2); transform-origin: left top; } +.collectionVideoView-snapshot{ + color : white; + top :25px; + right : 25px; + position: absolute; + background-color: rgba(50, 50, 50, 0.2); + transform-origin: left top; +} .collectionVideoView-play { width: 25px; height: 20px; diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx index a264cc402..5185d9d0e 100644 --- a/src/client/views/collections/CollectionVideoView.tsx +++ b/src/client/views/collections/CollectionVideoView.tsx @@ -9,6 +9,7 @@ import "./CollectionVideoView.scss"; import React = require("react"); import { InkingControl } from "../InkingControl"; import { InkTool } from "../../../new_fields/InkField"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @observer @@ -21,18 +22,20 @@ export class CollectionVideoView extends React.Component { private get uIButtons() { let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().Scale); let curTime = NumCast(this.props.Document.curPage); - return ([
+ return ([
{"" + Math.round(curTime)} {" " + Math.round((curTime - Math.trunc(curTime)) * 100)}
, +
+ +
, VideoBox._showControls ? (null) : [ -
- {this._videoBox && this._videoBox.Playing ? "\"" : ">"} +
+
, -
+
F -
- +
]]); } @@ -56,6 +59,15 @@ export class CollectionVideoView extends React.Component { } } + @action + onSnapshot = (e: React.PointerEvent) => { + if (this._videoBox) { + this._videoBox.Snapshot(); + e.stopPropagation(); + e.preventDefault(); + } + } + _isclick = 0; @action onResetDown = (e: React.PointerEvent) => { diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index d2657227a..1f8636826 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -89,6 +89,56 @@ export class VideoBox extends DocComponent(VideoD this._youtubePlayer && this.props.addDocTab(this.props.Document, this.props.DataDoc, "inTab"); } + @action public Snapshot() { + let width = NumCast(this.props.Document.width); + let height = NumCast(this.props.Document.height); + var canvas = document.createElement('canvas'); + canvas.width = 640; + canvas.height = 640 * NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.nativeWidth); + var ctx = canvas.getContext('2d');//draw image to canvas. scale to target dimensions + if (ctx) { + ctx.rect(0, 0, canvas.width, canvas.height); + ctx.fillStyle = "blue"; + ctx.fill(); + this._videoRef && ctx.drawImage(this._videoRef, 0, 0, canvas.width, canvas.height); + } + + if (!this._videoRef) { // can't find a way to take snapshots of videos + let b = Docs.Create.ButtonDocument({ + x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y), + width: 150, height: 50, title: NumCast(this.props.Document.curPage).toString() + }); + const script = CompileScript(`(self as any).curPage = ${NumCast(this.props.Document.curPage)}`, { + params: { this: Doc.name }, + capturedVariables: { self: this.props.Document }, + typecheck: false, + editable: true, + }); + if (script.compiled) { + b.onClick = new ScriptField(script); + this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.addDocument && this.props.ContainingCollectionView.props.addDocument(b, false); + } else { + console.log(script.errors.map(error => error.messageText).join("\n")); + } + } else { + //convert to desired file format + var dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png' + // if you want to preview the captured image, + let filename = encodeURIComponent("snapshot" + this.props.Document.title + "_" + this.props.Document.curPage).replace(/\./g, ""); + VideoBox.convertDataUri(dataUrl, filename).then(returnedFilename => { + if (returnedFilename) { + let url = Utils.prepend(returnedFilename); + let imageSummary = Docs.Create.ImageDocument(url, { + x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y), + width: 150, height: height / width * 150, title: "--snapshot" + NumCast(this.props.Document.curPage) + " image-" + }); + this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.addDocument && this.props.ContainingCollectionView.props.addDocument(imageSummary, false); + DocUtils.MakeLink(imageSummary, this.props.Document); + } + }); + } + } + @action updateTimecode = () => { this.player && (this.props.Document.curPage = this.player.currentTime); @@ -152,56 +202,7 @@ export class VideoBox extends DocComponent(VideoD let subitems: ContextMenuProps[] = []; subitems.push({ description: "Copy path", event: () => { Utils.CopyText(url); }, icon: "expand-arrows-alt" }); subitems.push({ description: "Toggle Show Controls", event: action(() => VideoBox._showControls = !VideoBox._showControls), icon: "expand-arrows-alt" }); - let width = NumCast(this.props.Document.width); - let height = NumCast(this.props.Document.height); - subitems.push({ - description: "Take Snapshot", event: async () => { - var canvas = document.createElement('canvas'); - canvas.width = 640; - canvas.height = 640 * NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.nativeWidth); - var ctx = canvas.getContext('2d');//draw image to canvas. scale to target dimensions - if (ctx) { - ctx.rect(0, 0, canvas.width, canvas.height); - ctx.fillStyle = "blue"; - ctx.fill(); - this._videoRef && ctx.drawImage(this._videoRef, 0, 0, canvas.width, canvas.height); - } - - if (!this._videoRef) { // can't find a way to take snapshots of videos - let b = Docs.Create.ButtonDocument({ - x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y), width: 150, height: 50, title: NumCast(this.props.Document.curPage).toString() - }); - const script = CompileScript(`this.props.Document.curPage = ${NumCast(this.props.Document.curPage)}`, { - params: { this: Doc.name }, - typecheck: false, - editable: true, - }); - if (!script.compiled) { - console.log(script.errors.map(error => error.messageText).join("\n")); - return; - } - b.onClick = new ScriptField(script); - this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.addDocument && this.props.ContainingCollectionView.props.addDocument(b, false); - } else { - //convert to desired file format - var dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png' - // if you want to preview the captured image, - let filename = encodeURIComponent("snapshot" + this.props.Document.title + "_" + this.props.Document.curPage).replace(/\./g, ""); - VideoBox.convertDataUri(dataUrl, filename).then(returnedFilename => { - if (returnedFilename) { - let url = Utils.prepend(returnedFilename); - let imageSummary = Docs.Create.ImageDocument(url, { - x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y), - width: 150, height: height / width * 150, title: "--snapshot" + NumCast(this.props.Document.curPage) + " image-" - }); - this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.addDocument && this.props.ContainingCollectionView.props.addDocument(imageSummary, false); - DocUtils.MakeLink(imageSummary, this.props.Document); - } - }); - } - }, - icon: "expand-arrows-alt" - }); + subitems.push({ description: "Take Snapshot", event: () => this.Snapshot(), icon: "expand-arrows-alt" }); ContextMenu.Instance.addItem({ description: "Video Funcs...", subitems: subitems, icon: "video" }); } } -- 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) :