ContentMonster stuff

This commit is contained in:
Kumi 2022-09-20 14:02:39 +00:00
parent a3f28a5b85
commit 37c10284f1
Signed by: kumi
GPG key ID: ECBCC9082395383F
19 changed files with 490 additions and 14 deletions

View file

@ -1,13 +1,23 @@
from django.urls import path, include from django.urls import path, include
from .views.urls import VesselsDataTableURLView, VesselsDeleteURLView, VesselsEditURLView, StaticsURLView from .views.urls import VesselsDataTableURLView, VesselsDeleteURLView, VesselsEditURLView, ReplicationSourcesDataTableURLView, ReplicationSourcesDeleteURLView, ReplicationSourcesEditURLView, ReplicationTargetsDataTableURLView, ReplicationTargetsDeleteURLView, ReplicationTargetsEditURLView, StaticsURLView
from .views.vessels import VesselsLocationView from .views.vessels import VesselsLocationView
urlpatterns = [ urlpatterns = [
path("urls/datatable/vessels/", VesselsDataTableURLView.as_view(), name=""), path("urls/vessels/datatable/", VesselsDataTableURLView.as_view(), name=""),
path("urls/datatable/vessels/edit/<str:id>/", VesselsDataTableURLView.as_view(), name=""), path("urls/vessels/edit/<str:id>/", VesselsEditURLView.as_view(), name=""),
path("urls/datatable/vessels/delete/<str:id>/", VesselsDataTableURLView.as_view(), name=""), path("urls/vessels/delete/<str:id>/", VesselsDeleteURLView.as_view(), name=""),
path("urls/replication/targets/datatable/", ReplicationTargetsDataTableURLView.as_view(), name=""),
path("urls/replication/targets/edit/<str:id>/", ReplicationTargetsEditURLView.as_view(), name=""),
path("urls/replication/targets/delete/<str:id>/", ReplicationTargetsDeleteURLView.as_view(), name=""),
path("urls/replication/sources/datatable/", ReplicationSourcesDataTableURLView.as_view(), name=""),
path("urls/replication/sources/edit/<str:id>/", ReplicationSourcesEditURLView.as_view(), name=""),
path("urls/replication/sources/delete/<str:id>/", ReplicationSourcesDeleteURLView.as_view(), name=""),
path("urls/static/", StaticsURLView.as_view(), name=""), path("urls/static/", StaticsURLView.as_view(), name=""),
path("vessels/location/<str:id>/", VesselsLocationView.as_view(), name=""), path("vessels/location/<str:id>/", VesselsLocationView.as_view(), name=""),
] ]

View file

@ -17,6 +17,30 @@ class VesselsDeleteURLView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
return JsonResponse(reverse_lazy("core:admin_vessels_delete", kwargs["id"]), safe=False) return JsonResponse(reverse_lazy("core:admin_vessels_delete", kwargs["id"]), safe=False)
class ReplicationSourcesDataTableURLView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
return JsonResponse(reverse_lazy("core:admin_replication_sources_datatable"), safe=False)
class ReplicationSourcesEditURLView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
return JsonResponse(reverse_lazy("core:admin_replication_sources_edit", kwargs["id"]), safe=False)
class ReplicationSourcesDeleteURLView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
return JsonResponse(reverse_lazy("core:admin_replication_sources_delete", kwargs["id"]), safe=False)
class ReplicationTargetsDataTableURLView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
return JsonResponse(reverse_lazy("core:admin_replication_targets_datatable"), safe=False)
class ReplicationTargetsEditURLView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
return JsonResponse(reverse_lazy("core:admin_replication_targets_edit", kwargs["id"]), safe=False)
class ReplicationTargetsDeleteURLView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
return JsonResponse(reverse_lazy("core:admin_replication_targets_delete", kwargs["id"]), safe=False)
class StaticsURLView(View): class StaticsURLView(View):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
return JsonResponse(static(request.GET["file"]), safe=False) return JsonResponse(static(request.GET["file"]), safe=False)

