forked from enviPath/enviPy
Implement functionality to assigne Licenses to Packages and show existing Licenses (#17)
Co-authored-by: Tim Lorsbach <tim@lorsba.ch> Reviewed-on: enviPath/enviPy#17
This commit is contained in:
@ -204,9 +204,14 @@ class ScenarioMixin(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
class License(models.Model):
|
||||||
|
link = models.URLField(blank=False, null=False, verbose_name='link')
|
||||||
|
image_link = models.URLField(blank=False, null=False, verbose_name='Image link')
|
||||||
|
|
||||||
|
|
||||||
class Package(EnviPathModel):
|
class Package(EnviPathModel):
|
||||||
reviewed = models.BooleanField(verbose_name='Reviewstatus', default=False)
|
reviewed = models.BooleanField(verbose_name='Reviewstatus', default=False)
|
||||||
|
license = models.ForeignKey('epdb.License', on_delete=models.SET_NULL, blank=True, null=True, verbose_name='License')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.name} (pk={self.pk})"
|
return f"{self.name} (pk={self.pk})"
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
from typing import List, Dict, Any
|
||||||
|
|
||||||
from django.conf import settings as s
|
from django.conf import settings as s
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
@ -11,7 +12,7 @@ from utilities.chem import FormatConverter, IndigoUtils
|
|||||||
from .logic import GroupManager, PackageManager, UserManager, SettingManager
|
from .logic import GroupManager, PackageManager, UserManager, SettingManager
|
||||||
from .models import Package, GroupPackagePermission, Group, CompoundStructure, Compound, Reaction, Rule, Pathway, Node, \
|
from .models import Package, GroupPackagePermission, Group, CompoundStructure, Compound, Reaction, Rule, Pathway, Node, \
|
||||||
EPModel, EnviFormer, MLRelativeReasoning, RuleBaseRelativeReasoning, Scenario, SimpleAmbitRule, APIToken, \
|
EPModel, EnviFormer, MLRelativeReasoning, RuleBaseRelativeReasoning, Scenario, SimpleAmbitRule, APIToken, \
|
||||||
UserPackagePermission, Permission
|
UserPackagePermission, Permission, License, User
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -20,7 +21,7 @@ def log_post_params(request):
|
|||||||
logger.debug(f"{k}\t{v}")
|
logger.debug(f"{k}\t{v}")
|
||||||
|
|
||||||
|
|
||||||
def get_base_context(request):
|
def get_base_context(request) -> Dict[str, Any]:
|
||||||
current_user = _anonymous_or_real(request)
|
current_user = _anonymous_or_real(request)
|
||||||
|
|
||||||
ctx = {
|
ctx = {
|
||||||
@ -47,7 +48,7 @@ def _anonymous_or_real(request):
|
|||||||
return get_user_model().objects.get(username='anonymous')
|
return get_user_model().objects.get(username='anonymous')
|
||||||
|
|
||||||
|
|
||||||
def breadcrumbs(first_level_object=None, second_level_namespace=None, second_level_object=None):
|
def breadcrumbs(first_level_object=None, second_level_namespace=None, second_level_object=None) -> List[Dict[str, str]]:
|
||||||
bread = [
|
bread = [
|
||||||
{'Home': s.SERVER_URL},
|
{'Home': s.SERVER_URL},
|
||||||
{'Package': s.SERVER_URL + '/package'},
|
{'Package': s.SERVER_URL + '/package'},
|
||||||
@ -130,6 +131,8 @@ def compounds(request):
|
|||||||
for p in PackageManager.get_reviewed_packages():
|
for p in PackageManager.get_reviewed_packages():
|
||||||
reviewed_compound_qs |= Compound.objects.filter(package=p)
|
reviewed_compound_qs |= Compound.objects.filter(package=p)
|
||||||
|
|
||||||
|
reviewed_compound_qs = reviewed_compound_qs.order_by('name')
|
||||||
|
|
||||||
if request.GET.get('all'):
|
if request.GET.get('all'):
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
"objects": [
|
"objects": [
|
||||||
@ -138,7 +141,7 @@ def compounds(request):
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
context['reviewed_objects'] = reviewed_compound_qs.order_by('name')
|
context['reviewed_objects'] = reviewed_compound_qs
|
||||||
return render(request, 'collections/objects_list.html', context)
|
return render(request, 'collections/objects_list.html', context)
|
||||||
|
|
||||||
elif request.method == 'POST':
|
elif request.method == 'POST':
|
||||||
@ -162,7 +165,9 @@ def rules(request):
|
|||||||
reviewed_rule_qs = Rule.objects.none()
|
reviewed_rule_qs = Rule.objects.none()
|
||||||
|
|
||||||
for p in PackageManager.get_reviewed_packages():
|
for p in PackageManager.get_reviewed_packages():
|
||||||
reviewed_rule_qs |= Rule.objects.filter(package=p).order_by('name')
|
reviewed_rule_qs |= Rule.objects.filter(package=p)
|
||||||
|
|
||||||
|
reviewed_rule_qs = reviewed_rule_qs.order_by('name')
|
||||||
|
|
||||||
if request.GET.get('all'):
|
if request.GET.get('all'):
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
@ -198,6 +203,8 @@ def reactions(request):
|
|||||||
for p in PackageManager.get_reviewed_packages():
|
for p in PackageManager.get_reviewed_packages():
|
||||||
reviewed_reaction_qs |= Reaction.objects.filter(package=p).order_by('name')
|
reviewed_reaction_qs |= Reaction.objects.filter(package=p).order_by('name')
|
||||||
|
|
||||||
|
reviewed_reaction_qs = reviewed_reaction_qs.order_by('name')
|
||||||
|
|
||||||
if request.GET.get('all'):
|
if request.GET.get('all'):
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
"objects": [
|
"objects": [
|
||||||
@ -233,6 +240,8 @@ def pathways(request):
|
|||||||
for p in PackageManager.get_reviewed_packages():
|
for p in PackageManager.get_reviewed_packages():
|
||||||
reviewed_pathway_qs |= Pathway.objects.filter(package=p).order_by('name')
|
reviewed_pathway_qs |= Pathway.objects.filter(package=p).order_by('name')
|
||||||
|
|
||||||
|
reviewed_pathway_qs = reviewed_pathway_qs.order_by('name')
|
||||||
|
|
||||||
if request.GET.get('all'):
|
if request.GET.get('all'):
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
"objects": [
|
"objects": [
|
||||||
@ -268,6 +277,8 @@ def scenarios(request):
|
|||||||
for p in PackageManager.get_reviewed_packages():
|
for p in PackageManager.get_reviewed_packages():
|
||||||
reviewed_scenario_qs |= Scenario.objects.filter(package=p).order_by('name')
|
reviewed_scenario_qs |= Scenario.objects.filter(package=p).order_by('name')
|
||||||
|
|
||||||
|
reviewed_scenario_qs = reviewed_scenario_qs.order_by('name')
|
||||||
|
|
||||||
if request.GET.get('all'):
|
if request.GET.get('all'):
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
"objects": [
|
"objects": [
|
||||||
@ -311,6 +322,8 @@ def models(request):
|
|||||||
for p in PackageManager.get_reviewed_packages():
|
for p in PackageManager.get_reviewed_packages():
|
||||||
reviewed_model_qs |= EPModel.objects.filter(package=p).order_by('name')
|
reviewed_model_qs |= EPModel.objects.filter(package=p).order_by('name')
|
||||||
|
|
||||||
|
reviewed_model_qs = reviewed_model_qs.order_by('name')
|
||||||
|
|
||||||
if request.GET.get('all'):
|
if request.GET.get('all'):
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
"objects": [
|
"objects": [
|
||||||
@ -535,11 +548,11 @@ def package(request, package_uuid):
|
|||||||
|
|
||||||
if s.DEBUG:
|
if s.DEBUG:
|
||||||
for k, v in request.POST.items():
|
for k, v in request.POST.items():
|
||||||
print(k, v)
|
logger.debug(f"{k}\t{v}")
|
||||||
|
|
||||||
if hidden := request.POST.get('hidden', None):
|
if hidden := request.POST.get('hidden', None):
|
||||||
if hidden == 'delete-package':
|
if hidden == 'delete-package':
|
||||||
print(current_package.delete())
|
logger.debug(current_package.delete())
|
||||||
return redirect(s.SERVER_URL + '/package')
|
return redirect(s.SERVER_URL + '/package')
|
||||||
else:
|
else:
|
||||||
return HttpResponseBadRequest()
|
return HttpResponseBadRequest()
|
||||||
@ -552,6 +565,9 @@ def package(request, package_uuid):
|
|||||||
write = request.POST.get('write') == 'on'
|
write = request.POST.get('write') == 'on'
|
||||||
owner = request.POST.get('owner') == 'on'
|
owner = request.POST.get('owner') == 'on'
|
||||||
|
|
||||||
|
license = request.POST.get('license')
|
||||||
|
license_link = request.POST.get('license-link')
|
||||||
|
license_image_link = request.POST.get('license-image-link')
|
||||||
|
|
||||||
if new_package_name:
|
if new_package_name:
|
||||||
current_package.name = new_package_name
|
current_package.name = new_package_name
|
||||||
@ -578,10 +594,33 @@ def package(request, package_uuid):
|
|||||||
max_perm = Permission.ALL[0]
|
max_perm = Permission.ALL[0]
|
||||||
|
|
||||||
PackageManager.update_permissions(current_user, current_package, grantee, max_perm)
|
PackageManager.update_permissions(current_user, current_package, grantee, max_perm)
|
||||||
|
return redirect(current_package.url)
|
||||||
|
elif license is not None:
|
||||||
|
if license == 'no-license':
|
||||||
|
if current_package.license is not None:
|
||||||
|
current_package.license.delete()
|
||||||
|
|
||||||
|
current_package.license = None
|
||||||
|
current_package.save()
|
||||||
|
return redirect(current_package.url)
|
||||||
|
else:
|
||||||
|
if current_package.license is not None:
|
||||||
|
current_package.license.delete()
|
||||||
|
|
||||||
|
l = License()
|
||||||
|
l.link = license_link
|
||||||
|
l.image_link = license_image_link
|
||||||
|
l.save()
|
||||||
|
|
||||||
|
current_package.license = l
|
||||||
|
current_package.save()
|
||||||
|
|
||||||
return redirect(current_package.url)
|
return redirect(current_package.url)
|
||||||
else:
|
else:
|
||||||
return HttpResponseBadRequest()
|
return HttpResponseBadRequest()
|
||||||
|
|
||||||
|
else:
|
||||||
|
return HttpResponseBadRequest()
|
||||||
|
|
||||||
# https://envipath.org/package/<id>/compound
|
# https://envipath.org/package/<id>/compound
|
||||||
def package_compounds(request, package_uuid):
|
def package_compounds(request, package_uuid):
|
||||||
@ -960,9 +999,9 @@ def package_pathways(request, package_uuid):
|
|||||||
|
|
||||||
# https://envipath.org/package/<id>/pathway/<id>
|
# https://envipath.org/package/<id>/pathway/<id>
|
||||||
def package_pathway(request, package_uuid, pathway_uuid):
|
def package_pathway(request, package_uuid, pathway_uuid):
|
||||||
current_user = _anonymous_or_real(request)
|
current_user: User = _anonymous_or_real(request)
|
||||||
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
current_package: Package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||||
current_pathway = Pathway.objects.get(package=current_package, uuid=pathway_uuid)
|
current_pathway: Pathway = Pathway.objects.get(package=current_package, uuid=pathway_uuid)
|
||||||
|
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,10 @@
|
|||||||
<a role="button" data-toggle="modal" data-target="#edit_package_permissions_modal">
|
<a role="button" data-toggle="modal" data-target="#edit_package_permissions_modal">
|
||||||
<i class="glyphicon glyphicon-user"></i> Edit Permissions</a>
|
<i class="glyphicon glyphicon-user"></i> Edit Permissions</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a role="button" data-toggle="modal" data-target="#set_license_modal">
|
||||||
|
<i class="glyphicon glyphicon-duplicate"></i> License</a>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="button" data-toggle="modal" data-target="#delete_package_modal">
|
<a class="button" data-toggle="modal" data-target="#delete_package_modal">
|
||||||
<i class="glyphicon glyphicon-trash"></i> Delete Package</a>
|
<i class="glyphicon glyphicon-trash"></i> Delete Package</a>
|
||||||
|
|||||||
153
templates/modals/objects/set_license_modal.html
Normal file
153
templates/modals/objects/set_license_modal.html
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
<div class="modal fade"
|
||||||
|
tabindex="-1"
|
||||||
|
id="set_license_modal"
|
||||||
|
role="dialog"
|
||||||
|
aria-labelledby="set_license_modal"
|
||||||
|
aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button"
|
||||||
|
class="close"
|
||||||
|
data-dismiss="modal">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
<span class="sr-only">Close</span>
|
||||||
|
</button>
|
||||||
|
<h3 class="modal-title">Set License</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-9">
|
||||||
|
<p>
|
||||||
|
Set the license for all data in this package:
|
||||||
|
<br> <br>
|
||||||
|
(For more information please visit our <a target="#"
|
||||||
|
href="https://wiki.envipath.org/index.php/License">wiki</a>.)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div id="ccfig"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<form id="set_license_form" accept-charset="UTF-8" action="" data-remote="true" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="radio">
|
||||||
|
<label><input type="radio" name="optlicense" onclick="cc()" id="ccradio">Creative commons license</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="checkbox">
|
||||||
|
<label><input type="checkbox" value="" onclick="cc()" id="ccremix" disabled>Allow adaptations of your work to be shared</label>
|
||||||
|
</div>
|
||||||
|
<div class="checkbox">
|
||||||
|
<label><input type="checkbox" value="" onclick="cc()" id="ccnocom" disabled>Prohibit commercial use</label>
|
||||||
|
</div>
|
||||||
|
<div class="checkbox">
|
||||||
|
<label><input type="checkbox" value="" onclick="cc()" id="ccalike" disabled>Share only if others share alike</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="radio">
|
||||||
|
<label><input type="radio" name="optlicense" onclick="cc()" id="noccradio">No creative commons license, contact package owner for license information</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input type="hidden" id="license" name="license">
|
||||||
|
<input type="hidden" id="license-link" name="license-link">
|
||||||
|
<input type="hidden" id="license-image-link" name="license-image-link">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button id="set_license_form_submit" class="btn btn-primary">Submit</button>
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function ccstring(ccremix, ccnocom, ccalike){
|
||||||
|
var ccstring = "by";
|
||||||
|
|
||||||
|
if(ccnocom){
|
||||||
|
ccstring +="-nc";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ccremix){
|
||||||
|
ccstring +="-nd";
|
||||||
|
} else{
|
||||||
|
if(ccalike){
|
||||||
|
ccstring +="-sa";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ccstring;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cc() {
|
||||||
|
var nocc = $('#noccradio').prop('checked')
|
||||||
|
var iscc = $('#ccradio').prop('checked');
|
||||||
|
|
||||||
|
if(nocc) {
|
||||||
|
$('#ccradio').prop('checked', false);
|
||||||
|
$('#ccremix').prop('checked', false);
|
||||||
|
$('#ccnocom').prop('checked', false);
|
||||||
|
$('#ccalike').prop('checked', false);
|
||||||
|
|
||||||
|
$('#ccremix').prop('disabled', true);
|
||||||
|
$('#ccnocom').prop('disabled', true);
|
||||||
|
$('#ccalike').prop('disabled', true);
|
||||||
|
} else if (iscc) {
|
||||||
|
$('#ccremix').prop('disabled', false);
|
||||||
|
$('#ccnocom').prop('disabled', false);
|
||||||
|
|
||||||
|
if ($('#ccremix').prop('checked')) {
|
||||||
|
$('#ccalike').prop('disabled', false);
|
||||||
|
} else {
|
||||||
|
$('#ccalike').prop('disabled', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var remix = $('#ccremix').prop('checked');
|
||||||
|
var nocom = $('#ccnocom').prop('checked');
|
||||||
|
var alike = $('#ccalike').prop('checked');
|
||||||
|
|
||||||
|
if(nocc) {
|
||||||
|
$('#set_license_form_submit').prop('disabled', false);
|
||||||
|
$('#ccfig').empty();
|
||||||
|
$('#license').val('no-license')
|
||||||
|
} else if(iscc) {
|
||||||
|
$('#set_license_form_submit').prop('disabled', false);
|
||||||
|
$('#ccfig').empty();
|
||||||
|
var ccstr = ccstring(remix, nocom, alike)
|
||||||
|
|
||||||
|
var link = `https://creativecommons.org/licenses/${ccstr}/4.0/`;
|
||||||
|
var imageLink = `https://licensebuttons.net/l/${ccstr}/4.0/88x31.png`;
|
||||||
|
|
||||||
|
var img_tpl = `<a href='${link}' target="_blank">
|
||||||
|
<img src='${imageLink}'>
|
||||||
|
</a>`;
|
||||||
|
|
||||||
|
$('#ccfig').append(img_tpl);
|
||||||
|
$('#license').val(ccstr);
|
||||||
|
$('#license-link').val(link);
|
||||||
|
$('#license-image-link').val(imageLink);
|
||||||
|
} else {
|
||||||
|
$('#ccfig').empty();
|
||||||
|
$('#set_license_form_submit').prop('disabled', true);
|
||||||
|
$('#license').val('no-license')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
// Disable by default as nothing is selected
|
||||||
|
|
||||||
|
cc();
|
||||||
|
$('#set_license_form_submit').prop('disabled', true);
|
||||||
|
|
||||||
|
$('#set_license_form_submit').on('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$('#set_license_form').submit();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
@ -5,6 +5,7 @@
|
|||||||
{% block action_modals %}
|
{% block action_modals %}
|
||||||
{% include "modals/objects/edit_package_modal.html" %}
|
{% include "modals/objects/edit_package_modal.html" %}
|
||||||
{% include "modals/objects/edit_package_permissions_modal.html" %}
|
{% include "modals/objects/edit_package_permissions_modal.html" %}
|
||||||
|
{% include "modals/objects/set_license_modal.html" %}
|
||||||
{% include "modals/objects/delete_package_modal.html" %}
|
{% include "modals/objects/delete_package_modal.html" %}
|
||||||
{% endblock action_modals %}
|
{% endblock action_modals %}
|
||||||
|
|
||||||
@ -50,5 +51,24 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if package.license %}
|
||||||
|
<p></p>
|
||||||
|
<div class="panel-group" id="license_accordion">
|
||||||
|
<div class="panel panel-default list-group-item" style="background-color:#f5f5f5">
|
||||||
|
<div class="panel-title">
|
||||||
|
<a data-toggle="collapse" data-parent="#licence_accordion" href="#license">License</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="license" class="panel-collapse collapse in">
|
||||||
|
<div class="panel-body list-group-item">
|
||||||
|
<a target="_blank" href="{{ package.license.link }}">
|
||||||
|
<img src="{{ package.license.image_link }}">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|||||||
Reference in New Issue
Block a user