mirror of
https://github.com/daniviga/django-ram.git
synced 2025-08-07 22:57:50 +02:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
764240d67a
|
|||
424b17ae58
|
|||
c73efb01e4 | |||
a21baac10c
|
|||
4b0361acc1
|
|||
425eed3d83 | |||
2d48463474
|
|||
08226247c7
|
|||
4f52736d97
|
@@ -12,9 +12,6 @@ class Migration(migrations.Migration):
|
|||||||
operations = [
|
operations = [
|
||||||
migrations.AlterModelOptions(
|
migrations.AlterModelOptions(
|
||||||
name="book",
|
name="book",
|
||||||
options={
|
options={"ordering": ["authors__last_name", "title"]},
|
||||||
"ordering": ["authors__last_name", "title"],
|
|
||||||
"verbose_name_plural": "Rolling stock",
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
18
ram/bookshelf/migrations/0006_alter_book_isbn.py
Normal file
18
ram/bookshelf/migrations/0006_alter_book_isbn.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.2.5 on 2023-10-03 20:43
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("bookshelf", "0005_alter_book_options"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="book",
|
||||||
|
name="ISBN",
|
||||||
|
field=models.CharField(blank=True, max_length=17),
|
||||||
|
),
|
||||||
|
]
|
17
ram/bookshelf/migrations/0007_alter_book_options.py
Normal file
17
ram/bookshelf/migrations/0007_alter_book_options.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 4.2.5 on 2023-10-03 21:07
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("bookshelf", "0006_alter_book_isbn"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="book",
|
||||||
|
options={"ordering": ["title"]},
|
||||||
|
),
|
||||||
|
]
|
@@ -0,0 +1,20 @@
|
|||||||
|
# Generated by Django 4.2.6 on 2023-10-09 21:08
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("bookshelf", "0007_alter_book_options"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="author",
|
||||||
|
options={"ordering": ["last_name", "first_name"]},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="publisher",
|
||||||
|
options={"ordering": ["name"]},
|
||||||
|
),
|
||||||
|
]
|
@@ -16,6 +16,9 @@ class Publisher(models.Model):
|
|||||||
country = CountryField(blank=True)
|
country = CountryField(blank=True)
|
||||||
website = models.URLField(blank=True)
|
website = models.URLField(blank=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ["name"]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
@@ -24,6 +27,9 @@ class Author(models.Model):
|
|||||||
first_name = models.CharField(max_length=100)
|
first_name = models.CharField(max_length=100)
|
||||||
last_name = models.CharField(max_length=100)
|
last_name = models.CharField(max_length=100)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ["last_name", "first_name"]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.last_name}, {self.first_name}"
|
return f"{self.last_name}, {self.first_name}"
|
||||||
|
|
||||||
@@ -36,7 +42,7 @@ class Book(models.Model):
|
|||||||
title = models.CharField(max_length=200)
|
title = models.CharField(max_length=200)
|
||||||
authors = models.ManyToManyField(Author)
|
authors = models.ManyToManyField(Author)
|
||||||
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
|
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
|
||||||
ISBN = models.CharField(max_length=13, blank=True)
|
ISBN = models.CharField(max_length=17, blank=True) # 13 + dashes
|
||||||
language = models.CharField(
|
language = models.CharField(
|
||||||
max_length=7,
|
max_length=7,
|
||||||
choices=settings.LANGUAGES,
|
choices=settings.LANGUAGES,
|
||||||
@@ -53,8 +59,7 @@ class Book(models.Model):
|
|||||||
updated_time = models.DateTimeField(auto_now=True)
|
updated_time = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["authors__last_name", "title"]
|
ordering = ["title"]
|
||||||
verbose_name_plural = "Rolling stock"
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.title
|
return self.title
|
||||||
|
@@ -15,6 +15,7 @@ from metadata.models import (
|
|||||||
|
|
||||||
@admin.register(Property)
|
@admin.register(Property)
|
||||||
class PropertyAdmin(admin.ModelAdmin):
|
class PropertyAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ("name", "private")
|
||||||
search_fields = ("name",)
|
search_fields = ("name",)
|
||||||
|
|
||||||
|
|
||||||
|
18
ram/metadata/migrations/0013_decoderdocument_private.py
Normal file
18
ram/metadata/migrations/0013_decoderdocument_private.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.2.5 on 2023-10-06 19:48
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("metadata", "0012_alter_decoder_manufacturer_decoderdocument"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="decoderdocument",
|
||||||
|
name="private",
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
@@ -66,7 +66,6 @@ class Flatpage(models.Model):
|
|||||||
return reverse("flatpage", kwargs={"flatpage": self.path})
|
return reverse("flatpage", kwargs={"flatpage": self.path})
|
||||||
|
|
||||||
def get_link(self):
|
def get_link(self):
|
||||||
if self.published:
|
|
||||||
return mark_safe(
|
return mark_safe(
|
||||||
'<a href="{0}" target="_blank">Link</a>'.format(
|
'<a href="{0}" target="_blank">Link</a>'.format(
|
||||||
self.get_absolute_url()
|
self.get_absolute_url()
|
||||||
|
@@ -46,12 +46,12 @@
|
|||||||
transform="rotate(-90)" />
|
transform="rotate(-90)" />
|
||||||
<text
|
<text
|
||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
style="font-weight:bold;font-size:0.444444px;line-height:1.25;font-family:'Noto Sans';-inkscape-font-specification:'Noto Sans Bold';letter-spacing:0px;word-spacing:0px;stroke-width:0.0138889"
|
style="font-weight:bold;font-size:0.444444px;line-height:1.25;font-family:system-ui,-apple-system,'Segoe UI',Roboto,'Helvetica Neue','Noto Sans','Liberation Sans',Arial,sans-serif;-inkscape-font-specification:'Noto Sans Bold';letter-spacing:0px;word-spacing:0px;stroke-width:0.0138889"
|
||||||
x="1.5366687"
|
x="1.5366687"
|
||||||
y="1.6798887"
|
y="1.6798887"
|
||||||
id="text1"><tspan
|
id="text1"><tspan
|
||||||
id="tspan1"
|
id="tspan1"
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:0.444444px;font-family:'Noto Sans';-inkscape-font-specification:'Noto Sans';fill:#dee2e6;fill-opacity:1;stroke-width:0.0138889"
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:0.444444px;font-family:system-ui,-apple-system,'Segoe UI',Roboto,'Helvetica Neue','Noto Sans','Liberation Sans',Arial,sans-serif;-inkscape-font-specification:'Noto Sans';fill:#dee2e6;fill-opacity:1;stroke-width:0.0138889"
|
||||||
x="1.5366687"
|
x="1.5366687"
|
||||||
y="1.6798887">Coming soon</tspan></text>
|
y="1.6798887">Coming soon</tspan></text>
|
||||||
</g>
|
</g>
|
||||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -171,8 +171,8 @@
|
|||||||
<li><a class="dropdown-item" href="{% url 'manufacturers' category='real' %}">Real</a></li>
|
<li><a class="dropdown-item" href="{% url 'manufacturers' category='real' %}">Real</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
{% show_flatpages_menu %}
|
|
||||||
{% show_bookshelf_menu %}
|
{% show_bookshelf_menu %}
|
||||||
|
{% show_flatpages_menu %}
|
||||||
</ul>
|
</ul>
|
||||||
{% include 'includes/search.html' %}
|
{% include 'includes/search.html' %}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -43,14 +43,12 @@
|
|||||||
<section class="py-4 text-start container">
|
<section class="py-4 text-start container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="mx-auto">
|
<div class="mx-auto">
|
||||||
<nav>
|
<nav class="nav nav-tabs flex-column flex-md-row mb-2" id="nav-tab">
|
||||||
<div class="nav nav-tabs" id="nav-tab" role="tablist">
|
|
||||||
<button class="nav-link active" id="nav-summary-tab" data-bs-toggle="tab" data-bs-target="#nav-summary" type="button" role="tab" aria-controls="nav-summary" aria-selected="true">Summary</button>
|
<button class="nav-link active" id="nav-summary-tab" data-bs-toggle="tab" data-bs-target="#nav-summary" type="button" role="tab" aria-controls="nav-summary" aria-selected="true">Summary</button>
|
||||||
{% if book.notes %}<button class="nav-link" id="nav-notes-tab" data-bs-toggle="tab" data-bs-target="#nav-notes" type="button" role="tab" aria-controls="nav-notes" aria-selected="false">Notes</button>{% endif %}
|
{% if book.notes %}<button class="nav-link" id="nav-notes-tab" data-bs-toggle="tab" data-bs-target="#nav-notes" type="button" role="tab" aria-controls="nav-notes" aria-selected="false">Notes</button>{% endif %}
|
||||||
</div>
|
|
||||||
</nav>
|
</nav>
|
||||||
<div class="tab-content" id="nav-tabContent">
|
<div class="tab-content" id="nav-tabContent">
|
||||||
<div class="tab-pane fade show active" id="nav-summary" role="tabpanel" aria-labelledby="nav-summary-tab">
|
<div class="tab-pane show active" id="nav-summary" role="tabpanel" aria-labelledby="nav-summary-tab">
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -112,7 +110,7 @@
|
|||||||
</table>
|
</table>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane fade" id="nav-notes" role="tabpanel" aria-labelledby="nav-notes-tab">
|
<div class="tab-pane" id="nav-notes" role="tabpanel" aria-labelledby="nav-notes-tab">
|
||||||
{{ book.notes | safe }}
|
{{ book.notes | safe }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,68 +1,4 @@
|
|||||||
{% extends "cards.html" %}
|
{% extends "cards.html" %}
|
||||||
|
|
||||||
{% block cards %}
|
|
||||||
{% for d in data %}
|
|
||||||
<div class="col">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
{% if d.image.all %}
|
|
||||||
<a href="{{ d.get_absolute_url }}">
|
|
||||||
{% for r in d.image.all %}
|
|
||||||
{% if forloop.first %}<img src="{{ r.image.url }}" alt="Card image cap">{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text" style="position: relative;">
|
|
||||||
<strong>{{ d }}</strong>
|
|
||||||
<a class="stretched-link" href="{{ d.get_absolute_url }}"></a>
|
|
||||||
</p>
|
|
||||||
{% if d.tags.all %}
|
|
||||||
<p class="card-text"><small>Tags:</small>
|
|
||||||
{% for t in d.tags.all %}<a href="{% url 'filtered' _filter="tag" search=t.slug %}" class="badge rounded-pill bg-primary">
|
|
||||||
{{ t.name }}</a>{# new line is required #}
|
|
||||||
{% endfor %}
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th colspan="2" scope="row">Book</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="table-group-divider">
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Authors</th>
|
|
||||||
<td>
|
|
||||||
<ul class="mb-0 list-unstyled">{% for a in d.authors.all %}<li>{{ a }}</li>{% endfor %}</ul>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Publisher</th>
|
|
||||||
<td>{{ d.publisher }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Language</th>
|
|
||||||
<td>{{ d.get_language_display }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Pages</th>
|
|
||||||
<td>{{ d.number_of_pages|default:"-" }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Year</th>
|
|
||||||
<td>{{ d.publication_year|default:"-" }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="d-grid gap-2 mb-1 d-md-block">
|
|
||||||
<a class="btn btn-sm btn-outline-primary" href="{{ d.get_absolute_url }}">Show all data</a>
|
|
||||||
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:bookshelf_book_change' d.pk %}">Edit</a>{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endblock %}
|
|
||||||
{% block pagination %}
|
{% block pagination %}
|
||||||
{% if data.has_other_pages %}
|
{% if data.has_other_pages %}
|
||||||
<nav aria-label="Page navigation example">
|
<nav aria-label="Page navigation example">
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
Bookshelf
|
Bookshelf
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu" aria-labelledby="bookshelfDropdownMenuLink">
|
<ul class="dropdown-menu" aria-labelledby="bookshelfDropdownMenuLink">
|
||||||
<li><a class="nav-link" href="{% url 'books' %}">Books</a></li>
|
<li><a class="dropdown-item" href="{% url 'books' %}">Books</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load static %}
|
|
||||||
|
|
||||||
{% block header %}
|
{% block header %}
|
||||||
<p class="lead text-muted">Results found: {{ matches }}</p>
|
<p class="lead text-muted">Results found: {{ matches }}</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -8,97 +6,21 @@
|
|||||||
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3">
|
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3">
|
||||||
{% block cards %}
|
{% block cards %}
|
||||||
{% for d in data %}
|
{% for d in data %}
|
||||||
<div class="col">
|
{% if d.type == "rolling_stock" %}
|
||||||
<div class="card shadow-sm">
|
{% include "cards/rolling_stock.html" %}
|
||||||
{% if d.image.count > 0 %}
|
{% elif d.type == "company" %}
|
||||||
<a href="{{d.get_absolute_url}}"><img class="card-img-top" src="{{ d.image.first.image.url }}" alt="{{ d }}"></a>
|
{% include "cards/company.html" %}
|
||||||
{% else %}
|
{% elif d.type == "rolling_stock_type" %}
|
||||||
<!-- Do not show the "Coming soon" image when running in a single card column mode (e.g. on mobile) -->
|
{% include "cards/rolling_stock_type.html" %}
|
||||||
<a href="{{d.get_absolute_url}}"><img class="card-img-top d-none d-sm-block" src="{% static DEFAULT_CARD_IMAGE %}" alt="{{ d }}"></a>
|
{% elif d.type == "scale" %}
|
||||||
|
{% include "cards/scale.html" %}
|
||||||
|
{% elif d.type == "consist" %}
|
||||||
|
{% include "cards/consist.html" %}
|
||||||
|
{% elif d.type == "manufacturer" %}
|
||||||
|
{% include "cards/manufacturer.html" %}
|
||||||
|
{% elif d.type == "book" %}
|
||||||
|
{% include "cards/book.html" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text" style="position: relative;">
|
|
||||||
<strong>{{ d }}</strong>
|
|
||||||
<a class="stretched-link" href="{{ d.get_absolute_url }}"></a>
|
|
||||||
</p>
|
|
||||||
{% if d.tags.all %}
|
|
||||||
<p class="card-text"><small>Tags:</small>
|
|
||||||
{% for t in d.tags.all %}<a href="{% url 'filtered' _filter="tag" search=t.slug %}" class="badge rounded-pill bg-primary">
|
|
||||||
{{ t.name }}</a>{# new line is required #}
|
|
||||||
{% endfor %}
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th colspan="2" scope="row">Data</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="table-group-divider">
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Type</th>
|
|
||||||
<td>{{ d.rolling_class.type }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Company</th>
|
|
||||||
<td>
|
|
||||||
<a href="{% url 'filtered' _filter="company" search=d.rolling_class.company.slug %}"><abbr title="{{ d.rolling_class.company.extended_name }}">{{ d.rolling_class.company }}</abbr></a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Class</th>
|
|
||||||
<td>{{ d.rolling_class.identifier }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Road number</th>
|
|
||||||
<td>{{ d.road_number }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Era</th>
|
|
||||||
<td>{{ d.era }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Manufacturer</th>
|
|
||||||
<td>{%if d.manufacturer %}
|
|
||||||
<a href="{% url 'filtered' _filter="manufacturer" search=d.manufacturer.slug %}">{{ d.manufacturer }}{% if d.manufacturer.website %}</a> <a href="{{ d.manufacturer.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a>{% endif %}
|
|
||||||
{% endif %}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Scale</th>
|
|
||||||
<td><a href="{% url 'filtered' _filter="scale" search=d.scale.slug %}"><abbr title="{{ d.scale.ratio }} - {{ d.scale.tracks }}">{{ d.scale }}</abbr></a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Item number</th>
|
|
||||||
<td>{{ d.item_number }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
{% if d.decoder %}
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th colspan="2" scope="row">DCC data</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="table-group-divider">
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Decoder</th>
|
|
||||||
<td>{{ d.decoder }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Address</th>
|
|
||||||
<td>{{ d.address }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
{% endif %}
|
|
||||||
<div class="d-grid gap-2 mb-1 d-md-block">
|
|
||||||
<a class="btn btn-sm btn-outline-primary" href="{{d.get_absolute_url}}">Show all data</a>
|
|
||||||
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:roster_rollingstock_change' d.pk %}">Edit</a>{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
|
60
ram/portal/templates/cards/book.html
Normal file
60
ram/portal/templates/cards/book.html
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<div class="col">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
{% if d.item.image.all %}
|
||||||
|
<a href="{{ d.item.get_absolute_url }}">
|
||||||
|
{% for r in d.item.image.all %}
|
||||||
|
{% if forloop.first %}<img src="{{ r.image.url }}" alt="Card image cap">{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text" style="position: relative;">
|
||||||
|
<strong>{{ d.item }}</strong>
|
||||||
|
<a class="stretched-link" href="{{ d.item.get_absolute_url }}"></a>
|
||||||
|
</p>
|
||||||
|
{% if d.item.tags.all %}
|
||||||
|
<p class="card-text"><small>Tags:</small>
|
||||||
|
{% for t in d.item.tags.all %}<a href="{% url 'filtered' _filter="tag" search=t.slug %}" class="badge rounded-pill bg-primary">
|
||||||
|
{{ t.name }}</a>{# new line is required #}
|
||||||
|
{% endfor %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="2" scope="row">Book</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="table-group-divider">
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Authors</th>
|
||||||
|
<td>
|
||||||
|
<ul class="mb-0 list-unstyled">{% for a in d.item.authors.all %}<li>{{ a }}</li>{% endfor %}</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Publisher</th>
|
||||||
|
<td>{{ d.item.publisher }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Language</th>
|
||||||
|
<td>{{ d.item.get_language_display }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Pages</th>
|
||||||
|
<td>{{ d.item.number_of_pages|default:"-" }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Year</th>
|
||||||
|
<td>{{ d.item.publication_year|default:"-" }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="d-grid gap-2 mb-1 d-md-block">
|
||||||
|
<a class="btn btn-sm btn-outline-primary" href="{{ d.item.get_absolute_url }}">Show all data</a>
|
||||||
|
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:bookshelf_book_change' d.item.pk %}">Edit</a>{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
46
ram/portal/templates/cards/company.html
Normal file
46
ram/portal/templates/cards/company.html
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<div class="col">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text" style="position: relative;">
|
||||||
|
<strong>{{ d.item.name }}</strong>
|
||||||
|
</p>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="2" scope="row">Company</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="table-group-divider">
|
||||||
|
{% if d.item.logo %}
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Logo</th>
|
||||||
|
<td><img style="max-height: 48px" src="{{ d.item.logo.url }}" /></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Name</th>
|
||||||
|
<td>{{ d.item.extended_name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Abbreviation</th>
|
||||||
|
<td>{{ d.item.name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Country</th>
|
||||||
|
<td>{{ d.item.country.name }} <img src="{{ d.item.country.flag }}" alt="{{ d.item.country }}" />
|
||||||
|
</tr>
|
||||||
|
{% if d.item.freelance %}
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Notes</th>
|
||||||
|
<td>A <em>freelance</em> company</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="d-grid gap-2 mb-1 d-md-block">
|
||||||
|
<a class="btn btn-sm btn-outline-primary" href="{% url 'filtered' _filter="company" search=d.item.slug %}">Show all rolling stock</a>
|
||||||
|
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_company_change' d.item.pk %}">Edit</a>{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
59
ram/portal/templates/cards/consist.html
Normal file
59
ram/portal/templates/cards/consist.html
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<div class="col">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<a href="{{ d.item.get_absolute_url }}">
|
||||||
|
{% if d.item.image %}
|
||||||
|
<img src="{{ d.item.image.url }}" alt="Card image cap">
|
||||||
|
{% else %}
|
||||||
|
{% with d.item.consist_item.first.rolling_stock as r %}
|
||||||
|
{% for i in r.image.all %}
|
||||||
|
{% if forloop.first %}<img src="{{ i.image.url }}" alt="Card image cap">{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endwith %}
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text" style="position: relative;">
|
||||||
|
<strong>{{ d.item }}</strong>
|
||||||
|
<a class="stretched-link" href="{{ d.item.get_absolute_url }}"></a>
|
||||||
|
</p>
|
||||||
|
{% if d.item.tags.all %}
|
||||||
|
<p class="card-text"><small>Tags:</small>
|
||||||
|
{% for t in d.item.tags.all %}<a href="{% url 'filtered' _filter="tag" search=t.slug %}" class="badge rounded-pill bg-primary">
|
||||||
|
{{ t.name }}</a>{# new line is required #}
|
||||||
|
{% endfor %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="2" scope="row">Consist</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="table-group-divider">
|
||||||
|
{% if d.item.address %}
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Address</th>
|
||||||
|
<td>{{ d.item.address }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Company</th>
|
||||||
|
<td><abbr title="{{ d.item.company.extended_name }}">{{ d.item.company }}</abbr></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Era</th>
|
||||||
|
<td>{{ d.item.era }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Length</th>
|
||||||
|
<td>{{ d.item.consist_item.all | length }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="d-grid gap-2 mb-1 d-md-block">
|
||||||
|
<a class="btn btn-sm btn-outline-primary" href="{{ d.item.get_absolute_url }}">Show all data</a>
|
||||||
|
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:consist_consist_change' d.item.pk %}">Edit</a>{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
39
ram/portal/templates/cards/manufacturer.html
Normal file
39
ram/portal/templates/cards/manufacturer.html
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<div class="col">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text" style="position: relative;">
|
||||||
|
<strong>{{ d.item.name }}</strong>
|
||||||
|
</p>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="2" scope="row">Manufacturer</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="table-group-divider">
|
||||||
|
{% if d.item.logo %}
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Logo</th>
|
||||||
|
<td><img style="max-height: 48px" src="{{ d.item.logo.url }}" /></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% if d.item.website %}
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Website</th>
|
||||||
|
<td><a href="{{ d.item.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Category</th>
|
||||||
|
<td>{{ d.item.category | title }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="d-grid gap-2 mb-1 d-md-block">
|
||||||
|
<a class="btn btn-sm btn-outline-primary" href="{% url 'filtered' _filter="manufacturer" search=d.item.slug %}">Show all rolling stock</a>
|
||||||
|
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_manufacturer_change' d.item.pk %}">Edit</a>{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
92
ram/portal/templates/cards/rolling_stock.html
Normal file
92
ram/portal/templates/cards/rolling_stock.html
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="col">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
{% if d.item.image.exists %}
|
||||||
|
<a href="{{d.item.get_absolute_url}}"><img class="card-img-top" src="{{ d.item.image.first.image.url }}" alt="{{ d }}"></a>
|
||||||
|
{% else %}
|
||||||
|
<!-- Do not show the "Coming soon" image when running in a single card column mode (e.g. on mobile) -->
|
||||||
|
<a href="{{d.item.get_absolute_url}}"><img class="card-img-top d-none d-sm-block" src="{% static DEFAULT_CARD_IMAGE %}" alt="{{ d }}"></a>
|
||||||
|
{% endif %}
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text" style="position: relative;">
|
||||||
|
<strong>{{ d.item }}</strong>
|
||||||
|
<a class="stretched-link" href="{{ d.item.get_absolute_url }}"></a>
|
||||||
|
</p>
|
||||||
|
{% if d.item.tags.all %}
|
||||||
|
<p class="card-text"><small>Tags:</small>
|
||||||
|
{% for t in d.item.tags.all %}<a href="{% url 'filtered' _filter="tag" search=t.slug %}" class="badge rounded-pill bg-primary">
|
||||||
|
{{ t.name }}</a>{# new line is required #}
|
||||||
|
{% endfor %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="2" scope="row">Rolling stock</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="table-group-divider">
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Type</th>
|
||||||
|
<td>{{ d.item.rolling_class.type }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Company</th>
|
||||||
|
<td>
|
||||||
|
<a href="{% url 'filtered' _filter="company" search=d.item.rolling_class.company.slug %}"><abbr title="{{ d.item.rolling_class.company.extended_name }}">{{ d.item.rolling_class.company }}</abbr></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Class</th>
|
||||||
|
<td>{{ d.item.rolling_class.identifier }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Road number</th>
|
||||||
|
<td>{{ d.item.road_number }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Era</th>
|
||||||
|
<td>{{ d.item.era }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Manufacturer</th>
|
||||||
|
<td>{%if d.item.manufacturer %}
|
||||||
|
<a href="{% url 'filtered' _filter="manufacturer" search=d.item.manufacturer.slug %}">{{ d.item.manufacturer }}{% if d.item.manufacturer.website %}</a> <a href="{{ d.item.manufacturer.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a>{% endif %}
|
||||||
|
{% endif %}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Scale</th>
|
||||||
|
<td><a href="{% url 'filtered' _filter="scale" search=d.item.scale.slug %}"><abbr title="{{ d.item.scale.ratio }} - {{ d.item.scale.tracks }}">{{ d.item.scale }}</abbr></a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Item number</th>
|
||||||
|
<td>{{ d.item.item_number }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% if d.item.decoder %}
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="2" scope="row">DCC data</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="table-group-divider">
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Decoder</th>
|
||||||
|
<td>{{ d.item.decoder }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Address</th>
|
||||||
|
<td>{{ d.item.address }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endif %}
|
||||||
|
<div class="d-grid gap-2 mb-1 d-md-block">
|
||||||
|
<a class="btn btn-sm btn-outline-primary" href="{{d.item.get_absolute_url}}">Show all data</a>
|
||||||
|
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:roster_rollingstock_change' d.item.pk %}">Edit</a>{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
29
ram/portal/templates/cards/rolling_stock_type.html
Normal file
29
ram/portal/templates/cards/rolling_stock_type.html
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<div class="col">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text"><strong>{{ d.item }}</strong></p>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="2" scope="row">Type</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="table-group-divider">
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Type</th>
|
||||||
|
<td>{{ d.item.type }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Category</th>
|
||||||
|
<td>{{ d.item.category | title}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="d-grid gap-2 mb-1 d-md-block">
|
||||||
|
<a class="btn btn-sm btn-outline-primary" href="{% url 'filtered' _filter="type" search=d.item.slug %}">Show all rolling stock</a>
|
||||||
|
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_scale_change' d.item.pk %}">Edit</a>{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
36
ram/portal/templates/cards/scale.html
Normal file
36
ram/portal/templates/cards/scale.html
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<div class="col">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text"><strong>{{ d.item }}</strong></p>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colspan="2" scope="row">Scale</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Name</th>
|
||||||
|
<td>{{ d.item.scale }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Ratio</th>
|
||||||
|
<td>{{ d.item.ratio }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Gauge</th>
|
||||||
|
<td>{{ d.item.gauge }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Tracks</th>
|
||||||
|
<td>{{ d.item.tracks }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="d-grid gap-2 mb-1 d-md-block">
|
||||||
|
<a class="btn btn-sm btn-outline-primary" href="{% url 'filtered' _filter="scale" search=d.item.slug %}">Show all rolling stock</a>
|
||||||
|
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_scale_change' d.item.pk %}">Edit</a>{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -1,55 +1,4 @@
|
|||||||
{% extends "cards.html" %}
|
{% extends "cards.html" %}
|
||||||
|
|
||||||
{% block cards %}
|
|
||||||
{% for d in data %}
|
|
||||||
<div class="col">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text" style="position: relative;">
|
|
||||||
<strong>{{ d.name }}</strong>
|
|
||||||
</p>
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th colspan="2" scope="row">Company</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="table-group-divider">
|
|
||||||
{% if d.logo %}
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Logo</th>
|
|
||||||
<td><img style="max-height: 48px" src="{{ d.logo.url }}" /></td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Name</th>
|
|
||||||
<td>{{ d.extended_name }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Abbreviation</th>
|
|
||||||
<td>{{ d.name }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Country</th>
|
|
||||||
<td>{{ d.country.name }} <img src="{{ d.country.flag }}" alt="{{ d.country }}" />
|
|
||||||
</tr>
|
|
||||||
{% if d.freelance %}
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Notes</th>
|
|
||||||
<td>A <em>freelance</em> company</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="d-grid gap-2 mb-1 d-md-block">
|
|
||||||
<a class="btn btn-sm btn-outline-primary" href="{% url 'filtered' _filter="company" search=d.slug %}">Show all rolling stock</a>
|
|
||||||
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_company_change' d.pk %}">Edit</a>{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endblock %}
|
|
||||||
{% block pagination %}
|
{% block pagination %}
|
||||||
{% if data.has_other_pages %}
|
{% if data.has_other_pages %}
|
||||||
<nav aria-label="Page navigation example">
|
<nav aria-label="Page navigation example">
|
||||||
|
@@ -66,14 +66,12 @@
|
|||||||
<section class="py-4 text-start container">
|
<section class="py-4 text-start container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="mx-auto">
|
<div class="mx-auto">
|
||||||
<nav>
|
<nav class="nav nav-tabs flex-column flex-md-row mb-2" id="nav-tab">
|
||||||
<div class="nav nav-tabs" id="nav-tab" role="tablist">
|
|
||||||
<button class="nav-link active" id="nav-summary-tab" data-bs-toggle="tab" data-bs-target="#nav-summary" type="button" role="tab" aria-controls="nav-summary" aria-selected="true">Summary</button>
|
<button class="nav-link active" id="nav-summary-tab" data-bs-toggle="tab" data-bs-target="#nav-summary" type="button" role="tab" aria-controls="nav-summary" aria-selected="true">Summary</button>
|
||||||
{% if consist.notes %}<button class="nav-link" id="nav-notes-tab" data-bs-toggle="tab" data-bs-target="#nav-notes" type="button" role="tab" aria-controls="nav-notes" aria-selected="false">Notes</button>{% endif %}
|
{% if consist.notes %}<button class="nav-link" id="nav-notes-tab" data-bs-toggle="tab" data-bs-target="#nav-notes" type="button" role="tab" aria-controls="nav-notes" aria-selected="false">Notes</button>{% endif %}
|
||||||
</div>
|
|
||||||
</nav>
|
</nav>
|
||||||
<div class="tab-content" id="nav-tabContent">
|
<div class="tab-content" id="nav-tabContent">
|
||||||
<div class="tab-pane fade show active" id="nav-summary" role="tabpanel" aria-labelledby="nav-summary-tab">
|
<div class="tab-pane show active" id="nav-summary" role="tabpanel" aria-labelledby="nav-summary-tab">
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -96,7 +94,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane fade" id="nav-notes" role="tabpanel" aria-labelledby="nav-notes-tab">
|
<div class="tab-pane" id="nav-notes" role="tabpanel" aria-labelledby="nav-notes-tab">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@@ -1,68 +1,4 @@
|
|||||||
{% extends "cards.html" %}
|
{% extends "cards.html" %}
|
||||||
|
|
||||||
{% block cards %}
|
|
||||||
{% for d in data %}
|
|
||||||
<div class="col">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<a href="{{ d.get_absolute_url }}">
|
|
||||||
{% if d.image %}
|
|
||||||
<img src="{{ d.image.url }}" alt="Card image cap">
|
|
||||||
{% else %}
|
|
||||||
{% with d.consist_item.first.rolling_stock as r %}
|
|
||||||
{% for i in r.image.all %}
|
|
||||||
{% if forloop.first %}<img src="{{ i.image.url }}" alt="Card image cap">{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endwith %}
|
|
||||||
{% endif %}
|
|
||||||
</a>
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text" style="position: relative;">
|
|
||||||
<strong>{{ d }}</strong>
|
|
||||||
<a class="stretched-link" href="{{ d.get_absolute_url }}"></a>
|
|
||||||
</p>
|
|
||||||
{% if d.tags.all %}
|
|
||||||
<p class="card-text"><small>Tags:</small>
|
|
||||||
{% for t in d.tags.all %}<a href="{% url 'filtered' _filter="tag" search=t.slug %}" class="badge rounded-pill bg-primary">
|
|
||||||
{{ t.name }}</a>{# new line is required #}
|
|
||||||
{% endfor %}
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th colspan="2" scope="row">Consist data</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="table-group-divider">
|
|
||||||
{% if d.address %}
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Address</th>
|
|
||||||
<td>{{ d.address }}</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Company</th>
|
|
||||||
<td><abbr title="{{ d.company.extended_name }}">{{ d.company }}</abbr></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Era</th>
|
|
||||||
<td>{{ d.era }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Length</th>
|
|
||||||
<td>{{ d.consist_item.all | length }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="d-grid gap-2 mb-1 d-md-block">
|
|
||||||
<a class="btn btn-sm btn-outline-primary" href="{{ d.get_absolute_url }}">Show all data</a>
|
|
||||||
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:consist_consist_change' d.pk %}">Edit</a>{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endblock %}
|
|
||||||
{% block pagination %}
|
{% block pagination %}
|
||||||
{% if data.has_other_pages %}
|
{% if data.has_other_pages %}
|
||||||
<nav aria-label="Page navigation example">
|
<nav aria-label="Page navigation example">
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
{% extends "cards.html" %}
|
{% extends "cards.html" %}
|
||||||
|
|
||||||
{% block pagination %}
|
{% block pagination %}
|
||||||
{% if data.has_other_pages %}
|
{% if data.has_other_pages %}
|
||||||
<nav aria-label="Page navigation example">
|
<nav aria-label="Page navigation example">
|
||||||
|
@@ -1,50 +1,7 @@
|
|||||||
{% extends "cards.html" %}
|
{% extends "cards.html" %}
|
||||||
|
|
||||||
{% block cards %}
|
|
||||||
{% for d in data %}
|
|
||||||
<div class="col">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text" style="position: relative;">
|
|
||||||
<strong>{{ d.name }}</strong>
|
|
||||||
</p>
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th colspan="2" scope="row">Manufacturer</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="table-group-divider">
|
|
||||||
{% if d.logo %}
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Logo</th>
|
|
||||||
<td><img style="max-height: 48px" src="{{ d.logo.url }}" /></td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
{% if d.website %}
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Website</th>
|
|
||||||
<td><a href="{{ d.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a></td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Category</th>
|
|
||||||
<td>{{ d.category | title }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="d-grid gap-2 mb-1 d-md-block">
|
|
||||||
<a class="btn btn-sm btn-outline-primary" href="{% url 'filtered' _filter="manufacturer" search=d.slug %}">Show all rolling stock</a>
|
|
||||||
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_manufacturer_change' d.pk %}">Edit</a>{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endblock %}
|
|
||||||
{% block pagination %}
|
{% block pagination %}
|
||||||
{% if data.has_other_pages %}
|
{% if data.has_other_pages %}
|
||||||
{% with data.0.category as c %}
|
{% with data.0.item.category as c %}
|
||||||
<nav aria-label="Page navigation example">
|
<nav aria-label="Page navigation example">
|
||||||
<ul class="pagination justify-content-center mt-4 mb-0">
|
<ul class="pagination justify-content-center mt-4 mb-0">
|
||||||
{% if data.has_previous %}
|
{% if data.has_previous %}
|
||||||
|
@@ -43,19 +43,17 @@
|
|||||||
<section class="py-4 text-start container">
|
<section class="py-4 text-start container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="mx-auto">
|
<div class="mx-auto">
|
||||||
<nav>
|
<nav class="nav nav-tabs flex-column flex-md-row mb-2" id="nav-tab">
|
||||||
<div class="nav nav-tabs" id="nav-tab" role="tablist">
|
|
||||||
<button class="nav-link active" id="nav-summary-tab" data-bs-toggle="tab" data-bs-target="#nav-summary" type="button" role="tab" aria-controls="nav-summary" aria-selected="true">Summary</button>
|
<button class="nav-link active" id="nav-summary-tab" data-bs-toggle="tab" data-bs-target="#nav-summary" type="button" role="tab" aria-controls="nav-summary" aria-selected="true">Summary</button>
|
||||||
<button class="nav-link" id="nav-model-tab" data-bs-toggle="tab" data-bs-target="#nav-model" type="button" role="tab" aria-controls="nav-model" aria-selected="false">Model data</button>
|
<button class="nav-link" id="nav-model-tab" data-bs-toggle="tab" data-bs-target="#nav-model" type="button" role="tab" aria-controls="nav-model" aria-selected="false">Model data</button>
|
||||||
<button class="nav-link" id="nav-class-tab" data-bs-toggle="tab" data-bs-target="#nav-class" type="button" role="tab" aria-controls="nav-class" aria-selected="false">Class data</button>
|
<button class="nav-link" id="nav-class-tab" data-bs-toggle="tab" data-bs-target="#nav-class" type="button" role="tab" aria-controls="nav-class" aria-selected="false">Class data</button>
|
||||||
{% if rolling_stock.decoder %}<button class="nav-link" id="nav-dcc-tab" data-bs-toggle="tab" data-bs-target="#nav-dcc" type="button" role="tab" aria-controls="nav-dcc" aria-selected="false">DCC</button>{% endif %}
|
{% if rolling_stock.decoder %}<button class="nav-link" id="nav-dcc-tab" data-bs-toggle="tab" data-bs-target="#nav-dcc" type="button" role="tab" aria-controls="nav-dcc" aria-selected="false">DCC</button>{% endif %}
|
||||||
{% if rolling_stock.document.count > 0 or rolling_stock.decoder.document.count > 0 %}<button class="nav-link" id="nav-documents-tab" data-bs-toggle="tab" data-bs-target="#nav-documents" type="button" role="tab" aria-controls="nav-documents" aria-selected="false">Documents</button>{% endif %}
|
{% if documents or decoder_documents %}<button class="nav-link" id="nav-documents-tab" data-bs-toggle="tab" data-bs-target="#nav-documents" type="button" role="tab" aria-controls="nav-documents" aria-selected="false">Documents</button>{% endif %}
|
||||||
{% if rolling_stock_journal.count > 0 %}<button class="nav-link" id="nav-journal-tab" data-bs-toggle="tab" data-bs-target="#nav-journal" type="button" role="tab" aria-controls="nav-journal" aria-selected="false">Journal</button>{% endif %}
|
{% if journal %}<button class="nav-link" id="nav-journal-tab" data-bs-toggle="tab" data-bs-target="#nav-journal" type="button" role="tab" aria-controls="nav-journal" aria-selected="false">Journal</button>{% endif %}
|
||||||
{% if rolling_stock.notes %}<button class="nav-link" id="nav-notes-tab" data-bs-toggle="tab" data-bs-target="#nav-notes" type="button" role="tab" aria-controls="nav-notes" aria-selected="false">Notes</button>{% endif %}
|
{% if rolling_stock.notes %}<button class="nav-link" id="nav-notes-tab" data-bs-toggle="tab" data-bs-target="#nav-notes" type="button" role="tab" aria-controls="nav-notes" aria-selected="false">Notes</button>{% endif %}
|
||||||
</div>
|
|
||||||
</nav>
|
</nav>
|
||||||
<div class="tab-content" id="nav-tabContent">
|
<div class="tab-content" id="nav-tabContent">
|
||||||
<div class="tab-pane fade show active" id="nav-summary" role="tabpanel" aria-labelledby="nav-summary-tab">
|
<div class="tab-pane show active" id="nav-summary" role="tabpanel" aria-labelledby="nav-summary-tab">
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -136,7 +134,7 @@
|
|||||||
</table>
|
</table>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane fade" id="nav-model" role="tabpanel" aria-labelledby="nav-model-tab">
|
<div class="tab-pane" id="nav-model" role="tabpanel" aria-labelledby="nav-model-tab">
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -172,7 +170,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% if rolling_stock_properties %}
|
{% if properties %}
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -180,7 +178,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="table-group-divider">
|
<tbody class="table-group-divider">
|
||||||
{% for p in rolling_stock_properties %}
|
{% for p in properties %}
|
||||||
<tr>
|
<tr>
|
||||||
<th class="w-33" scope="row">{{ p.property }}</th>
|
<th class="w-33" scope="row">{{ p.property }}</th>
|
||||||
<td>{{ p.value }}</td>
|
<td>{{ p.value }}</td>
|
||||||
@@ -190,7 +188,7 @@
|
|||||||
</table>
|
</table>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane fade" id="nav-class" role="tabpanel" aria-labelledby="nav-class-tab">
|
<div class="tab-pane" id="nav-class" role="tabpanel" aria-labelledby="nav-class-tab">
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -242,7 +240,7 @@
|
|||||||
</table>
|
</table>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane fade" id="nav-dcc" role="tabpanel" aria-labelledby="nav-dcc-tab">
|
<div class="tab-pane" id="nav-dcc" role="tabpanel" aria-labelledby="nav-dcc-tab">
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -277,8 +275,8 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane fade" id="nav-documents" role="tabpanel" aria-labelledby="nav-documents-tab">
|
<div class="tab-pane" id="nav-documents" role="tabpanel" aria-labelledby="nav-documents-tab">
|
||||||
{% if rolling_stock.document.count > 0 %}
|
{% if documents %}
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -286,7 +284,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="table-group-divider">
|
<tbody class="table-group-divider">
|
||||||
{% for d in rolling_stock.document.all %}
|
{% for d in documents.all %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="w-33">{{ d.description }}</td>
|
<td class="w-33">{{ d.description }}</td>
|
||||||
<td><a href="{{ d.file.url }}" target="_blank">{{ d.filename }}</a></td>
|
<td><a href="{{ d.file.url }}" target="_blank">{{ d.filename }}</a></td>
|
||||||
@@ -296,7 +294,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if rolling_stock.decoder.document.count > 0 %}
|
{% if decoder_documents %}
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -304,7 +302,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="table-group-divider">
|
<tbody class="table-group-divider">
|
||||||
{% for d in rolling_stock.decoder.document.all %}
|
{% for d in decoder_documents.all %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="w-33">{{ d.description }}</td>
|
<td class="w-33">{{ d.description }}</td>
|
||||||
<td><a href="{{ d.file.url }}" target="_blank">{{ d.filename }}</a></td>
|
<td><a href="{{ d.file.url }}" target="_blank">{{ d.filename }}</a></td>
|
||||||
@@ -315,7 +313,7 @@
|
|||||||
</table>
|
</table>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane fade" id="nav-journal" role="tabpanel" aria-labelledby="nav-journal-tab">
|
<div class="tab-pane" id="nav-journal" role="tabpanel" aria-labelledby="nav-journal-tab">
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -323,7 +321,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="table-group-divider">
|
<tbody class="table-group-divider">
|
||||||
{% for j in rolling_stock_journal %}
|
{% for j in journal %}
|
||||||
<tr>
|
<tr>
|
||||||
<th class="w-33" scope="row">{{ j.date }}</th>
|
<th class="w-33" scope="row">{{ j.date }}</th>
|
||||||
<td>{{ j.log | safe }}</a></td>
|
<td>{{ j.log | safe }}</a></td>
|
||||||
@@ -332,7 +330,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane fade" id="nav-notes" role="tabpanel" aria-labelledby="nav-notes-tab">
|
<div class="tab-pane" id="nav-notes" role="tabpanel" aria-labelledby="nav-notes-tab">
|
||||||
{{ rolling_stock.notes | safe }}
|
{{ rolling_stock.notes | safe }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,45 +1,4 @@
|
|||||||
{% extends "cards.html" %}
|
{% extends "cards.html" %}
|
||||||
|
|
||||||
{% block cards %}
|
|
||||||
{% for d in data %}
|
|
||||||
<div class="col">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text"><strong>{{ d }}</strong></p>
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th colspan="2" scope="row">Scale</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Name</th>
|
|
||||||
<td>{{ d.scale }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Ratio</th>
|
|
||||||
<td>{{ d.ratio }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Gauge</th>
|
|
||||||
<td>{{ d.gauge }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Tracks</th>
|
|
||||||
<td>{{ d.tracks }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="d-grid gap-2 mb-1 d-md-block">
|
|
||||||
<a class="btn btn-sm btn-outline-primary" href="{% url 'filtered' _filter="scale" search=d.slug %}">Show all rolling stock</a>
|
|
||||||
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_scale_change' d.pk %}">Edit</a>{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endblock %}
|
|
||||||
{% block pagination %}
|
{% block pagination %}
|
||||||
{% if data.has_other_pages %}
|
{% if data.has_other_pages %}
|
||||||
<nav aria-label="Page navigation example">
|
<nav aria-label="Page navigation example">
|
||||||
|
@@ -1,44 +1,11 @@
|
|||||||
{% extends "cards.html" %}
|
{% extends "cards.html" %}
|
||||||
|
|
||||||
{% block cards %}
|
|
||||||
{% for d in data %}
|
|
||||||
<div class="col">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text"><strong>{{ d }}</strong></p>
|
|
||||||
<table class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th colspan="2" scope="row">Type</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="table-group-divider">
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Type</th>
|
|
||||||
<td>{{ d.type }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th class="w-33" scope="row">Category</th>
|
|
||||||
<td>{{ d.category | title}}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="d-grid gap-2 mb-1 d-md-block">
|
|
||||||
<a class="btn btn-sm btn-outline-primary" href="{% url 'filtered' _filter="type" search=d.slug %}">Show all rolling stock</a>
|
|
||||||
{% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:metadata_scale_change' d.pk %}">Edit</a>{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endblock %}
|
|
||||||
{% block pagination %}
|
{% block pagination %}
|
||||||
{% if data.has_other_pages %}
|
{% if data.has_other_pages %}
|
||||||
<nav aria-label="Page navigation example">
|
<nav aria-label="Page navigation example">
|
||||||
<ul class="pagination justify-content-center mt-4 mb-0">
|
<ul class="pagination justify-content-center mt-4 mb-0">
|
||||||
{% if data.has_previous %}
|
{% if data.has_previous %}
|
||||||
<li class="page-item">
|
<li class="page-item">
|
||||||
<a class="page-link" href="{% url 'scales_pagination' page=data.previous_page_number %}#main-content" tabindex="-1">Previous</a>
|
<a class="page-link" href="{% url 'types_pagination' page=data.previous_page_number %}#main-content" tabindex="-1">Previous</a>
|
||||||
</li>
|
</li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li class="page-item disabled">
|
<li class="page-item disabled">
|
||||||
@@ -54,13 +21,13 @@
|
|||||||
{% if i == data.paginator.ELLIPSIS %}
|
{% if i == data.paginator.ELLIPSIS %}
|
||||||
<li class="page-item"><span class="page-link">{{ i }}</span></li>
|
<li class="page-item"><span class="page-link">{{ i }}</span></li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li class="page-item"><a class="page-link" href="{% url 'scales_pagination' page=i %}#main-content">{{ i }}</a></li>
|
<li class="page-item"><a class="page-link" href="{% url 'types_pagination' page=i %}#main-content">{{ i }}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if data.has_next %}
|
{% if data.has_next %}
|
||||||
<li class="page-item">
|
<li class="page-item">
|
||||||
<a class="page-link" href="{% url 'scales_pagination' page=data.next_page_number %}#main-content" tabindex="-1">Next</a>
|
<a class="page-link" href="{% url 'types_pagination' page=data.next_page_number %}#main-content" tabindex="-1">Next</a>
|
||||||
</li>
|
</li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li class="page-item disabled">
|
<li class="page-item disabled">
|
||||||
|
@@ -18,7 +18,7 @@ from portal.views import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", GetData.as_view(), name="index"),
|
path("", GetData.as_view(template="home.html"), name="index"),
|
||||||
path("roster", GetRoster.as_view(), name="roster"),
|
path("roster", GetRoster.as_view(), name="roster"),
|
||||||
path("roster/<int:page>", GetRoster.as_view(), name="roster_pagination"),
|
path("roster/<int:page>", GetRoster.as_view(), name="roster_pagination"),
|
||||||
path(
|
path(
|
||||||
@@ -26,9 +26,15 @@ urlpatterns = [
|
|||||||
GetFlatpage.as_view(),
|
GetFlatpage.as_view(),
|
||||||
name="flatpage",
|
name="flatpage",
|
||||||
),
|
),
|
||||||
path("consists", Consists.as_view(), name="consists"),
|
|
||||||
path(
|
path(
|
||||||
"consists/<int:page>", Consists.as_view(), name="consists_pagination"
|
"consists",
|
||||||
|
Consists.as_view(template="consists.html"),
|
||||||
|
name="consists"
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"consists/<int:page>",
|
||||||
|
Consists.as_view(template="consists.html"),
|
||||||
|
name="consists_pagination"
|
||||||
),
|
),
|
||||||
path("consist/<uuid:uuid>", GetConsist.as_view(), name="consist"),
|
path("consist/<uuid:uuid>", GetConsist.as_view(), name="consist"),
|
||||||
path(
|
path(
|
||||||
@@ -36,28 +42,56 @@ urlpatterns = [
|
|||||||
GetConsist.as_view(),
|
GetConsist.as_view(),
|
||||||
name="consist_pagination",
|
name="consist_pagination",
|
||||||
),
|
),
|
||||||
path("companies", Companies.as_view(), name="companies"),
|
path(
|
||||||
|
"companies",
|
||||||
|
Companies.as_view(template="companies.html"),
|
||||||
|
name="companies"
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"companies/<int:page>",
|
"companies/<int:page>",
|
||||||
Companies.as_view(),
|
Companies.as_view(template="companies.html"),
|
||||||
name="companies_pagination",
|
name="companies_pagination",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"manufacturers/<str:category>",
|
"manufacturers/<str:category>",
|
||||||
Manufacturers.as_view(),
|
Manufacturers.as_view(template="manufacturers.html"),
|
||||||
name="manufacturers"
|
name="manufacturers"
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"manufacturers/<str:category>/<int:page>",
|
"manufacturers/<str:category>/<int:page>",
|
||||||
Manufacturers.as_view(),
|
Manufacturers.as_view(template="manufacturers.html"),
|
||||||
name="manufacturers_pagination",
|
name="manufacturers_pagination",
|
||||||
),
|
),
|
||||||
path("scales", Scales.as_view(), name="scales"),
|
path(
|
||||||
path("scales/<int:page>", Types.as_view(), name="scales_pagination"),
|
"scales",
|
||||||
path("types", Types.as_view(), name="types"),
|
Scales.as_view(template="scales.html"),
|
||||||
path("types/<int:page>", Types.as_view(), name="types_pagination"),
|
name="scales"
|
||||||
path("bookshelf/books", Books.as_view(), name="books"),
|
),
|
||||||
path("bookshelf/books/<int:page>", Books.as_view(), name="books_pagination"),
|
path(
|
||||||
|
"scales/<int:page>",
|
||||||
|
Scales.as_view(template="scales.html"),
|
||||||
|
name="scales_pagination"
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"types",
|
||||||
|
Types.as_view(template="types.html"),
|
||||||
|
name="types"
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"types/<int:page>",
|
||||||
|
Types.as_view(template="types.html"),
|
||||||
|
name="types_pagination"
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"bookshelf/books",
|
||||||
|
Books.as_view(template="bookshelf/books.html"),
|
||||||
|
name="books"
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"bookshelf/books/<int:page>",
|
||||||
|
Books.as_view(template="bookshelf/books.html"),
|
||||||
|
name="books_pagination"
|
||||||
|
),
|
||||||
path("bookshelf/book/<uuid:uuid>", GetBook.as_view(), name="book"),
|
path("bookshelf/book/<uuid:uuid>", GetBook.as_view(), name="book"),
|
||||||
path(
|
path(
|
||||||
"search",
|
"search",
|
||||||
|
@@ -5,6 +5,7 @@ from urllib.parse import unquote
|
|||||||
|
|
||||||
from django.views import View
|
from django.views import View
|
||||||
from django.http import Http404, HttpResponseBadRequest
|
from django.http import Http404, HttpResponseBadRequest
|
||||||
|
from django.db.utils import OperationalError, ProgrammingError
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.shortcuts import render, get_object_or_404
|
from django.shortcuts import render, get_object_or_404
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
@@ -15,11 +16,17 @@ from portal.models import Flatpage
|
|||||||
from roster.models import RollingStock
|
from roster.models import RollingStock
|
||||||
from consist.models import Consist
|
from consist.models import Consist
|
||||||
from bookshelf.models import Book
|
from bookshelf.models import Book
|
||||||
from metadata.models import Company, Manufacturer, Scale, RollingStockType, Tag
|
from metadata.models import (
|
||||||
|
Company, Manufacturer, Scale, DecoderDocument, RollingStockType, Tag
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def order_by_fields():
|
def order_by_fields():
|
||||||
|
try:
|
||||||
order_by = get_site_conf().items_ordering
|
order_by = get_site_conf().items_ordering
|
||||||
|
except (OperationalError, ProgrammingError):
|
||||||
|
order_by = "type"
|
||||||
|
|
||||||
fields = [
|
fields = [
|
||||||
"rolling_class__type",
|
"rolling_class__type",
|
||||||
"rolling_class__company",
|
"rolling_class__company",
|
||||||
@@ -36,15 +43,22 @@ def order_by_fields():
|
|||||||
|
|
||||||
|
|
||||||
class GetData(View):
|
class GetData(View):
|
||||||
def __init__(self):
|
title = "Home"
|
||||||
self.title = "Home"
|
template = "roster.html"
|
||||||
self.template = "home.html"
|
item_type = "rolling_stock"
|
||||||
self.data = RollingStock.objects.order_by(*order_by_fields())
|
queryset = RollingStock.objects.order_by(*order_by_fields())
|
||||||
|
|
||||||
def get(self, request, page=1):
|
def get(self, request, page=1):
|
||||||
site_conf = get_site_conf()
|
site_conf = get_site_conf()
|
||||||
|
|
||||||
paginator = Paginator(self.data, site_conf.items_per_page)
|
data = []
|
||||||
|
for item in self.queryset:
|
||||||
|
data.append({
|
||||||
|
"type": self.item_type,
|
||||||
|
"item": item
|
||||||
|
})
|
||||||
|
|
||||||
|
paginator = Paginator(data, site_conf.items_per_page)
|
||||||
data = paginator.get_page(page)
|
data = paginator.get_page(page)
|
||||||
page_range = paginator.get_elided_page_range(
|
page_range = paginator.get_elided_page_range(
|
||||||
data.number, on_each_side=2, on_ends=1
|
data.number, on_each_side=2, on_ends=1
|
||||||
@@ -55,6 +69,7 @@ class GetData(View):
|
|||||||
self.template,
|
self.template,
|
||||||
{
|
{
|
||||||
"title": self.title,
|
"title": self.title,
|
||||||
|
"type": self.item_type,
|
||||||
"data": data,
|
"data": data,
|
||||||
"matches": paginator.count,
|
"matches": paginator.count,
|
||||||
"page_range": page_range,
|
"page_range": page_range,
|
||||||
@@ -63,10 +78,9 @@ class GetData(View):
|
|||||||
|
|
||||||
|
|
||||||
class GetRoster(GetData):
|
class GetRoster(GetData):
|
||||||
def __init__(self):
|
title = "Rolling stock"
|
||||||
self.title = "Rolling stock"
|
item_type = "rolling_stock"
|
||||||
self.template = "roster.html"
|
queryset = RollingStock.objects.order_by(*order_by_fields())
|
||||||
self.data = RollingStock.objects.order_by(*order_by_fields())
|
|
||||||
|
|
||||||
|
|
||||||
class SearchRoster(View):
|
class SearchRoster(View):
|
||||||
@@ -111,20 +125,50 @@ class SearchRoster(View):
|
|||||||
else:
|
else:
|
||||||
raise Http404
|
raise Http404
|
||||||
|
|
||||||
|
# FIXME duplicated code!
|
||||||
|
data = []
|
||||||
rolling_stock = (
|
rolling_stock = (
|
||||||
RollingStock.objects.filter(query)
|
RollingStock.objects.filter(query)
|
||||||
.distinct()
|
.distinct()
|
||||||
.order_by(*order_by_fields())
|
.order_by(*order_by_fields())
|
||||||
)
|
)
|
||||||
matches = rolling_stock.count()
|
for item in rolling_stock:
|
||||||
|
data.append({
|
||||||
|
"type": "rolling_stock",
|
||||||
|
"item": item
|
||||||
|
})
|
||||||
|
if _filter is None:
|
||||||
|
consists = (
|
||||||
|
Consist.objects.filter(
|
||||||
|
Q(
|
||||||
|
Q(identifier__icontains=search)
|
||||||
|
| Q(company__name__icontains=search)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.distinct()
|
||||||
|
)
|
||||||
|
for item in consists:
|
||||||
|
data.append({
|
||||||
|
"type": "consist",
|
||||||
|
"item": item
|
||||||
|
})
|
||||||
|
books = (
|
||||||
|
Book.objects.filter(title__icontains=search)
|
||||||
|
.distinct()
|
||||||
|
)
|
||||||
|
for item in books:
|
||||||
|
data.append({
|
||||||
|
"type": "book",
|
||||||
|
"item": item
|
||||||
|
})
|
||||||
|
|
||||||
paginator = Paginator(rolling_stock, site_conf.items_per_page)
|
paginator = Paginator(data, site_conf.items_per_page)
|
||||||
rolling_stock = paginator.get_page(page)
|
data = paginator.get_page(page)
|
||||||
page_range = paginator.get_elided_page_range(
|
page_range = paginator.get_elided_page_range(
|
||||||
rolling_stock.number, on_each_side=2, on_ends=1
|
data.number, on_each_side=2, on_ends=1
|
||||||
)
|
)
|
||||||
|
|
||||||
return rolling_stock, matches, page_range
|
return data, paginator.count, page_range
|
||||||
|
|
||||||
def split_search(self, search):
|
def split_search(self, search):
|
||||||
search = search.strip().split(":")
|
search = search.strip().split(":")
|
||||||
@@ -149,7 +193,7 @@ class SearchRoster(View):
|
|||||||
encoded_search = base64.b64encode(
|
encoded_search = base64.b64encode(
|
||||||
search.encode()).decode()
|
search.encode()).decode()
|
||||||
_filter, keyword = self.split_search(search)
|
_filter, keyword = self.split_search(search)
|
||||||
rolling_stock, matches, page_range = self.run_search(
|
data, matches, page_range = self.run_search(
|
||||||
request, keyword, _filter, page
|
request, keyword, _filter, page
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -160,8 +204,8 @@ class SearchRoster(View):
|
|||||||
"title": "Search: \"{}\"".format(search),
|
"title": "Search: \"{}\"".format(search),
|
||||||
"search": search,
|
"search": search,
|
||||||
"encoded_search": encoded_search,
|
"encoded_search": encoded_search,
|
||||||
|
"data": data,
|
||||||
"matches": matches,
|
"matches": matches,
|
||||||
"data": rolling_stock,
|
|
||||||
"page_range": page_range,
|
"page_range": page_range,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -200,15 +244,41 @@ class GetRosterFiltered(View):
|
|||||||
.distinct()
|
.distinct()
|
||||||
.order_by(*order_by_fields())
|
.order_by(*order_by_fields())
|
||||||
)
|
)
|
||||||
matches = rolling_stock.count()
|
|
||||||
|
|
||||||
paginator = Paginator(rolling_stock, site_conf.items_per_page)
|
data = []
|
||||||
rolling_stock = paginator.get_page(page)
|
for item in rolling_stock:
|
||||||
|
data.append({
|
||||||
|
"type": "rolling_stock",
|
||||||
|
"item": item
|
||||||
|
})
|
||||||
|
|
||||||
|
if _filter == "tag":
|
||||||
|
consists = (
|
||||||
|
Consist.objects.filter(query)
|
||||||
|
.distinct()
|
||||||
|
)
|
||||||
|
for item in consists:
|
||||||
|
data.append({
|
||||||
|
"type": "consist",
|
||||||
|
"item": item
|
||||||
|
})
|
||||||
|
books = (
|
||||||
|
Book.objects.filter(query)
|
||||||
|
.distinct()
|
||||||
|
)
|
||||||
|
for item in books:
|
||||||
|
data.append({
|
||||||
|
"type": "book",
|
||||||
|
"item": item
|
||||||
|
})
|
||||||
|
|
||||||
|
paginator = Paginator(data, site_conf.items_per_page)
|
||||||
|
data = paginator.get_page(page)
|
||||||
page_range = paginator.get_elided_page_range(
|
page_range = paginator.get_elided_page_range(
|
||||||
rolling_stock.number, on_each_side=2, on_ends=1
|
data.number, on_each_side=2, on_ends=1
|
||||||
)
|
)
|
||||||
|
|
||||||
return rolling_stock, title, matches, page_range
|
return data, title, paginator.count, page_range
|
||||||
|
|
||||||
def get(self, request, search, _filter, page=1):
|
def get(self, request, search, _filter, page=1):
|
||||||
data, title, matches, page_range = self.run_filter(
|
data, title, matches, page_range = self.run_filter(
|
||||||
@@ -223,8 +293,8 @@ class GetRosterFiltered(View):
|
|||||||
_filter.capitalize(), title),
|
_filter.capitalize(), title),
|
||||||
"search": search,
|
"search": search,
|
||||||
"filter": _filter,
|
"filter": _filter,
|
||||||
"matches": matches,
|
|
||||||
"data": data,
|
"data": data,
|
||||||
|
"matches": matches,
|
||||||
"page_range": page_range,
|
"page_range": page_range,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -237,23 +307,28 @@ class GetRollingStock(View):
|
|||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
raise Http404
|
raise Http404
|
||||||
|
|
||||||
class_properties = (
|
# FIXME there's likely a better and more efficient way of doing this
|
||||||
rolling_stock.rolling_class.property.all()
|
# but keeping KISS for now
|
||||||
if request.user.is_authenticated
|
decoder_documents = []
|
||||||
else rolling_stock.rolling_class.property.filter(
|
if request.user.is_authenticated:
|
||||||
|
class_properties = rolling_stock.rolling_class.property.all()
|
||||||
|
properties = rolling_stock.property.all()
|
||||||
|
documents = rolling_stock.document.all()
|
||||||
|
journal = rolling_stock.journal.all()
|
||||||
|
if rolling_stock.decoder:
|
||||||
|
decoder_documents = rolling_stock.decoder.document.all()
|
||||||
|
else:
|
||||||
|
class_properties = rolling_stock.rolling_class.property.filter(
|
||||||
property__private=False
|
property__private=False
|
||||||
)
|
)
|
||||||
|
properties = rolling_stock.property.filter(
|
||||||
|
property__private=False
|
||||||
)
|
)
|
||||||
rolling_stock_properties = (
|
documents = rolling_stock.document.filter(private=False)
|
||||||
rolling_stock.property.all()
|
journal = rolling_stock.journal.filter(private=False)
|
||||||
if request.user.is_authenticated
|
if rolling_stock.decoder:
|
||||||
else rolling_stock.property.filter(property__private=False)
|
decoder_documents = rolling_stock.decoder.document.filter(
|
||||||
)
|
private=False
|
||||||
|
|
||||||
rolling_stock_journal = (
|
|
||||||
rolling_stock.journal.all()
|
|
||||||
if request.user.is_authenticated
|
|
||||||
else rolling_stock.journal.filter(private=False)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
@@ -263,17 +338,18 @@ class GetRollingStock(View):
|
|||||||
"title": rolling_stock,
|
"title": rolling_stock,
|
||||||
"rolling_stock": rolling_stock,
|
"rolling_stock": rolling_stock,
|
||||||
"class_properties": class_properties,
|
"class_properties": class_properties,
|
||||||
"rolling_stock_properties": rolling_stock_properties,
|
"properties": properties,
|
||||||
"rolling_stock_journal": rolling_stock_journal,
|
"decoder_documents": decoder_documents,
|
||||||
|
"documents": documents,
|
||||||
|
"journal": journal,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Consists(GetData):
|
class Consists(GetData):
|
||||||
def __init__(self):
|
title = "Consists"
|
||||||
self.title = "Consists"
|
item_type = "consist"
|
||||||
self.template = "consists.html"
|
queryset = Consist.objects.all()
|
||||||
self.data = Consist.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
class GetConsist(View):
|
class GetConsist(View):
|
||||||
@@ -283,15 +359,15 @@ class GetConsist(View):
|
|||||||
consist = Consist.objects.get(uuid=uuid)
|
consist = Consist.objects.get(uuid=uuid)
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
raise Http404
|
raise Http404
|
||||||
rolling_stock = [
|
data = [{
|
||||||
RollingStock.objects.get(uuid=r.rolling_stock_id) for r in
|
"type": "rolling_stock",
|
||||||
consist.consist_item.all()
|
"item": RollingStock.objects.get(uuid=r.rolling_stock_id)
|
||||||
]
|
} for r in consist.consist_item.all()]
|
||||||
|
|
||||||
paginator = Paginator(rolling_stock, site_conf.items_per_page)
|
paginator = Paginator(data, site_conf.items_per_page)
|
||||||
rolling_stock = paginator.get_page(page)
|
data = paginator.get_page(page)
|
||||||
page_range = paginator.get_elided_page_range(
|
page_range = paginator.get_elided_page_range(
|
||||||
rolling_stock.number, on_each_side=2, on_ends=1
|
data.number, on_each_side=2, on_ends=1
|
||||||
)
|
)
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
@@ -300,52 +376,47 @@ class GetConsist(View):
|
|||||||
{
|
{
|
||||||
"title": consist,
|
"title": consist,
|
||||||
"consist": consist,
|
"consist": consist,
|
||||||
"data": rolling_stock,
|
"data": data,
|
||||||
"page_range": page_range,
|
"page_range": page_range,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Manufacturers(GetData):
|
class Manufacturers(GetData):
|
||||||
def __init__(self):
|
title = "Manufacturers"
|
||||||
self.title = "Manufacturers"
|
item_type = "manufacturer"
|
||||||
self.template = "manufacturers.html"
|
queryset = None # Set via method get
|
||||||
self.data = None # Set via method get
|
|
||||||
|
|
||||||
# overload get method to filter by category
|
# overload get method to filter by category
|
||||||
def get(self, request, category, page=1):
|
def get(self, request, category, page=1):
|
||||||
if category not in ("real", "model"):
|
if category not in ("real", "model"):
|
||||||
raise Http404
|
raise Http404
|
||||||
self.data = Manufacturer.objects.filter(category=category)
|
self.queryset = Manufacturer.objects.filter(category=category)
|
||||||
return super().get(request, page)
|
return super().get(request, page)
|
||||||
|
|
||||||
|
|
||||||
class Companies(GetData):
|
class Companies(GetData):
|
||||||
def __init__(self):
|
title = "Companies"
|
||||||
self.title = "Companies"
|
item_type = "company"
|
||||||
self.template = "companies.html"
|
queryset = Company.objects.all()
|
||||||
self.data = Company.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
class Scales(GetData):
|
class Scales(GetData):
|
||||||
def __init__(self):
|
title = "Scales"
|
||||||
self.title = "Scales"
|
item_type = "scale"
|
||||||
self.template = "scales.html"
|
queryset = Scale.objects.all()
|
||||||
self.data = Scale.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
class Types(GetData):
|
class Types(GetData):
|
||||||
def __init__(self):
|
title = "Types"
|
||||||
self.title = "Types"
|
item_type = "rolling_stock_type"
|
||||||
self.template = "types.html"
|
queryset = RollingStockType.objects.all()
|
||||||
self.data = RollingStockType.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
class Books(GetData):
|
class Books(GetData):
|
||||||
def __init__(self):
|
title = "Books"
|
||||||
self.title = "Books"
|
item_type = "book"
|
||||||
self.template = "bookshelf/books.html"
|
queryset = Book.objects.all()
|
||||||
self.data = Book.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
class GetBook(View):
|
class GetBook(View):
|
||||||
@@ -374,12 +445,13 @@ class GetBook(View):
|
|||||||
class GetFlatpage(View):
|
class GetFlatpage(View):
|
||||||
def get(self, request, flatpage):
|
def get(self, request, flatpage):
|
||||||
try:
|
try:
|
||||||
flatpage = Flatpage.objects.get(
|
flatpage = Flatpage.objects.get(path=flatpage)
|
||||||
Q(Q(path=flatpage) & Q(published=True))
|
|
||||||
)
|
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
raise Http404
|
raise Http404
|
||||||
|
|
||||||
|
if not request.user.is_authenticated:
|
||||||
|
flatpage = flatpage.filter(published=False)
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"flatpages/flatpage.html",
|
"flatpages/flatpage.html",
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
from ram.utils import git_suffix
|
from ram.utils import git_suffix
|
||||||
|
|
||||||
__version__ = "0.5.0"
|
__version__ = "0.6.5"
|
||||||
__version__ += git_suffix(__file__)
|
__version__ += git_suffix(__file__)
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.db.utils import OperationalError
|
from django.db.utils import OperationalError, ProgrammingError
|
||||||
from portal.utils import get_site_conf
|
from portal.utils import get_site_conf
|
||||||
|
|
||||||
try:
|
try:
|
||||||
site_name = get_site_conf().site_name
|
site_name = get_site_conf().site_name
|
||||||
except OperationalError:
|
except (OperationalError, ProgrammingError):
|
||||||
site_name = "Train Assets Manager"
|
site_name = "Train Assets Manager"
|
||||||
|
|
||||||
admin.site.site_header = site_name
|
admin.site.site_header = site_name
|
||||||
|
@@ -14,6 +14,7 @@ class Document(models.Model):
|
|||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
)
|
)
|
||||||
|
private = models.BooleanField(default=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
@@ -64,6 +64,7 @@ class RollingStockDocumentAdmin(admin.ModelAdmin):
|
|||||||
"__str__",
|
"__str__",
|
||||||
"rolling_stock",
|
"rolling_stock",
|
||||||
"description",
|
"description",
|
||||||
|
"private",
|
||||||
"download",
|
"download",
|
||||||
)
|
)
|
||||||
search_fields = (
|
search_fields = (
|
||||||
|
18
ram/roster/migrations/0019_rollingstockdocument_private.py
Normal file
18
ram/roster/migrations/0019_rollingstockdocument_private.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.2.5 on 2023-10-06 19:48
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("roster", "0018_rename_sku_rollingstock_item_number"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="rollingstockdocument",
|
||||||
|
name="private",
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
Reference in New Issue
Block a user