diff --git a/ui/src/components/ColumnNamesPreview.vue b/ui/src/components/ColumnNamesPreview.vue new file mode 100644 index 000000000..394db3133 --- /dev/null +++ b/ui/src/components/ColumnNamesPreview.vue @@ -0,0 +1,42 @@ + + + diff --git a/ui/src/components/SimpleTable.vue b/ui/src/components/DataPreviewTable.vue similarity index 75% rename from ui/src/components/SimpleTable.vue rename to ui/src/components/DataPreviewTable.vue index 5c3d0050a..e820843b2 100644 --- a/ui/src/components/SimpleTable.vue +++ b/ui/src/components/DataPreviewTable.vue @@ -9,26 +9,19 @@ {{ key }} - - ... - - {{ value }} - - - - {{ `+ ${nCols - 10} more` }} - - - - - - {{ `+ ${nRows - 10} more rows` }} + + + {{ value.toString().slice(0, tableHeader[index].length - 2 ) }}.. + + + {{ value }} + @@ -41,7 +34,7 @@ import { defineComponent, PropType } from "vue"; import { isIntArray, transformTable, truncate } from "@/helpers/utils"; export default defineComponent({ - name: "SimpleTable", + name: "DataPreviewTable", props: { data: { type: Array as PropType<{ [key: string]: string }[]>, @@ -55,10 +48,6 @@ export default defineComponent({ type: Number, required: true, }, - nCols: { - type: Number, - required: true, - }, }, computed: { maxNumberCharacters() { diff --git a/ui/src/types/types.d.ts b/ui/src/types/types.d.ts index 9c55eb589..8cbd11beb 100644 --- a/ui/src/types/types.d.ts +++ b/ui/src/types/types.d.ts @@ -57,6 +57,7 @@ export type ProjectsExplorerData = { selectedFolder: string; createLinkFromTarget: boolean; createLinkFromSrc: boolean; + columnNames: Array; }; export type ProjectsData = { diff --git a/ui/src/views/ProjectsExplorer.vue b/ui/src/views/ProjectsExplorer.vue index b6c23e2b2..b2c04193d 100644 --- a/ui/src/views/ProjectsExplorer.vue +++ b/ui/src/views/ProjectsExplorer.vue @@ -182,13 +182,18 @@ :viewTable="selectedFile" :onSave="doCreateLinkFile" > - + > + +
@@ -209,12 +214,14 @@ import FolderInput from "@/components/FolderInput.vue"; import ListGroup from "@/components/ListGroup.vue"; import LoadingSpinner from "@/components/LoadingSpinner.vue"; import FeedbackMessage from "@/components/FeedbackMessage.vue"; +import ColumnNamesPreview from "@/components/ColumnNamesPreview.vue"; import { getProject, deleteObject, previewObject, getFileDetails, createLinkFile, + getTableVariables, } from "@/api/api"; import { isEmptyObject, @@ -228,7 +235,7 @@ import { StringArray, ProjectsExplorerData } from "@/types/types"; import { useRoute, useRouter } from "vue-router"; import FileUpload from "@/components/FileUpload.vue"; import FileExplorer from "@/components/FileExplorer.vue"; -import SimpleTable from "@/components/SimpleTable.vue"; +import DataPreviewTable from "@/components/DataPreviewTable.vue"; import { processErrorMessages } from "@/helpers/errorProcessing"; import ViewEditor from "@/components/ViewEditor.vue"; @@ -244,8 +251,9 @@ export default defineComponent({ FileUpload, FileExplorer, FolderInput, - SimpleTable, + DataPreviewTable, ViewEditor, + ColumnNamesPreview, }, setup() { const project: Ref = ref([]); @@ -301,6 +309,7 @@ export default defineComponent({ }, createLinkFromTarget: false, createLinkFromSrc: false, + columnNames: [], }; }, watch: { @@ -318,21 +327,21 @@ export default defineComponent({ this.loading_preview = true; previewObject( this.projectId, - `${this.selectedFolder}/${this.selectedFile}` + `${this.selectedObject}` ) .then((data) => { this.filePreview = data; this.loading_preview = false; }) .catch((error) => { - this.errorMessage = `Cannot load preview for [${this.selectedFolder}/${this.selectedFile}] of project [${this.projectId}]. Because: ${error}.`; + this.errorMessage = `Cannot load preview for [${this.selectedObject}] of project [${this.projectId}]. Because: ${error}.`; this.clearFilePreview(); this.loading_preview = false; }); - } - getFileDetails( + + getFileDetails( this.projectId, - `${this.selectedFolder}/${this.selectedFile}` + `${this.selectedObject}` ) .then((data) => { this.fileInfo.fileSize = data["size"]; @@ -340,10 +349,16 @@ export default defineComponent({ this.fileInfo.dataSizeColumns = parseInt(data["columns"]); this.fileInfo.sourceLink = data["sourceLink"]; this.fileInfo.variables = data["variables"]; + if (isLinkFileType(this.selectedFile)) { + this.columnNames = this.fileInfo.variables + } else { + this.getTableColumnNames( this.projectId, `${this.selectedObject}`) + } }) .catch((error) => { - this.errorMessage = `Cannot load details for [${this.selectedFolder}/${this.selectedFile}] of project [${this.projectId}]. Because: ${error}.`; - }); + this.errorMessage = `Cannot load details for [${this.selectedObject}] of project [${this.projectId}]. Because: ${error}.`; + }); + } } }, project() { @@ -358,6 +373,9 @@ export default defineComponent({ projectFolders(): StringArray { return Object.keys(this.projectContent) as StringArray; }, + selectedObject(): String { + return `${this.selectedFolder}/${this.selectedFile}` + } }, methods: { isTableType, @@ -400,6 +418,18 @@ export default defineComponent({ this.errorMessage = "Folder name cannot be empty"; } }, + getTableColumnNames (project: string, object: string) { + getTableVariables( + project, + object + ) + .then((data) => { + this.columnNames = data; + }) + .catch((error) => { + this.errorMessage = `Cannot load column names for [${object}] of project [${project}]. Because: ${error}.`; + }); + }, cancelNewFolder() { this.createNewFolder = false; }, @@ -431,7 +461,7 @@ export default defineComponent({ const folder = splittedFileAndFolder[0]; const response = deleteObject( this.projectId, - `${this.selectedFolder}/${this.selectedFile}` + `${this.selectedObject}` ); response .then(() => { @@ -555,7 +585,7 @@ export default defineComponent({ this.editView = false; if (this.projectId !== "" && this.selectedFolder !== "") { this.router.push( - `/projects-explorer/${this.projectId}/${this.selectedFolder}/${this.selectedFile}` + `/projects-explorer/${this.projectId}/${this.selectedObject}` ); } }) diff --git a/ui/tests/unit/components/ColumnNamesPreview.spec.ts b/ui/tests/unit/components/ColumnNamesPreview.spec.ts new file mode 100644 index 000000000..92a524943 --- /dev/null +++ b/ui/tests/unit/components/ColumnNamesPreview.spec.ts @@ -0,0 +1,23 @@ +import { shallowMount, VueWrapper } from "@vue/test-utils"; +import ColumnNamesPreview from "@/components/ColumnNamesPreview.vue"; + +describe("ColumnNamesPreview", () => { + let wrapper: VueWrapper; + beforeEach(function () { + wrapper = shallowMount(ColumnNamesPreview, { + props: { + columnNames: ["col1", "col2"], + buttonName: "+ 2 more columns", + }, + }); + }); + + test("Toggle column names", () => { + expect(wrapper.vm.isCollapsed).toBe(false) + wrapper.vm.toggleColumnNames() + expect(wrapper.vm.isCollapsed).toBe(true) + }); + test("Join column names with comma", () => { + expect(wrapper.vm.columnNamesString).toBe("col1, col2") + }); +}); diff --git a/ui/tests/unit/components/SimpleTable.spec.ts b/ui/tests/unit/components/DataPreviewTable.ts similarity index 96% rename from ui/tests/unit/components/SimpleTable.spec.ts rename to ui/tests/unit/components/DataPreviewTable.ts index 5ca2ff4d8..636a9fec9 100644 --- a/ui/tests/unit/components/SimpleTable.spec.ts +++ b/ui/tests/unit/components/DataPreviewTable.ts @@ -1,5 +1,5 @@ import { shallowMount, VueWrapper } from "@vue/test-utils"; -import SimpleTable from "@/components/SimpleTable.vue"; +import DataPreviewTable from "@/components/DataPreviewTable.vue"; function getListOfColumnValues( data: { @@ -18,7 +18,7 @@ function getListOfColumnValues( }); } -describe("SimpleTable", () => { +describe("DataPreviewTable", () => { const data = [ { firstName: "Bofke", diff --git a/ui/tests/unit/views/ProjectExplorer.spec.ts b/ui/tests/unit/views/ProjectExplorer.spec.ts index 4001da142..92d81c2a4 100644 --- a/ui/tests/unit/views/ProjectExplorer.spec.ts +++ b/ui/tests/unit/views/ProjectExplorer.spec.ts @@ -142,6 +142,9 @@ describe("ProjectsExplorer", () => { api.getFileDetails.mockImplementation(() => { return Promise.resolve({}); }); + api.getTableVariables.mockImplementation(() => { + return Promise.resolve({}); + }); // Important: selectedFolder before selectedFile, since watcher for selectedFolder resets selectedFile to "" expect(wrapper.vm.fileToDelete).toBe(""); expect(wrapper.vm.folderToDeleteFrom).toBe("");