-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
248 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 132 additions & 0 deletions
132
meta_configurator/src/components/panels/list-analysis/ListAnalysisPanel.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
<script setup lang="ts"> | ||
import {SessionMode} from '@/store/sessionMode'; | ||
import {computed, type ComputedRef, onMounted, ref, type Ref} from "vue"; | ||
import {identifyArraysInJson} from "@/utility/arrayPathUtils"; | ||
import type {Path} from "@/utility/path"; | ||
import {getDataForMode} from "@/data/useDataLink"; | ||
import SelectButton from 'primevue/selectbutton'; | ||
import Button from 'primevue/button'; | ||
import Column from 'primevue/column'; | ||
import DataTable from "primevue/datatable"; | ||
import ScrollPanel from "primevue/scrollpanel"; | ||
import {jsonPointerToPathTyped, pathToJsonPointer} from "@/utility/pathUtils"; | ||
import { | ||
createItemsRowsFromJson, | ||
formatJsonPointerAsPropertyName, | ||
formatJsonPointerForUser | ||
} from "@/components/panels/list-analysis/listAnalysisUtils"; | ||
import TreeTable from "primevue/treetable"; | ||
const props = defineProps<{ | ||
sessionMode: SessionMode; | ||
}>(); | ||
const data = getDataForMode(props.sessionMode); | ||
onMounted(() => { | ||
updatePossibleArrays(data.data.value); | ||
}); | ||
const possibleArrays: Ref<string[]> = ref([]); | ||
const selectedArrayPointer: Ref<string | null> = ref(null); | ||
const selectedArrayPath = computed(() => { | ||
if (selectedArrayPointer.value == null) { | ||
return null; | ||
} | ||
return jsonPointerToPathTyped(selectedArrayPointer.value); | ||
}); | ||
const selectedArray: Ref<any | null> = computed(() => { | ||
if (selectedArrayPath.value == null) { | ||
return null; | ||
} | ||
return data.dataAt(selectedArrayPath.value); | ||
}); | ||
const tableData: ComputedRef<null | { rows: any[], columnNames: string[] }> = computed(() => { | ||
if (selectedArrayPath.value == null) { | ||
return null; | ||
} | ||
const currentData = data.dataAt(selectedArrayPath.value); | ||
return createItemsRowsFromJson(currentData); | ||
}); | ||
const itemRows = computed(() => { | ||
console.log("itemRows computed" + tableData.value?.rows); | ||
return tableData.value?.rows; | ||
}); | ||
// function to update the possible arrays based on the data | ||
function updatePossibleArrays(newData: any) { | ||
possibleArrays.value = identifyArraysInJson(newData, [], true, true).map( (path: Path) => { | ||
return pathToJsonPointer(path) | ||
}); | ||
if (possibleArrays.value.length == 0) { | ||
selectedArrayPointer.value = null; | ||
} else if (possibleArrays.value.length == 1) { | ||
selectedArrayPointer.value = possibleArrays.value[0]; | ||
} else { | ||
// if there are multiple arrays, we do not change the selection | ||
} | ||
console.log("tableData " , tableData.value); | ||
} | ||
</script> | ||
|
||
<template> | ||
|
||
<div > | ||
<label class="heading">Array Analysis</label> | ||
<Button label="Update Data" icon="pi pi-refresh" @click="updatePossibleArrays(data.data.value)" /> | ||
<div class="mt-3"> | ||
<div v-if="possibleArrays.length==0"> | ||
<b>No arrays available.</b> | ||
</div> | ||
<div v-else> | ||
<label for="arrayPath">Select an array to analyze:</label> | ||
<SelectButton v-model="selectedArrayPointer" :options="possibleArrays" /> | ||
</div> | ||
</div> | ||
|
||
|
||
<div v-if="tableData" > | ||
|
||
<ScrollPanel style="width: 100%; height: 100%" aria-orientation="horizontal"> | ||
|
||
<DataTable :value="selectedArray" :paginator="true" :rows="20" | ||
tableStyle="min-width: 50rem" | ||
showGridlines | ||
stripedRows | ||
removable-sort | ||
scrollable scrollHeight="flex" | ||
class="flex-grow" | ||
size="small" | ||
> | ||
<Column v-for="columnName in tableData.columnNames" :field="columnName" :header="columnName" :sortable="true"/> | ||
</DataTable> | ||
</ScrollPanel> | ||
</div> | ||
|
||
</div> | ||
|
||
</template> | ||
|
||
<style scoped> | ||
.heading { | ||
font-size: 24px; /* Make the text bigger */ | ||
font-weight: bold; /* Make the text bold */ | ||
text-align: center; /* Center the text horizontally */ | ||
display: block; /* Ensure the label behaves like a block element */ | ||
margin-bottom: 10px; /* Add some space below the label */ | ||
} | ||
</style> |
74 changes: 74 additions & 0 deletions
74
meta_configurator/src/components/panels/list-analysis/listAnalysisUtils.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import _ from 'lodash'; | ||
import {dataAt} from "@/utility/resolveDataAtPath"; | ||
import {jsonPointerToPathTyped} from "@/utility/pathUtils"; | ||
|
||
export function createItemsRowsFromJson(itemsJson: any): { rows: any[], columnNames: string[] } { | ||
const columnNames = collectItemColumnNames(itemsJson); | ||
|
||
const rows = itemsJson.map((itemJson: any) => { | ||
return createItemRow(itemJson, columnNames); | ||
}); | ||
|
||
const columnNamesFormatted: string[] = Array.from(columnNames).map((columnName: string) => { | ||
return formatJsonPointerForUser(columnName); | ||
}); | ||
|
||
return { rows: rows, columnNames: columnNamesFormatted }; | ||
} | ||
|
||
export function createItemRow(itemJson: any, columnNames: Set<string>): any { | ||
const row: any = {}; | ||
|
||
for (const columnName of columnNames) { | ||
|
||
const columnData = dataAt(jsonPointerToPathTyped(columnName), itemJson); | ||
|
||
const formattedColumnName = formatJsonPointerAsPropertyName(columnName); | ||
if (columnData !== undefined) { | ||
row[formattedColumnName] = columnData; | ||
} else { | ||
row[formattedColumnName] = null; | ||
} | ||
} | ||
|
||
return row; | ||
} | ||
|
||
|
||
// collect all properties of the items, including nested properties | ||
function collectItemColumnNames(itemsJson: any): Set<string> { | ||
const columnNames: Set<string> = new Set(); | ||
|
||
for (const itemJson of itemsJson) { | ||
for (const itemProperty in itemJson) { | ||
if (itemJson.hasOwnProperty(itemProperty)) { | ||
|
||
// if it is an object: recursively collect all nested properties | ||
if (_.isObject(itemJson[itemProperty])) { | ||
const nestedColumnNames = collectItemColumnNames([itemJson[itemProperty]]); | ||
nestedColumnNames.forEach((nestedColumnName: string) => { | ||
columnNames.add(`/${itemProperty}${nestedColumnName}`); | ||
}); | ||
} else { | ||
// if it is a simple property: add it to the list | ||
if (itemProperty !== undefined) { | ||
columnNames.add("/" + itemProperty); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
return columnNames; | ||
} | ||
|
||
|
||
export function formatJsonPointerAsPropertyName(pointer: string): string { | ||
// remove first slash and replace others by dot | ||
return pointer.replaceAll("/", ""); | ||
} | ||
|
||
export function formatJsonPointerForUser(pointer: string): string { | ||
// remove first slash and replace others by dot | ||
return pointer.substring(1).replaceAll("/", "."); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
|
||
// note that this function does not look for a table within a table | ||
import type {Path} from "@/utility/path"; | ||
|
||
export function identifyArraysInJson(json: any, path: Path = [], allowNestedArrays: boolean, onlyObjectArray: boolean): Path[] { | ||
const arrayPaths: Path[] = []; | ||
|
||
|
||
if (Array.isArray(json) && (!onlyObjectArray || json.length > 0 && typeof json[0] === 'object')) { | ||
arrayPaths.push(path); | ||
if (allowNestedArrays) { | ||
// for each array element, recursively search for nested arrays | ||
for (let i = 0; i < json.length; i++) { | ||
arrayPaths.push(...identifyArraysInJson(json[i], [...path, i], allowNestedArrays, onlyObjectArray)); | ||
} | ||
} | ||
|
||
} else if (typeof json === 'object' && json !== null) { | ||
// for each key, recursively search for nested arrays | ||
for (const key in json) { | ||
if (json.hasOwnProperty(key)) { | ||
arrayPaths.push(...identifyArraysInJson(json[key], [...path, key], allowNestedArrays, onlyObjectArray)); | ||
} | ||
} | ||
} | ||
|
||
|
||
return arrayPaths; | ||
} |