Switched to generic views
This commit is contained in:
parent
43700aa66b
commit
3e9c2c7ca0
@ -16,6 +16,10 @@ class SubmissionAdmin(admin.ModelAdmin):
|
||||
list_display = ['name', 'instrument', 'date', 'complete']
|
||||
list_filter = ['project', 'complete']
|
||||
|
||||
class ResourceAdmin(admin.ModelAdmin):
|
||||
list_display = ['name', 'media_type', 'project']
|
||||
list_filter = ['project']
|
||||
|
||||
class WikiPageAdmin(admin.ModelAdmin):
|
||||
list_display = ['title', 'project']
|
||||
list_filter = ['project']
|
||||
@ -23,5 +27,5 @@ class WikiPageAdmin(admin.ModelAdmin):
|
||||
admin.site.register(models.Ensemble, EnsembleAdmin)
|
||||
admin.site.register(models.Project, ProjectAdmin)
|
||||
admin.site.register(models.Submission, SubmissionAdmin)
|
||||
admin.site.register(models.Resource)
|
||||
admin.site.register(models.Resource, ResourceAdmin)
|
||||
admin.site.register(models.WikiPage, WikiPageAdmin)
|
||||
@ -1,29 +0,0 @@
|
||||
from django.http import HttpResponseRedirect
|
||||
|
||||
def check_allowed(view_func):
|
||||
|
||||
def _view(request, *args, **kwargs):
|
||||
|
||||
code = request.GET.get('code')
|
||||
if code:
|
||||
# just change if we can
|
||||
try:
|
||||
ensemble = request.session.get('registered', {})[code.replace('-', '')]
|
||||
request.session['ensemble'] = ensemble
|
||||
except KeyError:
|
||||
# need to register this code
|
||||
return HttpResponseRedirect('/register?code=' + code)
|
||||
|
||||
request.ensemble_id = request.session.get('ensemble')
|
||||
|
||||
if request.ensemble_id is None:
|
||||
return HttpResponseRedirect('/register')
|
||||
|
||||
return view_func(request, *args, **kwargs)
|
||||
|
||||
_view.__name__ = view_func.__name__
|
||||
_view.__dict__ = view_func.__dict__
|
||||
_view.__doc__ = view_func.__doc__
|
||||
|
||||
return _view
|
||||
|
||||
23
interface/migrations/0014_auto_20200909_1016.py
Normal file
23
interface/migrations/0014_auto_20200909_1016.py
Normal file
@ -0,0 +1,23 @@
|
||||
# Generated by Django 3.1.1 on 2020-09-09 00:16
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('interface', '0013_auto_20200907_1455'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='resource',
|
||||
name='description',
|
||||
field=models.TextField(blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='resource',
|
||||
name='key',
|
||||
field=models.CharField(blank=True, max_length=255),
|
||||
),
|
||||
]
|
||||
18
interface/migrations/0015_resource_media_type.py
Normal file
18
interface/migrations/0015_resource_media_type.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.1.1 on 2020-09-09 01:46
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('interface', '0014_auto_20200909_1016'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='resource',
|
||||
name='media_type',
|
||||
field=models.CharField(choices=[('audio', 'Audio'), ('video', 'Video'), ('*', 'General')], default='*', max_length=10),
|
||||
),
|
||||
]
|
||||
@ -15,6 +15,11 @@ s3client = boto3.client('s3')
|
||||
|
||||
BUCKET = settings.AWS_BUCKET
|
||||
|
||||
MEDIA_TYPES = [
|
||||
('audio', "Audio"),
|
||||
('video', "Video"),
|
||||
('*', "General"),
|
||||
]
|
||||
|
||||
def generate_code(length=9):
|
||||
return "".join([ random.choice('0123456789') for _ in range(length) ])
|
||||
@ -53,11 +58,21 @@ class Project(models.Model):
|
||||
class Resource(models.Model):
|
||||
project = models.ForeignKey(Project, related_name='resources', on_delete=models.CASCADE)
|
||||
name = models.CharField(max_length=100)
|
||||
key = models.CharField(max_length=255)
|
||||
|
||||
description = models.TextField(blank=True)
|
||||
key = models.CharField(max_length=255, blank=True)
|
||||
media_type = models.CharField(max_length=10, choices=MEDIA_TYPES, default='*')
|
||||
|
||||
def key_template(self):
|
||||
return "{}_${{filename}}".format(slugify(self.name))
|
||||
|
||||
def presigned_url(self):
|
||||
if not self.key:
|
||||
return ""
|
||||
params = {'Bucket': BUCKET, 'Key': self.key}
|
||||
return s3client.generate_presigned_url('get_object', Params=params, ExpiresIn=3600)
|
||||
return s3client.generate_presigned_url('get_object', Params=params, ExpiresIn=3600*24)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class WikiPage(models.Model):
|
||||
project = models.ForeignKey(Project, related_name='wiki_pages', on_delete=models.CASCADE)
|
||||
|
||||
@ -95,6 +95,11 @@ UL.nav-buttons > LI {
|
||||
margin: 2px 10px;
|
||||
}
|
||||
|
||||
.admin-actions {
|
||||
text-align: right;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
/* FORMS */
|
||||
|
||||
FORM {
|
||||
@ -157,14 +162,14 @@ TEXTAREA {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.list-group A {
|
||||
.list-group > * {
|
||||
border: 1px solid var(--gray-blue);
|
||||
border-radius: 10px;
|
||||
padding: 2px 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.list-group A:hover {
|
||||
.list-group > A:hover {
|
||||
background-color: var(--light-blue);
|
||||
text-decoration: none;
|
||||
}
|
||||
@ -211,4 +216,9 @@ TABLE.horizontal TH {
|
||||
TABLE.horizontal TD,
|
||||
TABLE.horizontal TH {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.resource-player {
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
@ -21,7 +21,7 @@
|
||||
<ul class="nav-buttons">
|
||||
{% if request.ensemble_id %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'my_projects' %}"><i class="fas fa-music"></i> <span class="">My
|
||||
<a class="nav-link" href="{% url 'ensemble_detail' %}"><i class="fas fa-music"></i> <span class="">My
|
||||
Projects</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<h1>Projects for {{ ensemble.name }}</h1>
|
||||
<div class="list-group narrow">
|
||||
{% for project in ensemble.active_projects %}
|
||||
<a class="" href="{% url 'project' project_id=project.id %}">
|
||||
<a class="" href="{% url 'project_detail' pk=project.id %}">
|
||||
<h3>{{ project.name }}</h3>
|
||||
<p><small>Due in {{ project.deadline|timeuntil }}</small></p>
|
||||
</a>
|
||||
@ -1,41 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{{ project.name }}</h1>
|
||||
{% block page %}
|
||||
<div class="narrow">
|
||||
<h3 class="text-center">Due in {{ project.deadline|timeuntil }}!</h3>
|
||||
<p>There have been {{ project.submissions.count }} submissions so far...</p>
|
||||
<table>
|
||||
<tbody>
|
||||
{% for submission in project.submissions %}
|
||||
<tr>
|
||||
<td>{{ submission.date|timesince }} ago</td>
|
||||
<td>{{ submission.name }} ({{ submission.instrument }})</td>
|
||||
{% if request.user.is_authenticated %}
|
||||
<td>
|
||||
<a href="{% url 'submission' project_id=project.pk submission_id=submission.pk %}"><i class="fas fa-info-circle"></i></a>
|
||||
|
||||
<a href="{{ submission.presigned_url }}"><i class="fas fa-download"></i></a>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
<div class="project-links">
|
||||
<div class="pills" role="tablist">
|
||||
<a role="tab" href="{% url 'project' project_id=project.id %}">Project info</a>
|
||||
<a role="tab" href="{% url 'resources' project_id=project.pk %}">Resources</a>
|
||||
{% for page in project.wiki_pages.all %}
|
||||
<a class="nav-link {% if page.id == wiki_id %}active{% endif %}"
|
||||
href="{% url 'wiki' project_id=project.id wiki_id=page.id %}">{{ page.title }}</a>
|
||||
{% endfor %}
|
||||
<!--a role="tab" href="">Record a submission</a-->
|
||||
<a role="tab" href="{% url 'create_submission' project_id=project.id %}">Send a file</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
21
interface/templates/interface/project_base.html
Normal file
21
interface/templates/interface/project_base.html
Normal file
@ -0,0 +1,21 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{{ project.name }}</h1>
|
||||
{% block page %}
|
||||
No content
|
||||
{% endblock %}
|
||||
<div class="project-links">
|
||||
<div class="pills" role="tablist">
|
||||
<a role="tab" href="{% url 'project_detail' pk=project.id %}">Project info</a>
|
||||
<a role="tab" href="{% url 'resource_list' project=project.pk %}">Resources</a>
|
||||
{% for page in project.wiki_pages.all %}
|
||||
<a class="nav-link {% if page.id == wiki_id %}active{% endif %}"
|
||||
href="{% url 'wiki' project=project.id pk=page.id %}">{{ page.title }}</a>
|
||||
{% endfor %}
|
||||
<!--a role="tab" href="">Record a submission</a-->
|
||||
<a role="tab" href="{% url 'submission_create' project=project.id %}">Send a file</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
25
interface/templates/interface/project_detail.html
Normal file
25
interface/templates/interface/project_detail.html
Normal file
@ -0,0 +1,25 @@
|
||||
{% extends "interface/project_base.html" %}
|
||||
|
||||
{% block page %}
|
||||
<div class="narrow">
|
||||
<h3 class="text-center">Due in {{ project.deadline|timeuntil }}!</h3>
|
||||
<p>There have been {{ project.submissions.count }} submissions so far...</p>
|
||||
<table>
|
||||
<tbody>
|
||||
{% for submission in project.submissions %}
|
||||
<tr>
|
||||
<td>{{ submission.date|timesince }} ago</td>
|
||||
<td>{{ submission.name }} ({{ submission.instrument }})</td>
|
||||
{% if request.user.is_authenticated %}
|
||||
<td>
|
||||
<a href="{% url 'submission_detail' project=project.pk pk=submission.pk %}"><i class="fas fa-info-circle"></i></a>
|
||||
|
||||
<a href="{{ submission.presigned_url }}"><i class="fas fa-download"></i></a>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
15
interface/templates/interface/project_form.html
Normal file
15
interface/templates/interface/project_form.html
Normal file
@ -0,0 +1,15 @@
|
||||
{% extends "interface/project_base.html" %}
|
||||
|
||||
{% block page %}
|
||||
<div class="narrow">
|
||||
<h3>{{ title }}</h3>
|
||||
<p>{{ instructions }}</p>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
<div class="form-actions">
|
||||
<button>Create</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
37
interface/templates/interface/resource_list.html
Normal file
37
interface/templates/interface/resource_list.html
Normal file
@ -0,0 +1,37 @@
|
||||
{% extends "interface/project_base.html" %}
|
||||
|
||||
{% block page %}
|
||||
<div class="narrow">
|
||||
<h3>Resources</h3>
|
||||
<div class="list-group narrow">
|
||||
{% for resource in object_list %}
|
||||
{% with download=resource.presigned_url %}
|
||||
<div>
|
||||
<h3>
|
||||
{{ resource.name }}
|
||||
{% if download %}
|
||||
<a href="{{ download }}">
|
||||
<i class="fas fa-download"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if request.user.is_authenticated %}
|
||||
<a href="{% url 'resource_upload' project=project.pk pk=resource.pk %}">
|
||||
<i class="fas fa-upload"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</h3>
|
||||
<p><small>{{ resource.description }}</small></p>
|
||||
{% if download and resource.media_type == 'audio' %}
|
||||
<audio class="resource-player" controls src="{{ download }}"></audio>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% if request.user.is_authenticated %}
|
||||
<div class="admin-actions">
|
||||
<a href="{% url 'resource_create' project=project.pk %}"><i class="fas fa-plus-circle"></i> Add new</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "interface/project.html" %}
|
||||
{% extends "interface/project_base.html" %}
|
||||
|
||||
{% block page %}
|
||||
<div class="narrow">
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "interface/project.html" %}
|
||||
{% extends "interface/project_base.html" %}
|
||||
|
||||
{% block page %}
|
||||
<div class="narrow">
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
<div class="form-actions text-right">
|
||||
<a class=""
|
||||
href="{% url 'cancel_submission' project_id=project.pk submission_id=submission.pk %}">Cancel</a>
|
||||
href="{{ cancel_url }}">Cancel</a>
|
||||
|
||||
<button type="submit" id="upload">Upload</button>
|
||||
</div>
|
||||
@ -53,8 +53,8 @@ function startUpload(e) {
|
||||
//$('input[name="file"]').attr('disabled', true);
|
||||
|
||||
// patch form to use our ajax policy
|
||||
$('input[name="policy"]').val("{{ ajax_post.fields.policy }}");
|
||||
$('input[name="signature"]').val("{{ ajax_post.fields.signature }}");
|
||||
$('input[name="policy"]').val("{{ ajax_upload.fields.policy }}");
|
||||
$('input[name="signature"]').val("{{ ajax_upload.fields.signature }}");
|
||||
$('input[name="success_action_redirect"]').remove();
|
||||
|
||||
|
||||
@ -81,7 +81,7 @@ function startUpload(e) {
|
||||
if (xhr.status == 204) {
|
||||
status.html("Finished upload");
|
||||
let s3_location = xhr.getResponseHeader("Location");
|
||||
location.href += "/complete?location=" + s3_location;
|
||||
location.href = "{{ success_url }}?location=" + s3_location;
|
||||
} else {
|
||||
status.html("Something went wrong");
|
||||
console.log(xhr.responseText);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "interface/project.html" %}
|
||||
{% extends "interface/project_base.html" %}
|
||||
|
||||
{% block page %}
|
||||
<div class="wiki-page">
|
||||
|
||||
@ -3,12 +3,18 @@ from django.urls import path
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.my_projects, name='my_projects'),
|
||||
path('', views.EnsembleDetailView.as_view(), name='ensemble_detail'),
|
||||
path('register', views.register, name="register"),
|
||||
path('projects/<int:project_id>', views.project_page, name="project"),
|
||||
path('projects/<int:project_id>/page/<int:wiki_id>', views.wiki_page, name="wiki"),
|
||||
path('projects/<int:project_id>/submission', views.create_submission, name="create_submission"),
|
||||
path('projects/<int:project_id>/submission/<int:submission_id>', views.submission, name="submission"),
|
||||
path('projects/<int:project_id>/submission/<int:submission_id>/complete', views.complete_submission, name="complete_submission"),
|
||||
path('projects/<int:project_id>/submission/<int:submission_id>/cancel', views.cancel_submission, name="cancel_submission"),
|
||||
path('projects/<int:pk>', views.ProjectDetailView.as_view(), name="project_detail"),
|
||||
path('projects/<int:project>/page/<int:pk>', views.WikiView.as_view(), name="wiki"),
|
||||
|
||||
path('projects/<int:project>/submission', views.SubmissionCreateView.as_view(), name="submission_create"),
|
||||
path('projects/<int:project>/submission/<int:pk>', views.SubmissionDetailView.as_view(), name="submission_detail"),
|
||||
path('projects/<int:project>/submission/<int:pk>/upload', views.SubmissionUploadView.as_view(), name="submission_upload"),
|
||||
path('projects/<int:project>/submission/<int:pk>/cancel', views.SubmissionCancelView.as_view(), name="submission_cancel"),
|
||||
|
||||
path('projects/<int:project>/resources', views.ResourceListView.as_view(), name="resource_list"),
|
||||
path('projects/<int:project>/resources/add', views.ResourceCreateView.as_view(), name="resource_create"),
|
||||
path('projects/<int:project>/resources/<int:pk>', views.ResourceUploadView.as_view(), name="resource_upload"),
|
||||
path('projects/<int:project>/resources/<int:pk>/complete', views.ResourceCompleteView.as_view(), name="resource_complete"),
|
||||
]
|
||||
@ -1,23 +1,91 @@
|
||||
from django.shortcuts import render, get_object_or_404, redirect, resolve_url
|
||||
from django.views.generic import TemplateView, View, RedirectView
|
||||
from django.views.generic.detail import DetailView, SingleObjectMixin
|
||||
from django.views.generic.list import ListView
|
||||
from django.views.generic.edit import CreateView
|
||||
from django.views.generic.base import ContextMixin
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.core.exceptions import SuspiciousOperation
|
||||
|
||||
from markdown2 import markdown
|
||||
from datetime import datetime
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from . import models, forms
|
||||
from .decorators import check_allowed
|
||||
|
||||
from base64 import b64decode
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class EnsembleMixin(object):
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
|
||||
request.ensemble_id = request.session.get('ensemble')
|
||||
|
||||
if not request.ensemble_id:
|
||||
return redirect('register')
|
||||
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
class ProjectMixin(EnsembleMixin):
|
||||
|
||||
def get_project(self):
|
||||
if not hasattr(self, '_project'):
|
||||
self._project = get_object_or_404(models.Project,
|
||||
pk=self.kwargs['project'], ensemble=self.request.ensemble_id)
|
||||
return self._project
|
||||
|
||||
def get_queryset(self):
|
||||
return super().get_queryset().filter(project=self.get_project())
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['project'] = self.get_project()
|
||||
return context
|
||||
|
||||
class S3UploadMixin(ProjectMixin):
|
||||
|
||||
def get_cancel_url(self):
|
||||
return self.cancel_url
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
success_url = self.request.build_absolute_uri(self.get_success_url())
|
||||
|
||||
key_template = self.object.key_template()
|
||||
|
||||
project = self.get_project()
|
||||
context['upload'] = project.presigned_post(key_template,
|
||||
fields={'success_action_redirect': success_url},
|
||||
conditions=[["starts-with", "$success_action_redirect", ""]])
|
||||
context['ajax_upload'] = project.presigned_post(key_template)
|
||||
context['success_url'] = success_url
|
||||
context['cancel_url'] = self.get_cancel_url()
|
||||
return context
|
||||
|
||||
class S3CompleteMixin(View):
|
||||
always_set = False
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
|
||||
if self.always_set or not self.object.key:
|
||||
uri = urlparse(request.GET['location'])
|
||||
self.object.key = uri.path[1:]
|
||||
self.object.save()
|
||||
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def forbidden(request):
|
||||
return render(request, 'interface/forbidden.html', {})
|
||||
|
||||
def register(request):
|
||||
|
||||
|
||||
if 'clear' in request.GET:
|
||||
request.session.clear()
|
||||
|
||||
|
||||
request.ensemble_id = request.session.get('ensemble')
|
||||
registered = request.session.setdefault('registered', {})
|
||||
|
||||
@ -32,7 +100,7 @@ def register(request):
|
||||
if ensemble.passphrase == data['passphrase']:
|
||||
request.session['ensemble'] = ensemble.pk
|
||||
registered[ensemble.code] = ensemble.pk
|
||||
return redirect('my_projects')
|
||||
return redirect('ensemble_detail')
|
||||
except models.Ensemble.DoesNotExist:
|
||||
form.add_error(None, "Incorrect code or passphrase")
|
||||
|
||||
@ -46,89 +114,104 @@ def register(request):
|
||||
return render(request, 'interface/register.html', {'form': form, 'current': current})
|
||||
|
||||
|
||||
@check_allowed
|
||||
def my_projects(request):
|
||||
ensemble = get_object_or_404(models.Ensemble, pk=request.ensemble_id)
|
||||
context = {'ensemble': ensemble}
|
||||
return render(request, 'interface/project_list.html', context)
|
||||
|
||||
@check_allowed
|
||||
def project_page(request, project_id):
|
||||
project = get_object_or_404(models.Project, pk=project_id, ensemble_id=request.ensemble_id)
|
||||
context = {'project': project}
|
||||
return render(request, 'interface/project.html', context)
|
||||
|
||||
@check_allowed
|
||||
def wiki_page(request, project_id, wiki_id):
|
||||
wiki = get_object_or_404(models.WikiPage, pk=wiki_id, project=project_id, project__ensemble=request.ensemble_id)
|
||||
context = {'project': wiki.project, 'wiki': wiki, 'wiki_html': markdown(wiki.markdown)}
|
||||
return render(request, 'interface/wiki.html', context)
|
||||
|
||||
@check_allowed
|
||||
def create_submission(request, project_id):
|
||||
project = get_object_or_404(models.Project, pk=project_id, ensemble=request.ensemble_id)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = forms.SubmissionForm(request.POST)
|
||||
|
||||
if form.is_valid():
|
||||
s = form.save(commit=False)
|
||||
s.project_id = project_id
|
||||
s.save()
|
||||
|
||||
# cache details for next time
|
||||
request.session['name'] = s.name
|
||||
request.session['instrument'] = s.instrument
|
||||
|
||||
return redirect('submission', project_id=project_id, submission_id=s.pk)
|
||||
else:
|
||||
initial = { k: request.session.get(k) for k in ('name', 'instrument') }
|
||||
form = forms.SubmissionForm(initial=initial)
|
||||
|
||||
context = {'project': project, 'form': form}
|
||||
return render(request, 'interface/submission_create.html', context)
|
||||
|
||||
@check_allowed
|
||||
def submission(request, project_id, submission_id):
|
||||
project = get_object_or_404(models.Project, pk=project_id, ensemble=request.ensemble_id)
|
||||
submission = project.all_submissions.get(pk=submission_id)
|
||||
|
||||
if submission.complete:
|
||||
context = {'project': project, 'submission': submission}
|
||||
if request.user.is_authenticated:
|
||||
context['download'] = submission.presigned_url()
|
||||
return render(request, 'interface/submission_detail.html', context)
|
||||
|
||||
class EnsembleDetailView(EnsembleMixin, DetailView):
|
||||
|
||||
# Need to do an upload
|
||||
redirect = request.build_absolute_uri(resolve_url('complete_submission', project_id=project.pk, submission_id=submission.pk))
|
||||
def get_object(self):
|
||||
return models.Ensemble.objects.get(pk=self.request.ensemble_id)
|
||||
|
||||
key = submission.key_template()
|
||||
upload = project.presigned_post(key,
|
||||
fields={'success_action_redirect': redirect},
|
||||
conditions=[["starts-with", "$success_action_redirect", ""]])
|
||||
class ProjectDetailView(EnsembleMixin, DetailView):
|
||||
|
||||
def get_queryset(self):
|
||||
return models.Project.objects.filter(ensemble=self.request.ensemble_id)
|
||||
|
||||
class WikiView(ProjectMixin, DetailView):
|
||||
template_name = 'interface/wiki.html'
|
||||
model = models.WikiPage
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
data = super().get_context_data(**kwargs)
|
||||
data['wiki_html'] = markdown(self.object.markdown)
|
||||
return data
|
||||
|
||||
class SubmissionCreateView(ProjectMixin, CreateView):
|
||||
model = models.Submission
|
||||
fields = ['name', 'instrument', 'notes']
|
||||
template_name = "interface/submission_create.html"
|
||||
|
||||
def form_valid(self, form):
|
||||
self.object = form.save(commit=False)
|
||||
self.object.project = self.get_project()
|
||||
self.object.save()
|
||||
|
||||
self.request.session['name'] = self.object.name
|
||||
self.request.session['instrument'] = self.object.instrument
|
||||
|
||||
return redirect('submission_upload', project=self.object.project.pk, pk=self.object.pk)
|
||||
|
||||
def get_initial(self):
|
||||
return { k: self.request.session.get(k) for k in ('name', 'instrument') }
|
||||
|
||||
|
||||
class SubmissionDetailView(ProjectMixin, S3CompleteMixin, DetailView):
|
||||
model = models.Submission
|
||||
|
||||
# need an additional presigned without the redirect for ajax submission
|
||||
ajax_post = project.presigned_post(key)
|
||||
context = {'upload': upload, 'ajax_post': ajax_post, 'project': project, 'submission': submission}
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
if self.request.user.is_authenticated:
|
||||
context['download'] = self.object.presigned_url()
|
||||
return context
|
||||
|
||||
return render(request, 'interface/submission_upload.html', context)
|
||||
class SubmissionUploadView(S3UploadMixin, DetailView):
|
||||
template_name = 'interface/submission_upload.html'
|
||||
model = models.Submission
|
||||
|
||||
@check_allowed
|
||||
def cancel_submission(request, project_id, submission_id):
|
||||
project = get_object_or_404(models.Project, pk=project_id, ensemble=request.ensemble_id)
|
||||
submission = project.all_submissions.get(pk=submission_id)
|
||||
submission.delete()
|
||||
return redirect('project', project_id=project_id)
|
||||
def get_success_url(self):
|
||||
return resolve_url('submission_detail', **self.kwargs)
|
||||
|
||||
@check_allowed
|
||||
def complete_submission(request, project_id, submission_id):
|
||||
project = get_object_or_404(models.Project, pk=project_id, ensemble=request.ensemble_id)
|
||||
s = project.all_submissions.get(pk=submission_id)
|
||||
s.complete = True
|
||||
|
||||
uri = urlparse(request.GET['location'])
|
||||
s.key = uri.path[1:]
|
||||
|
||||
s.save()
|
||||
return redirect('submission', project_id=project_id, submission_id=submission_id)
|
||||
def get_cancel_url(self):
|
||||
return resolve_url('submission_cancel', **self.kwargs)
|
||||
|
||||
class SubmissionCancelView(ProjectMixin, SingleObjectMixin, View):
|
||||
model = models.Submission
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
self.object.delete()
|
||||
return redirect('project_detail', pk=kwargs['project'])
|
||||
|
||||
class ResourceCreateView(ProjectMixin, CreateView):
|
||||
model = models.Resource
|
||||
fields = ['name', 'media_type', 'description']
|
||||
template_name = 'interface/project_form.html'
|
||||
title = "Add a new resource"
|
||||
|
||||
def form_valid(self, form):
|
||||
|
||||
if not self.request.user.is_authenticated:
|
||||
raise SuspiciousOperation("Must be logged in to create resources")
|
||||
|
||||
self.object = form.save(commit=False)
|
||||
self.object.project = self.get_project()
|
||||
self.object.save()
|
||||
return redirect('resource_upload', project=self.object.project_id, pk=self.object.pk)
|
||||
|
||||
class ResourceUploadView(S3UploadMixin, DetailView):
|
||||
model = models.Resource
|
||||
template_name = 'interface/submission_upload.html'
|
||||
|
||||
def get_success_url(self):
|
||||
return resolve_url('resource_complete', **self.kwargs)
|
||||
|
||||
def get_cancel_url(self):
|
||||
return resolve_url('resource_list', project=self.kwargs['project'])
|
||||
|
||||
class ResourceCompleteView(S3CompleteMixin, SingleObjectMixin, RedirectView):
|
||||
model = models.Resource
|
||||
always_set = True
|
||||
|
||||
def get_redirect_url(self, **kwargs):
|
||||
return resolve_url('resource_list', project=self.kwargs['project'])
|
||||
|
||||
|
||||
class ResourceListView(ProjectMixin, ListView):
|
||||
model = models.Resource
|
||||
|
||||
@ -25,7 +25,7 @@ SECRET_KEY = '6y#33930^6@c762u(@6+&#_qx8eu^e8q+4t-(@m60vnjw37k26'
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = ['localhost', '192.168.100.123']
|
||||
ALLOWED_HOSTS = ['localhost', '192.168.100.130']
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user