aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/old_collectionSchema/OldCollectionSchemaCells.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections/old_collectionSchema/OldCollectionSchemaCells.tsx')
-rw-r--r--src/client/views/collections/old_collectionSchema/OldCollectionSchemaCells.tsx683
1 files changed, 683 insertions, 0 deletions
diff --git a/src/client/views/collections/old_collectionSchema/OldCollectionSchemaCells.tsx b/src/client/views/collections/old_collectionSchema/OldCollectionSchemaCells.tsx
new file mode 100644
index 000000000..5953f85ad
--- /dev/null
+++ b/src/client/views/collections/old_collectionSchema/OldCollectionSchemaCells.tsx
@@ -0,0 +1,683 @@
+// import React = require('react');
+// import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+// import { action, computed, observable } from 'mobx';
+// import { observer } from 'mobx-react';
+// import { extname } from 'path';
+// import DatePicker from 'react-datepicker';
+// import { CellInfo } from 'react-table';
+// 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, StrCast } from '../../../../fields/Types';
+// import { ImageField } from '../../../../fields/URLField';
+// import { emptyFunction, Utils } 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 '../../../views/DocumentDecorations.scss';
+// import { EditableView } from '../../EditableView';
+// import { MAX_ROW_HEIGHT } from '../../global/globalCssVariables.scss';
+// import { DocumentIconContainer } from '../../nodes/DocumentIcon';
+// import { OverlayView } from '../../OverlayView';
+// import { CollectionView } from '../CollectionView';
+// import './CollectionSchemaView.scss';
+// import { OpenWhere } from '../../nodes/DocumentView';
+// import { PinProps } from '../../nodes/trails';
+
+// // intialize cell properties
+// export interface CellProps {
+// row: number;
+// col: number;
+// rowProps: CellInfo;
+// // currently unused
+// CollectionView: Opt<CollectionView>;
+// // currently unused
+// ContainingCollection: Opt<CollectionView>;
+// Document: Doc;
+// // column name
+// fieldKey: string;
+// // currently unused
+// renderDepth: number;
+// // called when a button is pressed on the node itself
+// addDocTab: (document: Doc, where: OpenWhere) => boolean;
+// pinToPres: (document: Doc, pinProps: PinProps) => void;
+// moveDocument?: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean;
+// isFocused: boolean;
+// changeFocusedCellByIndex: (row: number, col: number) => void;
+// // set whether the cell is in the isEditing mode
+// 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;
+// // currnetly unused
+// showDoc: (doc: Doc | undefined, dataDoc?: any, screenX?: number, screenY?: number) => void;
+// }
+
+// @observer
+// export class CollectionSchemaCell extends React.Component<CellProps> {
+// // return a field key that is corrected for whether it COMMENT
+// 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<HTMLDivElement>();
+// protected _rowDoc = this.props.rowProps.original;
+// // Gets the serialized data in proto form of the base proto that this document's proto inherits from
+// protected _rowDataDoc = Doc.GetProto(this.props.rowProps.original);
+// // methods for dragging and dropping
+// 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 a cell is editable and clicked, hitting enter shoudl allow the user to edit it
+// 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 => {
+// // a general method that takes a boolean that determines whether the cell should be in
+// // is-editing mode
+// // remove the event listener if it's there
+// document.removeEventListener('keydown', this.onKeyDown);
+// // it's not already in is-editing mode, re-add the event listener
+// 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<void> => {
+// // pan to the cell
+// this.onItemDown(e);
+// // focus on it
+// 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))) {
+// // opens up the the doc in a new window, blurring the old one
+// 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) => {
+// // apply a specified change to the cell
+// 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;
+// // change what is rendered to this new changed cell content
+// doc[this.renderFieldKey] = res.result;
+// return true;
+// // return whether the change was successful
+// };
+
+// private drop = (e: Event, de: DragManager.DropEvent) => {
+// // if the drag has data at its completion
+// if (de.complete.docDragData) {
+// // if only one doc was dragged
+// if (de.complete.docDragData.draggedDocuments.length === 1) {
+// // update the renderFieldKey
+// this._rowDataDoc[this.renderFieldKey] = de.complete.docDragData.draggedDocuments[0];
+// } else {
+// // create schema document reflecting the new column arrangement
+// 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) => {
+// // if the drop disposer is not undefined, run its function
+// this._dropDisposer?.();
+// // if ele is not null, give ele a non-undefined drop disposer
+// 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(
+// <span key="-1" style={{ color }}>
+// {contents?.slice(0, positions[0])}
+// </span>
+// );
+// positions.forEach((num, cur) => {
+// results.push(
+// <span key={'start' + cur} style={{ backgroundColor: '#FFFF00', color }}>
+// {contents?.slice(num, num + length)}
+// </span>
+// );
+// let end = 0;
+// cur === positions.length - 1 ? (end = contents.length) : (end = positions[cur + 1]);
+// results.push(
+// <span key={'end' + cur} style={{ color }}>
+// {contents?.slice(num + length, end)}
+// </span>
+// );
+// });
+// return results;
+// }
+// return <span style={{ color: contents ? 'black' : 'grey' }}>{contents ? contents?.valueOf() : 'undefined'}</span>;
+// }
+
+// @computed get renderFieldKey() {
+// // gets the resolved field key of this cell
+// return CollectionSchemaCell.resolvedFieldKey(this.props.rowProps.column.id!, this.props.rowProps.original);
+// }
+
+// onItemDown = async (e: React.PointerEvent) => {
+// // if the document is a document used to change UI for search results in schema view
+// if (this.props.Document._searchDoc) {
+// const aliasdoc = await SearchUtil.GetAliasesOfDocument(this._rowDataDoc);
+// const targetContext = aliasdoc.length <= 0 ? undefined : Cast(aliasdoc[0].context, Doc, null);
+// // Jump to the this document
+// DocumentManager.Instance.jumpToDocument(this._rowDoc, { willPan: true }, emptyFunction, targetContext ? [targetContext] : [], () => this.props.setPreviewDoc(this._rowDoc));
+// }
+// };
+
+// renderCellWithType(type: string | undefined) {
+// const dragRef: React.RefObject<HTMLDivElement> = React.createRef();
+
+// // the column
+// const fieldKey = this.renderFieldKey;
+// // the exact cell
+// const field = this._rowDoc[fieldKey];
+
+// const onPointerEnter = (e: React.PointerEvent): void => {
+// // e.buttons === 1 means the left moue pointer is down
+// if (e.buttons === 1 && SnappingManager.GetIsDragging() && (type === 'document' || type === undefined)) {
+// dragRef.current!.className = 'collectionSchemaView-cellContainer doc-drag-over';
+// }
+// };
+// const onPointerLeave = (e: React.PointerEvent): void => {
+// // change the class name to indicate that the cell is no longer being dragged
+// dragRef.current!.className = 'collectionSchemaView-cellContainer';
+// };
+
+// let contents = Field.toString(field as Field);
+// // display 2 hyphens instead of a blank box for empty cells
+// contents = contents === '' ? '--' : contents;
+
+// // classname reflects the tatus of the cell
+// 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() !== '') {
+// // term is ...promise pending... if the field is a Promise, otherwise it is the cell's contents
+// 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 search is found in term
+// if (start !== -1) {
+// positions.push(start);
+// }
+// // if search is found in term, continue finding all instances of search in term
+// 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);
+// }
+// // remove the last position
+// if (positions.length > 1) {
+// positions.pop();
+// }
+// }
+// const placeholder = type === 'number' ? '0' : contents === '' ? '--' : 'undefined';
+// return (
+// <div
+// className="collectionSchemaView-cellContainer"
+// style={{ cursor: field instanceof Doc ? 'grab' : 'auto' }}
+// ref={dragRef}
+// onPointerDown={this.onPointerDown}
+// onClick={action(e => (this._isEditing = true))}
+// onPointerEnter={onPointerEnter}
+// onPointerLeave={onPointerLeave}>
+// <div className={className} ref={this._focusRef} tabIndex={-1}>
+// <div className="collectionSchemaView-cellContents" ref={type === undefined || type === 'document' ? this.dropRef : null}>
+// {!this.props.Document._searchDoc ? (
+// <EditableView
+// editing={this._isEditing}
+// isEditingCallback={this.isEditingCallback}
+// display={'inline'}
+// contents={contents}
+// height={'auto'}
+// maxHeight={Number(MAX_ROW_HEIGHT)}
+// placeholder={placeholder}
+// GetValue={() => {
+// 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 (const s of value) {
+// if (isNaN(parseInt(s)) && !(s === '.') && !(s === ',')) {
+// inputIsNum = false;
+// }
+// }
+// // check if the input is a boolean
+// const 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;
+// // change it if a change is made, otherwise, just compile using the old cell conetnts
+// 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 (const 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 - 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 - 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) => {
+// // computes all of the value preceded by :=
+// 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)
+// )}
+// </div>
+// </div>
+// </div>
+// );
+// }
+
+// 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<DateField> {
+// // if the cell is a date field, cast then contents to a date. Otherrwwise, make the contents undefined.
+// 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 ? (
+// <span onPointerDown={this.onPointerDown}>{this._date ? Field.toString(this._date as Field) : '--'}</span>
+// ) : (
+// <DatePicker selected={this._date?.date || new Date()} onSelect={date => 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: true,
+// transformer: DocumentIconContainer.getTransformer(),
+// });
+// // compile the script
+// const results = script.compiled && script.run();
+// // if the script was compiled and 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(<DocumentIconContainer />, { x: 0, y: 0 });
+// };
+
+// @action
+// isEditingCallback = (isEditing: boolean): void => {
+// // the isEditingCallback from a general CollectionSchemaCell
+// 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() {
+// // if there's a doc, render it
+// return !this._doc ? (
+// this.renderCellWithType('document')
+// ) : (
+// <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
+// <div className="collectionSchemaView-cellContents-document" style={{ padding: '5.9px' }} ref={this.dropRef} onFocus={this.onFocus} onBlur={this.onBlur}>
+// <EditableView
+// editing={this._isEditing}
+// isEditingCallback={this.isEditingCallback}
+// display={'inline'}
+// contents={this._doc.title || '--'}
+// height={'auto'}
+// maxHeight={Number(MAX_ROW_HEIGHT)}
+// GetValue={() => StrCast(this._doc?.title)}
+// SetValue={action((value: string) => {
+// this.onSetValue(value);
+// return true;
+// })}
+// />
+// </div>
+// <div onClick={() => this._doc && this.props.addDocTab(this._doc, OpenWhere.addRight)} className="collectionSchemaView-cellContents-docButton">
+// <FontAwesomeIcon icon="external-link-alt" size="lg" />
+// </div>
+// </div>
+// );
+// }
+// }
+
+// @observer
+// export class CollectionSchemaImageCell extends CollectionSchemaCell {
+// choosePath(url: URL) {
+// if (url.protocol === 'data') return url.href; // if the url ises the data protocol, just return the href
+// if (url.href.indexOf(window.location.origin) === -1) return Utils.CorsProxy(url.href); // otherwise, put it through the cors proxy erver
+// if (!/\.(png|jpg|jpeg|gif|webp)$/.test(url.href.toLowerCase())) return url.href; //Why is this here — good question
+
+// const ext = extname(url.href);
+// return url.href.replace(ext, '_o' + ext);
+// }
+
+// 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;
+// // If there is a path, follow it; otherwise, follow a link to a default image icon
+// const url = paths.length ? paths : [Utils.CorsProxy('http://www.cs.brown.edu/~bcz/noImage.png')];
+
+// const aspect = Doc.NativeAspect(this._rowDoc); // aspect ratio
+// let width = Math.min(75, this.props.rowProps.width); // get a with that is no smaller than 75px
+// const height = Math.min(75, width / aspect); // get a height either proportional to that or 75 px
+// width = height * aspect; // increase the width of the image if necessary to maintain proportionality
+
+// const reference = React.createRef<HTMLDivElement>();
+// return (
+// <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
+// <div className="collectionSchemaView-cellContents" key={this._rowDoc[Id]} ref={reference}>
+// <img src={url[0]} width={paths.length ? width : '20px'} height={paths.length ? height : '20px'} />
+// </div>
+// </div>
+// );
+// }
+// }
+
+// @observer
+// export class CollectionSchemaListCell extends CollectionSchemaCell {
+// _overlayDisposer?: () => void;
+
+// @computed get _field() {
+// return this._rowDoc[this.renderFieldKey];
+// }
+// @computed get _optionsList() {
+// return this._field as List<any>;
+// }
+// @observable private _opened = false; // whether the list is opened
+// @observable private _text = 'select an item';
+// @observable private _selectedNum = 0; // the index of the list item selected
+
+// @action
+// onSetValue = (value: string) => {
+// // change if it's a document
+// this._optionsList[this._selectedNum] = this._text = value;
+
+// (this._field as List<any>).splice(this._selectedNum, 1, value);
+// };
+
+// @action
+// onSelected = (element: string, index: number) => {
+// // if an item is selected, the private variables should update to reflect this
+// this._text = element;
+// this._selectedNum = index;
+// };
+
+// onFocus = () => {
+// this._overlayDisposer?.();
+// this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
+// };
+
+// render() {
+// const link = false;
+// const reference = React.createRef<HTMLDivElement>();
+
+// // if the list is not opened, don't display it; otherwise, do.
+// if (this._optionsList?.length) {
+// const options = !this._opened ? null : (
+// <div>
+// {this._optionsList.map((element, index) => {
+// const val = Field.toString(element);
+// return (
+// <div className="collectionSchemaView-dropdownOption" key={index} style={{ padding: '6px' }} onPointerDown={e => this.onSelected(StrCast(element), index)}>
+// {val}
+// </div>
+// );
+// })}
+// </div>
+// );
+
+// const plainText = <div style={{ padding: '5.9px' }}>{this._text}</div>;
+// const textarea = (
+// <div className="collectionSchemaView-cellContents" key={this._rowDoc[Id]} style={{ padding: '5.9px' }} ref={this.dropRef}>
+// <EditableView
+// editing={this._isEditing}
+// isEditingCallback={this.isEditingCallback}
+// display={'inline'}
+// contents={this._text}
+// height={'auto'}
+// maxHeight={Number(MAX_ROW_HEIGHT)}
+// GetValue={() => this._text}
+// SetValue={action((value: string) => {
+// // add special for params
+// this.onSetValue(value);
+// return true;
+// })}
+// />
+// </div>
+// );
+
+// //☰
+// return (
+// <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
+// <div className="collectionSchemaView-cellContents" key={this._rowDoc[Id]} ref={reference}>
+// <div className="collectionSchemaView-dropDownWrapper">
+// <button type="button" className="collectionSchemaView-dropdownButton" style={{ right: 'length', position: 'relative' }} onClick={action(e => (this._opened = !this._opened))}>
+// <FontAwesomeIcon icon={this._opened ? 'caret-up' : 'caret-down'} size="sm" />
+// </button>
+// <div className="collectionSchemaView-dropdownText"> {link ? plainText : textarea} </div>
+// </div>
+// {options}
+// </div>
+// </div>
+// );
+// }
+// return this.renderCellWithType('list');
+// }
+// }
+
+// @observer
+// export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
+// @computed get _isChecked() {
+// return BoolCast(this._rowDoc[this.renderFieldKey]);
+// }
+
+// render() {
+// const reference = React.createRef<HTMLDivElement>();
+// return (
+// <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
+// <input type="checkbox" checked={this._isChecked} onChange={e => (this._rowDoc[this.renderFieldKey] = e.target.checked)} />
+// </div>
+// );
+// }
+// }
+
+// @observer
+// export class CollectionSchemaButtons extends CollectionSchemaCell {
+// // the navigation buttons for schema view when it is used for search.
+// render() {
+// return !this.props.Document._searchDoc || ![DocumentType.PDF, DocumentType.RTF].includes(StrCast(this._rowDoc.type) as DocumentType) ? (
+// <></>
+// ) : (
+// <div style={{ paddingTop: 8, paddingLeft: 3 }}>
+// <button style={{ padding: 2, left: 77 }} onClick={() => Doc.SearchMatchNext(this._rowDoc, true)}>
+// <FontAwesomeIcon icon="arrow-up" size="sm" />
+// </button>
+// <button style={{ padding: 2 }} onClick={() => Doc.SearchMatchNext(this._rowDoc, false)}>
+// <FontAwesomeIcon icon="arrow-down" size="sm" />
+// </button>
+// </div>
+// );
+// }
+// }