Add component tagging system

This commit is contained in:
Nathan Chapman 2022-08-03 09:48:47 -06:00
parent 808470aa93
commit 8bc68d2060
12 changed files with 346 additions and 12 deletions

View File

@ -29,7 +29,7 @@
<section>
<span>
{% for tag in component.tags.all %}
<a class="tag__item" href="{% url 'tag-detail' tag.pk %}">{{tag.name}}</a>
<a class="tag tag__info" href="{% url 'core:tag-detail' component.subject.school_year.year tag.pk %}">{{tag.name}}</a>
{% endfor %}
</span>
</section>

View File

@ -1,13 +1,33 @@
{% extends 'base.html' %}
{% block head_title %}Delete Tag | {% endblock head_title %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<menu>
<li><strong><a href="{% url 'core:schoolyear-detail' school_year.year %}">{{ school_year.year }}</a></strong></li>
<span></span>
<li><a href="{% url 'core:student-list' school_year.year %}">Students</a></li>
<span></span>
<li><a href="{% url 'core:stag-list' school_year.year %}">Student Tags</a></li>
<span></span>
<li><a href="{% url 'core:stag-detail' school_year.year tag.pk %}">{{ tag }}</a></li>
</menu>
</div>
{% endblock breadcrumbs %}
{% block content %}
<h1>Delete Studenttag</h1>
<form method="POST" action="{% url 'core:studenttag-delete' studenttag.pk %}">
<article class="form">
<header class="form__header">
<h1>Delete Tag</h1>
</header>
<form method="POST" action="{% url 'core:stag-delete' school_year.year tag.pk %}">
{% csrf_token %}
<p>Are you sure you want to delete "{{ studenttag }}"?</p>
<p>Are you sure you want to delete "{{ tag }}"?</p>
{{ form.as_p }}
<p>
<input type="submit" value="Delete"> or <a href="{% url 'core:studenttag-detail' studenttag.pk %}">cancel</a>
<input type="submit" value="Delete" class="action-delete"> or <a href="{% url 'core:stag-update' school_year.year tag.pk %}">cancel</a>
</p>
</form>
</form>
</article>
{% endblock %}

View File

@ -16,7 +16,12 @@
{% block content %}
<article class="form">
<header class="form__header">
<h1>Edit Tag</h1>
<p>
<a href="{% url 'core:stag-delete' school_year.year tag.pk %}" class="action-button action-delete">Delete</a>
</p>
</header>
<form method="POST" action="{% url 'core:stag-update' school_year.year tag.pk %}">
{% csrf_token %}
{{ form.as_p }}

View File

@ -18,7 +18,7 @@
<h1>Subjects</h1>
<a href="{% url 'core:subject-create' school_year.year %}" class="action-button">+ New Subject</a>
</div>
<a href="">Tags &rarr;</a>
<a href="{% url 'core:tag-list' school_year.year %}">Tags &rarr;</a>
</header>
<table class="list__table">
<thead>

View File

@ -0,0 +1,33 @@
{% extends 'base.html' %}
{% block head_title %}Delete Tag | {% endblock head_title %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<menu>
<li><strong><a href="{% url 'core:schoolyear-detail' school_year.year %}">{{ school_year.year }}</a></strong></li>
<span></span>
<li><a href="{% url 'core:subject-list' school_year.year %}">Subjects</a></li>
<span></span>
<li><a href="{% url 'core:tag-list' school_year.year %}">Tags</a></li>
<span></span>
<li><a href="{% url 'core:tag-detail' school_year.year tag.pk %}">{{ tag }}</a></li>
</menu>
</div>
{% endblock breadcrumbs %}
{% block content %}
<article class="form">
<header class="form__header">
<h1>Delete Tag</h1>
</header>
<form method="POST" action="{% url 'core:tag-delete' school_year.year tag.pk %}">
{% csrf_token %}
<p>Are you sure you want to delete "{{ tag }}"?</p>
{{ form.as_p }}
<p>
<input type="submit" value="Delete" class="action-delete"> or <a href="{% url 'core:tag-update' school_year.year tag.pk %}">cancel</a>
</p>
</form>
</article>
{% endblock %}

View File

@ -0,0 +1,28 @@
{% extends 'base.html' %}
{% block head_title %}New Tag | {% endblock head_title %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<menu>
<li><strong><a href="{% url 'core:schoolyear-detail' school_year.year %}">{{ school_year.year }}</a></strong></li>
<span></span>
<li><a href="{% url 'core:subject-list' school_year.year %}">Subjects</a></li>
<span></span>
<li><a href="{% url 'core:tag-list' school_year.year %}">Tags</a></li>
</menu>
</div>
{% endblock breadcrumbs %}
{% block content %}
<article class="form">
<h1>+ New Tag</h1>
<form method="POST" action="{% url 'core:tag-create' school_year.year %}">
{% csrf_token %}
{{ form.as_p }}
<p>
<input type="submit" value="Create"> or <a href="{% url 'core:tag-list' school_year.year %}">cancel</a>
</p>
</form>
</article>
{% endblock %}

View File

@ -0,0 +1,50 @@
{% extends 'base.html' %}
{% load helpers %}
{% block head_title %}Tag {{ tag }} | {% endblock head_title %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<menu>
<li><strong><a href="{% url 'core:schoolyear-detail' school_year.year %}">{{ school_year.year }}</a></strong></li>
<span></span>
<li><a href="{% url 'core:subject-list' school_year.year %}">Subjects</a></li>
<span></span>
<li><a href="{% url 'core:tag-list' school_year.year %}">Tags</a></li>
</menu>
</div>
{% endblock breadcrumbs %}
{% block content %}
<article class="detail">
<header class="detail__header">
<div class="detail__title">
<h1>{{ tag }}</h1>
</div>
<a href="{% url 'core:tag-update' school_year.year tag.pk %}" class="action-button">Edit</a>
</header>
<section>
<h3>Subjects with this tag</h3>
<table class="list__table">
<thead>
<tr>
<th>Subject</th>
<th>Name</th>
</tr>
</thead>
<tbody>
{% for component in tag.component_set.all %}
<tr class="has-link" onclick="document.location='{% url 'core:component-detail' school_year.year component.subject.pk component.pk %}'">
<td>{{ component.subject.name }}</td>
<td>{{ component }}</td>
</tr>
{% empty %}
<tr>
<td colspan="2">No components tagged yet.</td>
</tr>
{% endfor %}
</tbody>
</table>
</section>
</article>
{% endblock %}

View File

@ -0,0 +1,35 @@
{% extends 'base.html' %}
{% block head_title %}Edit Tag | {% endblock head_title %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<menu>
<li><strong><a href="{% url 'core:schoolyear-detail' school_year.year %}">{{ school_year.year }}</a></strong></li>
<span></span>
<li><a href="{% url 'core:subject-list' school_year.year %}">Subjects</a></li>
<span></span>
<li><a href="{% url 'core:tag-list' school_year.year %}">Tags</a></li>
<span></span>
<li><a href="{% url 'core:tag-detail' school_year.year tag.pk %}">{{ tag }}</a></li>
</menu>
</div>
{% endblock breadcrumbs %}
{% block content %}
<article class="form">
<header class="form__header">
<h1>Edit Tag</h1>
<p>
<a href="{% url 'core:tag-delete' school_year.year tag.pk %}" class="action-button action-delete">Delete</a>
</p>
</header>
<form method="POST" action="{% url 'core:tag-update' school_year.year tag.pk %}">
{% csrf_token %}
{{ form.as_p }}
<p>
<input type="submit" value="Save changes"> or <a href="{% url 'core:tag-detail' school_year.year tag.pk %}">cancel</a>
</p>
</form>
</article>
{% endblock %}

View File

@ -0,0 +1,32 @@
{% extends 'base.html' %}
{% load helpers %}
{% block head_title %}Tags | {% endblock head_title %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<menu>
<li><strong><a href="{% url 'core:schoolyear-detail' school_year.year %}">{{ school_year.year }}</a></strong></li>
<span></span>
<li><a href="{% url 'core:subject-list' school_year.year %}">Subjects</a></li>
</menu>
</div>
{% endblock breadcrumbs %}
{% block content %}
<article class="list">
<header class="list__header">
<div class="list__title">
<h1>Tags</h1>
<a href="{% url 'core:tag-create' school_year.year %}" class="action-button">+ New Tag</a>
</div>
</header>
<section>
{% for tag in tag_list %}
<a href="{% url 'core:tag-detail' school_year.year tag.pk %}" class="tag tag__info">{{ tag }}</a>
{% empty %}
<p>No tags yet.</p>
{% endfor %}
</section>
</article>
{% endblock %}

View File

@ -156,6 +156,37 @@ urlpatterns = [
])),
])),
])),
# Tags
path('tags/', include([
path(
'',
views.TagListView.as_view(),
name='tag-list'
),
path(
'new/',
views.TagCreateView.as_view(),
name='tag-create'
),
path('<int:tag_pk>/', include([
path(
'',
views.TagDetailView.as_view(),
name='tag-detail'
),
path(
'update/',
views.TagUpdateView.as_view(),
name='tag-update'
),
path(
'delete/',
views.TagDeleteView.as_view(),
name='tag-delete'
),
])),
])),
])),
# SchoolDays

