Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/lore wiki page #675

Open
wants to merge 31 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
aa4ac4f
Created new model Lore
Gunvor4 Aug 18, 2023
17d65c5
Made form for lore articles
Gunvor4 Aug 18, 2023
612185f
Added urls, views and template for lore wiki
Gunvor4 Aug 18, 2023
1a3e879
Added styling to lore wiki
Gunvor4 Aug 18, 2023
99080f8
Updated translation files
Gunvor4 Aug 18, 2023
33d45af
Added internal joke
Gunvor4 Aug 24, 2023
64c9027
Added hamburger menu to be shown on smaller screens
Gunvor4 Sep 7, 2023
dea71b2
Updated translation files
Gunvor4 Sep 7, 2023
d5ee29d
Updated changelog
Gunvor4 Sep 7, 2023
c0f69d7
Adjusted burger menu
Gunvor4 Sep 8, 2023
9f2d6e5
Adjusted media rules
Gunvor4 Sep 8, 2023
49257d6
Changed permissions
Gunvor4 Sep 8, 2023
d43b644
Changed how pencil and trash icon are shown on devices with smaller s…
Gunvor4 Sep 14, 2023
31443bf
Made CSS changes to lore page
Gunvor4 Nov 2, 2023
da6d810
Commented on checkbox
Gunvor4 Nov 2, 2023
ff5aefb
Set max length on main text field for lore article
Gunvor4 Nov 2, 2023
a99bb65
Added error to deal with titles consisting of symbols
Gunvor4 Nov 2, 2023
d8192ac
Changed the placement of the checkbox in the lore article update form
Gunvor4 Nov 2, 2023
ba0a763
Updated translation files
Gunvor4 Nov 2, 2023
6f6f595
Improved slugification of titles
Gunvor4 Nov 2, 2023
f38a527
Fixed alphabetical order of imports
Gunvor4 Nov 18, 2023
3bf1b3a
Changed content field on model from TextField to RichTextUploadingField
Gunvor4 Nov 18, 2023
31d6537
Change name on template files and CSS file
Gunvor4 Nov 18, 2023
f1e3c35
Switched from validating form data in views to validating in forms
Gunvor4 Nov 18, 2023
b16dc06
Changed url names
Gunvor4 Nov 18, 2023
b89ea66
Changed migrations
Gunvor4 Nov 18, 2023
e2bfa3d
Switched from overriding get_context_data to using extra_context
Gunvor4 Nov 18, 2023
2f5da3d
Changed context object names
Gunvor4 Nov 19, 2023
60c48d5
Various small changes
Gunvor4 Nov 19, 2023
94e8144
Updated translation files
Gunvor4 Nov 19, 2023
4d9e2a4
Removed additional CSS code for update forms from style.css
Gunvor4 Nov 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ A summary of changes made to the codebase, grouped per deployment.

### New features

- Added a MAKE lore wiki where MAKE members can write and edit articles about anything lore in the MAKE universe
- The apply button in the English header, which previously read "søk verv", has now been translated to English ("apply to MAKE")

### Improvements
Expand Down
8 changes: 7 additions & 1 deletion src/internal/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from util import html_utils
from util.admin_utils import DefaultAdminWidgetsMixin, UserSearchFieldsMixin, search_escaped_and_unescaped
from .models import Member, Quote, Secret, SystemAccess
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
from .models import Lore, Member, Quote, Secret, SystemAccess


