Skip to content

Commit

Permalink
Merge pull request #7 from tago-io/feat/newCmds
Browse files Browse the repository at this point in the history
fixed export for tago run new fields
  • Loading branch information
vitorfdl authored Sep 5, 2023
2 parents 25f9259 + 07d4fd7 commit 165dbba
Show file tree
Hide file tree
Showing 14 changed files with 749 additions and 394 deletions.
779 changes: 401 additions & 378 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tago-io/cli",
"version": "1.4.1",
"version": "1.5.0",
"description": "TagoIO Application CLI Node.JS",
"main": "./build/index.js",
"repository": "tago-io/tagoio-cli",
Expand Down Expand Up @@ -53,7 +53,7 @@
"luxon": "^3.4.1",
"prompts": "^2.4.2",
"socket.io-client": "4.7.2",
"string-comparison": "^1.1.0"
"string-comparison": "^1.2.0"
},
"devDependencies": {
"@types/async": "^3.2.20",
Expand All @@ -76,6 +76,6 @@
"prettier": "3.0.2",
"ts-jest": "^29.1.1",
"ts-node-dev": "2.0.0",
"typescript": "^5.1.6"
"typescript": "^5.2.2"
}
}
150 changes: 150 additions & 0 deletions src/commands/dashboard/copy-tab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import kleur from "kleur";
import prompts from "prompts";

import { Account } from "@tago-io/sdk";
import { DashboardInfo } from "@tago-io/sdk/lib/types";

import { getEnvironmentConfig } from "../../lib/config-file";
import { errorHandler, infoMSG, successMSG } from "../../lib/messages";
import { confirmPrompt } from "../../prompt/confirm";
import { pickDashboardIDFromTagoIO } from "../../prompt/pick-dashboard-id-from-tagoio";

interface IOptions {
to: string;
from: string;
environment: string;
amount: number;
}

interface DashboardTabs {
key: string;
value: string;
link: string;
hidden: boolean;
}

/**
*
* @param account
* @param dashID
* @param arrangement
* @param tabID
* @returns
*/
async function deleteWidgetsFromTab(account: Account, dashID: string, arrangement: DashboardInfo["arrangement"], tabID: string) {
if (!arrangement) {
return;
}

const myTabWidgets = arrangement.filter((x) => x.tab === tabID);
for (const item of myTabWidgets) {
await account.dashboards.widgets.delete(dashID, item.widget_id);
}

return arrangement.filter((x) => x.tab !== tabID);
}

/**
*
* @param account
* @param dashID
* @param arrangement
* @param tabID
* @param toTabID
* @returns
*/
async function copyWidgetsFromTab(account: Account, dashID: string, arrangement: DashboardInfo["arrangement"], tabID: string, toTabID: string) {
if (!arrangement) {
return;
}

const fromTabWidgets = arrangement.filter((x) => x.tab === tabID);
for (const item of fromTabWidgets) {
const widgetInfo = await account.dashboards.widgets.info(dashID, item.widget_id);
const { widget: newWidgetID } = await account.dashboards.widgets.create(dashID, widgetInfo);
arrangement.push({
widget_id: newWidgetID,
tab: toTabID,
x: item.x,
y: item.y,
width: item.width,
height: item.height,
});
}

return arrangement;
}

/**
*
* @param list
* @param message
* @returns
*/
async function pickTabFromDashboard(list: { title: string; value: string }[], message: string = "Which tab you want to pick?") {
const { id } = await prompts({
message,
name: "id",
type: "autocomplete",
choices: list,
});

return id as string;
}

