Many interface changes

This commit is contained in:
Tris Forster 2023-03-03 16:07:30 +11:00
parent 69f747d5b5
commit d1328ae1b1
11 changed files with 188 additions and 94 deletions

View File

@ -21,14 +21,16 @@
{% block page %} {% block page %}
<h3 class="title">Projects for {{ensemble.name }}</h3> <h3 class="title">Projects for {{ensemble.name }}</h3>
<p>{{ ensemble.details|markdown }}</p> <div class="content">
{{ ensemble.details|markdown }}
</div>
<p> <div class="block">
Administrators: Contacts:
{% for admin in ensemble.admins.all %} {% for admin in ensemble.admins.all %}
<a href="mailto:{{ admin.email }}">{% firstof admin.get_full_name admin.get_username %}</a> <a href="mailto:{{ admin.email }}" class="tag">{% firstof admin.get_full_name admin.get_username %}</a>
{% endfor %} {% endfor %}
</p> </div>
{% include 'interface/project_items.html' %} {% include 'interface/project_items.html' %}
@ -39,11 +41,10 @@ Administrators:
<p class="card-header-title">Admin Details</p> <p class="card-header-title">Admin Details</p>
</header> </header>
<div class="card-content"> <div class="card-content">
<ul>
<p> <li><a href="{{ ensemble_link }}">Ensemble Sharing Link</a></li>
Joining instructions for participants<br/><br/> <li><a href="{% url 'project_create' ensemble.pk %}">Add a new project</a></li>
URL: <a href="{{ ensemble_link }}">{{ ensemble_link }}</a><br/> </ul>
</p>
</div> </div>
</div> </div>
</div> </div>

View File

@ -2,9 +2,7 @@
{% block content %} {% block content %}
<div class="columns mx-2">
<div class="columns">
<div class="column is-narrow is-hidden-touch" id="projectMenu"> <div class="column is-narrow is-hidden-touch" id="projectMenu">
<div style="margin: auto 2em;"> <div style="margin: auto 2em;">
<aside class="menu"> <aside class="menu">
@ -27,7 +25,7 @@
<li><a class="nav-link" href="{% url 'item_list' project=project.pk %}">My Music</a></li> <li><a class="nav-link" href="{% url 'item_list' project=project.pk %}">My Music</a></li>
{% endif %} {% endif %}
{% for page in project.wiki_pages.all %} {% for page in project.wiki_pages.all %}
<li><a class="nav-link <li><a class="nav-link"
href="{% url 'wiki' project=project.id pk=page.id %}">{{ page.title }}</a></li> href="{% url 'wiki' project=project.id pk=page.id %}">{{ page.title }}</a></li>
{% endfor %} {% endfor %}
<li><a role="tab" href="{% url 'resource_list' project=project.pk %}">Resources</a></li> <li><a role="tab" href="{% url 'resource_list' project=project.pk %}">Resources</a></li>
@ -76,9 +74,9 @@
</div> </div>
{% endif %} {% endif %}
<div class="block" style="margin: auto 2em"> <div class="block">
{% if request.is_admin %} {% if request.is_admin %}
<div class="admin-tools is-pulled-right"> <div class="admin-tools is-pulled-right is-hidden-mobile">
{% block admin %} {% block admin %}
{% endblock %} {% endblock %}
</div> </div>

View File

