Skip to content

Commit

Permalink
Use 'Schedule' icon if replica is scheduled
Browse files Browse the repository at this point in the history
Currently an API query needs to be made for all replicas in order to
find out if it has a schedule item enabled.
  • Loading branch information
Sergiu Miclea committed Mar 25, 2019
1 parent 1cdd7cb commit 31e3126
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 5 deletions.
19 changes: 18 additions & 1 deletion src/components/molecules/MainListItem/MainListItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type { MainItem } from '../../../types/MainItem'
import type { Execution } from '../../../types/Execution'

import arrowImage from './images/arrow.svg'
import scheduleImage from './images/schedule.svg'

const CheckboxStyled = styled(Checkbox)`
opacity: ${props => props.checked ? 1 : 0};
Expand Down Expand Up @@ -79,6 +80,14 @@ const TitleLabel = styled.div`
white-space: nowrap;
text-overflow: ellipsis;
`
const StatusWrapper = styled.div`
display: flex;
margin-top: 8px;
`
const ScheduleImage = styled.div`
${StyleProps.exactSize('16px')}
background: url('${scheduleImage}') center no-repeat;
`
const EndpointsImages = styled.div`
display: flex;
align-items: center;
Expand Down Expand Up @@ -111,6 +120,7 @@ type Props = {
selected: boolean,
useTasksRemaining?: boolean,
image: string,
showScheduleIcon?: boolean,
endpointType: (endpointId: string) => string,
onSelectedChange: (value: boolean) => void,
}
Expand Down Expand Up @@ -205,7 +215,14 @@ class MainListItem extends React.Component<Props> {
<Image image={this.props.image} />
<Title>
<TitleLabel>{this.props.item.instances[0]}</TitleLabel>
{status ? <StatusPill data-test-id={`mainListItem-statusPill-${status}`} status={status} /> : null}
<StatusWrapper>
{status ? <StatusPill
status={status}
style={{ marginRight: '8px' }}
data-test-id={`mainListItem-statusPill-${status}`}
/> : null}
{this.props.showScheduleIcon ? <ScheduleImage /> : null}
</StatusWrapper>
</Title>
{endpointImages}
{this.renderLastExecution()}
Expand Down
17 changes: 17 additions & 0 deletions src/components/molecules/MainListItem/images/schedule.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions src/components/pages/ReplicasPage/ReplicasPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,15 @@ import replicaLargeImage from './images/replica-large.svg'

import projectStore from '../../../stores/ProjectStore'
import replicaStore from '../../../stores/ReplicaStore'
import scheduleStore from '../../../stores/ScheduleStore'
import endpointStore from '../../../stores/EndpointStore'
import notificationStore from '../../../stores/NotificationStore'
import configLoader from '../../../utils/Config'

const Wrapper = styled.div``

const SCHEDULE_POLL_TIMEOUT = 10000

const BulkActions = [
{ label: 'Execute', value: 'execute' },
{ label: 'Delete', value: 'delete' },
Expand All @@ -57,6 +60,8 @@ class ReplicasPage extends React.Component<{ history: any }, State> {

pollTimeout: TimeoutID
stopPolling: boolean
schedulePolling: boolean
schedulePollTimeout: TimeoutID

componentDidMount() {
document.title = 'Coriolis Replicas'
Expand All @@ -70,6 +75,7 @@ class ReplicasPage extends React.Component<{ history: any }, State> {

componentWillUnmount() {
clearTimeout(this.pollTimeout)
clearTimeout(this.schedulePollTimeout)
this.stopPolling = true
}

Expand Down Expand Up @@ -164,10 +170,25 @@ class ReplicasPage extends React.Component<{ history: any }, State> {
}

Promise.all([replicaStore.getReplicas(), endpointStore.getEndpoints()]).then(() => {
if (!this.schedulePolling) {
this.pollSchedule()
}
this.pollTimeout = setTimeout(() => { this.pollData() }, configLoader.config.requestPollTimeout)
})
}

pollSchedule() {
if (this.state.modalIsOpen || this.stopPolling || replicaStore.replicas.length === 0) {
return
}
this.schedulePolling = true
scheduleStore.getSchedulesBulk(replicaStore.replicas.map(r => r.id)).then(() => {
this.schedulePollTimeout = setTimeout(() => {
this.pollSchedule()
}, SCHEDULE_POLL_TIMEOUT)
})
}

searchText(item: MainItem, text: ?string) {
let result = false
if (item.instances[0].toLowerCase().indexOf(text || '') > -1) {
Expand Down Expand Up @@ -196,6 +217,14 @@ class ReplicasPage extends React.Component<{ history: any }, State> {
return true
}

isReplicaScheduled(replicaId: string): boolean {
let bulkScheduleItem = scheduleStore.bulkSchedules.find(b => b.replicaId === replicaId)
if (!bulkScheduleItem) {
return false
}
return Boolean(bulkScheduleItem.schedules.find(s => s.enabled))
}

render() {
return (
<Wrapper>
Expand All @@ -216,6 +245,7 @@ class ReplicasPage extends React.Component<{ history: any }, State> {
(<MainListItem
{...options}
image={replicaItemImage}
showScheduleIcon={this.isReplicaScheduled(options.item.id)}
endpointType={id => {
let endpoint = this.getEndpoint(id)
if (endpoint) {
Expand Down
7 changes: 5 additions & 2 deletions src/sources/ScheduleSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,11 @@ class ScheduleSource {
}))
}

static getSchedules(replicaId: string): Promise<Schedule[]> {
return Api.get(`${servicesUrl.coriolis}/${Api.projectId}/replicas/${replicaId}/schedules`).then(response => {
static getSchedules(replicaId: string, opts?: { skipLog?: boolean }): Promise<Schedule[]> {
return Api.send({
url: `${servicesUrl.coriolis}/${Api.projectId}/replicas/${replicaId}/schedules`,
skipLog: opts && opts.skipLog,
}).then(response => {
let schedules = [...response.data.schedules]
schedules.forEach(s => {
if (s.expiration_date) {
Expand Down
15 changes: 13 additions & 2 deletions src/stores/ScheduleStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.

// @flow

import { observable, action } from 'mobx'
import { observable, action, runInAction } from 'mobx'

import type { Schedule } from '../types/Schedule'
import type { Schedule, ScheduleBulkItem } from '../types/Schedule'
import Source from '../sources/ScheduleSource'

const updateSchedule = (schedules, id, data) => {
Expand All @@ -36,6 +36,7 @@ const updateSchedule = (schedules, id, data) => {
class ScheduleStore {
@observable loading: boolean = false
@observable schedules: Schedule[] = []
@observable bulkSchedules: ScheduleBulkItem[] = []
@observable unsavedSchedules: Schedule[] = []
@observable scheduling: boolean = false
@observable adding: boolean = false
Expand All @@ -62,6 +63,16 @@ class ScheduleStore {
})
}

getSchedulesBulk(replicaIds: string[]): Promise<void> {
return Promise.all(replicaIds.map(replicaId => {
return Source.getSchedules(replicaId, { skipLog: true }).then(schedules => {
return { replicaId, schedules }
})
})).then(bulkSchedules => {
runInAction(() => { this.bulkSchedules = bulkSchedules })
})
}

@action addSchedule(replicaId: string, schedule: Schedule): Promise<void> {
this.adding = true

Expand Down
5 changes: 5 additions & 0 deletions src/types/Schedule.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,8 @@ export type Schedule = {
expiration_date?: Date,
shutdown_instances?: boolean,
}

export type ScheduleBulkItem = {
replicaId: string,
schedules: Schedule[],
}

0 comments on commit 31e3126

Please sign in to comment.