View file

@ -0,0 +1,22 @@
# Generated by Django 4.1.1 on 2022-09-20 12:11
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('core', '0007_replicationfile_replicationsource_replicationtarget_and_more'),
]
operations = [
migrations.CreateModel(
name='VesselAlias',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('alias', models.CharField(max_length=64)),
('vessel', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.vessel')),
],
),
]

5
core/models/course.py Normal file
View file

@ -0,0 +1,5 @@
class Course(models.Model):
id = models.IntegerField(primary_key=True)
title = models.CharField(max_length=256)
shortcode = models.CharField(max_length=64)

18
core/models/crew.py Normal file
View file

@ -0,0 +1,18 @@
from django.db import models
from .course import Course
from .vessel import Vessel
class CrewMember(models.Model):
pin = models.IntegerField(primary_key=True)
first_name = models.CharField(max_length=256)
last_name = models.CharField(max_length=256)
email = models.EmailField()
dob = models.DateField()
class CourseAssignment(models.Model):
crew = models.ForeignKey(CrewMember, models.CASCADE)
course = models.ForeignKey(Course, models.CASCADE)
vessel = models.ForeignKey(Vessel, models.CASCADE, null=True)

View file

@ -1,5 +1,7 @@
from django.db import models from django.db import models
from typing import List, Dict
from pycruisemapper.classes import CruiseMapper, Ship from pycruisemapper.classes import CruiseMapper, Ship
@ -8,6 +10,23 @@ class Vessel(models.Model):
imo = models.IntegerField("IMO", null=True, blank=True) imo = models.IntegerField("IMO", null=True, blank=True)
mmsi = models.IntegerField("MMSI", null=True, blank=True) mmsi = models.IntegerField("MMSI", null=True, blank=True)
def get_names(self) -> List[str]:
names = [self.name]
for alias in self.vesselalias_set:
names.append(alias.alias)
return names
def name_dict(cls) -> Dict:
names = {}
for vessel in cls.objects.all():
for name in vessel.get_names():
names[name] = vessel
return names
def query_cruisemapper(self) -> Ship: def query_cruisemapper(self) -> Ship:
cm = CruiseMapper() cm = CruiseMapper()
all_ships = cm.get_ships() all_ships = cm.get_ships()
@ -31,3 +50,8 @@ class Vessel(models.Model):
pass pass
return ship return ship
class VesselAlias(models.Model):
vessel = models.ForeignKey(Vessel, models.CASCADE)
alias = models.CharField(max_length=64)

View file

