mirror of
https://github.com/Findus23/RPGnotes.git
synced 2024-09-19 15:43:45 +02:00
lots of changes
This commit is contained in:
parent
71b0d1cac8
commit
3c884d4e1d
37 changed files with 777 additions and 58 deletions
|
@ -1,10 +1,13 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
from notes.models import Character, Campaign, Faction, Location, Loot
|
||||
from simple_history.admin import SimpleHistoryAdmin
|
||||
|
||||
admin.site.register(Campaign)
|
||||
admin.site.register(Character)
|
||||
admin.site.register(Faction)
|
||||
admin.site.register(Location)
|
||||
admin.site.register(Loot)
|
||||
from notes.models import Character, Campaign, Faction, Location, Loot, IngameDay, Session
|
||||
|
||||
admin.site.register(Campaign, SimpleHistoryAdmin)
|
||||
admin.site.register(Character, SimpleHistoryAdmin)
|
||||
admin.site.register(Faction, SimpleHistoryAdmin)
|
||||
admin.site.register(Location, SimpleHistoryAdmin)
|
||||
admin.site.register(Loot, SimpleHistoryAdmin)
|
||||
admin.site.register(IngameDay, SimpleHistoryAdmin)
|
||||
admin.site.register(Session, SimpleHistoryAdmin)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.forms import ModelForm
|
||||
from django.forms import ModelForm, ModelMultipleChoiceField, CheckboxSelectMultiple
|
||||
|
||||
from notes.models import Campaign, Loot, Character
|
||||
from notes.models import Campaign, Loot, Character, IngameDay, Session
|
||||
|
||||
|
||||
class CampaignForm(ModelForm):
|
||||
|
@ -19,3 +19,14 @@ class CharacterForm(ModelForm):
|
|||
class Meta:
|
||||
model = Character
|
||||
fields = ["name", "description_md", "subtitle", "player", "faction", "location", "color", "image"]
|
||||
|
||||
|
||||
class DayForm(ModelForm):
|
||||
sessions = ModelMultipleChoiceField(
|
||||
queryset=Session.objects.all(),
|
||||
widget=CheckboxSelectMultiple()
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = IngameDay
|
||||
fields = ["day", "description_md", "sessions"]
|
||||
|
|
95
notes/migrations/0011_auto_20210822_1828.py
Normal file
95
notes/migrations/0011_auto_20210822_1828.py
Normal file
|
@ -0,0 +1,95 @@
|
|||
# Generated by Django 3.2.6 on 2021-08-22 18:28
|
||||
|
||||
import datetime
|
||||
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),
|
||||
('notes', '0010_alter_character_image'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='IngameDay',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('day', models.PositiveIntegerField()),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('last_modified', models.DateTimeField(auto_now=True)),
|
||||
('campaign', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='notes.campaign')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['-day'],
|
||||
},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='loot',
|
||||
options={'ordering': ['name']},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Session',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('description_md', models.TextField(blank=True)),
|
||||
('description_html', models.TextField(blank=True, editable=False)),
|
||||
('day', models.DateField(default=datetime.date.today)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('last_modified', models.DateTimeField(auto_now=True)),
|
||||
('campaign', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='notes.campaign')),
|
||||
('ingame_days', models.ManyToManyField(related_name='sessions', to='notes.IngameDay')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['-day'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='HistoricalSession',
|
||||
fields=[
|
||||
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
|
||||
('description_md', models.TextField(blank=True)),
|
||||
('description_html', models.TextField(blank=True, editable=False)),
|
||||
('day', models.DateField(default=datetime.date.today)),
|
||||
('created', models.DateTimeField(blank=True, editable=False)),
|
||||
('last_modified', models.DateTimeField(blank=True, editable=False)),
|
||||
('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)),
|
||||
('campaign', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='notes.campaign')),
|
||||
('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 session',
|
||||
'ordering': ('-history_date', '-history_id'),
|
||||
'get_latest_by': 'history_date',
|
||||
},
|
||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='HistoricalIngameDay',
|
||||
fields=[
|
||||
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
|
||||
('day', models.PositiveIntegerField()),
|
||||
('created', models.DateTimeField(blank=True, editable=False)),
|
||||
('last_modified', models.DateTimeField(blank=True, editable=False)),
|
||||
('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)),
|
||||
('campaign', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='notes.campaign')),
|
||||
('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 ingame day',
|
||||
'ordering': ('-history_date', '-history_id'),
|
||||
'get_latest_by': 'history_date',
|
||||
},
|
||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
||||
),
|
||||
]
|
30
notes/migrations/0012_auto_20210823_1333.py
Normal file
30
notes/migrations/0012_auto_20210823_1333.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Generated by Django 3.2.6 on 2021-08-23 11:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('notes', '0011_auto_20210822_1828'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='ingameday',
|
||||
name='sessions',
|
||||
field=models.ManyToManyField(related_name='ingame_days', to='notes.Session'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='ingameday',
|
||||
unique_together={('campaign', 'day')},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='session',
|
||||
unique_together={('campaign', 'day')},
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='session',
|
||||
name='ingame_days',
|
||||
),
|
||||
]
|
49
notes/migrations/0013_auto_20210823_1405.py
Normal file
49
notes/migrations/0013_auto_20210823_1405.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
# Generated by Django 3.2.6 on 2021-08-23 12:05
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('notes', '0012_auto_20210823_1333'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='historicalsession',
|
||||
name='description_html',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalsession',
|
||||
name='description_md',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='session',
|
||||
name='description_html',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='session',
|
||||
name='description_md',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalingameday',
|
||||
name='description_html',
|
||||
field=models.TextField(blank=True, editable=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalingameday',
|
||||
name='description_md',
|
||||
field=models.TextField(blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ingameday',
|
||||
name='description_html',
|
||||
field=models.TextField(blank=True, editable=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ingameday',
|
||||
name='description_md',
|
||||
field=models.TextField(blank=True),
|
||||
),
|
||||
]
|
|
@ -5,3 +5,5 @@ from .faction import Faction
|
|||
from .location import Location
|
||||
from .character import Character
|
||||
from .loot import Loot
|
||||
from .session import Session
|
||||
from .ingameday import IngameDay
|
||||
|
|
31
notes/models/ingameday.py
Normal file
31
notes/models/ingameday.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
from django.contrib.humanize.templatetags.humanize import ordinal
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from simple_history.models import HistoricalRecords
|
||||
|
||||
from notes.models import Campaign, Session, DescriptionModel
|
||||
|
||||
|
||||
class IngameDay(DescriptionModel):
|
||||
campaign = models.ForeignKey(Campaign, on_delete=models.PROTECT)
|
||||
|
||||
day = models.PositiveIntegerField()
|
||||
sessions = models.ManyToManyField(Session, related_name="ingame_days")
|
||||
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
last_modified = models.DateTimeField(auto_now=True)
|
||||
history = HistoricalRecords()
|
||||
|
||||
class Meta:
|
||||
ordering = ["-day"]
|
||||
unique_together = ["campaign", "day"]
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('daydetail', args=[self.campaign.slug, self.day])
|
||||
|
||||
@property
|
||||
def prettyname(self):
|
||||
return ordinal(self.day) + " day"
|
||||
|
||||
def __str__(self):
|
||||
return self.prettyname
|
|
@ -17,6 +17,9 @@ class Loot(DescriptionModel):
|
|||
last_modified = models.DateTimeField(auto_now=True)
|
||||
history = HistoricalRecords()
|
||||
|
||||
class Meta:
|
||||
ordering = ["name"]
|
||||
|
||||
@property
|
||||
def value_per_unit(self):
|
||||
return self.value_gold / self.quantity
|
||||
|
|
26
notes/models/session.py
Normal file
26
notes/models/session.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
from datetime import date
|
||||
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from simple_history.models import HistoricalRecords
|
||||
|
||||
from notes.models import Campaign
|
||||
|
||||
|
||||
class Session(models.Model):
|
||||
campaign = models.ForeignKey(Campaign, on_delete=models.PROTECT)
|
||||
|
||||
day = models.DateField(default=date.today)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
last_modified = models.DateTimeField(auto_now=True)
|
||||
history = HistoricalRecords()
|
||||
|
||||
class Meta:
|
||||
ordering = ["-day"]
|
||||
unique_together = ["campaign", "day"]
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('sessiondetail', args=[self.campaign.slug, self.id])
|
||||
|
||||
def __str__(self):
|
||||
return str(self.day)
|
|
@ -15,6 +15,9 @@
|
|||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url "characterlist" view.kwargs.campslug %}">Characters</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url "daylist" view.kwargs.campslug %}">Timeline</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url "lootlist" view.kwargs.campslug %}">Loot</a>
|
||||
</li>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{% load static %}
|
||||
|
||||
{% block heading %}
|
||||
<h1>Add new Loot</h1>
|
||||
<h1>Delete Object</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
{% extends "navbarbase.html" %}
|
||||
{% load thumbutils %}
|
||||
{% load thumbnail %}
|
||||
{% load humanize %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
|
@ -17,6 +20,19 @@
|
|||
</div>
|
||||
<div class="col-8">
|
||||
<div class="character-heading" style="border-bottom-color: #{{ character.color }}">
|
||||
{% if character.image %}
|
||||
{% thumbnail character.image "150x150" crop="center" as im %}
|
||||
<a href="{{ character.image.url }}" target="_blank">
|
||||
<img class="avatar avatar-image avatar-large rounded-circle" src="{{ im.url }}" width="{{ im.width }}"
|
||||
height="{{ im.height }}"
|
||||
srcset="{{ im.url|srcset }}">
|
||||
</a>
|
||||
{% endthumbnail %}
|
||||
{% else %}
|
||||
<div class="avatar avatar-text avatar-large"
|
||||
style="background: #{{ character.color }};color:{{ character.text_color }}">{{ character.initials }}</div>
|
||||
{% endif %}
|
||||
|
||||
<h1>
|
||||
{{ character.name }}
|
||||
<a href="{% url "characteredit" character.campaign.slug character.slug %}">
|
||||
|
@ -32,6 +48,10 @@
|
|||
{% endif %}
|
||||
</dl>
|
||||
{{ character.description_html|safe }}
|
||||
|
||||
<div>
|
||||
<small>Last updated: {{ character.last_modified|naturaltime }} by {{ character.history.first.history_user }} </small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
42
notes/templates/notes/day_detail.html
Normal file
42
notes/templates/notes/day_detail.html
Normal file
|
@ -0,0 +1,42 @@
|
|||
{% extends "navbarbase.html" %}
|
||||
{% load thumbutils %}
|
||||
{% load thumbnail %}
|
||||
{% load humanize %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<ul class="nav nav-pills flex-column">
|
||||
{% for d in days %}
|
||||
<li class="nav-item">
|
||||
<a href="{% url "daydetail" day.campaign.slug d.day %}"
|
||||
class="nav-link {% if d.id == day.id %}active{% endif %}">
|
||||
{{ d.prettyname }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<a class="btn btn-primary add-button" href="{% url "dayadd" day.campaign.slug %}">Add Day</a>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<div class="day-heading">
|
||||
<h1>
|
||||
{{ day.prettyname }}
|
||||
<a href="{% url "dayedit" day.campaign.slug day.day %}">
|
||||
edit
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
{{ day.description_html|safe }}
|
||||
<dl>
|
||||
<dt>Sessions:</dt>
|
||||
<dd>{{ day.sessions.all|join:", " }}</dd>
|
||||
</dl>
|
||||
|
||||
<div>
|
||||
<small>Last updated: {{ day.last_modified|naturaltime }}
|
||||
by {{ day.history.first.history_user }} </small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -5,6 +5,9 @@
|
|||
{% block heading %}
|
||||
{% if edit %}
|
||||
<h1>Edit "{{ object.name }}"</h1>
|
||||
{% if request.resolver_match.view_name %}
|
||||
<a class="btn btn-danger" href="{% url "lootdelete" object.campaign.slug object.id %}">Delete</a>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<h1>Add new</h1>
|
||||
{% endif %}
|
||||
|
@ -14,13 +17,15 @@
|
|||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<input type="submit" class="btn btn-primary" value="Update">
|
||||
{% bootstrap_form form %}
|
||||
<input type="submit" class="btn btn-primary" value="Update">
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{#{% block extra_head %}#}
|
||||
{# <script src="{% static "libs/codemirror.js" %}"></script>#}
|
||||
{# <script src="{% static "libs/markdown.js" %}"></script>#}
|
||||
{# <script src="{% static "libs/tagify.min.js" %}"></script>#}
|
||||
{#{% endblock %}#}
|
||||
{% block extra_js %}
|
||||
<script src="{% static "libs/easymde.min.js" %}"></script>
|
||||
<script src="{% static "libs/fontawesome-solid.min.js" %}"></script>
|
||||
<script src="{% static "libs/fontawesome.min.js" %}"></script>
|
||||
<script src="{% static "js/markdown.js" %}"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{% extends "navbarbase.html" %}
|
||||
{% load formatters %}
|
||||
|
||||
{% block heading %}
|
||||
<h1>Loot</h1>
|
||||
|
@ -22,7 +23,7 @@
|
|||
aria-controls="row-{{ l.id }}">
|
||||
<td>{{ l.name }}</td>
|
||||
<td>{{ l.quantity }}</td>
|
||||
<td>{{ l.value_gold }}</td>
|
||||
<td>{{ l.value_gold|format_money_html }}</td>
|
||||
<td>{{ l.owner.first_name }}</td>
|
||||
<td>
|
||||
<svg class="chev" viewBox="0 0 640 1024" xmlns="http://www.w3.org/2000/svg">
|
||||
|
@ -35,14 +36,17 @@
|
|||
<div class="collapse" id="row-{{ l.id }}">
|
||||
<h3>{{ l.name }} <a href="{% url "lootedit" l.campaign.slug l.id %}">edit</a></h3>
|
||||
{{ l.description_html|safe }}
|
||||
<p>Value each: {{ l.value_per_unit|floatformat:-2 }} Gold</p>
|
||||
<p>Value each: {{ l.value_per_unit|format_money_html }}</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<dl>
|
||||
<dd>Total value:</dd>
|
||||
<dt>{{ total_value|format_money_html }}</dt>
|
||||
</dl>
|
||||
<a href="{% url "lootadd" loot.0.campaign.slug %}" class="btn btn-primary">Add Loot</a>
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
<div class="image-col">
|
||||
{% if character.image %}
|
||||
{% thumbnail character.image "48x48" crop="center" as im %}
|
||||
<img class="rounded-circle" src="{{ im.url }}" width="{{ im.width }}"
|
||||
<img class="avatar avatar-image rounded-circle" src="{{ im.url }}" width="{{ im.width }}"
|
||||
height="{{ im.height }}"
|
||||
srcset="{{ im.url|srcset }}">
|
||||
{% endthumbnail %}
|
||||
{% else %}
|
||||
<div class="avatar"
|
||||
<div class="avatar avatar-text"
|
||||
style="background: #{{ character.color }};color:{{ character.text_color }}">{{ character.initials }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
|
16
notes/templatetags/formatters.py
Normal file
16
notes/templatetags/formatters.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
from django import template
|
||||
from django.template.defaultfilters import safe
|
||||
|
||||
from notes.utils.money import format_money as money_formatter
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter()
|
||||
def format_money(money):
|
||||
return money_formatter(money)
|
||||
|
||||
|
||||
@register.filter()
|
||||
def format_money_html(money):
|
||||
return safe(money_formatter(money, html=True))
|
|
@ -5,16 +5,21 @@ from notes import views
|
|||
urlpatterns = [
|
||||
path("", views.CampaignListView.as_view(), name="campaignlist"),
|
||||
path("c/add", views.CampaignCreateView.as_view(), name="campaigncreate"),
|
||||
path("c/<str:campslug>", views.CampaignDetailView.as_view(), name="campaigndetail"),
|
||||
path("c/<str:campslug>/edit", views.CampaignEditView.as_view(), name="campaignedit"),
|
||||
path("c/<str:campslug>/delete", views.CampaignDeleteView.as_view(), name="campaigndelete"),
|
||||
path("c/<str:campslug>/loot", views.LootListView.as_view(), name="lootlist"),
|
||||
path("c/<str:campslug>/loot/<int:pk>/edit", views.LootEditView.as_view(), name="lootedit"),
|
||||
path("c/<str:campslug>/loot/<int:pk>/delete", views.LootDeleteView.as_view(), name="lootdelete"),
|
||||
path("c/<str:campslug>/loot/add", views.LootCreateView.as_view(), name="lootadd"),
|
||||
path("c/<str:campslug>/character/", views.list_character_redirect, name="characterlist"),
|
||||
path("c/<str:campslug>/character/add", views.CharacterCreateView.as_view(), name="characteradd"),
|
||||
path("c/<str:campslug>/character/<str:charslug>", views.CharacterDetailView.as_view(), name="characterdetail"),
|
||||
path("c/<str:campslug>/character/<str:charslug>/edit", views.CharacterEditView.as_view(), name="characteredit"),
|
||||
path("c/<str:campslug>/character/<str:charslug>/delete", views.CharacterDeleteView.as_view(), name="characterdelete"),
|
||||
path("c/<slug:campslug>", views.CampaignDetailView.as_view(), name="campaigndetail"),
|
||||
path("c/<slug:campslug>/edit", views.CampaignEditView.as_view(), name="campaignedit"),
|
||||
path("c/<slug:campslug>/delete", views.CampaignDeleteView.as_view(), name="campaigndelete"),
|
||||
path("c/<slug:campslug>/loot", views.LootListView.as_view(), name="lootlist"),
|
||||
path("c/<slug:campslug>/loot/<int:pk>/edit", views.LootEditView.as_view(), name="lootedit"),
|
||||
path("c/<slug:campslug>/loot/<int:pk>/delete", views.LootDeleteView.as_view(), name="lootdelete"),
|
||||
path("c/<slug:campslug>/loot/add", views.LootCreateView.as_view(), name="lootadd"),
|
||||
path("c/<slug:campslug>/character/", views.list_character_redirect, name="characterlist"),
|
||||
path("c/<slug:campslug>/character/add", views.CharacterCreateView.as_view(), name="characteradd"),
|
||||
path("c/<slug:campslug>/character/<slug:charslug>", views.CharacterDetailView.as_view(), name="characterdetail"),
|
||||
path("c/<slug:campslug>/character/<slug:charslug>/edit", views.CharacterEditView.as_view(), name="characteredit"),
|
||||
path("c/<slug:campslug>/character/<slug:charslug>/delete", views.CharacterDeleteView.as_view(), name="characterdelete"),
|
||||
path("c/<slug:campslug>/day/", views.list_day_redirect, name="daylist"),
|
||||
path("c/<slug:campslug>/day/add", views.DayCreateView.as_view(), name="dayadd"),
|
||||
path("c/<slug:campslug>/day/<int:day>", views.DayDetailView.as_view(), name="daydetail"),
|
||||
path("c/<slug:campslug>/day/<int:day>/edit", views.DayEditView.as_view(), name="dayedit"),
|
||||
path("c/<slug:campslug>/day/<int:day>/delete", views.DayDeleteView.as_view(), name="daydelete"),
|
||||
]
|
||||
|
|
43
notes/utils/money.py
Normal file
43
notes/utils/money.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
from decimal import Decimal
|
||||
|
||||
gold = Decimal(1)
|
||||
silver = gold / 10
|
||||
copper = silver / 10
|
||||
platinum = gold * 10
|
||||
|
||||
currencies_text = ["CP", "SP", "GP", "PP"]
|
||||
currencies_HTML = [
|
||||
"<span class='cp'>CP</span>",
|
||||
"<span class='sp'>SP</span>",
|
||||
"<span class='gp'>GP</span>",
|
||||
"<span class='pp'>PP</span>"
|
||||
]
|
||||
|
||||
use_platinum=False
|
||||
|
||||
def digitize(n):
|
||||
print("n", n)
|
||||
digits = []
|
||||
i = 0
|
||||
if n == 0:
|
||||
return [0]
|
||||
while n:
|
||||
print(digits)
|
||||
i += 1
|
||||
if i > (3 if use_platinum else 2):
|
||||
digits.append(n)
|
||||
return digits
|
||||
n, d = divmod(n, 10)
|
||||
digits.append(d)
|
||||
return digits
|
||||
|
||||
|
||||
def format_money(money: Decimal, html=False) -> str:
|
||||
currencies = currencies_HTML if html else currencies_text
|
||||
output = []
|
||||
cp = round(money / copper, ndigits=0)
|
||||
|
||||
for i, value in enumerate(digitize(cp)):
|
||||
if value:
|
||||
output.append(str(value) + " " + currencies[i])
|
||||
return " ".join(reversed(output))
|
|
@ -1,4 +1,5 @@
|
|||
from .campaign_views import *
|
||||
from .loot_views import *
|
||||
from .character_views import *
|
||||
from .day_views import *
|
||||
from .debugviews import *
|
||||
|
|
|
@ -30,12 +30,16 @@ class CharacterDetailView(generic.DetailView):
|
|||
data["player_characters"] = Character.objects.filter(
|
||||
campaign__slug=self.kwargs['campslug'],
|
||||
player__isnull=False
|
||||
)
|
||||
data["npcs"] = Character.objects.filter(campaign__slug=self.kwargs['campslug'], player__isnull=True)
|
||||
).select_related()
|
||||
data["npcs"] = Character.objects.filter(
|
||||
campaign__slug=self.kwargs['campslug'], player__isnull=True
|
||||
).select_related()
|
||||
return data
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
return Character.objects.get(campaign__slug=self.kwargs['campslug'], slug=self.kwargs['charslug'])
|
||||
return Character.objects.get(
|
||||
campaign__slug=self.kwargs['campslug'], slug=self.kwargs['charslug']
|
||||
)
|
||||
|
||||
|
||||
class CharacterCreateView(generic.CreateView):
|
||||
|
|
58
notes/views/day_views.py
Normal file
58
notes/views/day_views.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
from django.shortcuts import redirect
|
||||
from django.urls import reverse_lazy
|
||||
from django.views import generic
|
||||
|
||||
from notes.forms import DayForm
|
||||
from notes.models import Session, Campaign, IngameDay
|
||||
|
||||
|
||||
def list_day_redirect(request, *args, **kwargs):
|
||||
latest_day: IngameDay = IngameDay.objects.first()
|
||||
return redirect(latest_day)
|
||||
|
||||
|
||||
class DayDetailView(generic.DetailView):
|
||||
template_name = "notes/day_detail.html"
|
||||
model = IngameDay
|
||||
context_object_name = "day"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
data = super().get_context_data(**kwargs)
|
||||
data["days"] = IngameDay.objects.filter(campaign__slug=self.kwargs['campslug'])
|
||||
return data
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
return IngameDay.objects.get(campaign__slug=self.kwargs['campslug'], day=self.kwargs['day'])
|
||||
|
||||
|
||||
class DayCreateView(generic.CreateView):
|
||||
template_name = "notes/loot_edit.html"
|
||||
model = IngameDay
|
||||
form_class = DayForm
|
||||
context_object_name = "object"
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.campaign = Campaign.objects.get(slug=self.kwargs['campslug'])
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class DayEditView(generic.UpdateView):
|
||||
template_name = "notes/loot_edit.html"
|
||||
model = IngameDay
|
||||
form_class = DayForm
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
data = super().get_context_data(**kwargs)
|
||||
data['edit'] = True
|
||||
return data
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
return IngameDay.objects.get(campaign__slug=self.kwargs['campslug'], day=self.kwargs['day'])
|
||||
|
||||
class DayDeleteView(generic.DeleteView):
|
||||
template_name = "notes/campaign_confirm_delete.html"
|
||||
model = IngameDay
|
||||
success_url = reverse_lazy('daylist')
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
return IngameDay.objects.get(campaign__slug=self.kwargs['campslug'], day=self.kwargs['day'])
|
|
@ -1,13 +1,14 @@
|
|||
from django.http import HttpResponse
|
||||
from django.views.decorators.cache import cache_page
|
||||
|
||||
from notes.utils.assets import get_css
|
||||
|
||||
|
||||
# @cache_page(60 * 15)
|
||||
def debug_css(request):
|
||||
css, source_map = get_css(debug=True)
|
||||
return HttpResponse(css, content_type="text/css")
|
||||
|
||||
|
||||
# @cache_page(60 * 15)
|
||||
def debug_css_sourcemap(request):
|
||||
css, source_map = get_css(debug=True)
|
||||
return HttpResponse(source_map, content_type="application/json")
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from django.db.models import Sum
|
||||
from django.urls import reverse_lazy, reverse
|
||||
from django.views import generic
|
||||
|
||||
|
@ -13,6 +14,12 @@ class LootListView(generic.ListView):
|
|||
def get_queryset(self):
|
||||
return Loot.objects.filter(campaign__slug=self.kwargs['campslug'])
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
data = super().get_context_data(**kwargs)
|
||||
data['total_value'] = self.get_queryset().aggregate(Sum("value_gold"))["value_gold__sum"]
|
||||
print(data['total_value'])
|
||||
return data
|
||||
|
||||
|
||||
class LootDetailView(generic.DetailView):
|
||||
template_name = "notes/loot_detail.html"
|
||||
|
@ -28,7 +35,8 @@ class LootCreateView(generic.CreateView):
|
|||
form.instance.campaign = Campaign.objects.get(slug=self.kwargs['campslug'])
|
||||
return super().form_valid(form)
|
||||
|
||||
success_url = reverse_lazy('lootlist')
|
||||
def get_success_url(self):
|
||||
return reverse("lootlist", kwargs={"campslug": self.kwargs.get("campslug")})
|
||||
|
||||
|
||||
class LootEditView(generic.UpdateView):
|
||||
|
@ -39,6 +47,7 @@ class LootEditView(generic.UpdateView):
|
|||
|
||||
def get_success_url(self):
|
||||
return reverse("lootlist", kwargs={"campslug": self.kwargs.get("campslug")})
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
data = super().get_context_data(**kwargs)
|
||||
data['edit'] = True
|
||||
|
@ -46,6 +55,7 @@ class LootEditView(generic.UpdateView):
|
|||
|
||||
|
||||
class LootDeleteView(generic.DeleteView):
|
||||
template_name = "notes/loot_confirm_delete.html"
|
||||
template_name = "notes/campaign_confirm_delete.html"
|
||||
model = Loot
|
||||
success_url = reverse_lazy('lootlist')
|
||||
def get_success_url(self):
|
||||
return reverse("lootlist", kwargs={"campslug": self.kwargs.get("campslug")})
|
||||
|
|
146
package-lock.json
generated
146
package-lock.json
generated
|
@ -5,7 +5,18 @@
|
|||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"bootstrap": "^5.1.0"
|
||||
"@fortawesome/fontawesome-free": "^5.15.4",
|
||||
"bootstrap": "^5.1.0",
|
||||
"easymde": "^2.15.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/fontawesome-free": {
|
||||
"version": "5.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz",
|
||||
"integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==",
|
||||
"hasInstallScript": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@popperjs/core": {
|
||||
|
@ -18,6 +29,32 @@
|
|||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/codemirror": {
|
||||
"version": "0.0.109",
|
||||
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.109.tgz",
|
||||
"integrity": "sha512-cSdiHeeLjvGn649lRTNeYrVCDOgDrtP+bDDSFDd1TF+i0jKGPDRozno2NOJ9lTniso+taiv4kiVS8dgM8Jm5lg==",
|
||||
"dependencies": {
|
||||
"@types/tern": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "0.0.50",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz",
|
||||
"integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw=="
|
||||
},
|
||||
"node_modules/@types/marked": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-2.0.4.tgz",
|
||||
"integrity": "sha512-L9VRSe0Id8xbPL99mUo/4aKgD7ZoRwFZqUQScNKHi2pFjF9ZYSMNShUHD6VlMT6J/prQq0T1mxuU25m3R7dFzg=="
|
||||
},
|
||||
"node_modules/@types/tern": {
|
||||
"version": "0.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz",
|
||||
"integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==",
|
||||
"dependencies": {
|
||||
"@types/estree": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/bootstrap": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.0.tgz",
|
||||
|
@ -29,20 +66,127 @@
|
|||
"peerDependencies": {
|
||||
"@popperjs/core": "^2.9.3"
|
||||
}
|
||||
},
|
||||
"node_modules/codemirror": {
|
||||
"version": "5.62.3",
|
||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.62.3.tgz",
|
||||
"integrity": "sha512-zZAyOfN8TU67ngqrxhOgtkSAGV9jSpN1snbl8elPtnh9Z5A11daR405+dhLzLnuXrwX0WCShWlybxPN3QC/9Pg=="
|
||||
},
|
||||
"node_modules/codemirror-spell-checker": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/codemirror-spell-checker/-/codemirror-spell-checker-1.1.2.tgz",
|
||||
"integrity": "sha1-HGYPkIlIPMtRE7m6nKGcP0mTNx4=",
|
||||
"dependencies": {
|
||||
"typo-js": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/easymde": {
|
||||
"version": "2.15.0",
|
||||
"resolved": "https://registry.npmjs.org/easymde/-/easymde-2.15.0.tgz",
|
||||
"integrity": "sha512-9jMRIVvKt1d0UjRN45yotUYECAM4xvw0TTAQw8sYDONP++keWJVnd8Xrn+V+vQEN/v9/X0SWEoo1rFSgCooGpw==",
|
||||
"dependencies": {
|
||||
"@types/codemirror": "0.0.109",
|
||||
"@types/marked": "^2.0.2",
|
||||
"codemirror": "^5.61.0",
|
||||
"codemirror-spell-checker": "1.1.2",
|
||||
"marked": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/marked": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz",
|
||||
"integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==",
|
||||
"bin": {
|
||||
"marked": "bin/marked"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/typo-js": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/typo-js/-/typo-js-1.2.0.tgz",
|
||||
"integrity": "sha512-dELuLBVa2jvWdU/CHTKi2L/POYaRupv942k+vRsFXsM17acXesQGAiGCio82RW7fvcr7bkuD/Zj8XpUh6aPC2A=="
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": {
|
||||
"version": "5.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz",
|
||||
"integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg=="
|
||||
},
|
||||
"@popperjs/core": {
|
||||
"version": "2.9.3",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.3.tgz",
|
||||
"integrity": "sha512-xDu17cEfh7Kid/d95kB6tZsLOmSWKCZKtprnhVepjsSaCij+lM3mItSJDuuHDMbCWTh8Ejmebwb+KONcCJ0eXQ==",
|
||||
"peer": true
|
||||
},
|
||||
"@types/codemirror": {
|
||||
"version": "0.0.109",
|
||||
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.109.tgz",
|
||||
"integrity": "sha512-cSdiHeeLjvGn649lRTNeYrVCDOgDrtP+bDDSFDd1TF+i0jKGPDRozno2NOJ9lTniso+taiv4kiVS8dgM8Jm5lg==",
|
||||
"requires": {
|
||||
"@types/tern": "*"
|
||||
}
|
||||
},
|
||||
"@types/estree": {
|
||||
"version": "0.0.50",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz",
|
||||
"integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw=="
|
||||
},
|
||||
"@types/marked": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-2.0.4.tgz",
|
||||
"integrity": "sha512-L9VRSe0Id8xbPL99mUo/4aKgD7ZoRwFZqUQScNKHi2pFjF9ZYSMNShUHD6VlMT6J/prQq0T1mxuU25m3R7dFzg=="
|
||||
},
|
||||
"@types/tern": {
|
||||
"version": "0.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz",
|
||||
"integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==",
|
||||
"requires": {
|
||||
"@types/estree": "*"
|
||||
}
|
||||
},
|
||||
"bootstrap": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.0.tgz",
|
||||
"integrity": "sha512-bs74WNI9BgBo3cEovmdMHikSKoXnDgA6VQjJ7TyTotU6L7d41ZyCEEelPwkYEzsG/Zjv3ie9IE3EMAje0W9Xew==",
|
||||
"requires": {}
|
||||
},
|
||||
"codemirror": {
|
||||
"version": "5.62.3",
|
||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.62.3.tgz",
|
||||
"integrity": "sha512-zZAyOfN8TU67ngqrxhOgtkSAGV9jSpN1snbl8elPtnh9Z5A11daR405+dhLzLnuXrwX0WCShWlybxPN3QC/9Pg=="
|
||||
},
|
||||
"codemirror-spell-checker": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/codemirror-spell-checker/-/codemirror-spell-checker-1.1.2.tgz",
|
||||
"integrity": "sha1-HGYPkIlIPMtRE7m6nKGcP0mTNx4=",
|
||||
"requires": {
|
||||
"typo-js": "*"
|
||||
}
|
||||
},
|
||||
"easymde": {
|
||||
"version": "2.15.0",
|
||||
"resolved": "https://registry.npmjs.org/easymde/-/easymde-2.15.0.tgz",
|
||||
"integrity": "sha512-9jMRIVvKt1d0UjRN45yotUYECAM4xvw0TTAQw8sYDONP++keWJVnd8Xrn+V+vQEN/v9/X0SWEoo1rFSgCooGpw==",
|
||||
"requires": {
|
||||
"@types/codemirror": "0.0.109",
|
||||
"@types/marked": "^2.0.2",
|
||||
"codemirror": "^5.61.0",
|
||||
"codemirror-spell-checker": "1.1.2",
|
||||
"marked": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"marked": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz",
|
||||
"integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA=="
|
||||
},
|
||||
"typo-js": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/typo-js/-/typo-js-1.2.0.tgz",
|
||||
"integrity": "sha512-dELuLBVa2jvWdU/CHTKi2L/POYaRupv942k+vRsFXsM17acXesQGAiGCio82RW7fvcr7bkuD/Zj8XpUh6aPC2A=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"bootstrap": "^5.1.0"
|
||||
"bootstrap": "^5.1.0",
|
||||
"easymde": "^2.15.0",
|
||||
"@fortawesome/fontawesome-free": "^5.15.4"
|
||||
}
|
||||
}
|
||||
|
|
18
poetry.lock
generated
18
poetry.lock
generated
|
@ -74,6 +74,18 @@ python-versions = ">=3.6"
|
|||
beautifulsoup4 = ">=4.8.0"
|
||||
Django = ">=2.2"
|
||||
|
||||
[[package]]
|
||||
name = "django-debug-toolbar"
|
||||
version = "3.2.2"
|
||||
description = "A configurable set of panels that display various debug information about the current request/response."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
Django = ">=2.2"
|
||||
sqlparse = ">=0.2.0"
|
||||
|
||||
[[package]]
|
||||
name = "django-simple-history"
|
||||
version = "3.0.0"
|
||||
|
@ -190,7 +202,7 @@ python-versions = "*"
|
|||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "245e8ddb9d285feb2d4ab950fa117b8422d0634fece9a59938b663cbeb4f45ae"
|
||||
content-hash = "de84127badac66220a787600d18455d7cf562aba0c81c05d7219f39f54a97cf9"
|
||||
|
||||
[metadata.files]
|
||||
asgiref = [
|
||||
|
@ -218,6 +230,10 @@ django-bootstrap5 = [
|
|||
{file = "django-bootstrap5-2.1.2.tar.gz", hash = "sha256:ac05ca69b990e62657c0bf40db14946c22fd64c7fb9dfe094a9f22ecc58f86c5"},
|
||||
{file = "django_bootstrap5-2.1.2-py3-none-any.whl", hash = "sha256:0021355df9212c511876e3f5336ba470416a6dd52f61bf5acec5bb783ab41ff5"},
|
||||
]
|
||||
django-debug-toolbar = [
|
||||
{file = "django-debug-toolbar-3.2.2.tar.gz", hash = "sha256:8c5b13795d4040008ee69ba82dcdd259c49db346cf7d0de6e561a49d191f0860"},
|
||||
{file = "django_debug_toolbar-3.2.2-py3-none-any.whl", hash = "sha256:d7bab7573fab35b0fd029163371b7182f5826c13da69734beb675c761d06a4d3"},
|
||||
]
|
||||
django-simple-history = [
|
||||
{file = "django-simple-history-3.0.0.tar.gz", hash = "sha256:66fe76c560054be393c52b1799661e104fbe372918d37d151e5d41c676158118"},
|
||||
{file = "django_simple_history-3.0.0-py2.py3-none-any.whl", hash = "sha256:a312adfe8fbec4c450b08e641b11249a8a589a7e7d1ba2404764b8b5bed53552"},
|
||||
|
|
|
@ -16,6 +16,7 @@ bleach-allowlist = "^1.0.3"
|
|||
Pillow = "^8.3.1"
|
||||
sorl-thumbnail = "^12.7.0"
|
||||
libsass = "^0.21.0"
|
||||
django-debug-toolbar = "^3.2.2"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
|
||||
|
|
|
@ -33,12 +33,15 @@ INSTALLED_APPS = [
|
|||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.humanize',
|
||||
'simple_history',
|
||||
'django_bootstrap5',
|
||||
'sorl.thumbnail'
|
||||
'sorl.thumbnail',
|
||||
'debug_toolbar'
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'debug_toolbar.middleware.DebugToolbarMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
|
@ -92,7 +95,7 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
TIME_ZONE = 'Europe/Vienna'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ Including another URLconf
|
|||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
import debug_toolbar
|
||||
from django.conf.urls.static import static
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
|
@ -26,6 +27,7 @@ urlpatterns = [
|
|||
]
|
||||
|
||||
if settings.DEBUG:
|
||||
urlpatterns.append(path('__debug__/', include(debug_toolbar.urls)), )
|
||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
urlpatterns.append(path("css", views.debug_css, name="css"))
|
||||
urlpatterns.append(path("css_sourcemap", views.debug_css_sourcemap, name="css_sourcemap"))
|
||||
|
|
39
static/js/markdown.js
Normal file
39
static/js/markdown.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* Copyright (C) 2020 Lukas Winkler
|
||||
*
|
||||
* @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later
|
||||
*
|
||||
*/
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
const ids = ["id_description_md"];
|
||||
ids.forEach(function (id) {
|
||||
const element = document.getElementById(id);
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
const easyMDE = new EasyMDE({
|
||||
element: element,
|
||||
forceSync: true, // for "required" to work
|
||||
spellChecker: false,
|
||||
nativeSpellcheck: true,
|
||||
autoDownloadFontAwesome: false,
|
||||
autosave: {
|
||||
delay: 1000,
|
||||
submit_delay: 5000,
|
||||
timeFormat: {
|
||||
locale: 'de-AT',
|
||||
format: {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
},
|
||||
},
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
1
static/libs/easymde.min.js
vendored
Symbolic link
1
static/libs/easymde.min.js
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../node_modules/easymde/dist/easymde.min.js
|
1
static/libs/fontawesome-solid.min.js
vendored
Symbolic link
1
static/libs/fontawesome-solid.min.js
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../node_modules/@fortawesome/fontawesome-free/js/solid.min.js
|
1
static/libs/fontawesome.min.js
vendored
Symbolic link
1
static/libs/fontawesome.min.js
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../node_modules/@fortawesome/fontawesome-free/js/fontawesome.min.js
|
27
static/scss/_avatar.scss
Normal file
27
static/scss/_avatar.scss
Normal file
|
@ -0,0 +1,27 @@
|
|||
|
||||
.avatar {
|
||||
display: block;
|
||||
|
||||
&.avatar-text {
|
||||
font-size: 1rem;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
vertical-align: middle;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
|
||||
&.avatar-large {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.avatar-large {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
line-height: 150px;
|
||||
margin: 1rem auto;
|
||||
}
|
||||
}
|
|
@ -17,18 +17,6 @@ tr.collapse-button:not(.collapsed) {
|
|||
background: darkgray;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
display: block;
|
||||
font-size: 1em;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
vertical-align: middle;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.side-card {
|
||||
display: flex;
|
||||
|
@ -42,13 +30,43 @@ tr.collapse-button:not(.collapsed) {
|
|||
.text-col {
|
||||
a {
|
||||
text-decoration: none;
|
||||
&:focus,&:active,&:hover{
|
||||
|
||||
&:focus, &:active, &:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.character-heading {
|
||||
border-bottom: solid 2px;
|
||||
}
|
||||
|
||||
.cp:after {
|
||||
background: #B87333;
|
||||
}
|
||||
|
||||
.sp:after {
|
||||
background: #CFD0D1;
|
||||
}
|
||||
|
||||
.gp:after {
|
||||
background: #FFD700;
|
||||
}
|
||||
|
||||
.pp:after {
|
||||
background: #B7B4AE;
|
||||
}
|
||||
|
||||
.cp, .sp, .gp, .pp {
|
||||
&:after {
|
||||
content: "";
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
vertical-align: middle;
|
||||
margin: 0 5px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
@import "variables";
|
||||
|
||||
@import "node_modules/bootstrap/scss/bootstrap";
|
||||
@import "node_modules/easymde/dist/easymde.min";
|
||||
|
||||
@import "misc";
|
||||
@import "avatar";
|
||||
|
|
Loading…
Reference in a new issue