@ -14,60 +14,71 @@
{% endblock %} {% endblock %}
{% block page %} {% block page %}
<div class="box"> <div class="columns is-multiline">
{% if project.event_date %} <div class="column ">
<h3 class="subtitle is-centered"> <div class="box">
<b>{{ project.event_date|date:"l jS F Y, g:i A" }}</b>
{% if project.has_happened %}
({{ project.event_date|roughtimesince }} ago)
{% else %}
(in {{ project.event_date|roughtimeuntil }})
{% endif %}
</h3>
{% endif %}
<div class="block"> {% if project.event_date %}
{% if project.description %} <h3 class="subtitle is-centered">
<p class="content">{{ project.description|markdown }}</p> <b>{{ project.event_date|date:"l jS F Y, g:i A" }}</b>
{% else %} {% if project.has_happened %}
<p>No description</p> ({{ project.event_date|roughtimesince }} ago)
{% else %}
(in {{ project.event_date|roughtimeuntil }})
{% endif %}
</h3>
{% endif %} {% endif %}
<div class="block">
{% if project.description %}
<p class="content">{{ project.description|markdown }}</p>
{% else %}
<p>No description</p>
{% endif %}
</div>
{% if project.owner %}
<div class="block">
{% if project.owner.email %}
The project owner is <a href="mailto:{{ project.owner.email }}">{{ project.owner }}</a>
{% else %}
The project owner is {{ project.owner }}.
{% endif %}
</div>
{% endif %}
</div>
</div> </div>
{% if 'library' in modules %} {% if 'library' in modules %}
<div class="block"> <div class="column is-one-third">
{% include 'library/project_detail.html' %} {% include 'library/project_detail.html' %}
</div> </div>
{% endif %} {% endif %}
{% if 'submission' in modules %} {% if 'submission' in modules %}
<div class="block"> <div class="column">
{% include 'submissions/project_detail.html' %} {% include 'submissions/project_detail.html' %}
</div> </div>
{% endif %}
{% if project.owner %}
<div class="block">
{% if project.owner.email %}
The project owner is <a href="mailto:{{ project.owner.email }}">{{ project.owner }}</a>
{% else %}
The project owner is {{ project.owner }}.
{% endif %}
</div>
{% endif %}
{% if request.is_admin %}
<div class="block">
<a href="{{ project_link }}">Project Link</a>
</div>
{% endif %} {% endif %}
</div> </div>
{% if request.is_admin %}
<div class="box">
<h3 class="subtitle">Admin Actions</h3>
<ul>
<li><a href="{{ project_link }}">Project Link</a></li>
{% if 'library' in modules %}
<li><a href="{% url 'item_list_manage' project=project.pk %}">Manage items</a></li>
{% endif %}
</ul>
</div>
{% endif %}
<!--
<div> <div>
<a href="{% url 'forget_resource' 'project' project.pk %}">Forget this project</a> <a href="{% url 'forget_resource' 'project' project.pk %}">Forget this project</a>
</div> </div>
-->
{% endblock %} {% endblock %}

View File

@ -9,6 +9,7 @@
{% endblock %} {% endblock %}
{% block page %} {% block page %}
<h3 class="subtitle">Resources</h3>
<div class="columns is-multiline"> <div class="columns is-multiline">
{% for resource in object_list %} {% for resource in object_list %}
{% with download=resource.file.url %} {% with download=resource.file.url %}
@ -51,7 +52,7 @@
{% endwith %} {% endwith %}
{% empty %} {% empty %}
<div class="column"> <div class="column">
<p>There are resources for this project</p> <p>There are no resources for this project</p>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>

View File

@ -9,6 +9,7 @@ from django.core.files.storage import get_storage_class
from django.db.models import Q, Count, Min, Max from django.db.models import Q, Count, Min, Max
import re import re
import os.path
from byostorage.user import BYOStorage from byostorage.user import BYOStorage
from byostorage.cached import CachedStorage from byostorage.cached import CachedStorage
@ -219,6 +220,9 @@ class Work(models.Model):
sections = list(dict(sections).items()) # primitive unique() sections = list(dict(sections).items()) # primitive unique()
return sections return sections
def pdfs(self):
return self.docs.filter(doctype=Document.DOCTYPE_PDF)
@property @property
def physical_parts(self): def physical_parts(self):
if not self.original_parts: if not self.original_parts:
@ -345,6 +349,9 @@ class Document(models.Model):
self.upload.delete(save=False) self.upload.delete(save=False)
return super().delete(*args, **kwargs) return super().delete(*args, **kwargs)
def filename(self):
return os.path.basename(self.upload.name)
def __str__(self): def __str__(self):
return self.upload.name return self.upload.name

View File

