Library working:

This commit is contained in:
Tris
2021-03-22 10:30:13 +11:00
parent 35555c3321
commit 1581f56b74
32 changed files with 511 additions and 211 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ class EnsembleAdmin(admin.ModelAdmin):
class ProjectAdmin(admin.ModelAdmin):
list_display = ['name', 'ensemble', 'deadline', 'active', 'slug']
list_display = ['name', 'ensemble', 'event_date', 'active', 'slug']
list_filter = ['ensemble', 'active']
class SubmissionAdmin(admin.ModelAdmin):
@@ -0,0 +1,93 @@
# Generated by Django 3.1.1 on 2021-03-21 23:10
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import interface.models
class Migration(migrations.Migration):
replaces = [('interface', '0001_initial'), ('interface', '0002_auto_20200904_1004'), ('interface', '0003_auto_20200905_0118'), ('interface', '0004_auto_20200905_0127'), ('interface', '0005_auto_20200905_0638'), ('interface', '0006_submission_key'), ('interface', '0007_auto_20200906_1009'), ('interface', '0008_auto_20200906_1122'), ('interface', '0009_auto_20200907_0103'), ('interface', '0010_auto_20200907_0148'), ('interface', '0011_auto_20200907_0234'), ('interface', '0012_remove_ensemble_bucket'), ('interface', '0013_auto_20200907_1455'), ('interface', '0014_auto_20200909_1016'), ('interface', '0015_resource_media_type'), ('interface', '0016_auto_20200910_2025'), ('interface', '0017_auto_20200914_0943'), ('interface', '0018_auto_20200914_1009'), ('interface', '0019_project_owner'), ('interface', '0020_auto_20201003_2103'), ('interface', '0021_project_description')]
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Project',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('active', models.BooleanField(default=True)),
],
),
migrations.CreateModel(
name='WikiPage',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('markdown', models.TextField()),
('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='wiki_pages', to='interface.project')),
('title', models.CharField(default='', max_length=255)),
],
),
migrations.CreateModel(
name='Ensemble',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('code', models.CharField(default=interface.models.generate_code, max_length=9)),
('passphrase', models.CharField(max_length=100)),
('admins', models.ManyToManyField(related_name='ensembles', to=settings.AUTH_USER_MODEL)),
],
),
migrations.AddField(
model_name='project',
name='ensemble',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='projects', to='interface.ensemble'),
),
migrations.AddField(
model_name='project',
name='deadline',
field=models.DateField(blank=True, null=True),
),
migrations.CreateModel(
name='Resource',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('key', models.CharField(blank=True, max_length=255)),
('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='resources', to='interface.project')),
('description', models.TextField(blank=True)),
('media_type', models.CharField(choices=[('audio', 'Audio'), ('video', 'Video'), ('general', 'General')], default='*', max_length=10)),
('visible', models.BooleanField(default=True)),
],
),
migrations.AddField(
model_name='project',
name='owner',
field=models.CharField(blank=True, max_length=255),
),
migrations.CreateModel(
name='Submission',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('instrument', models.CharField(max_length=100, verbose_name='Instrument / Voice')),
('notes', models.TextField(blank=True)),
('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='all_submissions', to='interface.project')),
('date', models.DateTimeField(auto_now_add=True)),
('complete', models.BooleanField(default=False)),
('url', models.CharField(blank=True, max_length=512)),
('private', models.BooleanField(default=False)),
],
),
migrations.AddField(
model_name='project',
name='description',
field=models.TextField(blank=True),
),
]
@@ -0,0 +1,19 @@
# Generated by Django 3.1.1 on 2021-03-12 02:56
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('interface', '0022_auto_20210303_2043'),
]
operations = [
migrations.AddField(
model_name='ensemble',
name='storage',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='byostorage.userstorage'),
),
]
@@ -0,0 +1,23 @@
# Generated by Django 3.1.1 on 2021-03-12 06:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('interface', '0023_ensemble_storage'),
]
operations = [
migrations.AddField(
model_name='project',
name='accept_submissions',
field=models.BooleanField(default=False, help_text='Allow media submissions from participants'),
),
migrations.AddField(
model_name='project',
name='has_items',
field=models.BooleanField(default=True, help_text='Enable items to be added from the library'),
),
]
@@ -0,0 +1,23 @@
# Generated by Django 3.1.1 on 2021-03-12 06:13
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('interface', '0024_auto_20210312_1712'),
]
operations = [
migrations.RenameField(
model_name='project',
old_name='has_items',
new_name='enable_library',
),
migrations.RenameField(
model_name='project',
old_name='accept_submissions',
new_name='enable_submissions',
),
]
@@ -0,0 +1,18 @@
# Generated by Django 3.1.1 on 2021-03-12 22:26
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('interface', '0025_auto_20210312_1713'),
]
operations = [
migrations.RenameField(
model_name='project',
old_name='deadline',
new_name='event_date',
),
]
+24 -1
View File
@@ -23,6 +23,18 @@ MEDIA_TYPES = [
('general', "General"),
]
def rough_date(d):
days = (self.event_date - timezone.now().date()).days
in_past = days < 0
if in_past:
days = abs(days)
if days ==0:
return "today!"
if days >= 7:
return in_past, "{0:d} weeks, {1:d} days".format(days / 7, days % 7)
return in_past, f"{days} days"
def generate_code(length=9):
return "".join([ random.choice('0123456789') for _ in range(length) ])
@@ -32,6 +44,7 @@ class Ensemble(models.Model):
passphrase = models.CharField(max_length=100)
admins = models.ManyToManyField('auth.User', related_name='ensembles')
slug = models.SlugField(max_length=100, editable=False)
storage = models.ForeignKey('byostorage.UserStorage', null=True, on_delete=models.SET_NULL)
def active_projects(self):
return self.projects.filter(active=True)
@@ -53,9 +66,11 @@ class Project(models.Model):
ensemble = models.ForeignKey(Ensemble, related_name='projects', on_delete=models.CASCADE, null=True)
description = models.TextField(blank=True)
active = models.BooleanField(default=True)
deadline =models.DateField(null=True, blank=True)
event_date =models.DateField(null=True, blank=True)
owner = models.CharField(max_length=255, blank=True)
slug = models.SlugField(max_length=100, editable=False)
enable_library = models.BooleanField(default=True, help_text="Enable items to be added from the library")
enable_submissions = models.BooleanField(default=False, help_text="Allow media submissions from participants")
@property
def submissions(self):
@@ -65,6 +80,14 @@ class Project(models.Model):
key = os.path.join(self.slug, object_name)
return s3client.generate_presigned_post(BUCKET, key, Fields=fields or {}, Conditions=conditions or [], ExpiresIn=expires)
@property
def days(self):
return (self.event_date - timezone.now().date()).days
@property
def has_happened(self):
return self.event_date < timezone.now()
def save(self):
if not self.slug:
self.slug = slugify(self.name)
@@ -313,7 +313,8 @@ TD.select-cell {
}
DIV.selected {
background-color: #EEE;
background-color: var(--gray-blue);
color: white;
border: 1px solid #999;
border-radius: 5px;
}
+1
View File
@@ -5,6 +5,7 @@
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="icon" type="image/png" href="{% static 'interface/icon.png' %}" />
<link rel="stylesheet" href="{% static 'interface/css/polyphonic.css' %}"></link>
<title>{% block title %}Polyphonic{% endblock %}</title>
@@ -1,11 +1,11 @@
{% extends "base.html" %}
{% extends "interface/project_base.html" %}
{% block content %}
{% block page %}
<div style="flex-grow: 1">
<h1>Projects for {{ ensemble.name }}</h1>
<div class="list-group narrow">
{% for project in ensemble.active_projects %}
<a class="" href="{% url 'project_detail' pk=project.id %}">
<a class="" href="{% url 'project_detail' project=project.id %}">
<h3>{{ project.name }}</h3>
<p><small>
{% if project.deadline %}In {{ project.deadline|timeuntil }}<br/>{% endif %}
@@ -15,7 +15,7 @@
</a>
{% endfor %}
</div>
<div style="text-align: right; margin-top: 10px; color: #999;">
<div style="float: right; margin-top: 10px; color: #999;">
<small>{{ ensemble.ensemble_code }}</small>
</div>
</div>
@@ -10,25 +10,32 @@
{% endif %}
<h1>{{ project.name }}</h1>
{% block page %}
No content
{% endblock %}
{% if project %}
<div class="project-links">
<div class="pills" role="tablist">
<a role="tab" href="{% url 'project_detail' pk=project.id %}">Project info</a>
{% if project %}
<a role="tab" href="{% url 'project_detail' project=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=project.id pk=page.id %}">{{ page.title }}</a>
{% endfor %}
{% endif %}
{% if project and project.enable_submissions%}
<a role="tab" href="{% url 'resource_list' project=project.pk %}">Resources</a>
<!--a role="tab" href="">Record a submission</a-->
{% if request.is_admin %}
<a role="tab" href="{% url 'submission_list' project=project.id %}">Submissions</a>
{% endif %}
<a role="tab" href="{% url 'submission_create' project=project.id %}">Send a file</a>
{% endif %}
{% include "library/project_menu.html" %}
</div>
</div>
{% endif %}
{% endblock %}
@@ -2,30 +2,25 @@
{% load md2 %}
{% block page %}
{% block page %}
<div class="narrow">
{% if project.deadline %}
<h3 class="text-center">In {{ project.deadline|timeuntil }}</h3>
{% if project.event_date %}
<h3 class="text-center">{{ project.when }}</h3>
{% endif %}
<p>{{ project.description|markdown }}</p>
<p>{{ project.description|markdown }}</p>
{% if project.owner %}
<p>Project email: <a href="mailto:{{ project.owner }}">{{ project.owner }}</a></p>
<p>Project email: <a href="mailto:{{ project.owner }}">{{ project.owner }}</a></p>
{% endif %}
{% with sub_count=project.submissions.count %}
<p>There have been {{ sub_count }} submission{{ sub_count|pluralize }} so far...</p>
{% if sub_count %}
<h4>Recent submissions</h4>
<table style="width: 100%">
<tbody">
{% for submission in project.submissions|slice:":5" %}
<tr>
<td>{{ submission.date|timesince }} ago</td>
<td>{{ submission.name }} ({{ submission.instrument }})</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if project.enable_submissions %}
{% include 'submissions/project_detail.html' %}
{% endif %}
{% endwith %}
{% if project.enable_library %}
{% include 'library/project_detail.html' %}
{% endif %}
</div>
{% endblock %}
{% endblock %}
+9
View File
@@ -0,0 +1,9 @@
from django import template
import os.path
register = template.Library()
def basename(value):
return os.path.basename(value)
register.filter('basename', basename)
+2 -2
View File
@@ -11,8 +11,8 @@ urlpatterns = [
path('manage', views.ManageView.as_view(), name="manage"),
path('', views.EnsembleDetailView.as_view(), name='ensemble_detail'),
path('projects/<int:pk>', views.ProjectDetailView.as_view(), name="project_detail"),
path('projects/<int:pk>/submissions.mk', views.ProjectMakefileView.as_view(), name="project_makefile"),
path('projects/<int:project>', views.ProjectDetailView.as_view(), name="project_detail"),
path('projects/<int:project>/submissions.mk', views.ProjectMakefileView.as_view(), name="project_makefile"),
path('projects/<int:project>/page/<int:pk>', views.WikiView.as_view(), name="wiki"),
path('projects/<int:project>/page/<int:pk>/edit', views.WikiEditView.as_view(), name="wiki_edit"),
+3 -3
View File
@@ -207,10 +207,10 @@ class EnsembleDetailView(EnsembleMixin, DetailView):
def get_object(self):
return models.Ensemble.objects.get(pk=self.request.ensemble_id)
class ProjectDetailView(EnsembleMixin, DetailView):
class ProjectDetailView(ProjectMixin, DetailView):
def get_queryset(self):
return models.Project.objects.filter(ensemble=self.request.ensemble_id)
def get_object(self):
return self.get_project()
class ProjectMakefileView(EnsembleMixin, DetailView):
template_name = 'interface/project_submissions.mk'