Skip to content

Commit dd06be1

Browse files
committed
Merge branch 'release/0.117.0'
2 parents 5f321d5 + 280295d commit dd06be1

File tree

129 files changed

+8390
-5971
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+8390
-5971
lines changed

addons/base/views.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -748,12 +748,23 @@ def addon_view_file(auth, node, file_node, version):
748748
'file_tags': list(file_node.tags.filter(system=False).values_list('name', flat=True)) if not file_node._state.adding else [], # Only access ManyRelatedManager if saved
749749
'file_guid': file_node.get_guid()._id,
750750
'file_id': file_node._id,
751-
'allow_comments': file_node.provider in settings.ADDONS_COMMENTABLE
751+
'allow_comments': file_node.provider in settings.ADDONS_COMMENTABLE,
752+
'checkout_user': file_node.checkout._id if file_node.checkout else None,
753+
'pre_reg_checkout': is_pre_reg_checkout(node, file_node),
752754
})
753755

754756
ret.update(rubeus.collect_addon_assets(node))
755757
return ret
756758

759+
def is_pre_reg_checkout(node, file_node):
760+
checkout_user = file_node.checkout
761+
if not checkout_user:
762+
return False
763+
if checkout_user in node.contributors:
764+
return False
765+
if checkout_user.has_perm('osf.prereg_view'):
766+
return node.draft_registrations_active.filter(registration_schema__name='Prereg Challenge').exists()
767+
return False
757768

758769
def get_archived_from_url(node, file_node):
759770
if file_node.copied_from:

addons/forward/apps.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ class ForwardAddonAppConfig(BaseAddonAppConfig):
1313

1414
name = 'addons.forward'
1515
label = 'addons_forward'
16-
full_name = 'External Link'
16+
full_name = 'Redirect Link'
1717
short_name = 'forward'
18-
configs = ['node']
18+
configs = []
1919
owners = ['node']
2020
views = ['widget']
2121
categories = ['other']

addons/forward/static/forwardConfig.js

Lines changed: 86 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,29 @@ var $osf = require('js/osfHelpers');
88

99
var MESSAGE_TIMEOUT = 5000;
1010

