From 11e308d14267286e75f03293ebf13037c6625548 Mon Sep 17 00:00:00 2001 From: Jim O'Donnell Date: Fri, 10 May 2024 14:20:24 +0100 Subject: [PATCH] fix: clear references to a task key after deleting a task A small helper function which iterates through `workflow.tasks` and deletes references to a given task key. It's called after deleting a task, so that other tasks no longer link to the deleted task. --- .../lab/helpers/removeTaskKeyFromWorkflow.js | 14 ++++++ .../helpers/removeTaskKeyFromWorkflow.spec.js | 43 +++++++++++++++++++ app/pages/lab/workflow.jsx | 7 ++- 3 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 app/pages/lab/helpers/removeTaskKeyFromWorkflow.js create mode 100644 app/pages/lab/helpers/removeTaskKeyFromWorkflow.spec.js diff --git a/app/pages/lab/helpers/removeTaskKeyFromWorkflow.js b/app/pages/lab/helpers/removeTaskKeyFromWorkflow.js new file mode 100644 index 0000000000..e43fe8fb01 --- /dev/null +++ b/app/pages/lab/helpers/removeTaskKeyFromWorkflow.js @@ -0,0 +1,14 @@ +export default function removeTaskKeyFromWorkflow(workflow, taskKey) { + const changes = {}; + Object.entries(workflow.tasks).forEach(([key, task]) => { + if (task.next === taskKey) { + changes[`tasks.${key}.next`] = ''; + } + task.answers?.forEach((answer, index) => { + if (answer.next === taskKey) { + changes[`tasks.${key}.answers.${index}.next`] = ''; + } + }); + }); + return workflow.update(changes); +} diff --git a/app/pages/lab/helpers/removeTaskKeyFromWorkflow.spec.js b/app/pages/lab/helpers/removeTaskKeyFromWorkflow.spec.js new file mode 100644 index 0000000000..74ad2e40a4 --- /dev/null +++ b/app/pages/lab/helpers/removeTaskKeyFromWorkflow.spec.js @@ -0,0 +1,43 @@ +import { expect } from 'chai'; +import sinon from 'sinon'; +import removeTaskKeyFromWorkflow from './removeTaskKeyFromWorkflow.js'; + +describe('removeTaskKeyFromWorkflow', function () { + let workflow; + + beforeEach(function () { + workflow = { + tasks: { + 'T1': { + type: 'single', + answers: [ + { label: 'Yes', next: 'T3' }, + { label: 'No', next: 'T2' } + ] + }, + 'T2': { + type: 'multiple', + next: 'T3', + answers: [ + { label: 'Blue' }, + { label: 'Green' } + ] + }, + 'T3': { + type: 'text', + next: '' + } + }, + update: sinon.stub(), + save: sinon.stub() + }; + }); + + it('should delete the selected key from each task', function () { + removeTaskKeyFromWorkflow(workflow, 'T3'); + expect(workflow.update).to.have.been.calledWith({ + 'tasks.T1.answers.0.next': '', + 'tasks.T2.next': '' + }); + }); +}); diff --git a/app/pages/lab/workflow.jsx b/app/pages/lab/workflow.jsx index e3663248fc..d1f60fb51e 100644 --- a/app/pages/lab/workflow.jsx +++ b/app/pages/lab/workflow.jsx @@ -1,16 +1,13 @@ import { Component, useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import handleInputChange from '../../lib/handle-input-change.js'; -import TriggeredModalForm from 'modal-form/triggered'; import ModalFormDialog from 'modal-form/dialog'; import apiClient from 'panoptes-client/lib/api-client'; -import ChangeListener from '../../components/change-listener.cjsx'; import RetirementRulesEditor from '../../components/retirement-rules-editor.cjsx'; import {Link} from 'react-router'; import MultiImageSubjectOptionsEditor from '../../components/multi-image-subject-options-editor.jsx'; import taskComponents from '../../classifier/tasks/index.js'; import AutoSave from '../../components/auto-save.coffee'; -import FileButton from '../../components/file-button.cjsx'; import WorkflowCreateForm from './workflow-create-form.cjsx'; import workflowActions from './actions/workflow.js'; import classnames from 'classnames'; @@ -21,6 +18,7 @@ import Tutorials from './workflow-components/tutorials.jsx'; import TaskOptions from './workflow-components/task-options.jsx'; import TaskPicker from './workflow-components/task-picker.jsx'; import TaskEditor from './workflow-components/task-editor.jsx'; +import removeTaskKeyFromWorkflow from './helpers/removeTaskKeyFromWorkflow.js'; const DEMO_SUBJECT_SET_ID = process.env.NODE_ENV === 'production' ? '6' // Cats @@ -807,8 +805,9 @@ class EditWorkflowPage extends Component { changes[`tasks.${taskKey}`] = undefined; this.props.workflow.update(changes); } + removeTaskKeyFromWorkflow(this.props.workflow, taskKey); - return this.updateFirstTask(); + return this.updateFirstTask().save(); } } }