Ditched bootstrap
This commit is contained in:
parent
a1d10ea30a
commit
8a8bccd850
@ -4,6 +4,8 @@ from django.contrib import admin
|
||||
|
||||
from . import models
|
||||
|
||||
class EnsembleAdmin(admin.ModelAdmin):
|
||||
list_display = ['name', 'ensemble_code']
|
||||
|
||||
class ProjectAdmin(admin.ModelAdmin):
|
||||
|
||||
@ -18,7 +20,7 @@ class WikiPageAdmin(admin.ModelAdmin):
|
||||
list_display = ['title', 'project']
|
||||
list_filter = ['project']
|
||||
|
||||
admin.site.register(models.Ensemble)
|
||||
admin.site.register(models.Ensemble, EnsembleAdmin)
|
||||
admin.site.register(models.Project, ProjectAdmin)
|
||||
admin.site.register(models.Submission, SubmissionAdmin)
|
||||
admin.site.register(models.Resource)
|
||||
|
||||
@ -4,6 +4,16 @@ 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:
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
from django.forms import ModelForm
|
||||
|
||||
from django import forms
|
||||
from .models import Submission
|
||||
|
||||
class SubmissionForm(ModelForm):
|
||||
class CodeForm(forms.Form):
|
||||
code = forms.CharField(max_length=14,
|
||||
widget=forms.TextInput(attrs={'placeholder': 'xxx-xxx-xxx'}))
|
||||
passphrase = forms.CharField(max_length=32)
|
||||
|
||||
class SubmissionForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Submission
|
||||
fields = ['name', 'instrument', 'notes']
|
||||
35
interface/migrations/0007_auto_20200906_1009.py
Normal file
35
interface/migrations/0007_auto_20200906_1009.py
Normal file
@ -0,0 +1,35 @@
|
||||
# Generated by Django 3.1.1 on 2020-09-06 10:09
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import interface.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('interface', '0006_submission_key'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='project',
|
||||
name='bucket',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ensemble',
|
||||
name='bucket',
|
||||
field=models.CharField(default='', max_length=100),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ensemble',
|
||||
name='code',
|
||||
field=models.CharField(default=interface.models.generate_code, max_length=12),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='submission',
|
||||
name='project',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='all_submissions', to='interface.project'),
|
||||
),
|
||||
]
|
||||
24
interface/migrations/0008_auto_20200906_1122.py
Normal file
24
interface/migrations/0008_auto_20200906_1122.py
Normal file
@ -0,0 +1,24 @@
|
||||
# Generated by Django 3.1.1 on 2020-09-06 11:22
|
||||
|
||||
from django.db import migrations, models
|
||||
import interface.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('interface', '0007_auto_20200906_1009'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='ensemble',
|
||||
old_name='password',
|
||||
new_name='passphrase',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ensemble',
|
||||
name='code',
|
||||
field=models.CharField(default=interface.models.generate_code, max_length=9),
|
||||
),
|
||||
]
|
||||
@ -1,6 +1,8 @@
|
||||
from django.db import models
|
||||
from django.utils.text import slugify
|
||||
|
||||
import random
|
||||
|
||||
import boto3
|
||||
|
||||
from datetime import datetime
|
||||
@ -9,14 +11,22 @@ import os.path
|
||||
|
||||
s3client = boto3.client('s3')
|
||||
|
||||
def generate_code(length=9):
|
||||
return "".join([ random.choice('0123456789') for _ in range(length) ])
|
||||
|
||||
class Ensemble(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
code = models.CharField(max_length=12)
|
||||
password = models.CharField(max_length=100)
|
||||
code = models.CharField(max_length=9, default=generate_code)
|
||||
passphrase = models.CharField(max_length=100)
|
||||
bucket = models.CharField(max_length=100)
|
||||
|
||||
def active_projects(self):
|
||||
return self.projects.filter(active=True)
|
||||
|
||||
def ensemble_code(self):
|
||||
code = str(self.code)
|
||||
return "{}-{}-{}".format(code[:3], code[3:6], code[6:])
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@ -25,14 +35,13 @@ class Project(models.Model):
|
||||
ensemble = models.ForeignKey(Ensemble, related_name='projects', on_delete=models.CASCADE, null=True)
|
||||
active = models.BooleanField(default=True)
|
||||
deadline =models.DateField(null=True, blank=True)
|
||||
bucket = models.CharField(max_length=100)
|
||||
|
||||
def submissions(self):
|
||||
return self.all_submissions.filter(complete=True)
|
||||
|
||||
def presigned_post(self, object_name, fields={}, conditions=[], expires=3600):
|
||||
key = os.path.join(slugify(self.name), object_name)
|
||||
return s3client.generate_presigned_post(self.bucket, key, Fields=fields, Conditions=conditions, ExpiresIn=expires)
|
||||
return s3client.generate_presigned_post(self.ensemble.bucket, key, Fields=fields, Conditions=conditions, ExpiresIn=expires)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@ -1,12 +1,183 @@
|
||||
.navbar {
|
||||
margin-bottom: 50px;
|
||||
background-color: #69C;
|
||||
|
||||
:root {
|
||||
--border-color: #292929;
|
||||
--gray-blue: #667788;
|
||||
--light-blue: #c5eff7;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
@font-face {
|
||||
font-family: 'DreamOrphans';
|
||||
src: url('../../fonts/dream orphans.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Quicksand';
|
||||
src: url('../../fonts/Quicksand_Book.otf');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'QuicksandBold';
|
||||
src: url('../../fonts/Quicksand_Bold_Oblique.otf');
|
||||
}
|
||||
|
||||
.debug DIV {
|
||||
border: 1px dashed #DDD;
|
||||
}
|
||||
|
||||
BODY {
|
||||
}
|
||||
|
||||
.main {
|
||||
max-width: 1000px;
|
||||
margin: 10px auto;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 5px;
|
||||
font-family: 'Quicksand', Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.narrow {
|
||||
max-width: 500px;
|
||||
margin: 0px auto;
|
||||
}
|
||||
|
||||
@media all and (max-width: 900px) {
|
||||
.mdhide {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width: 700px) {
|
||||
.smhide {
|
||||
display: none;
|
||||
}
|
||||
UL.nav-buttons {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
/* HEADER BAR */
|
||||
|
||||
.navigation {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 50px;
|
||||
background-color: var(--gray-blue);
|
||||
color: var(--light-blue) !important;
|
||||
}
|
||||
|
||||
.navigation > * {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.navigation A,
|
||||
.navigation A:visited {
|
||||
color: var(--light-blue);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.navigation .brand {
|
||||
font-family: 'QuicksandBold', 'Quicksand', Arial, Helvetica, sans-serif;
|
||||
font-size: 1.5rem;
|
||||
margin: auto 20px;
|
||||
}
|
||||
|
||||
UL.nav-buttons {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
}
|
||||
UL.nav-buttons > LI {
|
||||
margin: 2px 10px;
|
||||
}
|
||||
|
||||
/* FORMS */
|
||||
|
||||
FORM {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 400px;
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
LABEL {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#project H1 {
|
||||
TEXTAREA {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
text-align: right;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: var(--gray-blue);
|
||||
display: inline-block;
|
||||
border: none;
|
||||
color: var(--light-blue);
|
||||
text-decoration: none;
|
||||
border-radius: 1em;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.pills {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.pills A {
|
||||
border: 1px solid var(--gray-blue);
|
||||
padding: 4px 10px 2px 10px;
|
||||
margin: 10px 5px;
|
||||
border-radius: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pills A:hover {
|
||||
background-color: var(--light-blue);
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
.list-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.list-group A {
|
||||
border: 1px solid var(--gray-blue);
|
||||
border-radius: 10px;
|
||||
padding: 2px 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.list-group A:hover {
|
||||
background-color: var(--light-blue);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
A, A:visited {
|
||||
text-decoration: none;
|
||||
color: var(--gray-blue);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
A:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
H1 {
|
||||
text-align: center;
|
||||
}
|
||||
@ -6,49 +6,45 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
|
||||
|
||||
<link rel="stylesheet" href="{% static 'interface/css/polyphonic.css' %}"></link>
|
||||
<script src="https://kit.fontawesome.com/c837098e5b.js" crossorigin="anonymous"></script>
|
||||
<title>{% block title %}Polyphonic{% endblock %}</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{% block header %}
|
||||
<nav class="navbar navbar-expand-lg navbar-dark">
|
||||
<a class="navbar-brand" href="/"><i class="fas fa-random"></i> Polyphonic</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<span class="navbar-text">Virtual Ensemble Manager</span>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent"></div>
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<div class="main">
|
||||
{% block navigation %}
|
||||
<nav class="navigation">
|
||||
<div>
|
||||
<a class="brand" href="/"><i class="fas fa-random smhide"></i> Polyphonic</a>
|
||||
<span class="mdhide">Virtual Ensemble Manager</span>
|
||||
</div>
|
||||
<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> My Projects</a>
|
||||
<a class="nav-link" href="{% url 'my_projects' %}"><i class="fas fa-music"></i> <span class="">My
|
||||
Projects</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'register' %}"><i class="fas fa-users"></i> Change Ensemble</a>
|
||||
<a class="nav-link" href="{% url 'register' %}"><i class="fas fa-users"></i> <span class="">Change
|
||||
Ensemble</span></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href=""><i class="fas fa-question"></i> About</a>
|
||||
<a class="nav-link" href=""><i class="fas fa-question"></i> <span class="">About</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</ul>
|
||||
</nav>
|
||||
{% endblock %}
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
||||
|
||||
{% block content %}
|
||||
<h1>No content!</h1>
|
||||
{% endblock %}
|
||||
|
||||
<div class="content">
|
||||
{% block content %}
|
||||
<h1>No content!</h1>
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Optional JavaScript -->
|
||||
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
|
||||
<!-- late load scripts -->
|
||||
<script src="https://kit.fontawesome.com/c837098e5b.js" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@ -1,29 +0,0 @@
|
||||
<form class="form-horizontal" method="post">{% csrf_token %}
|
||||
<fieldset>
|
||||
<legend>{{ title }}</legend>
|
||||
{% for field in form %}
|
||||
{% if field.errors %}
|
||||
<div class="control-group error">
|
||||
<label class="control-label">{{ field.label }}</label>
|
||||
<div class="controls">{{ field }}
|
||||
<span class="help-inline">
|
||||
{% for error in field.errors %}{{ error }}{% endfor %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ field.label }}</label>
|
||||
<div class="controls">{{ field }}
|
||||
{% if field.help_text %}
|
||||
<p class="help-inline"><small>{{ field.help_text }}</small></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</fieldset>
|
||||
<div class="form-actions text-right">
|
||||
<button type="submit" class="btn btn-primary" >Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
@ -1,31 +1,24 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container" id="project">
|
||||
|
||||
<h1>{{ project.name }}</h1>
|
||||
<div class="row">
|
||||
<div class="col-9">
|
||||
{% block page %}
|
||||
<h3 class="text-center">Due in {{ project.deadline|timeuntil }}</h3>
|
||||
<p>There have been {{ project.submissions.count }} submissions so far...</p>
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<div class="nav flex-column nav-pills" role="tablist">
|
||||
<a class="nav-link" role=tab"
|
||||
href="{% url 'project' project_id=project.id %}">Project info</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 %}"
|
||||
role="tab">{{ page.title }}</a>
|
||||
{% endfor %}
|
||||
<a class="nav-link" role="tab"
|
||||
href="">Record a submission</a>
|
||||
<a class="nav-link" role="tab"
|
||||
href="{% url 'submission' project_id=project.id %}">Send a file</a>
|
||||
</div>
|
||||
</div>
|
||||
<h1>{{ project.name }}</h1>
|
||||
<div>
|
||||
{% 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>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div class="project-links">
|
||||
<div class="pills" role="tablist">
|
||||
<a role=tab" href="{% url 'project' project_id=project.id %}">Project info</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 'submission' project_id=project.id %}">Send a file</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -2,17 +2,13 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="container">
|
||||
<h1>Projects for {{ ensemble.name }}</h1>
|
||||
<div class="col-md-8 offset-md-2">
|
||||
<div class="list-group">
|
||||
<div class="list-group narrow">
|
||||
{% for project in ensemble.active_projects %}
|
||||
<a class="list-group-item list-group-item-action" href="{% url 'project' project_id=project.id %}">
|
||||
<h4>{{ project.name }}</h4>
|
||||
<a class="" href="{% url 'project' project_id=project.id %}">
|
||||
<h3>{{ project.name }}</h3>
|
||||
<p><small>Due in {{ project.deadline|timeuntil }}</small></p>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -1,25 +1,24 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-md-4 offset-md-4">
|
||||
<div class="card">
|
||||
<div class="card-header">Enter the ensemble details given to you</div>
|
||||
<div class="card-body">
|
||||
<div class="narrow">
|
||||
<div>
|
||||
<h3>My Ensembles</h3>
|
||||
<ul>
|
||||
{% for ensemble in current %}
|
||||
<li><a href="/?code={{ ensemble.ensemble_code}}">{{ ensemble.name }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<form action="" method="POST">
|
||||
<h3>Add a new ensemble</h3>
|
||||
{% csrf_token %}
|
||||
<div class="form-group">
|
||||
<label for="code">Ensemble Code</label>
|
||||
<input type="text" class="form-control" placeholder="xxxx-xxxx-xxxx" name="code" value="{{ code }}"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="passphrase">Passphrase</label>
|
||||
<input type="password" class="form-control" name="passphrase"/>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
{{ form }}
|
||||
<div class="form-actions">
|
||||
<button class="btn btn-primary">Enter</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -10,7 +10,13 @@
|
||||
</p>
|
||||
|
||||
<div class="">
|
||||
{% include "interface/bootstrap-form.html" %}
|
||||
<form action="" method="POST" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn-primary">Continue</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -4,44 +4,24 @@
|
||||
{% block content %}
|
||||
|
||||
|
||||
<div class="container">
|
||||
<div class="col-md-4 offset-md-4">
|
||||
<div class="card" id="legacy-upload">
|
||||
<div class="card-header">Ready to upload file</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ upload.url }}" enctype="multipart/form-data" id="video-upload">
|
||||
{% for field, value in upload.fields.items %}
|
||||
<input type="hidden" name="{{ field }}" value="{{ value }}" />
|
||||
{% endfor %}
|
||||
|
||||
<input name="file" type="file" accept="video/*"/>
|
||||
<div class="narrow">
|
||||
<h3>Ready to upload file</h3>
|
||||
<form method="POST" action="{{ upload.url }}" enctype="multipart/form-data" id="video-upload">
|
||||
{% for field, value in upload.fields.items %}
|
||||
<input type="hidden" name="{{ field }}" value="{{ value }}" />
|
||||
{% endfor %}
|
||||
|
||||
<div class="form-actions text-right">
|
||||
<a class="btn btn-secondary" href="{% url 'cancel_submission' project_id=project.pk submission_id=submission.pk %}">Cancel</a>
|
||||
<button class="btn btn-primary">Upload</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<input name="file" type="file" accept="video/*" />
|
||||
|
||||
<div class="form-actions text-right">
|
||||
<a class=""
|
||||
href="{% url 'cancel_submission' project_id=project.pk submission_id=submission.pk %}">Cancel</a>
|
||||
|
||||
<button class="">Upload</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script src="{% static 'dropzone/dropzone.js' %}"></script>
|
||||
<script>
|
||||
(function() {
|
||||
</div>
|
||||
|
||||
//document.getElementById('fallback-file').remove();
|
||||
|
||||
Dropzone.options.videoUpload = {
|
||||
paramName: "file", // The name that will be used to transfer the file
|
||||
maxFilesize: 500, // MB
|
||||
accept: function(file, done) {
|
||||
if (file.name == "justinbieber.jpg") {
|
||||
done("Naha, you don't.");
|
||||
} else { done(); }
|
||||
}
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
@ -1,3 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
0
interface/tests/__init__.py
Normal file
0
interface/tests/__init__.py
Normal file
26
interface/tests/test_submission.py
Normal file
26
interface/tests/test_submission.py
Normal file
@ -0,0 +1,26 @@
|
||||
from django.test import TestCase, Client
|
||||
|
||||
from interface import models
|
||||
|
||||
class SubmissionTestCase(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.client = Client()
|
||||
|
||||
def test_submission(self):
|
||||
ensemble = models.Ensemble.objects.create(name="The Be Sharps", passphrase="Homer", bucket="virtual-orchestra")
|
||||
project = ensemble.projects.create(name='Baby on Board')
|
||||
|
||||
response = self.client.post('/register', {'code': ensemble.code, 'passphrase': ensemble.passphrase})
|
||||
self.assertRedirects(response, '/')
|
||||
|
||||
response = self.client.post(f"/projects/{project.pk}/submission", {'name': 'Ned', 'instrument': 'God'})
|
||||
|
||||
upload = response.context['upload']
|
||||
self.assertEqual(upload['url'], f"https://{ensemble.bucket}.s3.amazonaws.com/")
|
||||
self.assertRegex(upload['fields']['key'], r'^baby-on-board\/[0-9T\-]+_ned_god_\$\{filename\}$')
|
||||
self.assertEqual(upload['fields']['success_action_redirect'], 'http://testserver/projects/1/submission/1/complete')
|
||||
|
||||
self.assertEqual(models.Submission.objects.count(), 1)
|
||||
self.assertRedirects(self.client.get(f"/projects/{project.pk}/submission/1/cancel"), '/projects/1')
|
||||
self.assertEqual(models.Submission.objects.count(), 0)
|
||||
@ -14,20 +14,30 @@ def forbidden(request):
|
||||
return render(request, 'interface/forbidden.html', {})
|
||||
|
||||
def register(request):
|
||||
code = ''
|
||||
try:
|
||||
code = request.POST.get('code', request.GET['code'])
|
||||
passphrase = request.POST.get('passphrase')
|
||||
|
||||
request.ensemble_id = request.session.get('ensemble')
|
||||
registered = request.session.setdefault('registered', {})
|
||||
|
||||
ensemble = models.Ensemble.objects.get(code=code)
|
||||
if ensemble.password != passphrase:
|
||||
raise ValueError("Incorrect passphase")
|
||||
if request.method == "POST":
|
||||
form = forms.CodeForm(request.POST)
|
||||
|
||||
request.session['ensemble'] = ensemble.pk
|
||||
return redirect('my_projects')
|
||||
except:
|
||||
logger.exception("Registration failed")
|
||||
return render(request, 'interface/register.html', {'code': code})
|
||||
if form.is_valid():
|
||||
|
||||
data = form.cleaned_data;
|
||||
ensemble = models.Ensemble.objects.get(code=data['code'].replace('-', ''))
|
||||
|
||||
|
||||
if ensemble.passphrase == data['passphrase']:
|
||||
request.session['ensemble'] = ensemble.pk
|
||||
registered[ensemble.code] = ensemble.pk
|
||||
return redirect('my_projects')
|
||||
|
||||
else:
|
||||
form = forms.CodeForm(initial=request.GET)
|
||||
|
||||
current = models.Ensemble.objects.filter(pk__in=registered.values())
|
||||
|
||||
return render(request, 'interface/register.html', {'form': form, 'current': current})
|
||||
|
||||
|
||||
@check_allowed
|
||||
@ -60,6 +70,10 @@ def submission(request, project_id):
|
||||
s.project_id = project_id
|
||||
s.save()
|
||||
|
||||
data = form.cleaned_data
|
||||
request.session['name'] = data['name']
|
||||
request.session['instrument'] = data['instrument']
|
||||
|
||||
redirect = request.build_absolute_uri(resolve_url('complete_submission', project_id=project.pk, submission_id=s.pk))
|
||||
|
||||
upload = project.presigned_post(s.generate_key(),
|
||||
@ -69,7 +83,8 @@ def submission(request, project_id):
|
||||
|
||||
return render(request, 'interface/upload.html', context)
|
||||
else:
|
||||
form = forms.SubmissionForm()
|
||||
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.html', context)
|
||||
@ -77,7 +92,7 @@ def submission(request, project_id):
|
||||
@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.submissions.get(pk=submission_id)
|
||||
submission = project.all_submissions.get(pk=submission_id)
|
||||
submission.delete()
|
||||
return redirect('project', project_id=project_id)
|
||||
|
||||
|
||||
@ -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 = []
|
||||
ALLOWED_HOSTS = ['localhost', '192.168.100.123']
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user