diff options
author | Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> | 2024-10-17 03:18:42 -0400 |
---|---|---|
committer | Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> | 2024-10-17 03:18:42 -0400 |
commit | e730ae254cd16559fdb7ca67ff1b4ed6767ab7e5 (patch) | |
tree | 91a303634f64dce38a1143e1841b163325968875 /src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx | |
parent | 064eba3ef2ba2211bf3ff44ec2fa4cae0d7acc40 (diff) |
work on getting collections to render directly into the layout editor
Diffstat (limited to 'src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx')
-rw-r--r-- | src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx | 424 |
1 files changed, 280 insertions, 144 deletions
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx index 91c86bef1..8977a282e 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx @@ -31,11 +31,12 @@ import { Transform } from '../../../../util/Transform'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; export enum LayoutType { - Stacked = 'stacked', - Grid = 'grid', + STACKED = 'stacked', + GRID = 'grid', Row = 'row', Column = 'column', Custom = 'custom', + CAROUSEL3D = 'carousel3d' } @observer @@ -46,12 +47,15 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { private _ref: HTMLDivElement | null = null; + @observable _fullyRenderedDocs: Doc[] = []; + @observable _renderedDocCollection: Doc | undefined = undefined; + @observable _templateDocs: Doc[] = []; @observable _selectedTemplate: Doc | undefined = undefined; @observable _columns: Col[] = []; @observable _selectedCols: { title: string; type: string; desc: string }[] | undefined = []; - @observable _layout: { type: LayoutType; yMargin: number; xMargin: number; columns?: number; repeat: number } = { type: LayoutType.Grid, yMargin: 0, xMargin: 0, repeat: 0 }; + @observable _layout: { type: LayoutType; yMargin: number; xMargin: number; columns?: number; repeat: number } = { type: LayoutType.GRID, yMargin: 0, xMargin: 0, repeat: 0 }; @observable _layoutPreview: boolean = true; @observable _layoutPreviewScale: number = 1; @observable _savedLayouts: DataVizTemplateLayout[] = []; @@ -112,14 +116,16 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { @computed get rowsCount() { switch (this._layout.type) { case LayoutType.Row: - case LayoutType.Stacked: + case LayoutType.STACKED: return 1; case LayoutType.Column: return this.docsToRender.length; - case LayoutType.Grid: + case LayoutType.GRID: return Math.ceil(this.docsToRender.length / (this._layout.columns ?? 1)) ?? 0; + case LayoutType.CAROUSEL3D: + return 1; default: - return 0; + return 1; } } @@ -128,12 +134,14 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { case LayoutType.Row: return this.docsToRender.length; case LayoutType.Column: - case LayoutType.Stacked: + case LayoutType.STACKED: return 1; - case LayoutType.Grid: + case LayoutType.GRID: return this._layout.columns ?? 0; + case LayoutType.CAROUSEL3D: + return 1.75; default: - return 0; + return 1; } } @@ -363,6 +371,9 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { } else { this._selectedTemplate = template; MakeTemplate(template); + const templateInfo: DataVizTemplateInfo = { doc: template, layout: this._layout, referencePos: { x: this._pageX + 450, y: this._pageY }, columns: this.columnsCount }; + this._fullyRenderedDocs = this._dataViz?.createDocsFromTemplate(templateInfo, true) ?? []; + this.updateRenderedDocCollection(); } }; @@ -1143,7 +1154,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { return <div className="docCreatorMenu-configuration-bar">{optionInput('arrows-left-right', this.updateXMargin, this._layout.xMargin, '0')}</div>; case LayoutType.Column: return <div className="docCreatorMenu-configuration-bar">{optionInput('arrows-up-down', this.updateYMargin, this._layout.yMargin, '1')}</div>; - case LayoutType.Grid: + case LayoutType.GRID: return ( <div className="docCreatorMenu-configuration-bar"> {optionInput('arrows-up-down', this.updateYMargin, this._layout.xMargin, '2')} @@ -1151,7 +1162,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { {optionInput('table-columns', this.updateColumns, this._layout.columns, '4', true)} </div> ); - case LayoutType.Stacked: + case LayoutType.STACKED: return null; default: break; @@ -1164,6 +1175,86 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { screenToLocalTransform = () => this._props.ScreenToLocalTransform(); + applyLayout = (collection: Doc, docs: Doc[]) => { + const layout = this._layout; + const columns: number = layout.columns ?? this.columnsCount; + const xGap: number = layout.xMargin; + const yGap: number = layout.yMargin; + // const repeat: number = templateInfo.layout.repeat; + const startX: number = -Number(collection._width)/2; + const startY: number = -Number(collection._height)/2; + const docHeight: number = Number(docs[0]._height); + const docWidth: number = Number(docs[0]._width); + + if (columns === 0 || docs.length === 0){ + return; + } + + let i: number = 0; + let docsChanged: number = 0; + let curX: number = startX; + let curY: number = startY; + + while (docsChanged < docs.length) { + while (i < columns && docsChanged < docs.length) { + docs[docsChanged].x = curX; + docs[docsChanged].y = curY; + curX += docWidth + xGap; + ++docsChanged; + ++i; + } + i = 0; + curX = startX; + curY += docHeight + yGap; + } + }; + + /** + * Updates the preview that shows how all docs will be rendered in the chosen collection type. + @type the type of collection the docs should render to (ie. freeform, carousel, card) + */ + updateRenderedDocCollection = () => { + if (!this._fullyRenderedDocs) return; + + const layout = this._layout; + + const docHeight: number = Number(this._fullyRenderedDocs[0]._height); + const docWidth: number = Number(this._fullyRenderedDocs[0]._width); + const horizontalSpan: number = (docWidth + layout.xMargin) * (this.columnsCount) - layout.xMargin; + const verticalSpan: number = (docHeight + layout.yMargin) * (this.rowsCount) - layout.yMargin; + const largerSpan: number = horizontalSpan > verticalSpan ? horizontalSpan : verticalSpan; + + const collectionFactory = (): (docs: Doc[], options: DocumentOptions) => Doc => { + switch (this._layout.type) { + case LayoutType.CAROUSEL3D: + return Docs.Create.Carousel3DDocument; + case LayoutType.GRID: + return Docs.Create.FreeformDocument; + default: + return Docs.Create.FreeformDocument; + } + } + + const docWithBasicOpts: Doc = collectionFactory()(this._fullyRenderedDocs, { + isDefaultTemplateDoc: true, + x: this._pageX, + y: this._pageY, + _height: verticalSpan, + _width: horizontalSpan, + title: 'title', + backgroundColor: 'gray', + }); + + this.applyLayout(docWithBasicOpts, this._fullyRenderedDocs); + + const wrapper: Doc = Docs.Create.FreeformDocument([docWithBasicOpts], { _height: NumListCast(docWithBasicOpts._height)[0], _width: NumListCast(docWithBasicOpts._width)[0], title: ''}); + + const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; + mainCollection.addDocument(docWithBasicOpts); + + this._renderedDocCollection = wrapper; + } + layoutPreviewContents = (outerSpan: number, altLayout?: DataVizTemplateLayout, small: boolean = false, id?: number) => { const doc: Doc | undefined = altLayout ? altLayout.template : this._selectedTemplate; if (!doc) return; @@ -1175,37 +1266,46 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { const horizontalSpan: number = (docWidth + layout.xMargin) * (altLayout ? altLayout.columns : this.columnsCount) - layout.xMargin; const verticalSpan: number = (docHeight + layout.yMargin) * (altLayout ? altLayout.rows : this.rowsCount) - layout.yMargin; const largerSpan: number = horizontalSpan > verticalSpan ? horizontalSpan : verticalSpan; + const scaledDown = (input: number) => { return input / ((largerSpan / outerSpan) * this._layoutPreviewScale); }; const fontSize = Math.min(scaledDown(docWidth / 3), scaledDown(docHeight / 3)); + + return ( - // <div className='divvv' style={{width: 100, height: 100, border: `1px solid white`}}> - // <CollectionFreeFormView - // // eslint-disable-next-line react/jsx-props-no-spreading - // {...this._props} - // Document={new Doc()} - // isContentActive={returnFalse} - // setContentViewBox={emptyFunction} - // NativeWidth={() => 100} - // NativeHeight={() => 100} - // pointerEvents={SnappingManager.IsDragging ? returnAll : returnNone} - // isAnnotationOverlay - // isAnnotationOverlayScrollable - // childDocumentsActive={returnFalse} - // fieldKey={this._props.fieldKey + '_annotations'} - // dropAction={dropActionType.move} - // select={emptyFunction} - // addDocument={returnFalse} - // removeDocument={returnFalse} - // moveDocument={returnFalse} - // renderDepth={this._props.renderDepth + 1}> - // {null} - // </CollectionFreeFormView> - // </div> <div className="docCreatorMenu-layout-preview-window-wrapper" id={String(id) ?? undefined}> - <div className="docCreatorMenu-zoom-button-container"> + <CollectionFreeFormView + Document={this._renderedDocCollection ?? new Doc()} + docViewPath={returnEmptyDocViewList} + childLayoutTemplate={() => Cast(doc.childLayoutTemplate, Doc, null)} + isContentActive={emptyFunction} + isAnyChildContentActive={() => true} + select={emptyFunction} + isSelected={returnFalse} + fieldKey={Doc.LayoutFieldKey(doc)} + addDocument={returnFalse} + moveDocument={returnFalse} + removeDocument={returnFalse} + PanelWidth={() => this._menuDimensions.width - 10} + PanelHeight={() => this._menuDimensions.height - 60} + ScreenToLocalTransform={() => new Transform(-this._pageX - 5,-this._pageY - 35, 1)} + renderDepth={5} + whenChildContentsActiveChanged={emptyFunction} + focus={emptyFunction} + styleProvider={DefaultStyleProvider} + addDocTab={this._props.addDocTab} + // eslint-disable-next-line no-use-before-define + pinToPres={() => undefined} + childFilters={returnEmptyFilter} + childFiltersByRanges={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} + fitContentsToBox={returnTrue} + xPadding={0} + yPadding={0} + /> + {/* <div className="docCreatorMenu-zoom-button-container"> <button className="docCreatorMenu-zoom-button" onPointerDown={e => this.setUpButtonClick(e, () => runInAction(() => (this._layoutPreviewScale *= 1.25)))}> <FontAwesomeIcon icon={'minus'} /> </button> @@ -1255,7 +1355,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { )) )} </div> - } + } */} </div> ); }; @@ -1271,7 +1371,10 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { onPointerDown={e => this.setUpButtonClick(e, () => { specialFunc?.(); - runInAction(() => (this._layout.type = option)); + runInAction(() => { + this._layout.type = option; + this.updateRenderedDocCollection(); + }); }) }> {option} @@ -1304,12 +1407,13 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { <div className="docCreatorMenu-dropdown-hoverable"> <div className="docCreatorMenu-option-title">{this._layout.type ? this._layout.type.toUpperCase() : 'Choose Layout'}</div> <div className="docCreatorMenu-dropdown-content"> - {layoutOption(LayoutType.Stacked)} - {layoutOption(LayoutType.Grid, undefined, () => { + {layoutOption(LayoutType.STACKED)} + {layoutOption(LayoutType.GRID, undefined, () => { if (!this._layout.columns) this._layout.columns = Math.ceil(Math.sqrt(this.docsToRender.length)); })} {layoutOption(LayoutType.Row)} {layoutOption(LayoutType.Column)} + {layoutOption(LayoutType.CAROUSEL3D)} {layoutOption(LayoutType.Custom, { borderBottom: `0px` })} </div> </div> @@ -1367,7 +1471,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> { clickEv.stopPropagation(); if (!this._selectedTemplate) return; const templateInfo: DataVizTemplateInfo = { doc: this._selectedTemplate, layout: this._layout, referencePos: { x: this._pageX + 450, y: this._pageY }, columns: this.columnsCount }; - this._dataViz?.createDocsFromTemplate(templateInfo); + this._fullyRenderedDocs = this._dataViz?.createDocsFromTemplate(templateInfo) ?? []; }, 'make docs') ) }> @@ -1642,105 +1746,40 @@ type FieldSettings = { tl: [number, number]; br: [number, number]; opts: FieldOpts; - subfields?: Field[]; + subfields?: FieldSettings[]; types?: TemplateFieldType[]; sizes?: TemplateFieldSize[]; + isDecoration?: boolean; description?: string; }; -interface ConstructedField { - renderToDoc: (content: FieldType, doc: Doc) => Doc; - validSubfieldGroups: () => Field[]; -} - -class Field { - settings: FieldSettings; - parent: Field; - - constructor(settings: FieldSettings, parent: Field, ) { - this.settings = settings; - this.parent = parent; - } - - private calculateFontSize = (contWidth: number, contHeight: number, text: string, uppercase: boolean): number => { - const words: string[] = text.split(/\s+/).filter(Boolean); - - let currFontSize = 1; - let rowsCount = 1; - let currTextHeight = currFontSize * rowsCount * 2; - - while (currTextHeight <= contHeight) { - let wordIndex = 0; - let currentRowWidth = 0; - let wordsInCurrRow = 0; - rowsCount = 1; - - while (wordIndex < words.length) { - const word = words[wordIndex]; - const wordWidth = word.length * currFontSize * 0.5; - //console.log(wordWidth) - - if (currentRowWidth + wordWidth <= contWidth) { - currentRowWidth += wordWidth; - ++wordsInCurrRow; - } else { - if (words.length !== 1 && words.length > wordsInCurrRow) { - rowsCount++; - currentRowWidth = wordWidth; - wordsInCurrRow = 1; - } else { - break; - } - } - - wordIndex++; - } - - currTextHeight = rowsCount * currFontSize * 2; - - currFontSize += 1; - } - - return currFontSize - 1; - }; - - private getDimensions = (coords: { tl: [number, number]; br: [number, number] }, parentWidth: number, parentHeight: number): { width: number; height: number; coord: { x: number; y: number } } => { - const l = (coords.tl[0] * parentHeight) / 2; - const t = coords.tl[1] * parentWidth / 2; //prettier-ignore - const r = (coords.br[0] * parentHeight) / 2; - const b = coords.br[1] * parentWidth / 2; //prettier-ignore - const width = r - l; - const height = b - t; - const coord = { x: l, y: t }; - return { width, height, coord }; - }; - - private docWithBasicOpts = (factory: (children: unknown, options: DocumentOptions) => Doc, settings: FieldSettings): Doc => { - const x = settings.tl[0]; - const y = settings.tl[1]; - const height = settings. - return factory([], {...}) - } -} - -class TextField implements Field { - settings: FieldSettings; - parent: Field; - - constructor(settings: FieldSettings, parent: Field) { - this.settings = settings; - this.parent = parent; - } - - renderToDoc = (content: FieldType, doc: Doc): Doc => { - - return new Doc; - } - - validSubfieldGroups = () => { - return []; - } -} +// class ContentField implements Field { +// tl: [number, number]; +// br: [number, number]; +// opts: FieldOpts; +// subfields?: Field[]; +// types?: TemplateFieldType[]; +// sizes?: TemplateFieldSize[]; +// description?: string; + +// constructor( tl: [number, number], br: [number, number], +// opts: FieldOpts, subfields?: Field[], +// types?: TemplateFieldType[], +// sizes?: TemplateFieldSize[], +// description?: string) { +// this.tl = tl; +// this.br = br; +// this.opts = opts; +// this.subfields = subfields; +// this.types = types; +// this.sizes = sizes; +// this.description = description; +// } + +// render = (content: any): Doc => { +// return new Doc; +// } +// } type DecorationField = FieldSettings; @@ -1954,6 +1993,66 @@ export class TemplateLayouts { ], }; + // public static FourField003: TemplateDocInfos = { + // title: 'fourfield3', + // width: 477, + // height: 662, + // opts: { + // backgroundColor: '#9E9C95' + // }, + // fields: [{ + // tl: [-.875, -.9], + // br: [.875, .7], + // types: [TemplateFieldType.VISUAL], + // sizes: [TemplateFieldSize.LARGE, TemplateFieldSize.HUGE], + // description: '', + // opts: { + // borderWidth: '15', + // borderColor: '#E0E0DA', + // } + // }, { + // tl: [-.95, .8], + // br: [-.1, .95], + // types: [TemplateFieldType.TEXT], + // sizes: [TemplateFieldSize.TINY, TemplateFieldSize.SMALL], + // description: '', + // opts: { + // backgroundColor: 'transparent', + // color: 'white', + // contentXCentering: 'h-right', + // } + // }, { + // tl: [.1, .8], + // br: [.95, .95], + // types: [TemplateFieldType.TEXT], + // sizes: [TemplateFieldSize.TINY, TemplateFieldSize.SMALL], + // description: '', + // opts: { + // backgroundColor: 'transparent', + // color: 'red', + // fontTransform: 'uppercase', + // contentXCentering: 'h-left' + // } + // }, { + // tl: [0, -.9], + // br: [.85, -.66], + // types: [TemplateFieldType.TEXT, TemplateFieldType.VISUAL], + // sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE], + // description: '', + // opts: { + // backgroundColor: 'transparent', + // contentXCentering: 'h-right' + // } + // }], + // decorations: [{ + // tl: [-.025, .8], + // br: [.025, .95], + // opts: { + // backgroundColor: '#E0E0DA', + // } + // }] + // }; + public static FourField004: TemplateDocInfos = { title: 'fourfield4', width: 414, @@ -2232,18 +2331,9 @@ export class FieldUtils { return { width, height, coord }; }; - public static docWithBasicOpts = (factory: (children: unknown, options: DocumentOptions) => Doc, settings: FieldSettings): Doc => { - const x = settings.tl[0]; - const y = settings.tl[1]; - const height = settings. - return factory([], {...}) - } - public static FreeformField = (coords: { tl: [number, number]; br: [number, number] }, parentWidth: number, parentHeight: number, title: string, content: string, opts: FieldOpts) => { const { width, height, coord } = FieldUtils.getDimensions(coords, parentWidth, parentHeight); - - const docWithBasicOpts = Docs.Create.FreeformDocument([], { isDefaultTemplateDoc: true, _height: height, @@ -2325,4 +2415,50 @@ export class FieldUtils { }; } - +// public static FourField002: TemplateDocInfos = { +// width: 450, +// height: 600, +// fields: [{ +// tl: [-.6, -.9], +// br: [.6, -.8], +// types: [FieldType.TEXT], +// sizes: [FieldSize.TINY] +// }, { +// tl: [-.9, -.7], +// br: [.9, .2], +// types: [FieldType.TEXT, FieldType.VISUAL], +// sizes: [FieldSize.MEDIUM, FieldSize.LARGE, FieldSize.HUGE] +// }, { +// tl: [-.9, .3], +// br: [-.05, .9], +// types: [FieldType.TEXT], +// sizes: [FieldSize.TINY] +// }, { +// tl: [.05, .3], +// br: [.9, .9], +// types: [FieldType.TEXT, FieldType.VISUAL], +// sizes: [FieldSize.MEDIUM, FieldSize.LARGE, FieldSize.HUGE] +// }] +// }; + +// public static TwoFieldPlusCarousel: TemplateDocInfos = { +// width: 500, +// height: 600, +// fields: [{ +// tl: [-.9, -.99], +// br: [.9, -.7], +// types: [FieldType.TEXT], +// sizes: [FieldSize.TINY] +// }, { +// tl: [-.9, -.65], +// br: [.9, .35], +// types: [], +// sizes: [] +// }, { +// tl: [-.9, .4], +// br: [.9, .95], +// types: [FieldType.TEXT], +// sizes: [FieldSize.TINY] +// }] +// }; +// }
\ No newline at end of file |