1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
<script>
import eventHub from '../event_hub';
import FilteredSearchTokenizer from '../filtered_search_tokenizer';
export default {
name: 'RecentSearchesDropdownContent',
props: {
items: {
type: Array,
required: true,
},
isLocalStorageAvailable: {
type: Boolean,
required: false,
default: true,
},
allowedKeys: {
type: Array,
required: true,
},
},
computed: {
/**
* Both Epic and Roadmap pages share same recents store
* and with https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36421
* Roadmap started using `GlFilteredSearch` which is not compatible
* with string tokens stored in recents, so this is a temporary
* fix by ignoring non-string recents while in Epic page.
*/
compatibleItems() {
return this.items.filter(item => typeof item === 'string');
},
processedItems() {
return this.compatibleItems.map(item => {
const { tokens, searchToken } = FilteredSearchTokenizer.processTokens(
item,
this.allowedKeys,
);
const resultantTokens = tokens.map(token => ({
prefix: `${token.key}:`,
operator: token.operator,
suffix: `${token.symbol}${token.value}`,
}));
return {
text: item,
tokens: resultantTokens,
searchToken,
};
});
},
hasItems() {
return this.compatibleItems.length > 0;
},
},
methods: {
onItemActivated(text) {
eventHub.$emit('recentSearchesItemSelected', text);
},
onRequestClearRecentSearches(e) {
// Stop the dropdown from closing
e.stopPropagation();
eventHub.$emit('requestClearRecentSearches');
},
},
};
</script>
<template>
<div>
<div v-if="!isLocalStorageAvailable" ref="localStorageNote" class="dropdown-info-note">
{{ __('This feature requires local storage to be enabled') }}
</div>
<ul v-else-if="hasItems">
<li
v-for="(item, index) in processedItems"
ref="dropdownItem"
:key="`processed-items-${index}`"
>
<button
type="button"
class="filtered-search-history-dropdown-item js-dropdown-button"
@click="onItemActivated(item.text)"
>
<span>
<span
v-for="(token, tokenIndex) in item.tokens"
:key="`dropdown-token-${tokenIndex}`"
class="filtered-search-history-dropdown-token js-dropdown-token"
>
<span class="name">{{ token.prefix }}</span>
<span class="name">{{ token.operator }}</span>
<span class="value">{{ token.suffix }}</span>
</span>
</span>
<span class="filtered-search-history-dropdown-search-token">{{ item.searchToken }}</span>
</button>
</li>
<li class="divider"></li>
<li>
<button
ref="clearButton"
type="button"
class="filtered-search-history-clear-button"
@click="onRequestClearRecentSearches($event)"
>
{{ __('Clear recent searches') }}
</button>
</li>
</ul>
<div v-else ref="dropdownNote" class="dropdown-info-note">
{{ __("You don't have any recent searches") }}
</div>
</div>
</template>
|