diff --git a/web/src/lang/en.js b/web/src/lang/en.js index d0bc49e3b..f8759b317 100644 --- a/web/src/lang/en.js +++ b/web/src/lang/en.js @@ -145,6 +145,7 @@ export default { title: 'Title *', description: 'Description', required: 'Required', + search: 'Search', key: '{expr}', surveyVariables: 'Survey Variables', addVariable: 'Add variable', diff --git a/web/src/lang/es.js b/web/src/lang/es.js index 0125a6d16..968cdd8ba 100644 --- a/web/src/lang/es.js +++ b/web/src/lang/es.js @@ -129,6 +129,7 @@ export default { title: 'Título *', description: 'Descripción', required: 'Requerido', + search: 'Buscar', key: '{expr}', surveyVariables: 'Variables de Encuesta', addVariable: 'Agregar variable', diff --git a/web/src/views/project/Templates.vue b/web/src/views/project/Templates.vue index ea65edb22..75650bf98 100644 --- a/web/src/views/project/Templates.vue +++ b/web/src/views/project/Templates.vue @@ -51,6 +51,18 @@ + + @@ -136,7 +148,7 @@ single-expand show-expand :headers="filteredHeaders" - :items="items" + :items="searchedItems" :items-per-page="Number.MAX_VALUE" :expanded.sync="openedItems" :style="{ @@ -257,6 +269,10 @@ padding-right: 0 !important; } +.templates-search { + max-width: 260px; +} + @media #{map-get($display-breakpoints, 'sm-and-down')} { .templates-table .v-data-table__mobile-row:first-child { display: none !important; @@ -311,6 +327,7 @@ export default { viewTab: null, apps: null, itemApp: '', + search: '', }; }, @@ -338,6 +355,36 @@ export default { && this.views && this.isAppsLoaded; }, + + inventoryNameById() { + return this.getResourceNameMap(this.inventory); + }, + + repositoryNameById() { + return this.getResourceNameMap(this.repositories); + }, + + environmentNameById() { + return this.getResourceNameMap(this.environment); + }, + + templateSearchIndex() { + return (this.items || []).map((item) => ({ + item, + searchText: this.getTemplateSearchText(item), + })); + }, + + searchedItems() { + const search = (this.search || '').trim().toLowerCase(); + if (!search) { + return this.items; + } + + return this.templateSearchIndex + .filter(({ searchText }) => searchText.includes(search)) + .map(({ item }) => item); + }, }, watch: { async viewId() { @@ -479,6 +526,29 @@ export default { this.newTaskDialog = true; }, + getResourceNameMap(resources) { + return new Map((resources || []).map(({ id, name }) => [id, name])); + }, + + getTemplateSearchText(item) { + const inventory = this.inventoryNameById.get(item.inventory_id) || ''; + const repository = this.repositoryNameById.get(item.repository_id) || ''; + const environments = Array.isArray(item.environment_ids) + ? item.environment_ids + .map((id) => this.environmentNameById.get(id) || '') + .join(' ') + : ''; + + return [ + item.name, + item.playbook, + item.description, + inventory, + repository, + environments, + ].filter(Boolean).join(' ').toLowerCase(); + }, + getHeaders() { return [ {