From e62a513a980762f9f8c8efc24b6e3562bd64fd2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20Vlachov=C3=A1?= <65499282+janavlachova@users.noreply.github.com> Date: Sat, 4 Jan 2025 13:38:36 +0100 Subject: [PATCH] [studio] expand table row #1458 (#1459) studio - expand table row --- agdb_studio/src/assets/button.less | 6 ++ .../components/base/dropdown/AgdbDropdown.vue | 6 +- .../src/components/base/menu/AgdbMenu.vue | 6 +- .../components/base/modal/AgdbModal.spec.ts | 10 +++- .../src/components/base/modal/AgdbModal.vue | 16 ++---- .../src/components/base/table/AgdbTable.vue | 8 ++- .../components/base/table/AgdbTableHeader.vue | 26 +++++---- .../base/table/AgdbTableRow.spec.ts | 45 ++++++++++++++- .../components/base/table/AgdbTableRow.vue | 57 +++++++++++++++++-- agdb_studio/src/components/db/DbTable.vue | 5 +- .../transitions/SlideUpTransition.vue | 22 +++++++ .../src/composables/table/tableConfig.ts | 30 +++++++--- .../src/composables/table/tableData.ts | 20 ++++--- .../src/composables/table/tableFilter.ts | 10 ++-- agdb_studio/src/composables/table/types.ts | 3 +- 15 files changed, 205 insertions(+), 65 deletions(-) create mode 100644 agdb_studio/src/components/transitions/SlideUpTransition.vue diff --git a/agdb_studio/src/assets/button.less b/agdb_studio/src/assets/button.less index b988ce18..a8cf61a8 100644 --- a/agdb_studio/src/assets/button.less +++ b/agdb_studio/src/assets/button.less @@ -43,6 +43,12 @@ --borderColor: #af2836; } +.button-transparent { + --backgroundColor: transparent; + --color: var(--color-text); + --borderColor: transparent; +} + .button:hover { opacity: 0.8; } diff --git a/agdb_studio/src/components/base/dropdown/AgdbDropdown.vue b/agdb_studio/src/components/base/dropdown/AgdbDropdown.vue index 44a918eb..a1c53a48 100644 --- a/agdb_studio/src/components/base/dropdown/AgdbDropdown.vue +++ b/agdb_studio/src/components/base/dropdown/AgdbDropdown.vue @@ -2,7 +2,7 @@ import { vOnClickOutside } from "@vueuse/components"; import { ref } from "vue"; import DropdownContent from "./DropdownContent.vue"; -import FadeTrasition from "@/components/transitions/FadeTrasition.vue"; +import SlideUpTransition from "@/components/transitions/SlideUpTransition.vue"; const opened = ref(false); const close = () => { @@ -25,7 +25,7 @@ const buttonRef = ref(); - + (); > - + diff --git a/agdb_studio/src/components/base/menu/AgdbMenu.vue b/agdb_studio/src/components/base/menu/AgdbMenu.vue index ef5d7d9a..755da634 100644 --- a/agdb_studio/src/components/base/menu/AgdbMenu.vue +++ b/agdb_studio/src/components/base/menu/AgdbMenu.vue @@ -1,7 +1,7 @@ @@ -52,7 +52,9 @@ provide(INJECT_KEY_COLUMNS, columns); grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 1rem; padding: 0.5rem; - border-bottom: 1px solid var(--color-border); white-space: nowrap; + &.expandable { + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)) 50px; + } } diff --git a/agdb_studio/src/components/base/table/AgdbTableHeader.vue b/agdb_studio/src/components/base/table/AgdbTableHeader.vue index 1cb0ddb0..36797d9e 100644 --- a/agdb_studio/src/components/base/table/AgdbTableHeader.vue +++ b/agdb_studio/src/components/base/table/AgdbTableHeader.vue @@ -1,23 +1,29 @@ diff --git a/agdb_studio/src/components/base/table/AgdbTableRow.spec.ts b/agdb_studio/src/components/base/table/AgdbTableRow.spec.ts index 6a8b7fe9..c8aa0d67 100644 --- a/agdb_studio/src/components/base/table/AgdbTableRow.spec.ts +++ b/agdb_studio/src/components/base/table/AgdbTableRow.spec.ts @@ -1,10 +1,20 @@ import { mount } from "@vue/test-utils"; import AgdbTableRow from "./AgdbTableRow.vue"; -import { columnsMap } from "@/tests/tableMocks"; +import { columnsMap, TABLE_NAME, tableConfig } from "@/tests/tableMocks"; import { describe, it, expect } from "vitest"; -import { INJECT_KEY_COLUMNS } from "@/composables/table/constants"; +import { + INJECT_KEY_COLUMNS, + INJECT_KEY_TABLE_NAME, +} from "@/composables/table/constants"; +import { addTable } from "@/composables/table/tableConfig"; describe("TableRow", () => { + addTable({ + name: TABLE_NAME, + columns: tableConfig, + rowDetailsComponent: "component", + }); + it("should render", () => { const wrapper = mount(AgdbTableRow, { props: { @@ -28,4 +38,35 @@ describe("TableRow", () => { expect(wrapper.text()).toContain("admin"); expect(wrapper.text()).toContain("app3"); }); + + it("should expand row", async () => { + const wrapper = mount(AgdbTableRow, { + props: { + columns: columnsMap, + row: { + role: "admin", + owner: "admin", + db: "app3", + db_type: "file", + size: 50, + backup: 0, + }, + }, + global: { + provide: { + [INJECT_KEY_COLUMNS]: { value: columnsMap }, + [INJECT_KEY_TABLE_NAME]: { value: TABLE_NAME }, + }, + stubs: { + transitions: false, + }, + }, + }); + + expect(wrapper.find(".expanded-row").exists()).toBe(false); + await wrapper.find(".expand-row").trigger("click"); + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); + expect(wrapper.find(".expanded-row").exists()).toBe(true); + }); }); diff --git a/agdb_studio/src/components/base/table/AgdbTableRow.vue b/agdb_studio/src/components/base/table/AgdbTableRow.vue index f8dc35d5..01dce201 100644 --- a/agdb_studio/src/components/base/table/AgdbTableRow.vue +++ b/agdb_studio/src/components/base/table/AgdbTableRow.vue @@ -1,8 +1,14 @@ - + diff --git a/agdb_studio/src/components/db/DbTable.vue b/agdb_studio/src/components/db/DbTable.vue index 8201b3f3..a15ffc9d 100644 --- a/agdb_studio/src/components/db/DbTable.vue +++ b/agdb_studio/src/components/db/DbTable.vue @@ -8,11 +8,12 @@ import { dbColumns } from "@/composables/db/dbConfig"; const { databases } = useDbStore(); -const TABLE_KEY = "databases"; +const TABLE_KEY = Symbol("databases"); addTable({ name: TABLE_KEY, columns: dbColumns, + rowDetailsComponent: "DbTableRowDetails", }); watchEffect(() => { @@ -35,7 +36,7 @@ watchEffect(() => { overflow: auto; } .db-table { - width: 1300px; + width: 1400px; margin: 0 auto; } diff --git a/agdb_studio/src/components/transitions/SlideUpTransition.vue b/agdb_studio/src/components/transitions/SlideUpTransition.vue new file mode 100644 index 00000000..120043a1 --- /dev/null +++ b/agdb_studio/src/components/transitions/SlideUpTransition.vue @@ -0,0 +1,22 @@ + + + diff --git a/agdb_studio/src/composables/table/tableConfig.ts b/agdb_studio/src/composables/table/tableConfig.ts index ad3b0ba3..076ceace 100644 --- a/agdb_studio/src/composables/table/tableConfig.ts +++ b/agdb_studio/src/composables/table/tableConfig.ts @@ -1,14 +1,21 @@ import { ref } from "vue"; import type { Column, Table, TRow } from "./types"; -const tables = ref>>(new Map>()); +const tables = ref>>( + new Map>(), +); -export type AddTableProps = { - name: string; +type AddTableProps = { + name: Symbol | string; columns: Column[]; + rowDetailsComponent?: string; }; -const addTable = ({ name, columns }: AddTableProps): void => { +const addTable = ({ + name, + columns, + rowDetailsComponent, +}: AddTableProps): void => { const columnMap = new Map>(); columns.forEach((column) => { columnMap.set(column.key, column); @@ -17,30 +24,35 @@ const addTable = ({ name, columns }: AddTableProps): void => { name, columns: columnMap, data: new Map(), + rowDetailsComponent, }); }; -const removeTable = (name: string): void => { +const removeTable = (name: Symbol | string): void => { tables.value.delete(name); }; -const getTable = (name: string): Table | undefined => { +const getTable = ( + name: Symbol | string, +): Table | undefined => { return tables.value.get(name) as Table | undefined; }; const getTableColumns = ( - name: string, + name: Symbol | string, ): Map> => { const table = getTable(name); return table?.columns ?? new Map>(); }; -const getTableColumnsArray = (name: string): Column[] => { +const getTableColumnsArray = ( + name: Symbol | string, +): Column[] => { const table = getTable(name); return Array.from(table?.columns.values() ?? []); }; -const tableExists = (name: string): boolean => { +const tableExists = (name: Symbol | string): boolean => { return tables.value.has(name); }; diff --git a/agdb_studio/src/composables/table/tableData.ts b/agdb_studio/src/composables/table/tableData.ts index c44330ae..6be56dc8 100644 --- a/agdb_studio/src/composables/table/tableData.ts +++ b/agdb_studio/src/composables/table/tableData.ts @@ -2,7 +2,10 @@ import type { TRow } from "./types"; import { getTable } from "./tableConfig"; import { getTableFilter } from "./tableFilter"; -const setTableData = (tableName: string, data: T[]): void => { +const setTableData = ( + tableName: Symbol | string, + data: T[], +): void => { const table = getTable(tableName); if (!table) { return; @@ -19,7 +22,7 @@ const setTableData = (tableName: string, data: T[]): void => { } }; -const addRow = (tableName: string, row: T): void => { +const addRow = (tableName: Symbol | string, row: T): void => { const table = getTable(tableName); const rowKey = table?.data?.size.toString(); if (!rowKey) { @@ -29,22 +32,25 @@ const addRow = (tableName: string, row: T): void => { table?.data?.set(rowKey, row); }; -const removeRow = (tableName: string, rowKey: string): void => { +const removeRow = ( + tableName: Symbol | string, + rowKey: string, +): void => { const table = getTable(tableName); table?.data?.delete(rowKey); }; -const clearTableData = (tableName: string): void => { +const clearTableData = (tableName: Symbol | string): void => { const table = getTable(tableName); table?.data?.clear(); }; -const getRows = (name: string): [string, T][] => { - const table = getTable(name); +const getRows = (tableName: Symbol | string): [string, T][] => { + const table = getTable(tableName); if (!table?.data) { return []; } - const filter = getTableFilter(name); + const filter = getTableFilter(tableName); const filteredRows = Array.from(table.data).filter(([, row]) => { if (filter.filters.size === 0) { return true; diff --git a/agdb_studio/src/composables/table/tableFilter.ts b/agdb_studio/src/composables/table/tableFilter.ts index e7f85b90..6529ba4f 100644 --- a/agdb_studio/src/composables/table/tableFilter.ts +++ b/agdb_studio/src/composables/table/tableFilter.ts @@ -3,9 +3,9 @@ type TableFilter = { sort: Map; }; -const tableFilters = new Map(); +const tableFilters = new Map(); -const getTableFilter = (tableName: string): TableFilter => { +const getTableFilter = (tableName: Symbol | string): TableFilter => { let tableFilter = tableFilters.get(tableName); if (!tableFilter) { tableFilter = { filters: new Map(), sort: new Map() }; @@ -15,7 +15,7 @@ const getTableFilter = (tableName: string): TableFilter => { }; const addFilter = ( - tableName: string, + tableName: Symbol | string, columnKey: string, value: string, ): void => { @@ -23,13 +23,13 @@ const addFilter = ( tableFilter.filters.set(columnKey, value); }; -const removeFilter = (tableName: string, filterKey: string): void => { +const removeFilter = (tableName: Symbol | string, filterKey: string): void => { const tableFilter = getTableFilter(tableName); tableFilter.filters.delete(filterKey); }; const setSort = ( - tableName: string, + tableName: Symbol | string, columnKey: string, direction: "asc" | "desc", ): void => { diff --git a/agdb_studio/src/composables/table/types.ts b/agdb_studio/src/composables/table/types.ts index 8a5f0dd0..bb3963b2 100644 --- a/agdb_studio/src/composables/table/types.ts +++ b/agdb_studio/src/composables/table/types.ts @@ -14,7 +14,8 @@ export type Column = { }; export type Table = { - name: string; + name: Symbol | string; columns: Map>; data?: Map; + rowDetailsComponent?: string; };