class MemberAdmin(DefaultAdminWidgetsMixin, SimpleHistoryAdmin):
Expand Down Expand Up @@ -93,7 +93,13 @@ class QuoteAdmin(DefaultAdminWidgetsMixin, UserSearchFieldsMixin, admin.ModelAdm
autocomplete_fields = ('author',)


class LoreAdmin(admin.ModelAdmin):
ordering = ('title',)
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
exclude = ('slug',)


admin.site.register(Member, MemberAdmin)
admin.site.register(SystemAccess, SystemAccessAdmin)
admin.site.register(Secret, SecretAdmin)
admin.site.register(Quote, QuoteAdmin)
admin.site.register(Lore, LoreAdmin)
36 changes: 35 additions & 1 deletion src/internal/forms.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from django import forms
from django.db import models
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _

from card import utils as card_utils
from card.formfields import CardNumberField
from ckeditor.widgets import CKEditorWidget
from users.models import User
from web.widgets import SemanticDateInput, SemanticMultipleSelectInput, SemanticSearchableChoiceInput
from .models import Member, Quote, Secret, SystemAccess
from .models import Lore, Member, Quote, Secret, SystemAccess


class AddMemberForm(forms.ModelForm):
Expand Down Expand Up @@ -176,3 +178,35 @@
widgets = {
'date': SemanticDateInput(),
}


class LoreForm(forms.ModelForm):
class Meta:
model = Lore
fields = ('title', 'content')
widgets = {
'text': CKEditorWidget()
}
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved

def clean(self):
cleaned_data = self.cleaned_data
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
title = cleaned_data.get('title')
title = title.replace('ø', 'o')
title = title.replace('æ', 'ae')
slug = slugify(title)
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
try:
article = self.instance
except NameError:
article = None
if article:
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
if (article.slug != slug) and (Lore.objects.filter(slug=slug).exists()):
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
self.add_error('title', _("An article with this title already exists. Please merge your text with the existing one!"))
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
elif slug == '':
self.add_error('title', _("Please make a title consisting of actual letters!"))
Comment on lines +204 to +205
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add a comment here explaining why having an empty slug means that the title doesn't consist of actual letters, as it's easy to be (initially) confused and think that the code author mistakenly added an error for title when a different field is checked 😅

elif not article:
if Lore.objects.filter(slug=slug).exists():
self.add_error('title', _("An article with this title already exists. Please merge your text with the existing one!"))
elif slug == '':
self.add_error('title', _("Please make a title consisting of actual letters!"))

Check warning on line 210 in src/internal/forms.py

View check run for this annotation

Codecov / codecov/patch

src/internal/forms.py#L192-L210

Added lines #L192 - L210 were not covered by tests
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
else:
return cleaned_data

Check warning on line 212 in src/internal/forms.py

View check run for this annotation

Codecov / codecov/patch

src/internal/forms.py#L212

Added line #L212 was not covered by tests
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
27 changes: 27 additions & 0 deletions src/internal/migrations/0027_lore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 4.1.7 on 2023-11-17 16:00

import ckeditor_uploader.fields
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('internal', '0026_add_secret_permissions'),
]

operations = [
migrations.CreateModel(
name='Lore',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=200, unique=True, verbose_name='title')),
('slug', models.SlugField(unique=True)),
('content', ckeditor_uploader.fields.RichTextUploadingField(max_length=150000, verbose_name='text')),
],
options={
'verbose_name': 'lore article',
'verbose_name_plural': 'lore articles',
},
),
]
23 changes: 22 additions & 1 deletion src/internal/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django.db.models import F
from django.db.models.functions import Lower
from django.utils import timezone
from django.utils.text import capfirst
from django.utils.text import capfirst, slugify
from django.utils.translation import gettext_lazy as _
from phonenumber_field.modelfields import PhoneNumberField
from phonenumber_field.phonenumber import PhoneNumber
Expand Down Expand Up @@ -314,3 +314,24 @@

def __str__(self):
return _("“{quote}” —{quoted}").format(quote=self.quote, quoted=self.quoted)


