diff options
author | Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> | 2024-07-12 14:44:48 -0400 |
---|---|---|
committer | Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> | 2024-07-12 14:44:48 -0400 |
commit | 1447bae0e24016f0c4fde772235d3e60f2b3555c (patch) | |
tree | e4314d296f10bb2c07c83c4eb0f92190d657df23 | |
parent | 54fbd0815e93da8aff7a601676a90aa0faf87de8 (diff) |
basic doc creation from templates working
-rw-r--r-- | src/client/views/collections/collectionSchema/SchemaRowBox.tsx | 3 | ||||
-rw-r--r-- | src/client/views/nodes/DataVizBox/DataVizBox.tsx | 51 | ||||
-rw-r--r-- | src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx | 68 |
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 |