mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2025-12-13 13:11:43 +00:00
Add searchbox in settings page (#338)
* Add searchbox in setting page Signed-off-by: Andy Lee <andy.lee@suse.com> * update based on comment Signed-off-by: Andy Lee <andy.lee@suse.com> * PR feedback Signed-off-by: Andy Lee <andy.lee@suse.com> --------- Signed-off-by: Andy Lee <andy.lee@suse.com>
This commit is contained in:
parent
fb59b396d1
commit
d9c97de0fd
@ -30,15 +30,23 @@ export default {
|
|||||||
category: {
|
category: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
searchQuery: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
const categorySettings = this.filterCategorySettings();
|
const categorySettings = this.filterCategorySettings();
|
||||||
|
const filteredSettings = this.filterSearchSettings(categorySettings, this.searchQuery);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
HCI_SETTING,
|
HCI_SETTING,
|
||||||
categorySettings,
|
categorySettings,
|
||||||
|
filteredSettings,
|
||||||
|
originalHideMap: this.createHideMap(categorySettings)
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -48,12 +56,81 @@ export default {
|
|||||||
settings: {
|
settings: {
|
||||||
deep: true,
|
deep: true,
|
||||||
handler() {
|
handler() {
|
||||||
this['categorySettings'] = this.filterCategorySettings();
|
this.categorySettings = this.filterCategorySettings();
|
||||||
|
this.filteredSettings = this.filterSearchSettings(this.categorySettings, this.searchQuery);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
searchQuery: {
|
||||||
|
immediate: true,
|
||||||
|
handler(newQuery) {
|
||||||
|
const filtered = this.filterSearchSettings(this.categorySettings, newQuery);
|
||||||
|
|
||||||
|
this.filteredSettings = newQuery ? this.openJsonSettings(filtered) : filtered.map((s) => ({ ...s, hide: this.originalHideMap[s.id] ?? false }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
createHideMap(settings = []) {
|
||||||
|
const map = settings.reduce((acc, s) => {
|
||||||
|
acc[s.id] = s.hide ?? false;
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, {} );
|
||||||
|
|
||||||
|
return map;
|
||||||
|
},
|
||||||
|
filterSearchSettings(settings, searchKey) {
|
||||||
|
if (!searchKey) {
|
||||||
|
return this.filterCategorySettings();
|
||||||
|
}
|
||||||
|
const searchQuery = searchKey.toLowerCase();
|
||||||
|
|
||||||
|
return settings.filter((setting) => {
|
||||||
|
const id = setting.id?.toLowerCase() || '';
|
||||||
|
|
||||||
|
// filter by id
|
||||||
|
if (id.includes(searchQuery) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const description = this.t(setting.description, {}, true)?.toLowerCase() || '';
|
||||||
|
|
||||||
|
// filter by description
|
||||||
|
if (description.includes(searchQuery)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter by customized value
|
||||||
|
if (setting.customized === true && setting.data?.value) {
|
||||||
|
const value = setting.data.value?.toLowerCase() || '';
|
||||||
|
|
||||||
|
return value.includes(searchQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter by json value
|
||||||
|
if (setting.kind === 'json' && setting.json) {
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(setting.json);
|
||||||
|
const jsonString = JSON.stringify(json).toLowerCase();
|
||||||
|
|
||||||
|
return jsonString.includes(searchQuery);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`${ setting.id }: wrong format`, e); // eslint-disable-line no-console
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter by default value
|
||||||
|
if (setting.data?.default) {
|
||||||
|
return setting.data?.default.includes(searchQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
filterCategorySettings() {
|
filterCategorySettings() {
|
||||||
return this.settings.filter((s) => {
|
return this.settings.filter((s) => {
|
||||||
if (!this.getFeatureEnabled(s.featureFlag)) {
|
if (!this.getFeatureEnabled(s.featureFlag)) {
|
||||||
@ -87,12 +164,17 @@ export default {
|
|||||||
return HCI_ALLOWED_SETTINGS.find((setting) => setting.id === id);
|
return HCI_ALLOWED_SETTINGS.find((setting) => setting.id === id);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
openJsonSettings(settings) {
|
||||||
|
return settings.map((s) => s.hide ? { ...s, hide: false } : s);
|
||||||
|
},
|
||||||
|
|
||||||
toggleHide(s) {
|
toggleHide(s) {
|
||||||
this.categorySettings.find((setting) => {
|
const setting = this.filteredSettings.find((setting) => setting.id === s.id);
|
||||||
if (setting.id === s.id) {
|
|
||||||
setting.hide = !setting.hide;
|
if (setting) {
|
||||||
}
|
setting.hide = !setting.hide;
|
||||||
});
|
this.originalHideMap[setting.id] = setting.hide;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async testConnect(buttonDone, value) {
|
async testConnect(buttonDone, value) {
|
||||||
@ -126,7 +208,7 @@ export default {
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
v-for="(setting, i) in categorySettings"
|
v-for="(setting, i) in filteredSettings"
|
||||||
:key="i"
|
:key="i"
|
||||||
class="advanced-setting mb-20"
|
class="advanced-setting mb-20"
|
||||||
>
|
>
|
||||||
@ -221,6 +303,12 @@ export default {
|
|||||||
{{ setting.data.errMessage }}
|
{{ setting.data.errMessage }}
|
||||||
</Banner>
|
</Banner>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="filteredSettings.length === 0"
|
||||||
|
class="advanced-setting mb-20 no-search-match"
|
||||||
|
>
|
||||||
|
<p> {{ t('harvester.setting.noSearchMatch') }} </p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -271,4 +359,8 @@ export default {
|
|||||||
padding: 2px 10px;
|
padding: 2px 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.no-search-match {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1041,6 +1041,7 @@ harvester:
|
|||||||
accessKeyId: Specify your access key ID
|
accessKeyId: Specify your access key ID
|
||||||
secretAccessKey: Specify your secret access key
|
secretAccessKey: Specify your secret access key
|
||||||
cert: Upload a self-signed SSL certificate
|
cert: Upload a self-signed SSL certificate
|
||||||
|
noSearchMatch: No settings match your search.
|
||||||
vlanChangeTip: The newly modified default network interface only applies to newly added nodes, not existing ones.
|
vlanChangeTip: The newly modified default network interface only applies to newly added nodes, not existing ones.
|
||||||
defaultPhysicalNIC: Default Network Interface
|
defaultPhysicalNIC: Default Network Interface
|
||||||
modifiedMessage: Settings that have been customized from default settings are tagged with 'Modified'.
|
modifiedMessage: Settings that have been customized from default settings are tagged with 'Modified'.
|
||||||
|
|||||||
@ -85,7 +85,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return { initSettings: [] };
|
return { initSettings: [], searchQuery: '' };
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
@ -135,9 +135,19 @@ export default {
|
|||||||
{{ t('harvester.setting.modifiedMessage') }}
|
{{ t('harvester.setting.modifiedMessage') }}
|
||||||
</div>
|
</div>
|
||||||
</Banner>
|
</Banner>
|
||||||
|
<div class="fixed-header-actions harvester-settings-search">
|
||||||
|
<div class="search row">
|
||||||
|
<input
|
||||||
|
v-model="searchQuery"
|
||||||
|
type="search"
|
||||||
|
class="input-sm search-box"
|
||||||
|
:aria-label="t('sortableTable.searchLabel')"
|
||||||
|
:placeholder="t('sortableTable.search')"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<Tabbed
|
<Tabbed
|
||||||
class="mt-30"
|
class="mt-15"
|
||||||
>
|
>
|
||||||
<Tab
|
<Tab
|
||||||
name="advanced"
|
name="advanced"
|
||||||
@ -146,6 +156,7 @@ export default {
|
|||||||
>
|
>
|
||||||
<Settings
|
<Settings
|
||||||
:settings="settings"
|
:settings="settings"
|
||||||
|
:search-query="searchQuery"
|
||||||
category="advanced"
|
category="advanced"
|
||||||
/>
|
/>
|
||||||
</Tab>
|
</Tab>
|
||||||
@ -156,6 +167,7 @@ export default {
|
|||||||
>
|
>
|
||||||
<Settings
|
<Settings
|
||||||
:settings="settings"
|
:settings="settings"
|
||||||
|
:search-query="searchQuery"
|
||||||
category="ui"
|
category="ui"
|
||||||
/>
|
/>
|
||||||
</Tab>
|
</Tab>
|
||||||
@ -167,4 +179,20 @@ export default {
|
|||||||
.settings-banner {
|
.settings-banner {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.harvester-settings-search {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box {
|
||||||
|
height: 40px;
|
||||||
|
margin-left: 10px;
|
||||||
|
min-width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user