From 04e0bbcc4cbcf204a0844be8aab9314d7cd1d6ae Mon Sep 17 00:00:00 2001 From: Matthew Irish Date: Mon, 20 May 2019 12:03:10 -0500 Subject: [PATCH] add common-prefix util and use it in the list controller --- ui/app/mixins/list-controller.js | 20 +++++++++++++++----- ui/app/utils/common-prefix.js | 23 +++++++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 ui/app/utils/common-prefix.js diff --git a/ui/app/mixins/list-controller.js b/ui/app/mixins/list-controller.js index 423b42a12e21..5d27f7a4abde 100644 --- a/ui/app/mixins/list-controller.js +++ b/ui/app/mixins/list-controller.js @@ -1,6 +1,7 @@ import { computed } from '@ember/object'; import Mixin from '@ember/object/mixin'; import escapeStringRegexp from 'escape-string-regexp'; +import commonPrefix from 'vault/utils/common-prefix'; export default Mixin.create({ queryParams: { @@ -26,11 +27,20 @@ export default Mixin.create({ var content = this.get('model'); var filterMatchesKey = this.get('filterMatchesKey'); var re = new RegExp('^' + escapeStringRegexp(filter)); - return filterMatchesKey - ? null - : content.find(function(key) { - return re.test(key.get('id')); - }); + let matchSet = content.filter(key => re.test(key.id)); + let match = matchSet.firstObject; + + if (filterMatchesKey || !match) { + return null; + } + + let sharedPrefix = commonPrefix(content); + // if we already are filtering the prefix, then next we want + // the exact match + if (filter === sharedPrefix || matchSet.length === 1) { + return match; + } + return { id: sharedPrefix }; }), actions: { diff --git a/ui/app/utils/common-prefix.js b/ui/app/utils/common-prefix.js new file mode 100644 index 000000000000..b5e4fda6fdbf --- /dev/null +++ b/ui/app/utils/common-prefix.js @@ -0,0 +1,23 @@ +import { get } from '@ember/object'; + +export default function(arr, attribute = 'id') { + let content = arr || []; + // this assumes an already sorted array, if we have a match, + // it will have matched the first one so we also want the last one + let firstString = get(content[0], attribute); + let lastString = get(content[arr.length - 1], attribute); + + // the longest the shared prefix could be is the length of the match + let targetLength = firstString.length; + let prefixLength = 0; + // walk the two strings, and if they match at the current length, + // increment the prefix and try again + while ( + prefixLength < targetLength && + firstString.charAt(prefixLength) === lastString.charAt(prefixLength) + ) { + prefixLength++; + } + // slice the prefix from the match + return firstString.substring(0, prefixLength); +}