From 0ec3c42b6ea1c9d56779185422f7fcef0a1b5f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hendrik=20L=C3=B6sch?= Date: Tue, 10 Mar 2026 15:50:05 +0100 Subject: [PATCH 1/3] fix: update v-text-field bindings to use :model-value and blur events in questionaires for better data handling otherwise inputs became far to laggy. --- src/components/questionaire/Questionnaire.vue | 25 +++++++++++++------ src/stores/workspaceStore.js | 2 +- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/components/questionaire/Questionnaire.vue b/src/components/questionaire/Questionnaire.vue index ca5edf4..2b9e3d2 100644 --- a/src/components/questionaire/Questionnaire.vue +++ b/src/components/questionaire/Questionnaire.vue @@ -90,28 +90,36 @@ @@ -150,7 +158,8 @@ diff --git a/src/stores/workspaceStore.js b/src/stores/workspaceStore.js index 0d6a355..97ffa3c 100644 --- a/src/stores/workspaceStore.js +++ b/src/stores/workspaceStore.js @@ -176,7 +176,7 @@ export const useWorkspaceStore = defineStore('workspace', () => { () => [workspace.value, activeQuestionnaireId.value, openQuestionnaireIds.value, activeWorkspaceTabId.value, openProjectSummaryIds.value, questionnaireHiddenEntries.value], () => { clearTimeout(persistDebounceTimer) - persistDebounceTimer = setTimeout(() => persist(), 500) + persistDebounceTimer = setTimeout(() => persist(), 1500) }, { deep: true } ) From 2ad30a333f164632df5776c67d16b0caa97eff5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hendrik=20L=C3=B6sch?= Date: Tue, 10 Mar 2026 15:59:33 +0100 Subject: [PATCH 2/3] fix: refactor example display logic into a new EntryExamples component for improved readability and maintainability --- src/components/questionaire/EntryExamples.vue | 82 +++++++++++++++++ src/components/questionaire/Questionnaire.vue | 91 +++++++++---------- 2 files changed, 124 insertions(+), 49 deletions(-) create mode 100644 src/components/questionaire/EntryExamples.vue diff --git a/src/components/questionaire/EntryExamples.vue b/src/components/questionaire/EntryExamples.vue new file mode 100644 index 0000000..473a1ef --- /dev/null +++ b/src/components/questionaire/EntryExamples.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/src/components/questionaire/Questionnaire.vue b/src/components/questionaire/Questionnaire.vue index 2b9e3d2..4aaa50c 100644 --- a/src/components/questionaire/Questionnaire.vue +++ b/src/components/questionaire/Questionnaire.vue @@ -229,18 +229,7 @@
-
- Examples: - - - - - {{ example.label }} - , - -
+
import { computed, ref, watch, nextTick, onMounted } from 'vue' import { useWorkspaceStore } from '../../stores/workspaceStore' +import EntryExamples from './EntryExamples.vue' export default { + components: { EntryExamples }, props: { categories: { type: Array, @@ -419,6 +410,21 @@ export default { 'not applicable': 'Entry does not apply to this solution.', unknown: 'Applicability is not known yet.' } + + // Static options - don't need to be recomputed + const applicabilityFilterOptions = [ + { title: 'All', value: 'all' }, + ...store.applicabilityOptions.map((label) => ({ + title: label.charAt(0).toUpperCase() + label.slice(1), + value: label + })) + ] + + const applicabilityItems = store.applicabilityOptions.map((label) => ({ + label, + description: applicabilityDescriptions[label] || '' + })) + const metadataCategory = computed(() => props.categories.find((category) => category.isMetadata) || null) const metadataValue = computed(() => metadataCategory.value?.metadata || null) const architecturalRoleValue = computed(() => metadataValue.value?.architecturalRole || '') @@ -534,22 +540,32 @@ export default { return result.filter((entry) => hiddenEntries.value.has(entry.id)).length }) - const applicabilityFilterOptions = computed(() => { - return [ - { title: 'All', value: 'all' }, - ...store.applicabilityOptions.map((label) => ({ - title: label.charAt(0).toUpperCase() + label.slice(1), - value: label - })) - ] + // Cache for category visibility to avoid recalculating on every render + const categoryVisibilityCache = computed(() => { + const cache = new Map() + visibleCategories.value.forEach(cat => { + if (cat.isMetadata) { + cache.set(cat.id, true) + } else { + const entries = Array.isArray(cat.entries) ? cat.entries : [] + const filtered = entries.filter((entry) => appliesToMatches(entry.appliesTo, metadataValue.value)) + + if (applicabilityFilter.value === 'all') { + cache.set(cat.id, filtered.length > 0) + } else { + const withApplicability = filtered.filter((entry) => + (entry.applicability || 'applicable') === applicabilityFilter.value + ) + cache.set(cat.id, withApplicability.length > 0) + } + } + }) + return cache }) - const applicabilityItems = computed(() => { - return store.applicabilityOptions.map((label) => ({ - label, - description: applicabilityDescriptions[label] || '' - })) - }) + function categoryHasVisibleEntries(category) { + return categoryVisibilityCache.value.get(category.id) ?? false + } const hasNext = computed(() => { return visibleCategories.value.findIndex((category) => category.id === activeCategoryId.value) < visibleCategories.value.length - 1 @@ -618,24 +634,6 @@ export default { } } - function categoryHasVisibleEntries(category) { - if (category.isMetadata) return true - - const entries = Array.isArray(category.entries) ? category.entries : [] - const filteredByMetadata = entries.filter((entry) => appliesToMatches(entry.appliesTo, metadataValue.value)) - - if (applicabilityFilter.value === 'all') { - return filteredByMetadata.length > 0 - } - - const filteredByApplicability = filteredByMetadata.filter((entry) => { - const entryApplicability = entry.applicability || 'applicable' - return entryApplicability === applicabilityFilter.value - }) - - return filteredByApplicability.length > 0 - } - function setAllApplicability(value) { if (!value || currentCategory.value.isMetadata) return @@ -692,7 +690,6 @@ export default { applicabilityFilterOptions, getStatusTooltip: store.getStatusTooltip, renderTextWithLinks: store.renderTextWithLinks, - getExampleItems: store.getExampleItems, isEntryApplicable: store.isEntryApplicable, setApplicability: store.setApplicability, addAnswer: store.addAnswer, @@ -720,10 +717,6 @@ export default {