@ -1,12 +1,43 @@
from django.urls import path from django.urls import path
from ..views.frontend import NotImplementedView from ..views.frontend import NotImplementedView
from ..views.admin.vessels import AdminVesselsListView, AdminVesselsListDataTableView, AdminVesselsCreateView from ..views.admin.vessels import AdminVesselsListView, AdminVesselsListDataTableView, AdminVesselsCreateView, AdminVesselsUpdateView, AdminVesselsDeleteView
from ..views.admin.replication.sources import AdminReplicationSourcesListView, AdminReplicationSourcesListDataTableView, AdminReplicationSourcesCreateView, AdminReplicationSourcesUpdateView, AdminReplicationSourcesDeleteView
from ..views.admin.replication.targets import AdminReplicationTargetsListView, AdminReplicationTargetsListDataTableView, AdminReplicationTargetsCreateView, AdminReplicationTargetsUpdateView, AdminReplicationTargetsDeleteView
urlpatterns = [ urlpatterns = [
path("admin/", NotImplementedView.as_view(), name="admin"), path("", NotImplementedView.as_view(), name="admin"),
path("vessels/", AdminVesselsListView.as_view(), name="admin_vessels"), path("vessels/", AdminVesselsListView.as_view(), name="admin_vessels"),
path("vessels/new/", AdminVesselsCreateView.as_view(), name="admin_vessels_create"), path("vessels/new/", AdminVesselsCreateView.as_view(),
path("vessels/datatable/", AdminVesselsListDataTableView.as_view(), name="admin_vessels_datatable"), name="admin_vessels_create"),
] path("vessels/datatable/", AdminVesselsListDataTableView.as_view(),
name="admin_vessels_datatable"),
path("vessels/<int:id>/", AdminVesselsCreateView.as_view(),
name="admin_vessels_edit"),
path("vessels/<int:id>/delete/", AdminVesselsCreateView.as_view(),
name="admin_vessels_delete"),
path("replication/sources/", AdminReplicationSourcesListView.as_view(),
name="admin_replication_sources"),
path("replication/sources/new/", AdminReplicationSourcesCreateView.as_view(),
name="admin_replication_sources_create"),
path("replication/sources/datatable/", AdminReplicationSourcesListDataTableView.as_view(),
name="admin_replication_sources_datatable"),
path("replication/sources/<int:id>/", AdminReplicationSourcesCreateView.as_view(),
name="admin_replication_sources_edit"),
path("replication/sources/<int:id>/delete/", AdminReplicationSourcesCreateView.as_view(),
name="admin_replication_sources_delete"),
path("replication/targets/", AdminReplicationTargetsListView.as_view(),
name="admin_replication_targets"),
path("replication/targets/new/", AdminReplicationTargetsCreateView.as_view(),
name="admin_replication_targets_create"),
path("replication/targets/datatable/", AdminReplicationTargetsListDataTableView.as_view(),
name="admin_replication_targets_datatable"),
path("replication/targets/<int:id>/", AdminReplicationTargetsCreateView.as_view(),
name="admin_replication_targets_edit"),
path("replication/targets/<int:id>/delete/", AdminReplicationTargetsCreateView.as_view(),
name="admin_replication_targets_delete"),
]

View file

View file

View file

@ -0,0 +1,83 @@
from django.views.generic import TemplateView, UpdateView, DeleteView, CreateView
from django.urls import reverse_lazy
from ajax_datatable.views import AjaxDatatableView
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from ....models.replication import ReplicationSource
from ....mixins.frontend import TitleMixin
from ....mixins.auth import SuperuserRequiredMixin
class AdminReplicationSourcesListView(TitleMixin, SuperuserRequiredMixin, TemplateView):
title = "Replication Sources"
template_name = "core/admin/replication_sources_list.html"
class AdminReplicationSourcesListDataTableView(SuperuserRequiredMixin, AjaxDatatableView):
model = ReplicationSource
title = 'Replication Sources'
initial_order = [["name", "asc"], ]
length_menu = [[10, 20, 50, 100, -1], [10, 20, 50, 100, 'all']]
search_values_separator = '+'
column_defs = [
AjaxDatatableView.render_row_tools_column_def(),
{'name': 'id', 'visible': False, },
{'name': 'name', 'visible': True, },
{'name': 'location', 'visible': True, },
]
def customize_row(self, row, obj):
row['edit'] = f"""
<a href="#" class="btn btn-info btn-edit"
onclick="editReplicationSource(this); return false;">
<i class="fas fa-pencil"></i> Edit
</a>
<a href="#" class="btn btn-danger"
onclick="deleteReplicationSource(this); return false;">
<i class="fas fa-trash-can"></i> Delete
</a>
"""
class AdminReplicationSourcesCreateView(TitleMixin, SuperuserRequiredMixin, CreateView):
model = ReplicationSource
title = "Create Replication Source"
template_name = "core/admin/replication_sources_new.html"
fields = ["name", "location"]
def get_form(self, form_class=None):
form = super().get_form(form_class)
form.helper = FormHelper()
form.helper.add_input(Submit('submit', 'Create', css_class='btn-primary'))
return form
def get_success_url(self):
return reverse_lazy("core:admin_replication_sources")
class AdminReplicationSourcesUpdateView(TitleMixin, SuperuserRequiredMixin, UpdateView):
model = ReplicationSource
title = "Edit Replication Source"
template_name = "core/admin/replication_sources_edit.html"
fields = ["name", "location"]
def get_form(self, form_class=None):
form = super().get_form(form_class)
form.helper = FormHelper()
form.helper.add_input(Submit('submit', 'Edit', css_class='btn-primary'))
return form
def get_success_url(self):
return reverse_lazy("core:admin_replication_sources")
class AdminReplicationSourcesDeleteView(TitleMixin, SuperuserRequiredMixin, DeleteView):
model = ReplicationSource
title = "Delete Replication Source"
template_name = "core/admin/replication_sources_delete.html"
def get_success_url(self):
return reverse_lazy("core:admin_replication_sources")

