18 Commits

20 changed files with 521 additions and 48 deletions

View File

@@ -2,22 +2,25 @@
[![Django CI](https://github.com/daniviga/django-rma/actions/workflows/django.yml/badge.svg)](https://github.com/daniviga/django-rma/actions/workflows/django.yml) [![Django CI](https://github.com/daniviga/django-rma/actions/workflows/django.yml/badge.svg)](https://github.com/daniviga/django-rma/actions/workflows/django.yml)
![image](https://user-images.githubusercontent.com/1818657/175789825-9a03f0ff-a95e-42a2-9611-e14d2817e22f.png)
A `jff` (just for fun) project that aims to create a A `jff` (just for fun) project that aims to create a
model railroad assets manager that allows to: model railroad assets manager that allows to:
- Create a database of assets (model trains) and consits with their metadata - Create a database of assets (model trains) and consists with their metadata
- Manage the database via a simple but rationale backoffice - Manage the database via a simple but rationale backoffice
- Expose main data via an HTML interface to show how beautiful is your collection - Expose main data via an HTML interface to show how beautiful is your collection
to the outside world to the outside world
- Act as a DCC++ EX REST API gateway to control assets remotely via DCC. - Act as a DCC++ EX REST API gateway to control assets remotely via DCC.
By anyone, if you'd like (really?). By anyone, if you'd like (seriously?).
## Preface ## Preface
Project is intended to have fun only and it has been developed with a **This project is work in progress**. It is intended for fun only and
commitment of few minutes a day; it lacks any kind of documentation, code it has been developed with a commitment of few minutes a day;
review, architectural review, security assesment, pentest, ISO certification, it lacks any kind of documentation, code review, architectural review,
etc. security assesment, pentest, ISO certification, etc.
This project probably doesn't match you needs nor expectations. Be aware. This project probably doesn't match you needs nor expectations. Be aware.
@@ -30,20 +33,20 @@ Project is based on the following technologies and components:
- [Django](https://www.djangoproject.com/): *the* web framework - [Django](https://www.djangoproject.com/): *the* web framework
- [Django REST](https://www.django-rest-framework.org/): API for the lazy - [Django REST](https://www.django-rest-framework.org/): API for the lazy
- [Bootstrap](https://getbootstrap.com/): for the web frontend - [Bootstrap](https://getbootstrap.com/): for the web frontend
- [Arduino](https://arduino.cc): DCC hardware - [Arduino](https://arduino.cc): DCC hardware; you must get one, really
- [DCC++ EX Command Station](https://dcc-ex.com/): DCC firmware; an amazing project - [DCC++ EX Command Station](https://dcc-ex.com/): DCC firmware; an amazing project
- [DCC++ EX WebThrottle](https://github.com/DCC-EX/WebThrottle-EX): a slighly modified version of the DCC++ EX web throttle - [DCC++ EX WebThrottle](https://github.com/DCC-EX/WebThrottle-EX): the DCC++ EX web throttle, a slightly modified version
It has been developed with: It has been developed with:
- [vim](https://www.vim.org/): because it rocks - [vim](https://www.vim.org/): because it rocks
- [arduino-cli](https://github.com/arduino/arduino-cli/): a mouse? What the hack? - [arduino-cli](https://github.com/arduino/arduino-cli/): a mouse? What the heck?
- [vim-arduino](https://github.com/stevearc/vim-arduino): another IDE? No thanks - [vim-arduino](https://github.com/stevearc/vim-arduino): another IDE? No thanks
- [podman](https://podman.io/): because containers are fancy - [podman](https://podman.io/): because containers are fancy
- [QEMU (avr)](https://qemu-project.gitlab.io/qemu/system/target-avr.html): QEMU can even make toast! - [QEMU (avr)](https://qemu-project.gitlab.io/qemu/system/target-avr.html): QEMU can even make toast!
## Requirments ## Requirements
- Python 3.8+ - Python 3.8+
- A USB port when running Arduino hardware (and adaptors if you have a Mac) - A USB port when running Arduino hardware (and adaptors if you have a Mac)
@@ -132,10 +135,30 @@ $ podman run --init --cpus 0.1 -d -p 2560:2560 dcc/net-to-serial:sim
To be continued ... To be continued ...
## Screenshots
### Frontend
![image](https://user-images.githubusercontent.com/1818657/175789897-9ec4a9bb-9c65-48ef-9b57-ae94e094e6a7.png)
---
![image](https://user-images.githubusercontent.com/1818657/175789901-ef50acd7-8c05-4788-92a2-1bb1280d598c.png)
---
![image](https://user-images.githubusercontent.com/1818657/175790004-18926d23-28f9-45bb-b279-6c26575ae3a5.png)
---
![image](https://user-images.githubusercontent.com/1818657/175790008-62eea2cc-1c41-42df-9026-4cf6e8ef712c.png)
### Backoffice
![image](https://user-images.githubusercontent.com/1818657/175789937-3e4970a2-b37d-44c3-8605-62dabe209c65.png)
---
![image](https://user-images.githubusercontent.com/1818657/175789946-d7ce882c-1ba6-49b2-8e0a-1144e5c6bc35.png)
---
![image](https://user-images.githubusercontent.com/1818657/175789954-0735a4ea-bcaf-4a45-adbc-64105091b051.png)
### Rest API
![image](https://user-images.githubusercontent.com/1818657/175790064-23ec038e-e8bf-4c39-964c-3118e4295b59.png)

View File

@@ -1,6 +1,6 @@
# AVR Simulator # AVR Simulator
`qemu-system-avr` tries to use all the CPU cicles (leaving a CPU core stuck at 100%. Limit CPU core usage to 10%. It may be adjusted on slower machines. `qemu-system-avr` tries to use all the CPU cicles (leaving a CPU core stuck at 100%; limit CPU core usage to 10% via `--cpus 0.1`. It can be adjusted on slower machines.
```bash ```bash
$ podman build -t dcc/net-to-serial:sim . $ podman build -t dcc/net-to-serial:sim .

View File

@@ -0,0 +1,17 @@
# Generated by Django 4.0.6 on 2022-07-10 13:19
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('consist', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='consist',
options={'ordering': ['creation_time']},
),
]

View File

@@ -27,6 +27,9 @@ class Consist(models.Model):
def get_absolute_url(self): def get_absolute_url(self):
return reverse("consist", kwargs={"uuid": self.uuid}) return reverse("consist", kwargs={"uuid": self.uuid})
class Meta:
ordering = ["creation_time"]
class ConsistItem(models.Model): class ConsistItem(models.Model):
consist = models.ForeignKey( consist = models.ForeignKey(

View File

@@ -0,0 +1,19 @@
# Generated by Django 4.0.6 on 2022-07-10 21:46
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('metadata', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='decoder',
name='manufacturer',
field=models.ForeignKey(limit_choices_to={'category': 'model'}, on_delete=django.db.models.deletion.CASCADE, to='metadata.manufacturer'),
),
]

View File

@@ -59,7 +59,11 @@ class Company(models.Model):
class Decoder(models.Model): class Decoder(models.Model):
name = models.CharField(max_length=128, unique=True) name = models.CharField(max_length=128, unique=True)
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE) manufacturer = models.ForeignKey(
Manufacturer,
on_delete=models.CASCADE,
limit_choices_to={"category": "model"}
)
version = models.CharField(max_length=64, blank=True) version = models.CharField(max_length=64, blank=True)
interface = models.PositiveSmallIntegerField( interface = models.PositiveSmallIntegerField(
choices=settings.DECODER_INTERFACES, null=True, blank=True choices=settings.DECODER_INTERFACES, null=True, blank=True

View File

@@ -34,7 +34,7 @@
<header> <header>
<div class="navbar navbar-light bg-light shadow-sm"> <div class="navbar navbar-light bg-light shadow-sm">
<div class="container"> <div class="container">
<a href="/" class="navbar-brand d-flex align-items-center"> <a href="{% url 'index' %}" class="navbar-brand d-flex align-items-center">
<svg class="me-2" width="26" height="16" enable-background="new 0 0 26 26" version="1" viewBox="0 0 26 16" xmlns="http://www.w3.org/2000/svg"> <svg class="me-2" width="26" height="16" enable-background="new 0 0 26 26" version="1" viewBox="0 0 26 16" xmlns="http://www.w3.org/2000/svg">
<path d="m2.8125 0.0010991a1.0001 1.0001 0 0 0-0.8125 1c0 0.55455-0.44545 1-1 1a1.0001 1.0001 0 0 0-1 1v10a1.0001 1.0001 0 0 0 1 1c0.55455 0 1 0.44546 1 1a1.0001 1.0001 0 0 0 1 1h20a1.0001 1.0001 0 0 0 1-1c0-0.55454 0.44546-1 1-1a1.0001 1.0001 0 0 0 1-1v-10a1.0001 1.0001 0 0 0-1-1c-0.55454 0-1-0.44545-1-1a1.0001 1.0001 0 0 0-1-1h-20a1.0001 1.0001 0 0 0-0.09375 0 1.0001 1.0001 0 0 0-0.09375 0zm0.78125 2h14.406v1h2v-1h2.4062c0.30628 0.76906 0.82469 1.2875 1.5938 1.5938v8.8125c-0.76906 0.30628-1.2875 0.82469-1.5938 1.5938h-2.4062v-1h-2v1h-14.406c-0.30628-0.76906-0.82469-1.2875-1.5938-1.5938v-8.8125c0.76906-0.30628 1.2875-0.82469 1.5938-1.5938zm14.406 2v2h2v-2zm0 3v2h2v-2zm0 3v2h2v-2z" enable-background="accumulate" fill="#000" overflow="visible" stroke-width="2" style="text-indent:0;text-transform:none"/> <path d="m2.8125 0.0010991a1.0001 1.0001 0 0 0-0.8125 1c0 0.55455-0.44545 1-1 1a1.0001 1.0001 0 0 0-1 1v10a1.0001 1.0001 0 0 0 1 1c0.55455 0 1 0.44546 1 1a1.0001 1.0001 0 0 0 1 1h20a1.0001 1.0001 0 0 0 1-1c0-0.55454 0.44546-1 1-1a1.0001 1.0001 0 0 0 1-1v-10a1.0001 1.0001 0 0 0-1-1c-0.55454 0-1-0.44545-1-1a1.0001 1.0001 0 0 0-1-1h-20a1.0001 1.0001 0 0 0-0.09375 0 1.0001 1.0001 0 0 0-0.09375 0zm0.78125 2h14.406v1h2v-1h2.4062c0.30628 0.76906 0.82469 1.2875 1.5938 1.5938v8.8125c-0.76906 0.30628-1.2875 0.82469-1.5938 1.5938h-2.4062v-1h-2v1h-14.406c-0.30628-0.76906-0.82469-1.2875-1.5938-1.5938v-8.8125c0.76906-0.30628 1.2875-0.82469 1.5938-1.5938zm14.406 2v2h2v-2zm0 3v2h2v-2zm0 3v2h2v-2z" enable-background="accumulate" fill="#000" overflow="visible" stroke-width="2" style="text-indent:0;text-transform:none"/>
</svg> </svg>
@@ -48,14 +48,14 @@
<div class="container py-2"> <div class="container py-2">
<nav class="navbar navbar-expand-lg navbar-light"> <nav class="navbar navbar-expand-lg navbar-light">
<div class="container-fluid g-0"> <div class="container-fluid g-0">
<a class="navbar-brand" href="/">Home</a> <a class="navbar-brand" href="{% url 'index' %}">Home</a>
<div class="collapse navbar-collapse" id="navbarSupportedContent"> <div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0"> <ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/portal">Roster</a> <a class="nav-link" href="{% url 'index' %}">Roster</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/portal/consist">Consists</a> <a class="nav-link" href="{% url 'consists' %}">Consists</a>
</li> </li>
</ul> </ul>
{% include 'includes/search.html' %} {% include 'includes/search.html' %}
@@ -79,7 +79,7 @@
<div class="col"> <div class="col">
<div class="card shadow-sm"> <div class="card shadow-sm">
{% for i in r.image.all %} {% for i in r.image.all %}
{% if i.is_thumbnail %}<a href="/portal/{{ r.uuid }}"><img src="{{ i.image.url }}" alt="Card image cap"></a>{% endif %} {% if i.is_thumbnail %}<a href="{{r.get_absolute_url}}"><img src="{{ i.image.url }}" alt="Card image cap"></a>{% endif %}
{% endfor %} {% endfor %}
<div class="card-body"> <div class="card-body">
<p class="card-text"><strong>{{ r }}</strong></p> <p class="card-text"><strong>{{ r }}</strong></p>
@@ -151,7 +151,7 @@
</table> </table>
{% endif %} {% endif %}
<div class="btn-group mb-4"> <div class="btn-group mb-4">
<a class="btn btn-sm btn-outline-primary" href="/portal/{{ r.uuid }}">Show all data</a> <a class="btn btn-sm btn-outline-primary" href="{{r.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' r.pk %}">Edit</a>{% endif %} {% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:roster_rollingstock_change' r.pk %}">Edit</a>{% endif %}
</div> </div>
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">

View File

@@ -16,7 +16,7 @@
<div class="col"> <div class="col">
<div class="card shadow-sm"> <div class="card shadow-sm">
{% for i in r.rolling_stock.image.all %} {% for i in r.rolling_stock.image.all %}
{% if i.is_thumbnail %}<a href="/portal/{{ r.rolling_stock.uuid }}"><img src="{{ i.image.url }}" alt="Card image cap"></a>{% endif %} {% if i.is_thumbnail %}<a href="{{r.rolling_stock.get_absolute_url}}"><img src="{{ i.image.url }}" alt="Card image cap"></a>{% endif %}
{% endfor %} {% endfor %}
<div class="card-body"> <div class="card-body">
<p class="card-text"><strong>{{ r }}</strong></p> <p class="card-text"><strong>{{ r }}</strong></p>
@@ -88,7 +88,7 @@
</table> </table>
{% endif %} {% endif %}
<div class="btn-group mb-4"> <div class="btn-group mb-4">
<a class="btn btn-sm btn-outline-primary" href="/portal/{{ r.rolling_stock.uuid }}">Show all data</a> <a class="btn btn-sm btn-outline-primary" href="{{r.rolling_stock.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' r.rolling_stock.pk %}">Edit</a>{% endif %} {% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{% url 'admin:roster_rollingstock_change' r.rolling_stock.pk %}">Edit</a>{% endif %}
</div> </div>
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
@@ -105,7 +105,7 @@
<ul class="pagination justify-content-center mt-4"> <ul class="pagination justify-content-center mt-4">
{% if rolling_stock.has_previous %} {% if rolling_stock.has_previous %}
<li class="page-item"> <li class="page-item">
<a class="page-link" href="/portal/consist/{{ consist.uuid }}/{{ rolling_stock.previous_page_number }}#rolling_stock" tabindex="-1">Previous</a> <a class="page-link" href="{% url 'consist_pagination' uuid=consist.uuid page=rolling_stock.previous_page_number %}#rolling-stock" tabindex="-1">Previous</a>
</li> </li>
{% else %} {% else %}
<li class="page-item disabled"> <li class="page-item disabled">
@@ -118,12 +118,12 @@
<span class="page-link">{{ i }}</span></span> <span class="page-link">{{ i }}</span></span>
</li> </li>
{% else %} {% else %}
<li class="page-item"><a class="page-link" href="/portal/consist/{{ consist.uuid }}/{{ i }}#rolling-stock">{{ i }}</a></li> <li class="page-item"><a class="page-link" href="{% url 'consist_pagination' uuid=consist.uuid page=i %}#rolling-stock">{{ i }}</a></li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% if rolling_stock.has_next %} {% if rolling_stock.has_next %}
<li class="page-item"> <li class="page-item">
<a class="page-link" href="/portal/consist/{{ consist.uuid }}/{{ rolling_stock.next_page_number }}#rolling-stock" tabindex="-1">Next</a> <a class="page-link" href="{% url 'consist_pagination' uuid=consist.uuid page=rolling_stock.next_page_number %}#rolling-stock" tabindex="-1">Next</a>
</li> </li>
{% else %} {% else %}
<li class="page-item disabled"> <li class="page-item disabled">

View File

@@ -45,7 +45,7 @@
</tbody> </tbody>
</table> </table>
<div class="btn-group mb-4"> <div class="btn-group mb-4">
<a class="btn btn-sm btn-outline-primary" href="/portal/consist/{{ c.uuid }}">Show all data</a> <a class="btn btn-sm btn-outline-primary" href="{{ c.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' c.pk #}">Edit</a>{% endif %} {% if request.user.is_staff %}<a class="btn btn-sm btn-outline-danger" href="{# url 'admin:consist_consist_change' c.pk #}">Edit</a>{% endif %}
</div> </div>
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
@@ -57,30 +57,30 @@
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}
{% block pagination %} {% block pagination %}
{% if rolling_stock.has_other_pages %} {% if consist.has_other_pages %}
<nav aria-label="Page navigation example"> <nav aria-label="Page navigation example">
<ul class="pagination justify-content-center mt-4"> <ul class="pagination justify-content-center mt-4">
{% if rolling_stock.has_previous %} {% if consist.has_previous %}
<li class="page-item"> <li class="page-item">
<a class="page-link" href="/portal/consist/{{ consist.uuid }}/{{ rolling_stock.previous_page_number }}#rolling_stock" tabindex="-1">Previous</a> <a class="page-link" href="{% url 'consists_pagination' page=consist.previous_page_number %}#rolling-stock" tabindex="-1">Previous</a>
</li> </li>
{% else %} {% else %}
<li class="page-item disabled"> <li class="page-item disabled">
<span class="page-link">Previous</span> <span class="page-link">Previous</span>
</li> </li>
{% endif %} {% endif %}
{% for i in rolling_stock.paginator.page_range %} {% for i in consist.paginator.page_range %}
{% if rolling_stock.number == i %} {% if consist.number == i %}
<li class="page-item active"> <li class="page-item active">
<span class="page-link">{{ i }}</span></span> <span class="page-link">{{ i }}</span></span>
</li> </li>
{% else %} {% else %}
<li class="page-item"><a class="page-link" href="/portal/consist/{{ consist.uuid }}/{{ i }}#rolling-stock">{{ i }}</a></li> <li class="page-item"><a class="page-link" href="{% url 'consists_pagination' page=i %}#rolling-stock">{{ i }}</a></li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% if rolling_stock.has_next %} {% if consist.has_next %}
<li class="page-item"> <li class="page-item">
<a class="page-link" href="/portal/consist/{{ consist.uuid }}/{{ rolling_stock.next_page_number }}#rolling-stock" tabindex="-1">Next</a> <a class="page-link" href="{% url 'consists_pagination' page=consist.next_page_number %}#rolling-stock" tabindex="-1">Next</a>
</li> </li>
{% else %} {% else %}
<li class="page-item disabled"> <li class="page-item disabled">

View File

@@ -12,7 +12,7 @@
<ul class="pagination justify-content-center mt-4"> <ul class="pagination justify-content-center mt-4">
{% if rolling_stock.has_previous %} {% if rolling_stock.has_previous %}
<li class="page-item"> <li class="page-item">
<a class="page-link" href="/portal/{{ rolling_stock.previous_page_number }}#rolling_stock" tabindex="-1">Previous</a> <a class="page-link" href="{% url 'index_pagination' page=rolling_stock.previous_page_number %}#rolling-stock" tabindex="-1">Previous</a>
</li> </li>
{% else %} {% else %}
<li class="page-item disabled"> <li class="page-item disabled">
@@ -25,12 +25,12 @@
<span class="page-link">{{ i }}</span></span> <span class="page-link">{{ i }}</span></span>
</li> </li>
{% else %} {% else %}
<li class="page-item"><a class="page-link" href="/portal/{{ i }}#rolling-stock">{{ i }}</a></li> <li class="page-item"><a class="page-link" href="{% url 'index_pagination' page=i %}#rolling-stock">{{ i }}</a></li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% if rolling_stock.has_next %} {% if rolling_stock.has_next %}
<li class="page-item"> <li class="page-item">
<a class="page-link" href="/portal/{{ rolling_stock.next_page_number }}#rolling-stock" tabindex="-1">Next</a> <a class="page-link" href="{% url 'index_pagination' page=rolling_stock.next_page_number %}#rolling-stock" tabindex="-1">Next</a>
</li> </li>
{% else %} {% else %}
<li class="page-item disabled"> <li class="page-item disabled">

View File

@@ -14,7 +14,7 @@
</div> </div>
{% if site_conf.show_version %} {% if site_conf.show_version %}
<div class="container"> <div class="container">
<p class="small text-muted">Version: {{ site_conf.version }}</p> <p class="small text-muted">Made with ❤️ and <a href="https://github.com/daniviga/django-ram">django-ram</a> version {{ site_conf.version }}</p>
</div> </div>
{% endif %} {% endif %}
</footer> </footer>

View File

@@ -1,4 +1,4 @@
<form class="d-flex" action="/portal/search" method="post"> <form class="d-flex" action="{% url 'search' %}" method="post">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search" name="search"> <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search" name="search">
<button class="btn btn-outline-primary" type="submit">Search</button> <button class="btn btn-outline-primary" type="submit">Search</button>
</form> </form>

View File

@@ -10,7 +10,7 @@
<ul class="pagination justify-content-center mt-4"> <ul class="pagination justify-content-center mt-4">
{% if rolling_stock.has_previous %} {% if rolling_stock.has_previous %}
<li class="page-item"> <li class="page-item">
<a class="page-link" href="/portal/search/{{ search }}/{{ rolling_stock.previous_page_number }}#rolling_stock" tabindex="-1">Previous</a> <a class="page-link" href="{% url 'search_pagination' search=search page=rolling_stock.previous_page_number %}#rolling-stock" tabindex="-1">Previous</a>
</li> </li>
{% else %} {% else %}
<li class="page-item disabled"> <li class="page-item disabled">
@@ -23,12 +23,12 @@
<span class="page-link">{{ i }}</span></span> <span class="page-link">{{ i }}</span></span>
</li> </li>
{% else %} {% else %}
<li class="page-item"><a class="page-link" href="/portal/search/{{ search }}/{{ i }}#rolling-stock">{{ i }}</a></li> <li class="page-item"><a class="page-link" href="{% url 'search_pagination' search=search page=i %}#rolling-stock">{{ i }}</a></li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% if rolling_stock.has_next %} {% if rolling_stock.has_next %}
<li class="page-item"> <li class="page-item">
<a class="page-link" href="/portal/search/{{ search }}/{{ rolling_stock.next_page_number }}#rolling-stock" tabindex="-1">Next</a> <a class="page-link" href="{% url 'search_pagination' search=search page=rolling_stock.next_page_number %}#rolling-stock" tabindex="-1">Next</a>
</li> </li>
{% else %} {% else %}
<li class="page-item disabled"> <li class="page-item disabled">

View File

@@ -22,7 +22,11 @@ urlpatterns = [
GetHomeFiltered.as_view(), GetHomeFiltered.as_view(),
name="search_pagination", name="search_pagination",
), ),
path("consist", Consists.as_view(), name="consists"), path("consists", Consists.as_view(), name="consists"),
path(
"consists/<int:page>",
Consists.as_view(), name="consists_pagination"
),
path("consist/<uuid:uuid>", GetConsist.as_view(), name="consist"), path("consist/<uuid:uuid>", GetConsist.as_view(), name="consist"),
path( path(
"consist/<uuid:uuid>/<int:page>", "consist/<uuid:uuid>/<int:page>",

View File

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

View File

@@ -0,0 +1,20 @@
# vim: syntax=python
"""
Django local_settings for ram project.
"""
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = (
"django-insecure-1fgtf05rwp0qp05@ef@a7%x#o+t6vk6063py=vhdmut0j!8s4u"
)
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
STORAGE_DIR = BASE_DIR / "storage"
ALLOWED_HOSTS = ["127.0.0.1"]
CSRF_TRUSTED_ORIGINS = ["https://myhost"]
ROOT_URLCONF = "ram.urls"
STATIC_URL = "static/"
MEDIA_URL = "media/"

View File

@@ -161,3 +161,10 @@ ROLLING_STOCK_TYPES = [
("equipment", "Equipment"), ("equipment", "Equipment"),
("other", "Other"), ("other", "Other"),
] ]
try:
from ram.local_settings import *
except ImportError:
# If a local_setting.py does not exist
# settings in this file only will be used
pass

View File

@@ -20,7 +20,7 @@ from django.contrib import admin
from django.urls import include, path from django.urls import include, path
urlpatterns = [ urlpatterns = [
path("", lambda r: redirect("/portal/")), path("", lambda r: redirect("portal/")),
path("portal/", include("portal.urls")), path("portal/", include("portal.urls")),
path("ht/", include("health_check.urls")), path("ht/", include("health_check.urls")),
path("admin/", admin.site.urls), path("admin/", admin.site.urls),

376
sample_data/metadata.json Normal file
View File

@@ -0,0 +1,376 @@
[
{
"model": "metadata.property",
"pk": 1,
"fields": {
"name": "Wheel arrangement"
}
},
{
"model": "metadata.property",
"pk": 2,
"fields": {
"name": "Trucks"
}
},
{
"model": "metadata.manufacturer",
"pk": 1,
"fields": {
"name": "Roco",
"category": "model",
"website": "https://www.roco.cc/",
"logo": "images/Roco_logo_ABtacmm.png"
}
},
{
"model": "metadata.manufacturer",
"pk": 2,
"fields": {
"name": "Liliput",
"category": "model",
"website": "https://liliput.de/",
"logo": "images/liliput_logo.png"
}
},
{
"model": "metadata.manufacturer",
"pk": 3,
"fields": {
"name": "Stängl",
"category": "model",
"website": "https://www.halling.at/",
"logo": "images/staengl_logo.png"
}
},
{
"model": "metadata.manufacturer",
"pk": 4,
"fields": {
"name": "Ferro-Train",
"category": "model",
"website": "https://www.halling.at/",
"logo": "images/ferro_logo.png"
}
},
{
"model": "metadata.manufacturer",
"pk": 5,
"fields": {
"name": "Bachmann",
"category": "model",
"website": "https://bachmanntrains.com/",
"logo": "images/Bachmann_bros_logo.png"
}
},
{
"model": "metadata.manufacturer",
"pk": 6,
"fields": {
"name": "ESU",
"category": "model",
"website": "https://www.esu.eu/",
"logo": ""
}
},
{
"model": "metadata.manufacturer",
"pk": 7,
"fields": {
"name": "Soundtraxx",
"category": "model",
"website": "https://soundtraxx.com/",
"logo": ""
}
},
{
"model": "metadata.manufacturer",
"pk": 8,
"fields": {
"name": "Lima Locomotive Works",
"category": "real",
"website": "",
"logo": ""
}
},
{
"model": "metadata.manufacturer",
"pk": 9,
"fields": {
"name": "Baldwin Locomotive Works",
"category": "real",
"website": "",
"logo": ""
}
},
{
"model": "metadata.manufacturer",
"pk": 10,
"fields": {
"name": "Rogers Locomotive and Machine Works",
"category": "real",
"website": "",
"logo": ""
}
},
{
"model": "metadata.manufacturer",
"pk": 11,
"fields": {
"name": "Porter Locomotive Works",
"category": "real",
"website": "",
"logo": ""
}
},
{
"model": "metadata.manufacturer",
"pk": 12,
"fields": {
"name": "Krauss & Comp. / Österreichische Siemens-Schuckert Werke",
"category": "real",
"website": "",
"logo": ""
}
},
{
"model": "metadata.manufacturer",
"pk": 13,
"fields": {
"name": "Simmering-Graz-Pauker",
"category": "real",
"website": "",
"logo": ""
}
},
{
"model": "metadata.manufacturer",
"pk": 14,
"fields": {
"name": "Davenport Locomotive Works",
"category": "real",
"website": "",
"logo": ""
}
},
{
"model": "metadata.company",
"pk": 1,
"fields": {
"name": "ÖBB",
"extended_name": "Österreichische Bundesbahnen",
"country": "AT",
"freelance": false,
"logo": "images/ÖBB_Logo_Pflatsch_neu_vQraZ8r.png"
}
},
{
"model": "metadata.company",
"pk": 2,
"fields": {
"name": "SCRR",
"extended_name": "Sand Creek Railroad",
"country": "US",
"freelance": true,
"logo": "images/scrr_Ikh9VQ4.png"
}
},
{
"model": "metadata.company",
"pk": 3,
"fields": {
"name": "RhB",
"extended_name": "Rhätische Bahn",
"country": "CH",
"freelance": false,
"logo": ""
}
},
{
"model": "metadata.company",
"pk": 4,
"fields": {
"name": "FO",
"extended_name": "Furka-Oberalp",
"country": "CH",
"freelance": false,
"logo": ""
}
},
{
"model": "metadata.decoder",
"pk": 1,
"fields": {
"name": "Basic",
"manufacturer": 5,
"version": "",
"interface": 2,
"sound": false,
"image": ""
}
},
{
"model": "metadata.decoder",
"pk": 2,
"fields": {
"name": "Tsunami",
"manufacturer": 7,
"version": "1",
"interface": 2,
"sound": true,
"image": ""
}
},
{
"model": "metadata.decoder",
"pk": 3,
"fields": {
"name": "LokPilot Micro",
"manufacturer": 6,
"version": "v4",
"interface": 1,
"sound": false,
"image": ""
}
},
{
"model": "metadata.scale",
"pk": 1,
"fields": {
"scale": "H0e",
"ratio": "1:87",
"gauge": "9 mm"
}
},
{
"model": "metadata.scale",
"pk": 2,
"fields": {
"scale": "H0",
"ratio": "1:87",
"gauge": "16.5 mm"
}
},
{
"model": "metadata.scale",
"pk": 3,
"fields": {
"scale": "0n30",
"ratio": "1:48",
"gauge": "16.5 mm"
}
},
{
"model": "metadata.scale",
"pk": 4,
"fields": {
"scale": "H0m",
"ratio": "1:87",
"gauge": "11 mm"
}
},
{
"model": "metadata.tag",
"pk": 1,
"fields": {
"name": "Mariazellerbahn",
"slug": "mariazellerbahn"
}
},
{
"model": "metadata.tag",
"pk": 2,
"fields": {
"name": "Colorado",
"slug": "colorado"
}
},
{
"model": "metadata.tag",
"pk": 3,
"fields": {
"name": "Narrow gauge",
"slug": "narrow-gauge"
}
},
{
"model": "metadata.rollingstocktype",
"pk": 1,
"fields": {
"type": "Electric",
"category": "engine"
}
},
{
"model": "metadata.rollingstocktype",
"pk": 2,
"fields": {
"type": "Diesel",
"category": "engine"
}
},
{
"model": "metadata.rollingstocktype",
"pk": 3,
"fields": {
"type": "Steam",
"category": "engine"
}
},
{
"model": "metadata.rollingstocktype",
"pk": 4,
"fields": {
"type": "EMU",
"category": "railcar"
}
},
{
"model": "metadata.rollingstocktype",
"pk": 5,
"fields": {
"type": "DMU",
"category": "railcar"
}
},
{
"model": "metadata.rollingstocktype",
"pk": 6,
"fields": {
"type": "Electric",
"category": "railcar"
}
},
{
"model": "metadata.rollingstocktype",
"pk": 7,
"fields": {
"type": "Diesel",
"category": "railcar"
}
},
{
"model": "metadata.rollingstocktype",
"pk": 8,
"fields": {
"type": "Passenger",
"category": "car"
}
},
{
"model": "metadata.rollingstocktype",
"pk": 9,
"fields": {
"type": "Freight",
"category": "car"
}
},
{
"model": "metadata.rollingstocktype",
"pk": 10,
"fields": {
"type": "Caboose",
"category": "equipment"
}
}
]