aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/documents/Documents.ts1
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx428
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DecorationField.tsx35
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DynamicField.tsx178
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/Field.tsx283
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/FieldUtils.tsx52
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/StaticContentField.tsx104
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/StaticField.tsx147
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.tsx70
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateBackend.tsx187
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateManager.tsx12
-rw-r--r--src/fields/Doc.ts2
12 files changed, 864 insertions, 635 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 317bb7feb..f5ea849ae 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -290,6 +290,7 @@ export class DocumentOptions {
_layout_showSidebar?: BOOLt = new BoolInfo('whether an annotationsidebar should be displayed for text docuemnts');
_layout_showCaption?: string; // which field to display in the caption area. leave empty to have no caption
_layout_showTags?: BOOLt = new BoolInfo('whether to show the list of document tags at the bottom of a DocView');
+ _layout_hideScroll?: BOOLt = new BoolInfo('whether to hide scroll bars on the document');
_chromeHidden?: BOOLt = new BoolInfo('whether the editing chrome for a document is hidden');
hideClickBehaviors?: BOOLt = new BoolInfo('whether to hide click behaviors in context menu');
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
index 64416c26d..9e5dbe967 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/DocCreatorMenu.tsx
@@ -1,5 +1,5 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Colors } from '@dash/components';
+import { Colors } from 'browndash-components';
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import { IDisposer } from 'mobx-utils';
@@ -7,7 +7,7 @@ import * as React from 'react';
import ReactLoading from 'react-loading';
import { ClientUtils, returnEmptyFilter, returnFalse, setupMoveUpEvents } from '../../../../../ClientUtils';
import { emptyFunction } from '../../../../../Utils';
-import { Doc, NumListCast, StrListCast, returnEmptyDoclist } from '../../../../../fields/Doc';
+import { Doc, DocListCast, FieldType, NumListCast, StrListCast, returnEmptyDoclist } from '../../../../../fields/Doc';
import { Id } from '../../../../../fields/FieldSymbols';
import { ImageCast, StrCast } from '../../../../../fields/Types';
import { ImageField } from '../../../../../fields/URLField';
@@ -28,7 +28,9 @@ import { Transform } from '../../../../util/Transform';
import { TemplateFieldSize, TemplateFieldType, TemplateLayouts } from './TemplateBackend';
import { TemplateManager } from './TemplateManager';
import { Template } from './Template';
-import { Field, FieldContentType } from './FieldTypes/Field';
+import { Field, ViewType } from './FieldTypes/Field';
+import { TabDocView } from '../../../collections/TabDocView';
+import { DocData } from '../../../../../fields/DocSymbols';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { Upload } from '../../../../../server/SharedMediaTypes';
@@ -72,18 +74,19 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
// eslint-disable-next-line no-use-before-define
static Instance: DocCreatorMenu;
+ private DEBUG_MODE: boolean = false;
+
private _disposers: { [name: string]: IDisposer } = {};
private _ref: HTMLDivElement | null = null;
private templateManager: TemplateManager;
- @observable _fullyRenderedDocs: Doc[] = [];
- @observable _renderedDocCollectionPreview: Doc | undefined = undefined;
- @observable _renderedDocCollection: Doc | undefined = undefined;
- @observable _docsRendering: boolean = false;
+ @observable _fullyRenderedDocs: Doc[] = []; // collection of templates filled in with content
+ @observable _renderedDocCollection: Doc | undefined = undefined; // fullyRenderedDocs in a parent collection
+ @observable _docsRendering: boolean = false; // dictates loading symbol
- @observable _userTemplates: { template: Template; doc: Doc }[] = []; //!!! used to keep track of all templates, should be refactored to work with actual templates and not docs
+ @observable _userTemplates: Template[] = [];
@observable _selectedTemplate: Template | undefined = undefined;
@observable _currEditingTemplate: Template | undefined = undefined;
@@ -91,15 +94,14 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
@observable _selectedCols: { title: string; type: string; desc: string }[] | undefined = [];
@observable _layout: { type: LayoutType; yMargin: number; xMargin: number; columns?: number; repeat: number } = { type: LayoutType.FREEFORM, yMargin: 10, xMargin: 10, columns: 3, repeat: 0 };
- @observable _layoutPreviewScale: number = 1;
@observable _savedLayouts: DataVizTemplateLayout[] = [];
@observable _expandedPreview: Doc | undefined = undefined;
@observable _suggestedTemplates: Template[] = [];
- @observable _suggestedTemplatePreviews: { doc: Doc; template: Template }[] = [];
@observable _GPTOpt: boolean = false;
@observable _callCount: number = 0;
@observable _GPTLoading: boolean = false;
+ @observable _DOCCC: Doc | undefined;
@observable _pageX: number = 0;
@observable _pageY: number = 0;
@@ -135,31 +137,26 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
this._dataViz = dataViz;
this._selectedTemplate = undefined;
this._renderedDocCollection = undefined;
- this._renderedDocCollectionPreview = undefined;
this._fullyRenderedDocs = [];
- this._suggestedTemplatePreviews = [];
this._suggestedTemplates = [];
this._userCreatedFields = [];
};
@action addUserTemplate = (template: Template) => {
- this._userTemplates.push({ template: template.cloneBase(), doc: template.getRenderedDoc() });
+ this._userTemplates.push(template);
};
@action removeUserTemplate = (template: Template) => {
- this._userTemplates = this._userTemplates.filter(info => info.template !== template);
- };
- @action updateTemplatePreview = (template: Template) => {
- template.renderUpdates();
- const preview = { template: template, doc: template.getRenderedDoc() };
- this._suggestedTemplatePreviews = this._suggestedTemplatePreviews.map(t => { return t.template === preview.template ? preview : t }); //prettier-ignore
- this._userTemplates = this._userTemplates.map(t => { return t.template === preview.template ? preview : t }); //prettier-ignore
- };
+ this._userTemplates.splice(this._userTemplates.indexOf(template), 1);
+ }
@action setSuggestedTemplates = (templates: Template[]) => {
- this._suggestedTemplates = templates;
- this._suggestedTemplatePreviews = templates.map(template => {return {template: template, doc: template.getRenderedDoc()}}); //prettier-ignore
+ this._suggestedTemplates = templates; //prettier-ignore
};
@computed get docsToRender() {
- return this._selectedTemplate ? NumListCast(this._dataViz?.layoutDoc.dataViz_selectedRows) : [];
+ if (this.DEBUG_MODE) {
+ return [1, 2, 3, 4];
+ } else {
+ return this._selectedTemplate ? NumListCast(this._dataViz?.layoutDoc.dataViz_selectedRows) : [];
+ }
}
@computed get rowsCount() {
@@ -374,15 +371,20 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
return undefined;
}
+ @action updateRenderedPreviewCollection = async (template: Template) => {
+ this._fullyRenderedDocs = await this.createDocsFromTemplate(template) ?? [];
+ console.log(this._fullyRenderedDocs);
+ this.updateRenderedDocCollection();
+ }
+
@action updateSelectedTemplate = async (template: Template) => {
if (this._selectedTemplate === template) {
this._selectedTemplate = undefined;
return;
} else {
this._selectedTemplate = template;
- template.renderUpdates();
- this._fullyRenderedDocs = (await this.createDocsFromTemplate(template)) ?? [];
- this.updateRenderedDocCollection();
+ //template.renderUpdates();
+ this.updateRenderedPreviewCollection(template);
}
};
@@ -403,6 +405,34 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
Doc.UnBrushDoc(doc);
};
+ testTemplate = async () => {
+
+ this._suggestedTemplates = this.templateManager.templates; //prettier-ignore
+
+ //console.log(this.templateManager.templates)
+
+ // const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView;
+
+ // this.templateManager.templates.forEach(template => {
+ // const doc = template.mainField.renderedDoc();
+ // mainCollection.addDocument(doc);
+ // })
+
+ // this.forceUpdate();
+
+ // try {
+ // const res = await gptImageCall('Image of panda eating a cookie');
+
+ // if (res) {
+ // const result = await Networking.PostToServer('/uploadRemoteImage', { sources: res });
+
+ // console.log(result);
+ // }
+ // } catch (e) {
+ // console.log(e);
+ // }
+ };
+
@action addField = () => {
const newFields: Col[] = this._userCreatedFields.concat([{ title: '', type: TemplateFieldType.UNSET, desc: '', sizes: [] }]);
this._userCreatedFields = newFields;
@@ -515,7 +545,7 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
compileFieldDescriptions = (templates: Template[]): string => {
let descriptions: string = '';
templates.forEach(template => {
- descriptions += `---------- NEW TEMPLATE TO INCLUDE: The title is: ${template.mainField.getTitle()}. Its fields are: `;
+ descriptions += `---------- NEW TEMPLATE TO INCLUDE: The title is: ${template.title}. Its fields are: `;
descriptions += template.descriptionSummary;
});
@@ -555,15 +585,14 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
const brokenDownAssignments: [Template, { [fieldID: number]: Col }][] = [];
Object.entries(assignments).forEach(([tempTitle, assignment]) => {
- const template = templates.filter(t => t.mainField.getTitle() === tempTitle)[0];
+ const template = templates.filter(template => template.title === tempTitle)[0];
if (!template) return;
const toObj = Object.entries(assignment).reduce(
(a, [fieldID, colTitle]) => {
const col = this.getColByTitle(colTitle);
- if (!this._userCreatedFields.includes(col)) {
- // do the following for any fields not added by the user; will change in the future, for now only GPT content works with user-added fields
+ if (!this._userCreatedFields.includes(col)){ // do the following for any fields not added by the user; will change in the future, for now only GPT content works with user-added field
const field = template.getFieldByID(Number(fieldID));
- field.setContent(col.defaultContent ?? '', col.type === TemplateFieldType.VISUAL ? FieldContentType.IMAGE : FieldContentType.STRING);
+ field.setContent(col.defaultContent ?? '', col.type === TemplateFieldType.VISUAL ? ViewType.IMG : ViewType.TEXT);
field.setTitle(col.title);
} else {
a[Number(fieldID)] = this.getColByTitle(colTitle);
@@ -585,16 +614,25 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
};
generatePresetTemplates = async () => {
- this._dataViz?.updateColDefaults();
- const cols = this.fieldsInfos;
- const templates = this.templateManager.getValidTemplates(cols);
+ const templates: Template[] = [];
- const assignments: [Template, { [field: number]: Col }][] = await this.assignColsToFields(templates, cols);
+ if (this.DEBUG_MODE) {
+ templates.push(...this.templateManager.templates)
+ } else {
+ this._dataViz?.updateColDefaults();
+
+ const cols = this.fieldsInfos;
+ templates.push(...this.templateManager.getValidTemplates(cols));
+
+ const assignments: [Template, { [field: number]: Col }][] = await this.assignColsToFields(templates, cols);
- const renderedTemplatePromises: Promise<Template | undefined>[] = assignments.map(([template, asns]) => this.applyGPTContentToTemplate(template, asns));
+ const renderedTemplatePromises: Promise<Template | undefined>[] = assignments.map(([template, assignments]) => this.applyGPTContentToTemplate(template, assignments));
- await Promise.all(renderedTemplatePromises);
+ const renderedTemplates: (Template | undefined)[] = await Promise.all(renderedTemplatePromises);
+ }
+
+ templates.forEach(template => template.mainField.initializeDocument())
setTimeout(() => {
this.setSuggestedTemplates(templates);
@@ -607,8 +645,8 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
const url = await this.generateGPTImage(prompt);
const field: Field = template.getFieldByID(Number(fieldNum));
- field.setContent(url ?? '', FieldContentType.IMAGE);
- field.setTitle(column.title);
+ field.setContent(url ?? '', ViewType.IMG);
+ field.setTitle(col.title);
};
const fieldContent: string = template.compiledContent;
@@ -656,14 +694,16 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
const res = await gptAPICall(`${++this._callCount}: ${prompt}`, GPTCallType.FILL);
+ // console.log('prompt: ', prompt, ' response: ', res);
+
if (res) {
const assignments: { [title: string]: { number: string; content: string } } = JSON.parse(res);
Object.entries(assignments).forEach(([title, info]) => {
const field: Field = template.getFieldByID(Number(info.number));
const column = this.getColByTitle(title);
- field.setContent(info.content ?? '', FieldContentType.STRING);
- field.setTitle(column.title);
+ field.setContent(info.content ?? '', ViewType.TEXT);
+ field.setTitle(col.title);
});
}
} catch (err) {
@@ -691,61 +731,56 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
return values;
});
+
+ const processContent = async (content: {[title: string]: string}) => {
- const processContent = async (content: { [title: string]: string }) => {
- const templateCopy = template.cloneBase();
-
- fields
- .filter(title => title)
- .forEach(title => {
- const field = templateCopy.getFieldByTitle(title);
- if (field === undefined) {
- return;
- }
- field.setContent(content[title]);
- });
-
- const gptPromises = this._userCreatedFields
- .filter(field => field.type === TemplateFieldType.TEXT)
- .map(field => {
- const title = field.title;
- const templateField = templateCopy.getFieldByTitle(title);
- if (templateField === undefined) {
- return;
- }
- const templatefieldID = templateField.getID;
-
- return this.renderGPTTextCall(templateCopy, field, templatefieldID);
- });
+ const templateCopy = await template.cloneBase();
- const imagePromises = this._userCreatedFields
- .filter(field => field.type === TemplateFieldType.VISUAL)
- .map(field => {
- const title = field.title;
- const templateField = templateCopy.getFieldByTitle(title);
- if (templateField === undefined) {
- return;
- }
- const templatefieldID = templateField.getID;
-
- return this.renderGPTImageCall(templateCopy, field, templatefieldID);
- });
+ fields.filter(title => title).forEach(title => {
+ const field = templateCopy.getFieldByTitle(title);
+ if (field === undefined) return;
+ field.setContent(content[title], field.viewType);
+ });
+
+ const gptPromises = this._userCreatedFields.filter(field => field.type === TemplateFieldType.TEXT).map(field => {
+ const title = field.title;
+ const templateField = templateCopy.getFieldByTitle(title);
+ if (templateField === undefined) return;
+ const templatefieldID = templateField.getID;
+
+ return this.renderGPTTextCall(templateCopy, field, templatefieldID);
+ });
+ const imagePromises = this._userCreatedFields.filter(field => field.type === TemplateFieldType.VISUAL).map(field => {
+ const title = field.title;
+ const templateField = templateCopy.getFieldByTitle(title);
+ if (templateField === undefined) return;
+ const templatefieldID = templateField.getID;
+
+ return this.renderGPTImageCall(templateCopy, field, templatefieldID);
+ });
+
await Promise.all(gptPromises);
await Promise.all(imagePromises);
- return templateCopy.getRenderedDoc();
+ this._DOCCC = templateCopy.mainField.renderedDoc;
+ return templateCopy.mainField.renderedDoc;
};
+
+ let docs: Promise<Doc>[];
+ if (this.DEBUG_MODE) {
+ docs = [1, 2, 3, 4].map(() => processContent({}));
+ } else {
+ docs = rowContents.map(content => processContent(content));
+ }
- const promises = rowContents.map(content => processContent(content));
-
- const renderedDocs = await Promise.all(promises);
+ const renderedDocs = await Promise.all(docs);
- this._docsRendering = false;
+ this._docsRendering = false; // removes loading indicator
return renderedDocs;
- };
+ }
addRenderedCollectionToMainview = () => {
const collection = this._renderedDocCollection;
@@ -760,7 +795,7 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
@action setExpandedView = (template: Template | undefined) => {
if (template) {
this._currEditingTemplate = template;
- this._expandedPreview = template.mainField.renderedDoc(); //Docs.Create.FreeformDocument([doc], { _height: NumListCast(doc._height)[0], _width: NumListCast(doc._width)[0], title: ''});
+ this._expandedPreview = template.doc; //Docs.Create.FreeformDocument([doc], { _height: NumListCast(doc._height)[0], _width: NumListCast(doc._width)[0], title: ''});
} else {
this._currEditingTemplate = undefined;
this._expandedPreview = undefined;
@@ -799,24 +834,16 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
<div className="top-panel" />
{rendered}
<div className="right-buttons-panel">
- <button
- className="docCreatorMenu-menu-button section-reveal-options top-right"
- onPointerDown={e =>
- this.setUpButtonClick(e, () => {
- this._currEditingTemplate && this.updateTemplatePreview(this._currEditingTemplate);
- this.setExpandedView(undefined);
- })
- }>
+ <button className="docCreatorMenu-menu-button section-reveal-options top-right" onPointerDown={e => this.setUpButtonClick(e, () => {
+ if (!this._currEditingTemplate) return;
+ if (this._currEditingTemplate === this._selectedTemplate) {
+ this.updateRenderedPreviewCollection(this._currEditingTemplate);
+ }
+ this.setExpandedView(undefined);
+ })}>
<FontAwesomeIcon icon="minimize" />
</button>
- <button
- className="docCreatorMenu-menu-button section-reveal-options top-right-lower"
- onPointerDown={e =>
- this.setUpButtonClick(e, () => {
- this._currEditingTemplate?.resetToBase();
- this.setExpandedView(this._currEditingTemplate);
- })
- }>
+ <button className="docCreatorMenu-menu-button section-reveal-options top-right-lower" onPointerDown={e => this.setUpButtonClick(e, () => {this._currEditingTemplate?.printFieldInfo();/*this._currEditingTemplate?.resetToBase();*/ this.setExpandedView(this._currEditingTemplate);})}>
<FontAwesomeIcon icon="arrows-rotate" color="white" />
</button>
</div>
@@ -825,8 +852,36 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
}
get templatesPreviewContents() {
+
const GPTOptions = <div></div>;
+ const previewDoc = (doc: Doc, template: Template) =>
+ <DocumentView
+ Document={doc}
+ isContentActive={emptyFunction} // !!! should be return false
+ addDocument={returnFalse}
+ moveDocument={returnFalse}
+ removeDocument={returnFalse}
+ PanelWidth={() => this._selectedTemplate === template ? 104 : 111}
+ PanelHeight={() => this._selectedTemplate === template ? 104 : 111}
+ ScreenToLocalTransform={() => new Transform(-this._pageX - 5,-this._pageY - 35, 1)}
+ renderDepth={1}
+ 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={returnFalse}
+ fitWidth={returnFalse}
+ hideDecorations={true}
+ />
+
+ //<img className='docCreatorMenu-preview-image expanded' src={this._expandedPreview.icon!.url.href.replace(".png", "_o.png")} />
+
return (
<div className={`docCreatorMenu-templates-view`}>
{this._expandedPreview ? (
@@ -846,51 +901,30 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
<ReactLoading type="spin" color={StrCast(Doc.UserDoc().userVariantColor)} height={30} width={30} />
</div>
) : (
- this._suggestedTemplatePreviews.map(({ doc, template }) => (
- <div
- className="docCreatorMenu-preview-window"
- key="0"
- style={{
- border: this._selectedTemplate === template ? `solid 3px ${Colors.MEDIUM_BLUE}` : '',
- boxShadow: this._selectedTemplate === template ? `0 0 15px rgba(68, 118, 247, .8)` : '',
- }}
- onPointerDown={e => this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(template)))}>
- <button
- className="option-button left"
- onPointerDown={e =>
- this.setUpButtonClick(e, () => {
- this.setExpandedView(template);
- })
- }>
- <FontAwesomeIcon icon="magnifying-glass" color="white" />
- </button>
- <button className="option-button right" onPointerDown={e => this.setUpButtonClick(e, () => this.addUserTemplate(template))}>
- <FontAwesomeIcon icon="plus" color="white" />
- </button>
- <DocumentView
- Document={doc}
- isContentActive={emptyFunction} // !!! should be return false
- addDocument={returnFalse}
- moveDocument={returnFalse}
- removeDocument={returnFalse}
- PanelWidth={() => (this._selectedTemplate === template ? 104 : 111)}
- PanelHeight={() => (this._selectedTemplate === template ? 104 : 111)}
- ScreenToLocalTransform={() => new Transform(-this._pageX - 5, -this._pageY - 35, 1)}
- renderDepth={1}
- whenChildContentsActiveChanged={emptyFunction}
- focus={emptyFunction}
- styleProvider={DefaultStyleProvider}
- addDocTab={this._props.addDocTab}
- pinToPres={() => undefined}
- childFilters={returnEmptyFilter}
- childFiltersByRanges={returnEmptyFilter}
- searchFilterDocs={returnEmptyDoclist}
- fitContentsToBox={returnFalse}
- fitWidth={returnFalse}
- hideDecorations={true}
- />
- </div>
- ))
+ this._suggestedTemplates
+ .map(template => (
+ <div
+ className="docCreatorMenu-preview-window"
+ style={{
+ border: this._selectedTemplate === template ? `solid 3px ${Colors.MEDIUM_BLUE}` : '',
+ boxShadow: this._selectedTemplate === template ? `0 0 15px rgba(68, 118, 247, .8)` : '',
+ }}
+ onPointerDown={e => this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(template)))}>
+ <button
+ className="option-button left"
+ onPointerDown={e =>
+ this.setUpButtonClick(e, () => {
+ this.setExpandedView(template);
+ })
+ }>
+ <FontAwesomeIcon icon="magnifying-glass" color="white" />
+ </button>
+ <button className="option-button right" onPointerDown={e => this.setUpButtonClick(e, () => this.addUserTemplate(template))}>
+ <FontAwesomeIcon icon="plus" color="white" />
+ </button>
+ {previewDoc(template.getRenderedDoc(), template)}
+ </div>
+ ))
)}
</div>
<div className="docCreatorMenu-GPT-options">
@@ -914,51 +948,30 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
<div className="docCreatorMenu-preview-window empty">
<FontAwesomeIcon icon="plus" color="rgb(160, 160, 160)" />
</div>
- {this._userTemplates.map(({ template, doc }) => (
- <div
- className="docCreatorMenu-preview-window"
- key="0"
- style={{
- border: this._selectedTemplate === template ? `solid 3px ${Colors.MEDIUM_BLUE}` : '',
- boxShadow: this._selectedTemplate === template ? `0 0 15px rgba(68, 118, 247, .8)` : '',
- }}
- onPointerDown={e => this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(template)))}>
- <button
- className="option-button left"
- onPointerDown={e =>
- this.setUpButtonClick(e, () => {
- this.setExpandedView(template);
- })
- }>
- <FontAwesomeIcon icon="magnifying-glass" color="white" />
- </button>
- <button className="option-button right" onPointerDown={e => this.setUpButtonClick(e, () => this.removeUserTemplate(template))}>
- <FontAwesomeIcon icon="minus" color="white" />
- </button>
- <DocumentView
- Document={doc}
- isContentActive={emptyFunction} // !!! should be return false
- addDocument={returnFalse}
- moveDocument={returnFalse}
- removeDocument={returnFalse}
- PanelWidth={() => (this._selectedTemplate === template ? 104 : 111)}
- PanelHeight={() => (this._selectedTemplate === template ? 104 : 111)}
- ScreenToLocalTransform={() => new Transform(-this._pageX - 5, -this._pageY - 35, 1)}
- renderDepth={1}
- whenChildContentsActiveChanged={emptyFunction}
- focus={emptyFunction}
- styleProvider={DefaultStyleProvider}
- addDocTab={this._props.addDocTab}
- pinToPres={() => undefined}
- childFilters={returnEmptyFilter}
- childFiltersByRanges={returnEmptyFilter}
- searchFilterDocs={returnEmptyDoclist}
- fitContentsToBox={returnFalse}
- fitWidth={returnFalse}
- hideDecorations={true}
- />
- </div>
- ))}
+ {this._userTemplates
+ .map(template => (
+ <div
+ className="docCreatorMenu-preview-window"
+ style={{
+ border: this._selectedTemplate === template ? `solid 3px ${Colors.MEDIUM_BLUE}` : '',
+ boxShadow: this._selectedTemplate === template ? `0 0 15px rgba(68, 118, 247, .8)` : '',
+ }}
+ onPointerDown={e => this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(template)))}>
+ <button
+ className="option-button left"
+ onPointerDown={e =>
+ this.setUpButtonClick(e, () => {
+ this.setExpandedView(template);
+ })
+ }>
+ <FontAwesomeIcon icon="magnifying-glass" color="white" />
+ </button>
+ <button className="option-button right" onPointerDown={e => this.setUpButtonClick(e, () => this.removeUserTemplate(template))}>
+ <FontAwesomeIcon icon="minus" color="white" />
+ </button>
+ {previewDoc(template.getRenderedDoc(), template)}
+ </div>
+ ))}
</div>
</div>
</div>
@@ -1017,13 +1030,11 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
collection._height = verticalSpan;
collection._width = horizontalSpan;
- 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 columns: number = this._layout.columns ?? this.columnsCount;
+ const xGap: number = this._layout.xMargin;
+ const yGap: number = this._layout.yMargin;
+ 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);
@@ -1070,8 +1081,6 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
updateRenderedDocCollection = () => {
if (!this._fullyRenderedDocs) return;
- const { horizontalSpan, verticalSpan } = this.previewInfo;
-
const collectionFactory = (): ((docs: Doc[], options: DocumentOptions) => Doc) => {
switch (this._layout.type) {
case LayoutType.CAROUSEL3D:
@@ -1089,18 +1098,25 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
}
};
- const collection: Doc = collectionFactory()(this._fullyRenderedDocs, {
+ const collection = collectionFactory()([this._fullyRenderedDocs[6], this._fullyRenderedDocs[9]], {
isDefaultTemplateDoc: true,
- _height: verticalSpan,
- _width: horizontalSpan,
title: 'title',
backgroundColor: 'gray',
+ x: 200,
+ y: 200,
+ _width: 4000,
+ _height: 4000,
});
this.applyLayout(collection, this._fullyRenderedDocs);
this._renderedDocCollection = collection;
- };
+
+ const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView;
+ mainCollection.addDocument(collection);
+
+ console.log('changed to: ', collection);
+ }
layoutPreviewContents = () => {
return this._docsRendering ? (
@@ -1109,7 +1125,7 @@ export class DocCreatorMenu extends ObservableReactComponent<DocCreateMenuProps>
<ReactLoading type="spin" color={StrCast(Doc.UserDoc().userVariantColor)} height={30} width={30} />
</div>
</div>
- ) : !this._renderedDocCollection ? null : (
+ ) : !this._renderedDocCollection ? null : (
<div className="docCreatorMenu-layout-preview-window-wrapper">
<DocumentView
Document={this._renderedDocCollection}
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DecorationField.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DecorationField.tsx
new file mode 100644
index 000000000..62f5504a8
--- /dev/null
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DecorationField.tsx
@@ -0,0 +1,35 @@
+import { Doc, DocListCast } from "../../../../../../fields/Doc";
+import { Docs, DocumentOptions } from "../../../../../documents/Documents";
+import { Field, FieldDimensions, FieldSettings, ViewType } from "./Field";
+import { RichTextField } from "../../../../../../fields/RichTextField";
+import { DocData } from "../../../../../../fields/DocSymbols";
+import { ImageField } from "../../../../../../fields/URLField";
+import { FieldUtils } from "./FieldUtils";
+
+export class DecorationField extends Field {
+
+ protected content: string = '';
+ protected subfields: Field[];
+
+ protected Document: Doc;
+
+ constructor(settings: FieldSettings, id: number, parent: Field) {
+ super(settings, id, FieldUtils.initField, parent);
+ this.subfields = this.setupSubfields(this);
+ this.Document = this.initializeDocument();
+ };
+
+ setContent = (content: string, type?: ViewType) => { return }
+ getContent = () => { return 'none'};
+ get isContentField(): boolean { return false };
+
+ initializeDocument = (): Doc => {
+ const renderedSubfields: Doc[] = this.subfields.map(field => field.renderedDoc);
+ this.settings.opts.title = this.title;
+ let doc: Doc = Docs.Create.FreeformDocument(renderedSubfields, this.settings.opts);
+
+ this.Document = doc;
+
+ return doc;
+ };
+} \ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DynamicField.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DynamicField.tsx
index c5254c17d..1970d1557 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DynamicField.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/DynamicField.tsx
@@ -1,117 +1,117 @@
-import { Doc } from "../../../../../../fields/Doc";
-import { Docs } from "../../../../../documents/Documents";
+import { makeAutoObservable, makeObservable, reaction } from "mobx";
+import { Doc, DocListCast } from "../../../../../../fields/Doc";
+import { Docs, DocumentOptions } from "../../../../../documents/Documents";
+import { Col } from "../DocCreatorMenu";
+import { TemplateLayouts } from "../TemplateBackend";
import { Field, FieldDimensions, FieldSettings, ViewType } from "./Field";
+import { IDisposer } from "mobx-utils";
import { FieldUtils } from "./FieldUtils";
-import { StaticField } from "./StaticField";
+import { random } from "lodash";
-export class DynamicField implements Field {
- private subfields: Field[] = [];
+export class DynamicField extends Field {
+ protected subfields: Field[];
- private id: number;
- private settings: FieldSettings;
- private title: string = '';
+ protected Document!: Doc;
- private parent: Field;
- private dimensions: FieldDimensions;
+ private idd: number;
constructor(settings: FieldSettings, id: number, parent?: Field) {
- this.id = id;
- this.settings = settings;
- if (settings.title) { this.title = settings.title };
- if (!parent) {
- this.parent = this;
- this.dimensions = {width: this.settings.br[0] - this.settings.tl[0], height: this.settings.br[1] - this.settings.tl[1], coord: {x: this.settings.tl[0], y: this.settings.tl[1]}};
- } else {
- this.parent = parent;
- this.dimensions = FieldUtils.getLocalDimensions({tl: settings.tl, br: settings.br}, this.parent.getDimensions);
- }
- this.subfields = this.setupSubfields();
+ super(settings, id, FieldUtils.initField, parent);
+ this.subfields = this.setupSubfields(this);
+ this.initializeDocument();
+ this.idd = random(0, 1000);
}
- setContent = () => { return };
+ setContent = (content: string, type: ViewType) => { return };
getContent = () => { return '' };
+ get isContentField(): boolean { return false };
- setTitle = (title: string) => { this.title = title };
- getTitle = () => { return this.title };
-
- get getSubfields() { return this.subfields };
- get getAllSubfields() {
- let fields: Field[] = [];
- this.subfields?.forEach(field => {
- fields.push(field);
- fields = fields.concat(field.getAllSubfields)
- });
- return fields;
- };
-
- get getDimensions() { return this.dimensions };
- get getID() { return this.id };
- get getViewType() { return this.settings.viewType };
-
- get getDescription(): string {
- return this.settings.description ?? '';
+ addChildToDocument = (doc: Doc) => {
+ Doc.SetContainer(doc, this.Document);
}
matches = (): Array<number> => {
return [];
}
- updateRenderedDoc = () => {
- return new Doc();
- }
-
- setupSubfields = (): Field[] => {
- const fields: Field[] = [];
- this.settings.subfields?.forEach((fieldSettings, index) => {
- let field: Field;
- const type = fieldSettings.viewType;
-
- const id = Number(String(this.id) + String(index));
-
- if (type == ViewType.CAROUSEL3D || type === ViewType.FREEFORM) {
- field = new DynamicField(fieldSettings, id, this);
- } else {
- field = new StaticField(fieldSettings, this, id);
- }
- fields.push(field);
- });
- return fields;
+ makeClone = async (subfields: boolean = false): Promise<Field> => {
+ const newSettings: FieldSettings = this.settings;
+ if (!subfields) newSettings.subfields = [];
+ const field: DynamicField = this.initField(newSettings, this.id, this.parent, true) as DynamicField;
+ //field.Document = (await Doc.MakeClone(this.Document)).clone;
+ return field
}
- applyAttributes = (field: Field) => {
- field.setTitle(this.title);
- field.updateRenderedDoc(this.renderedDoc());
- }
-
- getChildDimensions = (coords: { tl: [number, number]; br: [number, number] }): FieldDimensions => {
- const l = (coords.tl[0] * this.dimensions.height) / 2;
- const t = coords.tl[1] * this.dimensions.width / 2; //prettier-ignore
- const r = (coords.br[0] * this.dimensions.height) / 2;
- const b = coords.br[1] * this.dimensions.width / 2; //prettier-ignore
- const width = r - l;
- const height = b - t;
- const coord = { x: l, y: t };
- return { width, height, coord };
- };
-
- renderedDoc = (): Doc => {
+ initializeDocument = (oldOpts?: DocumentOptions): Doc => {
let doc: Doc;
+ //this.settings.opts.data = undefined;
+ const renderedSubfields: Doc[] = this.subfields.map(field => field.renderedDoc);
+ console.log('fields: ', renderedSubfields)
+ this.settings.opts.title = this.title;
switch (this.settings.viewType) {
case ViewType.CAROUSEL3D:
- doc = Docs.Create.Carousel3DDocument(this.subfields.map(field => field.renderedDoc()), {
- title: this.title,
- });
- FieldUtils.applyBasicOpts(doc, this.dimensions, this.settings);
- return doc;
+ doc = Docs.Create.Carousel3DDocument(renderedSubfields, this.settings.opts);
+ break;
case ViewType.FREEFORM:
- doc = Docs.Create.FreeformDocument(this.subfields.map(field => field.renderedDoc()), {
- title: this.title,
- });
- FieldUtils.applyBasicOpts(doc, this.dimensions, this.settings);
- return doc;
+ doc = Docs.Create.FreeformDocument(renderedSubfields, oldOpts ?? this.settings.opts);
+ break;
default:
- return new Doc();
+ doc = Docs.Create.FreeformDocument(renderedSubfields, this.settings.opts);
+ break;
}
+
+ this.Document = doc;
+ return doc;
}
}
+
+// export class DynamicField extends Field {
+// protected subfields: Field[];
+
+// protected Document!: Doc;
+
+// constructor(settings: FieldSettings, id: number, parent?: Field) {
+// super(settings, id, parent);
+// this.subfields = this.setupSubfields(this);
+// this.initializeDocument();
+// }
+
+// setContent = (content: string, type: ViewType) => { return };
+// getContent = () => { return '' };
+// get isContentField(): boolean { return false };
+
+// addChildToDocument = (doc: Doc) => {
+// Doc.SetContainer(doc, this.Document);
+// }
+
+// matches = (cols: Col[]): Array<number> => {
+// return [];
+// }
+
+// initializeDocument = (): Doc => {
+// let doc: Doc;
+// const renderedSubfields: Doc[] = this.subfields.map(field => field.renderedDoc);
+// switch (this.settings.viewType) {
+// case ViewType.CAROUSEL3D:
+// doc = Docs.Create.Carousel3DDocument(renderedSubfields, {
+// title: this.title,
+// });
+// break;
+// case ViewType.FREEFORM:
+// doc = Docs.Create.FreeformDocument(renderedSubfields, {
+// title: this.title,
+// });
+// break;
+// default:
+// doc = Docs.Create.FreeformDocument(renderedSubfields, {
+// title: this.title,
+// });
+// break;
+// }
+
+// this.Document = doc;
+// return doc;
+// }
+
+// } \ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/Field.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/Field.tsx
index ea9b566b3..06b364254 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/Field.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/Field.tsx
@@ -1,44 +1,232 @@
-import { Doc } from "../../../../../../fields/Doc";
+import { computed, makeAutoObservable, makeObservable, reaction } from "mobx";
+import { Doc, DocListCast } from "../../../../../../fields/Doc";
import { Col } from "../DocCreatorMenu";
import { TemplateFieldSize, TemplateFieldType } from "../TemplateBackend";
+import { IDisposer } from "mobx-utils";
+import { DocumentType } from "../../../../../documents/DocumentTypes";
+import { Partial } from "@react-spring/web";
+import { DocumentOptions } from "../../../../../documents/Documents";
+import { List } from "../../../../../../fields/List";
+import { runInThisContext } from "vm";
+import { DocData } from "../../../../../../fields/DocSymbols";
+import { ObjectField } from "../../../../../../fields/ObjectField";
+import { ComputedField } from "../../../../../../fields/ScriptField";
+import { Copy } from "../../../../../../fields/FieldSymbols";
+import { OmitKeys } from "../../../../../../ClientUtils";
-export enum FieldContentType {
- STRING = 'string',
- IMAGE = 'image',
-}
+export abstract class Field {
-export enum ViewType {
- CAROUSEL3D = 'carousel3d',
- FREEFORM = 'freeform',
- STATIC = 'static',
- DEC = 'decoration'
-}
+ protected disposers: { [name: string]: IDisposer } = {};
+
+ protected initField: (settings: FieldSettings, index: number, parent: Field, sameId?: boolean) => Field;
-export type FieldDimensions = {
- width: number;
- height: number;
- coord: {x: number, y: number};
-}
+ protected abstract subfields: Field[];
+
+ protected abstract Document: Doc;
+
+ protected parent: Field;
+ protected id: number;
+ protected settings: FieldSettings;
+ protected title: string = '';
+ protected dimensions: FieldDimensions;
+
+ constructor(settings: FieldSettings, id: number, fieldFactory: (settings: FieldSettings, index: number, parent: Field) => Field, parent?: Field) {
+ this.initField = fieldFactory;
+ this.parent = parent ? parent : this;
+ this.id = id;
+ this.settings = settings;
+ this.title = settings.title ?? '';
+ this.dimensions = this.getLocalDimensions({tl: this.settings.tl, br: this.settings.br}, this.parent.getDimensions);
+ this.applyBasicOpts(this.dimensions, settings);
+
+ // this.disposers.fieldList = reaction(
+ // () => DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)]),
+ // docs => {
+ // console.log('updated')
+ // this.handleFieldUpdate(docs);
+ // }
+ // );
+ }
+
+ get getSubfields(): Field[] { return this.subfields ?? []; };
+ get getAllSubfields() {
+ let fields: Field[] = [];
+ this.subfields?.forEach(field => {
+ fields.push(field);
+ fields = fields.concat(field.getAllSubfields)
+ });
+ return fields;
+ };
+
+ setSubFields = (fields: Field[]) => {
+ this.subfields = fields;
+ }
+
+ get renderedDoc(){ return this.Document };
+ get getDimensions() { return this.dimensions };
+ get getID() { return this.id };
+ get getDescription(): string { return this.settings.description ?? '' };
+ get viewType(): ViewType { return this.settings.viewType }
+
+ setTitle = (title: string) => {
+ this.title = title;
+ this.Document.title = title;
+ };
+ getTitle = () => { return this.title };
+
+ abstract get isContentField(): boolean;
+ abstract setContent(content: string, type: ViewType): void;
+ abstract getContent(): string;
+
+ makeClone = async (subfields: boolean = false): Promise<Field> => {
+ const newSettings: FieldSettings = this.settings;
+ if (!subfields) newSettings.subfields = [];
+ newSettings.opts = this.documentOptions;
+ newSettings.title = this.title;
+ console.log('settings: ', newSettings.opts)
+ const field: Field = this.initField(newSettings, this.id, this.parent, true);
+ //field.Document = (await Doc.MakeClone(this.Document)).clone;
+ return field
+ }
+
+ @computed get documentOptions(): DocumentOptions {
+ const opts: DocumentOptions = {};
+ Object.assign(opts, this.Document[DocData]);
+ Object.entries(opts).forEach(([key, field]) => {
+ if (field instanceof ObjectField) {
+ Object.assign(opts, {[key]: ObjectField.MakeCopy(field)})
+ } else if (field instanceof ComputedField) {
+ Object.assign(opts, {[key]: field[Copy]()})
+ }
+ })
+ return opts
+ }
+
+ changeFieldType = (newType: ViewType): Field => {
+ const newField: Field = this.initField(this.settings, this.id, this.parent, true);
+ this.parent.exchangeFields(newField, this);
+ return newField;
+ }
+
+ exchangeFields = (newField: Field, oldField: Field) => {
+ this.subfields.splice(this.subfields.indexOf(oldField), 1, newField);
+ }
+
+ addFieldFromDoc = (doc: Doc) => {
+ const par = this.Document;
+ const settings: FieldSettings = {
+ tl: [Number(doc._x) / Number(par._width), Number(doc._y) / Number(par._height)],
+ br: [(Number(doc._x) + Number(doc._width)) / Number(par._width), (Number(doc._y) + Number(doc._height)) / Number(par._height)],
+ viewType: doc.type === DocumentType.COL ? ViewType.FREEFORM : ViewType.STATIC,
+ opts: {},
+ };
+
+ const newField: Field = this.initField(settings, this.subfields.length, this);
+ this.subfields.push(newField);
+ };
+
+ addField = (field: Field) => {
+ if (!this.subfields.includes(field)){
+ this.subfields.push(field);
+ console.log('field added')
+ // Doc.SetContainer(field.Document, this.Document);
+ }
+ }
+
+ removeField = (field: Field) => {
+ // var childDocs: Doc[] = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)]);
+ // this.Document[Doc.LayoutFieldKey(this.Document)] = new List<Doc>([...childDocs.splice(childDocs.indexOf(field.Document), 1)]);
+ this.subfields.splice(this.subfields.indexOf(field), 1);
+ field.dispose();
+ };
+
+ setupSubfields = (parent: Field): Field[] => {
+ return this.settings.subfields?.map((fieldSettings, index) => {
+ return this.initField(fieldSettings, index, parent);
+ }) || [];
+ }
+
+ applyAttributes(field: Field) {
+ field.setTitle(this.title);
+ field.initializeDocument();
+ field.subfields = this.subfields;
+ }
+
+ abstract initializeDocument(): void;
+
+ dispose = () => {
+ Object.values(this.disposers).forEach(disposer => disposer?.());
+ }
+
+ handleFieldUpdate = (newDocsList: Doc[]) => {
+ const currRenderedDocs: Set<Doc> = new Set();
+ this.subfields.forEach(field => currRenderedDocs.add(field.Document));
+ newDocsList.forEach(doc => {
+ if (!currRenderedDocs.has(doc)) {
+ this.addFieldFromDoc(doc);
+ }
+ });
+ currRenderedDocs.forEach(doc => {
+ if (!newDocsList.includes(doc)){
+ const fields = this.subfields.filter(field => field.Document === doc);
+ fields.forEach(field => this.removeField(field));
+ }
+ });
+ }
+
+ matches = (cols: Col[]): number[] => {
+ const colMatchesField = (col: Col) => {
+ const isMatch: boolean = (
+ this.settings.sizes?.some(size => col.sizes?.includes(size))
+ && this.settings.types?.includes(col.type))
+ ?? false;
+ return isMatch;
+ }
+
+ const matches: Array<number> = [];
+
+ cols.forEach((col, v) => {
+ if (colMatchesField(col)) {
+ matches.push(v);
+ }
+ });
+
+ return matches;
+ };
+
+ private getLocalDimensions = (coords: { tl: [number, number]; br: [number, number] }, parentDimensions: FieldDimensions): FieldDimensions => {
+ if (this.parent === this) {
+ return {width: coords.br[0] - coords.tl[0], height: coords.br[1] - coords.tl[1], coord: {x: coords.tl[0], y: coords.tl[1]}};
+ }
+ const l = (coords.tl[0] * parentDimensions.width) / 2;
+ const t = coords.tl[1] * parentDimensions.height / 2; //prettier-ignore
+ const r = (coords.br[0] * parentDimensions.width) / 2;
+ const b = coords.br[1] * parentDimensions.height / 2; //prettier-ignore
+ const width = r - l;
+ const height = b - t;
+ const coord = { x: l, y: t };
+ return { width, height, coord };
+ };
+
+ private applyBasicOpts = (dimensions: FieldDimensions, settings: FieldSettings) => {
+ const opts: DocumentOptions = settings.opts;
+ opts.isDefaultTemplateDoc ??= true;
+ opts._layout_hideScroll ??= true;
+ opts.x ??= dimensions.coord.x;
+ opts.y ??= dimensions.coord.y;
+ opts._height ??= dimensions.height;
+ opts._width ??= dimensions.width;
+ opts._nativeWidth ??= dimensions.width;
+ opts._nativeHeight ??= dimensions.height;
+ opts._layout_nativeDimEditable ??= true;
+ };
-export interface FieldOpts {
- backgroundColor?: string;
- color?: string;
- cornerRounding?: number;
- borderWidth?: string;
- borderColor?: string;
- contentXCentering?: 'h-left' | 'h-center' | 'h-right';
- contentYCentering?: 'top' | 'center' | 'bottom';
- opacity?: number;
- rotation?: number;
- fontBold?: boolean;
- fontTransform?: 'uppercase' | 'lowercase';
- fieldViewType?: 'freeform' | 'stacked';
}
export type FieldSettings = {
tl: [number, number];
br: [number, number];
- opts: FieldOpts;
+ opts: DocumentOptions;
viewType: ViewType;
title?: string;
subfields?: FieldSettings[];
@@ -47,20 +235,21 @@ export type FieldSettings = {
description?: string;
};
-export interface Field {
- getContent: () => string;
- setContent: (content: string, type?: FieldContentType) => void;
- getDimensions: FieldDimensions;
- getSubfields: Field[];
- getAllSubfields: Field[];
- getID: number;
- getViewType: ViewType;
- getDescription: string;
- getTitle: () => string;
- setTitle: (title: string) => void;
- setupSubfields: () => Field[];
- applyAttributes: (field: Field) => void;
- renderedDoc: () => Doc;
- matches: (cols: Col[]) => number[];
- updateRenderedDoc: (oldDoc?: Doc) => Doc;
-} \ No newline at end of file
+export enum ViewType {
+ CAROUSEL3D = 'carousel3d',
+ FREEFORM = 'freeform',
+ STATIC = 'static',
+ DEC = 'decoration',
+ IMG = 'image',
+ TEXT = 'text',
+}
+
+export type FieldDimensions = {
+ width: number;
+ height: number;
+ coord: {x: number, y: number};
+}
+
+export type FieldTree = {
+ node: {field: Field, subfields: FieldTree[]}
+}
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/FieldUtils.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/FieldUtils.tsx
index 3886774d2..eb12bfef9 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/FieldUtils.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/FieldUtils.tsx
@@ -1,40 +1,24 @@
-import { Doc } from "../../../../../../fields/Doc";
-import { ComputedField, ScriptField } from "../../../../../../fields/ScriptField";
-import { Col } from "../DocCreatorMenu";
-import { TemplateFieldSize, TemplateFieldType, TemplateLayouts } from "../TemplateBackend";
-import { FieldDimensions, FieldSettings } from "./Field";
+import { DynamicField } from "./DynamicField";
+import { Field, FieldSettings, ViewType } from "./Field";
+import { TextTemplateField, ImageTemplateField } from "./StaticContentField";
+import { DecorationField } from "./DecorationField";
export class FieldUtils {
- public static getLocalDimensions = (coords: { tl: [number, number]; br: [number, number] }, parentDimensions: FieldDimensions): FieldDimensions => {
- const l = (coords.tl[0] * parentDimensions.width) / 2;
- const t = coords.tl[1] * parentDimensions.height / 2; //prettier-ignore
- const r = (coords.br[0] * parentDimensions.width) / 2;
- const b = coords.br[1] * parentDimensions.height / 2; //prettier-ignore
- const width = r - l;
- const height = b - t;
- const coord = { x: l, y: t };
- return { width, height, coord };
- };
- public static applyBasicOpts = (doc: Doc, parentDimensions: FieldDimensions, settings: FieldSettings, oldDoc?: Doc) => {
- const opts = settings.opts;
- doc.isDefaultTemplateDoc = oldDoc ? oldDoc.isDefaultTemplateDoc : true;
- doc._layout_hideScroll = oldDoc ? oldDoc._layout_hideScroll : true;
- doc.x = oldDoc ? oldDoc.x : parentDimensions.coord.x;
- doc.y = oldDoc ? oldDoc.y : parentDimensions.coord.y;
- doc._height = oldDoc ? oldDoc.height : parentDimensions.height;
- doc._width = oldDoc ? oldDoc.width : parentDimensions.width;
- doc.backgroundColor = oldDoc ? oldDoc.backgroundColor : opts.backgroundColor ?? '';
- doc._layout_borderRounding = !opts.cornerRounding ? '0px' : ScriptField.MakeFunction(`${opts.cornerRounding} * this.width + 'px'`);
- doc.borderColor = oldDoc ? oldDoc.borderColor : opts.borderColor;
- doc.borderWidth = oldDoc ? oldDoc.borderWidth : opts.borderWidth;
- doc.opacity = oldDoc ? oldDoc.opacity : opts.opacity;
- doc._rotation = oldDoc ? oldDoc._rotation : opts.rotation;
- doc.hCentering = oldDoc ? oldDoc.hCentering : opts.contentXCentering;
- doc.nativeWidth = parentDimensions.width;
- doc.nativeHeight = parentDimensions.height;
- doc._layout_nativeDimEditable = true;
- };
+ public static initField = (settings: FieldSettings, index: number, parent: Field, sameId: boolean = false): Field => {
+ const id = sameId ? index : Number(`${parent.getID}${index}`);
+ switch (settings.viewType) {
+ case ViewType.FREEFORM: case ViewType.CAROUSEL3D:
+ return new DynamicField(settings, id, parent);
+ case ViewType.IMG:
+ return new ImageTemplateField(settings, id, parent);
+ case ViewType.TEXT:
+ return new TextTemplateField(settings, id, parent);
+ case ViewType.DEC:
+ return new DecorationField(settings, id, parent);
+ }
+ return new TextTemplateField(settings, id, parent);
+ }
public static calculateFontSize = (contWidth: number, contHeight: number, text: string, uppercase: boolean): number => {
const words: string[] = text.split(/\s+/).filter(Boolean);
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/StaticContentField.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/StaticContentField.tsx
new file mode 100644
index 000000000..18b72e4ea
--- /dev/null
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/StaticContentField.tsx
@@ -0,0 +1,104 @@
+import { Doc, DocListCast } from "../../../../../../fields/Doc";
+import { Docs, DocumentOptions } from "../../../../../documents/Documents";
+import { Field, FieldDimensions, FieldSettings, ViewType } from "./Field";
+import { RichTextField } from "../../../../../../fields/RichTextField";
+import { DocData } from "../../../../../../fields/DocSymbols";
+import { ImageField } from "../../../../../../fields/URLField";
+import { ViewComponentType } from "@fullcalendar/core";
+import { DynamicField } from "./DynamicField";
+import { FieldUtils } from "./FieldUtils";
+import { random } from "lodash";
+
+export abstract class StaticContentField extends Field {
+
+ protected content: string = '';
+ protected subfields: Field[];
+
+ protected Document: Doc;
+
+ protected idd: number;
+
+ constructor(settings: FieldSettings, id: number, parent: Field) {
+ super(settings, id, FieldUtils.initField, parent);
+ this.subfields = this.setupSubfields(this);
+ this.Document = this.initializeDocument();
+ this.idd = random(0, 1000);
+ };
+
+ abstract setContent(content: string, type?: ViewType): void;
+ getContent = () => { return this.content ?? 'unset'};
+ get isContentField(): boolean { return true };
+
+ abstract initializeDocument(): Doc;
+}
+
+export class ImageTemplateField extends StaticContentField {
+
+ setContent = (url: string, type?: ViewType) => {
+ this.settings.viewType = type ?? this.settings.viewType;
+
+ if (type === ViewType.IMG || type === undefined){
+ const imgField = new ImageField(url);
+ this.Document[DocData]['data'] = imgField;
+ this.content = url;
+ } else {
+ const updatedField = this.changeFieldType(type);
+ updatedField.setContent(url, type);
+ }
+ };
+
+ initializeDocument(): Doc {
+ this.settings.opts.title = this.title;
+ this.settings.opts._layout_fitWidth = false;
+
+ let doc: Doc = Docs.Create.ImageDocument(this.content, this.settings.opts);
+
+ return doc;
+ };
+}
+
+export class TextTemplateField extends StaticContentField {
+
+ setContent = (text: string, type?: ViewType) => {
+ this.settings.viewType = type ?? this.settings.viewType;
+
+ if (type === ViewType.TEXT || type === undefined) {
+ const rtf = {
+ doc: {
+ type: 'doc',
+ content: [
+ {
+ type: 'paragraph',
+ content: [
+ {
+ type: 'text',
+ text,
+ },
+ ],
+ },
+ ],
+ },
+ selection: { type: 'text', anchor: 1, head: 1 },
+ storedMarks: [],
+ };
+ this.content = text;
+ const field = new RichTextField(JSON.stringify(rtf), text);
+ this.Document[DocData]['text'] = field;
+ } else {
+ const updatedField = this.changeFieldType(type);
+ updatedField.setContent(text, type);
+ }
+ };
+
+ initializeDocument(): Doc {
+ const opts = this.settings.opts;
+ const text = this.content;
+
+ opts._text_fontSize = `${FieldUtils.calculateFontSize(this.dimensions.width, this.dimensions.height, text, true)}`;
+ opts.title = this.title;
+
+ let doc: Doc = Docs.Create.TextDocument(text, opts);
+
+ return doc;
+ };
+} \ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/StaticField.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/StaticField.tsx
deleted file mode 100644
index 47b43f051..000000000
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/FieldTypes/StaticField.tsx
+++ /dev/null
@@ -1,147 +0,0 @@
-import { Doc } from "../../../../../../fields/Doc";
-import { Docs } from "../../../../../documents/Documents";
-import { Col } from "../DocCreatorMenu";
-import { DynamicField } from "./DynamicField";
-import { FieldUtils } from "./FieldUtils";
-import { Field, FieldContentType, FieldDimensions, FieldSettings, ViewType } from "./Field";
-
-export class StaticField {
- private content: string;
- private contentType: FieldContentType | undefined;
- private subfields: Field[] = [];
- private renderedDocument: Doc;
-
- private id: number;
- private title: string = '';
-
- private settings: FieldSettings;
-
- private parent: Field;
- private dimensions: FieldDimensions;
-
- constructor(settings: FieldSettings, parent: Field, id: number) {
- this.settings = settings;
- if (settings.title) { this.title = settings.title };
- this.id = id;
- this.parent = parent;
- this.dimensions = FieldUtils.getLocalDimensions({tl: settings.tl, br: settings.br}, this.parent.getDimensions);
- this.content = '';
- this.subfields = this.setupSubfields();
- this.renderedDocument = this.updateRenderedDoc();
- };
-
- get getSubfields(): Field[] { return this.subfields ?? []; };
-
- get getAllSubfields(): Field[] {
- let fields: Field[] = [];
- this.subfields?.forEach(field => {
- fields.push(field);
- fields = fields.concat(field.getAllSubfields);
- });
- return fields;
- };
-
- get getDimensions() { return this.dimensions };
- get getID() { return this.id };
- get getViewType() { return this.settings.viewType };
-
- get getDescription(): string {
- return this.settings.description ?? '';
- }
-
- renderedDoc = () => {
- return this.renderedDocument;
- }
-
- setContent = (newContent: string, type?: FieldContentType) => {
- this.content = newContent;
- if (type) this.contentType = type;
- this.updateRenderedDoc(this.renderedDocument);
- };
- getContent() { return this.content };
-
- setTitle = (title: string) => {
- this.title = title;
- this.renderedDocument.title = title;
- this.updateRenderedDoc(this.renderedDocument);
- };
- getTitle = () => { return this.title };
-
- applyAttributes = (field: Field) => { //!!! can be updated later for more robust clonign; this is all ythat's needed now
- field.setTitle(this.title);
- field.setContent('', this.contentType);
- field.updateRenderedDoc(this.renderedDoc());
- }
-
- setupSubfields = (): Field[] => {
- const fields: Field[] = [];
- this.settings.subfields?.forEach((fieldSettings, index) => {
- let field: Field;
- const type = fieldSettings.viewType;
-
- const id = Number(String(this.id) + String(index));
-
- if (type === ViewType.FREEFORM || type === ViewType.CAROUSEL3D) {
- field = new DynamicField(fieldSettings, id, this);
- } else {
- field = new StaticField(fieldSettings, this, id);
- };
-
- fields.push(field);
- });
- return fields;
- };
-
- matches = (cols: Col[]): number[] => {
- const colMatchesField = (col: Col) => {
- const isMatch: boolean = (
- this.settings.sizes?.some(size => col.sizes?.includes(size))
- && this.settings.types?.includes(col.type))
- ?? false;
- return isMatch;
- }
-
- const matches: Array<number> = [];
-
- cols.forEach((col, v) => {
- if (colMatchesField(col)) {
- matches.push(v);
- }
- });
-
- return matches;
- };
-
- updateRenderedDoc = (oldDoc?: Doc): Doc => {
- const opts = this.settings.opts;
-
- if (!this.contentType) { this.contentType = FieldContentType.STRING };
-
- let doc: Doc;
-
- switch (this.contentType) {
- case FieldContentType.STRING:
- doc = Docs.Create.TextDocument(String(this.content), {
- title: this.title,
- text_fontColor: oldDoc ? String(oldDoc.color) : opts.color,
- contentBold: oldDoc ? Boolean(oldDoc.fontBold) : opts.fontBold,
- textTransform: oldDoc ? String(oldDoc.fontTransform) : opts.fontTransform,
- color: oldDoc ? String(oldDoc.color) : opts.color,
- _text_fontSize: `${FieldUtils.calculateFontSize(this.dimensions.width, this.dimensions.height, String(this.content), true)}`
- });
- FieldUtils.applyBasicOpts(doc, this.dimensions, this.settings, oldDoc);
- break;
- case FieldContentType.IMAGE:
- doc = Docs.Create.ImageDocument(String(this.content), {
- title: this.title,
- _layout_fitWidth: false,
- });
- FieldUtils.applyBasicOpts(doc, this.dimensions, this.settings, oldDoc);
- break;
- }
-
- this.renderedDocument = doc;
-
- return doc;
- };
-} \ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.tsx
index 0a5097d4a..bdfedbdc9 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/Template.tsx
@@ -1,43 +1,64 @@
import { Doc, FieldType } from "../../../../../fields/Doc";
+
+import { makeAutoObservable, reaction } from "mobx";
+import { Doc, DocListCast, FieldType } from "../../../../../fields/Doc";
+import { Docs } from "../../../../documents/Documents";
import { Col } from "./DocCreatorMenu";
import { DynamicField } from "./FieldTypes/DynamicField";
-import { Field, FieldSettings, ViewType } from "./FieldTypes/Field";
+import { Field, FieldSettings, FieldTree, ViewType } from "./FieldTypes/Field";
import { } from "./FieldTypes/FieldUtils";
import { } from "./FieldTypes/StaticField";
+import { TemplateLayouts } from "./TemplateBackend";
export class Template {
mainField: DynamicField;
- settings: FieldSettings;
+ private settings: FieldSettings;
constructor(templateInfo: FieldSettings) {
- this.mainField = this.setupMainField(templateInfo);
+ makeAutoObservable(this);
this.settings = templateInfo;
+ this.mainField = this.setupMainField(templateInfo);
}
get childFields(): Field[] { return this.mainField.getSubfields };
get allFields(): Field[] { return this.mainField.getAllSubfields };
- get contentFields(): Field[] { return this.allFields.filter(field => field.getViewType === ViewType.STATIC) };
- get doc(){ return this.mainField.renderedDoc(); };
-
- cloneBase = () => {
- const clone: Template = new Template(this.settings);
- clone.allFields.forEach(field => {
- const matchingField: Field = this.allFields.filter(f => f.getID === field.getID)[0];
- matchingField.applyAttributes(field);
- })
+ get contentFields(): Field[] { return this.allFields.filter(field => field.isContentField) };
+ get doc(){ return this.mainField.renderedDoc; };
+ get title() { return this.mainField.getTitle() };
+
+ cleanup = () => {
+ //dispose each subfields disposers, etc.
+ }
+
+ cloneBase = async (): Promise<Template> => {
+ const makeCloneFieldTree = async (field: Field): Promise<Field> => {
+ const root: Field = await field.makeClone();
+ field.getSubfields.forEach(async field => {
+ const clone: Field = await makeCloneFieldTree(field);
+ root.addField(clone);
+ });
+ return root;
+ }
+
+ const clone: Template = new Template(TemplateLayouts.BasicSettings);
+ clone.mainField = await makeCloneFieldTree(this.mainField) as DynamicField;
+ console.log('last init')
+ clone.mainField.initializeDocument();
+ clone.mainField.renderedDoc._width = this.mainField.renderedDoc._width;
+ clone.mainField.renderedDoc._height = this.mainField.renderedDoc._height;
return clone;
}
- getRenderedDoc = () => {
- const doc: Doc = this.mainField.renderedDoc();
- this.contentFields.forEach(field => {
- const title: string = field.getTitle();
- const val: FieldType = field.getContent() as FieldType;
- if (!title || !val) return;
- doc[title] = val;
+ printFieldInfo = () => {
+ this.allFields.forEach(field => {
+ const doc = field.renderedDoc;
+ console.log('title: ', field.getTitle(), ' width: ', doc.width);
});
- return doc;
+ }
+
+ getRenderedDoc = () => {
+ return this.doc;
}
getFieldByID = (id: number): Field => {
@@ -68,21 +89,16 @@ export class Template {
return summary;
}
- renderUpdates = () => {
- this.allFields.forEach(field => {
- field.updateRenderedDoc(field.renderedDoc());
- });
- };
-
resetToBase = () => {
this.allFields.forEach(field => {
- field.updateRenderedDoc();
+ field.initializeDocument();
})
}
isValidTemplate = (cols: Col[]) => {
const matches: number[][] = this.getMatches(cols);
const maxMatches: number = this.maxMatches(matches);
+ console.log('title: ', this.mainField.getTitle(), ' matches: ', matches, ' max: ', maxMatches, ' num content fields: ', this.contentFields.length)
return maxMatches === this.contentFields.length;
}
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateBackend.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateBackend.tsx
index d3282eda3..2b32d49aa 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateBackend.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateBackend.tsx
@@ -1,5 +1,4 @@
import { FieldSettings, ViewType } from "./FieldTypes/Field";
-import { } from "./FieldTypes/StaticField";
export enum TemplateFieldType {
TEXT = 'text',
@@ -20,6 +19,14 @@ export class TemplateLayouts {
return Object.values(TemplateLayouts);
}
+ public static BasicSettings: FieldSettings = {
+ title: 'template_framework',
+ tl: [0, 0],
+ br: [400, 700],
+ viewType: ViewType.FREEFORM,
+ opts: {}
+ }
+
public static FourField001: FieldSettings = {
title: 'fourfield001',
tl: [0, 0],
@@ -27,7 +34,7 @@ export class TemplateLayouts {
viewType: ViewType.FREEFORM,
opts: {
backgroundColor: '#C0B887',
- cornerRounding: .05,
+ _layout_borderRounding: '.05',
//borderColor: '#6B461F',
//borderWidth: '12',
},
@@ -41,9 +48,9 @@ export class TemplateLayouts {
description: 'A title field for very short text that contextualizes the content.',
opts: {
backgroundColor: 'transparent',
- color: '#F1F0E9',
- contentXCentering: 'h-center',
- fontBold: true,
+ text_fontColor: '#F1F0E9',
+ hCentering: 'h-center',
+ contentBold: true,
},
},
{
@@ -54,9 +61,9 @@ export class TemplateLayouts {
sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE],
description: 'The main focus of the template; could be an image, long text, etc.',
opts: {
- cornerRounding: .05,
+ _layout_borderRounding: '.05',
borderColor: '#8F5B25',
- borderWidth: '6',
+ borderWidth: 6,
backgroundColor: '#CECAB9',
},
},
@@ -69,8 +76,8 @@ export class TemplateLayouts {
description: 'A caption for field #2, very short text.',
opts: {
backgroundColor: 'transparent',
- contentXCentering: 'h-center',
- color: '#F1F0E9',
+ hCentering: 'h-center',
+ text_fontColor: '#F1F0E9',
},
},
{
@@ -81,9 +88,9 @@ export class TemplateLayouts {
sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE],
description: 'A medium-sized field for medium/long text.',
opts: {
- cornerRounding: .05,
+ _layout_borderRounding: '.05',
borderColor: '#8F5B25',
- borderWidth: '6',
+ borderWidth: 6,
backgroundColor: '#CECAB9',
},
},
@@ -107,10 +114,10 @@ export class TemplateLayouts {
sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE],
description: 'A medium to large-sized field suitable for an image or longer text that should be the main focus.',
opts: {
- borderWidth: '8',
+ borderWidth: 8,
borderColor: '#F8E71C',
backgroundColor: '#242425',
- color: 'white',
+ text_fontColor: 'white',
},
},
{
@@ -122,9 +129,9 @@ export class TemplateLayouts {
description: 'A tiny field for just a word or two of plain text.',
opts: {
backgroundColor: 'transparent',
- color: 'white',
- contentXCentering: 'h-center',
- fontTransform: 'uppercase',
+ text_fontColor: 'white',
+ hCentering: 'h-center',
+ text_transform: 'uppercase',
},
},
{
@@ -136,9 +143,9 @@ export class TemplateLayouts {
description: 'A tiny field for just a word or two of plain text.',
opts: {
backgroundColor: 'transparent',
- color: 'white',
- contentXCentering: 'h-center',
- fontTransform: 'uppercase',
+ text_fontColor: 'white',
+ hCentering: 'h-center',
+ text_transform: 'uppercase',
},
},
{
@@ -149,9 +156,9 @@ export class TemplateLayouts {
sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE],
description: 'A medium to large-sized field suitable for longer text that should contextualize field 1.',
opts: {
- borderWidth: '8',
+ borderWidth: 8,
borderColor: '#F8E71C',
- color: 'white',
+ text_fontColor: 'white',
backgroundColor: '#242425',
},
},
@@ -161,7 +168,7 @@ export class TemplateLayouts {
br: [-0.525, 0.075],
opts: {
backgroundColor: '#F8E71C',
- rotation: 45,
+ _rotation: 45,
},
},
{
@@ -170,7 +177,7 @@ export class TemplateLayouts {
br: [-0.2175, 0.0245],
opts: {
backgroundColor: '#F8E71C',
- rotation: 45,
+ _rotation: 45,
},
},
{
@@ -179,7 +186,7 @@ export class TemplateLayouts {
br: [0.045, 0.0245],
opts: {
backgroundColor: '#F8E71C',
- rotation: 45,
+ _rotation: 45,
},
},
{
@@ -188,7 +195,7 @@ export class TemplateLayouts {
br: [0.3075, 0.0245],
opts: {
backgroundColor: '#F8E71C',
- rotation: 45,
+ _rotation: 45,
},
},
{
@@ -197,7 +204,7 @@ export class TemplateLayouts {
br: [0.8, 0.075],
opts: {
backgroundColor: '#F8E71C',
- rotation: 45,
+ _rotation: 45,
},
},
],
@@ -283,9 +290,9 @@ export class TemplateLayouts {
description: 'A tiny field for just a word or two of plain text.',
opts: {
backgroundColor: '#E2B4F5',
- borderWidth: '9',
+ borderWidth: 9,
borderColor: '#9222F1',
- contentXCentering: 'h-center',
+ hCentering: 'h-center',
},
},
{
@@ -297,9 +304,9 @@ export class TemplateLayouts {
description: 'A tiny field for just a word or two of plain text.',
opts: {
backgroundColor: '#F5B4DD',
- borderWidth: '9',
+ borderWidth: 9,
borderColor: '#E260F3',
- contentXCentering: 'h-center',
+ hCentering: 'h-center',
},
},
{
@@ -310,7 +317,7 @@ export class TemplateLayouts {
sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE],
description: 'A large to huge field for visual content that is the main content of the template.',
opts: {
- borderWidth: '16',
+ borderWidth: 16,
borderColor: '#A2BD77',
},
},
@@ -322,7 +329,7 @@ export class TemplateLayouts {
sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE],
description: 'A medium to large field for text that describes the visual content above',
opts: {
- borderWidth: '9',
+ borderWidth: 9,
borderColor: '#F0D601',
backgroundColor: '#F3F57D',
},
@@ -334,7 +341,7 @@ export class TemplateLayouts {
opts: {
backgroundColor: 'transparent',
borderColor: '#007C0C',
- borderWidth: '10',
+ borderWidth: 10,
},
},
],
@@ -358,8 +365,8 @@ export class TemplateLayouts {
description: 'A small text field for a title or word(s) that categorize the rest of the content.',
opts: {
borderColor: '#3B4A2C',
- borderWidth: '8',
- contentXCentering: "h-center",
+ borderWidth: 8,
+ hCentering: "h-center",
backgroundColor: '#B8DC90',
},
},
@@ -372,8 +379,8 @@ export class TemplateLayouts {
description: 'A small text field for a title that categorizes the rest of the content.',
opts: {
borderColor: '#3B4A2C',
- borderWidth: '8',
- contentXCentering: "h-center",
+ borderWidth: 8,
+ hCentering: "h-center",
backgroundColor: '#B8DC90',
},
},
@@ -384,7 +391,7 @@ export class TemplateLayouts {
opts: {
backgroundColor: '#94B058',
borderColor: '#3B4A2C',
- borderWidth: '8',
+ borderWidth: 8,
},
},
{
@@ -396,7 +403,7 @@ export class TemplateLayouts {
description: 'A medium to large field in the center of the template, for the main visual content.',
opts: {
borderColor: '#3B4A2C',
- borderWidth: '8',
+ borderWidth: 8,
backgroundColor: '#B8DC90',
},
},
@@ -409,8 +416,8 @@ export class TemplateLayouts {
description: 'A medium to large field at the bottom of the template, for the main text content.',
opts: {
borderColor: '#3B4A2C',
- borderWidth: '8',
- contentXCentering: "h-center",
+ borderWidth: 8,
+ hCentering: "h-center",
backgroundColor: '#B8DC90',
},
},
@@ -421,7 +428,7 @@ export class TemplateLayouts {
opts: {
backgroundColor: '#7A9D31',
borderColor: '#3B4A2C',
- borderWidth: '8',
+ borderWidth: 8,
},
},
{
@@ -431,7 +438,7 @@ export class TemplateLayouts {
opts: {
backgroundColor: '#94B058',
borderColor: '#3B4A2C',
- borderWidth: '8',
+ borderWidth: 8,
},
},
{
@@ -441,7 +448,7 @@ export class TemplateLayouts {
opts: {
backgroundColor: '#728745',
borderColor: '#3B4A2C',
- borderWidth: '8',
+ borderWidth: 8,
},
},
{
@@ -451,7 +458,7 @@ export class TemplateLayouts {
opts: {
backgroundColor: '#7A9D31',
borderColor: '#3B4A2C',
- borderWidth: '8',
+ borderWidth: 8,
},
},
{
@@ -461,7 +468,7 @@ export class TemplateLayouts {
opts: {
backgroundColor: '#728745',
borderColor: '#3B4A2C',
- borderWidth: '8',
+ borderWidth: 8,
},
},
{
@@ -471,7 +478,7 @@ export class TemplateLayouts {
opts: {
backgroundColor: '#94B058',
borderColor: '#3B4A2C',
- borderWidth: '8',
+ borderWidth: 8,
},
},
]
@@ -483,7 +490,7 @@ export class TemplateLayouts {
tl:[0,0],
br:[500, 600],
opts: {
- backgroundColor: '#DDD3A9',
+ backgroundColor: '#D7CBAB',
},
subfields: [
{
@@ -494,63 +501,75 @@ export class TemplateLayouts {
sizes: [TemplateFieldSize.TINY, TemplateFieldSize.SMALL],
description: 'A small text field for a title that categorizes the rest of the content.',
opts: {
- borderColor: 'yellow',
- borderWidth: '8',
- contentXCentering: "h-center",
+ hCentering: "h-center",
backgroundColor: 'transparent',
+ text_transform: 'uppercase',
},
},
{
viewType: ViewType.CAROUSEL3D,
- tl: [-0.9, -.3],
- br: [0.9, .9],
+ tl: [-0.9, -.5],
+ br: [0.9, .25],
opts: {
- borderColor: 'yellow',
- borderWidth: '8',
- backgroundColor: 'transparent',
+ borderColor: '#847F69',
+ borderWidth: 8,
+ backgroundColor: '#C8BA94',
},
subfields: [
{
viewType: ViewType.STATIC,
- tl: [-.3, -.6],
- br: [.3, .6],
+ tl: [-.4, -.6],
+ br: [.4, .6],
types: [TemplateFieldType.VISUAL, TemplateFieldType.TEXT],
sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE],
description: 'A medium to large field for content that will share central focus with other content in the carousel.',
opts: {
- borderColor: 'yellow',
- borderWidth: '8',
+ //borderColor: 'yellow',
+ //borderWidth: '8',
},
},
{
viewType: ViewType.STATIC,
- tl: [-.3, -.6],
- br: [.3, .6],
+ tl: [-.4, -.6],
+ br: [.4, .6],
types: [TemplateFieldType.VISUAL, TemplateFieldType.TEXT],
sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE],
description: 'A medium to large field for content that will share central focus with other content in the carousel.',
opts: {
- borderColor: 'black',
- borderWidth: '8',
+ //borderColor: 'black',
+ //borderWidth: '8',
},
},
{
viewType: ViewType.STATIC,
- tl: [-.3, -.6],
- br: [.3, .6],
+ tl: [-.4, -.6],
+ br: [.4, .6],
types: [TemplateFieldType.VISUAL, TemplateFieldType.TEXT],
sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE],
description: 'A medium to large field for content that will share central focus with other content in the carousel.',
opts: {
- borderColor: 'yellow',
- borderWidth: '8',
+ //borderColor: 'yellow',
+ //borderWidth: '8',
},
},
]
},
+ {
+ viewType: ViewType.STATIC,
+ tl: [-0.9, .35],
+ br: [0.9, .9],
+ types: [TemplateFieldType.TEXT],
+ sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE],
+ description: 'A medium text field for a description of the content in the carousel.',
+ opts: {
+ hCentering: "h-center",
+ backgroundColor: 'transparent',
+ },
+ },
]
}
+
public static ThreeField001: FieldSettings = {
title: 'threefield001',
viewType: ViewType.FREEFORM,
@@ -567,9 +586,9 @@ export class TemplateLayouts {
description: 'A medium to large field for visual content that is the central focus.',
opts: {
borderColor: 'yellow',
- borderWidth: '8',
+ borderWidth: 8,
backgroundColor: '#DDD3A9',
- rotation: 45,
+ _rotation: 45,
},
subfields: [
{
@@ -580,7 +599,7 @@ export class TemplateLayouts {
sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE],
description: 'A medium to large field for visual content that is the central focus.',
opts: {
- rotation: -45,
+ _rotation: -45,
},
},
]
@@ -594,7 +613,7 @@ export class TemplateLayouts {
description: 'A very small text field for one to a few words. A good caption for the image.',
opts: {
backgroundColor: 'transparent',
- contentXCentering: 'h-center',
+ hCentering: 'h-center',
},
},
{
@@ -606,7 +625,7 @@ export class TemplateLayouts {
description: 'A medium to large text field for a thorough description of the image. ',
opts: {
backgroundColor: 'transparent',
- color: 'white',
+ text_fontColor: 'white',
},
},
{
@@ -615,7 +634,7 @@ export class TemplateLayouts {
br: [1.8, -0.66],
opts: {
backgroundColor: '#CEB155',
- rotation: 45,
+ _rotation: 45,
},
subfields: [
{
@@ -634,7 +653,7 @@ export class TemplateLayouts {
br: [-0.2, -0.66],
opts: {
backgroundColor: '#CEB155',
- rotation: 135,
+ _rotation: 135,
},
subfields: [
{
@@ -653,7 +672,7 @@ export class TemplateLayouts {
br: [1.66, 1.25],
opts: {
backgroundColor: '#CEB155',
- rotation: 135,
+ _rotation: 135,
},
subfields: [
{
@@ -672,7 +691,7 @@ export class TemplateLayouts {
br: [-0.33, 1.25],
opts: {
backgroundColor: '#CEB155',
- rotation: 45,
+ _rotation: 45,
},
subfields: [
{
@@ -705,7 +724,7 @@ export class TemplateLayouts {
sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE],
description: 'A medium to large visual field for the main content of the template',
opts: {
- borderWidth: '15',
+ borderWidth: 15,
borderColor: '#E0E0DA',
},
},
@@ -718,10 +737,10 @@ export class TemplateLayouts {
description: 'A very small text field for one to a few words. The content should represent a general categorization of the image.',
opts: {
backgroundColor: 'transparent',
- color: '#AF0D0D',
- fontTransform: 'uppercase',
- fontBold: true,
- contentXCentering: 'h-left',
+ text_fontColor: '#AF0D0D',
+ text_transform: 'uppercase',
+ contentBold: true,
+ hCentering: 'h-left',
},
},
{
@@ -733,8 +752,8 @@ export class TemplateLayouts {
description: 'A very small text field for one to a few words. The content should contextualize field 2.',
opts: {
backgroundColor: 'transparent',
- color: 'black',
- contentXCentering: 'h-right',
+ text_fontColor: 'black',
+ hCentering: 'h-right',
},
},
{
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateManager.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateManager.tsx
index 50ae4d72a..09b4ce029 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateManager.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu/TemplateManager.tsx
@@ -1,3 +1,4 @@
+import { makeAutoObservable } from "mobx";
import { Col } from "./DocCreatorMenu";
import { FieldSettings } from "./FieldTypes/Field";
import { Template } from "./Template";
@@ -7,6 +8,7 @@ export class TemplateManager {
templates: Template[] = [];
constructor(templateSettings: FieldSettings[]) {
+ makeAutoObservable(this);
this.templates = this.initializeTemplates(templateSettings);
}
@@ -17,6 +19,16 @@ export class TemplateManager {
}
getValidTemplates = (cols: Col[]): Template[] => {
+ console.log('called in manager with templates: ', this.templates)
return this.templates.filter(template => template.isValidTemplate(cols));
}
+
+ addTemplate = (newTemplate: Template) =>{
+ this.templates.push(newTemplate);
+ }
+
+ removeTemplate = (template: Template) => {
+ this.templates.splice(this.templates.indexOf(template), 1);
+ template.cleanup();
+ }
} \ No newline at end of file
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index fc89dcbe7..bb7df75fc 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -573,7 +573,7 @@ export namespace Doc {
if (!skipUndefineds || value !== undefined) {
// Do we want to filter out undefineds?
if (typeof value === 'object' && 'values' in value) {
- console.log(value);
+ //console.log(value);
}
doc[key] = value;
}