feat: remove TemplateSearchBar component and enhance template filtering options with use cases and licenses

This commit is contained in:
Johnpaul
2025-08-20 19:39:37 +01:00
parent ce30ea3417
commit 989e4e50d3
5 changed files with 82 additions and 96 deletions

View File

@@ -1,64 +0,0 @@
<template>
<div class="relative w-full p-4">
<div class="h-12 flex items-center gap-4 justify-between">
<div class="flex-1 max-w-md">
<AutoComplete
v-model.lazy="searchQuery"
:placeholder="$t('templateWorkflows.searchPlaceholder')"
:complete-on-focus="false"
:delay="200"
class="w-full"
:pt="{
pcInputText: {
root: {
class: 'w-full rounded-2xl'
}
},
loader: {
style: 'display: none'
}
}"
:show-empty-message="false"
@complete="() => {}"
/>
</div>
</div>
<div class="flex items-center gap-4 mt-2">
<small
v-if="searchQuery && filteredCount !== null"
class="text-color-secondary"
>
{{ $t('g.resultsCount', { count: filteredCount }) }}
</small>
<Button
v-if="searchQuery"
text
size="small"
icon="pi pi-times"
:label="$t('g.clearFilters')"
@click="clearFilters"
/>
</div>
</div>
</template>
<script setup lang="ts">
import AutoComplete from 'primevue/autocomplete'
import Button from 'primevue/button'
const { filteredCount } = defineProps<{
filteredCount?: number | null
}>()
const searchQuery = defineModel<string>('searchQuery', { default: '' })
const emit = defineEmits<{
clearFilters: []
}>()
const clearFilters = () => {
searchQuery.value = ''
emit('clearFilters')
}
</script>

View File