View file

@ -0,0 +1,83 @@
from django.views.generic import TemplateView, UpdateView, DeleteView, CreateView
from django.urls import reverse_lazy
from ajax_datatable.views import AjaxDatatableView
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from ....models.replication import ReplicationTarget
from ....mixins.frontend import TitleMixin
from ....mixins.auth import SuperuserRequiredMixin
class AdminReplicationTargetsListView(TitleMixin, SuperuserRequiredMixin, TemplateView):
title = "Replication Targets"
template_name = "core/admin/replication_targets_list.html"
class AdminReplicationTargetsListDataTableView(SuperuserRequiredMixin, AjaxDatatableView):
model = ReplicationTarget
title = 'Replication Targets'
initial_order = [["name", "asc"], ]
length_menu = [[10, 20, 50, 100, -1], [10, 20, 50, 100, 'all']]
search_values_separator = '+'
column_defs = [
AjaxDatatableView.render_row_tools_column_def(),
{'name': 'id', 'visible': False, },
{'name': 'name', 'visible': True, },
{'name': 'address', 'visible': True, },
]
def customize_row(self, row, obj):
row['edit'] = f"""
<a href="#" class="btn btn-info btn-edit"
onclick="editReplicationTarget(this); return false;">
<i class="fas fa-pencil"></i> Edit
</a>
<a href="#" class="btn btn-danger"
onclick="deleteReplicationTarget(this); return false;">
<i class="fas fa-trash-can"></i> Delete
</a>
"""
class AdminReplicationTargetsCreateView(TitleMixin, SuperuserRequiredMixin, CreateView):
model = ReplicationTarget
title = "Create Replication Target"
template_name = "core/admin/replication_targets_new.html"
fields = ["name", "address", "username"]
def get_form(self, form_class=None):
form = super().get_form(form_class)
form.helper = FormHelper()
form.helper.add_input(Submit('submit', 'Create', css_class='btn-primary'))
return form
def get_success_url(self):
return reverse_lazy("core:admin_replication_targets")
class AdminReplicationTargetsUpdateView(TitleMixin, SuperuserRequiredMixin, UpdateView):
model = ReplicationTarget
title = "Edit Replication Target"
template_name = "core/admin/replication_targets_edit.html"
fields = ["name", "directory", "username"]
def get_form(self, form_class=None):
form = super().get_form(form_class)
form.helper = FormHelper()
form.helper.add_input(Submit('submit', 'Edit', css_class='btn-primary'))
return form
def get_success_url(self):
return reverse_lazy("core:admin_replication_targets")
class AdminReplicationTargetsDeleteView(TitleMixin, SuperuserRequiredMixin, DeleteView):
model = ReplicationTarget
title = "Delete Replication Target"
template_name = "core/admin/replication_targets_delete.html"
def get_success_url(self):
return reverse_lazy("core:admin_replication_targets")

View file

@ -0,0 +1,25 @@
$(document).ready(function () {
$.getJSON("/api/urls/replication/sources/datatable/")
.done(function (data) {
AjaxDatatableViewUtils.initialize_table(
$('#datatable_replication_sources'),
data,
);
});
});
function deleteReplicationSource(row) {
id = row.closest('tr').id.substr(4);
$.getJSON("/api/urls/replication/sources/delete/" + id + "/")
.done(function (data) {
window.location.href = data;
});
}
function editReplicationSource(row) {
id = row.closest('tr').id.substr(4);
$.getJSON("/api/urls/replication/sources/edit/" + id + "/")
.done(function (data) {
window.location.href = data;
});
}

