From fae2b931df21a459fba09ed11b07c8c320c12e41 Mon Sep 17 00:00:00 2001 From: Paul Beaudoin Date: Mon, 11 Jan 2016 13:23:47 -0500 Subject: [PATCH 1/2] selective merge from green-books transcribe frontend changes to support jumping btw verify and transcribe; support for verify EDIT button; support for DEL to remove mark and ENT to commit mark --- app/assets/javascripts/components/app.cjsx | 2 +- .../mark/tools/rectangle-tool/index.cjsx | 2 +- .../components/subject-viewer.cjsx | 21 ++++++++++++++----- .../components/transcribe/index.cjsx | 5 ++++- .../tools/composite-tool/index.cjsx | 10 +++++++-- .../transcribe/tools/text-tool/index.cjsx | 6 ++++++ .../verify/tools/verify-tool/index.cjsx | 7 ++++++- .../javascripts/lib/mark-button-mixin.cjsx | 4 ++-- app/assets/stylesheets/verify-tool.styl | 14 +++++++++++++ 9 files changed, 58 insertions(+), 13 deletions(-) diff --git a/app/assets/javascripts/components/app.cjsx b/app/assets/javascripts/components/app.cjsx index 7cb62d106..3785143b0 100644 --- a/app/assets/javascripts/components/app.cjsx +++ b/app/assets/javascripts/components/app.cjsx @@ -40,7 +40,7 @@ App = React.createClass error: "Having trouble logging you in" setTutorialComplete: -> - previously_saved = @state.user?.tutorial_complete? + previously_saved = @state.user?.tutorial_complete # Immediately ammend user object with tutorial_complete flag so that we can hide the Tutorial: @setState user: $.extend(@state.user ? {}, tutorial_complete: true) diff --git a/app/assets/javascripts/components/mark/tools/rectangle-tool/index.cjsx b/app/assets/javascripts/components/mark/tools/rectangle-tool/index.cjsx index ce2b07764..167bad719 100644 --- a/app/assets/javascripts/components/mark/tools/rectangle-tool/index.cjsx +++ b/app/assets/javascripts/components/mark/tools/rectangle-tool/index.cjsx @@ -200,7 +200,7 @@ module.exports = React.createClass classes.push 'transcribable' if @props.isTranscribable classes.push 'interim' if @props.interim classes.push if @props.disabled then 'committed' else 'uncommitted' - classes.push "tanscribing" if @checkLocation() + classes.push "tanscribing" if @inTranscribeWorkflow() x1 = @props.mark.x width = @props.mark.width diff --git a/app/assets/javascripts/components/subject-viewer.cjsx b/app/assets/javascripts/components/subject-viewer.cjsx index 977a72a83..07a335e12 100644 --- a/app/assets/javascripts/components/subject-viewer.cjsx +++ b/app/assets/javascripts/components/subject-viewer.cjsx @@ -54,6 +54,16 @@ module.exports = React.createClass @loadImage @props.subject.location.standard window.addEventListener "resize", this.updateDimensions + $(document).keydown (e) => + # Handle keypress + if e.keyCode == 46 + mark = @state.selectedMark + @destroyMark mark if mark? + + # Handle keypress + else if e.keyCode == 13 + @submitMark(@state.uncommittedMark) if @state.uncommittedMark? + scrollToSubject: -> # scroll to mark when transcribing if @props.workflow.name is 'transcribe' @@ -108,10 +118,10 @@ module.exports = React.createClass # VARIOUS EVENT HANDLERS # Commit mark - submitMark: (mark) -> + submitMark: (mark, oncomplete) -> return unless mark? @props.onComplete? mark - @setUncommittedMark null # reset uncommitted mark + @setUncommittedMark null, oncomplete # reset uncommitted mark # Handle initial mousedown: handleInitStart: (e) -> @@ -198,10 +208,11 @@ module.exports = React.createClass mark.belongsToUser = true @setUncommittedMark mark - setUncommittedMark: (mark) -> + setUncommittedMark: (mark, oncomplete) -> @setState uncommittedMark: mark, - selectedMark: mark #, => @forceUpdate() # not sure if this is needed? + selectedMark: mark, () => + oncomplete() if oncomplete? setView: (viewX, viewY, viewWidth, viewHeight) -> @setState {viewX, viewY, viewWidth, viewHeight} @@ -235,7 +246,7 @@ module.exports = React.createClass # First, if we're blurring some other uncommitted mark, commit it: if @state.uncommittedMark? && mark != @state.uncommittedMark - @submitMark sel + @submitMark @state.uncommittedMark, sel else sel() diff --git a/app/assets/javascripts/components/transcribe/index.cjsx b/app/assets/javascripts/components/transcribe/index.cjsx index 3326ec09a..1be14a66d 100644 --- a/app/assets/javascripts/components/transcribe/index.cjsx +++ b/app/assets/javascripts/components/transcribe/index.cjsx @@ -101,7 +101,9 @@ module.exports = React.createClass # rename to Classifier page: @props.query.page render: -> - if @props.params.workflow_id? and @props.params.parent_subject_id? + if @props.query.from == 'verify' + transcribeMode = 'verify' + else if @props.params.workflow_id? and @props.params.parent_subject_id? transcribeMode = 'page' else if @props.params.subject_id transcribeMode = 'single' @@ -113,6 +115,7 @@ module.exports = React.createClass # rename to Classifier else isLastSubject = null currentAnnotation = @getCurrentClassification().annotation + currentAnnotation = @props.query.annotation if @props.query.annotation? TranscribeComponent = @getCurrentTool() # @state.currentTool onFirstAnnotation = currentAnnotation?.task is @getActiveWorkflow().first_task diff --git a/app/assets/javascripts/components/transcribe/tools/composite-tool/index.cjsx b/app/assets/javascripts/components/transcribe/tools/composite-tool/index.cjsx index 238b80935..2bb2a656e 100644 --- a/app/assets/javascripts/components/transcribe/tools/composite-tool/index.cjsx +++ b/app/assets/javascripts/components/transcribe/tools/composite-tool/index.cjsx @@ -55,7 +55,7 @@ CompositeTool = React.createClass # If there are more inputs, move focus to next input # Otherwise commit annotation (which is default behavior when there's only one input handleCompletedField: -> - field_keys = (c.value for c of @props.task.tool_config.options) + field_keys = (c.value for c in @props.task.tool_config.options) next_field_key = field_keys[ field_keys.indexOf(@state.active_field_key) + 1 ] if next_field_key? @@ -63,7 +63,9 @@ CompositeTool = React.createClass , => @forceUpdate() else - @commitAnnotation() + # Default to first field key (in case we're repeating this task) + @setState active_field_key: field_keys[0], () => + @commitAnnotation() # User moved focus to an input: handleFieldFocus: (annotation_key) -> @@ -79,6 +81,8 @@ CompositeTool = React.createClass if @props.transcribeMode is 'page' or @props.transcribeMode is 'single' if @props.isLastSubject and not @props.task.next_task? @props.returnToMarking() + else if @props.transcribeMode == 'verify' + @transitionTo 'verify' # this can go into a mixin? (common across all transcribe tools) returnToMarking: -> @@ -109,6 +113,8 @@ CompositeTool = React.createClass else if @props.isLastSubject and ( @props.transcribeMode is 'page' or @props.transcribeMode is 'single' ) 'Return to Marking' + else if @props.transcribeMode is 'verify' + 'Return to Verify' else 'Next Entry' buttons.push diff --git a/app/assets/javascripts/components/transcribe/tools/text-tool/index.cjsx b/app/assets/javascripts/components/transcribe/tools/text-tool/index.cjsx index 5dbb2c424..a395ac8af 100644 --- a/app/assets/javascripts/components/transcribe/tools/text-tool/index.cjsx +++ b/app/assets/javascripts/components/transcribe/tools/text-tool/index.cjsx @@ -1,4 +1,5 @@ React = require 'react' +{Navigation} = require 'react-router' DraggableModal = require 'components/draggable-modal' SmallButton = require 'components/buttons/small-button' HelpButton = require 'components/buttons/help-button' @@ -7,6 +8,7 @@ IllegibleSubjectButton = require 'components/buttons/illegible-subject-button' TextTool = React.createClass displayName: 'TextTool' + mixins: [Navigation] # load subjects and set state variables: subjects, classification getInitialState: -> annotation: @props.annotation ? {} @@ -119,6 +121,8 @@ TextTool = React.createClass if @props.transcribeMode is 'page' or @props.transcribeMode is 'single' if @props.isLastSubject and not @props.task.next_task? @props.returnToMarking() + else if @props.transcribeMode == 'verify' + @transitionTo 'verify' # Get key to use in annotations hash (i.e. typically 'value', unless included in composite tool) fieldKey: -> @@ -235,6 +239,8 @@ TextTool = React.createClass else if @props.isLastSubject and ( @props.transcribeMode is 'page' or @props.transcribeMode is 'single' ) 'Return to Marking' + else if @props.transcribeMode is 'verify' + 'Return to Verify' else 'Next Entry' buttons.push diff --git a/app/assets/javascripts/components/verify/tools/verify-tool/index.cjsx b/app/assets/javascripts/components/verify/tools/verify-tool/index.cjsx index 76235bce0..749c45027 100644 --- a/app/assets/javascripts/components/verify/tools/verify-tool/index.cjsx +++ b/app/assets/javascripts/components/verify/tools/verify-tool/index.cjsx @@ -64,6 +64,11 @@ VerifyTool = React.createClass y = data.y + yPad return {x,y} + editAnnotation: (ann) -> + url = "/#/transcribe/#{@props.subject.parent_subject_id}?scrollX=#{window.scrollX}&scrollY=#{window.scrollY}&from=verify" + url += "&" + ("annotation[#{k}]=#{v}" for k,v of ann).join('&') + window.location.href = url + render: -> # return null unless @props.viewerSize? && @props.subject? # return null if ! @props.scale? || ! @props.scale.horizontal? @@ -115,7 +120,7 @@ VerifyTool = React.createClass # TODO: hack to approximate a friendly label in emigrant; should pull from original label: label = label.replace(/em_/,'') label = label.replace(/_/g, ' ') -
  • {label} {v}
  • +
  • {label} {v}
  • } diff --git a/app/assets/javascripts/lib/mark-button-mixin.cjsx b/app/assets/javascripts/lib/mark-button-mixin.cjsx index b9160d684..e9e7ab786 100644 --- a/app/assets/javascripts/lib/mark-button-mixin.cjsx +++ b/app/assets/javascripts/lib/mark-button-mixin.cjsx @@ -28,12 +28,12 @@ module.exports = markStatus: markStatus locked: '' - checkLocation: ()-> + inTranscribeWorkflow: ()-> pattern = new RegExp('^(#\/transcribe)') pattern.test("#{window.location.hash}") renderMarkButton: -> - return null if @checkLocation() + return null if @inTranscribeWorkflow() Date: Tue, 12 Jan 2016 12:16:21 -0500 Subject: [PATCH 2/2] making edit button in verify workflow configurable; better visual treatment for edit button; checkmark hover for verify options --- app/assets/images/checkmark.png | Bin 0 -> 258 bytes .../verify/tools/verify-tool/index.cjsx | 3 ++ .../lib/workflow-methods-mixin.cjsx | 2 +- app/assets/stylesheets/verify-tool.styl | 47 ++++++++++++------ app/models/workflow.rb | 3 ++ app/serializers/workflow_serializer.rb | 2 +- project/emigrant/workflows/verify.json | 1 + 7 files changed, 41 insertions(+), 17 deletions(-) create mode 100644 app/assets/images/checkmark.png diff --git a/app/assets/images/checkmark.png b/app/assets/images/checkmark.png new file mode 100644 index 0000000000000000000000000000000000000000..feaa040d551bb30879825c32a88e110518192dce GIT binary patch literal 258 zcmeAS@N?(olHy`uVBq!ia0vp^0w6XA8<1SE`<)7qVk{1FcVbv~PUa<$v&YlLF+@Xj z>ZH4ThZJ~P+20B7RdlK`V@`|v(Gm5=u}g<3X>#whZ`M=hr~bUW=X=}!$q8O_W*W8> zgm~Qz@ODXmey21_;jr}P?6^0af^(Z6UT9c4&x^e>{zz`()Fjy-g2^V=ZdD60tl7HH z;OOV~EFyIWR|JaI9AJqKYCp^#_I~G+4Mt27d@Yl{|6D71q(?^L&m}Xajayp%RtGh2 zdx6lw?Av!aiY^~BZ~mT_)*zniSjN-!_&_$$9}J$ZelF{r G5}E+7r)LZR literal 0 HcmV?d00001 diff --git a/app/assets/javascripts/components/verify/tools/verify-tool/index.cjsx b/app/assets/javascripts/components/verify/tools/verify-tool/index.cjsx index 749c45027..c2fa4d45f 100644 --- a/app/assets/javascripts/components/verify/tools/verify-tool/index.cjsx +++ b/app/assets/javascripts/components/verify/tools/verify-tool/index.cjsx @@ -124,6 +124,9 @@ VerifyTool = React.createClass } + { if @props.workflow.subjects_editable + + } } diff --git a/app/assets/javascripts/lib/workflow-methods-mixin.cjsx b/app/assets/javascripts/lib/workflow-methods-mixin.cjsx index 6e6fc5b13..115e2431b 100644 --- a/app/assets/javascripts/lib/workflow-methods-mixin.cjsx +++ b/app/assets/javascripts/lib/workflow-methods-mixin.cjsx @@ -250,7 +250,7 @@ module.exports = task = @getTasks()[@state.taskKey] # PB: Moving from hash of options to an array of options - if (options = (c for c in task.tool_config?.options when c.value is @getCurrentClassification().annotation?.value)) && options.length > 0 && (opt = options[0])? && opt.next_task? + if (options = (c for c in task.tool_config?.options when c.value is @getCurrentClassification()?.annotation?.value)) && options.length > 0 && (opt = options[0])? && opt.next_task? nextKey = opt.next_task else nextKey = @getTasks()[@state.taskKey].next_task diff --git a/app/assets/stylesheets/verify-tool.styl b/app/assets/stylesheets/verify-tool.styl index 4e5093ca3..c96acbae0 100644 --- a/app/assets/stylesheets/verify-tool.styl +++ b/app/assets/stylesheets/verify-tool.styl @@ -4,34 +4,45 @@ label margin 1em - ul + & > ul padding-left 0 list-style none text-align left - li + & > li + + position relative + flexbox(flex) + flex-direction(row) + flex-wrap(nowrap) + padding-bottom 1em button.edit-button z-index 2 - position absolute - right 0 - top 0 + opacity 0.6 + padding 0.2em 0.6em + margin-left 10px + + flex(shrink: 0) + + &:hover + opacity 1 a color black text-decoration none - position relative - display block + // display block + flex(grow: 1, shrink: 1) + background-color white + border-radius 6px + + opacity 0.7 ul.choice z-index 1 - margin 1em 0 + // margin 1em 0 padding 0.5em - - background-color white - border-radius 6px - - opacity 0.7 + list-style none span font-weight bold @@ -43,6 +54,12 @@ padding-right 10px font-weight normal - &:hover - opacity 1 + &:hover + opacity 1 + box-shadow 0 0 3px 3px rgba(0,0,0,.1) + + ul + background-image url(/assets/checkmark.png) + background-repeat no-repeat + background-position 96% center diff --git a/app/models/workflow.rb b/app/models/workflow.rb index 7a380337a..0193fe1c3 100644 --- a/app/models/workflow.rb +++ b/app/models/workflow.rb @@ -19,6 +19,9 @@ class Workflow # this `false` to prevent a user's transcriptions from being verified by same # user: field :subjects_classifiable_by_creator, type: Boolean, default: true + # Controls whether the user-generated subject shown may be "edited" (cloned, really) + # Currently only implemented as an EDIT button in Verify (user can transcribe using a prev transcription as a basis) + field :subjects_editable, type: Boolean, default: true field :active_subjects, type: Integer, default: 0 field :order, type: Integer, default: 0 diff --git a/app/serializers/workflow_serializer.rb b/app/serializers/workflow_serializer.rb index 6627c38f3..dd842a0f3 100644 --- a/app/serializers/workflow_serializer.rb +++ b/app/serializers/workflow_serializer.rb @@ -1,5 +1,5 @@ class WorkflowSerializer < ActiveModel::MongoidSerializer - attributes :id, :name, :label, :tasks, :retire_limit, :subject_fetch_limit, :first_task, :active_subjects, :generates_subjects_for, :order + attributes :id, :name, :label, :tasks, :retire_limit, :subject_fetch_limit, :first_task, :active_subjects, :generates_subjects_for, :order, :subjects_editable def id object._id.to_s diff --git a/project/emigrant/workflows/verify.json b/project/emigrant/workflows/verify.json index 95dd6df05..04b58c446 100644 --- a/project/emigrant/workflows/verify.json +++ b/project/emigrant/workflows/verify.json @@ -8,6 +8,7 @@ "generates_subjects_max": 20, "generates_subjects_agreement": 0.75, "subjects_classifiable_by_creator": false, + "subjects_editable": true, "tasks": {