/**
*
* @param dashID
* @param options
* @returns
*/
async function copyTabWidgets(dashID: string, options: IOptions) {
const config = getEnvironmentConfig(options.environment);
if (!config || !config.profileToken) {
errorHandler("Environment not found");
return;
}

const account = new Account({ token: config.profileToken, region: "usa-1" });
if (!dashID) {
dashID = await pickDashboardIDFromTagoIO(account);
}

const dashInfo = await account.dashboards.info(dashID);

if (!options.from || !options.to) {
let tabList = (dashInfo.tabs as DashboardTabs[]).map((x, i) => ({ title: `${i}. ${x.value} [${x.key}]`, value: x.key }));
if (!options.from) {
options.from = await pickTabFromDashboard(tabList, "Pick a source tab to copy the data from:");
}

tabList = tabList.filter((x) => x.value !== options.from);
if (!options.to) {
options.to = await pickTabFromDashboard(tabList, "Pick a target tab to copy the data to: ");
}
}

const { to, from } = options;
if (to === from) {
errorHandler("You can't copy data from and to the same tab");
return;
}

const toTabName = (dashInfo.tabs as DashboardTabs[]).find((x) => x.key === to)?.value as string;
const fromTabName = (dashInfo.tabs as DashboardTabs[]).find((x) => x.key === from)?.value as string;

infoMSG(`> Copying tab ${kleur.cyan(fromTabName)} to ${kleur.cyan(toTabName)}...`);
const yesNo = await confirmPrompt();
if (!yesNo) {
return;
}

let arrangement = await deleteWidgetsFromTab(account, dashID, dashInfo.arrangement, to);
arrangement = await copyWidgetsFromTab(account, dashID, arrangement, from, to);

await account.dashboards.edit(dashID, { arrangement });

successMSG(`> Tab ${fromTabName} [${kleur.cyan(from)}] copied to ${toTabName} [${kleur.cyan(to)}]`);
}

export { copyTabWidgets };
37 changes: 37 additions & 0 deletions src/commands/dashboard/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Command } from "commander";

import { copyTabWidgets } from "./copy-tab";

// function handleNumber(value: any, _previous: any) {
// if (Number.isNaN(Number(value))) {
// throw `${value} is not a number`;
// }
// return Number(value);
// }

function dashboardCommands(program: Command) {
program.command("Devices Header");
program
.command("copy-tab")
.alias("inspect")
.description("copy a tab of a dashboard to another tab")
.argument("[dashboardID]", "ID of the dashboard")
.option("-from, --from [tabID]", "ID of the Tab to copy")
.option("-to, --to [tabID]", "ID of the Tab to paste")
.option("--env [environment]", "environment from config.js")
// .option("-g, --getOnly", "fiter logs to show GET content only")
.action(copyTabWidgets)
.addHelpText(
"after",
`
Running this command will completely erase the target tab and replace it with a copy of the source tab.
Example:
$ tagoio copy-tab
$ tagoio copy-tab 62151835435d540010b768c4 -from 1688653060637 -to 2688653060638
$ tagoio copy-tab 62151835435d540010b768c4 --env dev
`
);
}

export { dashboardCommands };
85 changes: 85 additions & 0 deletions src/commands/devices/copy-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { Account, Device, Utils } from "@tago-io/sdk";

import { getEnvironmentConfig } from "../../lib/config-file";
import { errorHandler, highlightMSG, infoMSG, successMSG } from "../../lib/messages";
import { confirmPrompt } from "../../prompt/confirm";
import { pickDeviceIDFromTagoIO } from "../../prompt/pick-device-id-from-tagoio";

interface IOptions {
to: string;
from: string;
environment: string;
amount: number;
}

async function startCopy(deviceFrom: Device, deviceTo: Device, options: IOptions) {
const { amount } = options;

const dataStream = deviceFrom.getDataStreaming({}, { poolingRecordQty: 2000, poolingTime: 400, neverStop: false });

let total = 0;
for await (let data of dataStream) {
data = data.filter((x) => x.variable !== "payload");
total += data.length;
await deviceTo.sendData(data);
if (total >= amount) {
break;
}
}

successMSG(`> Data transfer completed. A total of ${total} registers were copied.`);
}

async function copyDeviceData(options: IOptions) {
const config = getEnvironmentConfig(options.environment);
if (!config || !config.profileToken) {
errorHandler("Environment not found");
return;
}

if (!options.from || !options.to) {
const account = new Account({ token: config.profileToken, region: "usa-1" });
options.from = await pickDeviceIDFromTagoIO(account, "Choose a device to copy the data from:");
options.to = await pickDeviceIDFromTagoIO(account, "Choose a device to copy the data to: ");
}

let deviceFrom: Device | undefined;
let deviceTo: Device | undefined;
if (options.from?.length === 24 || options.to?.length === 24) {
const account = new Account({ token: config.profileToken, region: "usa-1" });

if (options.from.length === 24) {
deviceFrom = await Utils.getDevice(account, options.from);
}

if (options.to.length === 24) {
deviceTo = await Utils.getDevice(account, options.to);
}
}

if (!deviceTo || !deviceFrom) {
errorHandler("Device not found");
return;
}

if (!deviceFrom) {
deviceFrom = new Device({ token: options.from });
}

if (!deviceTo) {
deviceTo = new Device({ token: options.to });
}

const deviceToInfo = await deviceTo.info();
const deviceFromInfo = await deviceFrom.info();

infoMSG(`> Copying tab ${highlightMSG(deviceFromInfo.name)} to ${highlightMSG(deviceToInfo.name)}...`);
const yesNo = await confirmPrompt();
if (!yesNo) {
return;
}

await startCopy(deviceFrom, deviceTo, options);
}

