Skip to content

Commit 8412607

Browse files
authored
fix: update tasks cloning to include labels (#3944)
1 parent 600f1d3 commit 8412607

File tree

3 files changed

+101
-41
lines changed

3 files changed

+101
-41
lines changed

cypress/e2e/shared/tasks.test.ts

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -211,26 +211,47 @@ from(bucket: "defbuck")
211211
})
212212

213213
it('can clone a task and activate just the cloned one', () => {
214-
createTask('task1', 'buckets()')
214+
const firstLabel = 'very important task'
215+
const secondLabel = 'mission critical'
215216

216-
cy.getByTestID('task-card')
217-
.eq(1)
218-
.then(() => {
219-
cy.getByTestID('context-menu-task')
220-
.eq(1)
221-
.click()
222-
cy.getByTestID('context-clone-task').click()
223-
})
217+
cy.get('button.cf-button[title="Add labels"]').click()
218+
cy.getByTestID('inline-labels--popover--dialog').should('be.visible')
219+
cy.getByTestID('inline-labels--popover-field').type(
220+
`${firstLabel}{enter}`
221+
)
222+
cy.getByTestID('overlay--container').should('be.visible')
223+
cy.getByTestID('create-label-form--submit').click()
224224

225+
cy.getByTestID('overlay--container').should('not.exist')
226+
cy.get('button.cf-button[title="Add labels"]').click()
227+
cy.getByTestID('inline-labels--popover--dialog').should('be.visible')
228+
cy.getByTestID('inline-labels--popover-field').type(
229+
`${secondLabel}{enter}`
230+
)
231+
cy.getByTestID('overlay--container').should('be.visible')
232+
cy.getByTestID('create-label-form--submit').click()
233+
234+
// ensure the two labels are present before cloning
235+
cy.getByTestID('overlay--container').should('not.exist')
236+
cy.getByTestID(`label--pill ${firstLabel}`).should('be.visible')
237+
cy.getByTestID(`label--pill ${secondLabel}`).should('be.visible')
238+
239+
// clone the task
240+
cy.getByTestID('context-menu-task').click()
241+
cy.getByTestID('context-clone-task').click()
242+
cy.getByTestID('task-card--slide-toggle').should('have.length', 2)
243+
cy.getByTestID(`label--pill ${firstLabel}`).should('have.length', 2)
244+
cy.getByTestID(`label--pill ${secondLabel}`).should('have.length', 2)
245+
246+
// disable the first task
225247
cy.getByTestID('task-card--slide-toggle')
226248
.eq(0)
227249
.should('have.class', 'active')
228250
cy.getByTestID('task-card--slide-toggle')
229251
.eq(0)
230252
.click()
231-
cy.getByTestID('task-card--slide-toggle')
232-
.eq(0)
233-
.should('not.have.class', 'active')
253+
254+
// only the clone should be active
234255
cy.getByTestID('task-card--slide-toggle')
235256
.eq(1)
236257
.should('have.class', 'active')
@@ -688,22 +709,3 @@ from(bucket: "defbuck")
688709
})
689710
})
690711
})
691-
692-
const createTask = (
693-
name: string,
694-
task: string,
695-
every = '3h',
696-
offset = '20m'
697-
) => {
698-
cy.getByTestID('create-task--button')
699-
.first()
700-
.click()
701-
702-
cy.getByTestID('flux-editor').monacoType(task)
703-
704-
cy.getByTestIDAndSetInputValue('task-form-name', name)
705-
cy.getByTestIDAndSetInputValue('task-form-offset-input', offset)
706-
cy.getByTestIDAndSetInputValue('task-form-schedule-input', every)
707-
cy.getByTestID('task-save-btn').click()
708-
cy.getByTestID('notification-success--dismiss').click()
709-
}

src/tasks/actions/thunks.ts

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,60 @@ export const deleteTask = (taskID: string) => async (
305305
}
306306
}
307307

308+
const cloneTaskLabels = (sourceTask: Task, destinationTask: Task) => async (
309+
dispatch: Dispatch<Action>
310+
) => {
311+
try {
312+
const pendingLabels = sourceTask.labels.map(labelID =>
313+
api.postTasksLabel({
314+
taskID: destinationTask.id,
315+
data: {labelID},
316+
})
317+
)
318+
319+
const mappedLabels = await Promise.all(pendingLabels)
320+
321+
if (
322+
mappedLabels.length &&
323+
mappedLabels.some(label => label.status !== 201)
324+
) {
325+
throw new Error('An error occurred cloning the labels for this task')
326+
}
327+
328+
dispatch(notify(copy.taskCloneSuccess(sourceTask.name)))
329+
} catch {
330+
dispatch(notify(copy.addTaskLabelFailed()))
331+
}
332+
}
333+
334+
const refreshTask = (task: Task) => async (dispatch: Dispatch<Action>) => {
335+
try {
336+
const response = await api.getTask({
337+
taskID: task.id,
338+
})
339+
340+
if (response.status !== 200) {
341+
throw new Error(response.data.message)
342+
}
343+
344+
const refreshedTask = response.data
345+
346+
const normTask = normalize<Task, TaskEntities, string>(
347+
refreshedTask,
348+
taskSchema
349+
)
350+
dispatch(addTask(normTask))
351+
} catch {
352+
dispatch(notify(copy.taskNotFound(task.name)))
353+
}
354+
}
355+
308356
export const cloneTask = (task: Task) => async (
309357
dispatch: Dispatch<Action>,
310358
getState: GetState
311359
) => {
360+
let newTask: Task
361+
312362
try {
313363
const state = getState()
314364
const resp = await api.getTask({taskID: task.id})
@@ -350,24 +400,19 @@ export const cloneTask = (task: Task) => async (
350400

351401
const fluxWithNewName = format_from_js_file(ast)
352402

353-
const newTask = await api.postTask({
403+
const newTaskResponse = await api.postTask({
354404
data: {
355405
...resp.data,
356406
flux: fluxWithNewName,
357407
},
358408
})
359409

360-
if (newTask.status !== 201) {
361-
throw new Error(newTask.data.message)
410+
if (newTaskResponse.status !== 201) {
411+
throw new Error(newTaskResponse.data.message)
362412
}
363413

364-
const normTask = normalize<Task, TaskEntities, string>(
365-
newTask.data,
366-
taskSchema
367-
)
414+
newTask = newTaskResponse.data as Task
368415

369-
dispatch(notify(copy.taskCloneSuccess(task.name)))
370-
dispatch(addTask(normTask))
371416
dispatch(checkTaskLimits())
372417
} catch (error) {
373418
console.error(error)
@@ -378,6 +423,12 @@ export const cloneTask = (task: Task) => async (
378423
dispatch(notify(copy.taskCloneFailed(task.name, message)))
379424
}
380425
}
426+
427+
// clone the labels
428+
cloneTaskLabels(task, newTask)(dispatch)
429+
430+
// get the updated task
431+
refreshTask(newTask)(dispatch)
381432
}
382433

383434
export const selectTaskByID = (id: string) => async (

src/tasks/containers/TasksPage.test.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,14 @@ jest.mock('src/client', () => ({
9393
status: 200,
9494
}
9595
}),
96-
getTask: jest.fn(() => {
96+
getTask: jest.fn(({taskID}) => {
97+
if (taskID === replacementID) {
98+
return {
99+
data: {...InactiveTask, id: replacementID, name: replacementName},
100+
headers: {},
101+
status: 200,
102+
}
103+
}
97104
return {
98105
data: InactiveTask,
99106
headers: {},

0 commit comments

Comments
 (0)