aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx306
-rw-r--r--src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx2
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx6
3 files changed, 114 insertions, 200 deletions
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 9623b0d12..0e5a1e6b6 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -47,6 +47,18 @@ import { threadId } from 'worker_threads';
import { FontIconBox } from '../../nodes/FontIconBox/FontIconBox';
import { SnappingManager } from '../../../util/SnappingManager';
+/**
+ * The schema view offers a spreadsheet-like interface for users to interact with documents. Within the schema,
+ * each doc is represented by its own row. Each column represents a field, for example the author or title fields.
+ * Users can apply varoius filters and sorts to columns to change what is displayed. The schemaview supports equations for
+ * cell linking.
+ *
+ * This class supports the main functionality for choosing which docs to render in the view, applying visual
+ * updates to rows and columns (such as user dragging or sort-related highlighting), applying edits to multiple cells
+ * at once, and applying filters and sorts to columns. It contains SchemaRowBoxes (which themselves contain SchemaTableCells,
+ * and SchemaCellFields) and SchemaColumnHeaders.
+ */
+
const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore
export const FInfotoColType: { [key: string]: ColumnType } = {
@@ -109,19 +121,19 @@ export class CollectionSchemaView extends CollectionSubView() {
@observable _newFieldType: ColumnType = ColumnType.Number;
@observable _menuValue: string = '';
@observable _filterColumnIndex: number | undefined = undefined;
- @observable _filterSearchValue: string = '';
+ @observable _filterSearchValue: string = ''; //the current text inside the filter search bar, used to determine which values to display
@observable _selectedCol: number = 0;
@observable _selectedCells: Array<Doc> = [];
@observable _mouseCoordinates = { x: 0, y: 0, prevX: 0, prevY: 0 };
@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 _colBeingDragged: boolean = false; //whether a column is being dragged by the user
@observable _colKeysFiltered: boolean = false;
@observable _cellTags: ObservableMap = new ObservableMap<Doc, Array<string>>();
@observable _highlightedCellsInfo: Array<[doc: Doc, field: string]> = [];
@observable _cellHighlightColors: ObservableMap = new ObservableMap<string, string[]>();
- @observable _docs: Doc[] = [];
+ @observable _containedDocs: Doc[] = []; //all direct children of the schema
@observable _referenceSelectMode: {enabled: boolean, currEditing: SchemaCellField | undefined} = {enabled: false, currEditing: undefined}
// target HTMLelement portal for showing a popup menu to edit cell values.
@@ -218,11 +230,11 @@ export class CollectionSchemaView extends CollectionSubView() {
);
this._disposers.docdata = reaction(
() => DocListCast(this.dataDoc[this.fieldKey]),
- (docs) => this._docs = docs,
+ (docs) => this._containedDocs = docs,
{fireImmediately: true}
)
this._disposers.sortHighlight = reaction(
- () => [this.sortField, this._docs, this._selectedDocs, this._highlightedCellsInfo],
+ () => [this.sortField, this._containedDocs, this._selectedDocs, this._highlightedCellsInfo],
() => {this.sortField && setTimeout(() => this.highlightSortedColumn())},
{fireImmediately: true}
)
@@ -239,7 +251,7 @@ export class CollectionSchemaView extends CollectionSubView() {
removeDoc = (doc: Doc) => {
this.removeDocument(doc);
- this._docs = this._docs.filter(d => d !== doc)
+ this._containedDocs = this._containedDocs.filter(d => d !== doc)
}
rowIndex = (doc: Doc) => this.docsWithDrag.docs.indexOf(doc);
@@ -301,11 +313,7 @@ export class CollectionSchemaView extends CollectionSubView() {
}
break;
case 'Backspace': {
- // this._docs.forEach(doc => {
- // if (!this.childDocs.concat(this.displayedSubCollectionDocs(this.Document)))
- // });
- // console.log('backspace detected')
- undoable(() => {this._selectedDocs.forEach(d => this._docs.includes(d) && this.removeDoc(d));}, 'delete schema row');
+ undoable(() => {this._selectedDocs.forEach(d => this._containedDocs.includes(d) && this.removeDoc(d));}, 'delete schema row');
break;
}
case 'Escape': {
@@ -320,9 +328,6 @@ export class CollectionSchemaView extends CollectionSubView() {
}
};
- @action
- changeSelectedCellColumn = () => {};
-
addRow = (doc: Doc | Doc[]) => this.addDocument(doc);
@undoBatch
@@ -363,7 +368,7 @@ export class CollectionSchemaView extends CollectionSubView() {
if (this.columnKeys.length === 1) return;
if (this._columnMenuIndex === index) {
this._headerRefs[index].toggleEditing(false);
- this.closeColumnMenu();
+ this.closeNewColumnMenu();
}
const currWidths = this.storedColumnWidths.slice();
currWidths.splice(index, 1);
@@ -436,7 +441,7 @@ export class CollectionSchemaView extends CollectionSubView() {
@action
dragColumn = (e: PointerEvent, index: number) => {
- this.closeColumnMenu();
+ this.closeNewColumnMenu();
this._headerRefs.forEach(ref => ref.toggleEditing(false));
this._draggedColIndex = index;
this.setColDrag(true);
@@ -447,6 +452,11 @@ export class CollectionSchemaView extends CollectionSubView() {
return true;
};
+ /**
+ * Uses cursor x coordinate to calculate which index the column should be rendered/dropped in
+ * @param mouseX cursor x coordinate
+ * @returns column index
+ */
findColDropIndex = (mouseX: number) => {
let xOffset: number = this._props.ScreenToLocalTransform().inverse().transformPoint(0,0)[0] + CollectionSchemaView._rowMenuWidth;
let index: number | undefined;
@@ -461,32 +471,11 @@ export class CollectionSchemaView extends CollectionSubView() {
};
/**
- * Calculates the relative index of the cursor in the group of selected rows, ie.
- * if five rows are selected and the cursor is in the middle row, its relative index would be 2.
- * Used to align actively dragged documents properly with the cursor.
- * @param mouseY the initial Y position of the cursor on drag
+ * Calculates the current index of dragged rows for dynamic rendering and drop logic.
+ * @param mouseY user's cursor position relative to the viewport
+ * @returns row index the dragged doc should be rendered/dropped in
*/
- @action
- setRelCursorIndex = (mouseY: number) => {
- this._mouseCoordinates.y = mouseY; // updates this.rowDropIndex computed value to overwrite the old cached value
-
- const rowHeight = CollectionSchemaView._rowHeight;
- const adjInitMouseY = mouseY - rowHeight - 100; // rowHeight: height of the column menu cells | 100: height of the top menu
- const yOffset = this._lowestSelectedIndex * rowHeight;
-
- const heights = this._selectedDocs.map(() => this.rowHeightFunc());
- let index: number = 0;
- heights.reduce((total, curr, i) => {
- if (total <= adjInitMouseY && total + curr >= adjInitMouseY) {
- if (adjInitMouseY <= total + curr) index = i;
- else index = i + 1;
- }
- return total + curr;
- }, yOffset);
- this._relCursorIndex = index;
- };
-
- findRowDropIndex = (mouseY: number) => {
+ findRowDropIndex = (mouseY: number): number => {
const rowHeight = CollectionSchemaView._rowHeight;
let index: number = 0;
this.rowHeights.reduce((total, curr, i) => {
@@ -545,10 +534,16 @@ export class CollectionSchemaView extends CollectionSubView() {
});
}
+ /**
+ * Applies a gradient highlight to a sorted column. The direction of the gradient depends
+ * on whether the sort is ascending or descending.
+ * @param field the column being sorted
+ * @param descending whether the sort is descending or ascending; descending if true
+ */
highlightSortedColumn = (field?: string, descending?: boolean) => {
let index = -1;
let highlightColors: string[] = [];
- const rowCount: number = this._docs.length + 1;
+ const rowCount: number = this._containedDocs.length + 1;
if (field || this.sortField){
index = this.columnKeys.indexOf(field || this.sortField);
const increment: number = 110/rowCount;
@@ -581,12 +576,23 @@ export class CollectionSchemaView extends CollectionSubView() {
}
+ /**
+ * Gets the html element representing a cell so that styles can be applied on it.
+ * @param doc the cell's row document
+ * @param fieldKey the cell's column's field key
+ * @returns the html element representing the cell at the given location
+ */
getCellElement = (doc: Doc, fieldKey: string) => {
const index = this.columnKeys.indexOf(fieldKey);
const cell = this._rowEles.get(doc).children[1].children[index];
return cell;
}
+ /**
+ * Given text in a cell, find references to other cells (for equations).
+ * @param text the text in the cell
+ * @returns the html cell elements referenced in the text.
+ */
findCellRefs = (text: string) => {
const pattern = /(this|d(\d+))\.(\w+)/g;
interface Match { docRef: string; field: string; }
@@ -604,12 +610,18 @@ export class CollectionSchemaView extends CollectionSubView() {
const {docRef, field} = match;
const docView = DocumentManager.Instance.DocumentViews[Number(docRef)];
const doc = docView?.Document ?? undefined;
- if (this.columnKeys.includes(field) && this._docs.includes(doc)) {cells.push([doc, field])}
+ if (this.columnKeys.includes(field) && this._containedDocs.includes(doc)) {cells.push([doc, field])}
})
return cells;
}
+ /**
+ * Determines whether the rows above or below a given row have been
+ * selected, so selection highlights don't overlap.
+ * @param doc the document row to check
+ * @returns a boolean tuple where 0 is the row above, and 1 is the row below
+ */
selectionOverlap = (doc: Doc): [boolean, boolean] => {
const docs = this.docsWithDrag.docs;
const index = this.rowIndex(doc);
@@ -647,6 +659,11 @@ export class CollectionSchemaView extends CollectionSubView() {
});
}
+ /**
+ * Highlights cells based on equation text in the cell currently being edited.
+ * Does not highlight selected cells (that's done directly in SchemaTableCell).
+ * @param text the equation
+ */
highlightCells = (text: string) => {
this.removeCellHighlights();
@@ -660,7 +677,6 @@ export class CollectionSchemaView extends CollectionSubView() {
const doc = info[0];
const field = info[1];
const key = `${doc[Id]}_${field}`;
- console.log(key + ' ' + i % 10 + ' color: ' + color[0].r + color[0].g + color[0].b);
const cell = this.getCellElement(doc, field);
this._cellHighlightColors.set(key, [colorStrings[0], colorStrings[1]]);
cell.style.border = colorStrings[0];
@@ -668,6 +684,7 @@ export class CollectionSchemaView extends CollectionSubView() {
}
}
+ //Used in SchemaRowBox
@action
addRowRef = (doc: Doc, ref: HTMLDivElement) => this._rowEles.set(doc, ref);
@@ -693,7 +710,8 @@ export class CollectionSchemaView extends CollectionSubView() {
this.deselectAllCells();
};
- selectRows = (doc: Doc, lastSelected: Doc) => {
+
+ selectRow = (doc: Doc, lastSelected: Doc) => {
const index = this.rowIndex(doc);
const lastSelectedRow = this.rowIndex(lastSelected);
const startRow = Math.min(lastSelectedRow, index);
@@ -706,6 +724,7 @@ export class CollectionSchemaView extends CollectionSubView() {
}
};
+ //Used in SchemaRowBox
selectReference = (doc: Doc | undefined, col: number) => {
if (!doc) return;
const docIndex = DocumentView.getDocViewIndex(doc);
@@ -719,7 +738,7 @@ export class CollectionSchemaView extends CollectionSubView() {
@action
selectCell = (doc: Doc, col: number, shiftKey: boolean, ctrlKey: boolean) => {
- this.closeColumnMenu();
+ this.closeNewColumnMenu();
if (!shiftKey && !ctrlKey) this.clearSelection();
!this._selectedCells && (this._selectedCells = []);
!shiftKey && this._selectedCells.push(doc);
@@ -727,7 +746,7 @@ export class CollectionSchemaView extends CollectionSubView() {
if (!this) return;
const lastSelected = Array.from(this._selectedDocs).lastElement();
- if (shiftKey && lastSelected && !this._selectedDocs.includes(doc)) this.selectRows(doc, lastSelected);
+ if (shiftKey && lastSelected && !this._selectedDocs.includes(doc)) this.selectRow(doc, lastSelected);
else if (ctrlKey) {
if (lastSelected && this._selectedDocs.includes(doc)) {
DocumentView.DeselectView(DocumentView.getFirstDocumentView(doc));
@@ -821,71 +840,6 @@ export class CollectionSchemaView extends CollectionSubView() {
return undefined;
};
- @computed get fieldDefaultInput() {
- switch (this._newFieldType) {
- case ColumnType.Number:
- return (
- <input
- type="number"
- name=""
- id=""
- value={this._newFieldDefault ?? 0}
- onPointerDown={e => e.stopPropagation()}
- onChange={action((e: any) => {
- this._newFieldDefault = e.target.value;
- })}
- />
- );
- case ColumnType.Boolean:
- return (
- <>
- <input
- type="checkbox"
- name=""
- id=""
- value={this._newFieldDefault}
- onPointerDown={e => e.stopPropagation()}
- onChange={action((e: any) => {
- this._newFieldDefault = e.target.checked;
- })}
- />
- {this._newFieldDefault ? 'true' : 'false'}
- </>
- );
- case ColumnType.String:
- return (
- <input
- type="text"
- name=""
- id=""
- value={this._newFieldDefault ?? ''}
- onPointerDown={e => e.stopPropagation()}
- onChange={action((e: any) => {
- this._newFieldDefault = e.target.value;
- })}
- />
- );
- default:
- return undefined;
- }
- }
-
- onSearchKeyDown = (e: React.KeyboardEvent) => {
- switch (e.key) {
- case 'Enter':
- this._menuKeys.length > 0 && this._menuValue.length > 0
- ? this.setKey(this._menuKeys[0])
- : runInAction(() => {
- this._makeNewField = true;
- });
- break;
- case 'Escape':
- this.closeColumnMenu();
- break;
- default:
- }
- };
-
@action
setKey = (key: string, defaultVal?: any, index?: number) => {
if (this.columnKeys.includes(key)) return;
@@ -895,9 +849,15 @@ export class CollectionSchemaView extends CollectionSubView() {
this._makeNewColumn = false;
} else this.changeColumnKey(this._columnMenuIndex! | index!, key, defaultVal);
- this.closeColumnMenu();
+ this.closeNewColumnMenu();
};
+ /**
+ * Used in SchemaRowBox to set
+ * @param key
+ * @param value
+ * @returns
+ */
setCellValues = (key: string, value: string) => {
if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value));
else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value));
@@ -905,24 +865,7 @@ export class CollectionSchemaView extends CollectionSubView() {
};
@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) => {
+ openNewColumnMenu = (index: number, newCol: boolean) => {
this.closeFilterMenu();
this._makeNewColumn = false;
@@ -934,7 +877,7 @@ export class CollectionSchemaView extends CollectionSubView() {
};
@action
- closeColumnMenu = () => {
+ closeNewColumnMenu = () => {
this._columnMenuIndex = undefined;
};
@@ -956,7 +899,7 @@ export class CollectionSchemaView extends CollectionSubView() {
};
openContextMenu = (x: number, y: number, index: number) => {
- this.closeColumnMenu();
+ this.closeNewColumnMenu();
this.closeFilterMenu();
const cm = ContextMenu.Instance;
cm.clearItems();
@@ -970,7 +913,7 @@ export class CollectionSchemaView extends CollectionSubView() {
event: () => {
this.setColumnSort(undefined);
const field = this.columnKeys[index];
- this._docs = this.sortDocs(field, false);
+ this._containedDocs = this.sortDocs(field, false);
setTimeout(() => {
this.highlightSortedColumn(field, false);
setTimeout(() => this.highlightSortedColumn(), 480);
@@ -982,7 +925,7 @@ export class CollectionSchemaView extends CollectionSubView() {
event: () => {
this.setColumnSort(undefined);
const field = this.columnKeys[index];
- this._docs = this.sortDocs(field, true);
+ this._containedDocs = this.sortDocs(field, true);
setTimeout(() => {
this.highlightSortedColumn(field, true);
setTimeout(() => this.highlightSortedColumn(), 480);
@@ -1016,7 +959,7 @@ export class CollectionSchemaView extends CollectionSubView() {
cm.addItem({
description: `Change field`,
- event: () => this.openColumnMenu(index, false),
+ event: () => this.openNewColumnMenu(index, false),
icon: 'pencil-alt',
});
cm.addItem({
@@ -1049,6 +992,7 @@ export class CollectionSchemaView extends CollectionSubView() {
cm.displayMenu(x, y, undefined, false);
};
+ //used in schemacolumnheader
@action
updateKeySearch = (val: string) => {
this._menuKeys = this.documentKeys.filter(value => value.toLowerCase().includes(val.toLowerCase()));
@@ -1075,70 +1019,12 @@ export class CollectionSchemaView extends CollectionSubView() {
this._filterSearchValue = e.target.value;
};
- // @computed get newFieldMenu() {
- // return (
- // <div className="schema-new-key-options">
- // <div className="schema-key-type-option">
- // <input
- // type="radio"
- // name="newFieldType"
- // checked={this._newFieldType === ColumnType.Number}
- // onChange={action(() => {
- // this._newFieldType = ColumnType.Number;
- // this._newFieldDefault = 0;
- // })}
- // />
- // number
- // </div>
- // <div className="schema-key-type-option">
- // <input
- // type="radio"
- // name="newFieldType"
- // checked={this._newFieldType === ColumnType.Boolean}
- // onChange={action(() => {
- // this._newFieldType = ColumnType.Boolean;
- // this._newFieldDefault = false;
- // })}
- // />
- // boolean
- // </div>
- // <div className="schema-key-type-option">
- // <input
- // type="radio"
- // name="newFieldType"
- // checked={this._newFieldType === ColumnType.String}
- // onChange={action(() => {
- // this._newFieldType = ColumnType.String;
- // this._newFieldDefault = '';
- // })}
- // />
- // string
- // </div>
- // <div className="schema-key-default-val">value: {this.fieldDefaultInput}</div>
- // <div className="schema-key-warning">{this._newFieldWarning}</div>
- // <div
- // className="schema-column-menu-button"
- // onPointerDown={action(() => {
- // if (this.documentKeys.includes(this._menuValue)) {
- // this._newFieldWarning = 'Field already exists';
- // } else if (this._menuValue.length === 0) {
- // this._newFieldWarning = 'Field cannot be an empty string';
- // } else {
- // this.setKey(this._menuValue, this._newFieldDefault);
- // }
- // this._columnMenuIndex = undefined;
- // })}>
- // done
- // </div>
- // </div>
- // );
- // }
-
onKeysPassiveWheel = (e: WheelEvent) => {
// if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this)
if (!this._oldKeysWheel.scrollTop && e.deltaY <= 0) e.preventDefault();
e.stopPropagation();
};
+
_oldKeysWheel: any;
@computed get keysDropdown() {
return (
@@ -1262,6 +1148,12 @@ export class CollectionSchemaView extends CollectionSubView() {
}
};
+ /**
+ * Gets docs contained by collections within the schema
+ * @param doc
+ * @param displayed
+ * @returns
+ */
subCollectionDocs = (doc: Doc, displayed: boolean) => {
const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]);
let collections: Array<Doc> = [];
@@ -1272,13 +1164,16 @@ export class CollectionSchemaView extends CollectionSubView() {
return toReturn;
}
+ /**
+ * Applies any filters active on the schema to filter out docs that don't match.
+ */
@computed get filteredDocs() {
const childDocFilters = this.childDocFilters();
const childFiltersByRanges = this.childDocRangeFilters();
const searchDocs = this.searchFilterDocs();
const docsforFilter: Doc[] = [];
- this._docs.forEach(d => {
+ this._containedDocs.forEach(d => {
// dragging facets
const dragged = this._props.childFilters?.().some(f => f.includes(ClientUtils.noDragDocsFilter));
if (dragged && SnappingManager.CanEmbed && DragManager.docsBeingDragged.includes(d)) return;
@@ -1315,12 +1210,15 @@ export class CollectionSchemaView extends CollectionSubView() {
return docsforFilter;
}
+ /**
+ * Returns all child docs of the schema and child docs of contained collections that satisfy applied filters.
+ */
@computed get docs() {
let docsFromChildren: Doc[] = [];
const displayedCollections = this.childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema);
displayedCollections.forEach(d => {
- let docsNotAlreadyDisplayed = this.subCollectionDocs(d, true).filter(dc => !this._docs.includes(dc));
+ let docsNotAlreadyDisplayed = this.subCollectionDocs(d, true).filter(dc => !this._containedDocs.includes(dc));
docsFromChildren = docsFromChildren.concat(docsNotAlreadyDisplayed);
});
let docs = this.filteredDocs;
@@ -1328,6 +1226,13 @@ export class CollectionSchemaView extends CollectionSubView() {
return docs;
}
+ /**
+ * Sorts docs first alphabetically and then numerically.
+ * @param field the column being sorted
+ * @param desc whether the sort is ascending or descending
+ * @param persistent whether the sort is applied persistently or is one-shot
+ * @returns
+ */
sortDocs = (field: string, desc: boolean, persistent?: boolean) => {
const numbers: Doc[] = [];
const strings: Doc[] = [];
@@ -1349,10 +1254,13 @@ export class CollectionSchemaView extends CollectionSubView() {
} else sortedStrings = strings.slice().sort((docB, docA) => collator.compare(Field.toString(docA[field] as FieldType), Field.toString(docB[field] as FieldType)));
const sortedDocs = desc ? sortedNums.concat(sortedStrings) : sortedStrings.concat(sortedNums);
- if (!persistent) this._docs = sortedDocs;
+ if (!persistent) this._containedDocs = sortedDocs;
return sortedDocs;
}
+ /**
+ * Returns all docs minus those currently being dragged by the user.
+ */
@computed get docsWithDrag() {
let docs = this.docs.slice();
if (this.sortField){
@@ -1380,7 +1288,7 @@ export class CollectionSchemaView extends CollectionSubView() {
<div className="collectionSchemaView" ref={(ele: HTMLDivElement | null) => this.createDashEventsTarget(ele)}
onDrop={this.onExternalDrop.bind(this)}
onPointerMove={e => this.onPointerMove(e)}
- onPointerDown={() => {this.closeColumnMenu(); this.setColDrag(false)}}>
+ onPointerDown={() => {this.closeNewColumnMenu(); this.setColDrag(false)}}>
<div ref={this._menuTarget} style={{ background: 'red', top: 0, left: 0, position: 'absolute', zIndex: 10000 }} />
<div
className="schema-table"
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 9f6478041..6da236d82 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -71,7 +71,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);}
@action updateAlt = (newAlt: string) => {this._altTitle = newAlt};
updateKeyDropdown = (value: string) => {this._props.schemaView.updateKeySearch(value)};
- openKeyDropdown = () => {!this._props.schemaView._colBeingDragged && this._props.schemaView.openColumnMenu(this._props.columnIndex, false)};
+ openKeyDropdown = () => {!this._props.schemaView._colBeingDragged && this._props.schemaView.openNewColumnMenu(this._props.columnIndex, false)};
toggleEditing = (editing: boolean) => {
this._inputRef?.setIsEditing(editing);
this._inputRef?.setIsFocused(editing);
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
index 8afd1bbf1..bb9ea7e17 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
@@ -631,6 +631,12 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
// return new Doc;
// }
+ /**
+ * Populates a preset template framework with content from a datavizbox or any AI-generated content.
+ * @param template the preloaded template framework being filled in
+ * @param assignments a list of template field numbers (from top to bottom) and their assigned columns from the linked dataviz
+ * @returns a doc containing the fully rendered template
+ */
fillPresetTemplate = async(template: TemplateDocInfos, assignments: {[field: string]: Col}): Promise<Doc> => {
const wordLimit = (size: TemplateFieldSize) => {
switch (size) {