Skip to content

Commit da1251e

Browse files
authored
Merge pull request #352 from smiclea/CORWEB-196
Use 'Schedule' icon if replica is scheduled CORWEB-196
2 parents 1cdd7cb + 997aac5 commit da1251e

7 files changed

Lines changed: 95 additions & 5 deletions

File tree

src/components/molecules/MainListItem/MainListItem.jsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import type { MainItem } from '../../../types/MainItem'
2828
import type { Execution } from '../../../types/Execution'
2929

3030
import arrowImage from './images/arrow.svg'
31+
import scheduleImage from './images/schedule.svg'
3132

3233
const CheckboxStyled = styled(Checkbox)`
3334
opacity: ${props => props.checked ? 1 : 0};
@@ -79,6 +80,14 @@ const TitleLabel = styled.div`
7980
white-space: nowrap;
8081
text-overflow: ellipsis;
8182
`
83+
const StatusWrapper = styled.div`
84+
display: flex;
85+
margin-top: 8px;
86+
`
87+
const ScheduleImage = styled.div`
88+
${StyleProps.exactSize('16px')}
89+
background: url('${scheduleImage}') center no-repeat;
90+
`
8291
const EndpointsImages = styled.div`
8392
display: flex;
8493
align-items: center;
@@ -111,6 +120,7 @@ type Props = {
111120
selected: boolean,
112121
useTasksRemaining?: boolean,
113122
image: string,
123+
showScheduleIcon?: boolean,
114124
endpointType: (endpointId: string) => string,
115125
onSelectedChange: (value: boolean) => void,
116126
}
@@ -205,7 +215,18 @@ class MainListItem extends React.Component<Props> {
205215
<Image image={this.props.image} />
206216
<Title>
207217
<TitleLabel>{this.props.item.instances[0]}</TitleLabel>
208-
{status ? <StatusPill data-test-id={`mainListItem-statusPill-${status}`} status={status} /> : null}
218+
<StatusWrapper>
219+
{status ? <StatusPill
220+
status={status}
221+
style={{ marginRight: '8px' }}
222+
data-test-id={`mainListItem-statusPill-${status}`}
223+
/> : null}
224+
{this.props.showScheduleIcon ? (
225+
<ScheduleImage
226+
data-tip="The Replica has scheduling enabled and will execute automatically"
227+
/>
228+
) : null}
229+
</StatusWrapper>
209230
</Title>
210231
{endpointImages}
211232
{this.renderLastExecution()}
Lines changed: 17 additions & 0 deletions
Loading

src/components/organisms/MainList/MainList.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import styled from 'styled-components'
2020

2121
import StatusImage from '../../atoms/StatusImage'
2222
import Button from '../../atoms/Button'
23+
import Tooltip from '../../atoms/Tooltip'
2324

2425
import type { MainItem } from '../../../types/MainItem'
2526
import Palette from '../../styleUtils/Palette'
@@ -184,6 +185,8 @@ class MainList extends React.Component<Props> {
184185
<Wrapper>
185186
{this.props.loading || this.props.items.length === 0 || this.props.showEmptyList ? <Separator /> : null}
186187
{renderContent()}
188+
<Tooltip />
189+
{setTimeout(() => { Tooltip.rebuild() }, 500)}
187190
</Wrapper>
188191
)
189192
}

src/components/pages/ReplicasPage/ReplicasPage.jsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,15 @@ import replicaLargeImage from './images/replica-large.svg'
3131

3232
import projectStore from '../../../stores/ProjectStore'
3333
import replicaStore from '../../../stores/ReplicaStore'
34+
import scheduleStore from '../../../stores/ScheduleStore'
3435
import endpointStore from '../../../stores/EndpointStore'
3536
import notificationStore from '../../../stores/NotificationStore'
3637
import configLoader from '../../../utils/Config'
3738

3839
const Wrapper = styled.div``
3940