View File

@ -409,6 +409,104 @@ class SubjectDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView):
return context
class TagListView(LoginRequiredMixin, ListView):
model = Tag
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['school_year'] = get_object_or_404(
SchoolYear, year=self.kwargs['year']
)
return context
class TagCreateView(
LoginRequiredMixin, SuccessMessageMixin, CreateView
):
model = Tag
success_message = 'Tag created.'
template_name_suffix = '_create_form'
fields = '__all__'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['school_year'] = get_object_or_404(
SchoolYear, year=self.kwargs['year']
)
return context
def get_success_url(self):
return reverse('core:tag-list', kwargs={
'year': self.kwargs['year']
})
class TagDetailView(LoginRequiredMixin, DetailView):
model = Tag
pk_url_kwarg = 'tag_pk'
def get_queryset(self):
queryset = Tag.objects.filter(
pk=self.kwargs.get(self.pk_url_kwarg)
).prefetch_related(
Prefetch(
'component_set',
queryset=Component.objects.filter(
subject__school_year__year=self.kwargs['year']
)
)
)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['school_year'] = get_object_or_404(
SchoolYear, year=self.kwargs['year']
)
return context
class TagUpdateView(
LoginRequiredMixin, SuccessMessageMixin, UpdateView
):
model = Tag
pk_url_kwarg = 'tag_pk'
success_message = 'Tag saved.'
fields = '__all__'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['school_year'] = get_object_or_404(
SchoolYear, year=self.kwargs['year']
)
return context
def get_success_url(self):
return reverse('core:tag-list', kwargs={
'year': self.kwargs['year']
})
class TagDeleteView(
LoginRequiredMixin, SuccessMessageMixin, DeleteView
):
model = Tag
pk_url_kwarg = 'tag_pk'
success_message = 'Tag deleted.'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['school_year'] = get_object_or_404(
SchoolYear, year=self.kwargs['year']
)
return context
def get_success_url(self):
return reverse('core:tag-list', kwargs={
'year': self.kwargs['year']
})
class ComponentListView(LoginRequiredMixin, ListView):
model = Component

View File

@ -219,6 +219,8 @@ input[type=submit],
border-radius: 0.5rem;
}
button.action-delete,
input[type=submit].action-delete,
.action-delete {
background-color: var(--color-danger);
}