Skip to content

Commit

Permalink
Pages Editor: add "Choose Starting Page" dropdown (zooniverse#7088)
Browse files Browse the repository at this point in the history
* pages-editor-pt21: reorganise WorkflowHeader, now has preview link

* WorkflowHeader: minor restyle

* WorkflowHeader: minor restyle

* TasksPage: replace preview link with 'choose starting page' dropdown

* TasksPage: update list of starting pages

* TasksPage: implement choose starting page

* TasksPage: setting Starting Page will now just rearrange Steps

* TasksPage: restyle starting page dropdown

* TasksPage: hide 'choose starting page' dropdown if 0 steps
  • Loading branch information
shaunanoordin authored May 17, 2024
1 parent 229aeab commit d270c1a
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ export default function ExperimentalPanel({
}) {
function experimentalReset() {
update({
first_task: '',
tasks: {},
steps: []
});
}

function experimentalQuickSetup() {
update({
first_task: '',
tasks: {
'T0': {
answers: [
Expand Down
45 changes: 30 additions & 15 deletions app/pages/lab-pages-editor/components/TasksPage/TasksPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,20 @@ import getNewStepKey from '../../helpers/getNewStepKey.js';
import getNewTaskKey from '../../helpers/getNewTaskKey.js';
import moveItemInArray from '../../helpers/moveItemInArray.js';
import cleanupTasksAndSteps from '../../helpers/cleanupTasksAndSteps.js';
import getPreviewEnv from '../../helpers/getPreviewEnv.js';
// import strings from '../../strings.json'; // TODO: move all text into strings

import ExperimentalPanel from './ExperimentalPanel.jsx';
import EditStepDialog from './components/EditStepDialog';
import NewTaskDialog from './components/NewTaskDialog.jsx';
import StepItem from './components/StepItem';
import ExternalLinkIcon from '../../icons/ExternalLinkIcon.jsx';

export default function TasksPage() {
const { project, workflow, update } = useWorkflowContext();
const { workflow, update } = useWorkflowContext();
const editStepDialog = useRef(null);
const newTaskDialog = useRef(null);
const [ activeStepIndex, setActiveStepIndex ] = useState(-1); // Tracks which Step is being edited.
const [ activeDragItem, setActiveDragItem ] = useState(-1); // Keeps track of active item being dragged (StepItem). This is because "dragOver" CAN'T read the data from dragEnter.dataTransfer.getData().
const firstStepKey = workflow?.steps?.[0]?.[0] || '';
const isActive = true; // TODO

/*
Expand Down Expand Up @@ -156,6 +155,13 @@ export default function TasksPage() {
setActiveStepIndex(-1);
}

function handleChangeStartingPage(e) {
const targetStepKey = e?.target?.value || '';
const targetStepIndex = workflow?.steps?.findIndex(([stepKey]) => stepKey === targetStepKey) || -1;
if (targetStepIndex < 0) return;
moveStep(targetStepIndex, 0);
}

// Changes the optional "next page" of a step/page
function updateNextStepForStep(stepKey, next = undefined) {
if (!workflow || !workflow.steps) return;
Expand Down Expand Up @@ -201,15 +207,14 @@ export default function TasksPage() {
stepHasOneTask: activeStep?.[1]?.taskKeys?.length > 0,
stepHasManyTasks: activeStep?.[1]?.taskKeys?.length > 1
}
const previewEnv = getPreviewEnv();
const previewUrl = `https://frontend.preview.zooniverse.org/projects/${project?.slug}/classify/workflow/${workflow?.id}${previewEnv}`;

if (!workflow) return null;

return (
<div className="tasks-page">
<div className="workflow-title flex-row">
<h2 className="flex-item">{workflow?.display_name}</h2>
<span className="workflow-id">{`#${workflow?.id}`}</span>
<h2 className="flex-item">{workflow.display_name}</h2>
<span className="workflow-id">{`#${workflow.id}`}</span>
{(isActive) ? <span className="status-active">Active</span> : <span className="status-inactive">Inactive</span>}
</div>
<section aria-labelledby="workflow-tasks-heading">
Expand All @@ -222,17 +227,27 @@ export default function TasksPage() {
>
Add a new Task
</button>
<a
className="flex-item button-link"
href={previewUrl}
rel="noopener noreferrer"
target='_blank'
<select
aria-label="Choose starting Page"
className="flex-item workflow-starting-page"
onChange={handleChangeStartingPage}
style={(workflow?.steps?.length < 1) ? { display: 'none' } : undefined}
value={firstStepKey}
>
Preview Workflow <ExternalLinkIcon />
</a>
<option value="">Choose starting page</option>
{workflow.steps?.map(([stepKey, stepBody]) => (
<option
key={`choose-starting-page-${stepKey}`}
value={stepKey}
>
{firstStepKey === stepKey && 'Starting page: '}
{stepBody?.taskKeys?.join(', ') || `(${stepKey})` /* Note: if you see the stepKey instead of the taskKeys, something's wrong. */}
</option>
))}
</select>
</div>
<ul className="steps-list" aria-label="Pages/Steps">
{workflow.steps.map((step, index) => (
{workflow.steps?.map((step, index) => (
<StepItem
key={`stepItem-${step[0]}`}
activeDragItem={activeDragItem}
Expand Down
31 changes: 23 additions & 8 deletions app/pages/lab-pages-editor/components/WorkflowHeader.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import PropTypes from 'prop-types';

import getPreviewEnv from '../helpers/getPreviewEnv.js';
import ExternalLinkIcon from '../icons/ExternalLinkIcon.jsx';
import ReturnIcon from '../icons/ReturnIcon.jsx';
import { useWorkflowContext } from '../context.js';
import strings from '../strings.json';
Expand All @@ -12,12 +14,14 @@ export default function WorkflowHeader({
setCurrentTab = DEFAULT_HANDLER,
tabs = []
}) {
const { workflow } = useWorkflowContext();
const { project, workflow } = useWorkflowContext();
const returnUrl = `/lab/${projectId}/workflows`;
const previewEnv = getPreviewEnv();
const previewUrl = `https://frontend.preview.zooniverse.org/projects/${project?.slug}/classify/workflow/${workflow?.id}${previewEnv}`;

// When clicking a tab button, make that tab active. This is pretty straightforward.
function onClick(e) {
const { tab } = e.target.dataset;
const { tab } = e?.target?.dataset || {};
setCurrentTab(parseInt(tab));
}

Expand All @@ -43,14 +47,25 @@ export default function WorkflowHeader({
if (!workflow) return null;

return (
<div className="workflow-header flex-row">
<a href={returnUrl}> {/* Formerly <Link> from 'react-router', but React was throwing Legacy Context errors. */}
<ReturnIcon />
{strings.PagesEditor.components.WorkflowHeader.return}
</a>
<div className="workflow-header">
<div className="workflow-header-links flex-row">
<a href={returnUrl}> {/* Formerly <Link> from 'react-router', but React was throwing Legacy Context errors. */}
<ReturnIcon />
{strings.PagesEditor.components.WorkflowHeader.return}
</a>
<span className="flex-item" />
<a
className="button-link"
href={previewUrl}
rel="noopener noreferrer"
target='_blank'
>
Preview Workflow <ExternalLinkIcon />
</a>
</div>
<div
role="tablist"
className="flex-row flex-item justify-around"
className="workflow-header-tabs flex-row flex-item justify-around"
>
{tabs.map((tab, index) => (
<TabButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ export default function WorkflowSettingsPage() {
}

function doUpdate(e) {
const key = e.target.name;
let value = e.target.value || '';
const { updaterule } = e.target.dataset;
const key = e?.target?.name;
let value = e?.target?.value || '';
const { updaterule } = e?.target?.dataset || {};
if (!key) return;

if (updaterule === 'convert_to_number') value = parseInt(value);
if (updaterule === 'undefined_if_empty') value = value || undefined;
Expand Down
54 changes: 35 additions & 19 deletions css/lab-pages-editor.styl
Original file line number Diff line number Diff line change
Expand Up @@ -170,30 +170,41 @@ $fontWeightBoldPlus = 700
// ---------------------------------------------------------------------------

.workflow-header
border-bottom: 0.5px solid $grey1
margin-bottom: $sizeXL

a
display: inline-block
font-size: $fontSizeS
text-decoration: none
min-width: 40%

.icon
margin-right: $sizeS
.workflow-header-links
margin-bottom: $sizeM

button
background: none
border: none
cursor: pointer
font-size: $fontSizeL
font-weight: $fontWeightBoldPlus
text-transform: uppercase
a
display: inline-block
font-size: $fontSizeS
text-decoration: none

&[aria-selected=true]
border-bottom: 4px solid $teal

&[aria-selected=false]
color: $grey1
border-bottom: 4px solid transparent
.icon
margin-right: $sizeS

.workflow-header-tabs
gap: $sizeXL
justify-content: center
border-bottom: 0.5px solid $grey1

button
background: none
border: none
cursor: pointer
font-size: $fontSizeL
font-weight: $fontWeightBoldPlus
text-transform: uppercase

&[aria-selected=true]
border-bottom: 4px solid $teal

&[aria-selected=false]
color: $grey1
border-bottom: 4px solid transparent

// Component: Workflow Settings Page
// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -294,6 +305,11 @@ $fontWeightBoldPlus = 700
.status-inactive
color: $redBright

.workflow-starting-page
border: 1.5px solid $grey1
border-radius: $sizeXS
color: $grey2

dialog
border: 1px solid $grey1
border-radius: $sizeS
Expand Down

0 comments on commit d270c1a

Please sign in to comment.