Skip to content
This repository has been archived by the owner on Oct 6, 2021. It is now read-only.

Commit

Permalink
Add a filtering step to the marking task
Browse files Browse the repository at this point in the history
Allow the decision tree task to control which subject representation (image or text) is shown in the viewer.
Use the OCR as the alt text for the subject image.
Add a back button which resets the marking task.
  • Loading branch information
eatyourgreens committed Jul 27, 2016
1 parent 5805f02 commit 3357e55
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 36 deletions.
21 changes: 3 additions & 18 deletions app/classifier.cjsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
React = require 'react'

SubjectTools = require './classify/subject-tools'
SubjectViewer = require './classify/subject-viewer'
Annotation = require './classify/annotation'
ClassificationTask = require './classify/classification-task'
Subject = require './classify/subject'
Subjects = require './lib/subjects'
Classifications = require './lib/classifications'

Expand Down Expand Up @@ -35,28 +34,14 @@ module.exports = React.createClass

render: ->
<ClassificationTask onChange={@onChangeAnnotation} onFinish={@onFinishPage}>
<div className="readymade-subject-viewer-container">
{
if @state.currentSubjects.length
<div className="readymade-subject-viewer">
<SubjectTools project={@props.project} api={@props.api} talk={@props.talk} user={@props.user} subject_set={@props.subject_set} subject={@state.currentSubjects[0]} />
<div className="scroll-container" ref="scrollContainer">
{<SubjectViewer subject={subject} key={subject.id} ref="subject#{subject.id}" isCurrent={subject.id is @subjects.current.id} /> for subject in @state.currentSubjects}
</div>
</div>
}
</div>
<Subject project={@props.project} api={@props.api} talk={@props.talk} user={@props.user} subject_set={@props.subject_set} currentSubjects={@state.currentSubjects} />
</ClassificationTask>

onChangeAnnotation: (annotation) ->
if annotation.issue
@refs["subject#{subject.id}"].getDOMNode().classList.add 'active' for subject in @state.currentSubjects
else
@refs["subject#{subject.id}"].getDOMNode().classList.remove 'active' for subject in @state.currentSubjects

onFinishPage: (task_annotations) ->
@classifications?.set_annotations ({task: key, value: value} for key, value of task_annotations)
@classifications.finish()
# @classifications.finish()
console.log JSON.stringify @classifications.current()
console.log @state.currentSubjects[0]?.metadata.image
@nextSubject()
Expand Down
29 changes: 25 additions & 4 deletions app/classify/classification-task.cjsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
React = require 'react'
FilterTask = require './tasks/filter'
ChooseTask = require './tasks/choose'
EditTask = require './tasks/edit'
Annotation = require './annotation'
Expand Down Expand Up @@ -40,32 +41,45 @@ module.exports = React.createClass
description: "Find a health issue on this page that fits one of the categories below. Your task is to collect all the information on the page about the issue you've found."

getInitialState: ->
step: 'choose'
step: 'filter'
type: 'health'
instructions: @defaultInstructions
annotations: []

render: ->
children = React.Children.map @props.children, (child) => React.cloneElement child, task: @state.step
<div>
<TaskInstructions instructions={@state.instructions} />
<div className="readymade-classification-interface">
<div className="readymade-decision-tree-container">
<div className="decision-tree">
{switch @state.step
when 'filter'
<FilterTask onComplete={@filter} />
when 'choose'
<div>
<ChooseTask onChooseTask={@create} onFinish={@finish} />
<ChooseTask onChooseTask={@create} onBack={@reset} onFinish={@finish} />
<AnnotationsSummary annotations={@state.annotations} deleteTool={@deleteAnnotation} onEdit={@edit} />
</div>
when 'edit'
<EditTask annotation={@state.annotations[0]} onChange={@props.onChange} onComplete={@choose}/>
}
</div>
</div>
{@props.children}
{children}
</div>
</div>

filter: (choice) ->
switch choice
when 'yes'
@setState
step: 'choose'
type: null
instructions: @defaultInstructions
when 'no'
@finish()

create: (type) ->
@newAnnotation type
@setState
Expand Down Expand Up @@ -104,6 +118,12 @@ module.exports = React.createClass

@props.onChange new AnnotationTool

reset: ->
annotation.destroy() for annotation in @state.annotations
step = 'filter'
annotations = []
@setState {annotations, step}

finish: ->
task_annotations = {}
@state.annotations.map (annotation, i) ->
Expand All @@ -114,7 +134,8 @@ module.exports = React.createClass
annotations = @state.annotations
annotation.destroy() for annotation in annotations
annotations = []
@setState {annotations}
step = 'filter'
@setState {annotations, step}

