6 Commits

27 changed files with 171 additions and 44 deletions

View File

@@ -21,7 +21,7 @@ it has been developed with a commitment of few minutes a day;
it lacks any kind of documentation, code review, architectural review,
security assesment, pentest, ISO certification, etc.
This project probably doesn't match you needs nor expectations. Be aware.
This project probably doesn't match your needs nor expectations. Be aware.
Your model train may also catch fire while using this software.

View File

@@ -0,0 +1,17 @@
# Generated by Django 4.1.3 on 2023-01-02 15:03
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("consist", "0007_alter_consist_image"),
]
operations = [
migrations.AlterModelOptions(
name="consist",
options={"ordering": ["company", "-creation_time"]},
),
]

View File

@@ -32,7 +32,7 @@ class Consist(models.Model):
return reverse("consist", kwargs={"uuid": self.uuid})
class Meta:
ordering = ["creation_time"]
ordering = ["company", "-creation_time"]
class ConsistItem(models.Model):

View File

@@ -3,7 +3,34 @@ from solo.admin import SingletonModelAdmin
from portal.models import SiteConfiguration, Flatpage
admin.site.register(SiteConfiguration, SingletonModelAdmin)
@admin.register(SiteConfiguration)
class SiteConfigurationAdmin(SingletonModelAdmin):
fieldsets = (
(
None,
{
"fields": (
"site_name",
"site_author",
"about",
"items_per_page",
"items_ordering",
"footer",
"footer_extended",
)
},
),
(
"Advanced",
{
"classes": ("collapse",),
"fields": (
"show_version",
"extra_head",
),
},
),
)
@admin.register(Flatpage)

View File

@@ -0,0 +1,18 @@
# Generated by Django 4.1.3 on 2022-12-28 22:43
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("portal", "0013_remove_flatpage_draft_flatpage_published"),
]
operations = [
migrations.AddField(
model_name="siteconfiguration",
name="extra_head",
field=models.TextField(blank=True),
),
]

View File

@@ -35,6 +35,7 @@ class SiteConfiguration(SingletonModel):
footer = RichTextField(blank=True)
footer_extended = RichTextField(blank=True)
show_version = models.BooleanField(default=True)
extra_head = models.TextField(blank=True)
class Meta:
verbose_name = "Site Configuration"

View File

@@ -12,7 +12,7 @@
<meta name="description" content="{{ site_conf.about}}">
<meta name="author" content="{{ site_conf.site_author }}">
<meta name="generator" content="Django Framework">
<title>{{ site_conf.site_name }}</title>
<title>{% block title %}{{ title }}{% endblock %} - {{ site_conf.site_name }}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap-dark-5@1.1.3/dist/css/bootstrap-nightshade.min.css" rel="stylesheet">
<link href="{% static "css/main.css" %}" rel="stylesheet">
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
@@ -34,6 +34,10 @@
html.dark .d-light-inline { display: none !important; }
html.dark .d-dark-inline { display: inline !important; }
</style>
{% block extra_head %}
{{ site_conf.extra_head | safe }}
{% endblock %}
</head>
<body>
<header>
@@ -81,7 +85,9 @@
<section class="py-4 text-center container">
<div class="row">
<div class="mx-auto">
{% block header %}{% endblock %}
<h1 class="fw-light">{{ title }}</h1>
{% block header %}
{% endblock %}
</div>
</div>
</section>
@@ -94,7 +100,7 @@
<div class="col">
<div class="card shadow-sm">
{% for i in r.image.all %}
{% if i.is_thumbnail %}<a href="{{r.get_absolute_url}}"><img src="{{ i.image.url }}" alt="Card image cap"></a>{% endif %}
{% if forloop.first %}<a href="{{r.get_absolute_url}}"><img src="{{ i.image.url }}" alt="Card image cap"></a>{% endif %}
{% endfor %}
<div class="card-body">
<p class="card-text" style="position: relative;">

View File

@@ -1,8 +1,5 @@
{% extends "base.html" %}
{% block header %}
<h1 class="fw-light">Companies</h1>
{% endblock %}
{% block cards %}
{% for c in company %}
<div class="col">

View File

