]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/form/GlobalSearchField.js
2 * This is a global search field it loads the /cluster/resources on focus and displays the
3 * result in a floating grid. Filtering and sorting is done in the customFilter function
5 * Accepts key up/down and enter for input, and it opens to CTRL+SHIFT+F and CTRL+SPACE
7 Ext
.define('PVE.form.GlobalSearchField', {
8 extend
: 'Ext.form.field.Text',
9 alias
: 'widget.pveGlobalSearchField',
11 emptyText
: gettext('Search'),
12 enableKeyEvents
: true,
18 userCls
: 'proxmox-tags-full',
19 focusOnToFront
: false,
21 emptyText
: Proxmox
.Utils
.noneText
,
30 model
: 'PVEResources',
33 url
: '/api2/extjs/cluster/resources',
37 ptype
: 'bufferedrenderer',
38 trailingBufferZone
: 20,
39 leadingBufferZone
: 20,
44 if (typeof me
.ctxMenu
!== 'undefined' && me
.ctxMenu
.isVisible()) {
48 if (!me
.textfield
.hasFocus
) {
53 setFocus: function() {
59 rowclick: function(grid
, record
) {
61 me
.textfield
.selectAndHide(record
.id
);
63 itemcontextmenu: function(v
, record
, item
, index
, event
) {
65 me
.ctxMenu
= PVE
.Utils
.createCmdMenu(v
, record
, item
, index
, event
);
68 focusenter
: 'setFocus',
73 text
: gettext('Type'),
76 renderer
: PVE
.Utils
.render_resource_type
,
79 text
: gettext('Description'),
82 renderer: function(value
, mD
, rec
) {
83 let overrides
= PVE
.UIOptions
.tagOverrides
;
84 let tags
= PVE
.Utils
.renderTags(rec
.data
.tags
, overrides
);
85 return `${value}${tags}`;
89 text
: gettext('Node'),
93 text
: gettext('Pool'),
99 customFilter: function(item
) {
102 if (me
.filterVal
=== '') {
103 item
.data
.relevance
= 0;
106 // different types have different fields to search, e.g., a node will never have a pool
108 'pool': ['type', 'pool', 'text'],
109 'node': ['type', 'node', 'text'],
110 'storage': ['type', 'pool', 'node', 'storage'],
111 'default': ['name', 'type', 'node', 'pool', 'vmid'],
113 let fields
= fieldMap
[item
.data
.type
] || fieldMap
.default;
114 let fieldArr
= fields
.map(field
=> item
.data
[field
]?.toString().toLowerCase());
115 if (item
.data
.tags
) {
116 let tags
= item
.data
.tags
.split(/[;, ]/);
117 fieldArr
.push(...tags
);
120 let filterWords
= me
.filterVal
.split(/\s+/);
122 // all text is case insensitive and each split-out word is searched for separately.
123 // a row gets 1 point for every partial match, and and additional point for every exact match
125 for (let fieldValue
of fieldArr
) {
126 if (fieldValue
=== undefined || fieldValue
=== "") {
129 for (let filterWord
of filterWords
) {
130 if (fieldValue
.indexOf(filterWord
) !== -1) {
131 match
++; // partial match
132 if (fieldValue
=== filterWord
) {
133 match
++; // exact match is worth more
138 item
.data
.relevance
= match
; // set the row's virtual 'relevance' value for ordering
142 updateFilter: function(field
, newValue
, oldValue
) {
144 // parse input and filter store, show grid
145 me
.grid
.store
.filterVal
= newValue
.toLowerCase().trim();
146 me
.grid
.store
.clearFilter(true);
147 me
.grid
.store
.filterBy(me
.customFilter
);
148 me
.grid
.getSelectionModel().select(0);
151 selectAndHide: function(id
) {
153 me
.tree
.selectById(id
);
159 onKey: function(field
, e
) {
161 var key
= e
.getKey();
164 case Ext
.event
.Event
.ENTER
:
165 // go to first entry if there is one
166 if (me
.grid
.store
.getCount() > 0) {
167 me
.selectAndHide(me
.grid
.getSelection()[0].data
.id
);
170 case Ext
.event
.Event
.UP
:
171 me
.grid
.getSelectionModel().selectPrevious();
173 case Ext
.event
.Event
.DOWN
:
174 me
.grid
.getSelectionModel().selectNext();
176 case Ext
.event
.Event
.ESC
:
183 loadValues: function(field
) {
186 me
.grid
.textfield
= me
;
187 me
.grid
.store
.load();
188 me
.grid
.showBy(me
, 'tl-bl');
191 hideGrid: function() {
194 if (!me
.grid
.hasFocus
) {
205 focusenter
: 'loadValues',
212 toggleFocus: function() {
221 initComponent: function() {
225 throw "no tree given";
228 me
.grid
= Ext
.create(me
.grid
);
232 // bind CTRL + SHIFT + F and CTRL + SPACE to open/close the search
233 me
.keymap
= new Ext
.KeyMap({
234 target
: Ext
.get(document
),
249 // always select first item and sort by relevance after load
250 me
.mon(me
.grid
.store
, 'load', function() {
251 me
.grid
.getSelectionModel().select(0);
253 property
: 'relevance',