@@ -7,28 +7,6 @@
pt:root="h-full grid grid-rows-[auto_1fr_auto]"
pt:content="p-2 overflow-auto"
>
<template #header>
<div class="flex flex-col">
<div class="flex justify-between items-center mb-4">
<h2 class="text-lg">{{ title }}</h2>
<SelectButton
v-model="layout"
:options="['grid', 'list']"
:allow-empty="false"
>
<template #option="{ option }">
<i :class="[option === 'list' ? 'pi pi-bars' : 'pi pi-table']" />
</template>
</SelectButton>
</div>
<TemplateSearchBar
v-model:search-query="searchQuery"
:filtered-count="filteredCount"
@clear-filters="() => reset()"
/>
</div>
</template>
<template #list="{ items }">
<TemplateWorkflowList
:source-module="sourceModule"
@@ -77,11 +55,8 @@
<script setup lang="ts">
import { useLocalStorage } from '@vueuse/core'
import DataView from 'primevue/dataview'
import SelectButton from 'primevue/selectbutton'
import { computed, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import TemplateSearchBar from '@/components/templates/TemplateSearchBar.vue'
import TemplateWorkflowCard from '@/components/templates/TemplateWorkflowCard.vue'
import TemplateWorkflowCardSkeleton from '@/components/templates/TemplateWorkflowCardSkeleton.vue'
import TemplateWorkflowList from '@/components/templates/TemplateWorkflowList.vue'

View File

@@ -6,7 +6,9 @@ import type { TemplateInfo } from '@/types/workflowTemplateTypes'
export interface TemplateFilterOptions {
searchQuery?: string
selectedModels?: string[]
sortBy?: 'recommended' | 'alphabetical' | 'newest'
selectedUseCases?: string[] // Now represents selected tags
selectedLicenses?: string[]
sortBy?: 'default' | 'alphabetical' | 'newest'
}
export function useTemplateFiltering(
@@ -14,7 +16,9 @@ export function useTemplateFiltering(
) {
const searchQuery = ref('')
const selectedModels = ref<string[]>([])
const sortBy = ref<'recommended' | 'alphabetical' | 'newest'>('recommended')
const selectedUseCases = ref<string[]>([])
const selectedLicenses = ref<string[]>([])
const sortBy = ref<'default' | 'alphabetical' | 'newest'>('default')
const templatesArray = computed(() => {
const templateData = 'value' in templates ? templates.value : templates
@@ -47,6 +51,20 @@ export function useTemplateFiltering(
return Array.from(modelSet).sort()
})
const availableUseCases = computed(() => {
const tagSet = new Set<string>()
templatesArray.value.forEach((template) => {
if (template.tags && Array.isArray(template.tags)) {
template.tags.forEach((tag) => tagSet.add(tag))
}
})
return Array.from(tagSet).sort()
})
const availableLicenses = computed(() => {
return ['Open Source', 'Closed Source (API Nodes)']
})
const filteredBySearch = computed(() => {
if (!searchQuery.value.trim()) {
return templatesArray.value
@@ -71,8 +89,45 @@ export function useTemplateFiltering(
})
})
const filteredByUseCases = computed(() => {
if (selectedUseCases.value.length === 0) {
return filteredByModels.value
}
return filteredByModels.value.filter((template) => {
if (!template.tags || !Array.isArray(template.tags)) {
return false
}
return selectedUseCases.value.some((selectedTag) =>
template.tags?.includes(selectedTag)
)
})
})
const filteredByLicenses = computed(() => {
if (selectedLicenses.value.length === 0) {
return filteredByUseCases.value
}
return filteredByUseCases.value.filter((template) => {
// Check if template has API in its tags or name (indicating it's a closed source API node)
const isApiTemplate =
template.tags?.includes('API') ||
template.name?.toLowerCase().includes('api_')
return selectedLicenses.value.some((selectedLicense) => {
if (selectedLicense === 'Closed Source (API Nodes)') {
return isApiTemplate
} else if (selectedLicense === 'Open Source') {
return !isApiTemplate
}
return false
})
})
})
const sortedTemplates = computed(() => {
const templates = [...filteredByModels.value]
const templates = [...filteredByLicenses.value]
switch (sortBy.value) {
case 'alphabetical':
@@ -87,9 +142,9 @@ export function useTemplateFiltering(
const dateB = new Date(b.date || '1970-01-01')
return dateB.getTime() - dateA.getTime()
})
case 'recommended':
case 'default':
default:
// Keep original order (recommended order)
// Keep original order (default order)
return templates
}
})
@@ -99,13 +154,23 @@ export function useTemplateFiltering(
const resetFilters = () => {
searchQuery.value = ''
selectedModels.value = []
sortBy.value = 'recommended'
selectedUseCases.value = []
selectedLicenses.value = []
sortBy.value = 'default'
}
const removeModelFilter = (model: string) => {
selectedModels.value = selectedModels.value.filter((m) => m !== model)
}
const removeUseCaseFilter = (tag: string) => {
selectedUseCases.value = selectedUseCases.value.filter((t) => t !== tag)
}
const removeLicenseFilter = (license: string) => {
selectedLicenses.value = selectedLicenses.value.filter((l) => l !== license)
}
const filteredCount = computed(() => filteredTemplates.value.length)
const totalCount = computed(() => templatesArray.value.length)
@@ -113,16 +178,22 @@ export function useTemplateFiltering(
// State
searchQuery,
selectedModels,
selectedUseCases,
selectedLicenses,
sortBy,
// Computed
filteredTemplates,
availableModels,
availableUseCases,
availableLicenses,
filteredCount,
totalCount,
// Methods
resetFilters,
removeModelFilter
removeModelFilter,
removeUseCaseFilter,
removeLicenseFilter
}
}

View File

@@ -895,6 +895,8 @@
"noResultsHint": "Try adjusting your search or filters",
"modelFilter": "Model Filter",
"modelsSelected": "{count} Models",
"useCasesSelected": "{count} Use Cases",
"licensesSelected": "{count} Licenses",
"resultsCount": "Showing {count} of {total} templates",
"sort": {
"recommended": "Recommended",

View File

@@ -15,6 +15,8 @@ export interface TemplateInfo {
tags?: string[]
models?: string[]
date?: string
useCase?: string
license?: string
}
export interface WorkflowTemplates {