From 06c393755bee347466082d48c46852fd32f899ff Mon Sep 17 00:00:00 2001 From: Samuel Padgett Date: Thu, 3 Nov 2016 13:01:36 -0400 Subject: [PATCH] Search image stream tag names and description in catalog Filter on specific image stream tag descriptions when searching the catalog. Limit the version dropdown to those tags that match the filter. --- .../directives/catalog/catalogImage.js | 19 ++++-- app/scripts/services/catalog.js | 68 +++++++++++++++++-- dist/scripts/scripts.js | 34 ++++++++-- 3 files changed, 101 insertions(+), 20 deletions(-) diff --git a/app/scripts/directives/catalog/catalogImage.js b/app/scripts/directives/catalog/catalogImage.js index 8d25f9ce30..84bafc3545 100644 --- a/app/scripts/directives/catalog/catalogImage.js +++ b/app/scripts/directives/catalog/catalogImage.js @@ -37,14 +37,19 @@ angular.module('openshiftConsole') return _.includes(tags, 'builder'); }; - var tags = _.get($scope, 'imageStream.status.tags', []); - $scope.tags = _.filter(tags, function(tag) { - return isBuilder(tag.tag) && !referenceTags[tag.tag]; - }); + // Watch status tags. Some tags might be removed from the list if they + // don't match the current filter. + $scope.$watch('imageStream.status.tags', function(tags) { + $scope.tags = _.filter(tags, function(tag) { + return isBuilder(tag.tag) && !referenceTags[tag.tag]; + }); - // Preselect the first tag value. - var firstTag = _.head($scope.tags); - _.set($scope, 'is.tag', firstTag); + var selected = _.get($scope, 'is.tag.tag'); + if (!selected || !_.some($scope.tags, { tag: selected })) { + // Preselect the first tag value. + _.set($scope, 'is.tag', _.head($scope.tags)); + } + }); } }; }); diff --git a/app/scripts/services/catalog.js b/app/scripts/services/catalog.js index 51a442e650..a2ecd4cbad 100644 --- a/app/scripts/services/catalog.js +++ b/app/scripts/services/catalog.js @@ -121,14 +121,68 @@ angular.module("openshiftConsole") return templatesByCategory; }; - // TODO: Filter by description - var imageStreamFilterFields = [ - 'metadata.name', - 'metadata.annotations["openshift.io/display-name"]' - ]; - + // Don't use KeywordService for image stream filtering so we can add + // special handling for image stream tags. Match keywords (array of regex) + // against image streams and image stream tags, returning a copy of the + // image streams with only matching status tags. + var getDisplayName = $filter('displayName'); var filterImageStreams = function(imageStreams, keywords) { - return KeywordService.filterForKeywords(imageStreams, imageStreamFilterFields, keywords); + if (!keywords.length) { + return imageStreams; + } + + var filteredImageStreams = []; + _.each(imageStreams, function(imageStream) { + var name = _.get(imageStream, 'metadata.name', ''); + var displayName = getDisplayName(imageStream, true); + var matchingTags = _.indexBy(imageStream.spec.tags, 'name'); + + // Find tags that match every keyword. Search image stream name, image + // stream display name, and tag names, and tag descriptions. If a + // keyword matches the image stream name or display name, it's + // considered to match all tags. + _.each(keywords, function(regex) { + if (regex.test(name)) { + return; + } + + if (displayName && regex.test(displayName)) { + return; + } + + // Check tag descriptions. + _.each(imageStream.spec.tags, function(tag) { + // If this is not a builder, don't match the tag. + var tagTags = _.get(tag, 'annotations.tags', ''); + if (!/\bbuilder\b/.test(tagTags)) { + delete matchingTags[tag.name]; + return; + } + + // If the keyword matches the tag name, accept it. + if (regex.test(tag.name)) { + return; + } + + var description = _.get(tag, 'annotations.description'); + if (!description || !regex.test(description)) { + delete matchingTags[tag.name]; + } + }); + }); + + // Make a copy of the image stream with only the matching tags. + var imageStreamCopy; + if (!_.isEmpty(matchingTags)) { + imageStreamCopy = angular.copy(imageStream); + imageStreamCopy.status.tags = _.filter(imageStreamCopy.status.tags, function(tag) { + return matchingTags[tag.tag]; + }); + filteredImageStreams.push(imageStreamCopy); + } + }); + + return filteredImageStreams; }; var templateFilterFields = [ diff --git a/dist/scripts/scripts.js b/dist/scripts/scripts.js index b17972ee9d..c5ac3bcf9e 100644 --- a/dist/scripts/scripts.js +++ b/dist/scripts/scripts.js @@ -3794,8 +3794,26 @@ _.each(e, function(d) { h(d, c) && (b[d.id] = b[d.id] || [], b[d.id].push(a), f = !0); }), f || (b[""] = b[""] || [], b[""].push(a)); }), b; -}, k = [ "metadata.name", 'metadata.annotations["openshift.io/display-name"]' ], l = function(a, b) { -return c.filterForKeywords(a, k, b); +}, k = a("displayName"), l = function(a, b) { +if (!b.length) return a; +var c = []; +return _.each(a, function(a) { +var d = _.get(a, "metadata.name", ""), e = k(a, !0), f = _.indexBy(a.spec.tags, "name"); +_.each(b, function(b) { +b.test(d) || e && b.test(e) || _.each(a.spec.tags, function(a) { +var c = _.get(a, "annotations.tags", ""); +if (!/\bbuilder\b/.test(c)) return void delete f[a.name]; +if (!b.test(a.name)) { +var d = _.get(a, "annotations.description"); +d && b.test(d) || delete f[a.name]; +} +}); +}); +var g; +_.isEmpty(f) || (g = angular.copy(a), g.status.tags = _.filter(g.status.tags, function(a) { +return f[a.tag]; +}), c.push(g)); +}), c; }, m = [ "metadata.name", 'metadata.annotations["openshift.io/display-name"]', "metadata.annotations.description" ], n = function(a, b) { return c.filterForKeywords(a, m, b); }; @@ -10118,12 +10136,16 @@ f[a.name] = c(b.imageStream, a.name), a.from && "ImageStreamTag" === a.from.kind var g = function(a) { var b = _.get(f, [ a ], []); return _.includes(b, "builder"); -}, h = _.get(b, "imageStream.status.tags", []); -b.tags = _.filter(h, function(a) { +}; +b.$watch("imageStream.status.tags", function(a) { +b.tags = _.filter(a, function(a) { return g(a.tag) && !d[a.tag]; }); -var i = _.head(b.tags); -_.set(b, "is.tag", i); +var c = _.get(b, "is.tag.tag"); +c && _.some(b.tags, { +tag:c +}) || _.set(b, "is.tag", _.head(b.tags)); +}); } }; } ]), angular.module("openshiftConsole").directive("catalogTemplate", function() {