Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/develop' into feature/cedar-in…
Browse files Browse the repository at this point in the history
…tegration
  • Loading branch information
cslzchen committed Feb 2, 2024
2 parents 1a3dddb + 13f633d commit 0a507de
Show file tree
Hide file tree
Showing 58 changed files with 877 additions and 234 deletions.
6 changes: 2 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@ RUN apk add --no-cache --virtual .run-deps \
libevent \
&& yarn global add bower

RUN apk add curl
RUN curl https://bootstrap.pypa.io/pip/3.6/get-pip.py -o get-pip.py
RUN python3 get-pip.py --force-reinstall pip==21.0
RUN apk del curl
RUN python3 -m ensurepip && \
pip3 install --upgrade pip==21.0

WORKDIR /code

Expand Down
2 changes: 2 additions & 0 deletions README-docker-compose.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@
- Populate preprint, registration, and collection providers:
- After resetting your database or with a new install, the required providers and subjects will be created automatically **when you run migrations.** To create more:
- `docker-compose run --rm web python3 manage.py populate_fake_providers`
- _NOTE: In case, you encounter error with missing data, when running the `'populate_fake_providers'` command. Fix this with 'update_taxonomies' command:_
- `docker-compose run --rm web python3 -m scripts.update_taxonomies`
- Populate citation styles
- Needed for api v2 citation style rendering.
- `docker-compose run --rm web python3 -m scripts.parse_citation_styles`
Expand Down
6 changes: 1 addition & 5 deletions addons/wiki/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,7 @@ def check_spam(self):
)

def _get_spam_content(self, node):
content = []
content.append(self.raw_text(node))
if not content:
return None
return ' '.join(content)
return self.content or None

