From b9d3dd7074eba13740a065637be813ae599a7113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20Vlachov=C3=A1?= <65499282+janavlachova@users.noreply.github.com> Date: Tue, 28 Jan 2025 19:23:28 +0100 Subject: [PATCH] [studio] fix fetch on update in db and user views #1532 (#1546) studio - fixed fetch in tables --- .../base/table/AgdbCellMenu.spec.ts | 19 +++---- .../components/base/table/AgdbCellMenu.vue | 18 ++++--- .../components/base/table/AgdbTable.spec.ts | 8 ++- .../base/table/AgdbTableRow.spec.ts | 3 ++ agdb_studio/src/components/db/DbTable.vue | 3 +- agdb_studio/src/components/user/UserTable.vue | 3 +- .../src/composables/table/tableConfig.spec.ts | 49 +++++++++++++++++-- .../src/composables/table/tableConfig.ts | 17 +++++++ .../src/composables/table/tableData.spec.ts | 6 ++- .../src/composables/table/tableFilter.spec.ts | 4 +- agdb_studio/src/composables/table/types.ts | 1 + 11 files changed, 105 insertions(+), 26 deletions(-) diff --git a/agdb_studio/src/components/base/table/AgdbCellMenu.spec.ts b/agdb_studio/src/components/base/table/AgdbCellMenu.spec.ts index dfa3b76f..db154001 100644 --- a/agdb_studio/src/components/base/table/AgdbCellMenu.spec.ts +++ b/agdb_studio/src/components/base/table/AgdbCellMenu.spec.ts @@ -2,25 +2,24 @@ import { mount } from "@vue/test-utils"; import AgdbCellMenu from "./AgdbCellMenu.vue"; import { describe, beforeEach, vi, it, expect } from "vitest"; import { dbActions } from "@/composables/db/dbConfig"; -import { INJECT_KEY_ROW } from "@/composables/table/constants"; +import { + INJECT_KEY_ROW, + INJECT_KEY_TABLE_NAME, +} from "@/composables/table/constants"; import useModal from "@/composables/modal/modal"; import { convertArrayOfStringsToContent } from "@/composables/content/utils"; import DropdownContent from "../dropdown/DropdownContent.vue"; import type { TRow } from "@/composables/table/types"; -const { fetchDatabases } = vi.hoisted(() => { +const { fetchData } = vi.hoisted(() => { return { - fetchDatabases: vi.fn(), + fetchData: vi.fn(), }; }); const { modalIsVisible, onConfirm, modal, closeModal } = useModal(); -vi.mock("@/composables/db/dbStore", () => { +vi.mock("@/composables/table/tableConfig", () => { return { - useDbStore: () => { - return { - fetchDatabases, - }; - }, + fetchData, }; }); describe("AgdbCellMenu", () => { @@ -89,6 +88,7 @@ describe("AgdbCellMenu", () => { await action.trigger("click"); await wrapper.vm.$nextTick(); expect(dropdown.isVisible()).toBe(false); + expect(fetchData).toHaveBeenCalledOnce(); }); it("should open the modal on click when confirmation is required", async () => { const deleteAction = vi.fn(); @@ -122,6 +122,7 @@ describe("AgdbCellMenu", () => { backup: 0, }, }, + [INJECT_KEY_TABLE_NAME]: "databases", }, }, }); diff --git a/agdb_studio/src/components/base/table/AgdbCellMenu.vue b/agdb_studio/src/components/base/table/AgdbCellMenu.vue index 3057b833..d4806b51 100644 --- a/agdb_studio/src/components/base/table/AgdbCellMenu.vue +++ b/agdb_studio/src/components/base/table/AgdbCellMenu.vue @@ -3,17 +3,21 @@ import type { TRow } from "@/composables/table/types"; import AgdbDropdown from "../dropdown/AgdbDropdown.vue"; import { MdRoundMenu } from "@kalimahapps/vue-icons"; import { computed, inject, type PropType, type Ref } from "vue"; -import { INJECT_KEY_ROW } from "@/composables/table/constants"; +import { + INJECT_KEY_ROW, + INJECT_KEY_TABLE_NAME, +} from "@/composables/table/constants"; import AgdbMenu from "../menu/AgdbMenu.vue"; -import { useDbStore } from "@/composables/db/dbStore"; import useModal from "@/composables/modal/modal"; +import { fetchData } from "@/composables/table/tableConfig"; const props = defineProps({ actions: { type: Array as PropType[]>, required: true }, }); const row = inject>(INJECT_KEY_ROW); -const { fetchDatabases } = useDbStore(); +const tableName = inject>(INJECT_KEY_TABLE_NAME); + const { openModal } = useModal(); const mapActions = (actions: Action[]): Action[] => { @@ -21,14 +25,16 @@ const mapActions = (actions: Action[]): Action[] => { return actions.map((action) => { const runAction: ActionFn | undefined = action.action - ? ({ event }: ActionProps): ActionReturn => { + ? async ({ + event, + }: ActionProps): Promise => { /* v8 ignore next */ if (!action.action) return false; - const result = action.action({ + const result = await action.action({ event, params: row?.value, }); - fetchDatabases(); + await fetchData(tableName?.value); return result; } : undefined; diff --git a/agdb_studio/src/components/base/table/AgdbTable.spec.ts b/agdb_studio/src/components/base/table/AgdbTable.spec.ts index 49fd96c5..af6ab535 100644 --- a/agdb_studio/src/components/base/table/AgdbTable.spec.ts +++ b/agdb_studio/src/components/base/table/AgdbTable.spec.ts @@ -3,14 +3,18 @@ import AgdbTable from "./AgdbTable.vue"; import { addTable, clearTables } from "@/composables/table/tableConfig"; import { setTableData } from "@/composables/table/tableData"; import { TABLE_NAME, tableConfig, tableData } from "@/tests/tableMocks"; -import { describe, beforeEach, it, expect } from "vitest"; +import { describe, beforeEach, it, expect, vi } from "vitest"; describe("AgdbTable", () => { beforeEach(() => { clearTables(); }); it("should render for correct data", () => { - addTable({ name: TABLE_NAME, columns: tableConfig }); + addTable({ + name: TABLE_NAME, + columns: tableConfig, + fetchData: vi.fn(), + }); setTableData(TABLE_NAME, tableData); const wrapper = mount(AgdbTable, { diff --git a/agdb_studio/src/components/base/table/AgdbTableRow.spec.ts b/agdb_studio/src/components/base/table/AgdbTableRow.spec.ts index 31ef72eb..d537c84c 100644 --- a/agdb_studio/src/components/base/table/AgdbTableRow.spec.ts +++ b/agdb_studio/src/components/base/table/AgdbTableRow.spec.ts @@ -29,10 +29,12 @@ vi.mock("@/composables/db/dbUsersStore", () => { }); describe("TableRow", () => { + const fetchDataMock = vi.fn(); addTable({ name: TABLE_NAME, columns: tableConfig, rowDetailsComponent: "DbDetails", + fetchData: fetchDataMock, }); it("should render", () => { @@ -96,6 +98,7 @@ describe("TableRow", () => { addTable({ name: "table_without_row_details", columns: tableConfig, + fetchData: fetchDataMock, }); const wrapper = mount(AgdbTableRow, { props: { diff --git a/agdb_studio/src/components/db/DbTable.vue b/agdb_studio/src/components/db/DbTable.vue index 08377bd8..8872245b 100644 --- a/agdb_studio/src/components/db/DbTable.vue +++ b/agdb_studio/src/components/db/DbTable.vue @@ -6,7 +6,7 @@ import { setTableData } from "@/composables/table/tableData"; import { watchEffect } from "vue"; import { dbColumns } from "@/composables/db/dbConfig"; -const { databases, getDbName } = useDbStore(); +const { databases, getDbName, fetchDatabases } = useDbStore(); const TABLE_KEY = Symbol("databases"); @@ -16,6 +16,7 @@ addTable({ rowDetailsComponent: "DbDetails", uniqueKey: (row) => getDbName({ owner: row.owner.toString(), db: row.db.toString() }), + fetchData: fetchDatabases, }); watchEffect(() => { diff --git a/agdb_studio/src/components/user/UserTable.vue b/agdb_studio/src/components/user/UserTable.vue index 15a86144..c644ba4c 100644 --- a/agdb_studio/src/components/user/UserTable.vue +++ b/agdb_studio/src/components/user/UserTable.vue @@ -6,7 +6,7 @@ import { useUserStore } from "@/composables/user/userStore"; import { watchEffect } from "vue"; import AgdbTable from "../base/table/AgdbTable.vue"; -const { users } = useUserStore(); +const { users, fetchUsers } = useUserStore(); const TABLE_KEY = Symbol("users"); @@ -14,6 +14,7 @@ addTable({ name: TABLE_KEY, columns: userColumns, uniqueKey: "username", + fetchData: fetchUsers, }); watchEffect(() => { diff --git a/agdb_studio/src/composables/table/tableConfig.spec.ts b/agdb_studio/src/composables/table/tableConfig.spec.ts index 4318e3c2..1c196782 100644 --- a/agdb_studio/src/composables/table/tableConfig.spec.ts +++ b/agdb_studio/src/composables/table/tableConfig.spec.ts @@ -6,21 +6,29 @@ import { getTableColumnsArray, removeTable, tableExists, + fetchData, } from "./tableConfig"; import { TABLE_NAME, tableConfig, columnsMap } from "@/tests/tableMocks"; -import { describe, beforeEach, it, expect } from "vitest"; +import { describe, beforeEach, it, expect, vi } from "vitest"; describe("tableData", () => { + const fetchDataMock = vi.fn(); beforeEach(() => { + vi.clearAllMocks(); clearTables(); }); it("should return table configs", () => { - addTable({ name: TABLE_NAME, columns: tableConfig }); + addTable({ + name: TABLE_NAME, + columns: tableConfig, + fetchData: fetchDataMock, + }); const table = getTable(TABLE_NAME); expect(table).toEqual({ name: TABLE_NAME, columns: columnsMap, data: new Map(), + fetchData: fetchDataMock, }); const columns = getTableColumns(TABLE_NAME); expect(columns).toEqual(columnsMap); @@ -41,7 +49,11 @@ describe("tableData", () => { }); it("should remove table", () => { - addTable({ name: TABLE_NAME, columns: tableConfig }); + addTable({ + name: TABLE_NAME, + columns: tableConfig, + fetchData: fetchDataMock, + }); const table = getTable(TABLE_NAME); expect(table).toBeDefined(); removeTable(TABLE_NAME); @@ -50,8 +62,37 @@ describe("tableData", () => { }); it("should check if table exists", () => { - addTable({ name: TABLE_NAME, columns: tableConfig }); + addTable({ + name: TABLE_NAME, + columns: tableConfig, + fetchData: fetchDataMock, + }); expect(tableExists(TABLE_NAME)).toBeTruthy(); expect(tableExists("non_existent_table")).toBeFalsy(); }); + + it("should fetch data", async () => { + addTable({ + name: TABLE_NAME, + columns: tableConfig, + fetchData: fetchDataMock, + }); + await fetchData(TABLE_NAME); + expect(fetchDataMock).toHaveBeenCalled(); + }); + + it("should fetch data for all tables", async () => { + addTable({ + name: TABLE_NAME, + columns: tableConfig, + fetchData: fetchDataMock, + }); + addTable({ + name: "table2", + columns: tableConfig, + fetchData: fetchDataMock, + }); + await fetchData(undefined); + expect(fetchDataMock).toHaveBeenCalledTimes(2); + }); }); diff --git a/agdb_studio/src/composables/table/tableConfig.ts b/agdb_studio/src/composables/table/tableConfig.ts index 027f112f..80667313 100644 --- a/agdb_studio/src/composables/table/tableConfig.ts +++ b/agdb_studio/src/composables/table/tableConfig.ts @@ -10,6 +10,7 @@ type AddTableProps = { columns: Column[]; rowDetailsComponent?: AsyncComponent; uniqueKey?: string | ((row: T) => string); + fetchData: () => Promise; }; const addTable = ({ @@ -17,6 +18,7 @@ const addTable = ({ columns, rowDetailsComponent, uniqueKey, + fetchData, }: AddTableProps): void => { const columnMap = new Map>(); columns.forEach((column) => { @@ -28,6 +30,7 @@ const addTable = ({ data: new Map(), rowDetailsComponent, uniqueKey, + fetchData, }); }; @@ -63,6 +66,19 @@ const clearTables = (): void => { tables.value.clear(); }; +const fetchData = async (name: symbol | string | undefined): Promise => { + if (!name) { + tables.value.forEach(async (table) => { + await table.fetchData(); + }); + return; + } + const table = getTable(name); + if (table) { + await table.fetchData(); + } +}; + export { getTable, addTable, @@ -71,4 +87,5 @@ export { clearTables, getTableColumns, getTableColumnsArray, + fetchData, }; diff --git a/agdb_studio/src/composables/table/tableData.spec.ts b/agdb_studio/src/composables/table/tableData.spec.ts index 4614be8c..82c09ac5 100644 --- a/agdb_studio/src/composables/table/tableData.spec.ts +++ b/agdb_studio/src/composables/table/tableData.spec.ts @@ -8,15 +8,17 @@ import { } from "./tableData"; import { TABLE_NAME, tableConfig, tableData } from "@/tests/tableMocks"; import { addFilter, getTableFilter, setSort } from "./tableFilter"; -import { describe, beforeEach, it, expect } from "vitest"; +import { describe, beforeEach, it, expect, vi } from "vitest"; import type { TRow } from "./types"; describe("tableData", () => { + const fetchDataMock = vi.fn(); addTable({ name: TABLE_NAME, columns: tableConfig, uniqueKey: (row: TRow) => `${row.owner.toString()}/${row.db.toString()}`, + fetchData: fetchDataMock, }); beforeEach(() => { @@ -41,6 +43,7 @@ describe("tableData", () => { addTable({ name: "table_without_unique_key", columns: tableConfig, + fetchData: fetchDataMock, }); setTableData("table_without_unique_key", tableData); const table = getTable("table_without_unique_key"); @@ -54,6 +57,7 @@ describe("tableData", () => { { key: "value", title: "Value" }, ], uniqueKey: "key", + fetchData: fetchDataMock, }); setTableData("table_with_string_unique_key", [ { key: "key1", value: "value1" }, diff --git a/agdb_studio/src/composables/table/tableFilter.spec.ts b/agdb_studio/src/composables/table/tableFilter.spec.ts index c601671b..3b9b7601 100644 --- a/agdb_studio/src/composables/table/tableFilter.spec.ts +++ b/agdb_studio/src/composables/table/tableFilter.spec.ts @@ -7,10 +7,10 @@ import { removeFilter, setSort, } from "./tableFilter"; -import { describe, beforeEach, it, expect } from "vitest"; +import { describe, beforeEach, it, expect, vi } from "vitest"; describe("tableFilter", () => { - addTable({ name: TABLE_NAME, columns: tableConfig }); + addTable({ name: TABLE_NAME, columns: tableConfig, fetchData: vi.fn() }); setTableData(TABLE_NAME, tableData); beforeEach(() => { diff --git a/agdb_studio/src/composables/table/types.ts b/agdb_studio/src/composables/table/types.ts index 1c556e48..89eacdb3 100644 --- a/agdb_studio/src/composables/table/types.ts +++ b/agdb_studio/src/composables/table/types.ts @@ -30,4 +30,5 @@ export type Table = { data?: Map; rowDetailsComponent?: AsyncComponent; uniqueKey?: string | ((row: T) => string); + fetchData: () => Promise; };