@@ -1,7 +1,6 @@
{% extends "base.html" %}
{% block header %}
<h1 class="fw-light">{{ consist }}</h1>
{% if consist.tags.all %}
<p><small>Tags:</small>
{% for t in consist.tags.all %}<a href="{% url 'filtered' _filter="tag" search=t.slug %}" class="badge rounded-pill bg-primary">
@@ -16,7 +15,7 @@
<div class="col">
<div class="card shadow-sm">
{% for i in r.rolling_stock.image.all %}
{% if i.is_thumbnail %}<a href="{{r.rolling_stock.get_absolute_url}}"><img src="{{ i.image.url }}" alt="Card image cap"></a>{% endif %}
{% if forloop.first %}<a href="{{r.rolling_stock.get_absolute_url}}"><img src="{{ i.image.url }}" alt="Card image cap"></a>{% endif %}
{% endfor %}
<div class="card-body">
<p class="card-text" style="position: relative;">

View File

@@ -1,8 +1,5 @@
{% extends "base.html" %}
{% block header %}
<h1 class="fw-light">Consists</h1>
{% endblock %}
{% block cards %}
{% for c in consist %}
<div class="col">
@@ -13,7 +10,7 @@
{% else %}
{% with c.consist_item.first.rolling_stock as r %}
{% for i in r.image.all %}
{% if i.is_thumbnail %}<img src="{{ i.image.url }}" alt="Card image cap">{% endif %}
{% if forloop.first %}<img src="{{ i.image.url }}" alt="Card image cap">{% endif %}
{% endfor %}
{% endwith %}
{% endif %}

View File

@@ -1,7 +1,6 @@
{% extends 'base.html' %}
{% block header %}
<h1 class="fw-light">{{ flatpage.name }}</h1>
<small class="text-muted">Updated {{ flatpage.updated_time | date:"M d, Y H:i" }}</small>
{% endblock %}
{% block extra_content %}

View File

@@ -1,7 +1,6 @@
{% extends "base.html" %}
{% block header %}
{% if site_conf.about %}<h1 class="fw-light">About</h1>{% endif %}
<p class="lead text-muted">{{ site_conf.about | safe }}</p>
{% endblock %}

View File

@@ -1,7 +1,6 @@
{% extends 'base.html' %}
{% block header %}
<h1 class="fw-light">{{ rolling_stock }}</h1>
{% if rolling_stock.tags.all %}
<p><small>Tags:</small>
{% for t in rolling_stock.tags.all %}<a href="{% url 'filtered' _filter="tag" search=t.slug %}" class="badge rounded-pill bg-primary">

View File

@@ -1,8 +1,5 @@
{% extends "base.html" %}
{% block header %}
<h1 class="fw-light">Scales</h1>
{% endblock %}
{% block cards %}
{% for s in scale %}
<div class="col">

View File

@@ -1,7 +1,6 @@
{% extends "base.html" %}
{% block header %}
<h1 class="fw-light">{{ filter | default_if_none:"Search" | title }}: {{ search }}</h1>
<p class="lead text-muted">Results found: {{ matches }}</p>
{% endblock %}
{% block pagination %}

View File

