diff --git a/src/commands/profile/dictionary/dictionary.ts b/src/commands/profile/dictionary/dictionary.ts new file mode 100644 index 0000000..01bd806 --- /dev/null +++ b/src/commands/profile/dictionary/dictionary.ts @@ -0,0 +1,58 @@ +import { Account } from "@tago-io/sdk"; + +import { editAutoDictionaryContent, IDictionaryContent } from "./edit-dictionary-content"; +import { generateDictionaryKey } from "./generate-dictionary-key"; +import { getDashboardDictionary } from "./get-dashboard-dictionary"; +import { getAutoDictionaryID } from "./get-dictionary-id"; +import { getWidgetInfo } from "./get-widget-info"; +import { removeDuplicatesAndEmptyStrings } from "./remove-strings"; + +async function dictionary() { + const accountToken = "YOUR-ACCOUNT-TOKEN"; + const account = new Account({ token: accountToken }); + + const dashboardList = await account.dashboards.list(); + + // const dictionaryContent: IDictionaryContent = {}; + // const dashboardDictionaryContent: IDictionaryContent = {}; + // const widgetDictionaryContent: IDictionaryContent = {}; + + const allDashboardDictionaries: string[] = []; + const allWidgetDictionaries: string[] = []; + const allDictionaryContent: IDictionaryContent = {}; + + for (const dashboard of dashboardList) { + const dashboardInfo = await account.dashboards.info(dashboard.id); + + const { dashboardDictionaries } = await getDashboardDictionary(dashboardInfo, account); + allDashboardDictionaries.push(...dashboardDictionaries); + + if (!dashboardInfo.arrangement) { + console.log(`No arrangement found for dashboard ${dashboard.label}: ID-${dashboard.id}`); + continue; + } + + for (const widget of dashboardInfo.arrangement) { + const widgetInfo = await getWidgetInfo(dashboard.id, widget.widget_id, accountToken); + // console.log(`Widget ${widgetInfo.label} found in dashboard ${dashboard.label}: ID-${dashboard.id}`); + console.dir(widgetInfo, { depth: null }); + + // } + } + + const dictionaries = [...allDashboardDictionaries, ...allWidgetDictionaries]; + const dictSet = removeDuplicatesAndEmptyStrings(dictionaries); + console.dir(dictSet, { depth: null }); + + for (const dict of dictSet) { + const dictKey = generateDictionaryKey(dict); + + allDictionaryContent[dictKey] = dict; + } + + const dictID = await getAutoDictionaryID(account); + await editAutoDictionaryContent(account, dictID, allDictionaryContent); + } +} + +export { dictionary }; diff --git a/src/commands/profile/dictionary/edit-dictionary-content.ts b/src/commands/profile/dictionary/edit-dictionary-content.ts new file mode 100644 index 0000000..bcc12a1 --- /dev/null +++ b/src/commands/profile/dictionary/edit-dictionary-content.ts @@ -0,0 +1,17 @@ +import { Account } from "@tago-io/sdk"; + +interface IDictionaryContent { + [key: string]: string; +} + +async function editAutoDictionaryContent(account: Account, dictionaryID: string, content: IDictionaryContent) { + //get the current values in the dictionary + const dictionaryLanguageInfo = await account.dictionaries.languageInfo(dictionaryID, "en-US"); + + //TODO: Maybe sort the dictionary alphabetically before saving it + + //overwrite the dictionary with the new values in the object + await account.dictionaries.languageEdit(dictionaryID, "en-US", { active: true, dictionary: { ...dictionaryLanguageInfo, ...content } }); +} + +export { editAutoDictionaryContent, IDictionaryContent }; diff --git a/src/commands/profile/dictionary/edit-widget-info.ts b/src/commands/profile/dictionary/edit-widget-info.ts new file mode 100644 index 0000000..01e0d7b --- /dev/null +++ b/src/commands/profile/dictionary/edit-widget-info.ts @@ -0,0 +1,22 @@ +import axios, { AxiosRequestConfig } from "axios"; + +async function editWidgetInfo(accountToken: string, dashboardID: string, widgetID: string, widgetInfo: any) { + const config: AxiosRequestConfig = { + method: "PUT", + url: `https://api.tago.io/dashboard/${dashboardID}/widget/${widgetID}`, + headers: { + "Content-Type": "application/json", + Authorization: accountToken, + }, + data: widgetInfo, + }; + + return axios(config) + .then((r) => r.data.result) + .catch((error) => { + console.error(config); + throw error.response.data; + }); +} + +export { editWidgetInfo }; diff --git a/src/commands/profile/dictionary/generate-dictionary-key.ts b/src/commands/profile/dictionary/generate-dictionary-key.ts new file mode 100644 index 0000000..bd696dc --- /dev/null +++ b/src/commands/profile/dictionary/generate-dictionary-key.ts @@ -0,0 +1,9 @@ +function generateDictionaryKey(string: string): string { + return string + .toUpperCase() + .replaceAll(/[[\]{}().,:;!?#]+/g, " ") + .trim() + .replaceAll(/\s+/g, "_"); +} + +export { generateDictionaryKey }; diff --git a/src/commands/profile/dictionary/get-dashboard-dictionary.ts b/src/commands/profile/dictionary/get-dashboard-dictionary.ts new file mode 100644 index 0000000..c2b24c2 --- /dev/null +++ b/src/commands/profile/dictionary/get-dashboard-dictionary.ts @@ -0,0 +1,69 @@ +import { Account } from "@tago-io/sdk"; +import { DashboardInfo } from "@tago-io/sdk/lib/types"; + +import { generateDictionaryKey } from "./generate-dictionary-key"; +import { isDictionaryString } from "./is-dictionary-string"; + +async function getDashboardDictionary(dashboardInfo: DashboardInfo, account: Account) { + const dashboardDictionaries: string[] = []; + + // Dashboard Name (label) + const dashboardLabel = dashboardInfo.label; + const isDashLabelDictionary = isDictionaryString(dashboardLabel); + if (!isDashLabelDictionary) { + dashboardDictionaries.push(dashboardLabel); + const dictKey = generateDictionaryKey(dashboardLabel); + dashboardInfo.label = `#AUTO.${dictKey}#`; + } + + // Dashboard Tabs Names (value) + const dashboardTabsValues = []; + + for (const tab of dashboardInfo.tabs) { + if (tab.value !== undefined) { + const isDashTabValueDictionary = isDictionaryString(tab.value); + + if (!isDashTabValueDictionary) { + dashboardTabsValues.push(tab?.value); + const dictKey = generateDictionaryKey(tab.value); + tab.value = `#AUTO.${dictKey}#`; + } + } + } + + // Dashboard Blueprint Devices (label and placeholder) + const dashboardBlueprintDevicesLabel = []; + const dashboardBlueprintDevicesPlaceholder = []; + + for (const device of dashboardInfo.blueprint_devices) { + if (device.label !== undefined) { + const isDashBlueprintDeviceLabelDictionary = isDictionaryString(device.label); + + if (!isDashBlueprintDeviceLabelDictionary) { + dashboardBlueprintDevicesLabel.push(device.label); + const dictKey = generateDictionaryKey(device.label); + device.label = `#AUTO.${dictKey}#`; + } + } + + if (device.placeholder !== undefined) { + const isDashBlueprintDevicePlaceholderDictionary = isDictionaryString(device.placeholder); + + if (!isDashBlueprintDevicePlaceholderDictionary) { + dashboardBlueprintDevicesPlaceholder.push(device.placeholder); + const dictKey = generateDictionaryKey(device.placeholder); + device.placeholder = `#AUTO.${dictKey}#`; + } + } + } + + // console.log({ dashboardLabel, dashboardTabsValues, dashboardBlueprintDevicesLabel, dashboardBlueprintDevicesPlaceholder }); + + dashboardDictionaries.push(...dashboardTabsValues, ...dashboardBlueprintDevicesLabel, ...dashboardBlueprintDevicesPlaceholder); + + await account.dashboards.edit(dashboardInfo.id, dashboardInfo); + + return { dashboardDictionaries }; +} + +export { getDashboardDictionary }; diff --git a/src/commands/profile/dictionary/get-dictionary-id.ts b/src/commands/profile/dictionary/get-dictionary-id.ts new file mode 100644 index 0000000..2a3423e --- /dev/null +++ b/src/commands/profile/dictionary/get-dictionary-id.ts @@ -0,0 +1,24 @@ +import { Account } from "@tago-io/sdk"; + +async function getAutoDictionaryID(account: Account) { + const dictionaries = await account.dictionaries.list(); + + // console.log(`Found ${dictionaries.length} dictionaries`); + // console.dir(dictionaries, { depth: null }); + + const isAutoDictionary = dictionaries.some((dictionary) => dictionary.slug === "AUTO"); + let autoDictionaryID = ""; + + if (!isAutoDictionary) { + const { dictionary: dictionaryID } = await account.dictionaries.create({ name: "TagoIO Automatic Dictionary", slug: "AUTO", fallback: "en-US" }); + + autoDictionaryID = dictionaryID; + console.log({ dictionaryID }); + } else { + autoDictionaryID = dictionaries.find((dictionary) => dictionary.slug === "AUTO")?.id as string; + } + + return autoDictionaryID; +} + +export { getAutoDictionaryID }; diff --git a/src/commands/profile/dictionary/get-widget-dictionary.ts b/src/commands/profile/dictionary/get-widget-dictionary.ts new file mode 100644 index 0000000..e0612b5 --- /dev/null +++ b/src/commands/profile/dictionary/get-widget-dictionary.ts @@ -0,0 +1,272 @@ +import { editWidgetInfo } from "./edit-widget-info"; +import { generateDictionaryKey } from "./generate-dictionary-key"; +import { isDictionaryString } from "./is-dictionary-string"; + +async function getWidgetDictionary(accountToken: string, dashboardID: string, widgetID: string, widgetInfo: any) { + const widgetDictionaries: string[] = []; + + const widgetLabel = widgetInfo.label; + const isWidgetLabelDictionary = isDictionaryString(widgetLabel); + if (!isWidgetLabelDictionary) { + const dictKey = generateDictionaryKey(widgetLabel); + widgetDictionaries.push(widgetLabel); + // widgetDictionaryContent[dictKey] = widgetLabel; + widgetInfo.label = `#AUTO.${dictKey}#`; + } + + const widgetHeaderButtonsText = []; + for (const button of widgetInfo.display.header_buttons) { + if (button.text !== undefined) { + const isWidgetButtonDictionary = isDictionaryString(button.text); + + if (!isWidgetButtonDictionary) { + widgetHeaderButtonsText.push(button.text); + const dictKey = generateDictionaryKey(button.text); + button.text = `#AUTO.${dictKey}#`; + } + } + } + + const widgetVariablesTextContent = []; + const widgetVariablesAlias = []; + + if (widgetInfo.display.variables) { + for (const variable of widgetInfo.display.variables) { + if (variable.text_content !== undefined) { + const isWidgetVariableTextContentDictionary = isDictionaryString(variable.text_content); + + if (!isWidgetVariableTextContentDictionary) { + widgetVariablesTextContent.push(variable.text_content); + const dictKey = generateDictionaryKey(variable.text_content); + variable.text_content = `#AUTO.${dictKey}#`; + } + } + + if (variable.alias !== undefined) { + const isWidgetVariableAliasDictionary = isDictionaryString(variable.alias); + + if (!isWidgetVariableAliasDictionary) { + widgetVariablesAlias.push(variable.alias); + const dictKey = generateDictionaryKey(variable.alias); + variable.alias = `#AUTO.${dictKey}#`; + } + } + } + } + + const widgetColumnsAlias = []; + if (widgetInfo.display.columns) { + for (const column of widgetInfo.display.columns) { + if (column.alias !== undefined) { + const isWidgetColumnAliasDictionary = isDictionaryString(column.alias); + + if (!isWidgetColumnAliasDictionary) { + widgetColumnsAlias.push(column.alias); + const dictKey = generateDictionaryKey(column.alias); + column.alias = `#AUTO.${dictKey}#`; + } + } + + if (column.buttons) { + for (const button of column.buttons) { + if (button.confirmation_modal_title !== undefined) { + const isWidgetButtonDictionary = isDictionaryString(button.confirmation_modal_title); + + if (!isWidgetButtonDictionary) { + const dictKey = generateDictionaryKey(button.confirmation_modal_title); + button.confirmation_modal_title = `#AUTO.${dictKey}#`; + } + } + + if (button.confirmation_modal_text !== undefined) { + const isWidgetButtonDictionary = isDictionaryString(button.confirmation_modal_text); + + if (!isWidgetButtonDictionary) { + const dictKey = generateDictionaryKey(button.confirmation_modal_text); + button.confirmation_modal_text = `#AUTO.${dictKey}#`; + } + } + + if (button.confirmation_modal_cancel_text !== undefined) { + const isWidgetButtonDictionary = isDictionaryString(button.confirmation_modal_cancel_text); + + if (!isWidgetButtonDictionary) { + const dictKey = generateDictionaryKey(button.confirmation_modal_cancel_text); + button.confirmation_modal_cancel_text = `#AUTO.${dictKey}#`; + } + } + + if (button.confirmation_modal_confirm_text !== undefined) { + const isWidgetButtonDictionary = isDictionaryString(button.confirmation_modal_confirm_text); + + if (!isWidgetButtonDictionary) { + const dictKey = generateDictionaryKey(button.confirmation_modal_confirm_text); + button.confirmation_modal_confirm_text = `#AUTO.${dictKey}#`; + } + } + } + } + } + } + + const widgetEditModalTitle = []; + const widgetEditModalCancel = []; + const widgetEditModalSave = []; + const widgetEditModalToastText = []; + + if (widgetInfo.display.edit_modal) { + for (const modal of widgetInfo.display.edit_modal) { + if (modal.title !== undefined) { + const isWidgetModalTitleDictionary = isDictionaryString(modal.title); + + if (!isWidgetModalTitleDictionary) { + widgetEditModalTitle.push(modal.title); + const dictKey = generateDictionaryKey(modal.title); + modal.title = `#AUTO.${dictKey}#`; + } + } + + if (modal.cancel !== undefined) { + const isWidgetModalCancelDictionary = isDictionaryString(modal.cancel); + + if (!isWidgetModalCancelDictionary) { + widgetEditModalCancel.push(modal.cancel); + const dictKey = generateDictionaryKey(modal.cancel); + modal.cancel = `#AUTO.${dictKey}#`; + } + } + + if (modal.save !== undefined) { + const isWidgetModalSaveDictionary = isDictionaryString(modal.save); + + if (!isWidgetModalSaveDictionary) { + widgetEditModalSave.push(modal.save); + const dictKey = generateDictionaryKey(modal.save); + modal.save = `#AUTO.${dictKey}#`; + } + } + + if (modal.toast_text !== undefined) { + const isWidgetModalToastTextDictionary = isDictionaryString(modal.toast_text); + + if (!isWidgetModalToastTextDictionary) { + widgetEditModalToastText.push(modal.toast_text); + const dictKey = generateDictionaryKey(modal.toast_text); + modal.toast_text = `#AUTO.${dictKey}#`; + } + } + } + } + + const widgetTotalRowsText = []; + if (widgetInfo.display.total_rows_text !== undefined) { + const isWidgetTotalRowsTextDictionary = isDictionaryString(widgetInfo.display.total_rows_text); + + if (!isWidgetTotalRowsTextDictionary) { + widgetTotalRowsText.push(widgetInfo.display.total_rows_text); + const dictKey = generateDictionaryKey(widgetInfo.display.total_rows_text); + widgetInfo.display.total_rows_text = `#AUTO.${dictKey}#`; + } + } + + const widgetButtonsText = []; + if (widgetInfo.display.buttons) { + for (const button of widgetInfo.display.buttons) { + if (button.text !== undefined) { + const isWidgetButtonDictionary = isDictionaryString(button.text); + + if (!isWidgetButtonDictionary) { + widgetButtonsText.push(button.text); + const dictKey = generateDictionaryKey(button.text); + button.text = `#AUTO.${dictKey}#`; + } + } + } + } + + const widgetSectionsDescription = []; + const widgetSectionsTitle = []; + const widgetSectionsFieldsLabel = []; + const widgetSectionsFieldsPlaceholder = []; + const widgetSectionsFieldsOptionsLabel = []; + if (widgetInfo.sections) { + for (const section of widgetInfo.sections) { + if (section.description !== undefined) { + const isWidgetSectionDescriptionDictionary = isDictionaryString(section.description); + + if (!isWidgetSectionDescriptionDictionary) { + widgetSectionsDescription.push(section.description); + const dictKey = generateDictionaryKey(section.description); + section.description = `#AUTO.${dictKey}#`; + } + } + + if (section.title !== undefined) { + const isWidgetSectionTitleDictionary = isDictionaryString(section.title); + + if (!isWidgetSectionTitleDictionary) { + widgetSectionsTitle.push(section.title); + const dictKey = generateDictionaryKey(section.title); + section.title = `#AUTO.${dictKey}#`; + } + } + + for (const field of section.fields) { + if (field.label !== undefined) { + const isWidgetFieldLabelDictionary = isDictionaryString(field.label); + + if (!isWidgetFieldLabelDictionary) { + widgetSectionsFieldsLabel.push(field.label); + const dictKey = generateDictionaryKey(field.label); + field.label = `#AUTO.${dictKey}#`; + } + } + + if (field.placeholder !== undefined) { + const isWidgetFieldPlaceholderDictionary = isDictionaryString(field.placeholder); + + if (!isWidgetFieldPlaceholderDictionary) { + widgetSectionsFieldsPlaceholder.push(field.placeholder); + const dictKey = generateDictionaryKey(field.placeholder); + field.placeholder = `#AUTO.${dictKey}#`; + } + } + + for (const option of field.options) { + if (option.label !== undefined) { + const isWidgetFieldOptionLabelDictionary = isDictionaryString(option.label); + + if (!isWidgetFieldOptionLabelDictionary) { + widgetSectionsFieldsOptionsLabel.push(option.label); + const dictKey = generateDictionaryKey(option.label); + option.label = `#AUTO.${dictKey}#`; + } + } + } + } + } + } + // } + + widgetDictionaries.push( + ...widgetHeaderButtonsText, + ...widgetVariablesTextContent, + ...widgetVariablesAlias, + ...widgetColumnsAlias, + ...widgetEditModalTitle, + ...widgetEditModalCancel, + ...widgetEditModalSave, + ...widgetEditModalToastText, + ...widgetTotalRowsText, + ...widgetButtonsText, + ...widgetSectionsDescription, + ...widgetSectionsTitle, + ...widgetSectionsFieldsLabel, + ...widgetSectionsFieldsPlaceholder, + ...widgetSectionsFieldsOptionsLabel + ); + + await editWidgetInfo(accountToken, dashboardID, widgetID, widgetInfo); +} + +export { getWidgetDictionary }; diff --git a/src/commands/profile/dictionary/get-widget-info.ts b/src/commands/profile/dictionary/get-widget-info.ts new file mode 100644 index 0000000..997260f --- /dev/null +++ b/src/commands/profile/dictionary/get-widget-info.ts @@ -0,0 +1,21 @@ +import axios, { AxiosRequestConfig } from "axios"; + +async function getWidgetInfo(dashboardID: string, widgetID: string, accountToken: string) { + const config: AxiosRequestConfig = { + method: "GET", + url: `https://api.tago.io/dashboard/${dashboardID}/widget/${widgetID}`, + headers: { + "Content-Type": "application/json", + Authorization: accountToken, + }, + }; + + return axios(config) + .then((r) => r.data.result) + .catch((error) => { + console.error(config); + throw error.response.data; + }); +} + +export { getWidgetInfo }; diff --git a/src/commands/profile/dictionary/is-dictionary-string.ts b/src/commands/profile/dictionary/is-dictionary-string.ts new file mode 100644 index 0000000..0a9ec12 --- /dev/null +++ b/src/commands/profile/dictionary/is-dictionary-string.ts @@ -0,0 +1,9 @@ +function isDictionaryString(string: string): boolean { + if (string.length === 0) { + return false; + } + + return string.at(0) === "#" && string.at(-1) === "#"; +} + +export { isDictionaryString }; diff --git a/src/commands/profile/dictionary/remove-strings.ts b/src/commands/profile/dictionary/remove-strings.ts new file mode 100644 index 0000000..934724f --- /dev/null +++ b/src/commands/profile/dictionary/remove-strings.ts @@ -0,0 +1,16 @@ +function removeDuplicatesAndEmptyStrings(arr: string[]): string[] { + const uniqueSet = new Set(); + const result: string[] = []; + + for (const item of arr) { + const lowerCasedItem = item.toLowerCase().trim(); + if (lowerCasedItem && !uniqueSet.has(lowerCasedItem)) { + uniqueSet.add(lowerCasedItem); + result.push(item); + } + } + + return result; +} + +export { removeDuplicatesAndEmptyStrings }; diff --git a/src/commands/profile/dictionary/text-locations.ts b/src/commands/profile/dictionary/text-locations.ts new file mode 100644 index 0000000..17ebba4 --- /dev/null +++ b/src/commands/profile/dictionary/text-locations.ts @@ -0,0 +1,32 @@ +const textLocationJson = { + dashLocations: [ + "dashInfo.label", + "dashInfo.tabs[i].value", //tabs use value instead of label + "dashInfo.blueprint_devices[i].label", // Blueprint devices name + "dashInfo.blueprint_devices[i].placeholder", // Blueprint devices placeholder + ], + widgetLocations: [ + "widgetInfo.label", // all widgets name + "widgetInfo.display.header_buttons[i].text", // Header buttons name + "widgetInfo.display.variables[i].text_content", // Static table text format + "widgetInfo.display.variables[i].alias", // Chart alias | Dynamic table column name + "widgetInfo.display.columns[i].alias", // Device List Column name + "widgetInfo.display.columns[i].buttons[j].confirmation_modal_title", // Device List Control Column label + "widgetInfo.display.columns[i].buttons[j].confirmation_modal_text", // Device List Control Column message + "widgetInfo.display.columns[i].buttons[j].confirmation_modal_cancel_text", // Device List Control Column button name + "widgetInfo.display.columns[i].buttons[j].confirmation_modal_confirm_text", // Device List Control Column button name + "widgetInfo.display.edit_modal_title", // Edit modal title + "widgetInfo.display.edit_modal_cancel", // Edit modal cancel + "widgetInfo.display.edit_modal_save", // Edit modal save + "widgetInfo.display.edit_modal_toast_text", // Edit modal toast + "widgetInfo.display.total_rows_text", // Total rows text + "widgetInfo.display.buttons[i].text", // Button name (e.g. "Save" | "Submit" for forms) + "widgetInfo.sections[i].description", // Section description + "widgetInfo.sections[i].title", // Section title + "widgetInfo.sections[i].fields[j].label", // Field label + "widgetInfo.sections[i].fields[j].placeholder", // Field placeholder + "widgetInfo.sections[i].fields[j].options[k].label", // Dropdown input options + ], +}; + +textLocationJson;