mirror of
https://github.com/Findus23/acronomy.git
synced 2024-09-19 15:33:45 +02:00
multiple improvements
This commit is contained in:
parent
964f2748a0
commit
07d9bac5c5
23 changed files with 222 additions and 42 deletions
|
@ -32,6 +32,7 @@ INSTALLED_APPS = [
|
|||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.sitemaps',
|
||||
'simple_history',
|
||||
'debug_toolbar',
|
||||
'rest_framework',
|
||||
|
@ -122,7 +123,7 @@ INTERNAL_IPS = [
|
|||
'127.0.0.1',
|
||||
]
|
||||
|
||||
TAGGIT_CASE_INSENSITIVE = True
|
||||
SIMPLE_HISTORY_FILEFIELD_TO_CHARFIELD = True
|
||||
|
||||
SECURE_BROWSER_XSS_FILTER = True
|
||||
SECURE_CONTENT_TYPE_NOSNIFF = True
|
||||
|
|
|
@ -24,7 +24,7 @@ class WikiInline(OwnInline):
|
|||
fields = ["title"]
|
||||
|
||||
|
||||
class TagAdmin(admin.ModelAdmin):
|
||||
class TagAdmin(SimpleHistoryAdmin):
|
||||
# prepopulated_fields = {'slug': ('name',)}
|
||||
readonly_fields = ["slug"]
|
||||
|
||||
|
@ -36,20 +36,20 @@ class AcronymAdmin(SimpleHistoryAdmin):
|
|||
filter_horizontal = ["tags"]
|
||||
readonly_fields = ["slug"]
|
||||
list_display = ["name", "full_name"]
|
||||
list_filter = ["tags"]
|
||||
list_filter = ["tags", "modified_date", "created_date"]
|
||||
save_on_top = True
|
||||
|
||||
|
||||
class PaperAdmin(admin.ModelAdmin):
|
||||
class PaperAdmin(SimpleHistoryAdmin):
|
||||
date_hierarchy = "pubdate"
|
||||
list_display = ["title", "authors"]
|
||||
|
||||
|
||||
class LinkAdmin(admin.ModelAdmin):
|
||||
class LinkAdmin(SimpleHistoryAdmin):
|
||||
readonly_fields = ["host"]
|
||||
|
||||
|
||||
class WikipediaAdmin(admin.ModelAdmin):
|
||||
class WikipediaAdmin(SimpleHistoryAdmin):
|
||||
readonly_fields = ["thumbnail_height", "thumbnail_width"]
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,11 @@ class TagWidget(TextInput):
|
|||
value = edit_string_for_tags(value)
|
||||
return super().format_value(value)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TagWidget, self).__init__(*args, **kwargs)
|
||||
attrs = {"class": "taginput"}
|
||||
self.attrs.update(attrs)
|
||||
|
||||
|
||||
class TagField(CharField):
|
||||
"""
|
||||
|
@ -54,6 +59,7 @@ class AddForm(ModelForm):
|
|||
|
||||
fields = ['name', 'full_name', "description_md", "tags"]
|
||||
|
||||
|
||||
class AddWikipediaForm(ModelForm):
|
||||
tags = TagField()
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
from simple_history.utils import update_change_reason
|
||||
|
||||
from acros.models import WikipediaLink
|
||||
|
||||
|
@ -12,4 +13,5 @@ class Command(BaseCommand):
|
|||
if link.fetched:
|
||||
self.stdout.write(link.title)
|
||||
link.fetched = False
|
||||
update_change_reason(link, "refetch_wikipedia command")
|
||||
link.save()
|
||||
|
|
37
acros/migrations/0028_auto_20200608_1705.py
Normal file
37
acros/migrations/0028_auto_20200608_1705.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
# Generated by Django 3.0.6 on 2020-06-08 17:05
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('acros', '0027_auto_20200608_1521'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='acronym',
|
||||
name='created_date',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='acronym',
|
||||
name='modified_date',
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalacronym',
|
||||
name='created_date',
|
||||
field=models.DateTimeField(blank=True, default=django.utils.timezone.now, editable=False),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalacronym',
|
||||
name='modified_date',
|
||||
field=models.DateTimeField(blank=True, default=django.utils.timezone.now, editable=False),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
36
acros/migrations/0029_historicaltag.py
Normal file
36
acros/migrations/0029_historicaltag.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
# Generated by Django 3.0.6 on 2020-06-08 18:19
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import simple_history.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('acros', '0028_auto_20200608_1705'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='HistoricalTag',
|
||||
fields=[
|
||||
('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=100)),
|
||||
('slug', models.CharField(editable=False, max_length=100)),
|
||||
('history_id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('history_date', models.DateTimeField()),
|
||||
('history_change_reason', models.CharField(max_length=100, null=True)),
|
||||
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
|
||||
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'historical tag',
|
||||
'ordering': ('-history_date', '-history_id'),
|
||||
'get_latest_by': 'history_date',
|
||||
},
|
||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
||||
),
|
||||
]
|
18
acros/migrations/0030_auto_20200608_1823.py
Normal file
18
acros/migrations/0030_auto_20200608_1823.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.0.6 on 2020-06-08 18:23
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('acros', '0029_historicaltag'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='historicalwikipedialink',
|
||||
name='thumbnail',
|
||||
field=models.CharField(blank=True, max_length=100),
|
||||
),
|
||||
]
|
|
@ -13,8 +13,10 @@ class Acronym(models.Model):
|
|||
slug = models.SlugField(null=False, unique=True)
|
||||
description_md = models.TextField(blank=True)
|
||||
description_html = models.TextField(editable=False)
|
||||
history = HistoricalRecords()
|
||||
history = HistoricalRecords(excluded_fields=["created_date"])
|
||||
tags = models.ManyToManyField(Tag, related_name="acronyms")
|
||||
created_date = models.DateTimeField(auto_now_add=True)
|
||||
modified_date = models.DateTimeField(auto_now=True)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.description_html = md_to_html(self.description_md)
|
||||
|
@ -28,5 +30,8 @@ class Acronym(models.Model):
|
|||
def get_absolute_url(self):
|
||||
return reverse('detail', args=[str(self.slug)])
|
||||
|
||||
def first_letter(self):
|
||||
return self.name and self.name[0] or ''
|
||||
|
||||
class Meta:
|
||||
ordering = ["name"]
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.text import slugify
|
||||
from simple_history.models import HistoricalRecords
|
||||
|
||||
|
||||
class Tag(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
slug = models.CharField(max_length=100, editable=False)
|
||||
history = HistoricalRecords()
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
|
14
acros/sitemaps.py
Normal file
14
acros/sitemaps.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
from django.contrib.sitemaps import Sitemap
|
||||
|
||||
from .models import Acronym
|
||||
|
||||
|
||||
class AcronymSitemap(Sitemap):
|
||||
changefreq = "weekly"
|
||||
priority = 0.8
|
||||
|
||||
def items(self):
|
||||
return Acronym.objects.all()
|
||||
|
||||
def lastmod(self, obj: Acronym):
|
||||
return obj.modified_date
|
|
@ -1,10 +1,23 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load bootstrap4 %}
|
||||
{% load static %}
|
||||
|
||||
{% block heading %}
|
||||
<h1>Add new Acronym</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form method="post">{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="Add">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<input type="submit" value="Update">
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<script src="{% static "libs/codemirror.js" %}"></script>
|
||||
<script src="{% static "libs/markdown.js" %}"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% block title %}{{ acro.name }}: {{ acro.full_name }} ‐ Acronomy{% endblock %}
|
||||
|
||||
{% block heading %}
|
||||
<h1 class="acronym">{{ acro.name }}</h1>
|
||||
<p class="fullName">{{ acro.full_name }}</p>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if acro.description_html %}
|
||||
<div class="description">
|
||||
{{ acro.description_html|safe }}
|
||||
|
@ -64,7 +71,7 @@
|
|||
<p>{{ paper.authors }}</p>
|
||||
<div class="linkbar">
|
||||
<a href="{{ paper.ads_url }}" data-toggle="tooltip" title="view on ADS">
|
||||
<img src="{% static "images/ads.png" %}" width="32" height="32">
|
||||
<img src="{% static "images/adees.png" %}" width="32" height="32">
|
||||
</a>
|
||||
{% if paper.arxiv_id %}
|
||||
<a href="{{ paper.arxiv_url }}" data-toggle="tooltip" title="view on arXiv.org">
|
||||
|
@ -142,6 +149,8 @@
|
|||
{# </div>#}
|
||||
{# {% endif %}#}
|
||||
</div>
|
||||
<a href="{% url 'admin:acros_acronym_change' acro.id %}">Admin-Edit</a>
|
||||
{# <a href="{% url 'edit' acro.slug %}">Edit</a>#}
|
||||
{% if user.is_staff %}
|
||||
<a class="btn btn-outline-secondary" href="{% url 'admin:acros_acronym_change' acro.id %}">Admin-Edit</a>
|
||||
{% endif %}
|
||||
<a class="btn btn-outline-secondary" href="{% url 'edit' acro.slug %}">Edit</a>
|
||||
{% endblock %}
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
{% load static %}
|
||||
{% load bootstrap4 %}
|
||||
|
||||
{% block heading %}
|
||||
<h1>Edit "{{ form.name.value }}"</h1>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form method="post">
|
||||
|
@ -15,7 +20,6 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<script src="{% static "lib/codemirror.js" %}"></script>
|
||||
<link rel="stylesheet" href="{% static "lib/codemirror.css" %}">
|
||||
<script src="{% static "mode/markdown/markdown.js" %}"></script>
|
||||
<script src="{% static "libs/codemirror.js" %}"></script>
|
||||
<script src="{% static "libs/markdown.js" %}"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,13 +1,25 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<dl>
|
||||
|
||||
{% for acro in acros %}
|
||||
<dt><a href="{% url "detail" acro.slug %}">{{ acro.name }}</a></dt>
|
||||
<dd>{{ acro.full_name }}</dd>
|
||||
|
||||
|
||||
{% endfor %}
|
||||
</dl>
|
||||
{% block heading %}
|
||||
<h1>All Acronyms</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% regroup acros by first_letter as letter_acros %}
|
||||
|
||||
<div class="quicklinks">
|
||||
{% for letter in letter_acros %}
|
||||
<a href="#{{ letter.grouper }}">{{ letter.grouper }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% for letter in letter_acros %}
|
||||
<h3 id="{{ letter.grouper }}">{{ letter.grouper }}</h3>
|
||||
<dl>
|
||||
{% for acro in letter.list %}
|
||||
<dt><a href="{% url "detail" acro.slug %}">{{ acro.name }}</a></dt>
|
||||
<dd>{{ acro.full_name }}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<dl>
|
||||
{% for acro in acros %}
|
||||
<dt><a href="{% url "detail" acro.slug %}">{{ acro.name }}</a></dt>
|
||||
<dd>{{ acro.full_name }}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
|
||||
{% block heading %}
|
||||
<h1>Acronyms tagged "{{ request.resolver_match.kwargs.slug }}"</h1>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<dl>
|
||||
{% for acro in acros %}
|
||||
<dt><a href="{% url "detail" acro.slug %}">{{ acro.name }}</a></dt>
|
||||
<dd>{{ acro.full_name }}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,24 +1,32 @@
|
|||
from django.conf.urls.static import static
|
||||
from django.contrib.sitemaps.views import sitemap
|
||||
from django.urls import path, include
|
||||
from django.views.decorators.cache import cache_page
|
||||
from django.views.generic import RedirectView
|
||||
from rest_framework import routers
|
||||
|
||||
from acronomy import settings
|
||||
from . import views
|
||||
from .sitemaps import AcronymSitemap
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
router.register(r'acronym', views.AcronymViewSet)
|
||||
router.register(r'tag', views.TagViewSet)
|
||||
|
||||
sitemaps = {
|
||||
"acronyms": AcronymSitemap
|
||||
}
|
||||
|
||||
urlpatterns = [
|
||||
path('', include('django.contrib.auth.urls')),
|
||||
path("sitemap.xml", cache_page(60 * 15)(sitemap), {"sitemaps": sitemaps}, name="sitemap"),
|
||||
path('api/', include(router.urls)),
|
||||
path('', views.IndexView.as_view(), name='index'),
|
||||
path('acro', RedirectView.as_view(pattern_name="overview")),
|
||||
path('acro/add', views.AddView.as_view(), name="add"),
|
||||
path('acro/<str:slug>', views.DetailView.as_view(), name='detail'),
|
||||
path('acro/<str:slug>/edit', views.EditView.as_view(), name='edit'),
|
||||
path('acros', views.OverView.as_view(), name='overview'),
|
||||
path('acronym', RedirectView.as_view(pattern_name="overview")),
|
||||
path('acronym/add', views.AddView.as_view(), name="add"),
|
||||
path('acronym/<str:slug>', views.DetailView.as_view(), name='detail'),
|
||||
path('acronym/<str:slug>/edit', views.EditView.as_view(), name='edit'),
|
||||
path('acronyms', views.OverView.as_view(), name='overview'),
|
||||
path('tags', views.TagListView.as_view(), name='tags'),
|
||||
path('tag', RedirectView.as_view(pattern_name="tags")),
|
||||
path('tag/<str:slug>', views.TagAcroView.as_view(), name='tag'),
|
||||
|
|
|
@ -31,11 +31,12 @@ new Autocomplete('#autocomplete', {
|
|||
// a new window
|
||||
onSubmit: result => {
|
||||
console.log(result)
|
||||
window.location = "/acro/" + result.slug
|
||||
window.location = "/acronym/" + result.slug
|
||||
},
|
||||
autoSelect: true,
|
||||
})
|
||||
const input = document.querySelector('input[name="tags"]')
|
||||
input.classList.remove("form-control")
|
||||
|
||||
document.querySelector("form").addEventListener("submit", function () {
|
||||
const list = JSON.parse(input.value).map(function (item) {
|
||||
|
@ -75,4 +76,3 @@ const myCodeMirror = CodeMirror.fromTextArea(
|
|||
lineNumbers: true,
|
||||
}
|
||||
);
|
||||
|
||||
|
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
1
static/libs/codemirror.js
Symbolic link
1
static/libs/codemirror.js
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../node_modules/codemirror/lib/codemirror.js
|
1
static/libs/markdown.js
Symbolic link
1
static/libs/markdown.js
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../node_modules/codemirror/mode/markdown/markdown.js
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
@import "node_modules/@trevoreyre/autocomplete-js/dist/style";
|
||||
@import "node_modules/@yaireo/tagify/dist/tagify";
|
||||
@import "node_modules/codemirror/lib/codemirror";
|
||||
|
||||
@import "node_modules/bootstrap/scss/functions";
|
||||
@import "node_modules/bootstrap/scss/variables";
|
||||
|
|
|
@ -21,7 +21,13 @@
|
|||
<div class="accountStatus">
|
||||
Hello {{ user.get_username }}, <a href="{% url 'logout' %}">Log out</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="accountStatus">
|
||||
<a href="{% url 'login' %}">Log in</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% block heading %}
|
||||
{% endblock %}
|
||||
<div id="autocomplete" class="autocomplete">
|
||||
<input class="autocomplete-input" {% block searchInput %}{% endblock %}/>
|
||||
<ul class="autocomplete-result-list"></ul>
|
||||
|
|
Loading…
Reference in a new issue