feat(xo-web/jobs/overview): use SortedTable (#2677)

See #2416
This commit is contained in:
Rajaa.BARHTAOUI 2018-03-27 16:56:56 +02:00 committed by Pierre Donias
parent 53f470518b
commit 0b9d031965
2 changed files with 113 additions and 103 deletions

View File

@ -256,6 +256,7 @@ const messages = {
jobMergedDataSpeed: 'Merge speed:',
allJobCalls: 'All',
job: 'Job',
jobEdit: 'Edit job',
jobModalTitle: 'Job {job}',
jobId: 'ID',
jobType: 'Type',
@ -290,11 +291,12 @@ const messages = {
'You are editing Schedule {name} ({id}). Saving will override previous schedule state.',
jobEditMessage:
'You are editing job {name} ({id}). Saving will override previous job state.',
scheduleEdit: 'Edit',
scheduleEdit: 'Edit schedule',
scheduleSave: 'Save',
cancelScheduleEdition: 'Cancel',
scheduleAdd: 'Add a schedule',
scheduleDelete: 'Delete',
scheduleRun: 'Run schedule',
deleteSelectedSchedules: 'Delete selected schedules',
noScheduledJobs: 'No scheduled jobs.',
newSchedule: 'New schedule',
@ -1160,7 +1162,6 @@ const messages = {
scheduleTimezone: 'Timezone',
scheduleExportRetention: 'Export ret.',
scheduleSnapshotRetention: 'Snapshot ret.',
scheduleRun: 'Run',
getRemote: 'Get remote',
listRemote: 'List Remote',
simpleBackup: 'simple',

View File

@ -1,14 +1,9 @@
import _ from 'intl'
import ActionRowButton from 'action-row-button'
import filter from 'lodash/filter'
import find from 'lodash/find'
import forEach from 'lodash/forEach'
import Icon from 'icon'
import Link from 'link'
import LogList from '../../logs'
import map from 'lodash/map'
import orderBy from 'lodash/orderBy'
import React, { Component } from 'react'
import SortedTable from 'sorted-table'
import StateButton from 'state-button'
import Tooltip from 'tooltip'
import Upgrade from 'xoa-upgrade'
@ -16,8 +11,10 @@ import { addSubscriptions } from 'utils'
import { Container } from 'grid'
import { createSelector } from 'selectors'
import { Card, CardHeader, CardBlock } from 'card'
import { filter, find, forEach, orderBy } from 'lodash'
import {
deleteSchedule,
deleteSchedules,
disableSchedule,
enableSchedule,
runJob,
@ -32,12 +29,88 @@ const jobKeyToLabel = {
genericTask: _('customJob'),
}
const SCHEDULES_COLUMNS = [
{
itemRenderer: schedule => (
<span>{`${schedule.name} (${schedule.id.slice(4, 8)})`}</span>
),
name: _('schedule'),
sortCriteria: 'name',
},
{
itemRenderer: (schedule, { jobs, isScheduleUserMissing }) => {
const jobId = schedule.jobId
const job = jobs[jobId]
return (
job !== undefined && (
<div>
<span>{`${job.name} - ${job.method} (${jobId.slice(4, 8)})`}</span>{' '}
{isScheduleUserMissing[schedule.id] && (
<Tooltip content={_('jobUserNotFound')}>
<Icon className='mr-1' icon='error' />
</Tooltip>
)}
<Link
className='btn btn-sm btn-primary ml-1'
to={`/jobs/${job.id}/edit`}
>
<Tooltip content={_('jobEdit')}>
<Icon icon='edit' />
</Tooltip>
</Link>
</div>
)
)
},
name: _('job'),
sortCriteria: (schedule, { jobs }) => {
const job = jobs[schedule.jobId]
return job !== undefined && job.name
},
},
{
itemRenderer: schedule => schedule.cron,
name: _('jobScheduling'),
},
{
itemRenderer: schedule => (
<StateButton
disabledLabel={_('jobStateDisabled')}
disabledHandler={enableSchedule}
disabledTooltip={_('logIndicationToEnable')}
enabledLabel={_('jobStateEnabled')}
enabledHandler={disableSchedule}
enabledTooltip={_('logIndicationToDisable')}
handlerParam={schedule.id}
state={schedule.enabled}
/>
),
name: _('jobState'),
},
]
const ACTIONS = [
{
handler: deleteSchedules,
icon: 'delete',
individualHandler: deleteSchedule,
individualLabel: _('scheduleDelete'),
label: _('deleteSelectedSchedules'),
level: 'danger',
},
]
// ===================================================================
@addSubscriptions({
users: subscribeUsers,
})
export default class Overview extends Component {
static contextTypes = {
router: React.PropTypes.object,
}
constructor (props) {
super(props)
this.state = {
@ -82,31 +155,6 @@ export default class Overview extends Component {
return jobs[schedule.jobId]
}
_getJobLabel (job = {}) {
return `${job.name} - ${job.method} (${job.id.slice(4, 8)})`
}
_getScheduleLabel (schedule) {
return `${schedule.name} (${schedule.id.slice(4, 8)})`
}
_getScheduleToggle (schedule) {
const { id } = schedule
return (
<StateButton
disabledLabel={_('jobStateDisabled')}
disabledHandler={enableSchedule}
disabledTooltip={_('logIndicationToEnable')}
enabledLabel={_('jobStateEnabled')}
enabledHandler={disableSchedule}
enabledTooltip={_('logIndicationToDisable')}
handlerParam={id}
state={schedule.enabled}
/>
)
}
_getIsScheduleUserMissing = createSelector(
() => this.state.schedules,
() => this.props.users,
@ -114,7 +162,7 @@ export default class Overview extends Component {
const isScheduleUserMissing = {}
forEach(schedules, schedule => {
isScheduleUserMissing[schedule.id] = !!find(
isScheduleUserMissing[schedule.id] = !find(
users,
user => user.id === this._getScheduleJob(schedule).userId
)
@ -124,11 +172,29 @@ export default class Overview extends Component {
}
)
_individualActions = [
{
disabled: (schedule, { isScheduleUserMissing }) =>
isScheduleUserMissing[schedule.id],
handler: schedule => runJob(schedule.jobId),
icon: 'run-schedule',
label: _('scheduleRun'),
level: 'warning',
},
{
handler: schedule =>
this.context.router.push({
pathname: `/jobs/schedules/${schedule.id}/edit`,
}),
icon: 'edit',
label: _('scheduleEdit'),
level: 'primary',
},
]
render () {
const { schedules } = this.state
const isScheduleUserMissing = this._getIsScheduleUserMissing()
return process.env.XOA_PLAN > 3 ? (
<Container>
<Card>
@ -136,73 +202,16 @@ export default class Overview extends Component {
<Icon icon='schedule' /> {_('backupSchedules')}
</CardHeader>
<CardBlock>
{schedules.length ? (
<table className='table'>
<thead className='thead-default'>
<tr>
<th>{_('schedule')}</th>
<th>{_('job')}</th>
<th className='hidden-xs-down'>{_('jobScheduling')}</th>
<th>{_('jobState')}</th>
<th className='text-xs-right'>{_('jobAction')}</th>
</tr>
</thead>
<tbody>
{map(schedules, (schedule, key) => {
const job = this._getScheduleJob(schedule)
return (
<tr key={key}>
<td>
{this._getScheduleLabel(schedule)}
<Link
className='btn btn-sm btn-primary ml-1'
to={`/jobs/schedules/${schedule.id}/edit`}
>
<Icon icon='edit' />
</Link>
</td>
<td>
{this._getJobLabel(job)}
<Link
className='btn btn-sm btn-primary ml-1'
to={`/jobs/${job.id}/edit`}
>
<Icon icon='edit' />
</Link>
</td>
<td className='hidden-xs-down'>{schedule.cron}</td>
<td>{this._getScheduleToggle(schedule)}</td>
<td className='text-xs-right'>
<fieldset>
{!isScheduleUserMissing[schedule.id] && (
<Tooltip content={_('jobUserNotFound')}>
<Icon className='mr-1' icon='error' />
</Tooltip>
)}
<ActionRowButton
icon='delete'
btnStyle='danger'
handler={deleteSchedule}
handlerParam={schedule}
/>
<ActionRowButton
disabled={!isScheduleUserMissing[schedule.id]}
icon='run-schedule'
btnStyle='warning'
handler={runJob}
handlerParam={schedule.jobId}
/>
</fieldset>
</td>
</tr>
)
})}
</tbody>
</table>
) : (
<p>{_('noScheduledJobs')}</p>
)}
<SortedTable
actions={ACTIONS}
collection={schedules}
columns={SCHEDULES_COLUMNS}
data-isScheduleUserMissing={this._getIsScheduleUserMissing()}
data-jobs={this.state.jobs || {}}
individualActions={this._individualActions}
shortcutsTarget='body'
stateUrlParam='s'
/>
</CardBlock>
</Card>
<LogList jobKeys={Object.keys(jobKeyToLabel)} />