aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
diff options
context:
space:
mode:
authorJames Hu <51237606+jameshu111@users.noreply.github.com>2023-05-04 10:36:59 -0400
committerJames Hu <51237606+jameshu111@users.noreply.github.com>2023-05-04 10:36:59 -0400
commit725bf38dc018cb218d8a88605234e95a2beee446 (patch)
tree9150905cf1b67b06c03fdd8d10ac6da6e8246832 /src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
parent96465f2dccc974a821fa912c90def988b76808e5 (diff)
parent1c24114bbe8f69f61948f7531277305457926498 (diff)
Merge branch 'master' into james-server-stats
Diffstat (limited to 'src/client/views/collections/collectionSchema/CollectionSchemaView.tsx')
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx334
1 files changed, 216 insertions, 118 deletions
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 6d5a73e55..a59d7e5a3 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1,21 +1,22 @@
import React = require('react');
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, ObservableMap, untracked } from 'mobx';
+import { action, computed, observable, ObservableMap, observe, trace } from 'mobx';
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
-import { Doc, Field, StrListCast } from '../../../../fields/Doc';
+import { Doc, DocListCast, Field, NumListCast, StrListCast } from '../../../../fields/Doc';
import { Id } from '../../../../fields/FieldSymbols';
import { List } from '../../../../fields/List';
import { listSpec } from '../../../../fields/Schema';
import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
-import { emptyFunction, returnDefault, returnEmptyDoclist, returnEmptyString, returnFalse, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils';
-import { Docs, DocUtils } from '../../../documents/Documents';
+import { emptyFunction, returnDefault, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils';
+import { Docs, DocumentOptions, DocUtils, FInfo } from '../../../documents/Documents';
import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
import { SelectionManager } from '../../../util/SelectionManager';
import { undoBatch } from '../../../util/UndoManager';
import { ContextMenu } from '../../ContextMenu';
import { EditableView } from '../../EditableView';
+import { Colors } from '../../global/globalEnums';
import { DocFocusOptions, DocumentView } from '../../nodes/DocumentView';
import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
import { KeyValueBox } from '../../nodes/KeyValueBox';
@@ -29,52 +30,59 @@ export enum ColumnType {
Number,
String,
Boolean,
- Doc,
+ Date,
Image,
+ RTF,
+ Any,
}
+export const FInfotoColType: { [key: string]: ColumnType } = {
+ string: ColumnType.String,
+ number: ColumnType.Number,
+ boolean: ColumnType.Boolean,
+ date: ColumnType.Date,
+ image: ColumnType.Image,
+ rtf: ColumnType.RTF,
+};
+
const defaultColumnKeys: string[] = ['title', 'type', 'author', 'creationDate', 'text'];
@observer
export class CollectionSchemaView extends CollectionSubView() {
+ private _keysDisposer: any;
private _closestDropIndex: number = 0;
private _previewRef: HTMLDivElement | null = null;
private _makeNewColumn: boolean = false;
+ private _documentOptions: DocumentOptions = new DocumentOptions();
+ private _tableContentRef: HTMLDivElement | null = null;
- public static _rowHeight: number = 40;
+ public static _rowHeight: number = 50;
public static _minColWidth: number = 25;
public static _rowMenuWidth: number = 60;
public static _previewDividerWidth: number = 4;
+ public static _newNodeInputHeight: number = 30;
+ public fieldInfos = new ObservableMap<string, FInfo>();
- @computed get _selectedDocs() {
- return SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.context), this.props.Document));
- }
+ @observable _menuKeys: string[] = [];
@observable _rowEles: ObservableMap = new ObservableMap<Doc, HTMLDivElement>();
@observable _colEles: HTMLDivElement[] = [];
@observable _displayColumnWidths: number[] | undefined;
@observable _columnMenuIndex: number | undefined;
- @observable _menuOptions: string[] = [];
@observable _newFieldWarning: string = '';
@observable _makeNewField: boolean = false;
@observable _newFieldDefault: any = 0;
@observable _newFieldType: ColumnType = ColumnType.Number;
@observable _menuValue: string = '';
@observable _filterColumnIndex: number | undefined;
- @observable _filterValue: string = '';
-
- get documentKeys() {
- const docs = this.childDocs;
- const 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
- // invalidated and re-rendered. This workaround will inquire all of the document fields before the options button is clicked.
- // then by the time the options button is clicked, all of the fields should be in place. If a new field is added while this menu
- // is displayed (unlikely) it won't show up until something else changes.
- //TODO Types
- untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => (keys[key] = false)))));
-
- // this.columns.forEach(key => (keys[key.heading] = true));
- return Array.from(Object.keys(keys));
+ @observable _filterSearchValue: string = '';
+ @observable _selectedCell: [Doc, number] | undefined;
+
+ @computed get _selectedDocs() {
+ return SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.context), this.rootDoc));
+ }
+
+ @computed get documentKeys() {
+ return Array.from(this.fieldInfos.keys());
}
@computed get previewWidth() {
@@ -90,20 +98,15 @@ export class CollectionSchemaView extends CollectionSubView() {
}
@computed get storedColumnWidths() {
- let widths = Cast(
+ const widths = NumListCast(
this.layoutDoc.columnWidths,
- listSpec('number'),
this.columnKeys.map(() => (this.tableWidth - CollectionSchemaView._rowMenuWidth) / this.columnKeys.length)
);
const totalWidth = widths.reduce((sum, width) => sum + width, 0);
if (totalWidth !== this.tableWidth - CollectionSchemaView._rowMenuWidth) {
- widths = widths.map(w => {
- const proportion = w / totalWidth;
- return proportion * (this.tableWidth - CollectionSchemaView._rowMenuWidth);
- });
+ return widths.map(w => (w / totalWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth));
}
-
return widths;
}
@@ -119,19 +122,37 @@ export class CollectionSchemaView extends CollectionSubView() {
return BoolCast(this.layoutDoc.sortDesc);
}
- rowIndex(doc: Doc) {
- return this.childDocs.indexOf(doc);
- }
-
+ @action
componentDidMount() {
this.props.setContentView?.(this);
document.addEventListener('keydown', this.onKeyDown);
+
+ Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => this.fieldInfos.set(pair[0], pair[1]));
+ this._keysDisposer = observe(
+ this.rootDoc[this.fieldKey ?? 'data'] as List<Doc>,
+ change => {
+ switch (change.type as any) {
+ case 'splice':
+ // prettier-ignore
+ (change as any).added.forEach((doc: Doc) => // for each document added
+ Doc.GetAllPrototypes(doc.value as Doc).forEach(proto => // for all of its prototypes (and itself)
+ Object.keys(proto).forEach(action(key => // check if any of its keys are new, and add them
+ !this.fieldInfos.get(key) && this.fieldInfos.set(key, new FInfo(''))))));
+ break;
+ case 'update': //let oldValue = change.oldValue; // fill this in if the entire child list will ever be reassigned with a new list
+ }
+ },
+ true
+ );
}
componentWillUnmount() {
+ this._keysDisposer?.();
document.removeEventListener('keydown', this.onKeyDown);
}
+ rowIndex = (doc: Doc) => this.sortedDocs.docs.indexOf(doc);
+
@action
onKeyDown = (e: KeyboardEvent) => {
if (this._selectedDocs.length > 0) {
@@ -140,30 +161,62 @@ export class CollectionSchemaView extends CollectionSubView() {
{
const lastDoc = this._selectedDocs.lastElement();
const lastIndex = this.rowIndex(lastDoc);
- const curDoc = this.childDocs[lastIndex];
+ const curDoc = this.sortedDocs.docs[lastIndex];
if (lastIndex >= 0 && lastIndex < this.childDocs.length - 1) {
!e.shiftKey && this.clearSelection();
- const newDoc = this.childDocs[lastIndex + 1];
- if (this._selectedDocs.includes(newDoc)) SelectionManager.DeselectView(DocumentManager.Instance.getFirstDocumentView(curDoc));
- else this.addDocToSelection(newDoc, e.shiftKey, lastIndex + 1);
+ const newDoc = this.sortedDocs.docs[lastIndex + 1];
+ if (this._selectedDocs.includes(newDoc)) {
+ SelectionManager.DeselectView(DocumentManager.Instance.getFirstDocumentView(curDoc));
+ } else {
+ this.addDocToSelection(newDoc, e.shiftKey, lastIndex + 1);
+ this._selectedCell && (this._selectedCell[0] = newDoc);
+ this.scrollToDoc(newDoc, {});
+ }
}
e.stopPropagation();
+ e.preventDefault();
}
break;
case 'ArrowUp':
{
const firstDoc = this._selectedDocs.lastElement();
const firstIndex = this.rowIndex(firstDoc);
- const curDoc = this.childDocs[firstIndex];
+ const curDoc = this.sortedDocs.docs[firstIndex];
if (firstIndex > 0 && firstIndex < this.childDocs.length) {
!e.shiftKey && this.clearSelection();
- const newDoc = this.childDocs[firstIndex - 1];
+ const newDoc = this.sortedDocs.docs[firstIndex - 1];
if (this._selectedDocs.includes(newDoc)) SelectionManager.DeselectView(DocumentManager.Instance.getFirstDocumentView(curDoc));
- else this.addDocToSelection(newDoc, e.shiftKey, firstIndex - 1);
+ else {
+ this.addDocToSelection(newDoc, e.shiftKey, firstIndex - 1);
+ this._selectedCell && (this._selectedCell[0] = newDoc);
+ this.scrollToDoc(newDoc, {});
+ }
}
e.stopPropagation();
+ e.preventDefault();
+ }
+ break;
+ case 'ArrowRight':
+ if (this._selectedCell) {
+ this._selectedCell[1] = Math.min(this._selectedCell[1] + 1, this.columnKeys.length - 1);
+ } else if (this._selectedDocs.length > 0) {
+ this.selectCell(this._selectedDocs[0], 0);
}
break;
+ case 'ArrowLeft':
+ if (this._selectedCell) {
+ this._selectedCell[1] = Math.max(this._selectedCell[1] - 1, 0);
+ } else if (this._selectedDocs.length > 0) {
+ this.selectCell(this._selectedDocs[0], 0);
+ }
+ break;
+ case 'Backspace': {
+ this.removeDocument(this._selectedDocs);
+ break;
+ }
+ case 'Escape': {
+ this.deselectCell();
+ }
}
}
};
@@ -177,7 +230,6 @@ export class CollectionSchemaView extends CollectionSubView() {
addRow = (doc: Doc | Doc[]) => {
const result: boolean = this.addDocument(doc);
- this.setSort(this.sortField, this.sortDesc);
return result;
};
@@ -270,18 +322,13 @@ export class CollectionSchemaView extends CollectionSubView() {
@undoBatch
@action
- swapColumns = (index1: number, index2: number) => {
- const tempKey = this.columnKeys[index1];
- const tempWidth = this.storedColumnWidths[index1];
-
- let currKeys = this.columnKeys;
- currKeys[index1] = currKeys[index2];
- currKeys[index2] = tempKey;
+ moveColumn = (fromIndex: number, toIndex: number) => {
+ let currKeys = this.columnKeys.slice();
+ currKeys.splice(toIndex, 0, currKeys.splice(fromIndex, 1)[0]);
this.layoutDoc.columnKeys = new List<string>(currKeys);
- let currWidths = this.storedColumnWidths;
- currWidths[index1] = currWidths[index2];
- currWidths[index2] = tempWidth;
+ let currWidths = this.storedColumnWidths.slice();
+ currWidths.splice(toIndex, 0, currWidths.splice(fromIndex, 1)[0]);
this.layoutDoc.columnWidths = new List<number>(currWidths);
};
@@ -294,10 +341,45 @@ export class CollectionSchemaView extends CollectionSubView() {
});
DragManager.StartColumnDrag(dragEles, dragData, e.x, e.y);
+ document.removeEventListener('pointermove', this.highlightDropColumn);
+ document.addEventListener('pointermove', this.highlightDropColumn);
+ let stopHighlight = (e: PointerEvent) => {
+ document.removeEventListener('pointermove', this.highlightDropColumn);
+ document.removeEventListener('pointerup', stopHighlight);
+ };
+ document.addEventListener('pointerup', stopHighlight);
+
return true;
};
@action
+ highlightDropColumn = (e: PointerEvent) => {
+ e.stopPropagation();
+ const mouseX = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0];
+ let index: number | undefined;
+ this.displayColumnWidths.reduce((total, curr, i) => {
+ if (total <= mouseX && total + curr >= mouseX) {
+ if (mouseX <= total + curr / 2) index = i;
+ else index = i + 1;
+ }
+ return total + curr;
+ }, CollectionSchemaView._rowMenuWidth);
+
+ this._colEles.forEach((colRef, i) => {
+ let leftStyle = '';
+ let rightStyle = '';
+ if (i + 1 === index) rightStyle = `solid 2px ${Colors.MEDIUM_BLUE}`;
+ if (i === index && i === 0) leftStyle = `solid 2px ${Colors.MEDIUM_BLUE}`;
+ colRef.style.borderLeft = leftStyle;
+ colRef.style.borderRight = rightStyle;
+ this.childDocs.forEach(doc => {
+ this._rowEles.get(doc).children[1].children[i].style.borderLeft = leftStyle;
+ this._rowEles.get(doc).children[1].children[i].style.borderRight = rightStyle;
+ });
+ });
+ };
+
+ @action
addRowRef = (doc: Doc, ref: HTMLDivElement) => this._rowEles.set(doc, ref);
@action
@@ -319,17 +401,23 @@ export class CollectionSchemaView extends CollectionSubView() {
clearSelection = () => SelectionManager.DeselectAll();
selectRows = (rootDoc: Doc, lastSelected: Doc) => {
- const index = this.childDocs.indexOf(rootDoc);
- const lastSelectedRow = this.childDocs.indexOf(lastSelected);
+ const index = this.rowIndex(rootDoc);
+ const lastSelectedRow = this.rowIndex(lastSelected);
const startRow = Math.min(lastSelectedRow, index);
const endRow = Math.max(lastSelectedRow, index);
for (let i = startRow; i <= endRow; i++) {
- const currDoc = this.childDocs[i];
+ const currDoc = this.sortedDocs.docs[i];
if (!this._selectedDocs.includes(currDoc)) this.addDocToSelection(currDoc, true, i);
}
};
- sortedSelectedDocs = () => this.childDocs.filter(doc => this._selectedDocs.includes(doc));
+ @action
+ selectCell = (doc: Doc, index: number) => (this._selectedCell = [doc, index]);
+
+ @action
+ deselectCell = () => (this._selectedCell = undefined);
+
+ sortedSelectedDocs = () => this.sortedDocs.docs.filter(doc => this._selectedDocs.includes(doc));
setDropIndex = (index: number) => (this._closestDropIndex = index);
@@ -338,25 +426,34 @@ export class CollectionSchemaView extends CollectionSubView() {
if (de.complete.columnDragData) {
e.stopPropagation();
const mouseX = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y)[0];
- let i = de.complete.columnDragData.colIndex;
- this.displayColumnWidths.reduce((total, curr, index) => {
+ let index = de.complete.columnDragData.colIndex;
+ this.displayColumnWidths.reduce((total, curr, i) => {
if (total <= mouseX && total + curr >= mouseX) {
- i = index;
+ if (mouseX <= total + curr / 2) index = i;
+ else index = i + 1;
}
return total + curr;
}, CollectionSchemaView._rowMenuWidth);
- this.swapColumns(de.complete.columnDragData.colIndex, i);
- e.stopPropagation();
+ this.moveColumn(de.complete.columnDragData.colIndex, index);
+
+ this._colEles.forEach((colRef, i) => {
+ colRef.style.borderLeft = '';
+ colRef.style.borderRight = '';
+ this.childDocs.forEach(doc => {
+ this._rowEles.get(doc).children[1].children[i].style.borderLeft = '';
+ this._rowEles.get(doc).children[1].children[i].style.borderRight = '';
+ });
+ });
+
return true;
}
const draggedDocs = de.complete.docDragData?.draggedDocuments;
- if (draggedDocs && super.onInternalDrop(e, de)) {
+ if (draggedDocs && super.onInternalDrop(e, de) && !this.sortField) {
const pushedDocs = this.childDocs.filter((doc, index) => index >= this._closestDropIndex && !draggedDocs.includes(doc));
const pushedAndDraggedDocs = [...pushedDocs, ...draggedDocs];
const removed = this.childDocs.slice().filter(doc => !pushedAndDraggedDocs.includes(doc));
this.dataDoc[this.fieldKey ?? 'data'] = new List<Doc>([...removed, ...draggedDocs, ...pushedDocs]);
- this.setSort(undefined);
- SelectionManager.DeselectAll();
+ this.clearSelection();
draggedDocs.forEach(doc => {
const draggedView = DocumentManager.Instance.getFirstDocumentView(doc);
if (draggedView) DocumentManager.Instance.RemoveView(draggedView);
@@ -371,7 +468,6 @@ export class CollectionSchemaView extends CollectionSubView() {
@action
onExternalDrop = async (e: React.DragEvent): Promise<void> => {
super.onExternalDrop(e, {}, undoBatch(action(docus => docus.map((doc: Doc) => this.addDocument(doc)))));
- this.setSort(undefined);
};
onDividerDown = (e: React.PointerEvent) => setupMoveUpEvents(this, e, this.onDividerMove, emptyFunction, emptyFunction);
@@ -410,18 +506,21 @@ export class CollectionSchemaView extends CollectionSubView() {
focusDocument = (doc: Doc, options: DocFocusOptions) => {
Doc.BrushDoc(doc);
+ this.scrollToDoc(doc, options);
+ return undefined;
+ };
- const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]);
+ scrollToDoc = (doc: Doc, options: DocFocusOptions) => {
+ const found = this._tableContentRef && Array.from(this._tableContentRef.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]);
if (found) {
- const top = found.getBoundingClientRect().top;
- const localTop = this.props.ScreenToLocalTransform().transformPoint(0, top);
- if (Math.floor(localTop[1]) !== 0) {
- let focusSpeed = options.zoomTime ?? 500;
- smoothScroll(focusSpeed, this._mainCont!, localTop[1] + this._mainCont!.scrollTop, options.easeFunc);
+ const rect = found.getBoundingClientRect();
+ const localRect = this.props.ScreenToLocalTransform().transformBounds(rect.left, rect.top, rect.width, rect.height);
+ if (localRect.y < CollectionSchemaView._rowHeight || localRect.y + localRect.height > this.props.PanelHeight()) {
+ let focusSpeed = options.zoomTime ?? 50;
+ smoothScroll(focusSpeed, this._tableContentRef!, localRect.y + this._tableContentRef!.scrollTop - CollectionSchemaView._rowHeight, options.easeFunc);
return focusSpeed;
}
}
- return undefined;
};
@computed get fieldDefaultInput() {
@@ -443,7 +542,7 @@ export class CollectionSchemaView extends CollectionSubView() {
onSearchKeyDown = (e: React.KeyboardEvent) => {
switch (e.key) {
case 'Enter':
- this._menuOptions.length > 0 && this._menuValue.length > 0 ? this.setKey(this._menuOptions[0]) : action(() => (this._makeNewField = true))();
+ this._menuKeys.length > 0 && this._menuValue.length > 0 ? this.setKey(this._menuKeys[0]) : action(() => (this._makeNewField = true))();
break;
case 'Escape':
this.closeColumnMenu();
@@ -472,7 +571,7 @@ export class CollectionSchemaView extends CollectionSubView() {
this._makeNewColumn = false;
this._columnMenuIndex = index;
this._menuValue = '';
- this._menuOptions = this.documentKeys;
+ this._menuKeys = this.documentKeys;
this._makeNewField = false;
this._newFieldWarning = '';
this._makeNewField = false;
@@ -485,24 +584,17 @@ export class CollectionSchemaView extends CollectionSubView() {
@action
openFilterMenu = (index: number) => {
this._filterColumnIndex = index;
- this._filterValue = this.getFieldFilters(this.columnKeys[this._filterColumnIndex!]).map(filter => filter.split(':')[1])[0];
+ this._filterSearchValue = '';
};
@action
- closeFilterMenu = (setValue: boolean) => {
- if (setValue) {
- if (this._filterValue !== '') {
- Doc.setDocFilter(this.Document, this.columnKeys[this._filterColumnIndex!], this._filterValue, 'check', false, undefined, false);
- } else {
- this.removeFieldFilters(this.columnKeys[this._filterColumnIndex!]);
- }
- }
+ closeFilterMenu = () => {
this._filterColumnIndex = undefined;
};
openContextMenu = (x: number, y: number, index: number) => {
this.closeColumnMenu();
- this.closeFilterMenu(false);
+ this.closeFilterMenu();
ContextMenu.Instance.clearItems();
ContextMenu.Instance.addItem({
description: 'Change field',
@@ -525,7 +617,7 @@ export class CollectionSchemaView extends CollectionSubView() {
@action
updateKeySearch = (e: React.ChangeEvent<HTMLInputElement>) => {
this._menuValue = e.target.value;
- this._menuOptions = this.documentKeys.filter(value => value.toLowerCase().includes(this._menuValue.toLowerCase()));
+ this._menuKeys = this.documentKeys.filter(value => value.toLowerCase().includes(this._menuValue.toLowerCase()));
};
getFieldFilters = (field: string) => StrListCast(this.Document._docFilters).filter(filter => filter.split(':')[0] == field);
@@ -535,15 +627,16 @@ export class CollectionSchemaView extends CollectionSubView() {
};
onFilterKeyDown = (e: React.KeyboardEvent) => {
- //prettier-ignore
switch (e.key) {
- case 'Enter' : this.closeFilterMenu(true); break;
- case 'Escape': this.closeFilterMenu(false);break;
+ case 'Enter':
+ case 'Escape':
+ this.closeFilterMenu();
+ break;
}
};
@action
- updateFilterSearch = (e: React.ChangeEvent<HTMLInputElement>) => (this._filterValue = e.target.value);
+ updateFilterSearch = (e: React.ChangeEvent<HTMLInputElement>) => (this._filterSearchValue = e.target.value);
@computed get newFieldMenu() {
return (
@@ -626,14 +719,23 @@ export class CollectionSchemaView extends CollectionSubView() {
{ passive: false }
)
}>
- {this._menuOptions.map(key => (
+ {this._menuKeys.map(key => (
<div
- className="schema-key-search-result"
+ className="schema-search-result"
onPointerDown={e => {
e.stopPropagation();
this.setKey(key);
}}>
- {key}
+ <p>
+ <span className="schema-search-result-key">
+ {key}
+ {this.fieldInfos.get(key)!.fieldType ? ', ' : ''}
+ </span>
+ <span className="schema-search-result-type" style={{ color: this.fieldInfos.get(key)!.readOnly ? 'red' : 'inherit' }}>
+ {this.fieldInfos.get(key)!.fieldType}
+ </span>
+ </p>
+ <p className="schema-search-result-desc">{this.fieldInfos.get(key)!.description}</p>
</div>
))}
</div>
@@ -662,21 +764,16 @@ export class CollectionSchemaView extends CollectionSubView() {
@computed get renderFilterOptions() {
const keyOptions: string[] = [];
const columnKey = this.columnKeys[this._filterColumnIndex!];
- this.childDocs.forEach(doc => {
- const key = StrCast(doc[columnKey]);
- if (keyOptions.includes(key) === false && (key.includes(this._filterValue) || !this._filterValue) && key !== '') {
- keyOptions.push(key);
+ const allDocs = DocListCast(this.dataDoc[this.props.fieldKey]);
+ allDocs.forEach(doc => {
+ const value = StrCast(doc[columnKey]);
+ if (!keyOptions.includes(value) && value !== '' && (this._filterSearchValue === '' || value.includes(this._filterSearchValue))) {
+ keyOptions.push(value);
}
});
const filters = StrListCast(this.Document._docFilters);
- for (let i = 0; i < (filters?.length ?? 0) - 1; i++) {
- if (filters[i] === columnKey && keyOptions.includes(filters[i].split(':')[1]) === false) {
- keyOptions.push(filters[i + 1]);
- }
- }
-
- const options = keyOptions.map(key => {
+ return keyOptions.map(key => {
let bool = false;
if (filters !== undefined) {
const ind = filters.findIndex(filter => filter.split(':')[1] === key);
@@ -702,21 +799,19 @@ export class CollectionSchemaView extends CollectionSubView() {
</div>
);
});
-
- return options;
}
@computed get renderFilterMenu() {
const x = this.displayColumnWidths.reduce((total, curr, index) => total + (index < this._filterColumnIndex! ? curr : 0), CollectionSchemaView._rowMenuWidth);
return (
<div className="schema-filter-menu" style={{ left: x, minWidth: CollectionSchemaView._minColWidth }}>
- <input className="schema-filter-input" type="text" value={this._filterValue} onKeyDown={this.onFilterKeyDown} onChange={this.updateFilterSearch} onPointerDown={e => e.stopPropagation()} />
+ <input className="schema-filter-input" type="text" value={this._filterSearchValue} onKeyDown={this.onFilterKeyDown} onChange={this.updateFilterSearch} onPointerDown={e => e.stopPropagation()} />
{this.renderFilterOptions}
<div
className="schema-column-menu-button"
onPointerDown={action(e => {
e.stopPropagation();
- this.closeFilterMenu(true);
+ this.closeFilterMenu();
})}>
done
</div>
@@ -725,11 +820,12 @@ export class CollectionSchemaView extends CollectionSubView() {
}
@computed get sortedDocs() {
+ trace();
const field = StrCast(this.layoutDoc.sortField);
const desc = BoolCast(this.layoutDoc.sortDesc);
const docs = !field
? this.childDocs
- : this.childDocs.sort((docA, docB) => {
+ : [...this.childDocs].sort((docA, docB) => {
const aStr = Field.toString(docA[field] as Field);
const bStr = Field.toString(docB[field] as Field);
var out = 0;
@@ -779,9 +875,8 @@ export class CollectionSchemaView extends CollectionSubView() {
</div>
{this._columnMenuIndex !== undefined && this.renderColumnMenu}
{this._filterColumnIndex !== undefined && this.renderFilterMenu}
- <CollectionSchemaViewDocs schema={this} childDocs={this.sortedDocsFunc} />
-
- <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} />
+ <CollectionSchemaViewDocs schema={this} childDocs={this.sortedDocsFunc} setRef={(ref: HTMLDivElement | null) => (this._tableContentRef = ref)} />
+ <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} height={CollectionSchemaView._newNodeInputHeight} />
</div>
{this.previewWidth > 0 && <div className="schema-preview-divider" style={{ width: CollectionSchemaView._previewDividerWidth }} onPointerDown={this.onDividerDown}></div>}
{this.previewWidth > 0 && (
@@ -794,6 +889,7 @@ export class CollectionSchemaView extends CollectionSubView() {
dontCenter={'y'}
onClickScriptDisable="always"
focus={emptyFunction}
+ defaultDoubleClick={returnIgnore}
renderDepth={this.props.renderDepth + 1}
rootSelected={this.rootSelected}
PanelWidth={this.previewWidthFunc}
@@ -809,7 +905,7 @@ export class CollectionSchemaView extends CollectionSubView() {
moveDocument={this.props.moveDocument}
addDocument={this.addRow}
removeDocument={this.props.removeDocument}
- whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
+ whenChildContentsActiveChanged={returnFalse}
addDocTab={this.props.addDocTab}
pinToPres={this.props.pinToPres}
bringToFront={returnFalse}
@@ -824,6 +920,7 @@ export class CollectionSchemaView extends CollectionSubView() {
interface CollectionSchemaViewDocsProps {
schema: CollectionSchemaView;
+ setRef: (ref: HTMLDivElement | null) => void;
childDocs: () => { docs: Doc[] };
}
@@ -834,11 +931,11 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP
childScreenToLocal = computedFn((index: number) => () => this.props.schema.props.ScreenToLocalTransform().translate(0, -CollectionSchemaView._rowHeight - index * this.rowHeightFunc()));
render() {
return (
- <div className="schema-table-content">
+ <div className="schema-table-content" ref={this.props.setRef} style={{ height: `calc(100% - ${CollectionSchemaView._newNodeInputHeight + CollectionSchemaView._rowHeight}px)` }}>
{this.props.childDocs().docs.map((doc: Doc, index: number) => {
const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField ? undefined : this.props.schema.props.DataDoc;
return (
- <div className="schema-row-wrapper" style={{ maxHeight: CollectionSchemaView._rowHeight }}>
+ <div className="schema-row-wrapper" style={{ height: CollectionSchemaView._rowHeight }}>
<DocumentView
key={doc[Id]}
{...this.props.schema.props}
@@ -851,7 +948,7 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP
PanelHeight={this.rowHeightFunc}
styleProvider={DefaultStyleProvider}
waitForDoubleClickToClick={returnNever}
- defaultDoubleClick={returnDefault}
+ defaultDoubleClick={returnIgnore}
enableDragWhenActive={true}
onClickScriptDisable="always"
focus={this.props.schema.focusDocument}
@@ -863,13 +960,14 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP
bringToFront={emptyFunction}
isDocumentActive={this.props.schema.props.childDocumentsActive?.() ? this.props.schema.props.isDocumentActive : this.props.schema.isContentActive}
isContentActive={emptyFunction}
- whenChildContentsActiveChanged={active => this.props.schema.props.whenChildContentsActiveChanged(active)}
+ whenChildContentsActiveChanged={this.props.schema.props.whenChildContentsActiveChanged}
hideDecorations={true}
hideTitle={true}
hideDocumentButtonBar={true}
hideLinkAnchors={true}
fitWidth={returnTrue}
scriptContext={this}
+ canEmbedOnDrag={true}
/>
</div>
);