From 828dda9b187684902710bb11621eca27bf0c6eec Mon Sep 17 00:00:00 2001 From: Derick Montague Date: Mon, 28 Jun 2021 15:52:22 -0500 Subject: IA update: Add logs and update overview icon This is the first patchset of the information architecture changes. These changes are the result of several months of design research with users to improve the existing information architecture (IA). More information can we found in the Github story. This patchset will add a Logs section and move event logs and dumps from the Health section to the new Logs section. It will also update the icon used for the Overview page. Github story: https://github.com/openbmc/webui-vue/issues/56 Testing: 1. IBM build: - Logs contained Event logs and dumps - Both pages rendered when clicking link 2. Intel build - Logs contained Event logs only - Logs page rendered when clicking link 3. Tested default build - Logs contained Event logs only - Logs page rendered when clicking link Signed-off-by: Derick Montague Change-Id: I4621837202cf5ad3469d6ea460d9a5bdc79c8816 --- src/store/modules/Logs/EventLogStore.js | 222 ++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 src/store/modules/Logs/EventLogStore.js (limited to 'src/store/modules/Logs/EventLogStore.js') diff --git a/src/store/modules/Logs/EventLogStore.js b/src/store/modules/Logs/EventLogStore.js new file mode 100644 index 00000000..c9bd82fd --- /dev/null +++ b/src/store/modules/Logs/EventLogStore.js @@ -0,0 +1,222 @@ +import api, { getResponseCount } from '@/store/api'; +import i18n from '@/i18n'; + +const getHealthStatus = (events, loadedEvents) => { + let status = loadedEvents ? 'OK' : ''; + for (const event of events) { + if (event.severity === 'Warning') { + status = 'Warning'; + } + if (event.severity === 'Critical') { + status = 'Critical'; + break; + } + } + return status; +}; + +// TODO: High priority events should also check if Log +// is resolved when the property is available in Redfish +const getHighPriorityEvents = (events) => + events.filter(({ severity }) => severity === 'Critical'); + +const EventLogStore = { + namespaced: true, + state: { + allEvents: [], + loadedEvents: false, + }, + getters: { + allEvents: (state) => state.allEvents, + highPriorityEvents: (state) => getHighPriorityEvents(state.allEvents), + healthStatus: (state) => + getHealthStatus(state.allEvents, state.loadedEvents), + }, + mutations: { + setAllEvents: (state, allEvents) => ( + (state.allEvents = allEvents), (state.loadedEvents = true) + ), + }, + actions: { + async getEventLogData({ commit }) { + return await api + .get('/redfish/v1/Systems/system/LogServices/EventLog/Entries') + .then(({ data: { Members = [] } = {} }) => { + const eventLogs = Members.map((log) => { + const { + Id, + Severity, + Created, + EntryType, + Message, + Name, + Modified, + Resolved, + AdditionalDataURI, + } = log; + return { + id: Id, + severity: Severity, + date: new Date(Created), + type: EntryType, + description: Message, + name: Name, + modifiedDate: new Date(Modified), + uri: log['@odata.id'], + filterByStatus: Resolved ? 'Resolved' : 'Unresolved', + status: Resolved, //true or false + additionalDataUri: AdditionalDataURI, + }; + }); + commit('setAllEvents', eventLogs); + }) + .catch((error) => { + console.log('Event Log Data:', error); + }); + }, + async deleteAllEventLogs({ dispatch }, data) { + return await api + .post( + '/redfish/v1/Systems/system/LogServices/EventLog/Actions/LogService.ClearLog' + ) + .then(() => dispatch('getEventLogData')) + .then(() => i18n.tc('pageEventLogs.toast.successDelete', data.length)) + .catch((error) => { + console.log(error); + throw new Error( + i18n.tc('pageEventLogs.toast.errorDelete', data.length) + ); + }); + }, + async deleteEventLogs({ dispatch }, uris = []) { + const promises = uris.map((uri) => + api.delete(uri).catch((error) => { + console.log(error); + return error; + }) + ); + return await api + .all(promises) + .then((response) => { + dispatch('getEventLogData'); + return response; + }) + .then( + api.spread((...responses) => { + const { successCount, errorCount } = getResponseCount(responses); + const toastMessages = []; + + if (successCount) { + const message = i18n.tc( + 'pageEventLogs.toast.successDelete', + successCount + ); + toastMessages.push({ type: 'success', message }); + } + + if (errorCount) { + const message = i18n.tc( + 'pageEventLogs.toast.errorDelete', + errorCount + ); + toastMessages.push({ type: 'error', message }); + } + + return toastMessages; + }) + ); + }, + async resolveEventLogs({ dispatch }, logs) { + const promises = logs.map((log) => + api.patch(log.uri, { Resolved: true }).catch((error) => { + console.log(error); + return error; + }) + ); + return await api + .all(promises) + .then((response) => { + dispatch('getEventLogData'); + return response; + }) + .then( + api.spread((...responses) => { + const { successCount, errorCount } = getResponseCount(responses); + const toastMessages = []; + if (successCount) { + const message = i18n.tc( + 'pageEventLogs.toast.successResolveLogs', + successCount + ); + toastMessages.push({ type: 'success', message }); + } + if (errorCount) { + const message = i18n.tc( + 'pageEventLogs.toast.errorResolveLogs', + errorCount + ); + toastMessages.push({ type: 'error', message }); + } + return toastMessages; + }) + ); + }, + async unresolveEventLogs({ dispatch }, logs) { + const promises = logs.map((log) => + api.patch(log.uri, { Resolved: false }).catch((error) => { + console.log(error); + return error; + }) + ); + return await api + .all(promises) + .then((response) => { + dispatch('getEventLogData'); + return response; + }) + .then( + api.spread((...responses) => { + const { successCount, errorCount } = getResponseCount(responses); + const toastMessages = []; + if (successCount) { + const message = i18n.tc( + 'pageEventLogs.toast.successUnresolveLogs', + successCount + ); + toastMessages.push({ type: 'success', message }); + } + if (errorCount) { + const message = i18n.tc( + 'pageEventLogs.toast.errorUnresolveLogs', + errorCount + ); + toastMessages.push({ type: 'error', message }); + } + return toastMessages; + }) + ); + }, + // Single log entry + async updateEventLogStatus({ dispatch }, log) { + const updatedEventLogStatus = log.status; + return await api + .patch(log.uri, { Resolved: updatedEventLogStatus }) + .then(() => { + dispatch('getEventLogData'); + }) + .then(() => { + if (log.status) { + return i18n.tc('pageEventLogs.toast.successResolveLogs', 1); + } else { + return i18n.tc('pageEventLogs.toast.successUnresolveLogs', 1); + } + }) + .catch((error) => { + console.log(error); + throw new Error(i18n.t('pageEventLogs.toast.errorLogStatusUpdate')); + }); + }, + }, +}; + +export default EventLogStore; -- cgit v1.2.3