Skip to content

Commit

Permalink
make settings handling more robust (#560)
Browse files Browse the repository at this point in the history
* make settings handling more robust

* fix tests

* apply formatting changes

---------

Co-authored-by: Logende <[email protected]>
  • Loading branch information
Logende and Logende authored Sep 21, 2024
1 parent 2af7c85 commit 108c9a4
Show file tree
Hide file tree
Showing 21 changed files with 112 additions and 94 deletions.
8 changes: 4 additions & 4 deletions meta_configurator/src/components/CombinedEditorComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Main component of the application.
Combines the code editor and the gui editor.
-->
<script lang="ts" setup>
import {computed, onMounted, ref, watch} from 'vue';
import {computed, onMounted, type Ref, ref, watch} from 'vue';
import 'primeicons/primeicons.css';
import SplitterPanel from 'primevue/splitterpanel';
import Splitter from 'primevue/splitter';
Expand Down Expand Up @@ -31,15 +31,15 @@ const props = defineProps<{
}>();

const settings = useSettings();
let panelsDefinition: SettingsInterfacePanels = settings.panels;
let panelsDefinition: SettingsInterfacePanels = settings.value.panels;

// update panelsDefinition only when underlying data changes. Otherwise, all panels will be rebuilt every time
// any setting is changed, which is not necessary and leads to Ace Editor becoming blank if settings were modified via
// Ace Editor
watchImmediate(
() => settings,
(settings: SettingsInterfaceRoot) => {
let panels = settings.panels;
(settings: Ref<SettingsInterfaceRoot>) => {
let panels = settings.value.panels;
if (JSON.stringify(panels) !== JSON.stringify(panelsDefinition)) {
panelsDefinition = panels;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ onMounted(() => {
*/
function setupAceMode(editor: Editor) {
watchImmediate(
() => settings.dataFormat,
() => settings.value.dataFormat,
format => {
if (format == 'json') {
editor.getSession().setMode('ace/mode/json');
Expand All @@ -64,13 +64,13 @@ function setupAceProperties(editor: Editor) {
});
editor.setTheme('ace/theme/clouds');
editor.setShowPrintMargin(false);
editor.getSession().setTabSize(settings.codeEditor.tabSize);
editor.getSession().setTabSize(settings.value.codeEditor.tabSize);

// it's not clear why timeout is needed here, but without it the
// ace editor starts flashing and becomes unusable
window.setTimeout(() => {
watchImmediate(
() => settings.codeEditor.fontSize,
() => settings.value.codeEditor.fontSize,
fontSize => {
if (editor && fontSize && fontSize > 6 && fontSize < 65) {
editor.setFontSize(fontSize.toString() + 'px');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ function canZoomIn(): boolean {
* depending on if the maximum depth has been reached or not.
*/
function onPressEnter() {
if (props.node.data.depth === settings.guiEditor.maximumDepth) {
if (props.node.data.depth === settings.value.guiEditor.maximumDepth) {
zoomIntoPath();
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ interface TreeNodeResolvingParameters {
depth: number;
}

const settings = useSettings();

/**
* Creates a {@link GuiEditorTreeNode} from a {@link JsonSchemaWrapper}.
*
Expand Down Expand Up @@ -98,7 +100,7 @@ export class ConfigTreeNodeResolver {
return (
(!dependsOnUserSelection && data && typeof data !== 'object') || // primitive type in data
(!schema.hasType('object') && !schema.hasType('array')) || // primitive type in schema
depth >= useSettings().guiEditor.maximumDepth // maximum depth reached
depth >= settings.value.guiEditor.maximumDepth // maximum depth reached
);
}

Expand All @@ -111,6 +113,7 @@ export class ConfigTreeNodeResolver {

/**
* Creates the children of a {@link GuiEditorTreeNode}.
* @param mode
* @param guiEditorTreeNode The node for which the children should be created.
*/
public createChildNodesOfNode(
Expand Down Expand Up @@ -150,7 +153,7 @@ export class ConfigTreeNodeResolver {
effectiveSchema: EffectiveSchema,
depth = 0
): GuiEditorTreeNode[] {
const depthLimit = useSettings().guiEditor.maximumDepth;
const depthLimit = settings.value.guiEditor.maximumDepth;
const schema = effectiveSchema.schema;

let children: GuiEditorTreeNode[] = [];
Expand Down Expand Up @@ -203,7 +206,7 @@ export class ConfigTreeNodeResolver {
mode: SessionMode,
parameters: TreeNodeResolvingParameters
) {
const propertySorting = useSettings().guiEditor.propertySorting;
const propertySorting = settings.value.guiEditor.propertySorting;
let result: GuiEditorTreeNode[] = [];

if (propertySorting === PropertySorting.SCHEMA_ORDER) {
Expand Down Expand Up @@ -621,7 +624,7 @@ export class ConfigTreeNodeResolver {

// if the user has not specified a custom schema for additional properties, we can hide the button
if (
useSettings().guiEditor.hideAddPropertyButton &&
settings.value.guiEditor.hideAddPropertyButton &&
schema.additionalProperties.isAlwaysTrue &&
_.isEmpty(schema.patternProperties)
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ function rebuildGraph() {
emit('rebuild_graph');
emit('fit_view');
}
const settings = useSettings();
</script>

<template>
Expand All @@ -22,24 +24,20 @@ function rebuildGraph() {
<div>
<label
>Edit Mode
<InputSwitch
v-model="useSettings().schemaDiagram.editMode"
class="options-input-switch" />
<InputSwitch v-model="settings.schemaDiagram.editMode" class="options-input-switch" />
</label>
</div>
<div>
<label
>Graph direction vertical
<InputSwitch
v-model="useSettings().schemaDiagram.vertical"
class="options-input-switch" />
<InputSwitch v-model="settings.schemaDiagram.vertical" class="options-input-switch" />
</label>
</div>
<div>
<label
>Show attributes
<InputSwitch
v-model="useSettings().schemaDiagram.showAttributes"
v-model="settings.schemaDiagram.showAttributes"
label="Automatic zoom"
class="options-input-switch" />
</label>
Expand All @@ -48,15 +46,15 @@ function rebuildGraph() {
<label
>Show enum values
<InputSwitch
v-model="useSettings().schemaDiagram.showEnumValues"
v-model="settings.schemaDiagram.showEnumValues"
class="options-input-switch" />
</label>
</div>
<div>
<label
>Move view on element selection
<InputSwitch
v-model="useSettings().schemaDiagram.moveViewToSelectedElement"
v-model="settings.schemaDiagram.moveViewToSelectedElement"
class="options-input-switch" />
</label>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@
import {
SchemaElementData,
SchemaEnumNodeData,
SchemaObjectNodeData,
} from '@/components/panels/schema-diagram/schemaDiagramTypes';
import type {Path} from '@/utility/path';
import {Handle, Position} from '@vue-flow/core';
import {useSettings} from '@/settings/useSettings';
import {type Ref, ref} from 'vue';
import InputText from 'primevue/inputtext';
import {pathToString} from '@/utility/pathUtils';
import Button from 'primevue/button';
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome';
Expand Down Expand Up @@ -38,7 +36,7 @@ function clickedNode() {
}
function isEnumEditable() {
return isHighlighted() && settings.schemaDiagram.editMode;
return isHighlighted() && settings.value.schemaDiagram.editMode;
}
function isDefinedInDefinitions() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import Button from 'primevue/button';
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome';
import {useSettings} from '@/settings/useSettings';
const settings = useSettings();
const props = defineProps<{
data: SchemaObjectAttributeData;
selectedData?: SchemaElementData;
Expand Down Expand Up @@ -65,7 +67,7 @@ function deleteAttribute() {
}
function isEditable() {
return isHighlighted() && useSettings().schemaDiagram.editMode;
return isHighlighted() && settings.value.schemaDiagram.editMode;
}
function isHighlighted() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@ const emit = defineEmits<{
}>();
const objectName = ref(props.data.name);
const settings = useSettings();
function isObjectEditable() {
return (isHighlighted() || isAttributeHighlighted()) && useSettings().schemaDiagram.editMode;
return (isHighlighted() || isAttributeHighlighted()) && settings.value.schemaDiagram.editMode;
}
function isNameEditable() {
Expand Down Expand Up @@ -183,7 +184,7 @@ function isAttributeHighlighted() {

<hr />
<SchemaObjectAttribute
v-if="useSettings().schemaDiagram.showAttributes"
v-if="settings.schemaDiagram.showAttributes"
v-for="attribute in props.data!.attributes"
:data="attribute!"
:key="attribute!.name + attribute.index + attribute.typeDescription"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const activeEdges: Ref<Edge[]> = ref<Edge[]>([]);
const graphDirection = computed(() => {
// note that having edges from left ro right will usually lead to a more vertical graph, because usually it is
// not very deeply nested, but there exist many nodes on the same levels
return settings.schemaDiagram.vertical ? 'LR' : 'TB';
return settings.value.schemaDiagram.vertical ? 'LR' : 'TB';
});
const selectedNode: Ref<Node | undefined> = ref(undefined);
Expand Down Expand Up @@ -116,7 +116,7 @@ function fitViewForElementByPath(path: Path) {
if (bestMatchingNode) {
if (
(previousBestMatchingNode && previousBestMatchingNode.id === bestMatchingNode.id) ||
!settings.schemaDiagram.moveViewToSelectedElement
!settings.value.schemaDiagram.moveViewToSelectedElement
) {
// if the node is already within the viewport, do not move the view
if (areNodesAlreadyWithinViewport([bestMatchingNode])) {
Expand All @@ -134,8 +134,8 @@ function fitViewForNodes(nodes: Node[]) {
nodes: nodes.map(node => node.id),
duration: 1000,
padding: 1,
maxZoom: settings.schemaDiagram.automaticZoomMaxValue,
minZoom: settings.schemaDiagram.automaticZoomMinValue,
maxZoom: settings.value.schemaDiagram.automaticZoomMaxValue,
minZoom: settings.value.schemaDiagram.automaticZoomMinValue,
});
});
}
Expand Down Expand Up @@ -163,7 +163,7 @@ function updateGraph(forceRebuild: boolean = false) {
const graph = constructSchemaGraph(schema);
let graphNeedsLayouting = forceRebuild;
const vueFlowGraph = graph.toVueFlowGraph(settings.schemaDiagram.vertical);
const vueFlowGraph = graph.toVueFlowGraph(settings.value.schemaDiagram.vertical);
if (wasNodeAdded(activeNodes.value, vueFlowGraph.nodes)) {
// node was added -> it is needed to update whole graph
activeNodes.value = vueFlowGraph.nodes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,24 @@
import {beforeEach, describe, expect, it, vi} from 'vitest';
import type {Path} from '@/utility/path';
import type {TopLevelSchema} from '@/schema/jsonSchemaType';
import {
EdgeType,
SchemaEnumNodeData,
SchemaGraph,
SchemaObjectNodeData,
} from '../schemaDiagramTypes';
import {
constructSchemaGraph,
generateAttributeEdges,
generateObjectAttributes,
identifyObjects,
populateGraph,
trimGraph,
trimNodeChildren,
} from '../schemaGraphConstructor';
import {useSettings} from '@/settings/useSettings';
import {SchemaGraph} from '../schemaDiagramTypes';
import {constructSchemaGraph} from '../schemaGraphConstructor';
import {findBestMatchingNode} from '../schemaDiagramHelper';
import {ref} from 'vue';

vi.mock('@/dataformats/formatRegistry', () => ({
useDataConverter: () => ({
stringify: (data: any) => JSON.stringify(data),
parse: (data: string) => JSON.parse(data),
}),
useSettings() {
return {
return ref({
schemaDiagram: {
showEnumValues: true,
maxEnumValuesToShow: 5,
showAttributes: true,
maxAttributesToShow: 5,
},
};
});
},
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,22 @@ import {
trimNodeChildren,
} from '../schemaGraphConstructor';
import {useSettings} from '@/settings/useSettings';
import {ref} from 'vue';

vi.mock('@/dataformats/formatRegistry', () => ({
useDataConverter: () => ({
stringify: (data: any) => JSON.stringify(data),
parse: (data: string) => JSON.parse(data),
}),
useSettings() {
return {
return ref({
schemaDiagram: {
showEnumValues: true,
maxEnumValuesToShow: 5,
showAttributes: true,
maxAttributesToShow: 5,
},
};
});
},
}));

Expand Down Expand Up @@ -140,6 +141,8 @@ describe('test schema graph constructor with objects and attributes with enums',

trimNodeChildren(schemaGraph);

expect(enumIntNode.values.length).toEqual(useSettings().schemaDiagram.maxEnumValuesToShow);
expect(enumIntNode.values.length).toEqual(
useSettings().value.schemaDiagram.maxEnumValuesToShow
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ import {jsonPointerToPath, pathToString} from '@/utility/pathUtils';
import {useSettings} from '@/settings/useSettings';
import {mergeAllOfs} from '@/schema/mergeAllOfs';

const settings = useSettings();

export function constructSchemaGraph(rootSchema: TopLevelSchema): SchemaGraph {
if (useSettings().schemaDiagram.mergeAllOfs) {
if (settings.value.schemaDiagram.mergeAllOfs) {
// duplicate root schema to avoid modifying the original schema
rootSchema = JSON.parse(JSON.stringify(rootSchema));

Expand Down Expand Up @@ -609,8 +611,8 @@ export function trimGraph(graph: SchemaGraph) {
}

export function trimNodeChildren(graph: SchemaGraph) {
const maxEnumValuesToShow = useSettings().schemaDiagram.maxEnumValuesToShow;
const maxAttributesToShow = useSettings().schemaDiagram.maxAttributesToShow;
const maxEnumValuesToShow = settings.value.schemaDiagram.maxEnumValuesToShow;
const maxAttributesToShow = settings.value.schemaDiagram.maxAttributesToShow;
for (const nodeData of graph.nodes) {
if (nodeData.getNodeType() == 'schemaobject') {
const nodeDataObject = nodeData as SchemaObjectNodeData;
Expand Down
4 changes: 2 additions & 2 deletions meta_configurator/src/components/toolbar/TopToolbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ function getPageSelectionMenuItems(settings: SettingsInterfaceRoot): MenuItem[]
return items;
}
const items = computed(() => getPageSelectionMenuItems(settings));
const items = computed(() => getPageSelectionMenuItems(settings.value));
function handleUserSelection(option: 'Example' | 'JsonStore' | 'File' | 'URL') {
switch (option) {
Expand Down Expand Up @@ -216,7 +216,7 @@ function getMenuItems(settings: SettingsInterfaceRoot): MenuItem[] {
}
// computed property function to get menu items to allow for updating of the menu items
const menuItems = computed(() => getMenuItems(settings));
const menuItems = computed(() => getMenuItems(settings.value));
const toggle = event => {
menu.value.toggle(event);
Expand Down
2 changes: 1 addition & 1 deletion meta_configurator/src/components/toolbar/downloadFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export function downloadFile(fileNamePrefix: string, isSchema: boolean): void {
});
const formattedDate = formatter.format(now);
const fileEnding =
(isSchema ? 'schema.' : '') + (useSettings().dataFormat === 'yaml' ? 'yml' : 'json');
(isSchema ? 'schema.' : '') + (useSettings().value.dataFormat === 'yaml' ? 'yml' : 'json');
const fileName: string = `${fileNamePrefix}-${formattedDate}.${fileEnding}`;

// Create a temporary link element
Expand Down
Loading

0 comments on commit 108c9a4

Please sign in to comment.