summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNishant Tiwari <tiwari.nishant@ibm.com>2026-07-16 11:27:11 +0300
committerNishant Tiwari <tiwari.nishant@ibm.com>2026-09-28 13:42:29 +0300
commit85248e05cf5c44fc2a77135f829ae33b0d485e2f (patch)
tree16378e768cfd50a88578c36ad28e6d9275dd8907
parent4628f24b336ea30b288a4b50d42c0e50d8d62869 (diff)
downloadwebui-vue-master.tar.xz
Add asset tag edit functionality to overview pageHEADmaster
Implemented the ability to view and edit the system asset tag directly from the Overview page, including a modal dialog for editing, Vuex store action for saving, and truncation in the app header. Changes: - Added ModalAssetTag.vue component with: - Form input for editing the asset tag value - Vuelidate validation requiring a non-empty tag - Updated OverviewServer.vue to: - Display asset tag in the system information section - Add inline edit button using Carbon edit icon - Dispatch saveAssetTag store action with toast feedback - Refresh global system info after a successful save - Added saveAssetTag action to SystemStore.js using PATCH against the system path endpoint - Updated AppHeader.vue to truncate asset tags longer than 30 characters with an ellipsis, preserving full value in the title attribute for accessibility - Added translation keys for asset tag label, modal title, and success/error toast messages in en-US, ka-GE, and ru-RU locale files Testing: - Verified asset tag displays correctly in system info section - Verified modal opens, validates, and submits correctly - Verified PATCH request updates asset tag on the server - Validated success and error toast notifications display - Confirmed long asset tags are truncated in the header Change-Id: I6ac51dfc24b9d40986b74e9220cff955b029d659 Signed-off-by: Nishant Tiwari <tiwari.nishant@ibm.com>
-rw-r--r--src/components/AppHeader/AppHeader.vue10
-rw-r--r--src/locales/en-US.json10
-rw-r--r--src/locales/ka-GE.json10
-rw-r--r--src/locales/ru-RU.json10
-rw-r--r--src/store/modules/HardwareStatus/SystemStore.js11
-rw-r--r--src/views/Overview/ModalAssetTag.vue126
-rw-r--r--src/views/Overview/OverviewServer.vue40
7 files changed, 212 insertions, 5 deletions
diff --git a/src/components/AppHeader/AppHeader.vue b/src/components/AppHeader/AppHeader.vue
index 79e5c167b..0773cbe3d 100644
--- a/src/components/AppHeader/AppHeader.vue
+++ b/src/components/AppHeader/AppHeader.vue
@@ -39,7 +39,9 @@
</b-navbar-brand>
<div v-if="isNavTagPresent" :key="routerKey" class="ps-2 nav-tags">
<span>|</span>
- <span class="ps-3 asset-tag">{{ assetTag }}</span>
+ <span class="ps-3 asset-tag" :title="assetTag">
+ {{ assetTag }}
+ </span>
<span class="ps-3">{{ modelType }}</span>
<span class="ps-3">{{ serialNumber }}</span>
</div>
@@ -367,6 +369,12 @@ export default {
@include media-breakpoint-down($responsive-layout-bp) {
@include visually-hidden;
}
+ max-width: 50rem;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ display: inline-block;
+ vertical-align: middle;
}
}
}
diff --git a/src/locales/en-US.json b/src/locales/en-US.json
index 99f4bd8b6..07b5a94ca 100644
--- a/src/locales/en-US.json
+++ b/src/locales/en-US.json
@@ -627,6 +627,7 @@
}
},
"pageOverview": {
+ "assetTag": "Asset tag",
"backupVersion": "Backup",
"bmcTime": "BMC date and time",
"criticalEvents": "Critical",
@@ -654,7 +655,14 @@
"systemInformation": "System information",
"total": "Total",
"warningEvents": "Warning",
- "viewMore": "View more"
+ "viewMore": "View more",
+ "modal": {
+ "editAssetTag": "Edit asset tag"
+ },
+ "toast": {
+ "successSaveAssetTag": "Successfully updated asset tag.",
+ "errorSaveAssetTag": "Error updating asset tag."
+ }
},
"pagePostCodeLogs": {
"allExportFilePrefix": "All_POST_codes_log_",
diff --git a/src/locales/ka-GE.json b/src/locales/ka-GE.json
index 5ada54f16..1bab9028c 100644
--- a/src/locales/ka-GE.json
+++ b/src/locales/ka-GE.json
@@ -627,6 +627,7 @@
}
},
"pageOverview": {
+ "assetTag": "აქტივის იდენტიფიკატორი",
"backupVersion": "მარქაფი",
"bmcTime": "BMC-ის დრო და თარიღი",
"criticalEvents": "კრიტიკული",
@@ -654,7 +655,14 @@
"systemInformation": "სისტემის ინფორმაცია",
"total": "სულ",
"warningEvents": "გაფრთხილება",
- "viewMore": "მეტის ნახვა"
+ "viewMore": "მეტის ნახვა",
+ "modal": {
+ "editAssetTag": "აქტივის იდენტიფიკატორის რედაქტირება"
+ },
+ "toast": {
+ "successSaveAssetTag": "აქტივის იდენტიფიკატორი წარმატებით განახლდა.",
+ "errorSaveAssetTag": "აქტივის იდენტიფიკატორის განახლების შეცდომა."
+ }
},
"pagePostCodeLogs": {
"allExportFilePrefix": "ყველა_POST_კოდის_ჟურნალი",
diff --git a/src/locales/ru-RU.json b/src/locales/ru-RU.json
index e9b049462..a22de1e9c 100644
--- a/src/locales/ru-RU.json
+++ b/src/locales/ru-RU.json
@@ -627,6 +627,7 @@
}
},
"pageOverview": {
+ "assetTag": "Метка актива",
"backupVersion": "Резервный",
"bmcTime": "Дата и время BMC",
"criticalEvents": "Критические",
@@ -654,7 +655,14 @@
"systemInformation": "Информация о системе",
"total": "Всего",
"warningEvents": "Предупреждения",
- "viewMore": "Подробнее"
+ "viewMore": "Подробнее",
+ "modal": {
+ "editAssetTag": "Изменить метку актива"
+ },
+ "toast": {
+ "successSaveAssetTag": "Метка актива успешно обновлена.",
+ "errorSaveAssetTag": "Ошибка при обновлении метки актива."
+ }
},
"pagePostCodeLogs": {
"allExportFilePrefix": "Лог_всех_POST_кодов_",
diff --git a/src/store/modules/HardwareStatus/SystemStore.js b/src/store/modules/HardwareStatus/SystemStore.js
index 7fbd6bc41..87bf4696c 100644
--- a/src/store/modules/HardwareStatus/SystemStore.js
+++ b/src/store/modules/HardwareStatus/SystemStore.js
@@ -74,6 +74,17 @@ const SystemStore = {
}
});
},
+ async saveAssetTag(_, assetTag) {
+ return await api
+ .patch(`${await this.dispatch('global/getSystemPath')}`, assetTag)
+ .then(() => {
+ return i18n.global.t('pageOverview.toast.successSaveAssetTag');
+ })
+ .catch((error) => {
+ console.log(error);
+ throw new Error(i18n.global.t('pageOverview.toast.errorSaveAssetTag'));
+ });
+ },
},
};
diff --git a/src/views/Overview/ModalAssetTag.vue b/src/views/Overview/ModalAssetTag.vue
new file mode 100644
index 000000000..c73b5ba5e
--- /dev/null
+++ b/src/views/Overview/ModalAssetTag.vue
@@ -0,0 +1,126 @@
+<template>
+ <b-modal
+ id="modal-asset-tag"
+ ref="modal"
+ :title="$t('pageOverview.modal.editAssetTag')"
+ @hidden="resetForm"
+ >
+ <b-form id="asset-settings" @submit.prevent="handleSubmit">
+ <b-row>
+ <b-col sm="8">
+ <b-form-group
+ :label="$t('pageOverview.assetTag')"
+ label-for="asset-tag"
+ >
+ <b-form-input
+ id="asset-tag"
+ v-model="form.assetTag"
+ type="text"
+ :state="getValidationState(v$.form.assetTag)"
+ @input="v$.form.assetTag.$touch()"
+ />
+ <b-form-invalid-feedback role="alert">
+ <template v-if="v$.form.assetTag.required.$invalid">
+ {{ $t('global.form.fieldRequired') }}
+ </template>
+ </b-form-invalid-feedback>
+ </b-form-group>
+ </b-col>
+ </b-row>
+ </b-form>
+ <template #footer="{ cancel }">
+ <b-button variant="secondary" @click="cancel()">
+ {{ $t('global.action.cancel') }}
+ </b-button>
+ <b-button
+ form="asset-settings"
+ type="submit"
+ variant="primary"
+ @click="onOk"
+ >
+ {{ $t('global.action.save') }}
+ </b-button>
+ </template>
+ </b-modal>
+</template>
+
+<script>
+import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js';
+import { useVuelidate } from '@vuelidate/core';
+import { required } from '@vuelidate/validators';
+
+export default {
+ mixins: [VuelidateMixin],
+ props: {
+ modelValue: {
+ type: Boolean,
+ default: false,
+ },
+ tag: {
+ type: String,
+ default: '',
+ },
+ },
+ emits: ['ok', 'hidden', 'update:modelValue'],
+ setup() {
+ return {
+ v$: useVuelidate(),
+ };
+ },
+ data() {
+ return {
+ form: {
+ assetTag: this.tag ? this.tag : '',
+ },
+ };
+ },
+ watch: {
+ tag() {
+ this.form.assetTag = this.tag;
+ },
+ modelValue: {
+ handler(newValue) {
+ if (newValue) {
+ this.$nextTick(() => {
+ this.$refs.modal?.show();
+ });
+ }
+ },
+ immediate: true,
+ },
+ },
+ validations() {
+ return {
+ form: {
+ assetTag: {
+ required,
+ },
+ },
+ };
+ },
+ methods: {
+ handleSubmit() {
+ this.v$.$touch();
+ if (this.v$.$invalid) return;
+ this.$emit('ok', { AssetTag: this.form.assetTag });
+ this.closeModal();
+ },
+ closeModal() {
+ this.$nextTick(() => {
+ this.$refs.modal.hide();
+ });
+ },
+ resetForm() {
+ this.form.assetTag = this.tag;
+ this.v$.$reset();
+ this.$emit('update:modelValue', false);
+ this.$emit('hidden');
+ },
+ onOk(bvModalEvt) {
+ // prevent modal close
+ bvModalEvt.preventDefault();
+ this.handleSubmit();
+ },
+ },
+};
+</script>
diff --git a/src/views/Overview/OverviewServer.vue b/src/views/Overview/OverviewServer.vue
index 044440a04..8d66da689 100644
--- a/src/views/Overview/OverviewServer.vue
+++ b/src/views/Overview/OverviewServer.vue
@@ -10,6 +10,13 @@
<dd>{{ dataFormatter(serverModel) }}</dd>
<dt>{{ $t('pageOverview.serialNumber') }}</dt>
<dd>{{ dataFormatter(serverSerialNumber) }}</dd>
+ <dt>
+ {{ $t('pageOverview.assetTag') }}
+ <b-button variant="link" class="p-1" @click="initAssetTagModal()">
+ <icon-edit :title="$t('pageOverview.modal.editAssetTag')" />
+ </b-button>
+ </dt>
+ <dd :title="assetTag">{{ dataFormatter(assetTag) }}</dd>
</dl>
</b-col>
<b-col sm="6">
@@ -19,26 +26,41 @@
</dl>
</b-col>
</b-row>
+ <modal-asset-tag v-model="showAssetTagModal" :tag="assetTag" @ok="saveAssetTag" />
</overview-card>
</template>
<script>
import OverviewCard from './OverviewCard';
import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin';
+import BVToastMixin from '@/components/Mixins/BVToastMixin';
+import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
import { mapState } from 'vuex';
+import ModalAssetTag from './ModalAssetTag.vue';
+import IconEdit from '@carbon/icons-vue/es/edit/16';
export default {
name: 'Server',
components: {
OverviewCard,
+ IconEdit,
+ ModalAssetTag,
+ },
+ mixins: [DataFormatterMixin, BVToastMixin, LoadingBarMixin],
+ data() {
+ return {
+ showAssetTagModal: false,
+ };
},
- mixins: [DataFormatterMixin],
computed: {
...mapState({
server: (state) => state.system.systems[0],
serverModel() {
return this.server?.model;
},
+ assetTag() {
+ return this.$store.getters['global/assetTag'];
+ },
serverSerialNumber() {
return this.server?.serialNumber;
},
@@ -52,5 +74,21 @@ export default {
this.$eventBus.$emit('overview-server-complete');
});
},
+ methods: {
+ initAssetTagModal() {
+ this.showAssetTagModal = true;
+ },
+ saveAssetTag(modalFormData) {
+ this.startLoader();
+ this.$store
+ .dispatch('system/saveAssetTag', modalFormData)
+ .then((message) => {
+ this.$store.dispatch('global/getSystemInfo');
+ this.successToast(message);
+ })
+ .catch(({ message }) => this.errorToast(message))
+ .finally(() => this.endLoader());
+ },
+ }
};
</script>