aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts51
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.scss17
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx108
-rw-r--r--src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx8
-rw-r--r--src/client/views/collections/collectionSchema/SchemaRowBox.tsx1
-rw-r--r--src/client/views/collections/collectionSchema/SchemaTableCell.tsx8
6 files changed, 115 insertions, 78 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 8d97ce5af..52f8d5717 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -70,12 +70,14 @@ class EmptyBox {
}
export abstract class FInfo {
description: string = '';
+ readOnly: boolean = false;
fieldType?: string;
values?: Field[];
// format?: string; // format to display values (e.g, decimal places, $, etc)
// parse?: ScriptField; // parse a value from a string
- constructor(d: string) {
+ constructor(d: string, readOnly?: boolean) {
this.description = d;
+ this.readOnly = readOnly ?? false;
}
}
class BoolInfo extends FInfo {
@@ -85,16 +87,16 @@ class BoolInfo extends FInfo {
class NumInfo extends FInfo {
fieldType? = 'number';
values?: number[] = [];
- constructor(d: string, values?: number[]) {
- super(d);
+ constructor(d: string, readOnly?: boolean, values?: number[]) {
+ super(d, readOnly);
this.values = values;
}
}
class StrInfo extends FInfo {
fieldType? = 'string';
values?: string[] = [];
- constructor(d: string, values?: string[]) {
- super(d);
+ constructor(d: string, readOnly?: boolean, values?: string[]) {
+ super(d, readOnly);
this.values = values;
}
}
@@ -102,21 +104,24 @@ class DocInfo extends FInfo {
fieldType? = 'Doc';
values?: Doc[] = [];
constructor(d: string, values?: Doc[]) {
- super(d);
+ super(d, true);
this.values = values;
}
}
class DimInfo extends FInfo {
fieldType? = 'DimUnit';
values? = [DimUnit.Pixel, DimUnit.Ratio];
+ readOnly = true;
}
class PEInfo extends FInfo {
fieldType? = 'pointerEvents';
values? = ['all', 'none'];
+ readOnly = true;
}
class DAInfo extends FInfo {
fieldType? = 'dropActionType';
values? = ['alias', 'copy', 'move', 'same', 'proto', 'none'];
+ readOnly = true;
}
type BOOLt = BoolInfo | boolean;
type NUMt = NumInfo | number;
@@ -128,12 +133,12 @@ type DROPt = DAInfo | dropActionType;
export class DocumentOptions {
x?: NUMt = new NumInfo('x coordinate of document in a freeform view');
y?: NUMt = new NumInfo('y coordinage of document in a freeform view');
- z?: NUMt = new NumInfo('whether document is in overlay (1) or not (0)', [1, 0]);
- system?: BOOLt = new BoolInfo('is this a system created/owned doc');
- type?: STRt = new StrInfo('type of document', Array.from(Object.keys(DocumentType)));
+ z?: NUMt = new NumInfo('whether document is in overlay (1) or not (0)', false, [1, 0]);
+ system?: BOOLt = new BoolInfo('is this a system created/owned doc', true);
+ type?: STRt = new StrInfo('type of document', true, Array.from(Object.keys(DocumentType)));
title?: string;
_dropAction?: DROPt = new DAInfo("what should happen to this document when it's dropped somewhere else");
- allowOverlayDrop?: BOOLt = new BoolInfo('can documents be dropped onto this document without using dragging title bar or holding down embed key (ctrl)?');
+ allowOverlayDrop?: BOOLt = new BoolInfo('can documents be dropped onto this document without using dragging title bar or holding down embed key (ctrl)?', true);
childDropAction?: DROPt = new DAInfo("what should happen to the source document when it's dropped onto a child of a collection ");
targetDropAction?: DROPt = new DAInfo('what should happen to the source document when ??? ');
userColor?: STRt = new StrInfo('color associated with a Dash user (seen in header fields of shared documents)');
@@ -147,14 +152,14 @@ export class DocumentOptions {
_panY?: NUMt = new NumInfo('vertical pan location of a freeform view');
_width?: NUMt = new NumInfo('displayed width of a document');
_height?: NUMt = new NumInfo('displayed height of document');
- _nativeWidth?: NUMt = new NumInfo('native width of document contents (e.g., the pixel width of an image)');
- _nativeHeight?: NUMt = new NumInfo('native height of document contents (e.g., the pixel height of an image)');
- _nativeDimModifiable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers');
- _nativeHeightUnfrozen?: BOOLt = new BoolInfo('native height can be changed independent of width by dragging decoration resizers');
- _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height");
- _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units");
- _fitWidth?: BOOLt = new BoolInfo('whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)');
- _fitContentsToBox?: BOOLt = new BoolInfo('whether a freeformview should zoom/scale to create a shrinkwrapped view of its content');
+ _nativeWidth?: NUMt = new NumInfo('native width of document contents (e.g., the pixel width of an image)', true);
+ _nativeHeight?: NUMt = new NumInfo('native height of document contents (e.g., the pixel height of an image)', true);
+ _nativeDimModifiable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers', true);
+ _nativeHeightUnfrozen?: BOOLt = new BoolInfo('native height can be changed independent of width by dragging decoration resizers', true);
+ _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height", true);
+ _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units", true);
+ _fitWidth?: BOOLt = new BoolInfo('whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)', true);
+ _fitContentsToBox?: BOOLt = new BoolInfo('whether a freeformview should zoom/scale to create a shrinkwrapped view of its content', true);
_contentBounds?: List<number>; // the (forced) bounds of the document to display. format is: [left, top, right, bottom]
_lockedPosition?: boolean; // lock the x,y coordinates of the document so that it can't be dragged
_lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed
@@ -197,11 +202,11 @@ export class DocumentOptions {
_timecodeToShow?: number; // the time that a document should be displayed (e.g., when an annotation shows up as a video plays)
_timecodeToHide?: number; // the time that a document should be hidden
_timelineLabel?: boolean; // whether the document exists on a timeline
- '_carousel-caption-xMargin'?: NUMt = new NumInfo('x margin of caption inside of a carouself collection');
- '_carousel-caption-yMargin'?: NUMt = new NumInfo('y margin of caption inside of a carouself collection');
- 'icon-nativeWidth'?: NUMt = new NumInfo('native width of icon view');
- 'icon-nativeHeight'?: NUMt = new NumInfo('native height of icon view');
- 'dragFactory-count'?: NUMt = new NumInfo('number of items created from a drag button (used for setting title with incrementing index)');
+ '_carousel-caption-xMargin'?: NUMt = new NumInfo('x margin of caption inside of a carouself collection', true);
+ '_carousel-caption-yMargin'?: NUMt = new NumInfo('y margin of caption inside of a carouself collection', true);
+ 'icon-nativeWidth'?: NUMt = new NumInfo('native width of icon view', true);
+ 'icon-nativeHeight'?: NUMt = new NumInfo('native height of icon view', true);
+ 'dragFactory-count'?: NUMt = new NumInfo('number of items created from a drag button (used for setting title with incrementing index)', true);
openFactoryLocation?: string; // an OpenWhere value to place the factory created document
openFactoryAsDelegate?: boolean; //
lat?: number;
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
index 1ef2fb4ef..a9434fde3 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
@@ -9,13 +9,18 @@
.schema-table {
background-color: $white;
cursor: grab;
- overflow: scroll;
+
+ .schema-table-content {
+ overflow: overlay;
+ scroll-behavior: smooth;
+ }
.schema-column-menu,
.schema-filter-menu {
background: $light-gray;
position: absolute;
min-width: 200px;
+ max-width: 400px;
display: flex;
flex-direction: column;
align-items: flex-start;
@@ -26,14 +31,20 @@
margin: 10px;
}
- .schema-key-search-result {
+ .schema-search-result {
cursor: pointer;
- padding: 2px 10px;
+ padding: 5px 10px;
width: 100%;
&:hover {
background-color: $medium-gray;
}
+
+ .schema-search-result-type,
+ .schema-search-result-desc {
+ color: $dark-gray;
+ font-size: $body-text;
+ }
}
.schema-key-search,
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index fd9bcf681..d3992d12c 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -3,13 +3,13 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, observable, ObservableMap, untracked } from 'mobx';
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
-import { Doc, Field, StrListCast } from '../../../../fields/Doc';
+import { Doc, DocListCast, Field, 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 { Docs, DocumentOptions, DocUtils, FInfo } from '../../../documents/Documents';
import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
import { SelectionManager } from '../../../util/SelectionManager';
@@ -40,11 +40,13 @@ export class CollectionSchemaView extends CollectionSubView() {
private _closestDropIndex: number = 0;
private _previewRef: HTMLDivElement | null = null;
private _makeNewColumn: boolean = false;
+ private _documentOptions: DocumentOptions = new DocumentOptions();
public static _rowHeight: number = 40;
public static _minColWidth: number = 25;
public static _rowMenuWidth: number = 60;
public static _previewDividerWidth: number = 4;
+ public static _newNodeInputHeight: number = 30;
@computed get _selectedDocs() {
return SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.context), this.props.Document));
@@ -53,16 +55,16 @@ export class CollectionSchemaView extends CollectionSubView() {
@observable _colEles: HTMLDivElement[] = [];
@observable _displayColumnWidths: number[] | undefined;
@observable _columnMenuIndex: number | undefined;
- @observable _menuOptions: string[] = [];
+ @observable _menuOptions: [string, { description: string; type: string; readOnly: boolean }][] = [];
@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 = '';
+ @observable _filterSearchValue: string = '';
- get documentKeys() {
+ get keyInfos() {
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.
@@ -74,7 +76,22 @@ export class CollectionSchemaView extends CollectionSubView() {
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));
+
+ let computedKeys: { [key: string]: { description: string; type: string; readOnly: boolean } } = {};
+ Object.keys(keys).forEach((key: string) => {
+ computedKeys[key] = { description: '', type: '', readOnly: false };
+ });
+
+ Object.entries(this._documentOptions).forEach((pair: [string, any]) => {
+ const info: FInfo = pair[1];
+ computedKeys[pair[0]] = { description: info.description, type: info.fieldType ?? '', readOnly: info.readOnly };
+ });
+
+ return computedKeys;
+ }
+
+ get documentKeys() {
+ return Object.keys(this.keyInfos);
}
@computed get previewWidth() {
@@ -177,7 +194,6 @@ export class CollectionSchemaView extends CollectionSubView() {
addRow = (doc: Doc | Doc[]) => {
const result: boolean = this.addDocument(doc);
- this.setSort(this.sortField, this.sortDesc);
return result;
};
@@ -355,7 +371,6 @@ export class CollectionSchemaView extends CollectionSubView() {
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();
draggedDocs.forEach(doc => {
const draggedView = DocumentManager.Instance.getFirstDocumentView(doc);
@@ -371,7 +386,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);
@@ -443,7 +457,8 @@ 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))();
+ const menuKeys = Object.keys(this._menuOptions);
+ menuKeys.length > 0 && this._menuValue.length > 0 ? this.setKey(menuKeys[0]) : action(() => (this._makeNewField = true))();
break;
case 'Escape':
this.closeColumnMenu();
@@ -472,7 +487,7 @@ export class CollectionSchemaView extends CollectionSubView() {
this._makeNewColumn = false;
this._columnMenuIndex = index;
this._menuValue = '';
- this._menuOptions = this.documentKeys;
+ this._menuOptions = Object.entries(this.keyInfos);
this._makeNewField = false;
this._newFieldWarning = '';
this._makeNewField = false;
@@ -485,24 +500,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 +533,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._menuOptions = Object.entries(this.keyInfos).filter(value => value[0].toLowerCase().includes(this._menuValue.toLowerCase()));
};
getFieldFilters = (field: string) => StrListCast(this.Document._docFilters).filter(filter => filter.split(':')[0] == field);
@@ -535,15 +543,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 +635,23 @@ export class CollectionSchemaView extends CollectionSubView() {
{ passive: false }
)
}>
- {this._menuOptions.map(key => (
+ {this._menuOptions.map(([key, info]) => (
<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}
+ {info.type ? ', ' : ''}
+ </span>
+ <span className="schema-search-result-type" style={{ color: info.readOnly ? 'red' : 'inherit' }}>
+ {info.type}
+ </span>
+ </p>
+ <p className="schema-search-result-desc">{info.description}</p>
</div>
))}
</div>
@@ -662,21 +680,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 +715,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>
@@ -729,7 +740,7 @@ export class CollectionSchemaView extends CollectionSubView() {
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;
@@ -781,7 +792,7 @@ export class CollectionSchemaView extends CollectionSubView() {
{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} />
+ <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 && (
@@ -836,11 +847,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" 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}
@@ -874,6 +885,7 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP
hideLinkAnchors={true}
fitWidth={returnTrue}
scriptContext={this}
+ canEmbedOnDrag={true}
/>
</div>
);
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index d88d67c94..b133347cf 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -12,7 +12,7 @@ export interface SchemaColumnHeaderProps {
columnIndex: number;
sortField: string;
sortDesc: boolean;
- setSort: (field: string, desc: boolean) => void;
+ setSort: (field: string | undefined, desc?: boolean) => void;
removeColumn: (index: number) => void;
resizeColumn: (e: any, index: number) => void;
dragColumn: (e: any, index: number) => boolean;
@@ -30,8 +30,10 @@ export class SchemaColumnHeader extends React.Component<SchemaColumnHeaderProps>
sortClicked = (e: React.PointerEvent) => {
e.stopPropagation();
e.preventDefault();
- if (this.props.sortField == this.fieldKey) {
- this.props.setSort(this.fieldKey, !this.props.sortDesc);
+ 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);
}
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 2defaae00..aa8a61205 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -123,6 +123,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps>() {
<SchemaTableCell
key={key}
Document={this.rootDoc}
+ schemaView={this.schemaView}
fieldKey={key}
columnWidth={this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth}
isRowActive={this.props.isContentActive}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 13e45963e..42c9f9d48 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -9,9 +9,11 @@ import { KeyValueBox } from '../../nodes/KeyValueBox';
import { DefaultStyleProvider } from '../../StyleProvider';
import { CollectionSchemaView } from './CollectionSchemaView';
import './CollectionSchemaView.scss';
+import { computed } from 'mobx';
export interface SchemaTableCellProps {
Document: Doc;
+ schemaView: CollectionSchemaView | undefined;
fieldKey: string;
columnWidth: number;
isRowActive: () => boolean | undefined;
@@ -20,6 +22,10 @@ export interface SchemaTableCellProps {
@observer
export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
+ get readOnly() {
+ return this.props.schemaView?.keyInfos[this.props.fieldKey].readOnly;
+ }
+
render() {
const props: FieldViewProps = {
Document: this.props.Document,
@@ -50,7 +56,7 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
return (
<div className="schema-table-cell" style={{ width: this.props.columnWidth }}>
- <div className="schemacell-edit-wrapper" style={this.props.isRowActive() ? { cursor: 'text', pointerEvents: 'auto' } : { cursor: 'default', pointerEvents: 'none' }}>
+ <div className="schemacell-edit-wrapper" style={this.props.isRowActive() && !this.readOnly ? { cursor: 'text', pointerEvents: 'auto' } : { cursor: 'default', pointerEvents: 'none' }}>
<EditableView
contents={<FieldView {...props} />}
GetValue={() => Field.toKeyValueString(this.props.Document, this.props.fieldKey)}