Skip to content

Commit

Permalink
Merge pull request #230 from lookit/208-ui-improvements-study-edit-ki…
Browse files Browse the repository at this point in the history
…m-review

208 ui improvements study edit kim review
  • Loading branch information
Datamance authored Jan 17, 2019
2 parents 921eb75 + 573fdf7 commit b25e33c
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 93 deletions.
18 changes: 10 additions & 8 deletions exp/views/study.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
from exp.mixins.study_responses_mixin import StudyResponsesMixin
from exp.views.mixins import ExperimenterLoginRequiredMixin, StudyTypeMixin
from project import settings
from studies.forms import StudyBuildForm, StudyForm, StudyUpdateForm
from studies.forms import StudyBuildForm, StudyForm, StudyEditForm
from studies.helpers import send_mail
from studies.models import Study, StudyLog, StudyType
from studies.tasks import build_experiment, build_zipfile_of_videos
from studies.workflow import STATE_UI_SIGNALS, STATUS_HELP_TEXT, TRANSITION_HELP_TEXT
from studies.workflow import STATE_UI_SIGNALS, STATUS_HELP_TEXT, TRANSITION_HELP_TEXT, TRANSITION_LABELS


class DiscoverabilityKey(NamedTuple):
Expand All @@ -41,17 +41,17 @@ class DiscoverabilityKey(NamedTuple):
public: bool


STUDY_LISTING_A_TAG = f'<a href="{settings.BASE_URL}/studies.">the study listing page</a>'
STUDY_LISTING_A_TAG = f'<a href="{settings.BASE_URL}/studies/">the study listing page</a>'


DISCOVERABILITY_HELP_TEXT = {
(True, True): 'Your study is active and public. Participants can access it at your study link, '
(True, True): 'Public. Your study is active and public. Participants can access it at your study link, '
f'and it can be found listed in {STUDY_LISTING_A_TAG}.',
(True, False): 'Your study is active, but not public. Participants may access it at your study link, '
(True, False): 'Private. Your study is active, but not public. Participants may access it at your study link, '
f'however will not be listed in {STUDY_LISTING_A_TAG}.',
(False, True): 'Your study is not currently active, but it is public. When it is active, participants will be able to access it at your study link, '
(False, True): 'Public. Your study is not currently active, but it is public. When it is active, participants will be able to access it at your study link, '
f'and it will be found listed in {STUDY_LISTING_A_TAG}. ',
(False, False): 'Your study is not currently active, and is not public. When it is active, participants will be able to access it at your study link, '
(False, False): 'Private. Your study is not currently active, and is not public. When it is active, participants will be able to access it at your study link, '
f'but it will not be listed in {STUDY_LISTING_A_TAG}. ',
}

Expand Down Expand Up @@ -331,6 +331,8 @@ def get_context_data(self, **kwargs):
context['study_admins'] = User.objects.filter(groups__name=admin_group.name).values_list('id', flat=True)
context['discoverability_text'] = get_discoverability_text(study)
context['transition_help'] = json.dumps(TRANSITION_HELP_TEXT)
context['triggers_with_labels'] = [{'name': trigger, 'label': TRANSITION_LABELS[trigger]}
for trigger in context['triggers']]
return context

