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 [
{