diff options
-rw-r--r-- | src/client/views/EditableView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/CollectionSchemaCells.tsx | 26 | ||||
-rw-r--r-- | src/client/views/collections/CollectionSchemaView.tsx | 82 |
3 files changed, 96 insertions, 14 deletions
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 373b63282..c3612fee9 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -134,7 +134,7 @@ export class EditableView extends React.Component<EditableProps> { return ( <div className={`editableView-container-editing${this.props.oneLine ? "-oneLine" : ""}`} style={{ display: this.props.display, height: "auto", maxHeight: `${this.props.height}` }} - onClick={this.onClick} > + onClick={this.onClick}> <span style={{ fontStyle: this.props.fontStyle, fontSize: this.props.fontSize }}>{this.props.contents}</span> </div> ); diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index c91f1017b..e00142c91 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -24,7 +24,7 @@ import { SelectionManager } from "../../util/SelectionManager"; import { library } from '@fortawesome/fontawesome-svg-core'; import { faExpand } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField"; +import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; library.add(faExpand); @@ -44,6 +44,8 @@ export interface CellProps { setIsEditing: (isEditing: boolean) => void; isEditable: boolean; setPreviewDoc: (doc: Doc) => void; + setComputed: (script: string, doc: Doc, field: string, row: number, col: number) => boolean; + getField: (row: number, col?: number) => void; } @observer @@ -84,9 +86,11 @@ export class CollectionSchemaCell extends React.Component<CellProps> { this.props.changeFocusedCellByIndex(this.props.row, this.props.col); } - applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { - const res = run({ this: doc }); + applyToDoc = (doc: Doc, row: number, col: number, run: (args?: { [name: string]: any }) => any) => { + const res = run({ this: doc, $r: row, $c: col, $: (r: number = 0, c: number = 0) => this.props.getField(r + row, c + col) }); if (!res.success) return false; + // doc[this.props.fieldKey] = res.result; + // return true; doc[this.props.rowProps.column.id as string] = res.result; return true; } @@ -176,7 +180,6 @@ export class CollectionSchemaCell extends React.Component<CellProps> { if (this.props.isFocused && !this.props.isEditable) className += " inactive"; let doc = FieldValue(Cast(field, Doc)); - if (type === "document") console.log("doc", typeof field); let fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc); let docExpander = ( <div className="collectionSchemaView-cellContents-docExpander" onPointerDown={this.expandDoc} > @@ -203,22 +206,25 @@ export class CollectionSchemaCell extends React.Component<CellProps> { } } SetValue={(value: string) => { - let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } }); + if (value.startsWith(":=")) { + return this.props.setComputed(value.substring(2), props.Document, this.props.rowProps.column.id!, this.props.row, this.props.col); + } + let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } }); if (!script.compiled) { return false; } - return this.applyToDoc(props.Document, script.run); + return this.applyToDoc(props.Document, this.props.row, this.props.col, script.run); }} OnFillDown={async (value: string) => { - let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } }); + let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } }); if (!script.compiled) { return; } const run = script.run; - //TODO This should be able to be refactored to compile the script once const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]); - val && val.forEach(doc => this.applyToDoc(doc, run)); - }} /> + val && val.forEach((doc, i) => this.applyToDoc(doc, i, this.props.col, run)); + }} + /> </div > {fieldIsDoc ? docExpander : null} </div> diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index d504f9799..42843ad30 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -321,13 +321,12 @@ export class SchemaTable extends React.Component<SchemaTableProps> { } let cols = this.columns.map(col => { - let header = <CollectionSchemaHeader keyValue={col} possibleKeys={possibleKeys} existingKeys={this.columns.map(c => c.heading)} keyType={this.getColumnType(col)} - typeConst={col.type !== undefined || columnTypes.get(col.heading) !== undefined} + typeConst={columnTypes.get(col.heading) !== undefined} onSelect={this.changeColumns} setIsEditing={this.setHeaderIsEditing} deleteColumn={this.deleteColumn} @@ -360,7 +359,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> { moveDocument: this.props.moveDocument, setIsEditing: this.setCellIsEditing, isEditable: isEditable, - setPreviewDoc: this.props.setPreviewDoc + setPreviewDoc: this.props.setPreviewDoc, + setComputed: this.setComputed, + getField: this.getField, }; let colType = this.getColumnType(col); @@ -772,6 +773,81 @@ export class SchemaTable extends React.Component<SchemaTableProps> { } } + getField = (row: number, col?: number) => { + // const docs = DocListCast(this.props.Document[this.props.fieldKey]); + + let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document; + const docs = DocListCast(cdoc[this.props.fieldKey]); + + row = row % docs.length; + while (row < 0) row += docs.length; + const columns = this.columns; + const doc = docs[row]; + if (col === undefined) { + return doc; + } + if (col >= 0 && col < columns.length) { + const column = this.columns[col].heading; + return doc[column]; + } + return undefined; + } + + createTransformer = (row: number, col: number): Transformer => { + const self = this; + const captures: { [name: string]: Field } = {}; + + const transformer: ts.TransformerFactory<ts.SourceFile> = context => { + return root => { + function visit(node: ts.Node) { + node = ts.visitEachChild(node, visit, context); + if (ts.isIdentifier(node)) { + const isntPropAccess = !ts.isPropertyAccessExpression(node.parent) || node.parent.expression === node; + const isntPropAssign = !ts.isPropertyAssignment(node.parent) || node.parent.name !== node; + if (isntPropAccess && isntPropAssign) { + if (node.text === "$r") { + return ts.createNumericLiteral(row.toString()); + } else if (node.text === "$c") { + return ts.createNumericLiteral(col.toString()); + } else if (node.text === "$") { + if (ts.isCallExpression(node.parent)) { + // captures.doc = self.props.Document; + // captures.key = self.props.fieldKey; + } + } + } + } + + return node; + } + return ts.visitNode(root, visit); + }; + }; + + // const getVars = () => { + // return { capturedVariables: captures }; + // }; + + return { transformer, /*getVars*/ }; + } + + setComputed = (script: string, doc: Doc, field: string, row: number, col: number): boolean => { + script = + `const $ = (row:number, col?:number) => { + if(col === undefined) { + return (doc as any)[key][row + ${row}]; + } + return (doc as any)[key][row + ${row}][(doc as any).schemaColumns[col + ${col}].heading]; + } + return ${script}`; + const compiled = CompileScript(script, { params: { this: Doc.name }, capturedVariables: { doc: this.props.Document, key: this.props.fieldKey }, typecheck: true, transformer: this.createTransformer(row, col) }); + if (compiled.compiled) { + doc[field] = new ComputedField(compiled); + return true; + } + return false; + } + render() { // if (SelectionManager.SelectedDocuments().length > 0) console.log(StrCast(SelectionManager.SelectedDocuments()[0].Document.title)); // if (DocumentManager.Instance.getDocumentView(this.props.Document)) console.log(StrCast(this.props.Document.title), SelectionManager.IsSelected(DocumentManager.Instance.getDocumentView(this.props.Document)!)) |