diff --git a/app/pages/lab-pages-editor/PagesEditor.jsx b/app/pages/lab-pages-editor/PagesEditor.jsx new file mode 100644 index 0000000000..cba24e27f5 --- /dev/null +++ b/app/pages/lab-pages-editor/PagesEditor.jsx @@ -0,0 +1,44 @@ +/* +Pages Editor +Main component of the Pages Editor feature. + */ + +// ESLint: don't import global React, and don't use .defaultProps. +/* eslint-disable no-console */ +/* eslint-disable react/react-in-jsx-scope */ +/* eslint-disable react/require-default-props */ + +import { StrictMode } from 'react'; +import PropTypes from 'prop-types'; + +import DataManager from './DataManager.jsx'; +import Tester from './Tester.jsx'; +import WorkflowHeader from './components/WorkflowHeader.jsx'; +import WorkflowSettingsPage from './components/WorkflowSettingsPage.jsx'; + +function PagesEditor({ params }) { + const { workflowID: workflowId, projectID: projectId } = params; + + return ( + +
+ + + + +
+
+ ); +} + +PagesEditor.propTypes = { + params: PropTypes.shape({ + projectID: PropTypes.string, + workflowID: PropTypes.string + }) +}; + +export default PagesEditor; diff --git a/app/pages/lab-pages-editor/README.md b/app/pages/lab-pages-editor/README.md index 954ed02757..f3eb94f66b 100644 --- a/app/pages/lab-pages-editor/README.md +++ b/app/pages/lab-pages-editor/README.md @@ -2,3 +2,14 @@ The "Pages Editor" is a variant of the Workflow Editor used in the Project Builder. +This experiment started development in late August/early September 2023, and runs parallel to the [FEM Lab](../lab-fem) + +### Dev Notes: Changes to Other PFE Files + +The Pages Editor aims to be standalone, with minimum changes to other parts of the PFE code base. However, some changes are necessary, so please note the changes on the following PFE files: + +- `app/router.jsx`: modified to add PagesEditor route (`lab/{projectId}/workflows/editor/{workflowId}`) +- `css/lab-pages-editor.syl`: added style sheet. +- `css/main.styl`: modified to import PagesEditor stylesheet. +- `app/pages/lab/project.jsx`: modified to include "isPartOfPagesEditorExperiment" flag, which adds a special style to the PagesEditor's container. + \ No newline at end of file diff --git a/app/pages/lab-pages-editor/components/WorkflowHeader.jsx b/app/pages/lab-pages-editor/components/WorkflowHeader.jsx new file mode 100644 index 0000000000..cb9e24825e --- /dev/null +++ b/app/pages/lab-pages-editor/components/WorkflowHeader.jsx @@ -0,0 +1,44 @@ +/* eslint-disable no-console */ +/* eslint-disable react/react-in-jsx-scope */ +/* eslint-disable react/require-default-props */ + +import PropTypes from 'prop-types'; +import { Link } from 'react-router'; + +import ReturnIcon from '../icons/ReturnIcon.jsx'; +import { useWorkflowContext } from '../context.js'; +import strings from '../strings.json'; + +export default function WorkflowHeader({ + projectId = '' +}) { + const { workflow } = useWorkflowContext(); + const returnUrl = `/lab/${projectId}/workflows`; + + function onClick() { + console.log('TODO'); + } + + if (!workflow) return null; + + return ( +
+ + + {strings.PagesEditor.components.WorkflowHeader.return} + +
+ + +
+
+ ); +} + +WorkflowHeader.propTypes = { + projectId: PropTypes.string +}; diff --git a/app/pages/lab-pages-editor/components/WorkflowSettingsPage.jsx b/app/pages/lab-pages-editor/components/WorkflowSettingsPage.jsx new file mode 100644 index 0000000000..0ac08e249a --- /dev/null +++ b/app/pages/lab-pages-editor/components/WorkflowSettingsPage.jsx @@ -0,0 +1,255 @@ +/* eslint-disable no-console */ +/* eslint-disable react/react-in-jsx-scope */ +/* eslint-disable react/require-default-props */ +/* eslint-disable radix */ + +import { useWorkflowContext } from '../context.js'; +import strings from '../strings.json'; // TODO: move all text into strings + +export default function WorkflowSettingsPage() { + const { workflow, update } = useWorkflowContext(); + + function onSubmit(e) { + e.preventDefault(); + try { + console.log('+++ onSubmit: ', e); + // TODO: on Submit, run update() on every available field. + // also, make sure the 'data-updaterule' rules are implemented. + } catch (err) { + console.error('WorkflowSettingsPageError: ', err); + } + return false; + } + + function doUpdate(e) { + const key = e.target.name; + let value = e.target.value || ''; + const { updaterule } = e.target.dataset; + + if (updaterule === 'convert_to_number') value = parseInt(value); + if (updaterule === 'undefined_if_empty') value = value || undefined; + + // TODO: due to onBlur={doUpdate}, keyboard navigation may accidentally cause the Workflow to update multiple times. + // One solution is to check if the new value is different from the existing one. + + update({ + [key]: value + // 'configuration.classifier_version': '2.0' // TODO: figure out if this needed. + }); + } + + function testUpdate(e) { + const key = e.target.name; + const value = e.target.value || ''; + console.log('+++ testUpdate: ', key, value); + } + + if (!workflow) return null; + + return ( +
+ + +
+
+ Associated Subject Sets +