newAnnotation: (type) ->
annotations = @state.annotations
Expand Down
5 changes: 2 additions & 3 deletions app/classify/subject-viewer.cjsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ module.exports = React.createClass

render: ->
classList=["readymade-marking-surface-container"]
classList.push "current" if @props.isCurrent
classList.push 'image' if @props.task is 'filter'
image = @mediaSrcs['image/jpeg']
<div className={classList.join ' '}>
<div className="text-viewer">
<div data-subject={@props.subject.id}>{@state.text}</div>
</div>
<div className="subject-image">
<h3>Scanned page</h3>
{<img src={image} alt="" /> if image}
{<img src={image} alt={@state.text} /> if image}
</div>
</div>

Expand Down
20 changes: 20 additions & 0 deletions app/classify/subject.cjsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
React = require 'react'
SubjectTools = require './subject-tools'
SubjectViewer = require './subject-viewer'

module.exports = React.createClass
displayName: 'Subject'

render: ->
console.log @props.task
<div className="readymade-subject-viewer-container">
{
if @props.currentSubjects.length
<div className="readymade-subject-viewer">
<SubjectTools project={@props.project} api={@props.api} talk={@props.talk} user={@props.user} subject_set={@props.subject_set} subject={@props.currentSubjects[0]} />
<div className="scroll-container" ref="scrollContainer">
{<SubjectViewer task={@props.task} subject={subject} key={subject.id} ref="subject#{subject.id}" /> for subject in @props.currentSubjects}
</div>
</div>
}
</div>
8 changes: 6 additions & 2 deletions app/classify/tasks/choose.cjsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module.exports = React.createClass
<div className="decision-tree-question">
To get started first select the category
</div>
<button type="button" className="decision-tree-choice major-button" onClick={@back}>Back</button>
<ul className="decision-tree-choices">
{for key, task of tasks
<li key={key} className="decision-tree-choice">
Expand All @@ -17,14 +18,17 @@ module.exports = React.createClass
</button>
</li>
}
{@props.children}
<button type="button" className="major-button" onClick={@finish}>Finish page</button>
</ul>
{@props.children}
<button type="button" className="major-button" onClick={@finish}>Finish page</button>
</div>

edit: (e) ->
@props.onChooseTask e.currentTarget.value

back: ->
@props.onBack()

finish: ->
@props.onFinish()

45 changes: 45 additions & 0 deletions app/classify/tasks/filter.cjsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
React = require 'react'

answers =
yes:
label: 'Yes'
value: 'yes'
no:
label: 'No'
value: 'no'

module.exports = React.createClass
displayName: 'FilterTask'

getDefaultProps: ->
name: 'filter'

getInitialState: ->
value: null

render: ->
label = 'Next'
label = 'Finish' if @state.value is 'no'
<div className="decision-tree-task">
<div className="decision-tree-question">
Are there any health issues to mark on this page?
</div>
<div className="decision-tree-choices">
{for key, answer of answers
<label className="decision-tree-choice">
<input type="radio" name={@props.name} value={answer.value} checked={@state.value is answer.value} onChange={@choose} />
<span className="readymade-choice-clickable standard-button">{answer.label}</span>
</label>
}
{@props.children}
<button type="button" className="major-button" onClick={@complete} disabled={!@state.value}>{label}</button>
</div>
</div>

choose: (e) ->
@setState value: e.currentTarget.value

complete: ->
@props.onComplete @state.value
@setState value: null

31 changes: 22 additions & 9 deletions css/custom.styl
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,14 @@

.readymade-marking-surface-container
display: flex
opacity: 0.2

&.current
&.active
opacity: 1
&.image
.subject-image
display: block
text-align: center

.text-viewer
display: none

.text-viewer
flex: 5
Expand All @@ -62,7 +65,6 @@

img
width: 100%
max-width: 500px

.text-selection
background: #0b517c
Expand All @@ -79,11 +81,22 @@
&:hover
background: rgba(0, 0, 0, 0.3)

.decision-tree-choice
margin-bottom: .5em
.readymade-decision-tree-container
.decision-tree-choice
display: block
margin-bottom: .5em

.decision-tree-choices
margin-top: .5em

input[type=radio]
position: absolute
height: 1px
width: 1px
opacity: 0

.decision-tree-choices
margin-top: .5em
&:checked + span
background: #0b517c

.readymade-choice-clickable
color: white
Expand Down

0 comments on commit 3357e55

Please sign in to comment.