class Lore(models.Model):
title = models.CharField(max_length=200, unique=True, verbose_name=_("title"))
slug = models.SlugField(unique=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SlugField uses a default max_length of 50 if not specified (see the docs on SlugField), and so we should either expand slug's max_length to the same value, or "cut off" all characters beyond 50 in the form.

Also, verbose_name should always be added - even if there are no good Norwegian translations (just having "slug" as the translation would be fine, I guess) - to have consistency between all model fields.

Suggested change
slug = models.SlugField(unique=True)
slug = models.SlugField(max_length=title.max_length, unique=True, verbose_name=_("slug"))

content = RichTextUploadingField(max_length=150000, verbose_name=_("text"))
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved

def __str__(self):
return self.title

Check warning on line 325 in src/internal/models.py

View check run for this annotation

Codecov / codecov/patch

src/internal/models.py#L325

Added line #L325 was not covered by tests

def save(self, *args, **kwargs):
title = self.title
self.title = capfirst(title)
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
title = title.replace('ø', 'o')
title = title.replace('æ', 'ae')
self.slug = slugify(title)
super().save(*args, **kwargs)

Check warning on line 333 in src/internal/models.py

View check run for this annotation

Codecov / codecov/patch

src/internal/models.py#L328-L333

Added lines #L328 - L333 were not covered by tests
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved

class Meta:
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
verbose_name = _("lore article")
verbose_name_plural = _("lore articles")
159 changes: 159 additions & 0 deletions src/internal/static/internal/css/lore_list.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#lore-page {
position: relative;
max-width: 100vw;
}

#lore-wiki-list {
float: left;
width: 20%;
padding: 3rem 0 40px 40px;
position: relative;
}

.lore-article-links a {
color: black;
}

ul.lore-article-links {
list-style-type: none;
list-style-position: inside;
padding: 0;
}

.lore-article-links .selected-lore-article {
font-weight: bold;
}

#lore-article {
float: left;
width: 80%;
padding: 3rem 25% 0 5%;
position: relative;
}

#lore-article p {
text-align: justify;
}

.lore-container img {
margin: 20px 30px;
}

#lore-article .lore-container {
margin-bottom: 70px;
}

#lore-wiki-list .plus.icon {
font-size: 90%;
}

#lore-burger-icon + h2 .plus.icon {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would make the CSS code more robust if you replaced #lore-burger-icon + h2 with a new class (or ID) placed on the h2 element. This is both because it's somewhat common to tweak exactly which heading level the heading has (e.g. replacing h2 with h1 or h3), and because it's also common to slightly change the order of HTML elements - which would make it necessary to update the + part of the selector.

The same goes for some similar selectors below.

font-size: 80%;
}

#lore-article .trash.icon,
#lore-article .pencil.icon {
font-size: 120%;
}

#lore-article .lore-heading {
display: block;
max-width: 100vw;
}

/* The burger menu used on the lore page is loosely based on https://alvarotrigo.com/blog/hamburger-menu-css-responsive/ */

#burger-input {
display: none;
}

#lore-burger-icon {
display: none;
width: 15px;
height: 15px;
cursor: pointer;
border: none;
margin-top:6px;
background: linear-gradient(
to bottom,
black, black 20%,
white 20%, white 40%,
black 40%, black 60%,
white 60%, white 80%,
black 80%, black 100%
);
position: absolute;
top: 3rem;
left: 15%;
}

#lore-burger-icon + h2 {
position: absolute;
top: 3rem;
left: 15%;
margin: 0 0 0 30px;
display: none;
}

#lore-burger-menu {
display: none;
max-width: 100vw;
padding: 6rem 15% 0 15%;
}

@media screen and (max-width: 992px) {

#lore-burger-icon {
display: inline;
}

#lore-burger-icon + h2 {
display: block;
}

#burger-input:not(:checked) ~ #lore-article {
position: absolute;
top: 6rem;
}

#burger-input:checked + #lore-burger-icon {
clip-path: polygon(15% 0%, 0% 15%, 35% 50%, 0% 85%, 15% 100%, 50% 65%, 85% 100%, 100% 85%, 65% 50%, 100% 15%, 85% 0%, 50% 35%);
background: black;
}

#burger-input:checked + #lore-burger-icon ~ #lore-burger-menu {
Comment on lines +114 to +124
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great if you could add a comment (both here and an extra one in the template) explaining that the exact order and "siblinghood" (i.e. that if e.g. an element was added between #burger-input and #lore-burger-icon, the code would no longer work) of the burger elements are important for this CSS code to work - especially considering that the + and ~ selectors are fairly uncommon to use, at least in my experience.

display: block;
top: 6rem;
}

#lore-wiki-list {
display: none;
float: none;
max-width: 100vw;
padding: 2rem 15% 0 15%;
}