@@ -46,7 +46,11 @@ class GetHome(View):
return render(
request,
"home.html",
{"rolling_stock": rolling_stock, "page_range": page_range},
{
"title": "Home",
"rolling_stock": rolling_stock,
"page_range": page_range,
},
)
@@ -83,8 +87,10 @@ class GetHomeFiltered(View):
query = Q(tags__slug__iexact=search)
else:
raise Http404
rolling_stock = RollingStock.objects.filter(query).distinct().order_by(
*order_by_fields()
rolling_stock = (
RollingStock.objects.filter(query)
.distinct()
.order_by(*order_by_fields())
)
matches = len(rolling_stock)
@@ -105,6 +111,7 @@ class GetHomeFiltered(View):
request,
"search.html",
{
"title": "{0}: {1}".format(_filter.capitalize(), search),
"search": search,
"filter": _filter,
"matches": matches,
@@ -125,6 +132,7 @@ class GetHomeFiltered(View):
request,
"search.html",
{
"title": "{0}: {1}".format(_filter.capitalize(), search),
"search": search,
"filter": _filter,
"matches": matches,
@@ -164,6 +172,7 @@ class GetRollingStock(View):
request,
"page.html",
{
"title": rolling_stock,
"rolling_stock": rolling_stock,
"class_properties": class_properties,
"rolling_stock_properties": rolling_stock_properties,
@@ -186,7 +195,11 @@ class Consists(View):
return render(
request,
"consists.html",
{"consist": consist, "page_range": page_range},
{
"title": "Consists",
"consist": consist,
"page_range": page_range,
},
)
@@ -209,6 +222,7 @@ class GetConsist(View):
request,
"consist.html",
{
"title": consist,
"consist": consist,
"rolling_stock": rolling_stock,
"page_range": page_range,
@@ -230,7 +244,11 @@ class Companies(View):
return render(
request,
"companies.html",
{"company": company, "page_range": page_range},
{
"title": "Companies",
"company": company,
"page_range": page_range,
},
)
@@ -248,7 +266,7 @@ class Scales(View):
return render(
request,
"scales.html",
{"scale": scale, "page_range": page_range},
{"title": "Scales", "scale": scale, "page_range": page_range},
)
@@ -264,5 +282,5 @@ class GetFlatpage(View):
return render(
request,
"flatpage.html",
{"flatpage": flatpage},
{"title": flatpage.name, "flatpage": flatpage},
)

View File

@@ -1,4 +1,4 @@
from ram.utils import git_suffix
__version__ = "0.0.21"
__version__ = "0.0.24"
__version__ += git_suffix(__file__)

View File

@@ -1,4 +1,6 @@
from django.contrib import admin
from adminsortable2.admin import SortableAdminBase, SortableInlineAdminMixin
from roster.models import (
RollingClass,
RollingClassProperty,
@@ -35,7 +37,7 @@ class RollingStockDocInline(admin.TabularInline):
classes = ["collapse"]
class RollingStockImageInline(admin.TabularInline):
class RollingStockImageInline(SortableInlineAdminMixin, admin.TabularInline):
model = RollingStockImage
min_num = 0
extra = 0
@@ -93,7 +95,7 @@ class RollingJournalDocumentAdmin(admin.ModelAdmin):
@admin.register(RollingStock)
class RollingStockAdmin(admin.ModelAdmin):
class RollingStockAdmin(SortableAdminBase, admin.ModelAdmin):
inlines = (
RollingStockPropertyInline,
RollingStockImageInline,

View File

@@ -0,0 +1,17 @@
# Generated by Django 4.1.3 on 2022-12-28 21:07
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("roster", "0014_alter_rollingstockdocument_file_and_more"),
]
operations = [
migrations.AlterModelOptions(
name="rollingstockimage",
options={"ordering": ["-is_thumbnail"]},
),
]

View File

@@ -0,0 +1,22 @@
# Generated by Django 4.1.3 on 2023-01-02 12:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("roster", "0015_alter_rollingstockimage_options"),
]
operations = [
migrations.AlterModelOptions(
name="rollingstockimage",
options={"ordering": ["order"]},
),
migrations.AddField(
model_name="rollingstockimage",
name="order",
field=models.PositiveIntegerField(default=0),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 4.1.3 on 2023-01-02 15:02
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("roster", "0016_alter_rollingstockimage_options_and_more"),
]
operations = [
migrations.RemoveField(
model_name="rollingstockimage",
name="is_thumbnail",
),
]

View File

@@ -155,13 +155,13 @@ class RollingStockDocument(models.Model):
class RollingStockImage(models.Model):
order = models.PositiveIntegerField(default=0, blank=False, null=False)
rolling_stock = models.ForeignKey(
RollingStock, on_delete=models.CASCADE, related_name="image"
)
image = models.ImageField(
upload_to="images/", storage=DeduplicatedStorage, null=True, blank=True
)
is_thumbnail = models.BooleanField()
def image_thumbnail(self):
return get_image_preview(self.image.url)
@@ -171,12 +171,8 @@ class RollingStockImage(models.Model):
def __str__(self):
return "{0}".format(os.path.basename(self.image.name))
def save(self, **kwargs):
if self.is_thumbnail:
RollingStockImage.objects.filter(
rolling_stock=self.rolling_stock
).update(is_thumbnail=False)
super().save(**kwargs)
class Meta:
ordering = ["order"]
class RollingStockProperty(models.Model):