From 99bf9c2a612590b7165b28891d4d320a4b019d1d Mon Sep 17 00:00:00 2001 From: kieftrav Date: Tue, 3 Dec 2024 07:42:24 -0600 Subject: [PATCH] wip --- .../tasks/experimental/volumetric/README.md | 11 +++ .../volumetric/components/VolumetricTask.js | 85 +++++++++++++++++++ .../components/VolumetricTask.spec.js | 0 .../components/VolumetricTask.stories.js | 20 +++++ .../tasks/experimental/volumetric/index.js | 9 ++ .../volumetric/models/VolumetricAnnotation.js | 11 +++ .../models/VolumetricAnnotation.spec.js | 0 .../volumetric/models/VolumetricTask.js | 22 +++++ .../volumetric/models/VolumetricTask.spec.js | 77 +++++++++++++++++ .../lib-classifier/src/plugins/tasks/index.js | 1 + .../src/store/Project/Project.js | 2 +- 11 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 packages/lib-classifier/src/plugins/tasks/experimental/volumetric/README.md create mode 100644 packages/lib-classifier/src/plugins/tasks/experimental/volumetric/components/VolumetricTask.js create mode 100644 packages/lib-classifier/src/plugins/tasks/experimental/volumetric/components/VolumetricTask.spec.js create mode 100644 packages/lib-classifier/src/plugins/tasks/experimental/volumetric/components/VolumetricTask.stories.js create mode 100644 packages/lib-classifier/src/plugins/tasks/experimental/volumetric/index.js create mode 100644 packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricAnnotation.js create mode 100644 packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricAnnotation.spec.js create mode 100644 packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricTask.js create mode 100644 packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricTask.spec.js diff --git a/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/README.md b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/README.md new file mode 100644 index 00000000000..b6775add124 --- /dev/null +++ b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/README.md @@ -0,0 +1,11 @@ +# Volumetric Task + +The volumetric task is a task type designed for use with structured volumetric JSON, as part of an NIH neuron mapping project. The task is a drawing/click-oriented task that constructs volumetric annotation data based on the clicked point in 3D space. + +The volumetric task requires subjects with a location of application/json mime type. The subject's location content is used to initialize the structured subject data to be annotated. + +The volumetric task does not support a required property. + +The volumetric task does not support tags (i.e. insertion, deletion). + +The volumetric task is disabled until the subject's JSON content is loaded. diff --git a/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/components/VolumetricTask.js b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/components/VolumetricTask.js new file mode 100644 index 00000000000..c67a9b1523f --- /dev/null +++ b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/components/VolumetricTask.js @@ -0,0 +1,85 @@ +import { Box, Text } from 'grommet' +import { Blank } from 'grommet-icons' +import { observer } from 'mobx-react' +import PropTypes from 'prop-types' +import styled from 'styled-components' +import { Markdownz } from '@zooniverse/react-components' +import InputIcon from './../../../components/InputIcon' +import InputStatus from '../../../components/InputStatus' +import TaskInput from '../../../components/TaskInput' + +const ToolIcon = ({ type }) => { + const arrow = '48 50, 48 15, 40 15, 50 0, 60 15, 52 15, 52 50' + return ( + + + + + + ) +} + +const StyledText = styled(Text)` + margin: 0; + padding: 0; + width: 100%; + + > *:first-child { + margin-top: 0; + } +` +function VolumetricTask(props) { + const { task } = props + const { setActiveTool } = task + function onChange(index, event) { + if (event.target.checked) { + setActiveTool(index) + } + } + + const ANNOTATION_COUNT = 3 + + console.log('Volumetric Task', JSON.parse(JSON.stringify((task)))) + console.log('task.tools', task.annotations) + + return ( + + + {task.instruction} + + + + + } + color={'white'} + /> + } + labelStatus={} + + name='volumetric-tool' + required={task.required} + type='radio' + /> + + ) +} + +VolumetricTask.defaultProps = { + task: {} +} + +VolumetricTask.propTypes = { + task: PropTypes.shape({ + help: PropTypes.string, + instruction: PropTypes.string, + required: PropTypes.bool + }) +} + +export default observer(VolumetricTask) diff --git a/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/components/VolumetricTask.spec.js b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/components/VolumetricTask.spec.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/components/VolumetricTask.stories.js b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/components/VolumetricTask.stories.js new file mode 100644 index 00000000000..9050c49dffb --- /dev/null +++ b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/components/VolumetricTask.stories.js @@ -0,0 +1,20 @@ +import { MockTask } from '@stories/components' +import VolumetricTask from './VolumetricTask' + +export default { + title: 'Tasks / Volumetric', + component: VolumetricTask, + args: {}, + argTypes: {} +} + +const tasks = { + T0: { + taskKey: 'T0', + type: 'volumetric' + } +} + +export function Default () { + return () +} diff --git a/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/index.js b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/index.js new file mode 100644 index 00000000000..f19c26c83f2 --- /dev/null +++ b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/index.js @@ -0,0 +1,9 @@ +import { default as TaskComponent } from './components/VolumetricTask' +import { default as TaskModel } from './models/VolumetricTask' +import { default as AnnotationModel } from './models/VolumetricAnnotation' + +export default { + TaskComponent, + TaskModel, + AnnotationModel +} diff --git a/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricAnnotation.js b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricAnnotation.js new file mode 100644 index 00000000000..87f631a745c --- /dev/null +++ b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricAnnotation.js @@ -0,0 +1,11 @@ +import { types } from 'mobx-state-tree' +import Annotation from '../../../models/Annotation' + +const Volumetric = types + .model('Volumetric', { + taskType: types.literal('volumetric'), + value: types.optional(types.string, ''), + }) + +const VolumetricAnnotation = types.compose('VolumetricAnnotation', Annotation, Volumetric) +export default VolumetricAnnotation diff --git a/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricAnnotation.spec.js b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricAnnotation.spec.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricTask.js b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricTask.js new file mode 100644 index 00000000000..434967bd801 --- /dev/null +++ b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricTask.js @@ -0,0 +1,22 @@ +import cuid from 'cuid' +import { types } from 'mobx-state-tree' +import Task from '../../../models/Task' +import VolumetricAnnotation from './VolumetricAnnotation' + +const Volumetric = types.model('Volumetric', { + annotation: types.safeReference(VolumetricAnnotation), + type: types.literal('volumetric'), +}) + .views(self => ({ + defaultAnnotation (id = cuid()) { + return VolumetricAnnotation.create({ + id, + task: self.taskKey, + taskType: self.type + }) + } + })) + +const VolumetricTask = types.compose('VolumetricTask', Task, Volumetric) + +export default VolumetricTask diff --git a/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricTask.spec.js b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricTask.spec.js new file mode 100644 index 00000000000..d8be867dac2 --- /dev/null +++ b/packages/lib-classifier/src/plugins/tasks/experimental/volumetric/models/VolumetricTask.spec.js @@ -0,0 +1,77 @@ +import VolumetricTask from '@plugins/tasks/experimental/volumetric' + +describe.only('Model > VolumetricTask', function () { + const volumetricTask = { + taskKey: 'T0', + type: 'volumetric' + } + + const singleChoiceTask = { + answers: [ + { label: 'yes', next: 'S2' }, + { label: 'no', next: 'S3' } + ], + strings: { + question: 'Do you exist?' + }, + required: '', + taskKey: 'T1', + type: 'single' + } + + it('should exist', function () { + const task = VolumetricTask.TaskModel.create(volumetricTask) + expect(task).to.be.ok() + expect(task).to.be.an('object') + }) + + it('should error for invalid tasks', function () { + let errorThrown = false + try { + VolumetricTask.TaskModel.create(singleChoiceTask) + } catch (e) { + errorThrown = true + } + expect(errorThrown).to.be.true() + }) + + describe('Views > defaultAnnotation', function () { + let task + + before(function () { + task = VolumetricTask.TaskModel.create(volumetricTask) + }) + + it('should be a valid annotation', function () { + const annotation = task.defaultAnnotation() + expect(annotation.id).to.be.ok() + expect(annotation.task).to.equal('T0') + expect(annotation.taskType).to.equal('volumetric') + }) + + it('should generate unique annotations', function () { + const firstAnnotation = task.defaultAnnotation() + const secondAnnotation = task.defaultAnnotation() + expect(firstAnnotation.id).to.not.equal(secondAnnotation.id) + }) + }) + + describe('with an annotation', function () { + let annotation + let task + + before(function () { + task = VolumetricTask.TaskModel.create(volumetricTask) + annotation = task.defaultAnnotation() + }) + + it('should start up with an empty string', function () { + expect(annotation.value).to.equal('') + }) + + it('should update annotations', function () { + annotation.update('Hello there!') + expect(annotation.value).to.equal('Hello there!') + }) + }) +}) diff --git a/packages/lib-classifier/src/plugins/tasks/index.js b/packages/lib-classifier/src/plugins/tasks/index.js index 7ab9979c286..1ecf1d3052a 100644 --- a/packages/lib-classifier/src/plugins/tasks/index.js +++ b/packages/lib-classifier/src/plugins/tasks/index.js @@ -10,3 +10,4 @@ export { default as text } from './text' export { default as highlighter } from './experimental/highlighter' export { default as textFromSubject } from './experimental/textFromSubject' export { default as transcription } from './experimental/transcription' +export { default as volumetric } from './experimental/volumetric' diff --git a/packages/lib-classifier/src/store/Project/Project.js b/packages/lib-classifier/src/store/Project/Project.js index 6fc0a93e901..0da522ef32d 100644 --- a/packages/lib-classifier/src/store/Project/Project.js +++ b/packages/lib-classifier/src/store/Project/Project.js @@ -26,7 +26,7 @@ const Project = types }, get isVolumetricViewer() { - return self.experimental_tools.includes('volumetricViewer') + return self.experimental_tools.includes('volumetricProject') }, }))