View file

@ -0,0 +1,25 @@
$(document).ready(function () {
$.getJSON("/api/urls/replication/targets/datatable/")
.done(function (data) {
AjaxDatatableViewUtils.initialize_table(
$('#datatable_replication_targets'),
data,
);
});
});
function deleteReplicationTarget(row) {
id = row.closest('tr').id.substr(4);
$.getJSON("/api/urls/replication/targets/delete/" + id + "/")
.done(function (data) {
window.location.href = data;
});
}
function editReplicationTarget(row) {
id = row.closest('tr').id.substr(4);
$.getJSON("/api/urls/replication/targets/edit/" + id + "/")
.done(function (data) {
window.location.href = data;
});
}

View file

@ -1,5 +1,5 @@
$(document).ready(function () { $(document).ready(function () {
$.getJSON("/api/urls/datatable/vessels/") $.getJSON("/api/urls/vessels/datatable/")
.done(function (data) { .done(function (data) {
AjaxDatatableViewUtils.initialize_table( AjaxDatatableViewUtils.initialize_table(
$('#datatable_vessels'), $('#datatable_vessels'),
@ -10,7 +10,7 @@ $(document).ready(function () {
function deleteVessel(row) { function deleteVessel(row) {
id = row.closest('tr').id.substr(4); id = row.closest('tr').id.substr(4);
$.getJSON("/api/urls/datatable/vessels/delete/" + id + "/") $.getJSON("/api/urls/vessels/delete/" + id + "/")
.done(function (data) { .done(function (data) {
window.location.href = data; window.location.href = data;
}); });
@ -18,7 +18,7 @@ function deleteVessel(row) {
function editVessel(row) { function editVessel(row) {
id = row.closest('tr').id.substr(4); id = row.closest('tr').id.substr(4);
$.getJSON("/api/urls/datatable/vessels/edit/" + id + "/") $.getJSON("/api/urls/vessels/edit/" + id + "/")
.done(function (data) { .done(function (data) {
window.location.href = data; window.location.href = data;
}); });

View file

@ -0,0 +1,45 @@
{% extends "core/base.html"%}
{% load static %}
{% block styles %}
<link href="{% static 'ajax_datatable/css/style.css' %}" rel="stylesheet" />
<link rel='stylesheet' href="{% static 'core/dist/css/dataTables.bootstrap4.min.css' %}">
<link rel='stylesheet' href="{% static 'core/dist/css/buttons.bootstrap.min.css' %}">
{% endblock %}
{% block content %}
<div class="card">
<div class="card-header">
<h3 class="card-title">List of Replication Sources</h3>
<div class="card-tools">
<ul class="pagination pagination-sm float-right">
<a href="{% url "core:admin_replication_sources_create" %}" class="btn btn-success"><i class="fas fa-plus"></i> New
Replication Source</a>
</ul>
</div>
</div>
<div class="card-body">
<div class="table-responsive">
<table id="datatable_replication_sources" width="100%"
class="table table-striped table-bordered dt-responsive compact nowrap">
</table>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="{% static 'ajax_datatable/js/utils.js' %}"></script>
<script src="{% static 'core/dist/js/jquery.dataTables.min.js' %}"></script>
<script src="{% static 'core/dist/js/dataTables.bootstrap4.min.js' %}"></script>
<script src="{% static 'core/dist/js/dataTables.buttons.min.js' %}"></script>
<script src="{% static 'core/dist/js/buttons.print.min.js' %}"></script>
<script src="{% static 'core/dist/js/buttons.html5.min.js' %}"></script>
<script src="{% static 'core/dist/js/buttons.bootstrap.min.js' %}"></script>
<script src="{% static 'core/dist/js/jszip.min.js' %}"></script>
<script src="{% static 'core/dist/js/pdfmake.min.js' %}"></script>
<script src="{% static 'core/dist/js/vfs_fonts.js' %}"></script>
<script type="text/javascript" src="{% static 'core/js/admin/replication_sources_datatable.js' %}"></script>
{% endblock %}

View file

@ -0,0 +1,18 @@
{% extends "core/base.html"%}
{% load crispy_forms_tags %}
{% block content %}
<div class="card">
<div class="card-header">
<h3 class="card-title">Create New Replication Source</h3>
<div class="card-tools">
<ul class="pagination pagination-sm float-right">
<a href="{% url "core:admin_replication_sources" %}" class="btn btn-danger"><i class="fas fa-xmark"></i> Abort</a>
</ul>
</div>
</div>
<div class="card-body">
{% crispy form %}
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,45 @@
{% extends "core/base.html"%}
{% load static %}
{% block styles %}
<link href="{% static 'ajax_datatable/css/style.css' %}" rel="stylesheet" />
<link rel='stylesheet' href="{% static 'core/dist/css/dataTables.bootstrap4.min.css' %}">
<link rel='stylesheet' href="{% static 'core/dist/css/buttons.bootstrap.min.css' %}">
{% endblock %}
{% block content %}
<div class="card">
<div class="card-header">
<h3 class="card-title">List of Replication Targets</h3>
<div class="card-tools">
<ul class="pagination pagination-sm float-right">
<a href="{% url " core:admin_replication_targets_create" %}" class="btn btn-success"><i
class="fas fa-plus"></i> New Replication Target</a>
</ul>
</div>
</div>
<div class="card-body">
<div class="table-responsive">
<table id="datatable_replication_targets" width="100%"
class="table table-striped table-bordered dt-responsive compact nowrap">
</table>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="{% static 'ajax_datatable/js/utils.js' %}"></script>
<script src="{% static 'core/dist/js/jquery.dataTables.min.js' %}"></script>
<script src="{% static 'core/dist/js/dataTables.bootstrap4.min.js' %}"></script>
<script src="{% static 'core/dist/js/dataTables.buttons.min.js' %}"></script>
<script src="{% static 'core/dist/js/buttons.print.min.js' %}"></script>
<script src="{% static 'core/dist/js/buttons.html5.min.js' %}"></script>
<script src="{% static 'core/dist/js/buttons.bootstrap.min.js' %}"></script>
<script src="{% static 'core/dist/js/jszip.min.js' %}"></script>
<script src="{% static 'core/dist/js/pdfmake.min.js' %}"></script>
<script src="{% static 'core/dist/js/vfs_fonts.js' %}"></script>
<script type="text/javascript" src="{% static 'core/js/admin/replication_targets_datatable.js' %}"></script>
{% endblock %}

View file

@ -0,0 +1,18 @@
{% extends "core/base.html"%}
{% load crispy_forms_tags %}
{% block content %}
<div class="card">
<div class="card-header">
<h3 class="card-title">Create New Replication Target</h3>
<div class="card-tools">
<ul class="pagination pagination-sm float-right">
<a href="{% url "core:admin_replication_targets" %}" class="btn btn-danger"><i class="fas fa-xmark"></i> Abort</a>
</ul>
</div>
</div>
<div class="card-body">
{% crispy form %}
</div>
</div>
{% endblock %}

View file

@ -132,7 +132,7 @@
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="{% url "core:admin_vessels" %}" class="nav-link"> <a href="{% url "core:admin_replication_sources" %}" class="nav-link">
<i class="nav-icon fas fa-cloud-arrow-up"></i> <i class="nav-icon fas fa-cloud-arrow-up"></i>
<p> <p>
File Replication Sources File Replication Sources
@ -140,7 +140,7 @@
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="{% url "core:admin_vessels" %}" class="nav-link"> <a href="{% url "core:admin_replication_targets" %}" class="nav-link">
<i class="nav-icon fas fa-cloud-arrow-down"></i> <i class="nav-icon fas fa-cloud-arrow-down"></i>
<p> <p>
File Replication Targets File Replication Targets