Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/analysis/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ async function startAnalysis(context: TagoContext, scope: Data[]): Promise<void>

// group routing
router.register(groupAdd).whenInputFormID("create-group");
router.register(groupDel).whenDeviceListIdentifier("delete-group");
_fixDashCustomBtnID(environment, scope);
router.register(groupDel).whenCustomBtnID("delete-group");
router.register(groupEdit).whenCustomBtnID("edit-group");

// User routing
Expand All @@ -98,7 +99,6 @@ async function startAnalysis(context: TagoContext, scope: Data[]): Promise<void>

//Plan routing
router.register(planAdd).whenInputFormID("create-plan");
_fixDashCustomBtnID(environment, scope);
router.register(planDel).whenCustomBtnID("delete-plan");;
router.register(planEdit).whenCustomBtnID("edit-plan");;

Expand Down
65 changes: 41 additions & 24 deletions src/services/group/edit.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
import { Resources } from "@tago-io/sdk";
import { DeviceListScope } from "@tago-io/sdk/lib/modules/Utils/router/router.types";

import { deviceNameExists } from "../../lib/device-name-exists";
import { sendNotificationFeedback } from "../../lib/send-notification";
import { undoDeviceChanges } from "../../lib/undo-device-changes";
import { undoEntityChanges } from "../../lib/undo-entity-changes";
import { RouterConstructorDevice } from "../../types";
import { EntityInfo } from "@tago-io/sdk/lib/modules/Resources/entities.types";
import { entityNameExists } from "../../lib/entity-name-exists";

async function editEntity(group_info: EntityInfo, new_group_name: string, new_group_address: string) {

let tags = group_info.tags;
if (new_group_address) {
tags = tags.map(tag => tag.key === "group_address" ? { ...tag, value: new_group_address } : tag);
}

await Resources.entities.edit(group_info.id, {
name: new_group_name,
tags
});
}

/**
* Main function of editing groups
Expand All @@ -15,13 +28,30 @@ async function groupEdit({ scope, environment }: RouterConstructorDevice & { sco
if (!environment || !scope) {
throw new Error("Missing parameters");
}
const group_id = scope[0].device;
const new_group_name = scope[0].name;
const orgGroup_id = scope[0].entity;
const dataId = scope[0].id;

const [orgGroupData] = await Resources.entities.getEntityData(orgGroup_id, {
filter: {
id: dataId,
},
amount: 1,
index: "id_idx",
});

if (!orgGroupData) {
throw new Error("Organization group not found");
}

const group_id = orgGroupData.group_id;

const new_group_name = scope[0].group_name;
const new_group_address = scope[0].group_address;
const group_info = await Resources.entities.info(group_id);
const org_id = group_info.tags.find((x) => x.key === "organization_id")?.value as string;

if (new_group_name) {
const group_info = await Resources.devices.info(group_id);
const org_id = group_info.tags.find((x) => x.key === "organization_id")?.value as string;
const is_device_name_exists = await deviceNameExists({
const is_group_name_exists = await entityNameExists({
name: new_group_name,
tags: [
{ key: "device_type", value: "group" },
Expand All @@ -30,27 +60,14 @@ async function groupEdit({ scope, environment }: RouterConstructorDevice & { sco
isEdit: true,
});

if (is_device_name_exists) {
await undoDeviceChanges({ deviceInfo: group_info, scope });
if (is_group_name_exists) {
await undoEntityChanges({ entityInfo: group_info, scope });
await sendNotificationFeedback({ environment, message: `The organization with name ${new_group_name} already exists.` });
throw `The organization with name ${new_group_name} already exists.`;
}
}

const { tags } = await Resources.devices.info(group_id);
if (!tags) {
throw new Error("Tags not found");
}
const org_id = tags.find((tag) => tag.key === "organization_id")?.value;
if (!org_id) {
throw new Error("Organization id not found");
}

const [group_id_data] = await Resources.devices.getDeviceData(org_id, { variables: "group_id", groups: group_id, qty: 1 });
if (group_id_data) {
await Resources.devices.deleteDeviceData(org_id, { variables: "group_id", groups: group_id });
await Resources.devices.sendDeviceData(org_id, { ...group_id_data, metadata: { ...group_id_data.metadata, label: new_group_name } });
}
await editEntity(group_info, new_group_name, new_group_address);

return console.debug("Group edited!");
}
Expand Down
77 changes: 77 additions & 0 deletions src/services/group/group.model.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { describe, it, expect } from "vitest";
import { groupModel, IGroup } from "./group.model";

describe("Group Model", () => {
describe("Valid cases", () => {
it("should validate a group with required fields", () => {
const validGroup = {
name: "Test Group",
};

const result = groupModel.safeParse(validGroup);
expect(result.success).toBe(true);
if (result.success) {
expect(result.data).toEqual(validGroup);
}
});

it("should validate a group with all fields", () => {
const validGroup = {
name: "Test Group",
address: "123 Test Street",
};

const result = groupModel.safeParse(validGroup);
expect(result.success).toBe(true);
if (result.success) {
expect(result.data).toEqual(validGroup);
}
});
});

describe("Invalid cases", () => {
it("should reject a group without a name", () => {
const invalidGroup = {};

const result = groupModel.safeParse(invalidGroup);
expect(result.success).toBe(false);
if (!result.success) {
expect(result.error.issues[0].message).toBe("Name is required");
}
});

it("should reject a group with a name shorter than 3 characters", () => {
const invalidGroup = {
name: "Te",
};

const result = groupModel.safeParse(invalidGroup);
expect(result.success).toBe(false);
if (!result.success) {
expect(result.error.issues[0].message).toBe("Name is smaller than 3 characters");
}
});

it("should reject a group with invalid field types", () => {
const invalidGroup = {
name: 123, // number instead of string
address: 456, // number instead of string
};

const result = groupModel.safeParse(invalidGroup);
expect(result.success).toBe(false);
});
});

describe("Type checking", () => {
it("should have correct TypeScript type inference", () => {
const group: IGroup = {
name: "Test Group",
address: "123 Test Street",
};

// This test will fail at compile time if the type is incorrect
expect(group).toBeDefined();
});
});
});
10 changes: 10 additions & 0 deletions src/services/group/group.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { z } from "zod";

const groupModel = z.object({
name: z.string({ required_error: "Name is required" }).min(3, { message: "Name is smaller than 3 characters" }),
address: z.string().optional(),
});

type IGroup = z.infer<typeof groupModel>;

export { IGroup, groupModel };
Loading