From 7f42c98318899a51cb64080fc4f4e315e43bb150 Mon Sep 17 00:00:00 2001 From: 0x85FB9C51 <77808164+0x85FB9C51@users.noreply.github.com> Date: Tue, 6 Jul 2021 23:47:38 -0400 Subject: reoganization of schema view files, partial --- .../views/collections/CollectionSchemaCells.tsx | 584 --------------------- 1 file changed, 584 deletions(-) delete mode 100644 src/client/views/collections/CollectionSchemaCells.tsx (limited to 'src/client/views/collections/CollectionSchemaCells.tsx') diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx deleted file mode 100644 index 3fb9910b5..000000000 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ /dev/null @@ -1,584 +0,0 @@ -import React = require("react"); -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, observable } from "mobx"; -import { observer } from "mobx-react"; -import DatePicker from "react-datepicker"; -import "react-datepicker/dist/react-datepicker.css"; -import { CellInfo } from "react-table"; -import "react-table/react-table.css"; -import { DateField } from "../../../fields/DateField"; -import { Doc, DocListCast, Field, Opt } from "../../../fields/Doc"; -import { Id } from "../../../fields/FieldSymbols"; -import { List } from "../../../fields/List"; -import { SchemaHeaderField } from "../../../fields/SchemaHeaderField"; -import { ComputedField } from "../../../fields/ScriptField"; -import { BoolCast, Cast, DateCast, FieldValue, NumCast, StrCast } from "../../../fields/Types"; -import { ImageField } from "../../../fields/URLField"; -import { Utils, emptyFunction } from "../../../Utils"; -import { Docs } from "../../documents/Documents"; -import { DocumentType } from "../../documents/DocumentTypes"; -import { DocumentManager } from "../../util/DocumentManager"; -import { DragManager } from "../../util/DragManager"; -import { KeyCodes } from "../../util/KeyCodes"; -import { CompileScript } from "../../util/Scripting"; -import { SearchUtil } from "../../util/SearchUtil"; -import { SnappingManager } from "../../util/SnappingManager"; -import { undoBatch } from "../../util/UndoManager"; -import '../DocumentDecorations.scss'; -import { EditableView } from "../EditableView"; -import { MAX_ROW_HEIGHT } from '../globalCssVariables.scss'; -import { DocumentIconContainer } from "../nodes/DocumentIcon"; -import { OverlayView } from "../OverlayView"; -import "./CollectionSchemaView.scss"; -import { CollectionView } from "./CollectionView"; -const path = require('path'); - -export interface CellProps { - row: number; - col: number; - rowProps: CellInfo; - CollectionView: Opt; - ContainingCollection: Opt; - Document: Doc; - fieldKey: string; - renderDepth: number; - addDocTab: (document: Doc, where: string) => boolean; - pinToPres: (document: Doc) => void; - moveDocument?: (document: Doc | Doc[], targetCollection: Doc | undefined, - addDocument: (document: Doc | Doc[]) => boolean) => boolean; - isFocused: boolean; - changeFocusedCellByIndex: (row: number, col: number) => void; - 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; - showDoc: (doc: Doc | undefined, dataDoc?: any, screenX?: number, screenY?: number) => void; -} - -@observer -export class CollectionSchemaCell extends React.Component { - public static resolvedFieldKey(column: string, rowDoc: Doc) { - const fieldKey = column; - if (fieldKey.startsWith("*")) { - const rootKey = fieldKey.substring(1); - const allKeys = [...Array.from(Object.keys(rowDoc)), ...Array.from(Object.keys(Doc.GetProto(rowDoc)))]; - const matchedKeys = allKeys.filter(key => key.includes(rootKey)); - if (matchedKeys.length) return matchedKeys[0]; - } - return fieldKey; - } - @observable protected _isEditing: boolean = false; - protected _focusRef = React.createRef(); - protected _rowDoc = this.props.rowProps.original; - protected _rowDataDoc = Doc.GetProto(this.props.rowProps.original); - protected _dropDisposer?: DragManager.DragDropDisposer; - @observable contents: string = ""; - - componentDidMount() { document.addEventListener("keydown", this.onKeyDown); } - componentWillUnmount() { document.removeEventListener("keydown", this.onKeyDown); } - - @action - onKeyDown = (e: KeyboardEvent): void => { - if (this.props.isFocused && this.props.isEditable && e.keyCode === KeyCodes.ENTER) { - document.removeEventListener("keydown", this.onKeyDown); - this._isEditing = true; - this.props.setIsEditing(true); - } - } - - @action - isEditingCallback = (isEditing: boolean): void => { - document.removeEventListener("keydown", this.onKeyDown); - isEditing && document.addEventListener("keydown", this.onKeyDown); - this._isEditing = isEditing; - this.props.setIsEditing(isEditing); - this.props.changeFocusedCellByIndex(this.props.row, this.props.col); - } - - @action - onPointerDown = async (e: React.PointerEvent): Promise => { - this.onItemDown(e); - this.props.changeFocusedCellByIndex(this.props.row, this.props.col); - this.props.setPreviewDoc(this.props.rowProps.original); - - let url: string; - if (url = StrCast(this.props.rowProps.row.href)) { - try { - new URL(url); - const temp = window.open(url)!; - temp.blur(); - window.focus(); - } catch { } - } - - const doc = Cast(this._rowDoc[this.renderFieldKey], Doc, null); - doc && this.props.setPreviewDoc(doc); - } - - @undoBatch - 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.renderFieldKey] = res.result; - return true; - } - - private drop = (e: Event, de: DragManager.DropEvent) => { - if (de.complete.docDragData) { - if (de.complete.docDragData.draggedDocuments.length === 1) { - this._rowDataDoc[this.renderFieldKey] = de.complete.docDragData.draggedDocuments[0]; - } - else { - const coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title", "#f1efeb")], de.complete.docDragData.draggedDocuments, {}); - this._rowDataDoc[this.renderFieldKey] = coll; - } - e.stopPropagation(); - } - } - - protected dropRef = (ele: HTMLElement | null) => { - this._dropDisposer?.(); - ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this))); - } - - returnHighlights(contents: string, positions?: number[]) { - if (positions) { - const results = []; - StrCast(this.props.Document._searchString); - const length = StrCast(this.props.Document._searchString).length; - const color = contents ? "black" : "grey"; - - results.push({contents?.slice(0, positions[0])}); - positions.forEach((num, cur) => { - results.push({contents?.slice(num, num + length)}); - let end = 0; - cur === positions.length - 1 ? end = contents.length : end = positions[cur + 1]; - results.push({contents?.slice(num + length, end)}); - } - ); - return results; - } - return {contents ? contents?.valueOf() : "undefined"}; - } - - @computed get renderFieldKey() { return CollectionSchemaCell.resolvedFieldKey(this.props.rowProps.column.id!, this.props.rowProps.original); } - onItemDown = async (e: React.PointerEvent) => { - if (this.props.Document._searchDoc) { - const aliasdoc = await SearchUtil.GetAliasesOfDocument(this._rowDataDoc); - const targetContext = aliasdoc.length <= 0 ? undefined : Cast(aliasdoc[0].context, Doc, null); - DocumentManager.Instance.jumpToDocument(this._rowDoc, false, emptyFunction, targetContext, - undefined, undefined, undefined, () => this.props.setPreviewDoc(this._rowDoc)); - } - } - renderCellWithType(type: string | undefined) { - const dragRef: React.RefObject = React.createRef(); - - const fieldKey = this.renderFieldKey; - const field = this._rowDoc[fieldKey]; - - const onPointerEnter = (e: React.PointerEvent): void => { - if (e.buttons === 1 && SnappingManager.GetIsDragging() && (type === "document" || type === undefined)) { - dragRef.current!.className = "collectionSchemaView-cellContainer doc-drag-over"; - } - }; - const onPointerLeave = (e: React.PointerEvent): void => { - dragRef.current!.className = "collectionSchemaView-cellContainer"; - }; - - let contents = Field.toString(field as Field); - contents = contents === "" ? "--" : contents; - - let className = "collectionSchemaView-cellWrapper"; - if (this._isEditing) className += " editing"; - if (this.props.isFocused && this.props.isEditable) className += " focused"; - if (this.props.isFocused && !this.props.isEditable) className += " inactive"; - - const positions = []; - if (StrCast(this.props.Document._searchString).toLowerCase() !== "") { - let term = (field instanceof Promise) ? "...promise pending..." : contents.toLowerCase(); - const search = StrCast(this.props.Document._searchString).toLowerCase(); - let start = term.indexOf(search); - let tally = 0; - if (start !== -1) { - positions.push(start); - } - while (start < contents?.length && start !== -1) { - term = term.slice(start + search.length + 1); - tally += start + search.length + 1; - start = term.indexOf(search); - positions.push(tally + start); - } - if (positions.length > 1) { - positions.pop(); - } - } - const placeholder = type === "number" ? "0" : contents === "" ? "--" : "undefined"; - return ( -
this._isEditing = true)} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave}> -
-
- {!this.props.Document._searchDoc ? - { - const cfield = ComputedField.WithoutComputed(() => FieldValue(field)); - const cscript = cfield instanceof ComputedField ? cfield.script.originalScript : undefined; - const cfinalScript = cscript?.split("return")[cscript.split("return").length - 1]; - return cscript ? (cfinalScript?.endsWith(";") ? `:=${cfinalScript?.substring(0, cfinalScript.length - 2)}` : cfinalScript) : - Field.IsField(cfield) ? Field.toScriptString(cfield) : ""; - }} - SetValue={action((value: string) => { - // sets what is displayed after the user makes an input - let retVal = false; - if (value.startsWith(":=") || value.startsWith("=:=")) { - // decides how to compute a value when given either of the above strings - const script = value.substring(value.startsWith("=:=") ? 3 : 2); - retVal = this.props.setComputed(script, value.startsWith(":=") ? this._rowDataDoc : this._rowDoc, this.renderFieldKey, this.props.row, this.props.col); - } else { - // check if the input is a number - let inputIsNum = true; - for (let s of value) { - if (isNaN(parseInt(s))) { - inputIsNum = false; - } - } - // check if the input is a boolean - let inputIsBool: boolean = value == "false" || value == "true"; - // what to do in the case - if (!inputIsNum && !inputIsBool && !value.startsWith("=")) { - // if it's not a number, it's a string, and should be processed as such - // strips the string of quotes when it is edited to prevent quotes form being added to the text automatically - // after each edit - let valueSansQuotes = value; - if (this._isEditing) { - const vsqLength = valueSansQuotes.length; - // get rid of outer quotes - valueSansQuotes = valueSansQuotes.substring(value.startsWith("\"") ? 1 : 0, - valueSansQuotes.charAt(vsqLength - 1) == "\"" ? vsqLength - 1 : vsqLength); - } - let inputAsString = '"'; - // escape any quotes in the string - for (const i of valueSansQuotes) { - if (i == '"') { - inputAsString += '\\"'; - } else { - inputAsString += i; - } - } - // add a closing quote - inputAsString += '"'; - //two options here: we can strip off outer quotes or we can figure out what's going on with the script - const script = CompileScript(inputAsString, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } }); - const changeMade = inputAsString.length !== value.length || inputAsString.length - 2 !== value.length - script.compiled && (retVal = this.applyToDoc(changeMade ? this._rowDoc : this._rowDataDoc, this.props.row, this.props.col, script.run)); - // handle numbers and expressions - } else if (inputIsNum || value.startsWith("=")) { - //TODO: make accept numbers - const inputscript = value.substring(value.startsWith("=") ? 1 : 0); - // if commas are not stripped, the parser only considers the numbers after the last comma - let inputSansCommas = ""; - for (let s of inputscript) { - if (!(s == ",")) { - inputSansCommas += s; - } - } - const script = CompileScript(inputSansCommas, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } }); - const changeMade = value.length !== value.length || value.length - 2 !== value.length - script.compiled && (retVal = this.applyToDoc(changeMade ? this._rowDoc : this._rowDataDoc, this.props.row, this.props.col, script.run)); - // handle booleans - } else if (inputIsBool) { - const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } }); - const changeMade = value.length !== value.length || value.length - 2 !== value.length - script.compiled && (retVal = this.applyToDoc(changeMade ? this._rowDoc : this._rowDataDoc, this.props.row, this.props.col, script.run)); - } - } - if (retVal) { - this._isEditing = false; // need to set this here. otherwise, the assignment of the field will invalidate & cause render() to be called with the wrong value for 'editing' - this.props.setIsEditing(false); - } - return retVal; - })} - OnFillDown={async (value: string) => { - const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } }); - script.compiled && DocListCast(this.props.Document[this.props.fieldKey]). - forEach((doc, i) => value.startsWith(":=") ? - this.props.setComputed(value.substring(2), Doc.GetProto(doc), this.renderFieldKey, i, this.props.col) : - this.applyToDoc(Doc.GetProto(doc), i, this.props.col, script.run)); - }} - /> - : - this.returnHighlights(contents, positions) - } -
-
-
- ); - } - - render() { return this.renderCellWithType(undefined); } -} - -@observer -export class CollectionSchemaNumberCell extends CollectionSchemaCell { render() { return this.renderCellWithType("number"); } } - -@observer -export class CollectionSchemaBooleanCell extends CollectionSchemaCell { render() { return this.renderCellWithType("boolean"); } } - -@observer -export class CollectionSchemaStringCell extends CollectionSchemaCell { render() { return this.renderCellWithType("string"); } } - -@observer -export class CollectionSchemaDateCell extends CollectionSchemaCell { - @computed get _date(): Opt { return this._rowDoc[this.renderFieldKey] instanceof DateField ? DateCast(this._rowDoc[this.renderFieldKey]) : undefined; } - - @action - handleChange = (date: any) => { - // const script = CompileScript(date.toString(), { requiredType: "Date", addReturn: true, params: { this: Doc.name } }); - // if (script.compiled) { - // this.applyToDoc(this._document, this.props.row, this.props.col, script.run); - // } else { - // ^ DateCast is always undefined for some reason, but that is what the field should be set to - this._rowDoc[this.renderFieldKey] = new DateField(date as Date); - //} - } - - render() { - return !this.props.isFocused ? {this._date ? Field.toString(this._date as Field) : "--"} : - this.handleChange(date)} - onChange={date => this.handleChange(date)} - />; - } -} - -@observer -export class CollectionSchemaDocCell extends CollectionSchemaCell { - - _overlayDisposer?: () => void; - - @computed get _doc() { return FieldValue(Cast(this._rowDoc[this.renderFieldKey], Doc)); } - - @action - onSetValue = (value: string) => { - this._doc && (Doc.GetProto(this._doc).title = value); - - const script = CompileScript(value, { - addReturn: true, - typecheck: false, - transformer: DocumentIconContainer.getTransformer() - }); - - const results = script.compiled && script.run(); - if (results && results.success) { - this._rowDoc[this.renderFieldKey] = results.result; - return true; - } - return false; - } - - componentWillUnmount() { this.onBlur(); } - - onBlur = () => { this._overlayDisposer?.(); }; - onFocus = () => { - this.onBlur(); - this._overlayDisposer = OverlayView.Instance.addElement(, { x: 0, y: 0 }); - } - - @action - isEditingCallback = (isEditing: boolean): void => { - document.removeEventListener("keydown", this.onKeyDown); - isEditing && document.addEventListener("keydown", this.onKeyDown); - this._isEditing = isEditing; - this.props.setIsEditing(isEditing); - this.props.changeFocusedCellByIndex(this.props.row, this.props.col); - } - - render() { - return !this._doc ? this.renderCellWithType("document") : -
-
- StrCast(this._doc?.title)} - SetValue={action((value: string) => { - this.onSetValue(value); - return true; - })} - /> -
-
this._doc && this.props.addDocTab(this._doc, "add:right")} className="collectionSchemaView-cellContents-docButton"> - -
-
; - } -} - -@observer -export class CollectionSchemaImageCell extends CollectionSchemaCell { - - choosePath(url: URL) { - if (url.protocol === "data") return url.href; - if (url.href.indexOf(window.location.origin) === -1) return Utils.CorsProxy(url.href); - if (!/\.(png|jpg|jpeg|gif|webp)$/.test(url.href.toLowerCase())) return url.href;//Why is this here - - const ext = path.extname(url.href); - return url.href.replace(ext, "_o" + path.extname(url.href)); - } - - render() { - const field = Cast(this._rowDoc[this.renderFieldKey], ImageField, null); // retrieve the primary image URL that is being rendered from the data doc - const alts = DocListCast(this._rowDoc[this.renderFieldKey + "-alternates"]); // retrieve alternate documents that may be rendered as alternate images - const altpaths = alts.map(doc => Cast(doc[Doc.LayoutFieldKey(doc)], ImageField, null)?.url).filter(url => url).map(url => this.choosePath(url)); // access the primary layout data of the alternate documents - const paths = field ? [this.choosePath(field.url), ...altpaths] : altpaths; - const url = paths.length ? paths : [Utils.CorsProxy("http://www.cs.brown.edu/~bcz/noImage.png")]; - - const aspect = Doc.NativeAspect(this._rowDoc); - let width = Math.min(75, this.props.rowProps.width); - const height = Math.min(75, width / aspect); - width = height * aspect; - - const reference = React.createRef(); - return
-
- -
-
; - } -} - - -@observer -export class CollectionSchemaListCell extends CollectionSchemaCell { - _overlayDisposer?: () => void; - - @computed get _field() { return this._rowDoc[this.renderFieldKey]; } - @computed get _optionsList() { return this._field as List; } - @observable private _opened = false; - @observable private _text = "select an item"; - @observable private _selectedNum = 0; - - @action - onSetValue = (value: string) => { - // change if its a document - this._optionsList[this._selectedNum] = this._text = value; - - (this._field as List).splice(this._selectedNum, 1, value); - } - - @action - onSelected = (element: string, index: number) => { - this._text = element; - this._selectedNum = index; - } - - onFocus = () => { - this._overlayDisposer?.(); - this._overlayDisposer = OverlayView.Instance.addElement(, { x: 0, y: 0 }); - } - - render() { - const link = false; - const reference = React.createRef(); - - if (this._optionsList?.length) { - const options = !this._opened ? (null) : -
- {this._optionsList.map((element, index) => { - const val = Field.toString(element); - return
this.onSelected(StrCast(element), index)} > - {val} -
; - })} -
; - - const plainText =
{this._text}
; - const textarea =
- this._text} - SetValue={action((value: string) => { - // add special for params - this.onSetValue(value); - return true; - })} - /> -
; - - //☰ - return ( -
-
-
- -
{link ? plainText : textarea}
-
- {options} -
-
- ); - } - return this.renderCellWithType("list"); - } -} - - -@observer -export class CollectionSchemaCheckboxCell extends CollectionSchemaCell { - @computed get _isChecked() { return BoolCast(this._rowDoc[this.renderFieldKey]); } - - render() { - const reference = React.createRef(); - return ( -
- this._rowDoc[this.renderFieldKey] = e.target.checked} /> -
- ); - } -} - - -@observer -export class CollectionSchemaButtons extends CollectionSchemaCell { - render() { - return !this.props.Document._searchDoc || ![DocumentType.PDF, DocumentType.RTF].includes(StrCast(this._rowDoc.type) as DocumentType) ? <> : -
- - -
; - } -} \ No newline at end of file -- cgit v1.2.3-70-g09d2