From 45937a65a858369e3489239e2b4adb46c4accdf1 Mon Sep 17 00:00:00 2001 From: Lukas Winkler Date: Sun, 19 Jul 2020 21:38:09 +0200 Subject: [PATCH] support showing acronym letters --- acros/forms.py | 6 ++ acros/migrations/0045_auto_20200719_1838.py | 24 +++++ acros/models/Acronym.py | 5 + acros/templates/acros/add.html | 2 +- acros/templates/acros/addform.html | 4 +- acros/templates/acros/detail.html | 5 +- acros/templates/acros/edit.html | 4 +- acros/templates/acros/edit_letter.html | 23 +++++ acros/urls.py | 1 + acros/views.py | 10 +- static/app.js | 104 +++++++++++++------- static/scss/main.scss | 30 ++++++ 12 files changed, 177 insertions(+), 41 deletions(-) create mode 100644 acros/migrations/0045_auto_20200719_1838.py create mode 100644 acros/templates/acros/edit_letter.html diff --git a/acros/forms.py b/acros/forms.py index c68dbc0..27d3551 100644 --- a/acros/forms.py +++ b/acros/forms.py @@ -51,6 +51,12 @@ class EditForm(ModelForm): fields = ['name', 'full_name', "description_md", "stub", "tags"] +class EditLetterForm(ModelForm): + class Meta: + model = Acronym + fields = ["acro_letters"] + + class AddForm(ModelForm): tags = TagField() diff --git a/acros/migrations/0045_auto_20200719_1838.py b/acros/migrations/0045_auto_20200719_1838.py new file mode 100644 index 0000000..0ba7fd2 --- /dev/null +++ b/acros/migrations/0045_auto_20200719_1838.py @@ -0,0 +1,24 @@ +# Generated by Django 3.0.8 on 2020-07-19 18:38 + +import django.contrib.postgres.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('acros', '0044_auto_20200718_2030'), + ] + + operations = [ + migrations.AddField( + model_name='acronym', + name='acro_letters', + field=django.contrib.postgres.fields.ArrayField(base_field=models.SmallIntegerField(), null=True, size=None), + ), + migrations.AddField( + model_name='historicalacronym', + name='acro_letters', + field=django.contrib.postgres.fields.ArrayField(base_field=models.SmallIntegerField(), null=True, size=None), + ), + ] diff --git a/acros/models/Acronym.py b/acros/models/Acronym.py index db6dbd9..2f4a4c2 100644 --- a/acros/models/Acronym.py +++ b/acros/models/Acronym.py @@ -1,3 +1,4 @@ +from django.contrib.postgres.fields import ArrayField from django.core.exceptions import ValidationError from django.db import models from django.urls import reverse @@ -17,6 +18,10 @@ class Acronym(models.Model): name = models.CharField(max_length=100, validators=[valid_acronym]) full_name = models.CharField(max_length=1000) slug = models.SlugField(null=False, unique=True) + acro_letters = ArrayField( + models.SmallIntegerField(), + null=True + ) description_md = models.TextField(blank=True) description_html = models.TextField(editable=False) history = HistoricalRecords(excluded_fields=["created_date"]) diff --git a/acros/templates/acros/add.html b/acros/templates/acros/add.html index 3c144ee..3d67a07 100644 --- a/acros/templates/acros/add.html +++ b/acros/templates/acros/add.html @@ -12,7 +12,7 @@ {% csrf_token %} {% bootstrap_form form %} {% buttons %} - + {% endbuttons %} {% endblock %} diff --git a/acros/templates/acros/addform.html b/acros/templates/acros/addform.html index 8233b01..16ab8b4 100644 --- a/acros/templates/acros/addform.html +++ b/acros/templates/acros/addform.html @@ -2,7 +2,7 @@
{% csrf_token %} {% bootstrap_form form %} - {% buttons %} - + {% buttons %} + {% endbuttons %}
diff --git a/acros/templates/acros/detail.html b/acros/templates/acros/detail.html index ed48b4c..5ad6f85 100644 --- a/acros/templates/acros/detail.html +++ b/acros/templates/acros/detail.html @@ -12,12 +12,15 @@ {% block heading %}

{{ acro.name }}

-

{{ acro.full_name }}

+

+ {% for letter in acro.full_name %}{{ letter }}{% endfor %} +

{% endblock %} {% block admin_navbar %} Edit + Letters {% if user.is_staff %} Admin-Edit {% endif %} diff --git a/acros/templates/acros/edit.html b/acros/templates/acros/edit.html index 8ce8aa4..fe1c52a 100644 --- a/acros/templates/acros/edit.html +++ b/acros/templates/acros/edit.html @@ -3,7 +3,7 @@ {% load bootstrap4 %} {% block heading %} -

Edit "{{ form.name.value }}"

+

Edit "{{ acro.full_name }}"

{% endblock %} @@ -13,7 +13,7 @@ {% csrf_token %} {% bootstrap_form form %} {% buttons %} - + {% endbuttons %} diff --git a/acros/templates/acros/edit_letter.html b/acros/templates/acros/edit_letter.html new file mode 100644 index 0000000..76d82cf --- /dev/null +++ b/acros/templates/acros/edit_letter.html @@ -0,0 +1,23 @@ +{% extends 'base.html' %} +{% load static %} + +{% block heading %} +

Edit "{{ acro.full_name }}"

+{% endblock %} + + +{% block content %} +

+ {% for letter in acro.full_name %}{{ letter }}{% endfor %} +