export { copyDeviceData };
19 changes: 19 additions & 0 deletions src/commands/devices/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Command } from "commander";

import { cmdRepeteableValue } from "../../lib/commander-repeatable";
import { changeBucketType } from "./change-bucket-type";
import { copyDeviceData } from "./copy-data";
import { getDeviceData } from "./data-get";
import { bkpDeviceData } from "./device-bkp";
import { deviceInfo } from "./device-info";
Expand Down Expand Up @@ -147,6 +148,24 @@ Example:
$ tagoio device-type 62151835435d540010b768c4
`
);

program
.command("device-copy")
.description(`copy data from one device to another`)
.option("-from, --from [token/id]", "token/id of the device where data will be copied from")
.option("-to, --to [token/id]", "token/id of the device where data will be copied to")
.option("-qty, --qty <number>", "amount of data to be copy", handleNumber, 10_000)
.option("-env, --environment [environment]", "environment from config.js")
.action(copyDeviceData)
.addHelpText(
"after",
`
Example:
$ tagoio device-copy
$ tagoio device-copy --to 62151835435d540010b768c4 --from 78151835435d540010b768c4
`
);
}

export { deviceCommands };
20 changes: 15 additions & 5 deletions src/commands/list-env.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Account } from "@tago-io/sdk";

import { getConfigFile, writeToConfigFile } from "../lib/config-file";
import { infoMSG } from "../lib/messages";
import { readToken } from "../lib/token";
Expand All @@ -20,11 +21,20 @@ async function fixEnvironments(configFile: ReturnType<typeof getConfigFile>, env
}

const account = new Account({ token });
const profile = await account.profiles.info("current");
const accInfo = await account.info();
environment.id = profile.info.id;
environment.profileName = profile.info.name;
environment.email = accInfo.email;
const profile = await account.profiles.info("current").catch((error) => {
console.error(`Error getting profile info for ${env}: ${error.message}`);
return;
});

if (profile) {
const accInfo = await account.info();
environment.id = profile.info.id;
environment.profileName = profile.info.name;
environment.email = accInfo.email;
} else if (!environment.id && !environment.profileName) {
environment.id = "N/A";
environment.profileName = "N/A";
}
}

writeToConfigFile(configFile);
Expand Down
3 changes: 2 additions & 1 deletion src/commands/profile/export/services/access-export.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Account } from "@tago-io/sdk";

import { replaceObj } from "../../../../lib/replace-obj";
import { IExportHolder } from "../types";

Expand All @@ -17,7 +18,7 @@ async function accessExport(account: Account, import_account: Account, export_ho

let { id: target_id } = import_list.find((access) => access.tags?.find((tag) => tag.key === "export_id" && tag.value == export_id)) || { id: null };

const new_access = replaceObj(access, { ...export_holder.devices, ...export_holder.dashboards });
const new_access = replaceObj(access, { ...export_holder.devices, ...export_holder.dashboards, ...export_holder.analysis });
if (!target_id) {
({ am_id: target_id } = await import_account.accessManagement.create(new_access));
} else {
Expand Down
6 changes: 6 additions & 0 deletions src/commands/profile/export/services/run-buttons-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ async function runButtonsExport(account: Account, import_account: Account, expor
targetRunInfo.email_templates[template_name] = email_obj;
}

// Custom Fields
// @ts-expect-error SDK doesn't have custom fields property yet
targetRunInfo.custom_fields = runInfo.custom_fields;

targetRunInfo.signin_buttons = runInfo.signin_buttons;

// @ts-expect-error ignore error
delete targetRunInfo.created_at;

Expand Down
Loading

0 comments on commit 165dbba

Please sign in to comment.