From 8cecbcb66d0d377ad7c40bee5b3b42fb72239ddb Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sun, 1 Sep 2024 17:16:01 -0400 Subject: commit --- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 5b435e44a..cbf7e8ff9 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -2112,6 +2112,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent -- cgit v1.2.3-70-g09d2 From 49850a02bb8684e481fc6368f9c11232d824e872 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sun, 1 Sep 2024 18:09:49 -0400 Subject: Added color and centering defaults to formattedtextbox --- src/client/documents/Documents.ts | 1 + .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 27 ++++++++++++---------- .../nodes/formattedText/FormattedTextBox.scss | 18 +++++++++++++++ .../views/nodes/formattedText/FormattedTextBox.tsx | 4 ++-- 4 files changed, 36 insertions(+), 14 deletions(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 40b0a2a32..09106dd00 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -243,6 +243,7 @@ export class DocumentOptions { borderColor?: STRt = new StrInfo('Color of user-added border', false); text_fontColor?: STRt = new StrInfo('Color of text', false); text_align?: STRt = new StrInfo('alignment'); + hCentering?: 'h-left' | 'h-center' | 'h-right'; layout?: string | Doc; // default layout string or template document layout_isSvg?: BOOLt = new BoolInfo('whether document decorations and other selections should handle pointerEvents for svg content or use doc bounding box'); diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 0d2f4c538..fa721517b 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -1236,7 +1236,7 @@ export interface FieldOpts { cornerRounding?: number; borderWidth?: string; borderColor?: string; - contentXCentering?: 'left' | 'center' | 'right'; + contentXCentering?: 'h-left' | 'h-center' | 'h-right'; contentYCentering?: 'top' | 'center' | 'bottom'; opacity?: number; rotation?: number; @@ -1276,7 +1276,7 @@ export class FieldFuncs { borderColor: opts.borderColor, borderWidth: opts.borderWidth, opacity: opts.opacity, - _layout_centered: opts.contentXCentering === 'center' ? true : false, + hCentering: opts.contentXCentering, _rotation: opts.rotation, }); @@ -1302,7 +1302,7 @@ export class FieldFuncs { borderColor: opts.borderColor, borderWidth: opts.borderWidth, opacity: opts.opacity, - _layout_centered: opts.contentXCentering === 'center' ? true : false, + hCentering: opts.contentXCentering, _rotation: opts.rotation, }); @@ -1327,7 +1327,7 @@ export class FieldFuncs { borderColor: opts.borderColor, borderWidth: opts.borderWidth, opacity: opts.opacity, - _layout_centered: opts.contentXCentering === 'center' ? true : false, + hCentering: opts.contentXCentering, _rotation: opts.rotation, }); @@ -1382,7 +1382,7 @@ export class TemplateLayouts { opts: { backgroundColor: 'transparent', color: '#2DBEAD', - contentXCentering: 'center', + contentXCentering: 'h-center', } }, { tl: [-.87, -.83], @@ -1403,7 +1403,8 @@ export class TemplateLayouts { sizes: [FieldSize.TINY, FieldSize.SMALL], description: 'A caption for field #2, very short to short text that contextualizes the content of field #2', opts: { - backgroundColor: 'transparent' + backgroundColor: 'transparent', + contentXCentering: 'h-center' } }, { tl: [-.87, .37], @@ -1446,7 +1447,8 @@ export class TemplateLayouts { description: '', opts: { backgroundColor: 'transparent', - color: 'white' + color: 'white', + contentXCentering: 'h-center' } }, { tl: [-.45, 0], @@ -1456,7 +1458,8 @@ export class TemplateLayouts { description: '', opts: { backgroundColor: 'transparent', - color: 'white' + color: 'white', + contentXCentering: 'h-center' } }, { tl: [-.83, .2], @@ -1536,7 +1539,7 @@ export class TemplateLayouts { opts: { backgroundColor: 'transparent', color: 'white', - contentXCentering: 'right', + contentXCentering: 'h-right', } }, { tl: [.1, .8], @@ -1547,7 +1550,7 @@ export class TemplateLayouts { opts: { backgroundColor: 'transparent', color: 'white', - contentXCentering: 'left' + contentXCentering: 'h-left' } }, { tl: [0, -.9], @@ -1557,7 +1560,7 @@ export class TemplateLayouts { description: '', opts: { backgroundColor: 'transparent', - contentXCentering: 'right' + contentXCentering: 'h-right' } }], decorations: [{ @@ -1607,7 +1610,7 @@ export class TemplateLayouts { description: '', opts: { backgroundColor: 'transparent', - contentXCentering: 'center', + contentXCentering: 'h-center', } }, { tl: [-.95, .5], diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss index 99b4a84fc..15ce9ec8f 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss @@ -14,6 +14,23 @@ } } +.formattedTextBox-inner { + &.h-center * { + display: flex; + justify-content: center; + } + + &.h-left * { + display: flex; + justify-content: flex-start; + } + + &.h-right * { + display: flex; + justify-content: flex-end; + } +} + .ProseMirror:focus { outline: none !important; } @@ -1035,3 +1052,4 @@ footnote::before { } } } + diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index cbf7e8ff9..2f36a2379 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -2104,7 +2104,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent
-- cgit v1.2.3-70-g09d2 From 47895246065408eed330bc2d6b655c49976b61df Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 2 Sep 2024 03:47:54 -0400 Subject: dynamic text size and styles --- src/client/documents/Documents.ts | 2 + .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 71 ++++++++++++++++++---- .../nodes/formattedText/FormattedTextBox.scss | 12 +++- .../views/nodes/formattedText/FormattedTextBox.tsx | 3 + 4 files changed, 74 insertions(+), 14 deletions(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 09106dd00..2d96796a2 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -244,6 +244,8 @@ export class DocumentOptions { text_fontColor?: STRt = new StrInfo('Color of text', false); text_align?: STRt = new StrInfo('alignment'); hCentering?: 'h-left' | 'h-center' | 'h-right'; + isDefaultTemplateDoc?: BOOLt = new BoolInfo(''); + contentBold?: BOOLt = new BoolInfo(''); layout?: string | Doc; // default layout string or template document layout_isSvg?: BOOLt = new BoolInfo('whether document decorations and other selections should handle pointerEvents for svg content or use doc bounding box'); diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index fa721517b..fc29531d1 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -1242,7 +1242,7 @@ export interface FieldOpts { rotation?: number; //animation?: boolean; fontBold?: boolean; - fontTransform?: 'toUpper' | 'toLower'; + fontTransform?: 'uppercase' | 'lowercase'; } interface TemplateOpts extends FieldOpts { @@ -1251,6 +1251,51 @@ interface TemplateOpts extends FieldOpts { export class FieldFuncs { + private static 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 * (uppercase ? 1.25 : 1); + + 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; + + 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 * (uppercase ? 1.25 : 1); + console.log(rowsCount, currTextHeight) + + currFontSize += 1; + } + + return currFontSize - 1; + }; + + + + private static 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 @@ -1263,15 +1308,14 @@ export class FieldFuncs { public static FreeformField = (coords: {tl: [number, number], br: [number, number]}, parentWidth: number, parentHeight: number, title: string, content: string, opts: FieldOpts) => { const {width, height, coord} = FieldFuncs.getDimensions(coords, parentWidth, parentHeight); - const docWithBasicOpts = (Docs.Create.FreeformDocument)([], { + const docWithBasicOpts = (Docs.Create.FreeformDocument)([], { + isDefaultTemplateDoc: true, _height: height, _width: width, title: title, x: coord.x, y: coord.y, - _text_fontSize: `${height/2}` , backgroundColor: opts.backgroundColor ?? '', - text_fontColor: opts.color, _layout_borderRounding: `${opts.cornerRounding}px` ?? '0px', borderColor: opts.borderColor, borderWidth: opts.borderWidth, @@ -1288,15 +1332,18 @@ export class FieldFuncs { const bool = true; - const docWithBasicOpts = (Docs.Create.TextDocument)('hi', { + const docWithBasicOpts = (Docs.Create.TextDocument)('Fluorite is a very', { + isDefaultTemplateDoc: true, _height: height, _width: width, title: title, x: coord.x, y: coord.y, - _text_fontSize: `${height/2}` , + _text_fontSize: `${FieldFuncs.calculateFontSize(width, height, 'Fluorite is a very', true)}` , backgroundColor: opts.backgroundColor ?? '', text_fontColor: opts.color, + contentBold: opts.fontBold, + textTransform: opts.fontTransform, color: opts.color, _layout_borderRounding: `${opts.cornerRounding}px` ?? '0px', borderColor: opts.borderColor, @@ -1314,20 +1361,18 @@ export class FieldFuncs { public static ImageField = (coords: {tl: [number, number], br: [number, number]}, parentWidth: number, parentHeight: number, title: string, content: string, opts: FieldOpts) => { const {width, height, coord} = FieldFuncs.getDimensions(coords, parentWidth, parentHeight); - const doc = Docs.Create.ImageDocument(content, { + const doc = Docs.Create.ImageDocument(content, { + isDefaultTemplateDoc: true, _height: height, _width: width, title: title, x: coord.x, - y: coord.y, - _text_fontSize: `${height/2}` , + y: coord.y, backgroundColor: opts.backgroundColor ?? '', - text_fontColor: opts.color, _layout_borderRounding: `${opts.cornerRounding}px` ?? '0px', borderColor: opts.borderColor, borderWidth: opts.borderWidth, opacity: opts.opacity, - hCentering: opts.contentXCentering, _rotation: opts.rotation, }); @@ -1424,8 +1469,8 @@ export class TemplateLayouts { public static FourField002: TemplateDocInfos = { title: 'fourfield2', - width: 475, - height: 870, + width: 425, + height: 778, opts: { backgroundColor: '#242425' }, diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss index 15ce9ec8f..d6fd81f83 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss @@ -22,13 +22,23 @@ &.h-left * { display: flex; - justify-content: flex-start; + justify-content: flex-start; } &.h-right * { display: flex; justify-content: flex-end; } + + &.template * { + ::-webkit-scrollbar-track { + background: none; + } + } + + &.bold * { + font-weight: bold; + } } .ProseMirror:focus { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 2f36a2379..54e6c0add 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -65,6 +65,7 @@ import { removeMarkWithAttrs } from './prosemirrorPatches'; import { RichTextMenu, RichTextMenuPlugin } from './RichTextMenu'; import { RichTextRules } from './RichTextRules'; import { schema } from './schema_rts'; +import { Property } from 'csstype'; // import * as applyDevTools from 'prosemirror-dev-tools'; export interface FormattedTextBoxProps extends FieldViewProps { @@ -2113,6 +2114,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent -- cgit v1.2.3-70-g09d2 From b4e4cca578747c987efde7fa8c14299790f3ee02 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 4 Sep 2024 04:14:59 -0400 Subject: stuff --- src/client/apis/gpt/GPT.ts | 2 +- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 1 + .../views/nodes/DataVizBox/DocCreatorMenu.scss | 15 +- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 261 ++++++++++++++++----- src/client/views/nodes/ImageBox.tsx | 23 +- .../nodes/formattedText/FormattedTextBox.scss | 1 + 6 files changed, 232 insertions(+), 71 deletions(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index ba8106c4d..6befad310 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -56,7 +56,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { temp: 0, prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', }, - template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You will be given a list of field descriptions for multiple templates in the format {field #0: “description”}{field #1: “description”}{...}, and a list of column descriptions in the format {“title”: “description}{...}. Your job is to match columns with fields based on their descriptions. Your output should be in the following JSON format: {“Template title”:{“#”: “title”, “#”: “title”, “#”: “title” …}, “Template title”:{“#”: “title”, “#”: “title”, “#”: “title” …}} where “Template title” represents the template, # represents the field # and “title” the title of the column assigned to it. A filled out example might look like {“fivefield2”:{0:”Name”, 1:”Image”, 2:”Caption”, 3:”Position”, 4:”Stats”}, “fivefield3”:{0:”Image”, 1:”Name”, 2:”Caption”, 3:”Stats”, 4:”Position”}. Include one object for each template. IT IS VERY IMPORTANT THAT YOU ONLY INCLUDE TEXT IN THE FORMAT ABOVE, WITH NO ADDITIONS WHATSOEVER. Do not include extraneous ‘#’ characters, ‘column’ for columns, or ‘template’ for templates: ONLY THE TITLES AND NUMBERS. Do this for each template whose fields are described. The descriptions are as follows: ' }, + template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You will be given a list of field descriptions for multiple templates in the format {field #0: “description”}{field #1: “description”}{...}, and a list of column descriptions in the format {“title”: “description”}{...}. Your job is to match columns with fields based on their descriptions. Your output should be in the following JSON format: {“Template title”:{“#”: “title”, “#”: “title”, “#”: “title” …}, “Template title”:{“#”: “title”, “#”: “title”, “#”: “title” …}} where “Template title” represents the template, # represents the field # and “title” the title of the column assigned to it. A filled out example might look like {“fivefield2”:{“0”:”Name”, “1”:”Image”, “2”:”Caption”, “3”:”Position”, “4”:”Stats”}, “fivefield3”:{0:”Image”, 1:”Name”, 2:”Caption”, 3:”Stats”, 4:”Position”}. Include one object for each template. IT IS VERY IMPORTANT THAT YOU ONLY INCLUDE TEXT IN THE FORMAT ABOVE, WITH NO ADDITIONS WHATSOEVER. Do not include extraneous ‘#’ characters, ‘column’ for columns, or ‘template’ for templates: ONLY THE TITLES AND NUMBERS. There should never be one column assigned to more than one field (ie. if the “name” column is assigned to field 1, it can’t be assigned to any other fields) . Do this for each template whose fields are described. The descriptions are as follows:' }, vizsum: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'Your job is to provide brief descriptions for columns in a dataset based on example rows. Your descriptions should be geared towards how each column’s data might fit together into a visual template. Would they make good titles, main focuses, captions, descriptions, etc. Pay special attention to connections between columns, i.e. is there one column that specifically seems to describe/be related to another more than the rest? You should provide your analysis in JSON format like so: {“col1”:”description”, “col2”:”description”, …}. DO NOT INCLUDE ANY OTHER TEXT, ONLY THE JSON.'}, vizsum2: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'Your job is to provide structured information on columns in a dataset based on example rows. You will categorize each column in two ways: by type and size. The size categories are as follows: tiny (one or two words), small (a sentence/multiple words), medium (a few sentences), large (a longer paragraph), and huge (a very long or multiple paragraphs). The type categories are as follows: visual (links/file paths to images, pdfs, maps, or any other visual media type), and text (plain text that isn’t a link/file path). Visual media should be assumed to have size “medium” “large” or “huge”. You will give your responses in JSON format, like so: {“title (of column)”:{“type”:”text”, “size”:”small”}, “title (of column)”:{“type”:”visual”, “size”:”medium”}, …}. DO NOT INCLUDE ANY OTHER TEXT, ONLY THE JSON.'} }; diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 6888d5f1e..e8235ce1a 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -712,6 +712,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { const targetKey = StrCast(templateInfo.doc!.layout_fieldKey, 'layout'); const applied = this.ApplyTemplateTo(templateInfo.doc!, target, targetKey, templateInfo.doc!.title + `${row}`); target.layout_fieldKey = targetKey; + //this.applyImagesTo(target, fields); return applied; }); diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index c93798979..1f81bf960 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -307,8 +307,11 @@ } .docCreatorMenu-preview-image{ - width: 105px; - height: 105px; + background-color: transparent; + height: 100px; + width: 100px; + display: block; + object-fit: contain; border-radius: 5px; } @@ -411,10 +414,16 @@ } .section-reveal-options { - margin: 0px; + margin-top: 0px; + margin-bottom: 0px; + margin-right: 0px; margin-left: auto; border: 0px; background: none; + + &.float-right { + float: right; + } } .docCreatorMenu-section-title { diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index e36adc40a..191b387c4 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -59,7 +59,7 @@ export class DocCreatorMenu extends ObservableReactComponent { @observable _layoutPreviewScale: number = 1; @observable _savedLayouts: DataVizTemplateLayout[] = []; - @observable _GPTTemplates: Doc[] = []; + @observable _suggestedTemplates: Doc[] = []; @observable _GPTOpt: boolean = false; @observable _userPrompt: string = ''; @observable _callCount: number = 0; @@ -99,7 +99,7 @@ export class DocCreatorMenu extends ObservableReactComponent { @action setDataViz = (dataViz: DataVizBox) => { this._dataViz = dataViz }; @action setTemplateDocs = (docs: Doc[]) => {this._templateDocs = docs.map(doc => doc.annotationOn ? DocCast(doc.annotationOn):doc)}; - @action setGPTTemplates = (docs: Doc[]) => {this._GPTTemplates = docs}; + @action setGSuggestedTemplates = (docs: Doc[]) => {this._suggestedTemplates = docs}; @computed get docsToRender() { return this._selectedTemplate ? NumListCast(this._dataViz?.layoutDoc.dataViz_selectedRows) : []; @@ -198,7 +198,7 @@ export class DocCreatorMenu extends ObservableReactComponent { document.addEventListener('pointerdown', this.onPointerDown, true); document.addEventListener('pointerup', this.onPointerUp); this._disposers.templates = reaction(() => this._templateDocs.slice(), (docs) => docs.map(this.getIcon)); - this._disposers.gpt = reaction(() => this._GPTTemplates.slice(), (docs) => docs.map(this.getIcon)); + this._disposers.gpt = reaction(() => this._suggestedTemplates.slice(), (docs) => docs.map(this.getIcon)); //this._disposers.columns = reaction(() => this._dataViz?.layoutDoc._dataViz_axes, () => {this.generateTemplates('')}) this._disposers.lightbox = reaction(() => LightboxView.LightboxDoc(), doc => { doc ? this._shouldDisplay && this.closeMenu() : !this._shouldDisplay && this.openMenu()}); //this._disposers.fields = reaction(() => this._dataViz?.axes, cols => this._selectedCols = cols?.map(col => { return {title: col, type: '', desc: ''}})) @@ -233,7 +233,7 @@ export class DocCreatorMenu extends ObservableReactComponent { @action openMenu = () => { - const allTemplates = this._templateDocs.concat(this._GPTTemplates); + const allTemplates = this._templateDocs.concat(this._suggestedTemplates); this._shouldDisplay = true; this.updateIcons(allTemplates); }; @@ -357,7 +357,7 @@ export class DocCreatorMenu extends ObservableReactComponent { const res = await gptAPICall(prompt, GPTCallType.TEMPLATE); if (res && this._callCount === origCount) { - this._GPTTemplates = []; + this._suggestedTemplates = []; this._GPTLoading = false; const templates: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[] = JSON.parse(res); this.createGeneratedTemplates(templates, 500, 500); @@ -389,14 +389,14 @@ export class DocCreatorMenu extends ObservableReactComponent { GPTTemplates.push(template); }); - setTimeout(() => {this.setGPTTemplates(GPTTemplates); /*GPTTemplates.forEach(template => mainCollection.removeDocument(template))*/}, 100); + setTimeout(() => {this.setGSuggestedTemplates(GPTTemplates); /*GPTTemplates.forEach(template => mainCollection.removeDocument(template))*/}, 100); this.forceUpdate(); }; editTemplate = (doc: Doc) => { //this.closeMenu(); - DocumentViewInternal.addDocTabFunc(doc, OpenWhere.lightboxAlways); + DocumentViewInternal.addDocTabFunc(doc, OpenWhere.addRight); DocumentView.DeselectAll(); Doc.UnBrushDoc(doc); }; @@ -419,20 +419,22 @@ export class DocCreatorMenu extends ObservableReactComponent { // const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; // mainCollection.addDocument(doc); - const temp = TemplateLayouts.FourField001; + // const temp = TemplateLayouts.FourField001; - const img: Col = {type: TemplateFieldType.VISUAL, title: 'Image', desc: 'description whpoo', size: TemplateFieldSize.LARGE}; - const capt1: Col = {type: TemplateFieldType.TEXT, title: 'Type', desc: 'description hey', size: TemplateFieldSize.TINY}; - const capt2: Col = {type: TemplateFieldType.TEXT, title: 'Locality', desc: '', size: TemplateFieldSize.TINY}; - const desc: Col = {type: TemplateFieldType.TEXT, title: 'Description', desc: '', size: TemplateFieldSize.LARGE}; + // const img: Col = {type: TemplateFieldType.TEXT, title: 'Type', desc: 'description whpoo', size: TemplateFieldSize.LARGE, defaultContent: ''}; + // const capt1: Col = {type: TemplateFieldType.TEXT, title: 'Image', desc: 'description hey', size: TemplateFieldSize.TINY}; + // const capt2: Col = {type: TemplateFieldType.TEXT, title: 'Locality', desc: '', size: TemplateFieldSize.TINY, defaultContent: ''}; + // const desc: Col = {type: TemplateFieldType.TEXT, title: 'Description', desc: '', size: TemplateFieldSize.LARGE, defaultContent: 'This is a description of a rock. It is kind of long. It is very long. It is gratuitous. This description should be shorter. Oh well. This is a description of a rock. It is kind of long. It is very long. It is gratuitous. This description should be shorter. Oh well. This is a description of a rock. It is kind of long. It is very long. It is gratuitous. This description should be shorter. Oh well.'}; // const assignments = {'0': img, '1': capt1, '2': capt2, '3': desc} // this.createEmptyTemplate(temp, assignments); + // console.log(this.findValidTemplates(this.fieldsInfos, TemplateLayouts.allTemplates)); - this.generatePresetTemplates(this.findValidTemplates(this.fieldsInfos, TemplateLayouts.allTemplates), this.fieldsInfos); // console.log(this._dataViz?.colsInfo.get("IMG")?.size, this._dataViz?.colsInfo.get("IMG")?.type) // console.log(this.fieldsInfos) + + }; @action addField = () => { @@ -492,7 +494,7 @@ export class DocCreatorMenu extends ObservableReactComponent { const colMatchesField = (col: Col, field : Field) => { return field.sizes?.includes(col.size) && field.types?.includes(col.type) }; const matches: number[][] = Array(template.fields.length).fill([]).map(() => []); - console.log(matches) + template.fields.forEach((field, i) => { cols.forEach((col, v) => { if (colMatchesField(col, field)) { @@ -507,11 +509,13 @@ export class DocCreatorMenu extends ObservableReactComponent { maxMatches = (fieldsCt: number, matches: number[][]) => { const used: boolean[] = Array(fieldsCt).fill(false); const mt: number[] = Array(fieldsCt).fill(-1); + console.log(fieldsCt, matches) const augmentingPath = (v: number): boolean => { if (used[v]) return false; used[v] = true; for (const to of matches[v]) { + console.log(mt[to]); if (mt[to] === -1 || augmentingPath(mt[to])) { mt[to] = v; return true; @@ -538,7 +542,8 @@ export class DocCreatorMenu extends ObservableReactComponent { findValidTemplates = (cols: Col[], templates: TemplateDocInfos[]) => { let validTemplates: any[] = []; templates.forEach(template => { - const numFields = template.fields.length; + const numFields = template.fields.length; + if (!(numFields === cols.length)) return; const matches = this.matchesForTemplate(template, cols); if (this.maxMatches(numFields, matches) === numFields) { validTemplates.push(template.title); @@ -546,6 +551,8 @@ export class DocCreatorMenu extends ObservableReactComponent { }) validTemplates = validTemplates.map(title => TemplateLayouts.fieldByTitle(title)); + + console.log(validTemplates); return validTemplates; }; @@ -571,7 +578,7 @@ export class DocCreatorMenu extends ObservableReactComponent { // return new Doc; // } - createEmptyTemplate = (template: TemplateDocInfos, assignments: {[field: string]: Col}) => { + createEmptyTemplate = (template: TemplateDocInfos, assignments: {[field: string]: Col}): Doc => { const fields: Doc[] = []; Object.entries(assignments).forEach(([f, col]) => { @@ -618,12 +625,13 @@ export class DocCreatorMenu extends ObservableReactComponent { const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; mainCollection.addDocument(renderedTemplate); + return renderedTemplate; }; compileFieldDescriptions = (templates: TemplateDocInfos[]): string => { let descriptions: string = ''; templates.forEach(template => { - descriptions += `---------- Description of template ${template.title}'s fields: ` + descriptions += `---------- NEW TEMPLATE TO INCLUDE: Description of template ${template.title}'s fields: ` template.fields.forEach((field, index) => { descriptions += `{Field #${index}: ${field.description}} ` }); @@ -633,7 +641,7 @@ export class DocCreatorMenu extends ObservableReactComponent { }; compileColDescriptions = (cols: Col[]): string => { - let descriptions: string = ''; + let descriptions: string = ' ------------- COL DESCRIPTIONS START HERE:'; cols.forEach(col => descriptions += `{title: ${col.title}, size: ${col.size}, type: ${col.type}, descreiption: ${col.desc}} `); return descriptions; @@ -648,6 +656,7 @@ export class DocCreatorMenu extends ObservableReactComponent { const inputText = fieldDescriptions.concat(colDescriptions); + console.log(inputText); ++this._callCount; const origCount = this._callCount; @@ -660,6 +669,9 @@ export class DocCreatorMenu extends ObservableReactComponent { if (res && this._callCount === origCount) { this._GPTLoading = false; + + console.log(res); + const assignments: {[templateTitle: string]: {[field: string]: string}} = JSON.parse(res); const brokenDownAssignments: [TemplateDocInfos, {[field: number]: Col}][] = []; Object.entries(assignments).forEach(([tempTitle, assignment]) => { @@ -681,11 +693,16 @@ export class DocCreatorMenu extends ObservableReactComponent { return []; }; - generatePresetTemplates = async(templates: TemplateDocInfos[], cols: Col[]) => { + generatePresetTemplates = async() => { + const cols = this.fieldsInfos; + const templates = this.findValidTemplates(cols, TemplateLayouts.allTemplates); const assignments: [TemplateDocInfos, {[field: number]: Col}][] = await this.assignColsToFields(templates, cols); + const renderedTemplates: Doc[] = []; assignments.forEach(([template, assignments]) => { - this.createEmptyTemplate(template, assignments); + renderedTemplates.push(this.createEmptyTemplate(template, assignments)); }); + + setTimeout(() => {this.setGSuggestedTemplates(renderedTemplates)}); } get templatesPreviewContents(){ @@ -699,7 +716,7 @@ export class DocCreatorMenu extends ObservableReactComponent {
Suggested Templates
-
@@ -709,7 +726,7 @@ export class DocCreatorMenu extends ObservableReactComponent {
) : ( - this._GPTTemplates?.map(doc => + this._suggestedTemplates?.map(doc => ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info =>
{
- - this._userPrompt = e.target.value}/>
{this._GPTOpt ? GPTOptions : null }
@@ -1036,9 +1052,12 @@ export class DocCreatorMenu extends ObservableReactComponent { return (
- + +
{this.fieldsInfos.map((field, index) =>
@@ -1261,12 +1280,12 @@ interface TemplateOpts extends FieldOpts { export class FieldFuncs { - private static calculateFontSize = (contWidth: number, contHeight: number, text: string, uppercase: boolean): number => { + public static 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 * (uppercase ? 1.25 : 1); + let currTextHeight = currFontSize * rowsCount * 2; while (currTextHeight <= contHeight) { let wordIndex = 0; @@ -1276,7 +1295,8 @@ export class FieldFuncs { while (wordIndex < words.length) { const word = words[wordIndex]; - const wordWidth = word.length * currFontSize; + const wordWidth = word.length * currFontSize * .5; + //console.log(wordWidth) if (currentRowWidth + wordWidth <= contWidth) { currentRowWidth += wordWidth; @@ -1291,11 +1311,11 @@ export class FieldFuncs { } } - wordIndex++; + wordIndex++; } - currTextHeight = rowsCount * currFontSize * (uppercase ? 1.25 : 1); - //console.log(rowsCount, currTextHeight) + currTextHeight = rowsCount * currFontSize * 2; + //console.log(rowsCount, currFontSize, currTextHeight) currFontSize += 1; } @@ -1312,6 +1332,7 @@ export class FieldFuncs { const width = r - l; const height = b - t; const coord = {x: l, y: t}; + console.log(coords, parentWidth, parentHeight, height); return {width, height, coord}; } @@ -1378,6 +1399,7 @@ export class FieldFuncs { title: title, x: coord.x, y: coord.y, + _layout_fitWidth: false, backgroundColor: opts.backgroundColor ?? '', _layout_borderRounding: `${opts.cornerRounding}px` ?? '0px', borderColor: opts.borderColor, @@ -1386,6 +1408,8 @@ export class FieldFuncs { _rotation: opts.rotation, }); + //setTimeout(() => {doc._height = height; doc._width = width}, 10); + return doc; } @@ -1415,8 +1439,12 @@ export class TemplateLayouts { return TemplateLayouts.FourField002; case 'fourfield3': return TemplateLayouts.FourField003; + case 'fourfield4': + return TemplateLayouts.FourField004; case 'threefield1': return TemplateLayouts.ThreeField001; + case 'threefield2': + return TemplateLayouts.ThreeField002; default: break; } @@ -1427,11 +1455,11 @@ export class TemplateLayouts { public static FourField001: TemplateDocInfos = { title: 'fourfield1', width: 416, - height: 721, + height: 700, opts: { - backgroundColor: '#7B8D62', + backgroundColor: '#C0B887', cornerRounding: 20, - borderColor: '#642B00', + borderColor: '#6B461F', borderWidth: '12', }, fields: [{ @@ -1454,13 +1482,13 @@ export class TemplateLayouts { description: 'The main focus of the template; could be an image, long text, etc.', opts: { cornerRounding: 20, - borderColor: '#642B00', + borderColor: '#8F5B25', borderWidth: '6', backgroundColor: '#CECAB9', } }, { tl: [-.8, .2], - br: [.8, .35], + br: [.8, .3], types: [TemplateFieldType.TEXT], sizes: [TemplateFieldSize.TINY, TemplateFieldSize.SMALL], description: 'A caption for field #2, very short to short text that contextualizes the content of field #2', @@ -1474,10 +1502,10 @@ export class TemplateLayouts { br: [.87, .96], types: [TemplateFieldType.TEXT, TemplateFieldType.VISUAL], sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE], - description: 'A medium-sized field for medium/long text or a secondary image that complements the main focus.', + description: 'A medium-sized field for medium/long text.', opts: { cornerRounding: 15, - borderColor: '#642B00', + borderColor: '#8F5B25', borderWidth: '6', backgroundColor: '#CECAB9', } @@ -1497,28 +1525,28 @@ export class TemplateLayouts { br: [.83, -.2], types: [TemplateFieldType.VISUAL, TemplateFieldType.TEXT], sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE], - description: '', + description: 'A medium to large-sized field suitable for an image or longer text that should be the main focus.', opts: { borderWidth: '8', borderColor: '#F8E71C', } }, { - tl: [-.45, -.18], - br: [.45, 0], + tl: [-.65, -.2], + br: [.65, -.02], types: [TemplateFieldType.TEXT], - sizes: [TemplateFieldSize.TINY, TemplateFieldSize.SMALL], - description: '', + sizes: [TemplateFieldSize.TINY], + description: 'A tiny field for just a word or two of plain text.', opts: { backgroundColor: 'transparent', color: 'white', contentXCentering: 'h-center' } }, { - tl: [-.45, 0], - br: [.45, .18], + tl: [-.65, 0], + br: [.65, .18], types: [TemplateFieldType.TEXT], - sizes: [TemplateFieldSize.TINY, TemplateFieldSize.SMALL], - description: '', + sizes: [TemplateFieldSize.TINY], + description: 'A tiny field for just a word or two of plain text.', opts: { backgroundColor: 'transparent', color: 'white', @@ -1529,11 +1557,12 @@ export class TemplateLayouts { br: [.83, .95], types: [TemplateFieldType.TEXT, TemplateFieldType.VISUAL], sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE], - description: '', + description: 'A medium to large-sized field suitable for an image or longer text that should be the main focus, or share focus with field 1.', opts: { borderWidth: '8', borderColor: '#F8E71C', - backgroundColor: '#242425' + color: 'white', + backgroundColor: '#242425', } }], decorations: [{ @@ -1612,7 +1641,8 @@ export class TemplateLayouts { description: '', opts: { backgroundColor: 'transparent', - color: 'white', + color: 'red', + fontTransform: 'uppercase', contentXCentering: 'h-left' } }, { @@ -1635,6 +1665,72 @@ export class TemplateLayouts { }] }; + public static FourField004: TemplateDocInfos = { + title: 'fourfield4', + width: 414, + height: 583, + opts: { + backgroundColor: '#6CCAF0', + borderColor: '#1088C3', + borderWidth: '10' + }, + fields: [{ + tl: [-.86, -.92], + br: [-.075, -.77], + types: [TemplateFieldType.TEXT], + sizes: [TemplateFieldSize.TINY], + description: 'A tiny field for just a word or two of plain text.', + opts: { + backgroundColor: '#E2B4F5', + borderWidth: '9', + borderColor: '#9222F1', + contentXCentering: 'h-center' + } + }, { + tl: [.075, -.92], + br: [.86, -.77], + types: [TemplateFieldType.TEXT], + sizes: [TemplateFieldSize.TINY], + description: 'A tiny field for just a word or two of plain text.', + opts: { + backgroundColor: '#F5B4DD', + borderWidth: '9', + borderColor: '#E260F3', + contentXCentering: 'h-center' + } + }, { + tl: [-.81, -.64], + br: [.81, .48], + types: [TemplateFieldType.VISUAL], + 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', + borderColor: '#A2BD77', + } + }, { + tl: [-.86, .6], + br: [.86, .92], + types: [TemplateFieldType.TEXT], + sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE], + description: 'A medium to large field for text that describes the visual content above', + opts: { + borderWidth: '9', + borderColor: '#F0D601', + backgroundColor: '#F3F57D', + } + }], + decorations: [{ + tl: [-.852, -.67], + br: [.852, .51], + opts: { + backgroundColor: 'transparent', + borderColor: '#007C0C', + borderWidth: '10', + } + }] + }; + public static ThreeField001: TemplateDocInfos = { title: 'threefield1', width: 575, @@ -1646,8 +1742,8 @@ export class TemplateLayouts { tl: [-.66, -.747], br: [.66, .247], types: [TemplateFieldType.VISUAL], - sizes: [TemplateFieldSize.LARGE, TemplateFieldSize.HUGE], - description: '', + sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE], + description: 'A medium to large field for visual content that is the central focus.', opts: { borderColor: 'yellow', borderWidth: '8', @@ -1670,7 +1766,7 @@ export class TemplateLayouts { br: [.7, .46], types: [TemplateFieldType.TEXT], sizes: [TemplateFieldSize.TINY, TemplateFieldSize.SMALL], - description: '', + description: 'A very small text field for one to a few words. A good caption for the image.', opts: { backgroundColor: 'transparent', contentXCentering: 'h-center', @@ -1680,7 +1776,7 @@ export class TemplateLayouts { br: [.95, .95], types: [TemplateFieldType.TEXT], sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE], - description: '', + description: 'A medium to large text field for a thorough description of the image. ', opts: { backgroundColor: 'transparent', color: 'white' @@ -1717,6 +1813,59 @@ export class TemplateLayouts { }] }; + public static ThreeField002: TemplateDocInfos = { + title: 'threefield2', + width: 477, + height: 662, + opts: { + backgroundColor: '#9E9C95' + }, + fields: [{ + tl: [-.95, .8], + br: [-.1, .95], + types: [TemplateFieldType.VISUAL], + sizes: [TemplateFieldSize.MEDIUM, TemplateFieldSize.LARGE, TemplateFieldSize.HUGE], + description: '', + opts: { + backgroundColor: 'transparent', + color: 'white', + contentXCentering: 'h-right', + } + }, { + tl: [.1, .8], + br: [.95, .95], + types: [TemplateFieldType.TEXT], + sizes: [TemplateFieldSize.TINY, TemplateFieldSize.SMALL], + 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: 'red', + fontTransform: 'uppercase', + fontBold: true, + contentXCentering: 'h-left' + } + }, { + tl: [0, -.9], + br: [.85, -.66], + types: [TemplateFieldType.TEXT], + sizes: [TemplateFieldSize.TINY, TemplateFieldSize.SMALL], + description: 'A very small text field for one to a few words. The content should contextualize field 2.', + opts: { + backgroundColor: 'transparent', + contentXCentering: 'h-right' + } + }], + decorations: [{ + tl: [-.025, .8], + br: [.025, .95], + opts: { + backgroundColor: '#E0E0DA', + } + }] + }; + + + // public static FourField002: TemplateDocInfos = { // width: 450, // height: 600, diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index faea05104..53aa7171f 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -123,15 +123,15 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { { fireImmediately: true, delay: 1000 } ); const { layoutDoc } = this; - this._disposers.path = reaction( - () => ({ nativeSize: this.nativeSize, width: NumCast(this.layoutDoc._width) }), - ({ nativeSize, width }) => { - if (layoutDoc === this.layoutDoc || !this.layoutDoc._height) { - this.layoutDoc._height = (width * nativeSize.nativeHeight) / nativeSize.nativeWidth; - } - }, - { fireImmediately: true } - ); + // this._disposers.path = reaction( + // () => ({ nativeSize: this.nativeSize, width: NumCast(this.layoutDoc._width) }), + // ({ nativeSize, width }) => { + // if (layoutDoc === this.layoutDoc || !this.layoutDoc._height) { + // this.layoutDoc._height = (width * nativeSize.nativeHeight) / nativeSize.nativeWidth; + // } + // }, + // { fireImmediately: true } + // ); this._disposers.scroll = reaction( () => this.layoutDoc.layout_scrollTop, sTop => { @@ -394,7 +394,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { alt="" key="paths" src={srcpath} - style={{ transform, transformOrigin }} + style={{ transform, transformOrigin, objectFit: 'fill', height: '100%' }} onError={action(e => { this._error = e.toString(); })} @@ -456,6 +456,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { savedAnnotations = () => this._savedAnnotations; render() { + console.log('img', this._props.PanelWidth(), this._props.PanelHeight()) TraceMobx(); const borderRad = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BorderRounding); const borderRadius = borderRad?.includes('px') ? `${Number(borderRad.split('px')[0]) / (this._props.NativeDimScaling?.() || 1)}px` : borderRad; @@ -475,7 +476,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { })} style={{ width: this._props.PanelWidth() ? undefined : `100%`, - height: this._props.PanelWidth() ? undefined : `100%`, + height: this._props.PanelHeight() ? undefined : `100%`, pointerEvents: this.layoutDoc._lockedPosition ? 'none' : undefined, borderRadius, overflow: this.layoutDoc.layout_fitWidth || this._props.fitWidth?.(this.Document) ? 'auto' : undefined, diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss index d6fd81f83..72d550c7e 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss @@ -79,6 +79,7 @@ audiotag:hover { transform-origin: left top; top: 0; left: 0; + } .formattedTextBox-cont { -- cgit v1.2.3-70-g09d2 From e7235baa7ed998908dec8bf48e4c244594aa76bb Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sun, 8 Sep 2024 18:42:12 -0400 Subject: schema changes reverted --- .../collectionSchema/CollectionSchemaView.tsx | 3 +- .../collectionSchema/SchemaCellField.tsx | 123 +-------------------- .../collectionSchema/SchemaColumnHeader.tsx | 2 +- .../collections/collectionSchema/SchemaRowBox.tsx | 5 +- .../collectionSchema/SchemaTableCell.tsx | 2 +- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 9 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- 7 files changed, 16 insertions(+), 130 deletions(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 12c342b9f..59ccec71f 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -46,7 +46,6 @@ import { SchemaCellField } from './SchemaCellField'; import { threadId } from 'worker_threads'; import { FontIconBox } from '../../nodes/FontIconBox/FontIconBox'; -// eslint-disable-next-line @typescript-eslint/no-var-requires const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore export const FInfotoColType: { [key: string]: ColumnType } = { @@ -1539,4 +1538,4 @@ class CollectionSchemaViewDocs extends React.Component ); } -} +} \ No newline at end of file diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 3be9167fe..e1059b8fc 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -8,15 +8,6 @@ import { FieldView, FieldViewProps } from "../../nodes/FieldView"; import { ObjectField } from "../../../../fields/ObjectField"; import { Doc } from "../../../../fields/Doc"; import { DocumentView } from "../../nodes/DocumentView"; -import { date } from "serializr"; -import { createRoot } from "react-dom/client"; -import DatePicker from "react-datepicker"; -import { emptyFunction } from "../../../../Utils"; -import { DateField } from "../../../../fields/DateField"; - -enum EleType { - plainText, fieldReference, date, boolean -} export interface SchemaCellFieldProps { contents: any; @@ -43,7 +34,6 @@ export class SchemaCellField extends ObservableReactComponent { - // if (!this._inputref) return; - - // const dateRefs = Array.from(this._inputref.querySelectorAll('.date-placeholder')); - - // dateRefs.forEach(ref => { - // const root = createRoot(ref); - // root.render(); - // }) - // } - - generateSpan = (text: string, cell: HTMLDivElement | undefined): JSX.Element => { + generateSpan = (text: string, cell: HTMLDivElement | undefined) => { const selfRef = text === this.selfRefPattern; - const color: string | undefined = cell?.style.borderTop.replace('2px solid', ''); - return ( - - {text} - - ); + return `${text}`; } makeSpans = (content: string) => { - const spans: JSX.Element[] = []; let chunkedText = content; const pattern = /(this|d(\d+))\.(\w+)/g; @@ -170,93 +140,17 @@ export class SchemaCellField extends ObservableReactComponent { - chunkedText = chunkedText.replace(match, ''); - spans.push(this.generateSpan(match, cells.get(match))); + chunkedText = chunkedText.replace(match, this.generateSpan(match, cells.get(match))); ++matchNum; }) - chunkedText = chunkedText.replace(/{{date}}/g, `placeholder text`); - return chunkedText; } - verifyCellRef = (text: string): [string, HTMLDivElement | undefined] | undefined => { - const pattern = /(this|d(\d+))\.(\w+)/g; - let matchedText: string = ''; - let matchedCell: HTMLDivElement | undefined = undefined; - let match: RegExpExecArray | null; - - while ((match = pattern.exec(text)) !== null) { - const cells = this._props.getCells(match[0]); - if (cells.length) { - matchedText = match[0]; - matchedCell = cells[0]; - } - } - - if (!matchedText && !matchedCell) return undefined; - else return [matchedText, matchedCell]; - } - - elementsFromText = (chunks: string[]): JSX.Element[] => { - const eles: any[] = []; - - chunks.forEach(text => { - const cellRef = this.verifyCellRef(text); - if (cellRef) { - eles.push(this.generateSpan(cellRef[0], cellRef[1])); - } else if (text && !text.replace('{{date}}', '')){ - eles.push(); - } else if (text && !text.replace('{{boolean}}', '')) { - eles.push(boolean thing); - } else { - eles.push({text}); - } - }); - - return eles; - } - - parseElements = (content: string) => { - let string: string = content; - if (string.startsWith(':')) string = string.slice(1); - if (string.startsWith('=')) string = string.slice(1); - - const chunks: string[] = []; - - let subStr: string = ''; - let currChar = ''; - for (let i = 0; i < string.length; i++){ - currChar = string[i]; - if (((string.charCodeAt(i) === 32 || string.charCodeAt(i) === 160) && subStr.trim()) || (currChar !== ' ' && !subStr.trim())) { - chunks.push(subStr); - subStr = currChar; - } else { - subStr += currChar; - } - } - - if (subStr) {chunks.push(subStr)}; - - return this.elementsFromText(chunks); - } - - // ` | undefined) => { - // if ((value?.nativeEvent as any).shiftKey) { - // this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + (value?.target?.checked.toString() ?? '')); - // } else Doc.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + (value?.target?.checked.toString() ?? '')); - // })} - // />` - @action setContent = (content: string, restoreCursorPos?: boolean) => { const pos = this.cursorPosition; - this._displayedContent = content; - this._displayedElements = this.parseElements(content); + this._displayedContent = this.makeSpans(content); restoreCursorPos && setTimeout(() => this.setCursorPosition(pos)); } @@ -339,9 +233,8 @@ export class SchemaCellField extends ObservableReactComponent this.parseElements(this._displayedContent).length) this.setContent(targVal, true); + if (this.shouldUpdate(prevVal, targVal)) {this.setContent(targVal, true)}; this.setupRefSelect(this.refSelectConditionMet); - console.log(this.parseElements(targVal)); }; setupRefSelect = (enabled: boolean) => { @@ -458,12 +351,8 @@ export class SchemaCellField extends ObservableReactComponent e.stopPropagation} onPointerUp={e => e.stopPropagation} onPointerMove={e => {e.stopPropagation(); e.preventDefault()}} - suppressContentEditableWarning={true} - //dangerouslySetInnerHTML={{ __html: this._displayedContent }} + dangerouslySetInnerHTML={{ __html: this._displayedContent }} > - {this._displayedElements.map((ele, index) => { - return {ele}; - })}
); } diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 40509c41b..9f6478041 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -249,4 +249,4 @@ export class SchemaColumnHeader extends ObservableReactComponent ); } -} +} \ No newline at end of file diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 72f5d8c25..ec94a8077 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -24,7 +24,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { infoState } from '../collectionFreeForm/CollectionFreeFormInfoState'; import { TbShieldX } from 'react-icons/tb'; -import { DocumentType } from '../../../documents/DocumentTypes'; interface SchemaRowBoxProps extends FieldViewProps { rowIndex: number; @@ -78,7 +77,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { icon: 'minus', }); const childDocs = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)]) - if (childDocs.length) { + if (this.Document.type === 'collection' && childDocs.length) { ContextMenu.Instance.addItem({ description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema', event: () => { @@ -197,4 +196,4 @@ export class SchemaRowBox extends ViewBoxBaseComponent() {
); } -} +} \ No newline at end of file diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 7d29e40cc..e2a05da7f 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -389,7 +389,7 @@ export class SchemaDateCell extends ObservableReactComponent -
+
{pointerEvents === 'none' ? null : ( diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index dcdd52c73..8273f3e09 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -375,7 +375,6 @@ export class DocCreatorMenu extends ObservableReactComponent { if (res && this._callCount === origCount) { this._suggestedTemplates = []; - this._GPTLoading = false; const templates: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[] = JSON.parse(res); this.createGeneratedTemplates(templates, 500, 500); } @@ -714,7 +713,7 @@ export class DocCreatorMenu extends ObservableReactComponent { try { const renderedImages: Doc[] = await Promise.all( calls.map(async ([fieldNum, col]) => { - const sysPrompt = 'Your job is to create a prompt for an AI image generator to help it generate an image based on existing content in a template and a user prompt. ONLY INCLUDE THE PROMPT, NO OTHER TEXT OR EXPLANATION. The existing content is as follows: ' + fieldContent + ' **** The user prompt is: ' + col.desc; + const sysPrompt = 'Your job is to create a prompt for an AI image generator to help it generate an image based on existing content in a template and a user prompt. Your prompt should focus heavily on visual elements to help the image generator; avoid unecessary info that might distract it. ONLY INCLUDE THE PROMPT, NO OTHER TEXT OR EXPLANATION. The existing content is as follows: ' + fieldContent + ' **** The user prompt is: ' + col.desc; const prompt = await gptAPICall(sysPrompt, GPTCallType.COMPLETEPROMPT); console.log(sysPrompt, prompt); @@ -852,7 +851,6 @@ export class DocCreatorMenu extends ObservableReactComponent { const res = await gptAPICall(prompt, GPTCallType.TEMPLATE); if (res && this._callCount === origCount) { - this._GPTLoading = false; const assignments: {[templateTitle: string]: {[field: string]: string}} = JSON.parse(res); const brokenDownAssignments: [TemplateDocInfos, {[field: number]: Col}][] = []; @@ -889,7 +887,7 @@ export class DocCreatorMenu extends ObservableReactComponent { const renderedTemplates: Doc[] = await Promise.all(renderedTemplatePromises); - setTimeout(() => { this.setGSuggestedTemplates(renderedTemplates) }); + setTimeout(() => { this.setGSuggestedTemplates(renderedTemplates); this._GPTLoading = false }); }; @action setExpandedView = (info: {icon: ImageField, doc: Doc} | undefined) => { @@ -908,6 +906,7 @@ export class DocCreatorMenu extends ObservableReactComponent {
{this._expandedPreview ?
+
); + } } -- cgit v1.2.3-70-g09d2 From a734c38aa317b8ca9bf2b19853115872824f2b97 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 9 Sep 2024 00:39:24 -0400 Subject: c --- src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx | 6 ++++-- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 5 +---- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 07d3c3e9c..01d5bc83b 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -1772,7 +1772,8 @@ export class TemplateLayouts { opts: { backgroundColor: 'transparent', color: 'white', - contentXCentering: 'h-center' + contentXCentering: 'h-center', + fontTransform: 'uppercase' } }, { tl: [-.65, 0], @@ -1783,7 +1784,8 @@ export class TemplateLayouts { opts: { backgroundColor: 'transparent', color: 'white', - contentXCentering: 'h-center' + contentXCentering: 'h-center', + fontTransform: 'uppercase' } }, { tl: [-.83, .2], diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 5095da1c4..3b21df2ed 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1425,7 +1425,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent void); setupEditor(config: any, fieldKey: string) { - try { const curText = Cast(this.dataDoc[this.fieldKey], RichTextField, null) || StrCast(this.dataDoc[this.fieldKey]); const rtfField = Cast((!curText && this.layoutDoc[this.fieldKey]) || this.dataDoc[fieldKey], RichTextField); if (this.ProseRef) { @@ -1521,9 +1520,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent this._editorView!.focus()); // not sure why setTimeout is needed but editing dashFieldView's doesn't work without it. - } catch (e) { - console.log(e); - } + } // add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet. -- cgit v1.2.3-70-g09d2 From 9323ad30103b474e95610e97eb92916a0cf71f7b Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 4 Oct 2024 21:35:22 -0400 Subject: more lint fixes to schema view changes. --- src/ClientUtils.ts | 5 +- src/client/util/LinkManager.ts | 2 +- src/client/util/Scripting.ts | 8 +- src/client/util/SelectionManager.ts | 1 - src/client/views/FieldsDropdown.tsx | 4 +- src/client/views/PropertiesView.tsx | 2 +- .../collectionSchema/CollectionSchemaView.tsx | 327 +++++++++++---------- .../collectionSchema/SchemaColumnHeader.tsx | 264 +++++++++-------- .../collections/collectionSchema/SchemaRowBox.tsx | 48 +-- .../collectionSchema/SchemaTableCell.tsx | 82 +++--- src/client/views/global/globalScripts.ts | 1 - src/client/views/nodes/DataVizBox/DataVizBox.tsx | 177 ++++++----- src/client/views/nodes/DocumentIcon.tsx | 10 +- src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/nodes/LabelBox.tsx | 4 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 2 - 16 files changed, 485 insertions(+), 454 deletions(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts index 8ecbc55bf..3066499d8 100644 --- a/src/ClientUtils.ts +++ b/src/ClientUtils.ts @@ -317,7 +317,7 @@ export namespace ClientUtils { } export function lightenRGB(rVal: number, gVal: number, bVal: number, percent: number): [number, number, number] { - const amount = 1 + percent/100; + const amount = 1 + percent / 100; const r = rVal * amount; const g = gVal * amount; const b = bVal * amount; @@ -347,8 +347,6 @@ export namespace ClientUtils { return undefined; } - - export function GetClipboardText(): string { const textArea = document.createElement('textarea'); document.body.appendChild(textArea); @@ -725,7 +723,6 @@ export function UpdateIcon( const newDiv = docViewContent.cloneNode(true) as HTMLDivElement; newDiv.style.width = width.toString(); newDiv.style.height = height.toString(); - console.log('width: ' + newDiv.style.width) replaceCanvases(docViewContent, newDiv); const htmlString = new XMLSerializer().serializeToString(newDiv); const nativeWidth = width; diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index bbf8d9c11..e11482572 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -260,7 +260,7 @@ export function UPDATE_SERVER_CACHE() { Doc.MyDockedBtns.linearView_IsOpen && console.log('Set cached docs = '); const isFiltered = filtered.filter(doc => !Doc.IsSystem(doc)); const strings = isFiltered.map(doc => StrCast(doc.title) + ' ' + (Doc.IsDataProto(doc) ? '(data)' : '(embedding)')); - //Doc.MyDockedBtns.linearView_IsOpen && strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str)); + Doc.MyDockedBtns.linearView_IsOpen && strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str)); rp.post(ClientUtils.prepend('/setCacheDocumentIds'), { body: { diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 3ba3ff4b5..b1db0bf39 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -81,6 +81,7 @@ function Run(script: string | undefined, customParams: string[], diagnostics: ts if (!options.editable) { batch = Doc.MakeReadOnly(); } + const result = compiledFunction.apply(thisParam, params).apply(thisParam, argsArray); batch?.end(); return { success: true, result }; @@ -177,13 +178,8 @@ function forEachNode(node: ts.Node, onEnter: Traverser, onExit?: Traverser, inde ); } -// ScriptField.CompileScript(value, {}, true, undefined, DocumentIconContainer.getTransformer()); -// //addreturn = true -// //capturedvariables = undefined -// // - export function CompileScript(script: string, options: ScriptOptions = {}): CompileResult { - const captured = options.capturedVariables ?? {}; + const captured = options.capturedVariables ?? {}; const signature = Object.keys(captured).reduce((p, v) => { const formatCapture = (obj: FieldType | undefined) => `${v}=${obj instanceof RefField ? 'XXX' : obj?.toString()}`; const captureVal = captured[v]; diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index c39d8ebc7..1ab84421c 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -58,7 +58,6 @@ export class SelectionManager { }); public static DeselectAll = (except?: Doc): void => { - const found = this.Instance.SelectedViews.find(dv => dv.Document === except); runInAction(() => { if (LinkManager.Instance) { diff --git a/src/client/views/FieldsDropdown.tsx b/src/client/views/FieldsDropdown.tsx index 176ac96b6..407031b40 100644 --- a/src/client/views/FieldsDropdown.tsx +++ b/src/client/views/FieldsDropdown.tsx @@ -34,7 +34,7 @@ export class FieldsDropdown extends ObservableReactComponent(); SearchUtil.foreachRecursiveDoc([this._props.Document], (depth, doc) => allDocs.add(doc)); return Array.from(allDocs); @@ -57,7 +57,7 @@ export class FieldsDropdown extends ObservableReactComponent facet[0] === facet.charAt(0).toUpperCase())]; Object.entries(DocOptions) - .filter(opts => opts[1].filterable) //!!! + .filter(opts => opts[1].filterable) .forEach((pair: [string, FInfo]) => filteredOptions.push(pair[0])); const options = filteredOptions.sort().map(facet => ({ value: facet, label: facet })); diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 69c46052e..c6dccb4fb 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -884,7 +884,7 @@ export class PropertiesView extends ObservableReactComponent(); private _headerRefs: SchemaColumnHeader[] = []; - private _eqHighlightColors: Array<[{r: number, g: number, b: number}, {r: number, g: number, b: number}]> = []; + private _eqHighlightColors: Array<[{ r: number; g: number; b: number }, { r: number; g: number; b: number }]> = []; + private _oldWheel: HTMLDivElement | null = null; constructor(props: SubCollectionViewProps) { super(props); makeObservable(this); const lightenedColor = (r: number, g: number, b:number) => { const lightened = ClientUtils.lightenRGB(r, g, b, 165); return {r: lightened[0], g: lightened[1], b: lightened[2]}} // prettier-ignore - const colors = (r: number, g: number, b: number): [any, any] => {return [{r: r, g: g, b: b}, lightenedColor(r, g, b)]} // prettier-ignore + const colors = (r: number, g: number, b: number):[{r:number,g:number,b:number},{r:number,g:number,b:number}] => ([{r, g, b}, lightenedColor(r, g, b)]); // prettier-ignore this._eqHighlightColors.push(colors(70, 150, 50)); this._eqHighlightColors.push(colors(180, 70, 20)); this._eqHighlightColors.push(colors(70, 50, 150)); @@ -122,8 +123,8 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _highlightedCellsInfo: Array<[doc: Doc, field: string]> = []; @observable _cellHighlightColors: ObservableMap = new ObservableMap(); @observable _containedDocs: Doc[] = []; //all direct children of the schema - @observable _referenceSelectMode: {enabled: boolean, currEditing: SchemaCellField | undefined} = {enabled: false, currEditing: undefined} - + @observable _referenceSelectMode: { enabled: boolean; currEditing: SchemaCellField | undefined } = { enabled: false, currEditing: undefined }; + // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { return this._menuTarget.current; @@ -217,15 +218,17 @@ export class CollectionSchemaView extends CollectionSubView() { true ); this._disposers.docdata = reaction( - () => DocListCast(this.dataDoc[this.fieldKey]), - (docs) => this._containedDocs = docs, - {fireImmediately: true} - ) + () => DocListCast(this.dataDoc[this.fieldKey]), + docs => (this._containedDocs = docs), + { fireImmediately: true } + ); this._disposers.sortHighlight = reaction( - () => [this.sortField, this._containedDocs, this._selectedDocs, this._highlightedCellsInfo], - () => {this.sortField && setTimeout(() => this.highlightSortedColumn())}, - {fireImmediately: true} - ) + () => [this.sortField, this._containedDocs, this._selectedDocs, this._highlightedCellsInfo], + () => { + this.sortField && setTimeout(() => this.highlightSortedColumn()); + }, + { fireImmediately: true } + ); } componentWillUnmount() { @@ -239,8 +242,8 @@ export class CollectionSchemaView extends CollectionSubView() { removeDoc = (doc: Doc) => { this.removeDocument(doc); - this._containedDocs = this._containedDocs.filter(d => d !== doc) - } + this._containedDocs = this._containedDocs.filter(d => d !== doc); + }; rowIndex = (doc: Doc) => this.docsWithDrag.docs.indexOf(doc); @@ -301,7 +304,9 @@ export class CollectionSchemaView extends CollectionSubView() { } break; case 'Backspace': { - undoable(() => {this._selectedDocs.forEach(d => this._containedDocs.includes(d) && this.removeDoc(d));}, 'delete schema row'); + undoable(() => { + this._selectedDocs.forEach(d => this._containedDocs.includes(d) && this.removeDoc(d)); + }, 'delete schema row'); break; } case 'Escape': { @@ -319,7 +324,7 @@ export class CollectionSchemaView extends CollectionSubView() { addRow = (doc: Doc | Doc[]) => this.addDocument(doc); @undoBatch - changeColumnKey = (index: number, newKey: string, defaultVal?: any) => { + changeColumnKey = (index: number, newKey: string, defaultVal?: FieldType) => { if (!this.documentKeys.includes(newKey)) this.addNewKey(newKey, defaultVal); const currKeys = this.columnKeys.slice(); // copy the column key array first, then change it. @@ -328,9 +333,10 @@ export class CollectionSchemaView extends CollectionSubView() { }; @undoBatch - addColumn = (index: number = 0, key?: string, defaultVal?: any) => { + addColumn = (index: number = 0, keyIn?: string, defaultVal?: FieldType) => { + let key = keyIn; if (key && !this.documentKeys.includes(key)) this.addNewKey(key, defaultVal); - + const newColWidth = this.tableWidth / (this.storedColumnWidths.length + 1); const currWidths = this.storedColumnWidths.slice(); currWidths.splice(index, 0, newColWidth); @@ -345,11 +351,11 @@ export class CollectionSchemaView extends CollectionSubView() { }; @action - addNewKey = (key: string, defaultVal: any) => { + addNewKey = (key: string, defaultVal: FieldType | undefined) => { this.childDocs.forEach(doc => { doc[DocData][key] = defaultVal; }); - } + }; @undoBatch removeColumn = (index: number) => { @@ -365,13 +371,13 @@ export class CollectionSchemaView extends CollectionSubView() { const currKeys = this.columnKeys.slice(); currKeys.splice(index, 1); - this.layoutDoc.schema_columnKeys = new List(currKeys); + this.layoutDoc.schema_columnKeys = new List(currKeys); this._colEles.splice(index, 1); }; @action - startResize = (e: any, index: number, rightSide: boolean) => { + startResize = (e: React.PointerEvent, index: number, rightSide: boolean) => { this._displayColumnWidths = this.storedColumnWidths; setupMoveUpEvents(this, e, moveEv => this.resizeColumn(moveEv, index, rightSide), this.finishResize, emptyFunction); }; @@ -384,8 +390,8 @@ export class CollectionSchemaView extends CollectionSubView() { let change = e.movementX; - if (rightSide && (index !== this._displayColumnWidths.length - 1)) { - growing = change < 0 ? index + 1: index; + if (rightSide && index !== this._displayColumnWidths.length - 1) { + growing = change < 0 ? index + 1 : index; shrinking = change < 0 ? index : index + 1; } else if (index !== 0) { growing = change < 0 ? index : index - 1; @@ -432,7 +438,7 @@ export class CollectionSchemaView extends CollectionSubView() { this.closeNewColumnMenu(); this._headerRefs.forEach(ref => ref.toggleEditing(false)); this._draggedColIndex = index; - this.setColDrag(true); + this.setColDrag(true); const dragData = new DragManager.ColumnDragData(index); const dragEles = [this._colEles[index]]; this.childDocs.forEach(doc => dragEles.push(this._rowEles.get(doc).children[1].children[index])); @@ -446,7 +452,7 @@ export class CollectionSchemaView extends CollectionSubView() { * @returns column index */ findColDropIndex = (mouseX: number) => { - const xOffset: number = this._props.ScreenToLocalTransform().inverse().transformPoint(0,0)[0] + CollectionSchemaView._rowMenuWidth; + const xOffset: number = this._props.ScreenToLocalTransform().inverse().transformPoint(0, 0)[0] + CollectionSchemaView._rowMenuWidth; let index: number | undefined; this.displayColumnWidths.reduce((total, curr, i) => { if (total <= mouseX && total + curr >= mouseX) { @@ -507,12 +513,7 @@ export class CollectionSchemaView extends CollectionSubView() { this._colEles.forEach((colRef, i) => { const edgeStyle = i === index ? `solid 2px ${Colors.MEDIUM_BLUE}` : ''; const sorted = i === this.columnKeys.indexOf(this.sortField); - const cellEles = [ - colRef, - ...this.docsWithDrag.docs - .filter(doc => (i !== this._selectedCol || !this._selectedDocs.includes(doc)) && !sorted) - .map(doc => this._rowEles.get(doc).children[1].children[i]), - ]; + const cellEles = [colRef, ...this.docsWithDrag.docs.filter(doc => (i !== this._selectedCol || !this._selectedDocs.includes(doc)) && !sorted).map(doc => this._rowEles.get(doc).children[1].children[i])]; cellEles.forEach(ele => { if (sorted || this.highlightedCells.includes(ele)) return; ele.style.borderTop = ele === cellEles[0] ? edgeStyle : ''; @@ -533,14 +534,14 @@ export class CollectionSchemaView extends CollectionSubView() { this.childDocs.forEach(doc => { const cell = this._rowEles.get(doc).children[1].children[i]; - if (!(this._selectedDocs.includes(doc) && i === this._selectedCol) && !(this.highlightedCells.includes(cell)) && cell) { + if (!(this._selectedDocs.includes(doc) && i === this._selectedCol) && !this.highlightedCells.includes(cell) && cell) { cell.style.borderLeft = ''; cell.style.borderRight = ''; cell.style.borderBottom = ''; } }); }); - } + }; /** * Applies a gradient highlight to a sorted column. The direction of the gradient depends @@ -552,10 +553,10 @@ export class CollectionSchemaView extends CollectionSubView() { let index = -1; const highlightColors: string[] = []; const rowCount: number = this._containedDocs.length + 1; - if (field || this.sortField){ + if (field || this.sortField) { index = this.columnKeys.indexOf(field || this.sortField); - const increment: number = 110/rowCount; - for (let i = 1; i <= rowCount; ++i){ + const increment: number = 110 / rowCount; + for (let i = 1; i <= rowCount; ++i) { const adjColor = ClientUtils.lightenRGB(16, 66, 230, increment * i); highlightColors.push(`solid 2px rgb(${adjColor[0]}, ${adjColor[1]}, ${adjColor[2]})`); } @@ -564,25 +565,20 @@ export class CollectionSchemaView extends CollectionSubView() { this._colEles.forEach((colRef, i) => { const highlight: boolean = i === index; const desc: boolean = descending || this.sortDesc; - const cellEles = [ - colRef, - ...this.docsWithDrag.docs - .filter(doc => (i !== this._selectedCol || !this._selectedDocs.includes(doc))) - .map(doc => this._rowEles.get(doc).children[1].children[i]), - ]; + const cellEles = [colRef, ...this.docsWithDrag.docs.filter(doc => i !== this._selectedCol || !this._selectedDocs.includes(doc)).map(doc => this._rowEles.get(doc).children[1].children[i])]; const cellCount = cellEles.length; - for (let ele = 0; ele < cellCount; ++ele){ + for (let ele = 0; ele < cellCount; ++ele) { const currCell = cellEles[ele]; if (this.highlightedCells.includes(currCell)) continue; - const style = highlight ? desc ? `${highlightColors[cellCount - 1 - ele]}` : `${highlightColors[ele]}` : ''; + const style = highlight ? (desc ? `${highlightColors[cellCount - 1 - ele]}` : `${highlightColors[ele]}`) : ''; currCell.style.borderLeft = style; currCell.style.borderRight = style; } - cellEles[0].style.borderTop = highlight ? desc ? `${highlightColors[cellCount - 1]}` : `${highlightColors[0]}` : ''; - if (!(this._selectedDocs.includes(this.docsWithDrag.docs[this.docsWithDrag.docs.length - 1]) && this._selectedCol === index) && !this.highlightedCells.includes(cellEles[cellCount - 1])) cellEles[cellCount - 1].style.borderBottom = highlight ? desc ? `${highlightColors[0]}` : `${highlightColors[cellCount - 1]}` : ''; + cellEles[0].style.borderTop = highlight ? (desc ? `${highlightColors[cellCount - 1]}` : `${highlightColors[0]}`) : ''; + if (!(this._selectedDocs.includes(this.docsWithDrag.docs[this.docsWithDrag.docs.length - 1]) && this._selectedCol === index) && !this.highlightedCells.includes(cellEles[cellCount - 1])) + cellEles[cellCount - 1].style.borderBottom = highlight ? (desc ? `${highlightColors[0]}` : `${highlightColors[cellCount - 1]}`) : ''; }); - - } + }; /** * Gets the html element representing a cell so that styles can be applied on it. @@ -594,35 +590,40 @@ export class CollectionSchemaView extends CollectionSubView() { const index = this.columnKeys.indexOf(fieldKey); const cell = this._rowEles.get(doc).children[1].children[index]; return cell; - } + }; /** * Given text in a cell, find references to other cells (for equations). * @param text the text in the cell - * @returns the html cell elements referenced in the text. + * @returns the html cell elements referenced in the text. */ findCellRefs = (text: string) => { const pattern = /(this|d(\d+))\.(\w+)/g; - interface Match { docRef: string; field: string; } + interface Match { + docRef: string; + field: string; + } const matches: Match[] = []; let match: RegExpExecArray | null; while ((match = pattern.exec(text)) !== null) { - const docRef = match[1] === 'this' ? match[1] : match[2]; + const docRef = match[1] === 'this' ? match[1] : match[2]; matches.push({ docRef, field: match[3] }); } - const cells: Array = []; - matches.forEach((match: Match) => { - const {docRef, field} = match; + const cells: [Doc, string][] = []; + matches.forEach((m: Match) => { + const { docRef, field } = m; const docView = DocumentManager.Instance.DocumentViews[Number(docRef)]; const doc = docView?.Document ?? undefined; - if (this.columnKeys.includes(field) && this._containedDocs.includes(doc)) {cells.push([doc, field])} - }) + if (this.columnKeys.includes(field) && this._containedDocs.includes(doc)) { + cells.push([doc, field]); + } + }); return cells; - } + }; /** * Determines whether the rows above or below a given row have been @@ -636,7 +637,7 @@ export class CollectionSchemaView extends CollectionSubView() { const selectedBelow: boolean = this._selectedDocs.includes(docs[index + 1]); const selectedAbove: boolean = this._selectedDocs.includes(docs[index - 1]); return [selectedAbove, selectedBelow]; - } + }; @action removeCellHighlights = () => { @@ -649,9 +650,10 @@ export class CollectionSchemaView extends CollectionSubView() { if (this.selectionOverlap(doc)[0]) cell.style.borderTop = ''; if (this.selectionOverlap(doc)[1]) cell.style.borderBottom = ''; } else cell.style.border = ''; - cell.style.backgroundColor = '';}); + cell.style.backgroundColor = ''; + }); this._highlightedCellsInfo = []; - } + }; restoreCellHighlights = () => { this._highlightedCellsInfo.forEach(info => { @@ -665,10 +667,10 @@ export class CollectionSchemaView extends CollectionSubView() { cell.style.borderRight = color; cell.style.borderBottom = color; }); - } + }; /** - * Highlights cells based on equation text in the cell currently being edited. + * Highlights cells based on equation text in the cell currently being edited. * Does not highlight selected cells (that's done directly in SchemaTableCell). * @param text the equation */ @@ -682,7 +684,7 @@ export class CollectionSchemaView extends CollectionSubView() { const info = this._highlightedCellsInfo[i]; const color = this._eqHighlightColors[i % 10]; const colorStrings = [`solid 2px rgb(${color[0].r}, ${color[0].g}, ${color[0].b})`, `rgb(${color[1].r}, ${color[1].g}, ${color[1].b})`]; - const doc = info[0]; + const doc = info[0]; const field = info[1]; const key = `${doc[Id]}_${field}`; const cell = this.getCellElement(doc, field); @@ -690,7 +692,7 @@ export class CollectionSchemaView extends CollectionSubView() { cell.style.border = colorStrings[0]; cell.style.backgroundColor = colorStrings[1]; } - } + }; //Used in SchemaRowBox @action @@ -718,7 +720,6 @@ export class CollectionSchemaView extends CollectionSubView() { this.deselectAllCells(); }; - selectRow = (doc: Doc, lastSelected: Doc) => { const index = this.rowIndex(doc); const lastSelectedRow = this.rowIndex(lastSelected); @@ -737,12 +738,12 @@ export class CollectionSchemaView extends CollectionSubView() { if (!doc) return; const docIndex = DocumentView.getDocViewIndex(doc); const field = this.columnKeys[col]; - const refToAdd = `d${docIndex}.${field}` - const editedField = this._referenceSelectMode.currEditing ? this._referenceSelectMode.currEditing as SchemaCellField : null; + const refToAdd = `d${docIndex}.${field}`; + const editedField = this._referenceSelectMode.currEditing ? (this._referenceSelectMode.currEditing as SchemaCellField) : null; editedField?.insertText(refToAdd, true); editedField?.setupRefSelect(false); return; - } + }; @action selectCell = (doc: Doc, col: number, shiftKey: boolean, ctrlKey: boolean) => { @@ -787,7 +788,9 @@ export class CollectionSchemaView extends CollectionSubView() { @action onInternalDrop = (e: Event, de: DragManager.DropEvent) => { if (de.complete.columnDragData) { - setTimeout(() => {this.setColDrag(false);}); + setTimeout(() => { + this.setColDrag(false); + }); e.stopPropagation(); return true; } @@ -849,9 +852,9 @@ export class CollectionSchemaView extends CollectionSubView() { }; @action - setKey = (key: string, defaultVal?: any, index?: number) => { + setKey = (key: string, defaultVal?: string, index?: number) => { if (this.columnKeys.includes(key)) return; - + if (this._makeNewColumn) { this.addColumn(this.columnKeys.indexOf(key), key, defaultVal); this._makeNewColumn = false; @@ -861,14 +864,14 @@ export class CollectionSchemaView extends CollectionSubView() { }; /** - * Used in SchemaRowBox to set - * @param key - * @param value - * @returns + * Used in SchemaRowBox to set + * @param key + * @param value + * @returns */ setCellValues = (key: string, value: string) => { - if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); - else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); + if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); + else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); return true; }; @@ -912,34 +915,36 @@ export class CollectionSchemaView extends CollectionSubView() { const cm = ContextMenu.Instance; cm.clearItems(); - const fieldSortedAsc = (this.sortField === this.columnKeys[index] && !this.sortDesc); - const fieldSortedDesc = (this.sortField === this.columnKeys[index] && this.sortDesc); - const revealOptions = cm.findByDescription('Sort column') - const sortOptions: ContextMenuProps[] = revealOptions && revealOptions && 'subitems' in revealOptions ? revealOptions.subitems ?? [] : []; + const fieldSortedAsc = this.sortField === this.columnKeys[index] && !this.sortDesc; + const fieldSortedDesc = this.sortField === this.columnKeys[index] && this.sortDesc; + const revealOptions = cm.findByDescription('Sort column'); + const sortOptions: ContextMenuProps[] = revealOptions && revealOptions && 'subitems' in revealOptions ? (revealOptions.subitems ?? []) : []; sortOptions.push({ - description: 'Sort A-Z', + description: 'Sort A-Z', event: () => { - this.setColumnSort(undefined); + this.setColumnSort(undefined); const field = this.columnKeys[index]; this._containedDocs = this.sortDocs(field, false); setTimeout(() => { this.highlightSortedColumn(field, false); - setTimeout(() => this.highlightSortedColumn(), 480); + setTimeout(() => this.highlightSortedColumn(), 480); }, 20); - }, - icon: 'arrow-down-a-z',}); + }, + icon: 'arrow-down-a-z', + }); sortOptions.push({ - description: 'Sort Z-A', + description: 'Sort Z-A', event: () => { - this.setColumnSort(undefined); + this.setColumnSort(undefined); const field = this.columnKeys[index]; this._containedDocs = this.sortDocs(field, true); setTimeout(() => { this.highlightSortedColumn(field, true); - setTimeout(() => this.highlightSortedColumn(), 480); + setTimeout(() => this.highlightSortedColumn(), 480); }, 20); - }, - icon: 'arrow-up-z-a'}); + }, + icon: 'arrow-up-z-a', + }); sortOptions.push({ description: 'Persistent Sort A-Z', event: () => { @@ -964,7 +969,7 @@ export class CollectionSchemaView extends CollectionSubView() { } }, icon: fieldSortedDesc ? 'lock' : 'lock-open'}); // prettier-ignore - + cm.addItem({ description: `Change field`, event: () => this.openNewColumnMenu(index, false), @@ -975,12 +980,12 @@ export class CollectionSchemaView extends CollectionSubView() { event: () => this.openFilterMenu(index), icon: 'filter', }); - cm.addItem({ - description: 'Sort column', - addDivider: false, - noexpand: true, - subitems: sortOptions, - icon: 'sort' + cm.addItem({ + description: 'Sort column', + addDivider: false, + noexpand: true, + subitems: sortOptions, + icon: 'sort', }); cm.addItem({ description: 'Add column to left', @@ -1068,7 +1073,7 @@ export class CollectionSchemaView extends CollectionSubView() { @computed get renderColumnMenu() { const x = this._columnMenuIndex! === -1 ? 0 : this.displayColumnWidths.reduce((total, curr, index) => total + (index < this._columnMenuIndex! ? curr : 0), CollectionSchemaView._rowMenuWidth); return ( -
+
{this.keysDropdown}
); @@ -1095,13 +1100,7 @@ export class CollectionSchemaView extends CollectionSubView() { } return (
- e.stopPropagation()} - onClick={e => e.stopPropagation()} - onChange={e => Doc.setDocFilter(this.Document, columnKey, key, e.target.checked ? 'check' : 'remove')} - checked={bool} - /> + e.stopPropagation()} onClick={e => e.stopPropagation()} onChange={e => Doc.setDocFilter(this.Document, columnKey, key, e.target.checked ? 'check' : 'remove')} checked={bool} /> {key}
); @@ -1111,7 +1110,7 @@ export class CollectionSchemaView extends CollectionSubView() { @computed get renderFilterMenu() { const x = this.displayColumnWidths.reduce((total, curr, index) => total + (index < this._filterColumnIndex! ? curr : 0), CollectionSchemaView._rowMenuWidth); return ( -
+
e.stopPropagation()} /> {this.renderFilterOptions}
{ this._colBeingDragged = beingDragged; !beingDragged && this.removeDragHighlight(); - } + }; @action updateMouseCoordinates = (e: React.PointerEvent) => { const prevX = this._mouseCoordinates.x; const prevY = this._mouseCoordinates.y; this._mouseCoordinates = { x: e.clientX, y: e.clientY, prevX: prevX, prevY: prevY }; - } + }; @action onPointerMove = (e: React.PointerEvent) => { @@ -1158,9 +1157,9 @@ export class CollectionSchemaView extends CollectionSubView() { /** * Gets docs contained by collections within the schema. Currently defunct. - * @param doc - * @param displayed - * @returns + * @param doc + * @param displayed + * @returns */ // subCollectionDocs = (doc: Doc, displayed: boolean) => { // const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]); @@ -1203,8 +1202,7 @@ export class CollectionSchemaView extends CollectionSubView() { subDocs.forEach(t => { const docFieldKey = Doc.LayoutFieldKey(t); const isSubDocAnnotatable = t[docFieldKey] instanceof List && !(t[docFieldKey] as List)?.some(ele => !(ele instanceof Doc)); - notFiltered = - notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!childDocFilters.length && !childFiltersByRanges.length) || DocUtils.FilterDocs([t], childDocFilters, childFiltersByRanges, d).length)); + notFiltered = notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!childDocFilters.length && !childFiltersByRanges.length) || DocUtils.FilterDocs([t], childDocFilters, childFiltersByRanges, d).length)); DocListCast(t[isSubDocAnnotatable ? docFieldKey + '_annotations' : docFieldKey]).forEach(newdoc => newarray.push(newdoc)); isSubDocAnnotatable && DocListCast(t[docFieldKey + '_sidebar']).forEach(newdoc => newarray.push(newdoc)); }); @@ -1231,19 +1229,19 @@ export class CollectionSchemaView extends CollectionSubView() { // docsFromChildren = docsFromChildren.concat(docsNotAlreadyDisplayed); // }); - return this.filteredDocs;; + return this.filteredDocs; } /** - * Sorts docs first alphabetically and then numerically. + * Sorts docs first alphabetically and then numerically. * @param field the column being sorted * @param desc whether the sort is ascending or descending * @param persistent whether the sort is applied persistently or is one-shot - * @returns + * @returns */ sortDocs = (field: string, desc: boolean, persistent?: boolean) => { const numbers: Doc[] = []; - const strings: Doc[] = []; + const strings: Doc[] = []; this.docs.forEach(doc => { if (!isNaN(Number(Field.toString(doc[field] as FieldType)))) numbers.push(doc); @@ -1253,25 +1251,26 @@ export class CollectionSchemaView extends CollectionSubView() { const sortedNums = numbers.sort((numOne, numTwo) => { const numA = Number(Field.toString(numOne[field] as FieldType)); const numB = Number(Field.toString(numTwo[field] as FieldType)); - return desc? numA - numB : numB - numA; + return desc ? numA - numB : numB - numA; }); - const collator = new Intl.Collator(undefined, {sensitivity: 'base'}); + const collator = new Intl.Collator(undefined, { sensitivity: 'base' }); let sortedStrings; - if (!desc) {sortedStrings = strings.slice().sort((docA, docB) => collator.compare(Field.toString(docA[field] as FieldType), Field.toString(docB[field] as FieldType))); + if (!desc) { + sortedStrings = strings.slice().sort((docA, docB) => collator.compare(Field.toString(docA[field] as FieldType), Field.toString(docB[field] as FieldType))); } else sortedStrings = strings.slice().sort((docB, docA) => collator.compare(Field.toString(docA[field] as FieldType), Field.toString(docB[field] as FieldType))); const sortedDocs = desc ? sortedNums.concat(sortedStrings) : sortedStrings.concat(sortedNums); if (!persistent) this._containedDocs = sortedDocs; return sortedDocs; - } - + }; + /** * Returns all docs minus those currently being dragged by the user. */ @computed get docsWithDrag() { let docs = this.docs.slice(); - if (this.sortField){ + if (this.sortField) { const field = StrCast(this.layoutDoc.sortField); const desc = BoolCast(this.layoutDoc.sortDesc); // is this an ascending or descending sort docs = this.sortDocs(field, desc, true); @@ -1290,13 +1289,17 @@ export class CollectionSchemaView extends CollectionSubView() { previewWidthFunc = () => this.previewWidth; onPassiveWheel = (e: WheelEvent) => e.stopPropagation(); displayedDocsFunc = () => this.docsWithDrag.docs; - _oldWheel: any; render() { return ( -
this.createDashEventsTarget(ele)} - onDrop={this.onExternalDrop.bind(this)} - onPointerMove={e => this.onPointerMove(e)} - onPointerDown={() => {this.closeNewColumnMenu(); this.setColDrag(false)}}> +
this.createDashEventsTarget(ele)} + onDrop={this.onExternalDrop.bind(this)} + onPointerMove={e => this.onPointerMove(e)} + onPointerDown={() => { + this.closeNewColumnMenu(); + this.setColDrag(false); + }}>
} - size={Size.XSMALL} - color={'black'} - onPointerDown={e => - setupMoveUpEvents( - this, - e, - returnFalse, - emptyFunction, - undoable(clickEv => { - clickEv.stopPropagation(); - this.addColumn() - }, 'add key to schema') - ) - } + tooltip="Add a new key" + icon={} + size={Size.XSMALL} + color={'black'} + onPointerDown={e => + setupMoveUpEvents( + this, + e, + returnFalse, + emptyFunction, + undoable(clickEv => { + clickEv.stopPropagation(); + this.addColumn(); + }, 'add key to schema') + ) + } />
{this.columnKeys.map((key, index) => ( r && this._headerRefs.push(r)} - keysDropdown={(this.keysDropdown)} + keysDropdown={this.keysDropdown} schemaView={this} columnWidth={() => CollectionSchemaView._minColWidth} //TODO: update Document={this.Document} @@ -1445,7 +1447,6 @@ class CollectionSchemaViewDoc extends ObservableReactComponent ); } -} \ No newline at end of file +} diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index c5cdac8af..47918f9c1 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/no-unused-prop-types */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; @@ -21,7 +20,8 @@ import { undoable } from '../../../util/UndoManager'; import { IconButton, Size } from 'browndash-components'; export enum SchemaFieldType { - Header, Cell + Header, + Cell, } export interface SchemaColumnHeaderProps { @@ -49,7 +49,6 @@ export interface SchemaColumnHeaderProps { @observer export class SchemaColumnHeader extends ObservableReactComponent { - private _inputRef: EditableView | null = null; @observable _altTitle: string | undefined = undefined; @observable _showMenuIcon: boolean = false; @@ -58,18 +57,26 @@ export class SchemaColumnHeader extends ObservableReactComponent this._props.schemaView?.fieldInfos.get(fieldKey)); - setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);} - @action updateAlt = (newAlt: string) => {this._altTitle = newAlt}; - updateKeyDropdown = (value: string) => {this._props.schemaView.updateKeySearch(value)}; - openKeyDropdown = () => {!this._props.schemaView._colBeingDragged && this._props.schemaView.openNewColumnMenu(this._props.columnIndex, false)}; + setColumnValues = (field: string, defaultValue: string) => { + this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex); + }; + @action updateAlt = (newAlt: string) => { + this._altTitle = newAlt; + }; + updateKeyDropdown = (value: string) => { + this._props.schemaView.updateKeySearch(value); + }; + openKeyDropdown = () => { + !this._props.schemaView._colBeingDragged && this._props.schemaView.openNewColumnMenu(this._props.columnIndex, false); + }; toggleEditing = (editing: boolean) => { - this._inputRef?.setIsEditing(editing); + this._inputRef?.setIsEditing(editing); this._inputRef?.setIsFocused(editing); }; @@ -110,139 +117,156 @@ export class SchemaColumnHeader extends ObservableReactComponent { - SchemaColumnHeader.isDefaultField(this.fieldKey) && this.openKeyDropdown(); - this._props.schemaView.deselectAllCells(); - }} - style={{ - color, - width: '100%', - pointerEvents, - }}> - {this._inputRef = r; this._props.autoFocus && r?.setIsFocused(true)}} - oneLine={true} - allowCRs={false} - contents={''} - onClick={this.openKeyDropdown} - fieldContents={fieldProps} - editing={undefined} - placeholder={'Add key'} - updateAlt={this.updateAlt} // alternate title to display - updateSearch={this.updateKeyDropdown} - schemaFieldType={SchemaFieldType.Header} - GetValue={() => { - if (SchemaColumnHeader.isDefaultField(this.fieldKey)) return ''; - else if (this._altTitle) return this._altTitle; - else return this.fieldKey; + const { color, fieldProps, pointerEvents } = this.renderProps(this._props); + + return ( +
{ + SchemaColumnHeader.isDefaultField(this.fieldKey) && this.openKeyDropdown(); + this._props.schemaView.deselectAllCells(); }} - SetValue={undoable((value: string, shiftKey?: boolean, enterKey?: boolean) => { - if (enterKey) { // if shift & enter, set value of each cell in column - this.setColumnValues(value, ''); - this._altTitle = undefined; + style={{ + color, + width: '100%', + pointerEvents, + }}> + { + this._inputRef = r; + this._props.autoFocus && r?.setIsFocused(true); + }} + oneLine={true} + allowCRs={false} + contents={''} + onClick={this.openKeyDropdown} + fieldContents={fieldProps} + editing={undefined} + placeholder={'Add key'} + updateAlt={this.updateAlt} // alternate title to display + updateSearch={this.updateKeyDropdown} + schemaFieldType={SchemaFieldType.Header} + GetValue={() => { + if (SchemaColumnHeader.isDefaultField(this.fieldKey)) return ''; + else if (this._altTitle) return this._altTitle; + else return this.fieldKey; + }} + SetValue={undoable((value: string, shiftKey?: boolean, enterKey?: boolean) => { + if (enterKey) { + // if shift & enter, set value of each cell in column + this.setColumnValues(value, ''); + this._altTitle = undefined; + this._props.finishEdit?.(); + return true; + } this._props.finishEdit?.(); return true; - } - this._props.finishEdit?.(); - return true; - }, 'edit column header')} - /> + }, 'edit column header')} + />
+ ); } public static isDefaultField = (key: string) => { const defaultPattern = /EmptyColumnKey/; - const isDefault: boolean = (defaultPattern.exec(key) != null); + const isDefault: boolean = defaultPattern.exec(key) != null; return isDefault; - } + }; - get headerButton(){ - const toRender = SchemaColumnHeader.isDefaultField(this.fieldKey) ? - (} - size={Size.XSMALL} - color={'black'} - onPointerDown={e => - setupMoveUpEvents( - this, - e, - returnFalse, - emptyFunction, - undoable(clickEv => { - clickEv.stopPropagation(); - this._props.schemaView.removeColumn(this._props.columnIndex); - }, 'open column menu') - ) - } - />) - : (} - size={Size.XSMALL} - color={'black'} - onPointerDown={e => - setupMoveUpEvents( - this, - e, - returnFalse, - emptyFunction, - undoable(clickEv => { - clickEv.stopPropagation(); - this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex) - }, 'open column menu') - ) - } - />) + get headerButton() { + const toRender = SchemaColumnHeader.isDefaultField(this.fieldKey) ? ( + } + size={Size.XSMALL} + color={'black'} + onPointerDown={e => + setupMoveUpEvents( + this, + e, + returnFalse, + emptyFunction, + undoable(clickEv => { + clickEv.stopPropagation(); + this._props.schemaView.removeColumn(this._props.columnIndex); + }, 'open column menu') + ) + } + /> + ) : ( + } + size={Size.XSMALL} + color={'black'} + onPointerDown={e => + setupMoveUpEvents( + this, + e, + returnFalse, + emptyFunction, + undoable(clickEv => { + clickEv.stopPropagation(); + this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex); + }, 'open column menu') + ) + } + /> + ); return toRender; } - @action handlePointerEnter = () => this._showMenuIcon = true; - @action handlePointerLeave = () => this._showMenuIcon = false; + @action handlePointerEnter = () => { this._showMenuIcon = true; } // prettier-ignore + @action handlePointerLeave = () => { this._showMenuIcon = false; } // prettier-ignore - @computed get displayButton() {return this._showMenuIcon;} + @computed get displayButton() { + return this._showMenuIcon; + } render() { return ( -
{this.handlePointerEnter()}} - onPointerLeave={() => {this.handlePointerLeave()}} - onPointerDown={e => { - this.setupDrag(e); - setupMoveUpEvents( - this, - e, - () => {return this._inputRef?.setIsEditing(false) ?? false}, - emptyFunction, - emptyFunction, - ); - } +
{ + this.handlePointerEnter(); + }} + onPointerLeave={() => { + this.handlePointerLeave(); + }} + onPointerDown={e => { + this.setupDrag(e); + setupMoveUpEvents( + this, + e, + () => { + return this._inputRef?.setIsEditing(false) ?? false; + }, + emptyFunction, + emptyFunction + ); + }} + ref={col => { + if (col) { + this._props.setColRef(this._props.columnIndex, col); } - ref={col => { - if (col) { - this._props.setColRef(this._props.columnIndex, col); - } - }}> -
this._props.resizeColumn(e, this._props.columnIndex, false)} /> + }}> +
this._props.resizeColumn(e, this._props.columnIndex, false)} /> -
{this.editableView}
+
{this.editableView}
-
-
- {this.headerButton} -
-
- -
this._props.resizeColumn(e, this._props.columnIndex, true)} /> +
+
+ {this.headerButton} +
+ +
this._props.resizeColumn(e, this._props.columnIndex, true)} /> +
); } -} \ No newline at end of file +} diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index a8a4ef2c2..6ffb0865a 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -21,7 +21,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; /** * The SchemaRowBox renders a doc as a row of cells, with each cell representing - * one field value of the doc. It mostly handles communication from the SchemaView + * one field value of the doc. It mostly handles communication from the SchemaView * to each SchemaCell, passing down necessary functions are props. */ @@ -59,7 +59,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { ContextMenu.Instance.clearItems(); ContextMenu.Instance.addItem({ description: this.Document._lockedSchemaEditing ? 'Unlock field editing' : 'Lock field editing', - event: () => this.Document._lockedSchemaEditing = !this.Document._lockedSchemaEditing, + event: () => (this.Document._lockedSchemaEditing = !this.Document._lockedSchemaEditing), icon: this.Document._lockedSchemaEditing ? 'lock-open' : 'lock', }); ContextMenu.Instance.addItem({ @@ -78,17 +78,19 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { // ContextMenu.Instance.addItem({ // description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema', // event: () => { - // this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; + // this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; // }, // icon: this.Document._childrenSharedWithSchema ? 'minus' : 'plus', // }); // } ContextMenu.Instance.displayMenu(x, y, undefined, false); - } + }; - @computed get menuBackgroundColor(){ - if (this.Document._lockedSchemaEditing) {return '#F5F5F5'} - return '' + @computed get menuBackgroundColor() { + if (this.Document._lockedSchemaEditing) { + return '#F5F5F5'; + } + return ''; } @computed get menuInfos() { @@ -98,22 +100,28 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { return infos; } - isolatedSelection = (doc: Doc) => {return this.schemaView?.selectionOverlap(doc)}; + isolatedSelection = (doc: Doc) => { + return this.schemaView?.selectionOverlap(doc); + }; setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY); selectedCol = () => this.schemaView._selectedCol; getFinfo = computedFn((fieldKey: string) => this.schemaView?.fieldInfos.get(fieldKey)); selectCell = (doc: Doc, col: number, shift: boolean, ctrl: boolean) => this.schemaView?.selectCell(doc, col, shift, ctrl); deselectCell = () => this.schemaView?.deselectAllCells(); selectedCells = () => this.schemaView?._selectedDocs; - setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false; + setColumnValues = (field: string, value: string) => this.schemaView?.setCellValues(field, value) ?? false; columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth); computeRowIndex = () => this.schemaView?.rowIndex(this.Document); highlightCells = (text: string) => this.schemaView?.highlightCells(text); - selectReference = (doc: Doc, col: number) => {this.schemaView.selectReference(doc, col)} + selectReference = (doc: Doc, col: number) => { + this.schemaView.selectReference(doc, col); + }; eqHighlightFunc = (text: string) => { const info = this.schemaView.findCellRefs(text); const cells: HTMLDivElement[] = []; - info.forEach(info => {cells.push(this.schemaView.getCellElement(info[0], info[1]))}) + info.forEach(inf => { + cells.push(this.schemaView.getCellElement(inf[0], inf[1])); + }); return cells; }; render() { @@ -121,7 +129,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() {
this.setCursorIndex(e.clientY)} - style={{ height: this._props.PanelHeight()}} + style={{ height: this._props.PanelHeight() }} ref={(row: HTMLDivElement | null) => { row && this.schemaView?.addRowRef?.(this.Document, row); this._ref = row; @@ -131,11 +139,11 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { style={{ width: CollectionSchemaView._rowMenuWidth, pointerEvents: !this._props.isContentActive() ? 'none' : undefined, - backgroundColor: this.menuBackgroundColor + backgroundColor: this.menuBackgroundColor, }}> } + icon={} size={Size.XSMALL} color={'black'} onPointerDown={e => @@ -146,14 +154,16 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { emptyFunction, undoable(clickEv => { clickEv.stopPropagation(); - this.openContextMenu(e.clientX, e.clientY) + this.openContextMenu(e.clientX, e.clientY); }, 'open actions menu') ) } /> -
- {this.menuInfos.map(icn => )} -
+
+ {this.menuInfos.map(icn => ( + + ))} +
{this.schemaView?.columnKeys?.map((key, index) => ( @@ -192,4 +202,4 @@ export class SchemaRowBox extends ViewBoxBaseComponent() {
); } -} \ No newline at end of file +} diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index c05382ce0..f036ff843 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/jsx-props-no-spreading */ /* eslint-disable no-use-before-define */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Popup, Size, Type } from 'browndash-components'; @@ -37,7 +36,7 @@ import { SchemaCellField } from './SchemaCellField'; /** * SchemaTableCells make up the majority of the visual representation of the SchemaView. * They are rendered for each cell in the SchemaView, and each represents one field value - * of a doc. Editing the content of the cell changes the corresponding doc's field value. + * of a doc. Editing the content of the cell changes the corresponding doc's field value. */ export interface SchemaTableCellProps { @@ -67,21 +66,16 @@ export interface SchemaTableCellProps { isolatedSelection: (doc: Doc) => [boolean, boolean]; highlightCells: (text: string) => void; eqHighlightFunc: (text: string) => HTMLDivElement[] | []; - refSelectModeInfo: {enabled: boolean, currEditing: SchemaCellField | undefined}; + refSelectModeInfo: { enabled: boolean; currEditing: SchemaCellField | undefined }; selectReference: (doc: Doc, col: number) => void; } function selectedCell(props: SchemaTableCellProps) { - return ( - props.isRowActive() && - props.selectedCol() === props.col && - props.selectedCells()?.filter(d => d === props.Document)?.length - ); + return props.isRowActive() && props.selectedCol() === props.col && props.selectedCells()?.filter(d => d === props.Document)?.length; } @observer export class SchemaTableCell extends ObservableReactComponent { - // private _fieldRef: SchemaCellField | null = null; private _submittedValue: string = ''; @@ -96,9 +90,11 @@ export class SchemaTableCell extends ObservableReactComponent { @@ -110,7 +106,7 @@ export class SchemaTableCell extends ObservableReactComponent { const modField = field.replace(/\bthis.\b/g, `d${this.docIndex}.`); return modField; - } + }; // parses a field from the "idToDoc(####)" format to DocumentId (d#) format for readability cleanupField = (field: string) => { let modField = field.slice(); let eqSymbol: string = ''; - if (modField.startsWith('=')) {modField = modField.substring(1); eqSymbol += '=';} - if (modField.startsWith(':=')) {modField = modField.substring(2); eqSymbol += ':=';} + if (modField.startsWith('=')) { + modField = modField.substring(1); + eqSymbol += '='; + } + if (modField.startsWith(':=')) { + modField = modField.substring(2); + eqSymbol += ':='; + } const idPattern = /idToDoc\((.*?)\)/g; let matches; const results = new Array<[id: string, func: string]>(); - while ((matches = idPattern.exec(field)) !== null) {results.push([matches[0], matches[1].replace(/"/g, '')]); } - results.forEach((idFuncPair) => {modField = modField.replace(idFuncPair[0], 'd' + (DocumentView.getDocViewIndex(IdToDoc(idFuncPair[1]))).toString());}) + while ((matches = idPattern.exec(field)) !== null) { + results.push([matches[0], matches[1].replace(/"/g, '')]); + } + results.forEach(idFuncPair => { + modField = modField.replace(idFuncPair[0], 'd' + DocumentView.getDocViewIndex(IdToDoc(idFuncPair[1])).toString()); + }); if (modField.endsWith(';')) modField = modField.substring(0, modField.length - 1); - const inQuotes = (field: string) => {return ((field.startsWith('`') && field.endsWith('`')) || (field.startsWith("'") && field.endsWith("'")) || (field.startsWith('"') && field.endsWith('"')))} + const inQuotes = (strField: string) => { + return (strField.startsWith('`') && strField.endsWith('`')) || (strField.startsWith("'") && strField.endsWith("'")) || (strField.startsWith('"') && strField.endsWith('"')); + }; if (!inQuotes(this._submittedValue) && inQuotes(modField)) modField = modField.substring(1, modField.length - 1); return eqSymbol + modField; - } + }; @computed get defaultCellContent() { const { color, textDecoration, fieldProps, pointerEvents } = SchemaTableCell.renderProps(this._props); @@ -203,7 +211,7 @@ export class SchemaTableCell extends ObservableReactComponent = []; sides[0] = selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // left sides[1] = selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // right - sides[2] = (!this._props.isolatedSelection(this._props.Document)[0] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // top - sides[3] = (!this._props.isolatedSelection(this._props.Document)[1] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // bottom + sides[2] = !this._props.isolatedSelection(this._props.Document)[0] && selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // top + sides[3] = !this._props.isolatedSelection(this._props.Document)[1] && selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // bottom return sides; } @@ -256,9 +264,13 @@ export class SchemaTableCell extends ObservableReactComponent StopEvent(e)} onPointerDown={action(e => { - if (this.lockedInteraction) { e.stopPropagation(); e.preventDefault(); return; } + if (this.lockedInteraction) { + e.stopPropagation(); + e.preventDefault(); + return; + } - if (this._props.refSelectModeInfo.enabled && !selectedCell(this._props)){ + if (this._props.refSelectModeInfo.enabled && !selectedCell(this._props)) { e.stopPropagation(); e.preventDefault(); this._props.selectReference(this._props.Document, this._props.col); @@ -274,14 +286,16 @@ export class SchemaTableCell extends ObservableReactComponent + style={{ + padding: this._props.padding, + maxWidth: this._props.maxWidth?.(), + width: this._props.columnWidth() || undefined, + borderLeft: this.borderColor[0], + borderRight: this.borderColor[1], + borderTop: this.borderColor[2], + borderBottom: this.borderColor[3], + backgroundColor: this.backgroundColor, + }}> {this.isDefault ? '' : this.content}
); @@ -524,4 +538,4 @@ export class SchemaEnumerationCell extends ObservableReactComponent ); } -} \ No newline at end of file +} diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 962a21dbb..6c3f4eaff 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -84,7 +84,6 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b } else { const dataKey = Doc.LayoutFieldKey(dv.Document); const alternate = (dv.layoutDoc[dataKey + '_usePath'] ? '_' + dv.layoutDoc[dataKey + '_usePath'] : '').replace(':hover', ''); - console.log('color: ' + dv.dataDoc[fieldKey + alternate] + ' to set to: ' + color) dv.layoutDoc[fieldKey + alternate] = undefined; dv.dataDoc[fieldKey + alternate] = color; } diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 12196f290..a44014444 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/jsx-props-no-spreading */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Checkbox } from '@mui/material'; import { Colors, Toggle, ToggleType, Type } from 'browndash-components'; @@ -8,42 +7,36 @@ import * as React from 'react'; import { ClientUtils, returnEmptyString, returnFalse, returnOne, setupMoveUpEvents } from '../../../../ClientUtils'; import { emptyFunction } from '../../../../Utils'; import { Doc, DocListCast, Field, FieldType, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; +import { AclAdmin, AclAugment, AclEdit } from '../../../../fields/DocSymbols'; import { InkTool } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; +import { PrefetchProxy } from '../../../../fields/Proxy'; import { Cast, CsvCast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; import { CsvField } from '../../../../fields/URLField'; -import { GetEffectiveAcl, TraceMobx, inheritParentAcls } from '../../../../fields/util'; +import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util'; +import { GPTCallType, gptAPICall } from '../../../apis/gpt/GPT'; import { DocUtils } from '../../../documents/DocUtils'; import { DocumentType } from '../../../documents/DocumentTypes'; import { Docs } from '../../../documents/Documents'; +import { LinkManager } from '../../../util/LinkManager'; import { UndoManager, undoable } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; import { ViewBoxAnnotatableComponent } from '../../DocComponent'; import { MarqueeAnnotator } from '../../MarqueeAnnotator'; import { PinProps } from '../../PinFuncs'; import { SidebarAnnos } from '../../SidebarAnnos'; +import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; import { AnchorMenu } from '../../pdf/AnchorMenu'; import { GPTPopup, GPTPopupMode } from '../../pdf/GPTPopup/GPTPopup'; import { DocumentView } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; import { FocusViewOptions } from '../FocusViewOptions'; import './DataVizBox.scss'; +import { Col, DataVizTemplateInfo, DocCreatorMenu, LayoutType, TemplateFieldSize, TemplateFieldType } from './DocCreatorMenu'; import { Histogram } from './components/Histogram'; import { LineChart } from './components/LineChart'; import { PieChart } from './components/PieChart'; import { TableBox } from './components/TableBox'; -import { LinkManager } from '../../../util/LinkManager'; -import { Col, DataVizTemplateInfo, DataVizTemplateLayout, DocCreatorMenu, TemplateFieldSize, LayoutType, TemplateFieldType } from './DocCreatorMenu'; -import { CollectionFreeFormView, MarqueeView } from '../../collections/collectionFreeForm'; -import { PrefetchProxy } from '../../../../fields/Proxy'; -import { AclAdmin, AclAugment, AclEdit } from '../../../../fields/DocSymbols'; -import { template } from 'lodash'; -import { data } from 'jquery'; -import { listSpec } from '../../../../fields/Schema'; -import { ObjectField } from '../../../../fields/ObjectField'; -import { Id } from '../../../../fields/FieldSymbols'; -import { GPTCallType, gptAPICall } from '../../../apis/gpt/GPT'; -import { TbSortDescendingShapes } from 'react-icons/tb'; export enum DataVizView { TABLE = 'table', @@ -65,7 +58,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { @observable _marqueeing: number[] | undefined = undefined; @observable _savedAnnotations = new ObservableMap(); @observable _specialHighlightedRow: number | undefined = undefined; - @observable GPTSummary: ObservableMap | undefined = undefined; + @observable GPTSummary: ObservableMap | undefined = undefined; @observable colsInfo: ObservableMap = new ObservableMap(); @observable _GPTLoading: boolean = false; @@ -121,12 +114,9 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { const records = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey]).url.href); this._urlError = false; return records?.filter(record => Object.keys(record).some(key => record[key])) ?? []; - } catch (e){ + } catch { this._urlError = true; - const data: { [key: string]: string; }[] = [ - { error: "Data not found"}, - ]; - return data; + return [{ error: 'Data not found' }] as { [key: string]: string }[]; } } @@ -153,70 +143,73 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { @action setSpecialHighlightedRow = (row: number | undefined) => { this._specialHighlightedRow = row; - } + }; @action setColumnType = (colTitle: string, type: TemplateFieldType) => { const colInfo = this.colsInfo.get(colTitle); - if (colInfo) { + if (colInfo) { colInfo.type = type; } else { - this.colsInfo.set(colTitle, {title: colTitle, desc: '', type: type, sizes: [TemplateFieldSize.MEDIUM]}) + this.colsInfo.set(colTitle, { title: colTitle, desc: '', type: type, sizes: [TemplateFieldSize.MEDIUM] }); } - } + }; @action modifyColumnSizes = (colTitle: string, size: TemplateFieldSize, valid: boolean) => { const column = this.colsInfo.get(colTitle); - if (column) { + if (column) { if (!valid && column.sizes.includes(size)) { column.sizes.splice(column.sizes.indexOf(size), 1); } else if (valid && !column.sizes.includes(size)) { column.sizes.push(size); } } else { - this.colsInfo.set(colTitle, {title: colTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [size]}) + this.colsInfo.set(colTitle, { title: colTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [size] }); } - } + }; @action setColumnTitle = (colTitle: string, newTitle: string) => { const colInfo = this.colsInfo.get(colTitle); - if (colInfo) { + if (colInfo) { colInfo.title = newTitle; - console.log(colInfo.title) + console.log(colInfo.title); } else { - this.colsInfo.set(colTitle, {title: newTitle, desc: '', type: TemplateFieldType.UNSET, sizes: []}) + this.colsInfo.set(colTitle, { title: newTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [] }); } - } + }; @action setColumnDesc = (colTitle: string, desc: string) => { const colInfo = this.colsInfo.get(colTitle); if (colInfo) { - if (!desc) { colInfo.desc = this.GPTSummary?.get(colTitle)?.desc ?? ''; } - else { colInfo.desc = desc; } + if (!desc) { + colInfo.desc = this.GPTSummary?.get(colTitle)?.desc ?? ''; + } else { + colInfo.desc = desc; + } } else { - this.colsInfo.set(colTitle, {title: colTitle, desc: desc, type: TemplateFieldType.UNSET, sizes: []}) + this.colsInfo.set(colTitle, { title: colTitle, desc: desc, type: TemplateFieldType.UNSET, sizes: [] }); } - } + }; @action setColumnDefault = (colTitle: string, cont: string) => { const colInfo = this.colsInfo.get(colTitle); if (colInfo) { colInfo.defaultContent = cont; } else { - this.colsInfo.set(colTitle, {title: colTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [], defaultContent: cont}) + this.colsInfo.set(colTitle, { title: colTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [], defaultContent: cont }); } - } + }; @action // pinned / linked anchor doc includes selected rows, graph titles, and graph colors - restoreView = (data: Doc) => { + restoreView = (viewData: Doc) => { // const changedView = data.config_dataViz && this.dataVizView !== data.config_dataViz && (this.layoutDoc._dataViz = data.config_dataViz); // const changedAxes = data.config_dataVizAxes && this.axes.join('') !== StrListCast(data.config_dataVizAxes).join('') && (this.layoutDoc._dataViz_axes = new List(StrListCast(data.config_dataVizAxes))); - this.layoutDoc.dataViz_selectedRows = Field.Copy(data.dataViz_selectedRows); - this.layoutDoc.dataViz_histogram_barColors = Field.Copy(data.dataViz_histogram_barColors); - this.layoutDoc.dataViz_histogram_defaultColor = data.dataViz_histogram_defaultColor; - this.layoutDoc.dataViz_pie_sliceColors = Field.Copy(data.dataViz_pie_sliceColors); + this.layoutDoc.dataViz_selectedRows = Field.Copy(viewData.dataViz_selectedRows); + this.layoutDoc.dataViz_histogram_barColors = Field.Copy(viewData.dataViz_histogram_barColors); + this.layoutDoc.dataViz_histogram_defaultColor = viewData.dataViz_histogram_defaultColor; + this.layoutDoc.dataViz_pie_sliceColors = Field.Copy(viewData.dataViz_pie_sliceColors); Object.keys(this.layoutDoc).forEach(key => { if (key.startsWith('dataViz_histogram_title') || key.startsWith('dataViz_lineChart_title') || key.startsWith('dataViz_pieChart_title')) { - this.layoutDoc['_' + key] = data[key]; + this.layoutDoc['_' + key] = viewData[key]; } }); return true; @@ -354,7 +347,9 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { componentDidMount() { this._props.setContentViewBox?.(this); - if (!this._urlError) { if (!DataVizBox.dataset.has(CsvCast(this.dataDoc[this.fieldKey]).url.href)) this.fetchData() }; + if (!this._urlError) { + if (!DataVizBox.dataset.has(CsvCast(this.dataDoc[this.fieldKey]).url.href)) this.fetchData(); + } this._disposers.datavis = reaction( () => { if (this.layoutDoc.dataViz_schemaLive === undefined) this.layoutDoc.dataViz_schemaLive = true; @@ -516,14 +511,14 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { DocCreatorMenu.Instance.toggleDisplay(x, y); DocCreatorMenu.Instance.setDataViz(this); DocCreatorMenu.Instance.setTemplateDocs(this.getPossibleTemplates()); - } + }; - specificContextMenu = (x: number, y: number): void => { + specificContextMenu = (e: MouseEventHandler) => { const cm = ContextMenu.Instance; const options = cm.findByDescription('Options...'); const optionItems = options?.subitems ?? []; optionItems.push({ description: `Analyze with AI`, event: () => this.askGPT(), icon: 'lightbulb' }); - optionItems.push({ description: `Create documents`, event: () => this.openDocCreatorMenu(x, y), icon: 'table-cells' }); + optionItems.push({ description: `Create documents`, event: () => this.openDocCreatorMenu(e.pageX, e.pageY), icon: 'table-cells' }); !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' }); }; @@ -533,19 +528,19 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { GPTPopup.Instance.createFilteredDoc = this.createFilteredDoc; GPTPopup.Instance.setDataJson(''); GPTPopup.Instance.setMode(GPTPopupMode.DATA); - const data = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey]).url.href); - GPTPopup.Instance.setDataJson(JSON.stringify(data)); + const csvdata = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey]).url.href); + GPTPopup.Instance.setDataJson(JSON.stringify(csvdata)); GPTPopup.Instance.generateDataAnalysis(); }); getColSummary = (): string => { - let possibleIds: number[] = this.records.map((_, index) => index); + const possibleIds: number[] = this.records.map((_, index) => index); for (let i = possibleIds.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [possibleIds[i], possibleIds[j]] = [possibleIds[j], possibleIds[i]]; } - + const rowsToCheck = possibleIds.slice(0, Math.min(10, this.records.length)); let prompt: string = 'Col titles: '; @@ -553,37 +548,37 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { const cols = Array.from(Object.keys(this.records[0])).filter(header => header !== '' && header !== undefined); cols.forEach((col, i) => { - prompt += `Col #${i}: ${col} ------` - }) + prompt += `Col #${i}: ${col} ------`; + }); - prompt += '----------- Rows: ' + prompt += '----------- Rows: '; - rowsToCheck.forEach((row, i) => { - prompt += `Row #${row}: ` + rowsToCheck.forEach(row => { + prompt += `Row #${row}: `; cols.forEach(col => { - prompt += `${col}: ${this.records[row][col]} -----` - }) - }) + prompt += `${col}: ${this.records[row][col]} -----`; + }); + }); return prompt; - } + }; updateColDefaults = () => { - let possibleIds: number[] = this.records.map((_, index) => index); + const possibleIds: number[] = this.records.map((_, index) => index); for (let i = possibleIds.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [possibleIds[i], possibleIds[j]] = [possibleIds[j], possibleIds[i]]; } - + const rowToCheck = possibleIds[0]; const cols = Array.from(Object.keys(this.records[0])).filter(header => header !== '' && header !== undefined); - cols.forEach(col => { - this.setColumnDefault(col, `${this.records[rowToCheck][col]}`) + cols.forEach(col => { + this.setColumnDefault(col, `${this.records[rowToCheck][col]}`); }); - } + }; updateGPTSummary = async () => { this._GPTLoading = true; @@ -594,15 +589,12 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { const cols = Array.from(Object.keys(this.records[0])).filter(header => header !== '' && header !== undefined); cols.forEach(col => { - if (!this.colsInfo.get(col)) this.colsInfo.set(col, {title: col, desc: '', sizes: [], type: TemplateFieldType.UNSET}); + if (!this.colsInfo.get(col)) this.colsInfo.set(col, { title: col, desc: '', sizes: [], type: TemplateFieldType.UNSET }); }); try { - const [res1, res2] = await Promise.all([ - gptAPICall(prompt, GPTCallType.VIZSUM), - gptAPICall('Info:' + prompt, GPTCallType.VIZSUM2) - ]); - + const [res1, res2] = await Promise.all([gptAPICall(prompt, GPTCallType.VIZSUM), gptAPICall('Info:' + prompt, GPTCallType.VIZSUM2)]); + if (res1) { this.GPTSummary = new ObservableMap(); const descs: { [col: string]: string } = JSON.parse(res1); @@ -611,10 +603,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { if (!this.colsInfo.get(key)?.desc) this.setColumnDesc(key, val); } } - + if (res2) { !this.GPTSummary && (this.GPTSummary = new ObservableMap()); - const info: { [col: string]: { type: TemplateFieldType, size: TemplateFieldSize } } = JSON.parse(res2); + const info: { [col: string]: { type: TemplateFieldType; size: TemplateFieldSize } } = JSON.parse(res2); for (const [key, val] of Object.entries(info)) { const colSummary = this.GPTSummary.get(key); if (colSummary) { @@ -628,30 +620,29 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { } catch (err) { console.error(err); } - - } + }; getPossibleTemplates = (): Doc[] => { const linkedDocs: Doc[] = LinkManager.Instance.getAllRelatedLinks(this.Document).map(d => DocCast(LinkManager.getOppositeAnchor(d, this.Document))); const linkedCollections: Doc[] = linkedDocs.filter(doc => doc.type === 'config').map(doc => DocCast(doc.annotationOn)); const isColumnTitle = (title: string): boolean => { const colTitles: string[] = Object.keys(this.records[0]); - for (let i = 0; i < colTitles.length; ++i){ + for (let i = 0; i < colTitles.length; ++i) { if (colTitles[i] === title) { return true; } } return false; - } + }; const isValidTemplate = (collection: Doc) => { const childDocs = DocListCast(collection[Doc.LayoutFieldKey(collection)]); - for (let i = 0; i < childDocs.length; ++i){ + for (let i = 0; i < childDocs.length; ++i) { if (isColumnTitle(String(childDocs[i].title))) return true; } return false; - } + }; return linkedCollections.filter(col => isValidTemplate(col)); - } + }; ApplyTemplateTo = (templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined) => { if (!Doc.AreProtosEqual(target[targetKey] as Doc, templateDoc)) { @@ -664,14 +655,14 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { } } return target; - } + }; applyLayout = (templateInfo: DataVizTemplateInfo, docs: Doc[]) => { if (templateInfo.layout.type === LayoutType.Stacked) return; const columns: number = templateInfo.columns; const xGap: number = templateInfo.layout.xMargin; const yGap: number = templateInfo.layout.yMargin; - const repeat: number = templateInfo.layout.repeat; + // const repeat: number = templateInfo.layout.repeat; const startX: number = templateInfo.referencePos.x; const startY: number = templateInfo.referencePos.y; const templWidth = Number(templateInfo.doc._width); @@ -682,8 +673,8 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { let curX: number = startX; let curY: number = startY; - while (docsChanged < docs.length){ - while (i < columns && docsChanged < docs.length){ + while (docsChanged < docs.length) { + while (i < columns && docsChanged < docs.length) { docs[docsChanged].x = curX; docs[docsChanged].y = curY; curX += templWidth + xGap; @@ -695,27 +686,29 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { curX = startX; curY += templHeight + yGap; } - } + }; // @action addSavedLayout = (layout: DataVizTemplateLayout) => { // const saved = Cast(this.layoutDoc.dataViz_savedTemplates, listSpec('RefField')); - + // } @action createDocsFromTemplate = (templateInfo: DataVizTemplateInfo) => { if (!templateInfo.doc) return; const mainCollection = this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; - const fields: string[] = Array.from(Object.keys(this.records[0])); + const fields: string[] = Array.from(Object.keys(this.records[0])); const selectedRows = NumListCast(this.layoutDoc.dataViz_selectedRows); const docs: Doc[] = selectedRows.map(row => { - const values: String[] = []; + const values: string[] = []; fields.forEach(col => values.push(this.records[row][col])); const proto = new Doc(); proto.author = ClientUtils.CurrentUserEmail(); - values.forEach((val, i) => {proto[fields[i]] = val as FieldType}); - + values.forEach((val, i) => { + proto[fields[i]] = val as FieldType; + }); + const target = Doc.MakeDelegate(proto); const targetKey = StrCast(templateInfo.doc!.layout_fieldKey, 'layout'); const applied = this.ApplyTemplateTo(templateInfo.doc!, target, targetKey, templateInfo.doc!.title + `${row}`); @@ -728,7 +721,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { docs.forEach(doc => mainCollection.addDocument(doc)); this.applyLayout(templateInfo, docs); - } + }; /** * creates a new dataviz document filter from this one @@ -783,7 +776,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { transform: `scale(${scale})`, position: 'absolute', }} - onContextMenu={(e) => this.specificContextMenu(e.pageX, e.pageY)} + onContextMenu={this.specificContextMenu} onWheel={e => e.stopPropagation()} ref={this._mainCont}>
diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx index 0b94ae4f7..9769ecb3d 100644 --- a/src/client/views/nodes/DocumentIcon.tsx +++ b/src/client/views/nodes/DocumentIcon.tsx @@ -1,5 +1,5 @@ import { Tooltip } from '@mui/material'; -import { action, makeObservable, observable } from 'mobx'; +import { makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { factory } from 'typescript'; @@ -18,14 +18,14 @@ interface DocumentIconProps { @observer export class DocumentIcon extends ObservableReactComponent { @observable _hovered = false; - constructor(props: any) { + constructor(props: DocumentIconProps) { super(props); makeObservable(this); } render() { const { view } = this._props; - const { left, top, right, bottom } = view.getBounds || { left: 0, top: 0, right: 0, bottom: 0 }; + const { left, top, bottom } = view.getBounds || { left: 0, top: 0, right: 0, bottom: 0 }; return (
{ pointerEvents: 'all', position: 'absolute', background: SnappingManager.userBackgroundColor, - transform: `translate(${left}px, ${bottom - (bottom - top)/2}px)`, //**!** + transform: `translate(${left}px, ${bottom - (bottom - top) / 2}px)`, //**!** }}> {StrCast(this._props.view.Document?.title)}
}>

d{this._props.index}

@@ -44,7 +44,7 @@ export class DocumentIcon extends ObservableReactComponent { } } -@observer +@observer export class DocumentIconContainer extends React.Component { public static getTransformer(): Transformer { const usedDocuments = new Set(); diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index ba85bfb68..741d63909 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -138,7 +138,7 @@ export class FieldView extends React.Component { const field = this.fieldval; // prettier-ignore if (field instanceof Doc) return

{field.title?.toString()}

; - if (field === undefined) return

{''}

; + if (field === undefined) return

; if (field instanceof DateField) return

{field.date.toLocaleString()}

; if (field instanceof List) return
{field.map(f => Field.toString(f)).join(', ')}
; if (field instanceof WebField) return

{Field.toString(field.url.href)}

; diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index cfcf76b12..8974cccaf 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -2,7 +2,7 @@ import { Property } from 'csstype'; import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -//import * as textfit from 'textfit'; +import * as textfit from 'textfit'; import { Field, FieldType } from '../../../fields/Doc'; import { BoolCast, NumCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; @@ -96,7 +96,7 @@ export class LabelBox extends ViewBoxBaseComponent() { this._timeout = setTimeout(() => this.fitTextToBox(r)); return textfitParams; } - //textfit(r, textfitParams); + textfit(r, textfitParams); } return textfitParams; }; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index c1367aa0b..0d7914a82 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1498,7 +1498,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent this._editorView!.focus()); // not sure why setTimeout is needed but editing dashFieldView's doesn't work without it. - } // add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet. @@ -2087,7 +2086,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent
); - } } -- cgit v1.2.3-70-g09d2