@ -78,8 +78,8 @@
{% for tag, inst in document.work.music_tags %} {% for tag, inst in document.work.music_tags %}
<li class="is-clickable" onclick="assignInstrument('{{tag}}', this)")>{{ inst }}</li> <li class="is-clickable" onclick="assignInstrument('{{tag}}', this)")>{{ inst }}</li>
{% endfor %} {% endfor %}
<li><a onclick="document.getElementById('add-modal').classList.add('is-active')">Add instrument</a></li>
</ul> </ul>
<a onclick="document.getElementById('add-modal').classList.add('is-active')">Add Tag</a>
</div> </div>
<div class="column is-narrow"> <div class="column is-narrow">
<div class="has-text-centered"> <div class="has-text-centered">
@ -122,7 +122,7 @@
<input type="number" class="input" max="4" min="1" size="3" id="add-instrument-variant"/> <input type="number" class="input" max="4" min="1" size="3" id="add-instrument-variant"/>
</span> </span>
<span class="control"> <span class="control">
<button class="button is-primary" onclick="addInstrument()">Add</button> <button class="button is-primary" onclick="addInstrument();">Add</button>
</span> </span>
</div> </div>
</section> </section>
@ -301,7 +301,14 @@
variant.value = ''; variant.value = '';
name.value = ''; name.value = '';
let li = document.createElement('li');
li.classList.add("is-clickable");
li.addEventListener('click', () => assignInstrument(tag, li));
li.innerHTML = get_instrument(tag);
document.getElementById('unassigned-area').appendChild(li);
addTag(tag, pageNum, pageNum); addTag(tag, pageNum, pageNum);
closeAddModal();
} }
function assignInstrument(tag, el) { function assignInstrument(tag, el) {
@ -334,11 +341,6 @@
del.className = "icon is-action"; del.className = "icon is-action";
del.innerHTML = '<i class="fas fa-trash-alt" title="Remove this tag"></i>'; del.innerHTML = '<i class="fas fa-trash-alt" title="Remove this tag"></i>';
del.addEventListener('click', () => { del.addEventListener('click', () => {
let li = document.createElement('li');
li.classList.add("is-clickable");
li.addEventListener('click', () => assignInstrument(tag, li));
li.innerHTML = get_instrument(el.dataset.tag);
document.getElementById('unassigned-area').appendChild(li);
el.remove(); el.remove();
dirty=true; dirty=true;
}); });

View File

@ -1,21 +1,14 @@
{% extends "interface/project_base.html" %} {% extends "interface/project_base.html" %}
{% block admin %}
<a class="button is-link" href="{% url 'item_list_manage' project.pk %}">
<span class="icon"><i class="fas fa-list"></i></span>
<span>Change items</span>
</a>
{% endblock %}
{% block page %} {% block page %}
<form action="" method="post" target="_blank"> <form action="" method="post" target="_blank">
{% csrf_token %} {% csrf_token %}
<div> <div>
<div class="field is-grouped is-grouped-centered"> <div class="field is-grouped is-grouped-centered is-grouped-multiline">
<div class="field has-addons control"> <div class="field has-addons control has-addons-centered is-expanded">
<span class="control"> <span class="control is-hidden-mobile">
<a class="button is-static">Your Instrument</a> <a class="button is-static">Instrument</a>
</span> </span>
<span class="control"> <span class="control">
@ -47,12 +40,12 @@
</div> </div>
</div> </div>
<table class="table is-striped is-fullwidth"> <table class="table is-striped mx-auto">
<thead> <thead>
<tr> <tr>
<th/> <th/>
<th>Piece</th> <th>Piece</th>
<th>Running time</th> <th class="is-hidden-mobile">Running time</th>
<th>Part</th> <th>Part</th>
<th/> <th/>
</tr> </tr>
@ -68,11 +61,11 @@
{{ item.work.name }} {{ item.work.name }}
{% endif %} {% endif %}
</td> </td>
<td>{% firstof item.work.running_time "------" %}</td> <td class="is-hidden-mobile">{% firstof item.work.running_time "------" %}</td>
<td class="select-cell"> <td class="select-cell">
<input type="hidden" name="works" value="{{ item.work.pk }}"/> <input type="hidden" name="works" value="{{ item.work.pk }}"/>
<span class="select is-small"> <span class="select is-small" style="width: 100%">
<select name="instruments"> <select name="instruments" id="part-{{ item.work.pk }}" style="width: 100%">
<option value='-'>None</option> <option value='-'>None</option>
{% for tag, name in item.work.digital_parts %} {% for tag, name in item.work.digital_parts %}
<option value='{{ tag }}'>{{ name }}</option> <option value='{{ tag }}'>{{ name }}</option>
@ -81,7 +74,9 @@
</span> </span>
</td> </td>
<td> <td>
<a href=""><i class="fas fa-download"></i></a> <span class="is-action" onclick="downloadPart({{ item.work.collection_id }}, {{ item.work.pk }})">
<i class="fas fa-download" title="Download Part"></i>
</span>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
@ -90,11 +85,13 @@
<tr> <tr>
<td/> <td/>
<td/> <td/>
<td>{{ running_time }}</td> <td>{% firstof running_time "------" %}</td>
<td/> <td/>
<td> <td>
<!--
<button class="button is-link is-small" type="submit"><span class="icon"><i class="fas fa-copy"></i></span><span>Single combined PDF</span></button> <button class="button is-link is-small" type="submit"><span class="icon"><i class="fas fa-copy"></i></span><span>Single combined PDF</span></button>
<a class="button is-link is-small"><span class="icon"><i class="fas fa-archive"></i></span><span>Individual files (zipped)</span></a> <a class="button is-link is-small"><span class="icon"><i class="fas fa-archive"></i></span><span>Individual files (zipped)</span></a>
-->
</td> </td>
</tr> </tr>
</tfoot> </tfoot>
@ -154,6 +151,17 @@ function selectParts(inst, part) {
} }
function downloadPart(collection, work) {
let part = document.getElementById("part-" + work).value;
if (part == '-') {
alert("No part selected!");
return;
}
console.log(part);
let url = "/collections/" + collection + "/works/" + work + "/download?tag=" + part;
window.location = url;
}
document.getElementById("instrument-name").value = localStorage.getItem('instrument-name', 'All'); document.getElementById("instrument-name").value = localStorage.getItem('instrument-name', 'All');
document.getElementById("part-preference").value = localStorage.getItem('part-preference', 'Any'); document.getElementById("part-preference").value = localStorage.getItem('part-preference', 'Any');
updateParts(); updateParts();

View File

@ -1,12 +1,50 @@
<h4 class="is-size-4">Items</h4> <div class="panel">
<ul> <p class="panel-heading">
{% for item in project.items.all %} Items
{% with work=item.work %} </p>
<li>
<a href="{% url 'work_detail' item.work.collection.pk item.work.pk %}">{{ item.work.name }}</a> {% for item in project.items.all %}
</li> {% with work=item.work %}
{% endwith %} <a class="panel-block" onclick="showDownloadOptions('{% url 'work_parts' work.collection_id work.pk %}')">
{% empty %} {{ item.work.name }}
<li>There are no items listed yet for this project - please check back later...</li> </a>
{% endfor %} {% endwith %}
</ul> {% empty %}
<span class="panel-block">
There are no items listed yet for this project - please check back later...
</span>
{% endfor %}
</div>
<div class="modal" id="download-modal">
<div class="modal-background" onclick="closeDownloadModal()"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Parts</p>
<button class="delete" aria-label="close" onclick="closeDownloadModal()"></button>
</header>
<section class="modal-card-body" id="download-target">
</section>
</div>
</div>
<script>
function showDownloadOptions(url) {
let target = document.getElementById("download-target");
target.innerHTML = "Loading available parts...";
document.getElementById("download-modal").classList.add('is-active');
fetch(url).then((data) => {
console.log(data);
data.text().then((text) => {
target.innerHTML = text;
});
});
}
function closeDownloadModal() {
document.getElementById("download-modal").classList.remove('is-active');
}
</script>

View File

@ -0,0 +1,25 @@
<h3 class="subtitle">{{ work.name }}</h3>
<div class="block">
{% for tag, name in work.digital_parts %}
<a class="tag is-info" href="{% url 'work_download' work.collection_id work.pk %}?tag={{ tag }}">{{ name }}</a>
{% endfor %}
</div>
<h3 class="subtitle">Files</h3>
<table class="table is-narrow is-fullwidth">
<tbody>
{% for doc in work.pdfs %}
<tr>
<td><a href="{{ doc.upload.url }}">{{ doc.filename }}</a></td>
</tr>
{% empty %}
<tr>
<td>There are no files available for this work</td>
</tr>
{% endfor %}
</tbody>
</table>
<p>
<a href="{% url 'work_detail' work.collection_id work.pk %}">More details...</a>
</p>

View File

@ -25,6 +25,7 @@ urlpatterns = [
path('collections/<int:collection>/works/<int:pk>', views.WorkDetailView.as_view(), name="work_detail"), path('collections/<int:collection>/works/<int:pk>', views.WorkDetailView.as_view(), name="work_detail"),
path('collections/<int:collection>/works/<int:pk>/edit', views.WorkUpdateView.as_view(), name="work_edit"), path('collections/<int:collection>/works/<int:pk>/edit', views.WorkUpdateView.as_view(), name="work_edit"),
path('collections/<int:collection>/works/<int:pk>/partset', views.WorkPartSetView.as_view(), name="work_partset"), path('collections/<int:collection>/works/<int:pk>/partset', views.WorkPartSetView.as_view(), name="work_partset"),
path('collections/<int:collection>/works/<int:pk>/parts', views.WorkPartsView.as_view(), name="work_parts"),
path('collections/<int:collection>/works/<int:pk>/add_to_project', views.WorkAddToProject.as_view(), name="work_add_to_project"), path('collections/<int:collection>/works/<int:pk>/add_to_project', views.WorkAddToProject.as_view(), name="work_add_to_project"),
path('collections/<int:collection>/works/<int:pk>/upload', views.WorkAddDocumentView.as_view(), name="document_add"), path('collections/<int:collection>/works/<int:pk>/upload', views.WorkAddDocumentView.as_view(), name="document_add"),
path('collections/<int:collection>/works/<int:pk>/download', views.WorkDownloadView.as_view(), name="work_download"), path('collections/<int:collection>/works/<int:pk>/download', views.WorkDownloadView.as_view(), name="work_download"),

View File

@ -273,7 +273,9 @@ class WorkAddToProject(CollectionMixin, FormView):
work.project_items.create(project=project, approved_by=self.request.user, checkout=now()) work.project_items.create(project=project, approved_by=self.request.user, checkout=now())
return redirect('item_list', project=project.pk) return redirect('item_list', project=project.pk)
class WorkPartsView(CollectionMixin, DetailView):
model = models.Work
template_name = "library/work_parts_fragment.html"
class WorkPartSetView(CollectionMixin, DetailView): class WorkPartSetView(CollectionMixin, DetailView):
template_name = "library/work_partset.html" template_name = "library/work_partset.html"