aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan-SR <144961007+Nathan-SR@users.noreply.github.com>2024-07-12 14:44:48 -0400
committerNathan-SR <144961007+Nathan-SR@users.noreply.github.com>2024-07-12 14:44:48 -0400
commit1447bae0e24016f0c4fde772235d3e60f2b3555c (patch)
treee4314d296f10bb2c07c83c4eb0f92190d657df23
parent54fbd0815e93da8aff7a601676a90aa0faf87de8 (diff)
basic doc creation from templates working
-rw-r--r--src/client/views/collections/collectionSchema/SchemaRowBox.tsx3
-rw-r--r--src/client/views/nodes/DataVizBox/DataVizBox.tsx51
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx68
3 files changed, 95 insertions, 27 deletions
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 2410b2793..72f5d8c25 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -24,6 +24,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { infoState } from '../collectionFreeForm/CollectionFreeFormInfoState';
import { TbShieldX } from 'react-icons/tb';
+import { DocumentType } from '../../../documents/DocumentTypes';
interface SchemaRowBoxProps extends FieldViewProps {
rowIndex: number;
@@ -77,7 +78,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
icon: 'minus',
});
const childDocs = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)])
- if (this.Document.type === 'collection' && childDocs.length) {
+ if (childDocs.length) {
ContextMenu.Instance.addItem({
description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema',
event: () => {
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index c43177c51..86a9db79c 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -5,14 +5,14 @@ import { Colors, Toggle, ToggleType, Type } from 'browndash-components';
import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { returnEmptyString, returnFalse, returnOne, setupMoveUpEvents } from '../../../../ClientUtils';
+import { ClientUtils, returnEmptyString, returnFalse, returnOne, setupMoveUpEvents } from '../../../../ClientUtils';
import { emptyFunction } from '../../../../Utils';
-import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../../fields/Doc';
+import { Doc, DocListCast, Field, FieldType, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
import { InkTool } from '../../../../fields/InkField';
import { List } from '../../../../fields/List';
import { Cast, CsvCast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
import { CsvField } from '../../../../fields/URLField';
-import { TraceMobx } from '../../../../fields/util';
+import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util';
import { DocUtils } from '../../../documents/DocUtils';
import { DocumentType } from '../../../documents/DocumentTypes';
import { Docs } from '../../../documents/Documents';
@@ -33,8 +33,10 @@ import { LineChart } from './components/LineChart';
import { PieChart } from './components/PieChart';
import { TableBox } from './components/TableBox';
import { LinkManager } from '../../../util/LinkManager';
-import { Collection } from 'mongoose';
-import { DocCreatorMenu } from './DocCreatorMenu';
+import { DataVizTemplateInfo, DocCreatorMenu } from './DocCreatorMenu';
+import { CollectionFreeFormView } from '../../collections/collectionFreeForm';
+import { PrefetchProxy } from '../../../../fields/Proxy';
+import { AclAdmin, AclAugment, AclEdit } from '../../../../fields/DocSymbols';
export enum DataVizView {
TABLE = 'table',
@@ -149,6 +151,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// }
// return func() ?? false;
};
+
getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
const visibleAnchor = AnchorMenu.Instance.GetAnchor?.(undefined, addAsAnnotation);
const anchor = !pinProps
@@ -457,7 +460,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
getPossibleTemplates = (): Doc[] => {
const linkedDocs: Doc[] = LinkManager.Instance.getAllRelatedLinks(this.Document).map(d => DocCast(LinkManager.getOppositeAnchor(d, this.Document)));
- const linkedCollections: Doc[] = linkedDocs.filter(doc => doc.type === 'config').filter(doc => DocCast(doc.annotationOn).type === 'collection').map(doc => DocCast(doc.annotationOn));
+ const linkedCollections: Doc[] = linkedDocs.filter(doc => doc.type === 'config').map(doc => DocCast(doc.annotationOn));
const isColumnTitle = (title: string): boolean => {
const colTitles: string[] = Object.keys(this.records[0]);
for (let i = 0; i < colTitles.length; ++i){
@@ -470,7 +473,6 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
const isValidTemplate = (collection: Doc) => {
const childDocs = DocListCast(collection[Doc.LayoutFieldKey(collection)]);
- console.log('childDocs of col: ' + childDocs)
for (let i = 0; i < childDocs.length; ++i){
if (isColumnTitle(String(childDocs[i].title))) return true;
}
@@ -479,6 +481,41 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return linkedCollections.filter(col => isValidTemplate(col));
}
+ ApplyTemplateTo = (templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined) => {
+ if (!Doc.AreProtosEqual(target[targetKey] as Doc, templateDoc)) {
+ if (target.resolvedDataDoc) {
+ target[targetKey] = new PrefetchProxy(templateDoc);
+ } else {
+ titleTarget && (Doc.GetProto(target).title = titleTarget);
+ const setDoc = [AclAdmin, AclEdit, AclAugment].includes(GetEffectiveAcl(Doc.GetProto(target))) ? Doc.GetProto(target) : target;
+ setDoc[targetKey] = new PrefetchProxy(templateDoc);
+ }
+ }
+ return target;
+ }
+
+ @action
+ createDocsFromTemplate = (templateInfo: DataVizTemplateInfo) => {
+ const mainCollection = this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView;
+ const fields: string[] = Array.from(Object.keys(this.records[0]));
+ const selectedRows = NumListCast(this.layoutDoc.dataViz_selectedRows);
+ const docs: Doc[] = selectedRows.map(row => {
+ const values: String[] = [];
+ fields.forEach(col => values.push(this.records[row][col]));
+
+ const proto = new Doc();
+ proto.author = ClientUtils.CurrentUserEmail();
+ values.forEach((val, i) => {proto[fields[i]] = val as FieldType});
+
+ const target = Doc.MakeDelegate(proto);
+ const targetKey = StrCast(templateInfo.doc.layout_fieldKey, 'layout');
+ const applied = this.ApplyTemplateTo(templateInfo.doc, target, targetKey, templateInfo.doc.title + `${row}`);
+ target.layout_fieldKey = targetKey;
+ return applied;
+ });
+ docs.forEach(doc => mainCollection.addDocument(doc));
+ }
+
/**
* creates a new dataviz document filter from this one
* it appears to the right of this document, with the
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
index 3ebf97570..88308c226 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
@@ -2,7 +2,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { IReactionDisposer, ObservableMap, action, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils';
+import { returnAll, returnFalse, setupMoveUpEvents } from '../../../../ClientUtils';
import { Doc } from '../../../../fields/Doc';
import { DocCast, ImageCast } from '../../../../fields/Types';
import { ImageField } from '../../../../fields/URLField';
@@ -15,6 +15,15 @@ import { DataVizBox } from './DataVizBox';
import './DocCreatorMenu.scss';
import { Id } from '../../../../fields/FieldSymbols';
import { Colors } from 'browndash-components';
+import { MakeTemplate } from '../../../util/DropConverter';
+
+export enum LayoutType {
+ Stacked = 'stacked',
+ Grid = 'grid',
+ Row = 'row',
+ Column = 'column',
+ Custom = 'custom'
+}
@observer
export class DocCreatorMenu extends ObservableReactComponent<{}> {
@@ -25,9 +34,9 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
@observable _templateDocs: Doc[] = [];
@observable _templateRefToDoc?: ObservableMap<HTMLDivElement, Doc>;
- @observable _selectedTemplateID?: Doc;
+ @observable _selectedTemplate?: Doc;
- @observable _selectedLayout?: 'stacked' | 'grid' | 'row' | 'column' | 'custom';
+ @observable _selectedLayout?: LayoutType;
@observable _pageX: number = 0;
@observable _pageY: number = 0;
@@ -49,9 +58,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
}
@action setDataViz = (dataViz: DataVizBox) => { this._dataViz = dataViz };
- @action setTemplateDocs = (docs: Doc[]) => {
- this._templateDocs = docs.map(doc => doc.annotationOn ? DocCast(doc.annotationOn):doc);
- };
+ @action setTemplateDocs = (docs: Doc[]) => {this._templateDocs = docs.map(doc => doc.annotationOn ? DocCast(doc.annotationOn):doc)};
+
@action
onPointerDown = (e: PointerEvent) => {
@@ -126,17 +134,22 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
{this._templateDocs.map(doc => ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => {
if (renderedTemplates.includes(info.doc)) return undefined;
renderedTemplates.push(info.doc);
+ //let ref: any = undefined;
return (<div
+ //ref={r => ref = r}
className='docCreatorMenu-preview-window'
style={{
- background: this._selectedTemplateID === info.doc ? Colors.MEDIUM_BLUE : '',
- boxShadow: this._selectedTemplateID === info.doc ? `0 0 15px rgba(68, 118, 247, .8)` : ''
+ background: this._selectedTemplate === info.doc ? Colors.MEDIUM_BLUE : '',
+ boxShadow: this._selectedTemplate === info.doc ? `0 0 15px rgba(68, 118, 247, .8)` : ''
}}
onPointerDown={e =>
setupMoveUpEvents(this, e, returnFalse, emptyFunction,
undoable(clickEv => {
clickEv.stopPropagation();
- this._selectedTemplateID = info.doc;
+ this._selectedTemplate = info.doc;
+ MakeTemplate(info.doc);
+ // ref.style.background = Colors.MEDIUM_BLUE;
+ // ref.style.boxShadow = `0 0 15px rgba(68, 118, 247, .8)`;
this.forceUpdate();
}, 'open actions menu')
)
@@ -150,7 +163,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
get optionsMenuContents(){
- const layoutOption = (option: 'stacked' | 'grid' | 'row' | 'column' | 'custom', optStyle?: {}) => {
+ const layoutOption = (option: LayoutType, optStyle?: {}) => {
return (
<div
className="docCreatorMenu-dropdown-option"
@@ -173,11 +186,11 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
<div className='docCreatorMenu-dropdown-hoverable'>
<div className="docCreatorMenu-dropdown-title">Choose Layout</div>
<div className="docCreatorMenu-dropdown-content">
- {layoutOption('stacked')}
- {layoutOption('grid')}
- {layoutOption('row')}
- {layoutOption('column')}
- {layoutOption('custom', {borderBottom: `0px`})}
+ {layoutOption(LayoutType.Stacked)}
+ {layoutOption(LayoutType.Grid)}
+ {layoutOption(LayoutType.Row)}
+ {layoutOption(LayoutType.Column)}
+ {layoutOption(LayoutType.Custom, {borderBottom: `0px`})}
</div>
</div>
<div className='docCreatorMenu-layout-preview-window'>
@@ -242,7 +255,22 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
>
<FontAwesomeIcon icon={this._menuContent === 'templates' ? 'bars' : 'magnifying-glass'}/>
</button>
- <button className='docCreatorMenu-menu-button right'>
+ <button
+ className='docCreatorMenu-menu-button right'
+ onPointerDown={e =>
+ setupMoveUpEvents(
+ this,
+ e,
+ returnFalse,
+ emptyFunction,
+ undoable(clickEv => {
+ clickEv.stopPropagation();
+ if (!this._selectedTemplate) return;
+ const templateInfo: DataVizTemplateInfo = {doc: this._selectedTemplate};
+ this._dataViz?.createDocsFromTemplate(templateInfo);
+ }, 'make docs')
+ )
+ }>
<FontAwesomeIcon icon={'plus'}/>
</button>
<button
@@ -258,8 +286,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
this.closeMenu();
}, 'close menu')
)
- }
- >
+ }>
<FontAwesomeIcon icon={'minus'}/>
</button>
</div>
@@ -270,6 +297,9 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
</div>
)
}
-
+}
+export interface DataVizTemplateInfo {
+ doc: Doc;
+ layout?: LayoutType;
} \ No newline at end of file