#lore-article {
float: none;
width: 100vw;
padding: 3rem 15% 2rem 15%;
position: relative;
}
}

@media screen and (max-width: 450px) {

#lore-article {
float: none;
width: 100%;
padding: 3rem 15% 2rem 15%;
position: relative;
}

.lore-container img {
float: none;
width: 100%;
height: unset;
margin: 10px 0;
}
}
10 changes: 10 additions & 0 deletions src/internal/static/internal/js/lore_list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
$(document).ready(function() {
$('img').each(function() {
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
if ($(this).css('float') === 'left') {
$(this).css('margin-left', '0');
}
if ($(this).css('float') === 'right') {
Comment on lines +3 to +6
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add a comment explaining that this code relies on the fact that CKEditor sets this CSS for images that are aligned left or right 🙂 Also - perhaps above that - you should explain why this code is here in the first place, i.e. a quick summary of what it's trying to do and potentially why.

$(this).css('margin-right', '0');
}
});
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
});
4 changes: 4 additions & 0 deletions src/internal/templates/internal/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
<div class="text">{% translate "Quotes" %}</div>
<div class="make-bg-blue bubble-background"></div>
</a>
<a class="item" href="{% url 'lore_list' %}">
<div class="text">{% translate "MAKE Lore" %}</div>
<div class="make-bg-turquoise bubble-background"></div>
</a>

<div class="nav-dropdown ui dropdown item">
<div class="text">{% translate "Misc." %}</div>
Expand Down
66 changes: 66 additions & 0 deletions src/internal/templates/internal/lore/lore_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{% extends 'internal/base.html' %}
{% load i18n %}
{% load static %}


{% block title %}
{% translate "The wiki of MAKE lore" %}
{% endblock title %}

{% block extra_head %}
<link rel="stylesheet" href="{% static 'internal/css/lore_list.css' %}"/>
<script src="{% static 'internal/js/lore_list.js' %}"></script>
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
{% endblock extra_head %}

{% block body %}
<div id="lore-page">
<div id="lore-wiki-list" class="word-breaking hyphenated">
<h2>{% translate "Topics" %}
{% if perms.internal.add_lore %}
<a href="{% url 'lore_create' %}">
<i class="green plus icon"></i>
</a>
{% endif %}
</h2>
{% include 'internal/lore/lore_list__article_links.html' %}
</div>

{# Checkbox belongs to hamburger menu. Checkbox status decides if hamburger menu will be shown or not #}
<input type="checkbox" id="burger-input"/>
<label id="lore-burger-icon" for="burger-input"></label>
<h2>{% translate "Topics" %}
{% if perms.internal.add_lore %}
<a href="{% url 'lore_create' %}">
<i class="green plus icon"></i>
</a>
{% endif %}
</h2>
<div id="lore-burger-menu" class="word-breaking hyphenated">
{% include 'internal/lore/lore_list__article_links.html' %}
</div>

<div id="lore-article">
{% if show_article %}
<h1 class="lore-heading word-breaking hyphenated">{{ shown_lore_article.title|capfirst }}</h1>
{% if perms.internal.delete_lore and shown_lore_article.title != "Dev" %}
<a class="delete-modal-button"
data-url="{% url 'lore_delete' shown_lore_article.slug %}"
data-obj-name="{{ shown_lore_article }}">
<i class="red trash icon"></i>
</a>
{% endif %}
{% if perms.internal.change_lore and shown_lore_article.title != "Dev" %}
Gunvor4 marked this conversation as resolved.
Show resolved Hide resolved
<a href="{% url 'lore_update' shown_lore_article.slug %}">
<i class="make-col-yellow pencil icon"></i>
</a>
{% endif %}
<div class="lore-container word-breaking hyphenated">
<p>{{ shown_lore_article.content|safe }}</p>
</div>
{% else %}
<h1>{% translate "Welcome to the wiki of MAKE lore" %}</h1>
<p>{% translate "Click a topic in the menu to access a wiki article" %}</p>
{% endif %}
</div>
</div>
{% endblock body %}
Loading