Skip to content

Commit

Permalink
feat(#62): GraphQL visualiser for hierarchies
Browse files Browse the repository at this point in the history
  • Loading branch information
lukashornych committed Nov 1, 2023
1 parent db68876 commit 8c1e06a
Show file tree
Hide file tree
Showing 11 changed files with 540 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ function initializeSchemaEditor(): void {
<VWindowItem v-if="supportsVisualisation" value="visualiser">
<LabEditorGraphQLConsoleVisualiser
:console-props="props"
:result="JSON.parse(resultCode)"
:result="resultCode == undefined || !resultCode ? undefined : JSON.parse(resultCode)"
/>
</VWindowItem>
</VWindow>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@ import VMarkdown from '@/components/base/VMarkdown.vue'
import { UnexpectedError } from '@/model/lab'
import { Toaster, useToaster } from '@/services/editor/toaster'
import LabEditorGraphQLConsoleVisualiserFacetStatistics
from '@/components/lab/editor/graphql-console/visualiser/LabEditorGraphQLConsoleVisualiserFacetStatistics.vue'
from '@/components/lab/editor/graphql-console/visualiser/facet-summary/LabEditorGraphQLConsoleVisualiserFacetStatistics.vue'
const toaster: Toaster = useToaster()
const props = defineProps<{
queryResult: any,
group: any | undefined,
groupResult: any | undefined,
groupRepresentativeAttributes: string[],
facetRepresentativeAttributes: string[]
}>()
const primaryKey = computed<number | undefined>(() => {
return props.group['groupEntity']?.['primaryKey']
return props.groupResult['groupEntity']?.['primaryKey']
})
const title = computed<string | undefined>(() => {
const groupEntity = props.group['groupEntity']
const groupEntity = props.groupResult['groupEntity']
if (!groupEntity) {
return undefined
}
Expand All @@ -46,16 +46,16 @@ const title = computed<string | undefined>(() => {
const count = computed<number | undefined>(() => {
return props.group['count']
return props.groupResult['count']
})
const facetsInitialized = ref<boolean>(false)
const facets = computed<any[]>(() => {
const facetResults = computed<any[]>(() => {
if (!facetsInitialized.value) {
return []
}
return props.group['facetStatistics'] || []
return props.groupResult['facetStatistics'] || []
})
Expand Down Expand Up @@ -100,10 +100,11 @@ function copyPrimaryKey(): void {
<VListItemTitle class="group-title">
<span
v-if="primaryKey != undefined"
class="text-disabled"
class="text-disabled d-flex align-center"
@click.stop="copyPrimaryKey"
>
{{ primaryKey }}:
<VIcon size="20" class="mr-1">mdi-key</VIcon>
{{ primaryKey }}{{ title ? ':' : '' }}
</span>
<span>
{{ title ?? 'Unknown' }}
Expand All @@ -130,10 +131,10 @@ function copyPrimaryKey(): void {

<template v-if="facetsInitialized">
<LabEditorGraphQLConsoleVisualiserFacetStatistics
v-for="(facet, index) in facets"
v-for="(facetResult, index) in facetResults"
:key="index"
:query-result="queryResult"
:facet="facet"
:facet-result="facetResult"
:facet-representative-attributes="facetRepresentativeAttributes"
/>
</template>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@ const toaster: Toaster = useToaster()
const props = defineProps<{
queryResult: any
facet: any,
facetResult: any,
facetRepresentativeAttributes: string[]
}>()
const requested = computed<boolean | undefined>(() => {
return props.facet['requested']
return props.facetResult['requested']
})
const primaryKey = computed<number | undefined>(() => {
return props.facet['facetEntity']?.['primaryKey']
return props.facetResult['facetEntity']?.['primaryKey']
})
const title = computed<string | undefined>(() => {
const facetEntity = props.facet['facetEntity']
const facetEntity = props.facetResult['facetEntity']
if (!facetEntity) {
return undefined
}
Expand All @@ -51,18 +51,18 @@ const numberOfEntities = computed<number | undefined>(() => {
return props.queryResult['recordPage']?.['totalRecordCount'] ?? props.queryResult['recordStrip']?.['totalRecordCount']
})
const impactDifference = computed<string | undefined>(() => {
const difference: number | undefined = props.facet['impact']?.['difference']
const difference: number | undefined = props.facetResult['impact']?.['difference']
if (difference == undefined) {
return undefined
}
return `${difference > 0 ? '+' : ''}${difference}`
})
const impactMatchCount = computed<number | undefined>(() => {
return props.facet['impact']?.['matchCount']
return props.facetResult['impact']?.['matchCount']
})
const count = computed<number | undefined>(() => {
return props.facet['count']
return props.facetResult['count']
})
Expand Down Expand Up @@ -115,11 +115,12 @@ function copyPrimaryKey(): void {
<VListItemTitle class="facet-title">
<span
v-if="primaryKey != undefined"
class="text-disabled"
class="text-disabled d-flex align-center"
style="cursor: pointer;"
@click.stop="copyPrimaryKey"
>
{{ primaryKey }}:
<VIcon size="20" class="mr-1">mdi-key</VIcon>
{{ primaryKey }}{{ title ? ':' : '' }}
</span>
<span :class="{ 'text-disabled': impactMatchCount === 0 }">
{{ title || 'Unknown' }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Toaster, useToaster } from '@/services/editor/toaster'
import LabEditorGraphQLConsoleVisualiserMissingDataIndicator
from '@/components/lab/editor/graphql-console/visualiser/LabEditorGraphQLConsoleVisualiserMissingDataIndicator.vue'
import LabEditorGraphQLConsoleVisualiserReferenceFacetGroupStatistics
from '@/components/lab/editor/graphql-console/visualiser/LabEditorGraphQLConsoleVisualiserReferenceFacetGroupStatistics.vue'
from '@/components/lab/editor/graphql-console/visualiser/facet-summary/LabEditorGraphQLConsoleVisualiserReferenceFacetGroupStatistics.vue'
import { UnexpectedError } from '@/model/lab'
const labService: LabService = useLabService()
Expand All @@ -25,32 +25,32 @@ const props = defineProps<{
entitySchema: EntitySchema,
}>()
const groups = computed<[ReferenceSchema, any][]>(() => {
const referenceGroups: [ReferenceSchema, any][] = []
const referencesWithGroups = computed<[ReferenceSchema, any][]>(() => {
const referencesWithGroups: [ReferenceSchema, any][] = []
for (const referenceName of Object.keys(props.facetSummaryResult)) {
const referenceSchema: ReferenceSchema | undefined = Object.values(props.entitySchema.references)
.find(reference => reference.nameVariants.camelCase === referenceName)
if (referenceSchema == undefined) {
throw new UnexpectedError(props.consoleProps.params.instancePointer.connection, `Reference '${referenceName}' not found in entity '${props.entitySchema.name}' in catalog '${props.consoleProps.params.instancePointer.catalogName}'.`)
}
referenceGroups.push([referenceSchema, props.facetSummaryResult[referenceName]])
referencesWithGroups.push([referenceSchema, props.facetSummaryResult[referenceName]])
}
return referenceGroups
return referencesWithGroups
})
</script>

<template>
<VExpansionPanels v-if="groups && groups.length > 0" variant="accordion">
<VExpansionPanel v-for="group in groups" :key="group[0].name">
<VExpansionPanels v-if="referencesWithGroups && referencesWithGroups.length > 0" variant="accordion">
<VExpansionPanel v-for="referenceWithGroup in referencesWithGroups" :key="referenceWithGroup[0].name">
<VExpansionPanelTitle>
{{ group[0].name }} ({{ group[1].length }})
{{ referenceWithGroup[0].name }} ({{ referenceWithGroup[1].length }})
</VExpansionPanelTitle>
<VExpansionPanelText>
<LabEditorGraphQLConsoleVisualiserReferenceFacetGroupStatistics
:console-props="consoleProps"
:query-result="queryResult"
:reference-schema="group[0]"
:groups="group[1]"
:reference-schema="referenceWithGroup[0]"
:group-results="referenceWithGroup[1]"
/>
</VExpansionPanelText>
</VExpansionPanel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ import { Toaster, useToaster } from '@/services/editor/toaster'
import { TabComponentProps } from '@/model/editor/editor'
import { GraphQLConsoleData, GraphQLConsoleParams } from '@/model/editor/graphql-console'
import LabEditorGraphQLConsoleVisualiserFacetGroupStatistics
from '@/components/lab/editor/graphql-console/visualiser/LabEditorGraphQLConsoleVisualiserFacetGroupStatistics.vue'
from '@/components/lab/editor/graphql-console/visualiser/facet-summary/LabEditorGraphQLConsoleVisualiserFacetGroupStatistics.vue'
import LabEditorGraphQLConsoleVisualiserFacetStatistics
from '@/components/lab/editor/graphql-console/visualiser/LabEditorGraphQLConsoleVisualiserFacetStatistics.vue'
from '@/components/lab/editor/graphql-console/visualiser/facet-summary/LabEditorGraphQLConsoleVisualiserFacetStatistics.vue'
const labService: LabService = useLabService()
const toaster: Toaster = useToaster()
const props = defineProps<{
consoleProps: TabComponentProps<GraphQLConsoleParams, GraphQLConsoleData>,
queryResult: any,
groups: any,
groupResults: any,
referenceSchema: ReferenceSchema
}>()
Expand All @@ -35,10 +35,10 @@ const facets = computed<any[] | undefined>(() => {
if (isGroupedFacets.value) {
return undefined
}
if (props.groups.length === 0) {
if (props.groupResults.length === 0) {
return []
}
return props.groups[0]['facetStatistics']
return props.groupResults[0]['facetStatistics']
})
function initialize() {
Expand Down Expand Up @@ -84,11 +84,11 @@ initialize()
<VList v-if="initialized" density="compact">
<template v-if="isGroupedFacets">
<LabEditorGraphQLConsoleVisualiserFacetGroupStatistics
v-for="(group, index) in groups"
v-for="(groupResult, index) in groupResults"
:key="index"
:console-props="consoleProps"
:query-result="queryResult"
:group="group"
:group-result="groupResult"
:group-representative-attributes="groupRepresentativeAttributes"
:facet-representative-attributes="facetRepresentativeAttributes"
/>
Expand All @@ -98,7 +98,7 @@ initialize()
v-for="(facet, index) in facets"
:key="index"
:query-result="queryResult"
:facet="facet"
:facet-result="facet"
:facet-representative-attributes="facetRepresentativeAttributes"
/>
</template>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<script setup lang="ts">
/**
* Visualises raw JSON hierarchies.
*/
import { EntitySchema, ReferenceSchema } from '@/model/evitadb'
import { TabComponentProps } from '@/model/editor/editor'
import { GraphQLConsoleData, GraphQLConsoleParams } from '@/model/editor/graphql-console'
import { computed } from 'vue'
import { LabService, useLabService } from '@/services/lab.service'
import { Toaster, useToaster } from '@/services/editor/toaster'
import { UnexpectedError } from '@/model/lab'
import LabEditorGraphQLConsoleVisualiserMissingDataIndicator
from '@/components/lab/editor/graphql-console/visualiser/LabEditorGraphQLConsoleVisualiserMissingDataIndicator.vue'
import LabEditorGraphQLConsoleVisualiserReferenceHierarchies
from '@/components/lab/editor/graphql-console/visualiser/hierarchy/LabEditorGraphQLConsoleVisualiserReferenceHierarchies.vue'
const labService: LabService = useLabService()
const toaster: Toaster = useToaster()
const props = defineProps<{
consoleProps: TabComponentProps<GraphQLConsoleParams, GraphQLConsoleData>,
queryResult: any,
hierarchyResult: any,
entitySchema: EntitySchema,
}>()
const referencesWithHierarchies = computed<[ReferenceSchema | undefined, any][]>(() => {
const referencesWithHierarchies: [ReferenceSchema | undefined, any][] = []
for (const referenceName of Object.keys(props.hierarchyResult)) {
const hierarchiesResult = props.hierarchyResult[referenceName]
if (referenceName === 'self') {
referencesWithHierarchies.push([undefined, hierarchiesResult])
} else {
const referenceSchema: ReferenceSchema | undefined = Object.values(props.entitySchema.references)
.find(reference => reference.nameVariants.camelCase === referenceName)
if (referenceSchema == undefined) {
throw new UnexpectedError(props.consoleProps.params.instancePointer.connection, `Reference '${referenceName}' not found in entity '${props.entitySchema.name}' in catalog '${props.consoleProps.params.instancePointer.catalogName}'.`)
}
referencesWithHierarchies.push([referenceSchema, hierarchiesResult])
}
}
return referencesWithHierarchies
})
function getPanelKey(referenceSchema: ReferenceSchema | undefined): string {
if (referenceSchema == undefined) {
return 'self'
}
return referenceSchema.name
}
</script>

<template>
<VExpansionPanels v-if="referencesWithHierarchies && referencesWithHierarchies.length > 0" variant="accordion">
<VExpansionPanel v-for="referenceWithHierarchies in referencesWithHierarchies" :key="getPanelKey(referenceWithHierarchies[0])">
<VExpansionPanelTitle>
{{ referenceWithHierarchies[0]?.name ?? `${entitySchema.name} (self)` }} ({{ Object.values(referenceWithHierarchies[1]).length }})
</VExpansionPanelTitle>
<VExpansionPanelText>
<LabEditorGraphQLConsoleVisualiserReferenceHierarchies
:console-props="consoleProps"
:query-result="queryResult"
:parent-entity-schema="entitySchema"
:reference-schema="referenceWithHierarchies[0]"
:hierarchy-results="referenceWithHierarchies[1]"
/>
</VExpansionPanelText>
</VExpansionPanel>
</VExpansionPanels>

<LabEditorGraphQLConsoleVisualiserMissingDataIndicator
v-else
icon="mdi-text-search"
title="No hierarchies found."
/>
</template>

<style lang="scss" scoped>
</style>
Loading

0 comments on commit 8c1e06a

Please sign in to comment.