+
+ {% csrf_token %} + {{ form.acro_letters }} + + +
+ +{% endblock %} + +{% block extra_head %} +{% endblock %} diff --git a/acros/urls.py b/acros/urls.py index 8f473e9..b5ce732 100644 --- a/acros/urls.py +++ b/acros/urls.py @@ -26,6 +26,7 @@ urlpatterns = [ path('acronym/add', views.AddView.as_view(), name="add"), path('acronym/', views.DetailView.as_view(), name='detail'), path('acronym//edit', views.EditView.as_view(), name='edit'), + path('acronym//edit-letters', views.EditLetterView.as_view(), name='edit_letter'), path('acronym//add/wikipedia', views.AddWikipediaView.as_view(), name='add_wikipedia'), path('acronym//add/paper', views.AddPaperView.as_view(), name='add_paper'), path('acronym//add/weblink', views.AddWeblinkView.as_view(), name='add_weblink'), diff --git a/acros/views.py b/acros/views.py index 5a09892..aff645d 100644 --- a/acros/views.py +++ b/acros/views.py @@ -7,7 +7,7 @@ from django.urls import reverse from django.views import generic from rest_framework import viewsets, filters -from acros.forms import EditForm, AddForm, WikipediaForm, PaperForm, WeblinkForm +from acros.forms import EditForm, AddForm, WikipediaForm, PaperForm, WeblinkForm, EditLetterForm from acros.models import Acronym, Tag, AcroOfTheDay, WikipediaLink, PaperReference, Weblink from acros.serializers import AcronymSerializer, AcronymListSerializer, TagSerializer from acros.utils.assets import get_css @@ -52,6 +52,14 @@ class EditView(LoginRequiredMixin, SuccessMessageMixin, generic.UpdateView): success_message = 'Acronym "%(name)s" was edited successfully' +class EditLetterView(LoginRequiredMixin, SuccessMessageMixin, generic.UpdateView): + template_name = 'acros/edit_letter.html' + context_object_name = 'acro' + model = Acronym + form_class = EditLetterForm + success_message = 'Letters were edited successfully' + + class AddView(LoginRequiredMixin, SuccessMessageMixin, generic.CreateView): template_name = "acros/add.html" form_class = AddForm diff --git a/static/app.js b/static/app.js index bbb9014..821c533 100644 --- a/static/app.js +++ b/static/app.js @@ -33,42 +33,78 @@ $(function () { autoSelect: true, }) const input = document.querySelector('input[name="tags"]') - input.classList.remove("form-control") + if (input) { + input.classList.remove("form-control") - document.querySelector("form").addEventListener("submit", function () { - const list = JSON.parse(input.value).map(function (item) { - return item['value']; - }) - input.value = list.join(",") - console.log(input.value) - return false; - }) - const tagify = new Tagify(input, { - whitelist: [], - maxTags: 10, - dropdown: { - maxItems: 20, - enabled: 0 - } - }) - fetch("/api/tag/") - .then(response => response.json()) - .then(data => - data.map(function (item) { - return item['name']; + document.querySelector("form").addEventListener("submit", function () { + const list = JSON.parse(input.value).map(function (item) { + return item['value']; }) - ) - .then(data => { - - tagify.settings.whitelist = data - + input.value = list.join(",") + console.log(input.value) + return false; }) + const tagify = new Tagify(input, { + whitelist: [], + maxTags: 10, + dropdown: { + maxItems: 20, + enabled: 0 + } + }) + fetch("/api/tag/") + .then(response => response.json()) + .then(data => + data.map(function (item) { + return item['name']; + }) + ) + .then(data => { - const myCodeMirror = CodeMirror.fromTextArea( - document.getElementById("id_description_md"), - { - lineWrapping: true, - lineNumbers: true, - } - ); + tagify.settings.whitelist = data + + }) + } + if (typeof CodeMirror !== "undefined") { + const myCodeMirror = CodeMirror.fromTextArea( + document.getElementById("id_description_md"), + { + lineWrapping: true, + lineNumbers: true, + } + ); + } + const letterform = document.getElementById("letterform"); + if (letterform) { + console.log("found form") + const letters = document.querySelectorAll("#letterselect span") + letters.forEach(function (letter) { + letter.addEventListener("click", function (e) { + letter.classList.toggle("als") + }) + }) + letterform.addEventListener("submit", function (e) { + const result = []; + for (let i = 0; i < letters.length; i++) { + const el = letters[i]; + if (el.classList.contains("als") && el.innerText !== " ") { + result.push(i); + } + } + const inputForm = document.getElementById("id_acro_letters"); + inputForm.value = result.join(","); + }); + const inButton = document.getElementById("initials"); + inButton.addEventListener("click", function () { + letters.forEach(function (el) { + const content = el.innerText + if (content !== content.toLowerCase()) { + el.classList.add("als") + } else { + el.classList.remove("als") + } + + }) + }); + } }) diff --git a/static/scss/main.scss b/static/scss/main.scss index 60e9b23..ac19a93 100644 --- a/static/scss/main.scss +++ b/static/scss/main.scss @@ -65,6 +65,36 @@ h1.acronym { .fullName { text-align: center; font-size: 2rem; + + .al { + transition: color .2s, text-decoration-color .2s; + text-decoration-line: underline; + text-decoration-color: white; + } + + &:hover { + .al { + color: green; + text-decoration-color: green; + } + } +} + +#letterselect { + span { + cursor: pointer; + user-select: none; + + &.als { + color: green; + } + } +} + +#letterform { + input[type=text] { + display: none; + } } /*.linkwrapper {*/