Choose the set of subjects you want to use for this workflow. Add subject sets in the Subject Sets tab.

+

TODO

+
+ +
+ Associated Tutorial +

Choose the tutorials you want to use for this workflow. Create tutorials in the Tutorial tab.

+

TODO

+
+ +
+ +
+ Subject Retirement +

+ Set how many people should classify each subject before it is + "done." Once a subject has reached the retirement limit it + will no longer be shown to volunteers. +

+
+ + +
+

+ If you'd like more complex retirement rules such as conditional + retirement using Caesar, please get in touch via the Contact Us + page. +

+
+
+ +
+
+ Subject Viewer +

+ Choose how to display your subjects. + Refer to the Subject Viewer section of the Glossary for more info. +

+
+ +
+
+ +
+ Multi-Image Options +

+ Choose how to display subjects with multiple images. + If your subjects are in a sequence, such as camera trap images, + volunteers can play them like a .gif using the Flipbook viewer. +

+

TODO

+
+ +
+ +
+ Classification Tools +

TEST: HTML and styling for checkbox input

+ + + +
+ +
+ Quicktalk +

TEST: HTML and styling for radio options

+ + + +
+ +
+
+ ); +} diff --git a/app/pages/lab-pages-editor/icons/README.md b/app/pages/lab-pages-editor/icons/README.md new file mode 100644 index 0000000000..ad77351564 --- /dev/null +++ b/app/pages/lab-pages-editor/icons/README.md @@ -0,0 +1,3 @@ +# Icons for the Pages Editor + +Icons are organised into this folder, to make them easier should we choose to update them in the future - e.g. replace all FontAwesome icons with Grommet icons. diff --git a/app/pages/lab-pages-editor/icons/ReturnIcon.jsx b/app/pages/lab-pages-editor/icons/ReturnIcon.jsx new file mode 100644 index 0000000000..a993e27016 --- /dev/null +++ b/app/pages/lab-pages-editor/icons/ReturnIcon.jsx @@ -0,0 +1,7 @@ +/* eslint-disable react/react-in-jsx-scope */ + +export default function ReturnIcon() { + return ( + + ); +} diff --git a/app/pages/lab-pages-editor/index.jsx b/app/pages/lab-pages-editor/index.jsx index 0af0c5d300..349379a4de 100644 --- a/app/pages/lab-pages-editor/index.jsx +++ b/app/pages/lab-pages-editor/index.jsx @@ -1,40 +1,3 @@ -// ESLint: don't import global React, and don't use .defaultProps. -/* eslint-disable no-console */ -/* eslint-disable react/react-in-jsx-scope */ -/* eslint-disable react/require-default-props */ - -import { StrictMode } from 'react'; -import PropTypes from 'prop-types'; -import DataManager from './DataManager.jsx'; -import Tester from './Tester.jsx'; - -function PagesEditor(props) { - const { params } = props; - - return ( - -
-
Pages Editor
- -
- Workflow - {' '} - {params?.workflowId} -
- -
-
-
- ); -} - -PagesEditor.propTypes = { - params: PropTypes.shape({ - workflowId: PropTypes.string - }) -}; +import PagesEditor from './PagesEditor.jsx'; export default PagesEditor; diff --git a/app/pages/lab-pages-editor/strings.json b/app/pages/lab-pages-editor/strings.json new file mode 100644 index 0000000000..9801e81762 --- /dev/null +++ b/app/pages/lab-pages-editor/strings.json @@ -0,0 +1,11 @@ +{ + "PagesEditor": { + "components": { + "WorkflowHeader": { + "return": "Back to Workflows", + "tasks": "Tasks", + "workflow_settings": "Workflow Settings" + } + } + } +} diff --git a/app/pages/lab/project.jsx b/app/pages/lab/project.jsx index 3f551ce6bd..8f5f6a8daf 100644 --- a/app/pages/lab/project.jsx +++ b/app/pages/lab/project.jsx @@ -83,8 +83,9 @@ function EditProjectPage({ } const { pathname } = location + const isPartOfPagesEditorExperiment = pathname?.includes('workflows/editor') // PagesEditor: see pages/lab-pages-editor return ( -
+