41+
const SCHEDULE_POLL_TIMEOUT = 10000
42+
4043
const BulkActions = [
4144
{ label: 'Execute', value: 'execute' },
4245
{ label: 'Delete', value: 'delete' },
@@ -57,6 +60,8 @@ class ReplicasPage extends React.Component<{ history: any }, State> {
5760

5861
pollTimeout: TimeoutID
5962
stopPolling: boolean
63+
schedulePolling: boolean
64+
schedulePollTimeout: TimeoutID
6065

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

7176
componentWillUnmount() {
7277
clearTimeout(this.pollTimeout)
78+
clearTimeout(this.schedulePollTimeout)
7379
this.stopPolling = true
7480
}
7581

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

166172
Promise.all([replicaStore.getReplicas(), endpointStore.getEndpoints()]).then(() => {
173+
if (!this.schedulePolling) {
174+
this.pollSchedule()
175+
}
167176
this.pollTimeout = setTimeout(() => { this.pollData() }, configLoader.config.requestPollTimeout)
168177
})
169178
}
170179

180+
pollSchedule() {
181+
if (this.state.modalIsOpen || this.stopPolling || replicaStore.replicas.length === 0) {
182+
return
183+
}
184+
this.schedulePolling = true
185+
scheduleStore.getSchedulesBulk(replicaStore.replicas.map(r => r.id)).then(() => {
186+
this.schedulePollTimeout = setTimeout(() => {
187+
this.pollSchedule()
188+
}, SCHEDULE_POLL_TIMEOUT)
189+
})
190+
}
191+
171192
searchText(item: MainItem, text: ?string) {
172193
let result = false
173194
if (item.instances[0].toLowerCase().indexOf(text || '') > -1) {
@@ -196,6 +217,14 @@ class ReplicasPage extends React.Component<{ history: any }, State> {
196217
return true
197218
}
198219

220+
isReplicaScheduled(replicaId: string): boolean {
221+
let bulkScheduleItem = scheduleStore.bulkSchedules.find(b => b.replicaId === replicaId)
222+
if (!bulkScheduleItem) {
223+
return false
224+
}
225+
return Boolean(bulkScheduleItem.schedules.find(s => s.enabled))
226+
}
227+
199228
render() {
200229
return (
201230
<Wrapper>
@@ -216,6 +245,7 @@ class ReplicasPage extends React.Component<{ history: any }, State> {
216245
(<MainListItem
217246
{...options}
218247
image={replicaItemImage}
248+
showScheduleIcon={this.isReplicaScheduled(options.item.id)}
219249
endpointType={id => {
220250
let endpoint = this.getEndpoint(id)
221251
if (endpoint) {

src/sources/ScheduleSource.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,11 @@ class ScheduleSource {
5656
}))
5757
}
5858

59-
static getSchedules(replicaId: string): Promise<Schedule[]> {
60-
return Api.get(`${servicesUrl.coriolis}/${Api.projectId}/replicas/${replicaId}/schedules`).then(response => {
59+
static getSchedules(replicaId: string, opts?: { skipLog?: boolean }): Promise<Schedule[]> {
60+
return Api.send({
61+
url: `${servicesUrl.coriolis}/${Api.projectId}/replicas/${replicaId}/schedules`,
62+
skipLog: opts && opts.skipLog,
63+
}).then(response => {
6164
let schedules = [...response.data.schedules]
6265
schedules.forEach(s => {
6366
if (s.expiration_date) {

src/stores/ScheduleStore.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
1414

1515
// @flow
1616

17-
import { observable, action } from 'mobx'
17+
import { observable, action, runInAction } from 'mobx'
1818

19-
import type { Schedule } from '../types/Schedule'
19+
import type { Schedule, ScheduleBulkItem } from '../types/Schedule'
2020
import Source from '../sources/ScheduleSource'
2121

2222
const updateSchedule = (schedules, id, data) => {
@@ -36,6 +36,7 @@ const updateSchedule = (schedules, id, data) => {
3636
class ScheduleStore {
3737
@observable loading: boolean = false
3838
@observable schedules: Schedule[] = []
39+
@observable bulkSchedules: ScheduleBulkItem[] = []
3940
@observable unsavedSchedules: Schedule[] = []
4041
@observable scheduling: boolean = false
4142
@observable adding: boolean = false
@@ -62,6 +63,16 @@ class ScheduleStore {
6263
})
6364
}
6465

66+
getSchedulesBulk(replicaIds: string[]): Promise<void> {
67+
return Promise.all(replicaIds.map(replicaId => {
68+
return Source.getSchedules(replicaId, { skipLog: true }).then(schedules => {
69+
return { replicaId, schedules }
70+
})
71+
})).then(bulkSchedules => {
72+
runInAction(() => { this.bulkSchedules = bulkSchedules })
73+
})
74+
}
75+
6576
@action addSchedule(replicaId: string, schedule: Schedule): Promise<void> {
6677
this.adding = true
6778

src/types/Schedule.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,8 @@ export type Schedule = {
2929
expiration_date?: Date,
3030
shutdown_instances?: boolean,
3131
}
32+
33+
export type ScheduleBulkItem = {
34+
replicaId: string,
35+
schedules: Schedule[],
36+
}

0 commit comments

Comments
 (0)