aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/documents/Documents.ts3
-rw-r--r--src/client/util/DocumentManager.ts11
-rw-r--r--src/client/util/Scripting.ts1
-rw-r--r--src/client/views/EditableView.scss3
-rw-r--r--src/client/views/EditableView.tsx52
-rw-r--r--src/client/views/FieldsDropdown.tsx4
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.scss22
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx136
-rw-r--r--src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx152
-rw-r--r--src/client/views/collections/collectionSchema/SchemaRowBox.tsx6
-rw-r--r--src/client/views/collections/collectionSchema/SchemaTableCell.tsx11
-rw-r--r--src/client/views/global/globalScripts.ts2
-rw-r--r--src/client/views/nodes/DocumentIcon.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx1
-rw-r--r--src/fields/SchemaHeaderField.ts1
15 files changed, 300 insertions, 107 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index a67e6b4f6..c34a833f8 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -43,7 +43,7 @@ export class FInfo {
readOnly: boolean = false;
fieldType?: FInfoFieldType;
values?: FieldType[];
-
+ onLayout?: boolean;
filterable?: boolean = true; // can be used as a Filter in FilterPanel
// format?: string; // format to display values (e.g, decimal places, $, etc)
// parse?: ScriptField; // parse a value from a string
@@ -177,6 +177,7 @@ export class DocumentOptions {
map_pitch?: NUMt = new NumInfo('pitch of a map view', false);
map_bearing?: NUMt = new NumInfo('bearing of a map view', false);
map_style?: STRt = new StrInfo('mapbox style for a map view', false);
+ identifier?: STRt = new StrInfo('documentIcon displayed for each doc as "d[x]"', false);
date_range?: STRt = new StrInfo('date range for calendar', false);
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 8ad6ddf47..487187dfe 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -46,6 +46,7 @@ export class DocumentManager {
DocumentView.addViewRenderedCb = this.AddViewRenderedCb;
DocumentView.getFirstDocumentView = this.getFirstDocumentView;
DocumentView.getDocumentView = this.getDocumentView;
+ DocumentView.getDocViewIndex = this.getDocViewIndex;
DocumentView.getContextPath = DocumentManager.GetContextPath;
DocumentView.getLightboxDocumentView = this.getLightboxDocumentView;
observe(Doc.CurrentlyLoading, change => {
@@ -138,6 +139,16 @@ export class DocumentManager {
);
}
+ public getDocViewIndex(target: Doc): number {
+ const docViewArray = DocumentManager.Instance.DocumentViews;
+ for (let i = 0; i < docViewArray.length; ++i){
+ if (docViewArray[i].Document == target){
+ return i;
+ }
+ }
+ return -1;
+ }
+
public getLightboxDocumentView = (toFind: Doc): DocumentView | undefined => {
const views: DocumentView[] = [];
DocumentManager.Instance.DocumentViews.forEach(view => DocumentView.LightboxContains(view) && Doc.AreProtosEqual(view.Document, toFind) && views.push(view));
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index 6948469cc..6ef592ef2 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -88,7 +88,6 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an
if (!options.editable) {
batch = Doc.MakeReadOnly();
}
-
const result = compiledFunction.apply(thisParam, params).apply(thisParam, argsArray);
batch?.end();
return { success: true, result };
diff --git a/src/client/views/EditableView.scss b/src/client/views/EditableView.scss
index 27b260450..e492068c8 100644
--- a/src/client/views/EditableView.scss
+++ b/src/client/views/EditableView.scss
@@ -5,6 +5,7 @@
hyphens: auto;
overflow: hidden;
height: 100%;
+ width: 100%;
min-width: 20;
text-overflow: ellipsis;
}
@@ -33,6 +34,8 @@
pointer-events: all;
}
+
+
.editableView-input:focus {
border: none;
outline: none;
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 684b948af..5b691c507 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -1,6 +1,6 @@
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
-import { action, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import * as Autosuggest from 'react-autosuggest';
@@ -54,6 +54,9 @@ export interface EditableProps {
background?: string | undefined;
placeholder?: string;
wrap?: string; // nowrap, pre-wrap, etc
+
+ showKeyNotVal?: boolean;
+ updateAlt?: (newAlt: string) => void;
}
/**
@@ -155,7 +158,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
case 'ArrowDown':
case 'ArrowLeft':
case 'ArrowRight':
- e.stopPropagation();
+ //e.stopPropagation();
break;
case 'Shift':
case 'Alt':
@@ -180,6 +183,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
@action
onClick = (e: React.MouseEvent) => {
+ if (this._props.GetValue() == 'None' && this._props.updateAlt) this._props.updateAlt('.');
if (this._props.editing !== false) {
e.nativeEvent.stopPropagation();
if (this._ref.current && this._props.showMenuOnLoad) {
@@ -242,9 +246,9 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
/>
) : this._props.oneLine !== false && this._props.GetValue()?.toString().indexOf('\n') === -1 ? (
<input
- className="editableView-input"
+ className="editableView-input"
ref={r => { this._inputref = r; }} // prettier-ignore
- style={{ display: this._props.display, overflow: 'auto', fontSize: this._props.fontSize, minWidth: 20, background: this._props.background }}
+ style={{ display: this._props.display, overflow: 'auto', fontSize: this._props.fontSize, minWidth: 20, background: this._props.background}}
placeholder={this._props.placeholder}
onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true, false)}
defaultValue={this._props.GetValue()}
@@ -275,9 +279,35 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
);
}
+ display = () => {
+ let toDisplay;
+ const gval = this._props.GetValue()?.replace(/\n/g, '\\r\\n');
+ if (this._props.showKeyNotVal){
+ toDisplay = <input className="editableView-input"
+ value={this._props.GetValue()}
+ readOnly
+ style={{ display: this._props.display, overflow: 'auto', pointerEvents: 'none', fontSize: this._props.fontSize, width: '100%', margin: 0, background: this._props.background}}
+ // eslint-disable-next-line jsx-a11y/no-autofocus
+ />
+ } else {
+ toDisplay = (<span
+ style={{
+ fontStyle: this._props.fontStyle,
+ fontSize: this._props.fontSize,
+ }}>
+ {
+ // eslint-disable-next-line react/jsx-props-no-spreading
+ this._props.fieldContents ? <FieldView {...this._props.fieldContents} /> : this.props.contents ? this._props.contents?.valueOf() : ''
+ }
+ </span>)
+ }
+
+ return toDisplay;
+ }
+
render() {
const gval = this._props.GetValue()?.replace(/\n/g, '\\r\\n');
- if (this._editing && gval !== undefined) {
+ if ((this._editing && gval !== undefined)) {
return this._props.sizeToContent ? (
<div style={{ display: 'grid', minWidth: 100 }}>
<div style={{ display: 'inline-block', position: 'relative', height: 0, width: '100%', overflow: 'hidden' }}>{gval}</div>
@@ -298,21 +328,13 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
minHeight: '10px',
whiteSpace: this._props.oneLine ? 'nowrap' : 'pre-line',
height: this._props.height,
+ width: '100%',
maxHeight: this._props.maxHeight,
fontStyle: this._props.fontStyle,
fontSize: this._props.fontSize,
}}
onClick={this.onClick}>
- <span
- style={{
- fontStyle: this._props.fontStyle,
- fontSize: this._props.fontSize,
- }}>
- {
- // eslint-disable-next-line react/jsx-props-no-spreading
- this._props.fieldContents ? <FieldView {...this._props.fieldContents} /> : this.props.contents ? this._props.contents?.valueOf() : ''
- }
- </span>
+ {this.display()}
</div>
);
}
diff --git a/src/client/views/FieldsDropdown.tsx b/src/client/views/FieldsDropdown.tsx
index 0ea0ebd83..011cd51b3 100644
--- a/src/client/views/FieldsDropdown.tsx
+++ b/src/client/views/FieldsDropdown.tsx
@@ -34,7 +34,7 @@ export class FieldsDropdown extends ObservableReactComponent<fieldsDropdownProps
makeObservable(this);
}
- @computed get allDescendantDocs() {
+ @computed get allDescendantDocs() { //!!!
const allDocs = new Set<Doc>();
SearchUtil.foreachRecursiveDoc([this._props.Document], (depth, doc) => allDocs.add(doc));
return Array.from(allDocs);
@@ -57,7 +57,7 @@ export class FieldsDropdown extends ObservableReactComponent<fieldsDropdownProps
const filteredOptions = ['author', ...(this._newField ? [this._newField] : []), ...(this._props.addedFields ?? []), ...this.fieldsOfDocuments.filter(facet => facet[0] === facet.charAt(0).toUpperCase())];
Object.entries(DocOptions)
- .filter(opts => opts[1].filterable)
+ .filter(opts => opts[1].filterable) //!!!
.forEach((pair: [string, FInfo]) => filteredOptions.push(pair[0]));
const options = filteredOptions.sort().map(facet => ({ value: facet, label: facet }));
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
index 6fb8e40db..1dbe75a8d 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
@@ -50,13 +50,15 @@
.schema-column-menu,
.schema-filter-menu {
background: $light-gray;
- position: relative;
- min-width: 200px;
- max-width: 400px;
+ position: absolute;
+ min-width: 150px;
+ max-width: 300px;
+ max-height: 300px;
display: flex;
+ overflow: hidden;
flex-direction: column;
align-items: flex-start;
- z-index: 1;
+ z-index: 5;
.schema-key-search-input {
width: calc(100% - 20px);
@@ -159,6 +161,13 @@
flex-grow: 2;
margin: 5px;
overflow: hidden;
+ min-width: 100%;
+ }
+
+ .schema-column-edit-wrapper {
+ flex-grow: 2;
+ margin: 5px;
+ overflow: hidden;
min-width: 20%;
}
@@ -176,6 +185,11 @@
}
}
+ .editableView-input {
+ border: none;
+ outline: none;
+ }
+
/*.schema-column-resizer.left {
min-width: 5px;
transform: translate(-3px, 0px);
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 7c2cfd15f..ef1819120 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1,12 +1,12 @@
/* eslint-disable no-restricted-syntax */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Popup, PopupTrigger, Type } from 'browndash-components';
-import { ObservableMap, action, computed, makeObservable, observable, observe, runInAction } from 'mobx';
+import { ObservableMap, action, autorun, computed, makeObservable, observable, observe, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../ClientUtils';
import { emptyFunction } from '../../../../Utils';
-import { Doc, DocListCast, Field, FieldType, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
+import { Doc, DocListCast, Field, FieldType, IdToDoc, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
import { DocData } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
import { List } from '../../../../fields/List';
@@ -31,6 +31,8 @@ import { CollectionSubView } from '../CollectionSubView';
import './CollectionSchemaView.scss';
import { SchemaColumnHeader } from './SchemaColumnHeader';
import { SchemaRowBox } from './SchemaRowBox';
+import { ActionButton } from '@adobe/react-spectrum';
+import { CollectionMasonryViewFieldRow } from '../CollectionMasonryViewFieldRow';
const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore
@@ -83,10 +85,12 @@ export class CollectionSchemaView extends CollectionSubView() {
@observable _selectedCol: number = 0;
@observable _selectedCells: Array<Doc> = [];
@observable _mouseCoordinates = { x: 0, y: 0 };
- @observable _lowestSelectedIndex = -1; // lowest index among selected rows; used to properly sync dragged docs with cursor position
- @observable _relCursorIndex = -1; // cursor index relative to the current selected cells
- @observable _draggedColIndex = 0;
- @observable _colBeingDragged = false;
+ @observable _lowestSelectedIndex: number = -1; //lowest index among selected rows; used to properly sync dragged docs with cursor position
+ @observable _relCursorIndex: number = -1; //cursor index relative to the current selected cells
+ @observable _draggedColIndex: number = 0;
+ @observable _colBeingDragged: boolean = false;
+ @observable _colKeysFiltered: boolean = false;
+ @observable _cellTags: ObservableMap = new ObservableMap<Doc, Array<string>>();
// target HTMLelement portal for showing a popup menu to edit cell values.
public get MenuTarget() {
@@ -270,9 +274,7 @@ export class CollectionSchemaView extends CollectionSubView() {
@undoBatch
changeColumnKey = (index: number, newKey: string, defaultVal?: any) => {
- if (!this.documentKeys.includes(newKey)) {
- this.addNewKey(newKey, defaultVal);
- }
+ if (!this.documentKeys.includes(newKey)) this.addNewKey(newKey, defaultVal);
const currKeys = this.columnKeys.slice(); // copy the column key array first, then change it.
currKeys[index] = newKey;
@@ -280,11 +282,9 @@ export class CollectionSchemaView extends CollectionSubView() {
};
@undoBatch
- addColumn = (key: string, defaultVal?: any) => {
- if (!this.documentKeys.includes(key)) {
- this.addNewKey(key, defaultVal);
- }
-
+ addColumn = (key?: string, defaultVal?: any) => {
+ if (key && !this.documentKeys.includes(key)) this.addNewKey(key, defaultVal);
+
const newColWidth = this.tableWidth / (this.storedColumnWidths.length + 1);
const currWidths = this.storedColumnWidths.slice();
currWidths.splice(0, 0, newColWidth);
@@ -292,15 +292,33 @@ export class CollectionSchemaView extends CollectionSubView() {
this.layoutDoc.schema_columnWidths = new List<number>(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth)));
const currKeys = this.columnKeys.slice();
+ if (!key) key = 'EmptyColumnKey' + Math.floor(Math.random() * 1000000000000000).toString();
currKeys.splice(0, 0, key);
+ this.changeColumnKey(0, 'EmptyColumnKey' + Math.floor(Math.random() * 1000000000000000).toString());
this.layoutDoc.schema_columnKeys = new List<string>(currKeys);
};
@action
- addNewKey = (key: string, defaultVal: any) =>
+ addNewKey = (key: string, defaultVal: any) => {
this.childDocs.forEach(doc => {
doc[DocData][key] = defaultVal;
});
+ }
+
+ // parses a field from the "idToDoc(####)" format to DocumentId (d#) format for readability
+ cleanupComputedField = (field: string) => {
+ const idPattern = /idToDoc\((.*?)\)/g;
+ let modField = field.slice();
+ let matches;
+ let results = new Map<string, string>();
+ while ((matches = idPattern.exec(field)) !== null) {
+ results.set(matches[0], matches[1].replace(/"/g, ''));
+ }
+ results.forEach((id, funcId) => {
+ modField = modField.replace(funcId, 'd' + (DocumentView.getDocViewIndex(IdToDoc(id))).toString());
+ })
+ return modField;
+ }
@undoBatch
removeColumn = (index: number) => {
@@ -312,7 +330,8 @@ export class CollectionSchemaView extends CollectionSubView() {
const currKeys = this.columnKeys.slice();
currKeys.splice(index, 1);
- this.layoutDoc.schema_columnKeys = new List<string>(currKeys);
+ this.layoutDoc.schema_columnKeys = new List<string>(currKeys);
+ console.log(...currKeys);
};
@action
@@ -383,6 +402,7 @@ export class CollectionSchemaView extends CollectionSubView() {
};
findColDropIndex = (mouseX: number) => {
+ let xOffset: number = this._props.ScreenToLocalTransform().inverse().transformPoint(0,0)[0] + CollectionSchemaView._rowMenuWidth;
let index: number | undefined;
this.displayColumnWidths.reduce((total, curr, i) => {
if (total <= mouseX && total + curr >= mouseX) {
@@ -390,7 +410,7 @@ export class CollectionSchemaView extends CollectionSubView() {
else index = i + 1;
}
return total + curr;
- }, 2 * CollectionSchemaView._rowMenuWidth); // probably prone to issues; find better implementation (!!!)
+ }, xOffset);
return index;
};
@@ -445,7 +465,7 @@ export class CollectionSchemaView extends CollectionSubView() {
const edgeStyle = i === index ? `solid 2px ${Colors.MEDIUM_BLUE}` : '';
const cellEles = [
colRef,
- ...this.childDocs //
+ ...this.childDocs
.filter(doc => i !== this._selectedCol || !this._selectedDocs.includes(doc))
.map(doc => this._rowEles.get(doc).children[1].children[i]),
];
@@ -513,8 +533,6 @@ export class CollectionSchemaView extends CollectionSubView() {
this._selectedCol = col;
if (this._lowestSelectedIndex === -1 || index < this._lowestSelectedIndex) this._lowestSelectedIndex = index;
-
- // let selectedIndexes: Array<Number> = this._selectedCells.map(doc => this.rowIndex(doc));
};
@action
@@ -562,7 +580,6 @@ export class CollectionSchemaView extends CollectionSubView() {
const draggedDocs = de.complete.docDragData?.draggedDocuments;
if (draggedDocs && super.onInternalDrop(e, de) && !this.sortField) {
const map = draggedDocs?.map(doc => this.rowIndex(doc));
- console.log(map);
this.dataDoc[this.fieldKey ?? 'data'] = new List<Doc>([...this.sortedDocs.docs]);
this.clearSelection();
draggedDocs.forEach(doc => {
@@ -682,40 +699,44 @@ export class CollectionSchemaView extends CollectionSubView() {
};
@action
- setKey = (key: string, defaultVal?: any) => {
+ setKey = (key: string, defaultVal?: any, index?: number) => {
+ if (this.columnKeys.includes(key)) return;
+
if (this._makeNewColumn) {
this.addColumn(key, defaultVal);
- } else {
- this.changeColumnKey(this._columnMenuIndex!, key, defaultVal);
- }
+ this._makeNewColumn = false;
+ } else this.changeColumnKey(this._columnMenuIndex! | index!, key, defaultVal);
+
this.closeColumnMenu();
};
- setColumnValues = (key: string, value: string) => {
+ setCellValues = (key: string, value: string) => {
const selectedDocs: Doc[] = [];
this.childDocs.forEach(doc => {
- const docIsSelected = this._selectedCells && !(this._selectedCells?.filter(d => d === doc).length === 0);
- if (docIsSelected) {
- selectedDocs.push(doc);
- }
+ const isSelected = this._selectedCells && !(this._selectedCells?.filter(d => d === doc).length === 0);
+ isSelected && selectedDocs.push(doc);
});
- if (selectedDocs.length === 1) {
- this.childDocs.forEach(doc => Doc.SetField(doc, key, value));
- } else {
- selectedDocs.forEach(doc => Doc.SetField(doc, key, value));
- }
+ if (selectedDocs.length === 1) this.childDocs.forEach(doc => Doc.SetField(doc, key, value)); // if only one cell selected, fill all
+ else selectedDocs.forEach(doc => Doc.SetField(doc, key, value)); // else only fill selected cells
return true;
};
- setSelectedColumnValues = (key: string, value: string) => {
- this.childDocs.forEach(doc => {
- const docIsSelected = this._selectedCells && !(this._selectedCells?.filter(d => d === doc).length === 0);
- if (docIsSelected) {
- Doc.SetField(doc, key, value);
- }
- });
- return true;
- };
+ @action
+ toggleMenuKeyFilter = () => {
+ if (!this._colKeysFiltered){
+ this._colKeysFiltered = true;
+ this._menuKeys = this.documentKeys.filter(key => this.childDocsInclude(key));
+ } else {
+ this._colKeysFiltered = false;
+ this._menuKeys = this.documentKeys;
+ }
+ }
+
+ childDocsInclude = (key: string) => {
+ let keyExists: boolean = false;
+ this.childDocs.forEach(doc => {if (Object.keys(doc).includes(key)) keyExists = true;})
+ return keyExists
+ }
@action
openColumnMenu = (index: number, newCol: boolean) => {
@@ -748,9 +769,10 @@ export class CollectionSchemaView extends CollectionSubView() {
openContextMenu = (x: number, y: number, index: number) => {
this.closeColumnMenu();
this.closeFilterMenu();
+
ContextMenu.Instance.clearItems();
ContextMenu.Instance.addItem({
- description: 'Change field',
+ description: `Change field`,
event: () => this.openColumnMenu(index, false),
icon: 'pencil-alt',
});
@@ -862,14 +884,11 @@ export class CollectionSchemaView extends CollectionSubView() {
@computed get keysDropdown() {
return (
<div className="schema-key-search">
- <div
- className="schema-column-menu-button"
- onPointerDown={action((e: any) => {
- e.stopPropagation();
- this._makeNewField = true;
- })}>
- + new field
- </div>
+ <button
+ className="schema-column-menu-button"
+ onClick={() => this.toggleMenuKeyFilter()}>
+ {this._colKeysFiltered ? "All keys" : "Active keys only"}
+ </button>
<div
className="schema-key-list"
ref={r => {
@@ -910,6 +929,7 @@ export class CollectionSchemaView extends CollectionSubView() {
</div>
);
}
+
get renderKeysMenu() {
return (
<div className="schema-column-menu" style={{ left: 0, minWidth: CollectionSchemaView._minColWidth }}>
@@ -1015,7 +1035,9 @@ export class CollectionSchemaView extends CollectionSubView() {
_oldWheel: any;
render() {
return (
- <div className="collectionSchemaView" ref={(ele: HTMLDivElement | null) => this.createDashEventsTarget(ele)} onDrop={this.onExternalDrop.bind(this)} onPointerMove={e => this.onPointerMove(e)}>
+ <div className="collectionSchemaView" ref={(ele: HTMLDivElement | null) => this.createDashEventsTarget(ele)}
+ onDrop={this.onExternalDrop.bind(this)}
+ onPointerMove={e => this.onPointerMove(e)} >
<div ref={this._menuTarget} style={{ background: 'red', top: 0, left: 0, position: 'absolute', zIndex: 10000 }} />
<div
className="schema-table"
@@ -1032,7 +1054,7 @@ export class CollectionSchemaView extends CollectionSubView() {
placement="right"
background={SettingsManager.userBackgroundColor}
color={SettingsManager.userColor}
- toggle={<FontAwesomeIcon onPointerDown={() => this.openColumnMenu(-1, true)} icon="plus" />}
+ toggle={<FontAwesomeIcon onPointerDown={() => this.addColumn()} icon="plus" />} //here
trigger={PopupTrigger.CLICK}
type={Type.TERT}
isOpen={this._columnMenuIndex !== -1 ? false : undefined}
@@ -1042,6 +1064,10 @@ export class CollectionSchemaView extends CollectionSubView() {
{this.columnKeys.map((key, index) => (
<SchemaColumnHeader
// eslint-disable-next-line react/no-array-index-key
+ //cleanupField={this.cleanupComputedField}
+ schemaView={this}
+ columnWidth={() => CollectionSchemaView._minColWidth} //TODO: update
+ Document={this.Document}
key={index}
columnIndex={index}
columnKeys={this.columnKeys}
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 6b5a34ec0..6e2f85cc0 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -1,19 +1,38 @@
/* eslint-disable react/no-unused-prop-types */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action } from 'mobx';
+import { action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { setupMoveUpEvents } from '../../../../ClientUtils';
+import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero, setupMoveUpEvents } from '../../../../ClientUtils';
import { emptyFunction } from '../../../../Utils';
import { Colors } from '../../global/globalEnums';
import './CollectionSchemaView.scss';
+import { EditableView } from '../../EditableView';
+import { ObservableReactComponent } from '../../ObservableReactComponent';
+import { DefaultStyleProvider, returnEmptyDocViewList } from '../../StyleProvider';
+import { FieldViewProps } from '../../nodes/FieldView';
+import { Doc, Field } from '../../../../fields/Doc';
+import { dropActionType } from '../../../util/DropActionTypes';
+import { Transform } from '../../../util/Transform';
+import { SchemaTableCell } from './SchemaTableCell';
+import { DocCast } from '../../../../fields/Types';
+import { computedFn } from 'mobx-utils';
+import { CollectionSchemaView } from './CollectionSchemaView';
+import { SnappingManager } from '../../../util/SnappingManager';
+import { undoable } from '../../../util/UndoManager';
+import { FInfo } from '../../../documents/Documents';
+import { ColumnType } from '../../../../fields/SchemaHeaderField';
export interface SchemaColumnHeaderProps {
+ Document: Doc;
+ autoFocus?: boolean;
columnKeys: string[];
columnWidths: number[];
columnIndex: number;
sortField: string;
sortDesc: boolean;
+ schemaView: CollectionSchemaView;
+ //cleanupField: (s: string) => string;
isContentActive: (outsideReaction?: boolean | undefined) => boolean | undefined;
setSort: (field: string | undefined, desc?: boolean) => void;
removeColumn: (index: number) => void;
@@ -22,54 +41,147 @@ export interface SchemaColumnHeaderProps {
dragColumn: (e: any, index: number) => boolean;
openContextMenu: (x: number, y: number, index: number) => void;
setColRef: (index: number, ref: HTMLDivElement) => void;
+ rootSelected?: () => boolean;
+ columnWidth: () => number;
+ finishEdit?: () => void; // notify container that edit is over (eg. to hide view in DashFieldView)
+ //transform: () => Transform;
}
@observer
-export class SchemaColumnHeader extends React.Component<SchemaColumnHeaderProps> {
- get fieldKey() {
- return this.props.columnKeys[this.props.columnIndex];
+export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHeaderProps> {
+
+ @observable _altTitle: string | undefined = undefined;
+
+ @computed get fieldKey() {
+ return this._props.columnKeys[this._props.columnIndex];
+ }
+
+ isDefaultTitle = (key: string) => {
+ const defaultPattern = /EmptyColumnKey/;
+ let isDefault: boolean = (defaultPattern.exec(key) != null);
+ return isDefault;
}
+ getFinfo = computedFn((fieldKey: string) => this._props.schemaView?.fieldInfos.get(fieldKey));
+ setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);}
+ @action updateAlt = (newAlt: string) => {this._altTitle = newAlt;}
+
@action
sortClicked = (e: React.PointerEvent) => {
e.stopPropagation();
e.preventDefault();
- if (this.props.sortField === this.fieldKey && this.props.sortDesc) {
- this.props.setSort(undefined);
- } else if (this.props.sortField === this.fieldKey) {
- this.props.setSort(this.fieldKey, true);
+ if (this._props.sortField === this.fieldKey && this._props.sortDesc) {
+ this._props.setSort(undefined);
+ } else if (this._props.sortField === this.fieldKey) {
+ this._props.setSort(this.fieldKey, true);
} else {
- this.props.setSort(this.fieldKey, false);
+ this._props.setSort(this.fieldKey, false);
}
};
@action
- onPointerDown = (e: React.PointerEvent) => {
- this.props.isContentActive(true) && setupMoveUpEvents(this, e, moveEv => this.props.dragColumn(moveEv, this.props.columnIndex), emptyFunction, emptyFunction);
+ setupDrag = (e: React.PointerEvent) => {
+ this._props.isContentActive(true) && setupMoveUpEvents(this, e, moveEv => this._props.dragColumn(moveEv, this._props.columnIndex), emptyFunction, emptyFunction);
};
+ renderProps = (props: SchemaColumnHeaderProps) => {
+ const { columnKeys, columnWidth, Document } = props;
+ const fieldKey = columnKeys[props.columnIndex];
+ const color = 'black'; // color of text in cells
+ const fieldProps: FieldViewProps = {
+ childFilters: returnEmptyFilter,
+ childFiltersByRanges: returnEmptyFilter,
+ docViewPath: returnEmptyDocViewList,
+ searchFilterDocs: returnEmptyDoclist,
+ styleProvider: DefaultStyleProvider,
+ isSelected: returnFalse,
+ setHeight: returnFalse,
+ select: emptyFunction,
+ dragAction: dropActionType.move,
+ renderDepth: 1,
+ noSidebar: true,
+ isContentActive: returnFalse,
+ whenChildContentsActiveChanged: emptyFunction,
+ ScreenToLocalTransform: Transform.Identity,
+ focus: emptyFunction,
+ addDocTab: SchemaTableCell.addFieldDoc,
+ pinToPres: returnZero,
+ Document: DocCast(Document.rootDocument, Document),
+ fieldKey: fieldKey,
+ PanelWidth: columnWidth,
+ PanelHeight: props.rowHeight,
+ rootSelected: props.rootSelected,
+ };
+ const readOnly = this.getFinfo(fieldKey)?.readOnly ?? false;
+ const cursor = !readOnly ? 'text' : 'default';
+ const pointerEvents: 'all' | 'none' = 'all';
+ return { color, fieldProps, cursor, pointerEvents };
+ }
+
+ @computed get editableView() {
+ const { color, fieldProps, pointerEvents } = this.renderProps(this._props);
+
+ return <div className='schema-column-edit-wrapper'
+ style={{
+ color,
+ width: '100%',
+ pointerEvents,
+ }}>
+ <EditableView
+ ref={r => this._props.autoFocus && r?.setIsFocused(true)}
+ oneLine={true}
+ allowCRs={false}
+ contents={undefined}
+ fieldContents={fieldProps}
+ editing={undefined}
+ updateAlt={this.updateAlt} // alternate title to display
+ showKeyNotVal={true} // tells the EditableView to display the fieldKey itself, and not its value
+ GetValue={() => {
+ if (this.isDefaultTitle(this.fieldKey)) return '';
+ else if (this._altTitle) return this._altTitle;
+ else return this.fieldKey;
+ }}
+ SetValue={undoable((value: string, shiftKey?: boolean, enterKey?: boolean) => {
+ if (shiftKey && enterKey) { // if shift & enter, set value of each cell in column
+ this.setColumnValues(value, '');
+ this._altTitle = undefined;
+ this._props.finishEdit?.();
+ return true;
+ } else if (enterKey) this.updateAlt(value);
+ this._props.finishEdit?.();
+ return true;
+ }, 'edit column header')}
+ />
+ </div>
+ }
+
+ // staticView = () => {
+ // return <div className="schema-column-title" onPointerDown={e => {this._editing = true; console.log(this._editing)}}>{this.fieldKey}</div>
+ // }
+
render() {
return (
<div
className="schema-column-header"
style={{
- width: this.props.columnWidths[this.props.columnIndex],
+ width: this._props.columnWidths[this._props.columnIndex],
}}
- onPointerDown={this.onPointerDown}
+ onPointerDown={this.setupDrag}
ref={col => {
if (col) {
- this.props.setColRef(this.props.columnIndex, col);
+ this._props.setColRef(this._props.columnIndex, col);
}
}}>
- <div className="schema-column-resizer left" onPointerDown={e => this.props.resizeColumn(e, this.props.columnIndex)} />
- <div className="schema-column-title">{this.fieldKey}</div>
+ <div className="schema-column-resizer left" onPointerDown={e => this._props.resizeColumn(e, this._props.columnIndex)} />
+
+ <div>{this.editableView}</div>
<div className="schema-header-menu">
- <div className="schema-header-button" onPointerDown={e => this.props.openContextMenu(e.clientX, e.clientY, this.props.columnIndex)}>
+ <div className="schema-header-button" onPointerDown={e => this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)}>
<FontAwesomeIcon icon="ellipsis-h" />
</div>
- <div className="schema-sort-button" onPointerDown={this.sortClicked} style={this.props.sortField === this.fieldKey ? { backgroundColor: Colors.MEDIUM_BLUE } : {}}>
- <FontAwesomeIcon icon="caret-right" style={this.props.sortField === this.fieldKey ? { transform: `rotate(${this.props.sortDesc ? '270deg' : '90deg'})` } : {}} />
+ <div className="schema-sort-button" onPointerDown={this.sortClicked} style={this._props.sortField === this.fieldKey ? { backgroundColor: Colors.MEDIUM_BLUE } : {}}>
+ <FontAwesomeIcon icon="caret-right" style={this._props.sortField === this.fieldKey ? { transform: `rotate(${this._props.sortDesc ? '270deg' : '90deg'})` } : {}} />
</div>
</div>
</div>
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 760089ffb..da272cd18 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -52,14 +52,14 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
this._props.setContentViewBox?.(this);
}
+ cleanupField = (field: string) => this.schemaView.cleanupComputedField(field)
setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY);
selectedCol = () => this.schemaView._selectedCol;
getFinfo = computedFn((fieldKey: string) => this.schemaView?.fieldInfos.get(fieldKey));
selectCell = (doc: Doc, col: number, shift: boolean, ctrl: boolean) => this.schemaView?.selectCell(doc, col, shift, ctrl);
deselectCell = () => this.schemaView?.deselectAllCells();
selectedCells = () => this.schemaView?._selectedDocs;
- setColumnValues = (field: any, value: any) => this.schemaView?.setColumnValues(field, value) ?? false;
- setSelectedColumnValues = (field: any, value: any) => this.schemaView?.setSelectedColumnValues(field, value) ?? false;
+ setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false;
columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
render() {
return (
@@ -146,9 +146,9 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
selectedCells={this.selectedCells}
selectedCol={this.selectedCol}
setColumnValues={this.setColumnValues}
- setSelectedColumnValues={this.setSelectedColumnValues}
oneLine={BoolCast(this.schemaDoc?._singleLine)}
menuTarget={this.schemaView.MenuTarget}
+ cleanupField={this.cleanupField}
transform={() => {
const ind = index === this.schemaView.columnKeys.length - 1 ? this.schemaView.columnKeys.length - 3 : index;
const x = this.schemaView?.displayColumnWidths.reduce((p, c, i) => (i <= ind ? p + c : p), 0);
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 5874364e0..e6660f379 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -48,7 +48,6 @@ export interface SchemaTableCellProps {
isRowActive: () => boolean | undefined;
getFinfo: (fieldKey: string) => FInfo | undefined;
setColumnValues: (field: string, value: string) => boolean;
- setSelectedColumnValues: (field: string, value: string) => boolean;
oneLine?: boolean; // whether all input should fit on one line vs allowing textare multiline inputs
allowCRs?: boolean; // allow carriage returns in text input (othewrise CR ends the edit)
finishEdit?: () => void; // notify container that edit is over (eg. to hide view in DashFieldView)
@@ -57,6 +56,7 @@ export interface SchemaTableCellProps {
transform: () => Transform;
autoFocus?: boolean; // whether to set focus on creation, othwerise wait for a click
rootSelected?: () => boolean;
+ cleanupField: (field: string) => string;
}
function selectedCell(props: SchemaTableCellProps) {
@@ -141,14 +141,15 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
contents={undefined}
fieldContents={fieldProps}
editing={selectedCell(this._props) ? undefined : false}
- GetValue={() => Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey)}
+ GetValue={() => this._props.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey))} //TODO: feed this into parser that handles idToDoc
SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => {
if (shiftDown && enterKey) {
this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value);
this._props.finishEdit?.();
return true;
}
- const ret = Doc.SetField(fieldProps.Document, this._props.fieldKey.replace(/^_/, ''), value, Doc.IsDataProto(fieldProps.Document) ? true : undefined);
+ const hasNoLayout = Doc.IsDataProto(fieldProps.Document) ? true : undefined; // the "delegate" is a a data document so never write to it's proto
+ const ret = Doc.SetField(fieldProps.Document, this._props.fieldKey.replace(/^_/, ''), value, true);
this._props.finishEdit?.();
return ret;
}, 'edit schema cell')}
@@ -192,7 +193,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
onPointerDown={action(e => {
const shift: boolean = e.shiftKey;
const ctrl: boolean = e.ctrlKey;
- if (this._props.isRowActive?.() !== false) {
+ if (this._props.isRowActive?.()) {
if (selectedCell(this._props) && ctrl) {
this._props.selectCell(this._props.Document, this._props.col, shift, ctrl);
e.stopPropagation();
@@ -441,4 +442,4 @@ export class SchemaEnumerationCell extends ObservableReactComponent<SchemaTableC
</div>
);
}
-}
+} \ No newline at end of file
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
index 7730ed385..95f83bc5c 100644
--- a/src/client/views/global/globalScripts.ts
+++ b/src/client/views/global/globalScripts.ts
@@ -84,6 +84,8 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b
} else {
const dataKey = Doc.LayoutFieldKey(dv.Document);
const alternate = (dv.layoutDoc[dataKey + '_usePath'] ? '_' + dv.layoutDoc[dataKey + '_usePath'] : '').replace(':hover', '');
+ console.log('color: ' + dv.dataDoc[fieldKey + alternate] + ' to set to: ' + color)
+ dv.layoutDoc[fieldKey + alternate] = undefined;
dv.dataDoc[fieldKey + alternate] = color;
}
});
diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx
index ffd350e92..79fc06279 100644
--- a/src/client/views/nodes/DocumentIcon.tsx
+++ b/src/client/views/nodes/DocumentIcon.tsx
@@ -47,7 +47,7 @@ export class DocumentIcon extends ObservableReactComponent<DocumentIconProps> {
}
}
-@observer
+@observer
export class DocumentIconContainer extends React.Component {
public static getTransformer(): Transformer {
const usedDocuments = new Set<number>();
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 7a1f94948..aff5a3dca 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1076,6 +1076,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
public static getViews = (doc?: Doc) => Array.from(doc?.[DocViews] ?? []) as DocumentView[];
public static getFirstDocumentView: (toFind: Doc) => DocumentView | undefined;
public static getDocumentView: (target: Doc | undefined, preferredCollection?: DocumentView) => Opt<DocumentView>;
+ public static getDocViewIndex: (target: Doc) => number;
public static getContextPath: (doc: Opt<Doc>, includeExistingViews?: boolean) => Doc[];
public static getLightboxDocumentView: (toFind: Doc) => Opt<DocumentView>;
public static showDocumentView: (targetDocView: DocumentView, options: FocusViewOptions) => Promise<void>;
diff --git a/src/fields/SchemaHeaderField.ts b/src/fields/SchemaHeaderField.ts
index 0a8dd1d9e..6fa94204a 100644
--- a/src/fields/SchemaHeaderField.ts
+++ b/src/fields/SchemaHeaderField.ts
@@ -12,6 +12,7 @@ export enum ColumnType {
Image,
RTF,
Enumeration,
+ Equation,
Any,
}