From 04a4bbe66b393caea0499d0e028563d1148f14c0 Mon Sep 17 00:00:00 2001 From: "Shaun A. Noordin" Date: Mon, 8 Apr 2024 17:27:06 +0100 Subject: [PATCH] Pages Editor: rebuild "Next Page" logic. Add placeholder answers. (#7055) * pages-editor-pt17: debug, show step.next * Add SimpleNextControls. Rename BranchingControls. * Refactor: separate NextStepArrow. SimpleNextControls: test functionality * SimpleNextControls: add and populate 'next page' dropdown * TasksPage: add second QuickSetup debug feature * BranchingNextControls: move from Step to Task * TaskItem: add PlaceholderAnswers subcomponent * TasksPage: rename updateAnswerNext() * TasksPage: implement updateNextStepForStep() * Remove automatic linking of steps/pages * cleanupTasksAndSteps: now also removes orphaned references in step.next --- .../components/TasksPage/TasksPage.jsx | 79 ++++++++++++++++--- ...Controls.jsx => BranchingNextControls.jsx} | 47 ++++------- .../components/StepItem/NextStepArrow.jsx | 26 ++++++ .../StepItem/SimpleNextControls.jsx | 52 ++++++++++++ .../components/StepItem/StepItem.jsx | 24 +++--- .../components/StepItem/TaskItem.jsx | 55 ++++++++++++- .../helpers/cleanupTasksAndSteps.js | 23 ++++-- css/lab-pages-editor.styl | 73 +++++++++++------ 8 files changed, 292 insertions(+), 87 deletions(-) rename app/pages/lab-pages-editor/components/TasksPage/components/StepItem/{BranchingControls.jsx => BranchingNextControls.jsx} (54%) create mode 100644 app/pages/lab-pages-editor/components/TasksPage/components/StepItem/NextStepArrow.jsx create mode 100644 app/pages/lab-pages-editor/components/TasksPage/components/StepItem/SimpleNextControls.jsx diff --git a/app/pages/lab-pages-editor/components/TasksPage/TasksPage.jsx b/app/pages/lab-pages-editor/components/TasksPage/TasksPage.jsx index 403f68dea0..a49900fa43 100644 --- a/app/pages/lab-pages-editor/components/TasksPage/TasksPage.jsx +++ b/app/pages/lab-pages-editor/components/TasksPage/TasksPage.jsx @@ -4,7 +4,6 @@ import createStep from '../../helpers/createStep.js'; import createTask from '../../helpers/createTask.js'; import getNewStepKey from '../../helpers/getNewStepKey.js'; import getNewTaskKey from '../../helpers/getNewTaskKey.js'; -import linkStepsInWorkflow from '../../helpers/linkStepsInWorkflow.js'; import moveItemInArray from '../../helpers/moveItemInArray.js'; import cleanupTasksAndSteps from '../../helpers/cleanupTasksAndSteps.js'; import getPreviewEnv from '../../helpers/getPreviewEnv.js'; @@ -39,7 +38,7 @@ export default function TasksPage() { ...workflow.tasks, [newTaskKey]: newTask }; - const steps = linkStepsInWorkflow([...workflow.steps, newStep]); + const steps = [...workflow.steps, newStep]; await update({ tasks, steps }); return steps.length - 1; @@ -57,9 +56,9 @@ export default function TasksPage() { tasks: { 'T0': { answers: [ - {next: "P1", label: "Animals"}, - {next: "P2", label: "Fruits"}, - {label: "Neither"} + {next: 'P1', label: 'Animals'}, + {next: 'P2', label: 'Fruits'}, + {label: 'Neither'} ], help: '', question: 'Do you like Animals or Fruits?', @@ -70,18 +69,56 @@ export default function TasksPage() { 'T2': { help: '', type: 'text', required: false, instruction: 'Which fruit?' } }, steps: [ - ['P0', { next: 'P1', stepKey: 'P0', taskKeys: ["T0"] }], + ['P0', { stepKey: 'P0', taskKeys: ["T0"] }], ['P1', { next: 'P2', stepKey: 'P1', taskKeys: ["T1"] }], ['P2', { stepKey: 'P2', taskKeys: ["T2"] }] ] }); } + function experimentalQuickSetupBranching() { + update({ + tasks: { + 'T1.1': { + answers: [ + {next: 'P2', label: 'Go to the 🔴 RED page'}, + {next: 'P3', label: 'Go to the 🔵 BLUE page'}, + ], + help: '', + question: 'Oh dear, this page has multiple branching tasks. Let\'s see what happens', + required: false, + type: 'single' + }, + 'T1.2': { + answers: [ + {next: 'P4', label: 'Go to the 🟡 YELLOW page'}, + {next: 'P5', label: 'Go to the 🟢 GREEN page'}, + ], + help: '', + question: 'This is the second branching task. If you answer both on the page, where do you branch to?', + required: false, + type: 'single' + }, + 'T2': { help: '', type: 'text', required: false, instruction: 'Welcome to the 🔴 RED page! How do you feel?' }, + 'T3': { help: '', type: 'text', required: false, instruction: 'Welcome to the 🔵 BLUE page! How do you feel?' }, + 'T4': { help: '', type: 'text', required: false, instruction: 'Welcome to the 🟡 YELLOW page! How do you feel?' }, + 'T5': { help: '', type: 'text', required: false, instruction: 'Welcome to the 🟢 GREEN page! How do you feel?' }, + }, + steps: [ + ['P1', { stepKey: 'P1', taskKeys: ['T1.1', 'T1.2'] }], + ['P2', { stepKey: 'P2', taskKeys: ['T2'] }], + ['P3', { stepKey: 'P3', taskKeys: ['T3'] }], + ['P4', { stepKey: 'P4', taskKeys: ['T4'] }], + ['P5', { stepKey: 'P5', taskKeys: ['T5'] }], + ] + }); + } + function moveStep(from, to) { const oldSteps = workflow?.steps || []; if (from < 0 || to < 0 || from >= oldSteps.length || to >= oldSteps.length) return; - const steps = linkStepsInWorkflow(moveItemInArray(oldSteps, from, to)); + const steps = moveItemInArray(oldSteps, from, to); update({ steps }); } @@ -124,8 +161,21 @@ export default function TasksPage() { update({tasks}); } + // Changes the optional "next page" of a step/page + function updateNextStepForStep(stepKey, next = undefined) { + // Check if input is valid + const stepIndex = workflow?.steps?.findIndex(step => step[0] === stepKey); + const stepBody = workflow?.steps?.[stepIndex]?.[1]; + if (!stepBody) return; + + const newSteps = workflow.steps.slice(); + newSteps[stepIndex] = [stepKey, { ...stepBody, next }]; + + update({ steps: newSteps }); + } + // Changes the optional "next page" of a branching answer/choice - function updateAnswerNext(taskKey, answerIndex, next = undefined) { + function updateNextStepForTaskAnswer(taskKey, answerIndex, next = undefined) { // Check if input is valid const task = workflow?.tasks?.[taskKey]; const answer = task?.answers[answerIndex]; @@ -185,7 +235,8 @@ export default function TasksPage() { step={step} stepKey={step[0]} stepIndex={index} - updateAnswerNext={updateAnswerNext} + updateNextStepForStep={updateNextStepForStep} + updateNextStepForTaskAnswer={updateNextStepForTaskAnswer} /> ))} @@ -225,7 +276,15 @@ export default function TasksPage() { type="button" style={{ margin: '0 4px' }} > - QUICK SETUP + QUICK SETUP (simple) + + diff --git a/app/pages/lab-pages-editor/components/TasksPage/components/StepItem/BranchingControls.jsx b/app/pages/lab-pages-editor/components/TasksPage/components/StepItem/BranchingNextControls.jsx similarity index 54% rename from app/pages/lab-pages-editor/components/TasksPage/components/StepItem/BranchingControls.jsx rename to app/pages/lab-pages-editor/components/TasksPage/components/StepItem/BranchingNextControls.jsx index d0a33c334c..9ca96a5248 100644 --- a/app/pages/lab-pages-editor/components/TasksPage/components/StepItem/BranchingControls.jsx +++ b/app/pages/lab-pages-editor/components/TasksPage/components/StepItem/BranchingNextControls.jsx @@ -1,10 +1,13 @@ +import PropTypes from 'prop-types'; +import NextStepArrow from './NextStepArrow.jsx'; + const DEFAULT_HANDLER = () => {}; -export default function BranchingControls({ +export default function BranchingNextControls({ allSteps = [], task, taskKey, - updateAnswerNext = DEFAULT_HANDLER + updateNextStepForTaskAnswer = DEFAULT_HANDLER }) { if (!task || !taskKey) return null; @@ -13,13 +16,13 @@ export default function BranchingControls({ function onChange(e) { const next = e.target?.value; const index = e?.target?.dataset.index; - updateAnswerNext(taskKey, index, next); + updateNextStepForTaskAnswer(taskKey, index, next); } return ( -