def get_study_researchers(self):
Expand Down Expand Up @@ -434,7 +436,7 @@ class StudyUpdateView(ExperimenterLoginRequiredMixin, PermissionRequiredMixin, g
Also allows you to update the study status.
'''
template_name = 'studies/study_edit.html'
form_class = StudyUpdateForm
form_class = StudyEditForm
model = Study
permission_required = 'studies.can_edit_study'
raise_exception = True
Expand Down
86 changes: 37 additions & 49 deletions studies/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,36 @@ def clean(self):
return cleaned_data


# Form for editing an existing study
class StudyEditForm(BaseStudyForm):
# Form for creating a new study or editing an existing study
class StudyForm(BaseStudyForm):

structure = forms.CharField(label='Build Study - Add JSON',
widget=AceOverlayWidget(mode='json', wordwrap=True, theme='textmate', width='100%',
height='100%', showprintmargin=False), required=False,
help_text='Add the frames of your study as well as the sequence of those frames. This can be added later.')

def clean_structure(self):
structure = self.cleaned_data['structure']
try:
json_data = json.loads(structure) # loads string as json
except:
raise forms.ValidationError("Save failed due to invalid JSON! Please use valid JSON and save again. If you reload this page, all changes will be lost.")
return json_data

class Meta:
model = Study
fields = ['name', 'image', 'short_description', 'long_description', 'exit_url', 'criteria', 'min_age_days', 'min_age_months', 'min_age_years', 'max_age_days', 'max_age_months', 'max_age_years', 'duration', 'contact_info', 'public']
fields = ['name', 'image', 'short_description', 'long_description', 'exit_url',
'criteria', 'min_age_days', 'min_age_months', 'min_age_years', 'max_age_days',
'max_age_months', 'max_age_years', 'duration', 'contact_info', 'public',
'structure', 'study_type']
labels = {
'short_description': 'Short Description',
'long_description': 'Purpose',
'exit_url': 'Exit URL',
'criteria': 'Participant Eligibility',
'contact_info': 'Researcher Contact Information',
'public': 'Discoverable - Do you want this study to be publicly discoverable on Lookit once activated?'
'public': 'Discoverable - Do you want this study to be publicly discoverable on Lookit once activated?',
'study_type': 'Study Type'
}
widgets = {
'short_description': Textarea(attrs={'rows': 2}),
Expand All @@ -62,53 +79,24 @@ class Meta:
'short_description': 'Give your study a description here.',
'long_description': 'Explain the purpose of your study here.',
'contact_info': 'This should give the name of the PI for your study, and an email address where the PI or study staff can be reached with questions. Format: PIs Name (contact: [email protected])',
'criteria': 'Text shown to families - this is not used to actually verify eligibility.'
'criteria': 'Text shown to families - this is not used to actually verify eligibility.',
'study_type': '''<p>After selecting a study type above, you'll be asked
to fill out some study type metadata as well. This metadata is unique to the
study type, and provides important configurations for building your study.</p>
<p>If you're not sure what to enter here, just leave the defaults (you can change this later).</p>
<p>For more information on study types and their metadata, please
<a href="https://lookit.readthedocs.io/en/develop/experimenter.html#editing-study-type">see the documentation.</a></p>'''
}


# Form for creating a new study. Set study_type and structure in same form
# in this case, rather than separately in the build form.
class StudyForm(StudyEditForm):
structure = forms.CharField(label='Build Study - Add JSON', widget=AceOverlayWidget(mode='json', wordwrap=True, theme='textmate', width='100%', height='100%', showprintmargin=False), required=False, help_text='Add the frames of your study as well as the sequence of those frames. This can be added later.')

def clean_structure(self):
structure = self.cleaned_data['structure']
try:
json_data = json.loads(structure) # loads string as json
except:
raise forms.ValidationError("Save failed due to invalid JSON! Please use valid JSON and save again. If you reload this page, all changes will be lost.")
return json_data

class Meta(StudyEditForm.Meta):
fields = StudyEditForm.Meta.fields + ['structure', 'study_type']

labels = StudyEditForm.Meta.labels.copy()
labels['study_type'] = 'Study Type'

help_texts = StudyEditForm.Meta.help_texts.copy()
help_texts['study_type'] = "Specify the build process as well as the parameters needed by the experiment builder. If you don't know what this is, just select the default."


class StudyUpdateForm(StudyEditForm):
structure = forms.CharField(label='Build Study - Add JSON',
widget=AceOverlayWidget(mode='json', wordwrap=True, theme='textmate', width='100%',
height='100%', showprintmargin=False), required=False,
help_text='Add the frames of your study as well as the sequence of those frames. This can be added later.')

def clean_structure(self):
structure = self.cleaned_data['structure']
try:
json_data = json.loads(structure) # loads string as json
except:
raise forms.ValidationError("Save failed due to invalid JSON! Please use valid JSON and save again. If you reload this page, all changes will be lost.")
return json_data

class Meta(StudyEditForm.Meta):
fields = StudyEditForm.Meta.fields + ['structure']

labels = StudyEditForm.Meta.labels.copy()

help_texts = StudyEditForm.Meta.help_texts.copy()
class StudyEditForm(StudyForm):

class Meta(StudyForm.Meta):
help_texts = StudyForm.Meta.help_texts.copy()
help_texts['study_type'] += '''<p class="help-block"> Once you've filled in the required metadata, you'll have to build the dependencies for your
experiment in order to deploy it, which you can do from the detail page. However, you'll
probably want to see what your experiment looks like before you actually deploy it and start
collecting data! You can do that by clicking the "Build Preview Dependencies" button and
then clicking on "See Preview" above after the build finishes.</p>'''


class StudyBuildForm(forms.ModelForm):
Expand Down
19 changes: 12 additions & 7 deletions studies/templates/studies/study_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,14 @@ <h1 class="col-xs-6"> {{ study.name }} </h1>
<div class="row">
<div class="col-xs-4">
{% include "studies/_image_display.html" with object=study large=1 %}
<div class="row">
<div class="col-xs-12">
<p>
<span class="pr-md"><label
class='pr-xs'> Last edited: </label> {{ study.date_modified |date:"M d, Y" }} </span>
</p>
</div>
</div>
</div>
<div class="col-xs-8">
{# PUT THE DESCRIPTION STUFF HERE #}
Expand Down Expand Up @@ -242,8 +250,6 @@ <h1 class="col-xs-6"> {{ study.name }} </h1>
class='pr-xs'> Minimum age cutoff: </label> {{ study.min_age_years }} year{{ study.min_age_years|pluralize }} {{ study.min_age_months }} month{{ study.min_age_months|pluralize }} {{ study.min_age_days }} day{{ study.min_age_days|pluralize }} </span>
<span class="pr-md"><label
class='pr-xs'> Maximum age cutoff: </label> {{ study.max_age_years }} year{{ study.max_age_years|pluralize }} {{ study.max_age_months }} month{{ study.max_age_months|pluralize }} {{ study.max_age_days }} day{{ study.max_age_days|pluralize }}</span>
<span class="pr-md"><label
class='pr-xs'> Last edited: </label> {{ study.date_modified |date:"M d, Y" }} </span>
</p>
</div>
</div>
Expand All @@ -252,8 +258,6 @@ <h1 class="col-xs-6"> {{ study.name }} </h1>
<p>
<span class="pr-md"><label class='pr-xs'> UUID: </label></span>
{{ study.uuid }}
<div class="small uuid-padding"><em>This is the study id that participants will see</em>
</div>
</p>
</div>
</div>
Expand All @@ -267,6 +271,7 @@ <h1 class="col-xs-6"> {{ study.name }} </h1>
</div>
<div class="col-xs-12">
{% if study.built %}
<span><label>Study link: </label></span>
<div class="input-group">
<input type="text" class="form-control" id="private-study-link"
value="{% url 'web:study-detail' study.uuid %}"
Expand Down Expand Up @@ -296,10 +301,10 @@ <h1 class="col-xs-6"> {{ study.name }} </h1>
Change State <span class="caret"></span>
</a>
<ul class="dropdown-menu">
{% for trigger in triggers %}
{% for trigger in triggers_with_labels %}
<li role="button" onclick="onStateSelect(this)" data-toggle="modal"
href="#study-state-modal" data-trigger="{{ trigger }}">
<a>{{ trigger }}</a>
href="#study-state-modal" data-trigger="{{ trigger.name }}">
<a>{{ trigger.label }}</a>
</li>
{% endfor %}
</ul>
Expand Down
30 changes: 1 addition & 29 deletions studies/templates/studies/study_edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -129,35 +129,7 @@ <h1 class="panel-title">Change Study Type and Dependencies</h1>
<div class="panel-body">
<form id="study-type-form" method="POST">{% csrf_token %}

<div class="form-group">
<label class="control-label" for="id_study_type">Study Type</label>
<select name="study_type" class="form-control" title="" required="" id="id_study_type">
<option value="">---------</option>
{% for option in study_types %}
<option {% if option.name == study.study_type.name %} selected {% endif %}
value="{{ option.id }}"> {{ option.name }}
</option>
{% endfor %}
</select>
<p class="help-block">
After selecting a study type above, you'll be asked to fill out some study type
metadata
as well. This metadata is unique to the study type, and provides important
configurations
for building your study.
<p class="help-block">For more information on study types and their metadata,
please
<a href="https://lookit.readthedocs.io/en/develop/experimenter.html#editing-study-type">see the documentation.</a></p>
</p>
<p class="help-block">
Once you've filled in the required metadata, you'll have to build the dependencies
for your experiment in order to deploy it, which you can do from the detail page.
However, you'll probably want to see what your experiment looks like <em>before</em>
you actually deploy it and start collecting data! You can do that by clicking the
"Build Preview Dependencies" button and then clicking on "See Preview" above after
the build finishes.
</p>
</div>
{% bootstrap_field form.study_type %}
{% include "studies/_study_type.html" with types=types create=0 currentType=study.study_type.id %}
<div class="pull-right">
<a class="btn btn-default" href="{% url 'exp:study-edit' study.id %}"> Discard
Expand Down
12 changes: 12 additions & 0 deletions studies/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,15 @@
"deactivate": "This will archive the study and prevent participants from accessing it. You will still be able to access your study data, but would need to resubmit it to collect more data. If you expect to collect more data for this study, use the Pause action instead.",
"archive": "This will effectively delete your study! You will not be able to access your study or any response data. If you have already collected participant data or might want your study protocol for reference, deactivate instead."
}

TRANSITION_LABELS = {
"submit": "Submit (submit study for Lookit admin review)",
"resubmit": "Submit (submit study for Lookit admin review)",
"reject": "Reject (request changes before researchers can collect data)",
"retract": "Retract (retract request for Lookit admin study review)",
"approve": "Approve (allow researchers to start data collection)",
"activate": "Start (start data collection - make study accessible to participants)",
"pause": "Pause (pause data collection - make study inaccessible to participants)",
"deactivate": "Deactivate (archive study - data collection is complete)",
"archive": "Delete (delete study and any data)"
}

0 comments on commit b25e33c

Please sign in to comment.