From 1ecf7382224e9084201c37230c0bd5b13d0110eb Mon Sep 17 00:00:00 2001 From: underscope Date: Fri, 27 Mar 2026 08:21:43 +0100 Subject: [PATCH 01/15] Add outline processor for discovery --- .../Discovery/TopicPicker/useOutlineTree.ts | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts diff --git a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts new file mode 100644 index 000000000..15ebadca0 --- /dev/null +++ b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts @@ -0,0 +1,60 @@ +import { activity as activityUtils } from '@tailor-cms/utils'; +import { schema as schemaConfig } from '@tailor-cms/config'; + +import { useCurrentRepository } from '@/stores/current-repository'; +import type { TopicItem } from './types'; + +const buildTopicMeta = ( + activity: any, + activityCollection: any[], + repositoryName: string, +): TopicItem => { + const name = activity.data?.name || ''; + const isLeaf = schemaConfig.isEditable(activity.type); + const ancestors = activityUtils.getAncestors(activityCollection, activity); + const ancestorNames = ancestors.map((a: any) => a.data?.name).filter(Boolean); + return { + id: activity.id, + name, + parentName: ancestorNames.at(-1), + isLeaf, + isGroup: !isLeaf, + depth: ancestors.length, + context: [name, ...ancestorNames, repositoryName].filter(Boolean), + }; +}; + +function flattenTree(nodes: any[]): TopicItem[] { + const result: TopicItem[] = []; + for (const node of nodes) { + if (node.topicMeta) result.push(node.topicMeta); + if (node.children?.length) { + result.push(...flattenTree(node.children)); + } + } + return result; +} + +/** + * Derives a flat topic list from the repository outline. + * Uses shared toTreeFormat for hierarchy, schemaConfig.isEditable + * for leaf detection, and getAncestors for parent context. + */ +export function useOutlineTree() { + const store = useCurrentRepository(); + const hasOutline = computed(() => store.outlineActivities.length > 0); + + const items = computed(() => { + const activities = store.outlineActivities as any[]; + if (!activities.length) return []; + const repo = store.repository; + const tree = activityUtils.toTreeFormat(activities, { + processNodeFn: (activity: any) => ({ + topicMeta: buildTopicMeta(activity, activities, repo?.name || ''), + }), + }); + return flattenTree(tree); + }); + + return { hasOutline, items }; +} From 972f7cb144806dc743f17cbb5a8c423e0ad59875 Mon Sep 17 00:00:00 2001 From: underscope Date: Fri, 27 Mar 2026 08:23:34 +0100 Subject: [PATCH 02/15] Add filtering type --- .../repository/Assets/Discovery/TopicPicker/types.ts | 10 ++++++++++ .../Assets/Discovery/TopicPicker/useOutlineTree.ts | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/types.ts diff --git a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/types.ts b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/types.ts new file mode 100644 index 000000000..5aadbb2ae --- /dev/null +++ b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/types.ts @@ -0,0 +1,10 @@ +export interface TopicItem { + id: number; + name: string; + parentName?: string; + isGroup: boolean; + isLeaf: boolean; + depth: number; + // Full context path for building search queries. + context: string[]; +} diff --git a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts index 15ebadca0..63053c733 100644 --- a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts +++ b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts @@ -17,8 +17,8 @@ const buildTopicMeta = ( id: activity.id, name, parentName: ancestorNames.at(-1), - isLeaf, isGroup: !isLeaf, + isLeaf, depth: ancestors.length, context: [name, ...ancestorNames, repositoryName].filter(Boolean), }; From fe07d4cf375668d1feb8a66f8b2bc696b0d854b6 Mon Sep 17 00:00:00 2001 From: underscope Date: Fri, 27 Mar 2026 08:24:46 +0100 Subject: [PATCH 03/15] Emit search input --- .../components/repository/Assets/Discovery/SearchBar.vue | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/frontend/app/components/repository/Assets/Discovery/SearchBar.vue b/apps/frontend/app/components/repository/Assets/Discovery/SearchBar.vue index fc46f3d28..3cf56677c 100644 --- a/apps/frontend/app/components/repository/Assets/Discovery/SearchBar.vue +++ b/apps/frontend/app/components/repository/Assets/Discovery/SearchBar.vue @@ -15,6 +15,7 @@ hide-details @click:clear="query = ''" @keyup.enter="emit('search')" + @update:model-value="emit('search:input')" /> (); -const emit = defineEmits<{ search: [] }>(); +const emit = defineEmits<{ + 'search': []; + 'search:input': []; +}>(); const query = defineModel('query', { required: true }); const contentFilter = defineModel('contentFilter', { required: true }); From 12347d8aca24cb7f2b1099e753ef40cb1a92b788 Mon Sep 17 00:00:00 2001 From: underscope Date: Fri, 27 Mar 2026 08:43:05 +0100 Subject: [PATCH 04/15] Init Topic picker --- .../Discovery/TopicPicker/TopicList.vue | 55 ++++++++++++++++ .../Assets/Discovery/TopicPicker/index.vue | 63 +++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/TopicList.vue create mode 100644 apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue diff --git a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/TopicList.vue b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/TopicList.vue new file mode 100644 index 000000000..c44fca548 --- /dev/null +++ b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/TopicList.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue new file mode 100644 index 000000000..8c60801b0 --- /dev/null +++ b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue @@ -0,0 +1,63 @@ + + + From 3b0208242580fef77a6eac029133b2020f082633 Mon Sep 17 00:00:00 2001 From: underscope Date: Fri, 27 Mar 2026 09:17:04 +0100 Subject: [PATCH 05/15] Add outline based discovery --- .../Assets/Discovery/SearchResults/index.vue | 60 +++++++++++++----- .../repository/Assets/Discovery/index.vue | 62 ++++++++++++++++--- 2 files changed, 98 insertions(+), 24 deletions(-) diff --git a/apps/frontend/app/components/repository/Assets/Discovery/SearchResults/index.vue b/apps/frontend/app/components/repository/Assets/Discovery/SearchResults/index.vue index 6f71243b5..a6c300540 100644 --- a/apps/frontend/app/components/repository/Assets/Discovery/SearchResults/index.vue +++ b/apps/frontend/app/components/repository/Assets/Discovery/SearchResults/index.vue @@ -1,5 +1,5 @@ + + diff --git a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue new file mode 100644 index 000000000..8c60801b0 --- /dev/null +++ b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue @@ -0,0 +1,63 @@ + + + From f3bc112686adf3a84fc80f51b9b55402ef277cf4 Mon Sep 17 00:00:00 2001 From: underscope Date: Fri, 27 Mar 2026 09:17:04 +0100 Subject: [PATCH 10/15] Add outline based discovery --- .../Assets/Discovery/SearchResults/index.vue | 59 ++++++++++++++---- .../repository/Assets/Discovery/index.vue | 61 ++++++++++++++++--- 2 files changed, 98 insertions(+), 22 deletions(-) diff --git a/apps/frontend/app/components/repository/Assets/Discovery/SearchResults/index.vue b/apps/frontend/app/components/repository/Assets/Discovery/SearchResults/index.vue index b626ce123..a6c300540 100644 --- a/apps/frontend/app/components/repository/Assets/Discovery/SearchResults/index.vue +++ b/apps/frontend/app/components/repository/Assets/Discovery/SearchResults/index.vue @@ -1,5 +1,5 @@ diff --git a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts index 63053c733..290ee6790 100644 --- a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts +++ b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts @@ -16,8 +16,8 @@ const buildTopicMeta = ( return { id: activity.id, name, - parentName: ancestorNames.at(-1), isGroup: !isLeaf, + parentName: ancestorNames.at(-1), isLeaf, depth: ancestors.length, context: [name, ...ancestorNames, repositoryName].filter(Boolean), diff --git a/apps/frontend/app/components/repository/Assets/Discovery/index.vue b/apps/frontend/app/components/repository/Assets/Discovery/index.vue index 5bcf98eae..0226fc80c 100644 --- a/apps/frontend/app/components/repository/Assets/Discovery/index.vue +++ b/apps/frontend/app/components/repository/Assets/Discovery/index.vue @@ -28,7 +28,6 @@ v-if="hasOutline" v-model="selectedTopic" class="mb-4" - @topic:select="onTopicSelect" @topic:clear="clearTopic" /> @@ -142,14 +140,6 @@ async function search() { } } -function onTopicSelect(topic: TopicItem) { - query.value = topic.context - .join(' ') - .split(/\s+/) - .slice(0, MAX_QUERY_WORDS) - .join(' '); - search(); -} function clearTopic() { selectedTopic.value = null; @@ -227,6 +217,16 @@ watch(show, (v) => { selectedTopic.value = null; }); +watch(selectedTopic, (topic) => { + if (!topic) return; + query.value = topic.context + .join(' ') + .split(/\s+/) + .slice(0, MAX_QUERY_WORDS) + .join(' '); + search(); +}); + watch(contentFilter, () => { if (query.value.trim()) search(); }); From 678abb983a889b9bd235d82cf8fb36e42506c8f1 Mon Sep 17 00:00:00 2001 From: underscope Date: Tue, 7 Apr 2026 11:05:17 +0200 Subject: [PATCH 13/15] =?UTF-8?q?=F0=9F=92=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/components/repository/Assets/Discovery/index.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/frontend/app/components/repository/Assets/Discovery/index.vue b/apps/frontend/app/components/repository/Assets/Discovery/index.vue index 0226fc80c..9b41cebea 100644 --- a/apps/frontend/app/components/repository/Assets/Discovery/index.vue +++ b/apps/frontend/app/components/repository/Assets/Discovery/index.vue @@ -140,7 +140,6 @@ async function search() { } } - function clearTopic() { selectedTopic.value = null; query.value = ''; From aba427a9de739fb16dd0eb86f6785ac7f2a1908a Mon Sep 17 00:00:00 2001 From: underscope Date: Mon, 13 Apr 2026 14:24:52 +0200 Subject: [PATCH 14/15] =?UTF-8?q?=F0=9F=92=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Assets/Discovery/TopicPicker/index.vue | 91 ++++++++++--------- .../Assets/Discovery/TopicPicker/types.ts | 2 + .../Discovery/TopicPicker/useOutlineTree.ts | 1 + 3 files changed, 51 insertions(+), 43 deletions(-) diff --git a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue index 3509535d3..1d3407925 100644 --- a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue +++ b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue @@ -1,45 +1,48 @@ diff --git a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/types.ts b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/types.ts index 5aadbb2ae..ec1615293 100644 --- a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/types.ts +++ b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/types.ts @@ -2,6 +2,8 @@ export interface TopicItem { id: number; name: string; parentName?: string; + // Full ancestor breadcrumb (e.g. "Module 1 / Sub-module") + breadcrumb: string; isGroup: boolean; isLeaf: boolean; depth: number; diff --git a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts index 290ee6790..0d27b7384 100644 --- a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts +++ b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/useOutlineTree.ts @@ -18,6 +18,7 @@ const buildTopicMeta = ( name, isGroup: !isLeaf, parentName: ancestorNames.at(-1), + breadcrumb: ancestorNames.toReversed().join(' / '), isLeaf, depth: ancestors.length, context: [name, ...ancestorNames, repositoryName].filter(Boolean), From 107dc84669df9becf0b711742ec6db7a8cb78832 Mon Sep 17 00:00:00 2001 From: underscope Date: Wed, 15 Apr 2026 11:28:17 +0200 Subject: [PATCH 15/15] =?UTF-8?q?=F0=9F=92=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/Assets/Discovery/TopicPicker/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue index 1d3407925..1562e5bc9 100644 --- a/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue +++ b/apps/frontend/app/components/repository/Assets/Discovery/TopicPicker/index.vue @@ -17,7 +17,7 @@ @update:model-value="onSelect" >