11-
var DEFAULT_FORWARD_BOOL = true;
12-
1311
/**
1412
* Knockout view model for the Forward node settings widget.
1513
*/
16-
var ViewModel = function(url, nodeId) {
14+
var ViewModel = function(node, enabled, url, label) {
1715

1816
var self = this;
1917

20-
// Forward configuration
21-
self.url = ko.observable().extend({
18+
var forwardUrl = $osf.apiV2Url('nodes/' + node.id + '/addons/forward/');
19+
20+
self.enabled = ko.observable(enabled);
21+
self.label = koHelpers.sanitizedObservable(label);
22+
self.url = ko.observable(url).extend({
2223
ensureHttp: true,
2324
url: true,
2425
required: true
2526
});
27+
28+
// Flashed messages
29+
self.message = ko.observable('');
30+
self.messageClass = ko.observable('text-info');
31+
32+
self.pendingRequest = ko.observable(false);
33+
2634
ko.validation.addAnonymousRule(
2735
self.url,
2836
koHelpers.makeRegexValidator(
@@ -31,50 +39,54 @@ var ViewModel = function(url, nodeId) {
3139
false
3240
)
3341
);
34-
self.label = koHelpers.sanitizedObservable();
35-
36-
// Flashed messages
37-
self.message = ko.observable('');
38-
self.messageClass = ko.observable('text-info');
3942

4043
self.validators = ko.validatedObservable({
4144
url: self.url,
4245
});
4346

44-
45-
/**
46-
* Update the view model from data returned from the server.
47-
*/
48-
self.updateFromData = function(data) {
49-
self.url(data.url);
50-
self.label(data.label);
51-
};
52-
53-
self.fetchFromServer = function() {
54-
$.ajax({
55-
type: 'GET',
56-
url: url,
57-
dataType: 'json'
58-
}).done(function(response) {
59-
self.updateFromData(response);
60-
}).fail(function(xhr, textStatus, error) {
61-
self.changeMessage('Could not retrieve Forward settings at ' +
62-
'this time. Please refresh ' +
63-
'the page. If the problem persists, email ' +
64-
'<a href="mailto:support@osf.io">support@osf.io</a>.',
65-
'text-danger');
66-
Raven.captureMessage('Could not GET get Forward addon settings.', {
67-
extra: {
68-
url: url,
69-
textStatus: textStatus,
70-
error: error
47+
self.enabled.subscribe(function(newValue) {
48+
self.pendingRequest(true);
49+
if (!newValue) {
50+
$osf.ajaxJSON(
51+
'delete',
52+
forwardUrl,
53+
{'isCors': true}
54+
).done(function(response) {
55+
self.pendingRequest(false);
56+
}).fail(function(xhr, status, error) {
57+
$osf.growl('Error', 'Unable to disable redirect link.');
58+
Raven.captureMessage('Error disabling redirect link.', {
59+
extra: {
60+
url: forwardUrl, status: status, error: error
61+
}
62+
});
63+
});
64+
} else {
65+
$osf.ajaxJSON(
66+
'post',
67+
forwardUrl,
68+
{
69+
'data': {
70+
'data': {
71+
'id': 'forward',
72+
'type': 'node_addons',
73+
'attributes': {}
74+
}
75+
},
76+
'isCors': true
7177
}
78+
).done(function(response) {
79+
self.pendingRequest(false);
80+
}).fail(function(xhr, status, error) {
81+
$osf.growl('Error', 'Unable to enable redirect link.');
82+
Raven.captureMessage('Error enabling redirect link.', {
83+
extra: {
84+
url: forwardUrl, status: status, error: error
85+
}
86+
});
7287
});
73-
});
74-
};
75-
76-
// Initial fetch from server
77-
self.fetchFromServer();
88+
}
89+
});
7890

7991
function onSubmitSuccess() {
8092
if (self.url() == null) {
@@ -103,24 +115,45 @@ var ViewModel = function(url, nodeId) {
103115
}
104116
else {
105117
self.changeMessage(
106-
'Could not change settings. Please try again later.',
118+
'Could not change redirect link settings. Please try again later.',
107119
'text-danger'
108120
);
121+
Raven.captureMessage('Error updating redirect link.', {
122+
extra: {
123+
url: forwardUrl, status: status, error: error
124+
}
125+
});
109126
}
110127
}
111128

112129
/**
113130
* Submit new settings.
114131
*/
115132
self.submitSettings = function() {
116-
$osf.putJSON(
117-
url,
118-
ko.toJS(self)
119-
).done(
120-
onSubmitSuccess
121-
).fail(
122-
onSubmitError
123-
);
133+
self.pendingRequest(true);
134+
$osf.ajaxJSON(
135+
'put',
136+
forwardUrl,
137+
{
138+
'data': {
139+
'data': {
140+
'id': 'forward',
141+
'type': 'node_addons',
142+
'attributes': {
143+
'url': self.url(),
144+
'label': self.label()
145+
}
146+
}
147+
},
148+
'isCors': true
149+
}
150+
).done(function(response) {
151+
onSubmitSuccess()
152+
self.pendingRequest(false);
153+
}).fail(function(response) {
154+
onSubmitError()
155+
self.pendingRequest(false);
156+
});
124157
};
125158

126159
/** Change the flashed message. */
@@ -140,9 +173,9 @@ var ViewModel = function(url, nodeId) {
140173
};
141174

142175
// Public API
143-
function ForwardConfig(selector, url, nodeId) {
176+
function ForwardConfig(selector, node, enabled, url, label) {
144177
var self = this;
145-
self.viewModel = new ViewModel(url, nodeId);
178+
self.viewModel = new ViewModel(node, enabled, url, label);
146179
$osf.applyBindings(self.viewModel, selector);
147180
}
148181

addons/forward/static/node-cfg.js

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,31 @@
1+
var $osf = require('js/osfHelpers');
12
var ForwardConfig = require('./forwardConfig.js');
23

3-
var url = window.contextVars.node.urls.api + 'forward/config/';
4-
// #forwardScope will only be in the DOM if the addon is properly configured
5-
if ($('#forwardScope')[0]) {
6-
new ForwardConfig('#forwardScope', url, window.contextVars.node.id);
7-
}
4+
var ctx = window.contextVars;
5+
6+
var enabled = false;
7+
var url = '';
8+
var label = '';
9+
10+
$(document).ready(function() {
11+
$osf.ajaxJSON(
12+
'GET',
13+
$osf.apiV2Url('nodes/' + ctx.node.id + '/addons/'),
14+
{'isCors': true}
15+
).done(function(response){
16+
response.data.forEach(function(addon) {
17+
if (addon.id === 'forward') {
18+
enabled = true;
19+
url = addon.attributes.url;
20+
label = addon.attributes.label;
21+
}
22+
});
23+
new ForwardConfig('#configureForward', ctx.node, enabled, url, label);
24+
}).fail(function(response){
25+
$osf.growl('Error:', 'Unable to retrieve settings.');
26+
Raven.captureMessage('Error occurred retrieving node addons');
27+
});
28+
29+
});
30+
31+

addons/forward/templates/forward_node_settings.mako

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
<div id="forwardScope" class="scripted">
22

3-
<h4 class="addon-title">
4-
<i class="fa fa-external-link"></i>
5-
External Link
6-
</h4>
7-
83
<!-- Settings Pane -->
94
<div class="forward-settings">
105

@@ -16,7 +11,7 @@
1611
id="forwardUrl"
1712
class="form-control"
1813
data-bind="value: url"
19-
placeholder="Required"
14+
placeholder="Send people who visit your OSF project page to this link instead"
2015
/>
2116
</div>
2217

admin/base/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
url(r'^password/', include('password_reset.urls')),
2222
url(r'^nodes/', include('admin.nodes.urls', namespace='nodes')),
2323
url(r'^preprints/', include('admin.preprints.urls', namespace='preprints')),
24+
url(r'^subjects/', include('admin.subjects.urls', namespace='subjects')),
2425
url(r'^users/', include('admin.users.urls', namespace='users')),
2526
url(r'^meetings/', include('admin.meetings.urls',
2627
namespace='meetings')),

admin/nodes/urls.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
name='confirm-spam'),
2424
url(r'^(?P<guid>[a-z0-9]+)/confirm_ham/$', views.NodeConfirmHamView.as_view(),
2525
name='confirm-ham'),
26+
url(r'^(?P<guid>[a-z0-9]+)/reindex_share_node/$', views.NodeReindexShare.as_view(),
27+
name='reindex-share-node'),
28+
url(r'^(?P<guid>[a-z0-9]+)/reindex_elastic_node/$', views.NodeReindexElastic.as_view(),
29+
name='reindex-elastic-node'),
2630
url(r'^(?P<node_id>[a-z0-9]+)/remove_user/(?P<user_id>[a-z0-9]+)/$',
2731
views.NodeRemoveContributorView.as_view(), name='remove_user'),
2832
]

admin/nodes/views.py

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from django.contrib.auth.mixins import PermissionRequiredMixin
99
from modularodm import Q
1010

11+
from website import search
1112
from osf.models import NodeLog
1213
from osf.models.user import OSFUser
1314
from osf.models.node import Node
@@ -19,9 +20,14 @@
1920
NODE_REMOVED,
2021
NODE_RESTORED,
2122
CONTRIBUTOR_REMOVED,
22-
CONFIRM_SPAM, CONFIRM_HAM)
23+
CONFIRM_SPAM,
24+
CONFIRM_HAM,
25+
REINDEX_SHARE,
26+
REINDEX_ELASTIC,
27+
)
2328
from admin.nodes.templatetags.node_extras import reverse_node
2429
from admin.nodes.serializers import serialize_node, serialize_simple_user_and_node_permissions
30+
from website.project.tasks import update_share
2531
from website.project.views.register import osf_admin_change_status_identifier
2632

2733

@@ -238,7 +244,7 @@ def get_queryset(self):
238244
query = (
239245
Q('spam_status', 'eq', self.SPAM_STATE)
240246
)
241-
return Node.find(query).sort(self.ordering)
247+
return Node.find(query).order_by(self.ordering)
242248

243249
def get_context_data(self, **kwargs):
244250
query_set = kwargs.pop('object_list', self.object_list)
@@ -318,3 +324,43 @@ def delete(self, request, *args, **kwargs):
318324
action_flag=CONFIRM_HAM
319325
)
320326
return redirect(reverse_node(self.kwargs.get('guid')))
327+
328+
class NodeReindexShare(PermissionRequiredMixin, NodeDeleteBase):
329+
template_name = 'nodes/reindex_node_share.html'
330+
permission_required = 'osf.mark_spam'
331+
raise_exception = True
332+
333+
def get_object(self, queryset=None):
334+
return Node.load(self.kwargs.get('guid')) or Registration.load(self.kwargs.get('guid'))
335+
336+
def delete(self, request, *args, **kwargs):
337+
node = self.get_object()
338+
update_share(node)
339+
update_admin_log(
340+
user_id=self.request.user.id,
341+
object_id=node._id,
342+
object_repr='Node',
343+
message='Node Reindexed (SHARE): {}'.format(node._id),
344+
action_flag=REINDEX_SHARE
345+
)
346+
return redirect(reverse_node(self.kwargs.get('guid')))
347+
348+
class NodeReindexElastic(PermissionRequiredMixin, NodeDeleteBase):
349+
template_name = 'nodes/reindex_node_elastic.html'
350+
permission_required = 'osf.mark_spam'
351+
raise_exception = True
352+
353+
def get_object(self, queryset=None):
354+
return Node.load(self.kwargs.get('guid')) or Registration.load(self.kwargs.get('guid'))
355+
356+
def delete(self, request, *args, **kwargs):
357+
node = self.get_object()
358+
search.search.update_node(node, bulk=False, async=False)
359+
update_admin_log(
360+
user_id=self.request.user.id,
361+
object_id=node._id,
362+
object_repr='Node',
363+
message='Node Reindexed (Elastic): {}'.format(node._id),
364+
action_flag=REINDEX_ELASTIC
365+
)
366+
return redirect(reverse_node(self.kwargs.get('guid')))

admin/preprint_providers/views.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,12 @@ def get_context_data(self, *args, **kwargs):
8686
preprint_provider_attributes = model_to_dict(preprint_provider)
8787
kwargs.setdefault('page_number', self.request.GET.get('page', '1'))
8888

89-
preprint_provider_attributes['licenses_acceptable'] = preprint_provider.licenses_acceptable.values_list('name', flat=True)
89+
licenses_acceptable = list(preprint_provider.licenses_acceptable.values_list('name', flat=True))
90+
licenses_html = '<ul>'
91+
for license in licenses_acceptable:
92+
licenses_html += '<li>{}</li>'.format(license)
93+
licenses_html += '</ul>'
94+
preprint_provider_attributes['licenses_acceptable'] = licenses_html
9095

9196
subject_html = '<ul class="three-cols">'
9297
for parent in preprint_provider.top_level_subjects:

0 commit comments

Comments
 (0)