def clone_version(self, wiki_page, user):
"""Clone a node wiki page.
Expand Down
62 changes: 62 additions & 0 deletions admin/collection_providers/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class CollectionProviderForm(forms.ModelForm):
program_area_choices = forms.CharField(widget=forms.HiddenInput(), required=False)
school_type_choices = forms.CharField(widget=forms.HiddenInput(), required=False)
study_design_choices = forms.CharField(widget=forms.HiddenInput(), required=False)
data_type_choices = forms.CharField(widget=forms.HiddenInput(), required=False)
disease_choices = forms.CharField(widget=forms.HiddenInput(), required=False)
_id = forms.SlugField(
required=True,
help_text='URL Slug',
Expand Down Expand Up @@ -268,3 +270,63 @@ def clean_study_design_choices(self):
if choices:
added_choices = json.loads(choices)
return {'added': added_choices, 'removed': removed_choices}

def clean_disease_choices(self):
if not self.data.get('disease_choices'):
return {'added': [], 'removed': []}

collection_provider = self.instance
primary_collection = collection_provider.primary_collection
if primary_collection: # Modifying an existing CollectionProvider
old_choices = {c.strip(' ') for c in primary_collection.disease_choices}
updated_choices = {c.strip(' ') for c in json.loads(self.data.get('disease_choices'))}
added_choices = updated_choices - old_choices
removed_choices = old_choices - updated_choices

active_removed_choices = set(
primary_collection.collectionsubmission_set.filter(
disease__in=removed_choices
).values_list('disease', flat=True)
)
if active_removed_choices:
raise forms.ValidationError(
'Cannot remove the following choices for "disease", as they are '
f'currently in use: {active_removed_choices}'
)
else: # Creating a new CollectionProvider
added_choices = set()
removed_choices = set()
choices = self.data.get('disease_choices')
if choices:
added_choices = json.loads(choices)
return {'added': added_choices, 'removed': removed_choices}

def clean_data_type_choices(self):
if not self.data.get('data_type_choices'):
return {'added': [], 'removed': []}

collection_provider = self.instance
primary_collection = collection_provider.primary_collection
if primary_collection: # Modifying an existing CollectionProvider
old_choices = {c.strip(' ') for c in primary_collection.data_type_choices}
updated_choices = {c.strip(' ') for c in json.loads(self.data.get('data_type_choices'))}
added_choices = updated_choices - old_choices
removed_choices = old_choices - updated_choices

active_removed_choices = set(
primary_collection.collectionsubmission_set.filter(
data_type__in=removed_choices
).values_list('data_type', flat=True)
)
if active_removed_choices:
raise forms.ValidationError(
'Cannot remove the following choices for "data_type", as they are '
f'currently in use: {active_removed_choices}'
)
else: # Creating a new CollectionProvider
added_choices = set()
removed_choices = set()
choices = self.data.get('data_type_choices')
if choices:
added_choices = json.loads(choices)
return {'added': added_choices, 'removed': removed_choices}
59 changes: 31 additions & 28 deletions admin/collection_providers/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@
from admin.providers.views import AddAdminOrModerator, RemoveAdminsAndModerators


def _process_collection_choices(provider, choices_name, form):
collection = provider.primary_collection
choices_name_attr = f'{choices_name}_choices'
choices_added = form.cleaned_data[choices_name_attr]['added']
choices_removed = form.cleaned_data[choices_name_attr]['removed']

getattr(collection, choices_name_attr).extend(choices_added)
for item in choices_removed:
getattr(collection, choices_name_attr).remove(item)


class CreateCollectionProvider(PermissionRequiredMixin, CreateView):
raise_exception = True
permission_required = 'osf.change_collectionprovider'
Expand All @@ -47,6 +58,10 @@ def form_valid(self, form):
self.object.primary_collection.school_type_choices.append(item)
for item in form.cleaned_data['study_design_choices']['added']:
self.object.primary_collection.study_design_choices.append(item)
for item in form.cleaned_data['data_type_choices']['added']:
self.object.primary_collection.data_type_choices.append(item)
for item in form.cleaned_data['disease_choices']['added']:
self.object.primary_collection.disease_choices.append(item)
self.object.primary_collection.save()
return super().form_valid(form)

Expand Down Expand Up @@ -163,6 +178,16 @@ def get_context_data(self, *args, **kwargs):
))
kwargs['study_design_choices'] = study_design_choices_html

disease_choices_html = '<ul>{choices}</ul>'.format(choices=''.join(
f'<li>{choice}</li>' for choice in primary_collection.disease_choices
))
kwargs['disease_choices'] = disease_choices_html

data_type_choices_html = '<ul>{choices}</ul>'.format(choices=''.join(
f'<li>{choice}</li>' for choice in primary_collection.data_type_choices
))
kwargs['data_type_choices'] = data_type_choices_html

# get a dict of model fields so that we can set the initial value for the update form
fields = model_to_dict(collection_provider)
fields['collected_type_choices'] = json.dumps(primary_collection.collected_type_choices)
Expand All @@ -175,6 +200,8 @@ def get_context_data(self, *args, **kwargs):

fields['school_type_choices'] = json.dumps(primary_collection.school_type_choices)
fields['study_design_choices'] = json.dumps(primary_collection.study_design_choices)
fields['data_type_choices'] = json.dumps(primary_collection.data_type_choices)
fields['disease_choices'] = json.dumps(primary_collection.disease_choices)

# compile html list of collected_type_choices
if collection_provider.primary_collection:
Expand Down Expand Up @@ -235,34 +262,8 @@ class CollectionProviderChangeForm(PermissionRequiredMixin, UpdateView):

def form_valid(self, form):
if self.object.primary_collection:
self.object.primary_collection.collected_type_choices.extend(form.cleaned_data['collected_type_choices']['added'])
for item in form.cleaned_data['collected_type_choices']['removed']:
self.object.primary_collection.collected_type_choices.remove(item)

self.object.primary_collection.status_choices.extend(form.cleaned_data['status_choices']['added'])
for item in form.cleaned_data['status_choices']['removed']:
self.object.primary_collection.status_choices.remove(item)

self.object.primary_collection.issue_choices.extend(form.cleaned_data['issue_choices']['added'])
for item in form.cleaned_data['issue_choices']['removed']:
self.object.primary_collection.issue_choices.remove(item)

self.object.primary_collection.volume_choices.extend(form.cleaned_data['volume_choices']['added'])
for item in form.cleaned_data['volume_choices']['removed']:
self.object.primary_collection.volume_choices.remove(item)

self.object.primary_collection.program_area_choices.extend(form.cleaned_data['program_area_choices']['added'])
for item in form.cleaned_data['program_area_choices']['removed']:
self.object.primary_collection.program_area_choices.remove(item)

self.object.primary_collection.school_type_choices.extend(form.cleaned_data['school_type_choices']['added'])
for item in form.cleaned_data['school_type_choices']['removed']:
self.object.primary_collection.school_type_choices.remove(item)

self.object.primary_collection.study_design_choices.extend(form.cleaned_data['study_design_choices']['added'])
for item in form.cleaned_data['study_design_choices']['removed']:
self.object.primary_collection.study_design_choices.remove(item)

for choices_name in ['collected_type', 'status', 'issue', 'volume', 'program_area', 'school_type', 'study_design', 'data_type', 'disease']:
_process_collection_choices(self.object, choices_name, form)
self.object.primary_collection.save()
return super().form_valid(form)

Expand Down Expand Up @@ -399,6 +400,8 @@ def create_or_update_provider(self, provider_data):
provider.primary_collection.program_area_choices = primary_collection['fields']['program_area_choices']
provider.primary_collection.school_type_choices = primary_collection['fields']['school_type_choices']
provider.primary_collection.study_design_choices = primary_collection['fields']['study_design_choices']
provider.primary_collection.disease_choices = primary_collection['fields']['disease_choices']
provider.primary_collection.data_type_choices = primary_collection['fields']['data_type_choices']
provider.primary_collection.save()
if licenses:
provider.licenses_acceptable.set(licenses)
Expand Down
26 changes: 26 additions & 0 deletions admin/static/js/pages/collection-provider-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,22 @@ $('#tags-input-study-design').on('itemRemoved', function(event) {
$('#id_study_design_choices').val(JSON.stringify($('#tags-input-study-design').tagsinput('items')));
});

$('#tags-input-data-type').on('itemAdded', function(event) {
$('#id_data_type_choices').val(JSON.stringify($('#tags-input-data-type').tagsinput('items')));
});

$('#tags-input-data-type').on('itemRemoved', function(event) {
$('#id_data_type_choices').val(JSON.stringify($('#tags-input-data-type').tagsinput('items')));
});

$('#tags-input-disease').on('itemAdded', function(event) {
$('#id_disease_choices').val(JSON.stringify($('#tags-input-disease').tagsinput('items')));
});

$('#tags-input-disease').on('itemRemoved', function(event) {
$('#id_disease_choices').val(JSON.stringify($('#tags-input-disease').tagsinput('items')));
});


$(document).ready(function() {
var collectedTypeItems = JSON.parse($('#id_collected_type_choices').val());
Expand Down Expand Up @@ -93,4 +109,14 @@ $(document).ready(function() {
studyDesignItems.forEach(function(element){
$('#tags-input-study-design').tagsinput('add', element)
});

var diseaseItems = JSON.parse($('#id_disease_choices').val());
diseaseItems.forEach(function(element){
$('#tags-input-disease').tagsinput('add', element)
});

var dataTypeItems = JSON.parse($('#id_data_type_choices').val());
dataTypeItems.forEach(function(element){
$('#tags-input-data-type').tagsinput('add', element)
});
});
8 changes: 8 additions & 0 deletions admin/templates/collection_providers/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ <h2>{{ collection_provider.name }}</h2>
<th>study_design_choices</th>
<td>{{ study_design_choices | safe}}</td>
</tr>
<tr>
<th>disease_choices</th>
<td>{{ disease_choices | safe}}</td>
</tr>
<tr>
<th>data_type_choices</th>
<td>{{ data_type_choices | safe}}</td>
</tr>
</table>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,18 @@
<input id="tags-input-study-design" type="text" data-role="tagsinput"/>
</div>
</div>
<div>
<label>Disease choices:</label>
<div class=#bootstrap-tagsinput">
<input id="tags-input-disease" type="text" data-role="tagsinput"/>
</div>
</div>
<div>
<label>Data Type choices:</label>
<div class=#bootstrap-tagsinput">
<input id="tags-input-data-type" type="text" data-role="tagsinput"/>
</div>
</div>
<input class="form-button" type="submit" value="Save" />
</form>
</div>
Expand Down
2 changes: 1 addition & 1 deletion api/actions/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ class ReviewActionListCreate(JSONAPIBaseView, generics.ListCreateAPIView, ListFi
)

required_read_scopes = [CoreScopes.ACTIONS_READ]
required_write_scopes = [CoreScopes.NULL]
required_write_scopes = [CoreScopes.ACTIONS_WRITE]

parser_classes = (JSONAPIMultipleRelationshipsParser, JSONAPIMultipleRelationshipsParserForRegularJSON,)
serializer_class = ReviewActionSerializer
Expand Down
3 changes: 3 additions & 0 deletions api/base/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,9 @@ def to_representation(self, value):
or related_class.view_name == 'registration-citation':
related_id = resolved_url.kwargs['node_id']
related_type = 'citation'
elif related_class.view_name == 'preprint-citation':
related_id = resolved_url.kwargs['preprint_id']
related_type = 'citation'
elif related_type in ('preprint_providers', 'preprint-providers', 'registration-providers'):
related_id = resolved_url.kwargs['provider_id']
elif related_type in ('registrations', 'draft_nodes'):
Expand Down
20 changes: 20 additions & 0 deletions api/collections/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ class CollectionSerializer(JSONAPISerializer):
child=ser.CharField(max_length=127),
default=list(),
)
data_type_choices = ser.ListField(
child=ser.CharField(max_length=127),
default=list(),
)
disease_choices = ser.ListField(
child=ser.CharField(max_length=127),
default=list(),
)

links = LinksField({})

Expand Down Expand Up @@ -241,6 +249,8 @@ def subjects_view_kwargs(self):
program_area = ser.CharField(required=False)
school_type = ser.CharField(required=False)
study_design = ser.CharField(required=False)
data_type = ser.CharField(required=False)
disease = ser.CharField(required=False)

def get_absolute_url(self, obj):
return absolute_reverse(
Expand Down Expand Up @@ -272,6 +282,10 @@ def update(self, obj, validated_data):
obj.school_Type = validated_data.pop('school_type')
if 'study_design' in validated_data:
obj.study_design = validated_data.pop('study_design')
if 'data_type' in validated_data:
obj.data_type = validated_data.pop('data_type')
if 'disease' in validated_data:
obj.disease = validated_data.pop('disease')

obj.save()
return obj
Expand Down Expand Up @@ -337,6 +351,8 @@ def subjects_view_kwargs(self):
program_area = ser.CharField(required=False)
school_type = ser.CharField(required=False)
study_design = ser.CharField(required=False)
date_type = ser.CharField(required=False)
disease = ser.CharField(required=False)

def get_absolute_url(self, obj):
return absolute_reverse(
Expand Down Expand Up @@ -368,6 +384,10 @@ def update(self, obj, validated_data):
obj.school_Type = validated_data.pop('school_type')
if 'study_design' in validated_data:
obj.study_design = validated_data.pop('study_design')
if 'data_type' in validated_data:
obj.data_type = validated_data.pop('data_type')
if 'disease' in validated_data:
obj.disease = validated_data.pop('disease')

obj.save()
return obj
Expand Down
16 changes: 6 additions & 10 deletions api/nodes/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,12 @@ class NodeSerializer(TaxonomizableSerializerMixin, JSONAPISerializer):
related_view_kwargs={'node_id': '<_id>'},
)

subjects_acceptable = HideIfRegistration(RelationshipField(
related_view='subjects:subject-list',
related_view_kwargs={},
read_only=True,
))

@property
def subjects_related_view(self):
# Overrides TaxonomizableSerializerMixin
Expand Down Expand Up @@ -1562,12 +1568,6 @@ class DraftRegistrationLegacySerializer(JSONAPISerializer):
'html': 'get_absolute_url',
})

affiliate_user_institutions = ser.BooleanField(
required=False,
default=True,
help_text='Specify whether user institution affiliations should be copied over to the draft registration.',
)

def get_absolute_url(self, obj):
return obj.absolute_url

Expand Down Expand Up @@ -1608,7 +1608,6 @@ def create(self, validated_data):
registration_responses = validated_data.pop('registration_responses', None)
schema = validated_data.pop('registration_schema')
provider = validated_data.pop('provider', None)
affiliate_user_institutions = validated_data.pop('affiliate_user_institutions', True)

self.enforce_metadata_or_registration_responses(metadata, registration_responses)

Expand All @@ -1623,9 +1622,6 @@ def create(self, validated_data):
if registration_responses:
self.update_registration_responses(draft, registration_responses)

if affiliate_user_institutions and draft.branched_from_type == DraftNode:
draft.affiliated_institutions.set(draft.creator.affiliated_institutions.all())

return draft

class Meta:
Expand Down
Loading

0 comments on commit 0a507de

Please sign in to comment.