From 0c23ca5b667b6fa027db178103119014ebe53141 Mon Sep 17 00:00:00 2001 From: badrAZ Date: Wed, 6 Jun 2018 14:25:31 +0200 Subject: [PATCH] feat(xo-web/Backup NG/logs): details are now dynamic (#3031) --- .../xo-web/src/common/add-subscriptions.js | 20 ++-- .../xo-web/src/xo-app/logs/backup-ng-logs.js | 2 +- .../xo-web/src/xo-app/logs/log-alert-body.js | 91 ++++++++++--------- 3 files changed, 58 insertions(+), 55 deletions(-) diff --git a/packages/xo-web/src/common/add-subscriptions.js b/packages/xo-web/src/common/add-subscriptions.js index a927f879b..3f6a52389 100644 --- a/packages/xo-web/src/common/add-subscriptions.js +++ b/packages/xo-web/src/common/add-subscriptions.js @@ -7,26 +7,22 @@ const call = fn => fn() // callbacks have been correctly initialized when there are circular dependencies const addSubscriptions = subscriptions => Component => class SubscriptionWrapper extends React.PureComponent { - constructor () { - super() - - // provide all props since the beginning (better behavior with Freactal) - const state = (this.state = {}) - Object.keys(subscriptions).forEach(key => { - state[key] = undefined - }) - } - _unsubscribes = null componentWillMount () { + const state = {} this._unsubscribes = map( typeof subscriptions === 'function' ? subscriptions(this.props) : subscriptions, - (subscribe, prop) => - subscribe(value => this.setState({ [prop]: value })) + (subscribe, prop) => { + state[prop] = undefined + return subscribe(value => this.setState({ [prop]: value })) + } ) + + // provide all props since the beginning (better behavior with Freactal) + this.setState(state) } componentWillUnmount () { diff --git a/packages/xo-web/src/xo-app/logs/backup-ng-logs.js b/packages/xo-web/src/xo-app/logs/backup-ng-logs.js index 466264fca..b4fca728f 100644 --- a/packages/xo-web/src/xo-app/logs/backup-ng-logs.js +++ b/packages/xo-web/src/xo-app/logs/backup-ng-logs.js @@ -115,7 +115,7 @@ const showTasks = log => {log.id} , - + ) const LOG_INDIVIDUAL_ACTIONS = [ diff --git a/packages/xo-web/src/xo-app/logs/log-alert-body.js b/packages/xo-web/src/xo-app/logs/log-alert-body.js index 177c06985..504999adb 100644 --- a/packages/xo-web/src/xo-app/logs/log-alert-body.js +++ b/packages/xo-web/src/xo-app/logs/log-alert-body.js @@ -7,10 +7,10 @@ import renderXoItem, { renderXoItemFromId } from 'render-xo-item' import Select from 'form/select' import Tooltip from 'tooltip' import { addSubscriptions, formatSize, formatSpeed } from 'utils' -import { filter, isEmpty, get, keyBy, map } from 'lodash' +import { countBy, filter, get, keyBy, map } from 'lodash' import { FormattedDate } from 'react-intl' import { injectState, provideState } from '@julien-f/freactal' -import { runBackupNgJob, subscribeRemotes } from 'xo' +import { runBackupNgJob, subscribeBackupNgLogs, subscribeRemotes } from 'xo' const TASK_STATUS = { failure: { @@ -77,40 +77,20 @@ const TASK_FILTER_OPTIONS = [ { label: 'taskSuccess', value: 'success' }, ] -const getFilteredTaskLogs = (logs, filterValue) => - filterValue === 'all' - ? logs - : filter(logs, ({ status }) => status === filterValue) - -const getInitialFilter = tasks => { - const isEmptyFilter = filterValue => - isEmpty(getFilteredTaskLogs(tasks, filterValue)) - - if (!isEmptyFilter('pending')) { - return PENDING_FILTER_OPTION - } - - if (!isEmptyFilter('failure')) { - return FAILURE_FILTER_OPTION - } - - if (!isEmptyFilter('interrupted')) { - return INTERRUPTED_FILTER_OPTION - } - - return ALL_FILTER_OPTION -} - export default [ - addSubscriptions({ + addSubscriptions(({ id }) => ({ remotes: cb => subscribeRemotes(remotes => { cb(keyBy(remotes, 'id')) }), - }), + log: cb => + subscribeBackupNgLogs(logs => { + cb(logs[id]) + }), + })), provideState({ - initialState: ({ log }) => ({ - filter: getInitialFilter(log.tasks), + initialState: () => ({ + filter: undefined, }), effects: { setFilter: (_, filter) => state => ({ @@ -129,21 +109,47 @@ export default [ }, }, computed: { - filteredTaskLogs: ({ filter: { value } }, { log }) => - getFilteredTaskLogs(log.tasks, value), - optionRenderer: (state, { log }) => ({ label, value }) => ( + filteredTaskLogs: ( + { defaultFilter, filter: { value } = defaultFilter }, + { log = {} } + ) => + value === 'all' + ? log.tasks + : filter(log.tasks, ({ status }) => status === value), + optionRenderer: ({ countByStatus }) => ({ label, value }) => ( - {_(label)} ({getFilteredTaskLogs(log.tasks, value).length}) + {_(label)} ({countByStatus[value] || 0}) ), + countByStatus: (_, { log = {} }) => ({ + all: get(log.tasks, 'length'), + ...countBy(log.tasks, 'status'), + }), + defaultFilter: ({ countByStatus }) => { + if (countByStatus.pending > 0) { + return PENDING_FILTER_OPTION + } + + if (countByStatus.failure > 0) { + return FAILURE_FILTER_OPTION + } + + if (countByStatus.interrupted > 0) { + return INTERRUPTED_FILTER_OPTION + } + + return ALL_FILTER_OPTION + }, }, }), injectState, - ({ log, remotes, state, effects }) => - log.result !== undefined ? ( - - - {log.result.message} + ({ log = {}, remotes, state, effects }) => { + const { status, result, scheduleId } = log + return (status === 'failure' || status === 'skipped') && + result !== undefined ? ( + + + {result.message} ) : ( @@ -154,7 +160,7 @@ export default [ optionRenderer={state.optionRenderer} options={TASK_FILTER_OPTIONS} required - value={state.filter} + value={state.filter || state.defaultFilter} valueKey='value' />
@@ -165,7 +171,7 @@ export default [ 4, 8 )}) {' '} - {log.scheduleId !== undefined && + {scheduleId !== undefined && taskLog.status === 'failure' && ( - ), + ) + }, ].reduceRight((value, decorator) => decorator(value))