Add Sortable.js and make scope matrix AJAX

dynamic-frontend
Pete Ley 2 months ago
parent 48e701fea4
commit a0735aba07

@ -25,7 +25,7 @@ SECRET_KEY = "django-insecure-%q_1-ql04zin3dy32cx@gtj_)onxaa1fm9wvvmf+2qhwyz4_&r
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['dwgstatus', '127.0.0.1', 'localhost', 'localhost:8000', '10.10.48.73']
ALLOWED_HOSTS = ['dwgstatus', '127.0.0.1', 'localhost', 'localhost:8000', '10.10.48.73', 'psc-227']
# Application definition

@ -1,3 +1,8 @@
tbody input {
max-width: 80px;
}
.drag-handle {
cursor: move;
}

@ -16,6 +16,7 @@
{% block extra_style %}{% endblock %}
</style>
<script src="{% static 'jobs/jquery-3.6.3.min.js' %}"></script>
<script src="{% static 'jobs/Sortable.min.js' %}"></script>
<script src="{% static 'jobs/htmx.min.js' %}"></script>
</head>
<body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>

@ -1,9 +1,14 @@
{% if title %}
<span data-bs-toggle="tooltip"
title="{{ title }}"
style="border-bottom: 1px dotted">
{{ content }}
</span>
style="border-bottom: 1px dotted"
needstooltip
>{{ content }}</span>
<script>
var tt = document.querySelector('[needstooltip]');
new bootstrap.Tooltip(tt);
tt.removeAttribute('needstooltip');
</script>
{% else %}
{{ content }}
{% endif %}

@ -208,58 +208,26 @@
{% endwith %}
<div class="mt-3">
<h3>
Scope Matrix
{% include 'jobs/_hideshowbtn.html' with target='scopematrix' %}
</h3>
<div class="d-flex align-items-center">
<h3>Scope Matrix</h3>
<span class="btn-group ms-2">
{% include 'jobs/_hideshowbtn.html' with target='scopematrix' %}
<button class="btn btn-sm btn-primary"
hx-get="{% url 'jobs:sub_scope' pk=job.pk %}"
hx-params="add"
hx-target="#scopematrix"
hx-swap="beforeend"
>Add sub</button>
</span>
</div>
<div id="scopematrix" class="collapse show overflow-x-auto">
<table class="table table-bordered table-striped table-hover mb-4">
<thead>
<tr>
{% if user.is_staff %}<th></th>{% endif %}
<th>Stair</th>
<th>Grid</th>
<th>Levels</th>
<th>Flights</th>
<th>Stringer Type</th>
<th>Stair Construction</th>
<th>Landings</th>
<th>Landing Construction</th>
<th>Rail Type</th>
<th>Finish</th>
<th>STN</th>
</tr>
</thead>
<tbody hx-target="closest tr" hx-swap="outerHTML">
{% for sub in job.submittal_set.all %}
<th colspan="100">
{{ sub.label }}
{% if user.is_staff %}
<a href="/admin/jobs/submittal/{{ sub.pk }}/change"
class="edit-link">Edit</a>
{% endif %}
</th>
{% for stair in sub.get_stairs %}
{% include 'jobs/stair_scope_row.html' %}
{% endfor %}
<tr class="{% cycle 'odd' 'even' %} total">
<td colspan="{% if user.is_staff %}4{% else %}3{% endif %}">
{% if user.is_staff %}
<button class="btn btn-sm btn-primary"
hx-get="{% url 'jobs:stair_scope_row_add' %}?submittal={{sub.pk}}"
hx-swap="beforebegin"
>Add</button>
{% endif %}
</td>
<td>{{ sub.total_flights }}</td>
<td colspan="2"></td>
<td>{{ sub.total_landings }}</td>
<td colspan="11"></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% for sub in job.submittal_set.all %}
<table hx-trigger="load"
hx-swap="outerHTML"
hx-get="{% url 'jobs:sub_scope' pk=sub.pk %}"
></table>
{% endfor %}
</div>
</div>
<div>
@ -304,7 +272,7 @@
</tr>
{% for stair in sub.calendar %}
{% for xmtl in stair.xmtls %}
<tr class="{% cycle 'odd' 'even' as oddeven %}">
<tr>
{% if user.is_staff %}
<td>
<a href="/admin/jobs/transmittal/{{xmtl.pk}}/change"
@ -375,7 +343,7 @@
</th>
</tr>
{% for s in sub.get_stairs %}
<tr class="{% cycle 'odd' 'even' as oddeven %}">
<tr>
{% if user.is_staff %}
<td>
<a href="/admin/jobs/stair/{{s.pk}}/change"
@ -459,7 +427,7 @@
</thead>
<tbody>
{% for item in job.get_correspondence %}
<tr class="{% cycle 'odd' 'even' as oddeven %}">
<tr>
<td>{{ item.date_str }}</td>
<td>{{ item.date|days_since }}</td>
<td style="color:{{ item.color}}">{{ item.type }}</td>

@ -1,9 +1,10 @@
<tr class="{% cycle 'odd' 'even' %}">
<tr class="draggable" hx-target="closest tr">
{% if user.is_staff %}
<td>
<div class="btn-group-vertical btn-group-sm" role="group">
<button class="btn btn-primary"
hx-get="{% url 'jobs:stair_scope_row' pk=stair.pk %}"
hx-swap="outerHTML"
>Edit</button>
<button class="btn btn-primary"
hx-get="{% url 'jobs:stair_scope_row_add' %}?clone={{stair.pk}}"
@ -12,7 +13,7 @@
</div>
</td>
{% endif %}
<td>
<td class="drag-handle">
{% include 'jobs/_tooltip.html' with content=stair.name title=stair.alt_name %}
</td>
<td>{{ stair.grid }}</td>
@ -46,3 +47,4 @@
</td>
{% endif %}
</tr>

@ -1,4 +1,4 @@
<tr class="{% cycle 'odd' 'even' %}">
<tr class="{% cycle 'odd' 'even' %}" hx-target="closest tr" hx-swap="outerHTML">
<td>
{% if stair.pk %}
<div class="btn-group-vertical" role="group">
@ -11,9 +11,8 @@
hx-params="reset"
>Cancel</button>
<button class="btn btn-danger btn-sm"
hx-post="{% url 'jobs:stair_scope_row' pk=stair.pk %}"
hx-delete="{% url 'jobs:stair_scope_row' pk=stair.pk %}"
hx-confirm="Are you sure you want to delete stair {{stair.name}}?"
hx-params="delete"
>Delete</button>
</div>
{% else %}

@ -0,0 +1,72 @@
<table class="table table-striped table-bordered table-hover mb-4">
<thead class="table-secondary">
<tr>
<th colspan="100">
{{ sub.label }}
{% if user.is_staff %}
<a href="/admin/jobs/submittal/{{ sub.pk }}/change"
class="edit-link">Edit</a>
<div class="btn-group float-end">
<button class="btn btn-primary btn-sm"
hx-get="{% url 'jobs:stair_scope_row_add' %}?submittal={{ sub.pk }}"
hx-target="#{{ bodyid }}"
hx-swap="beforeend"
>Add stair</button>
<button class="btn btn-danger btn-sm"
hx-delete="{% url 'jobs:sub_scope' pk=sub.pk %}"
hx-target="closest table"
hx-swap="outerHTML"
hx-confirm="Are you sure you want to delete {{ sub.job.number }} sub {{ sub.number }} and all its stairs?"
>Delete sub</button>
</div>
{% endif %}
</th>
</tr>
<tr>
{% if user.is_staff %}<th></th>{% endif %}
<th>Stair</th>
<th>Grid</th>
<th>Levels</th>
<th>Flights</th>
<th>Stringer Type</th>
<th>Stair Construction</th>
<th>Landings</th>
<th>Landing Construction</th>
<th>Rail Type</th>
<th>Finish</th>
<th>STN</th>
</tr>
</thead>
<tbody id="{{ bodyid }}" class="collapse show">
<tr class="mh-1 py-0"><td class="py-0" colspan="100"></td></tr>
{% for stair in sub.get_stairs %}
{% include 'jobs/stair_scope_row.html' %}
{% endfor %}
</tbody>
<script>
new Sortable(document.getElementById("{{ bodyid }}"), {
group: {
name: 'subs',
},
handle: '.drag-handle',
draggable: '.draggable',
animation: 200,
});
</script>
<tfoot class="table-secondary table-bordered">
<tr class="mh-1 py-0"><td class="py-0" colspan="100"></td></tr>
<tr hx-target="closest tr" hx-swap="outerHTML">
<td colspan="{% if user.is_staff %}4{% else %}3{% endif %}">
{% if user.is_staff %}
{% endif %}
</td>
<td>{{ sub.total_flights }}</td>
<td colspan="2"></td>
<td>{{ sub.total_landings }}</td>
<td colspan="11"></td>
</tr>
</tfoot>
</table>

@ -28,6 +28,7 @@ urlpatterns = [
path('jobreport/', views.job_report, name='job_report'),
path('ajax/current-messages', views.current_messages, name='current_messages'),
path('ajax/sub_scope/<int:pk>', views.sub_scope, name='sub_scope'),
path('ajax/stair-scope-row/<int:pk>', views.stair_scope_row, name='stair_scope_row'),
path('ajax/stair-scope-row-add', views.stair_scope_row_add, name='stair_scope_row_add'),
]

@ -7,6 +7,7 @@ from django.utils.safestring import mark_safe
from django.views import generic
from .models import (
Job,
Submittal,
Detailer,
ProjectManager,
Company,
@ -143,14 +144,32 @@ def job_report(request):
)
def sub_scope(request, pk):
if request.method == 'DELETE':
Submittal.objects.get(pk=pk).delete()
return HttpResponse()
if 'add' in request.GET:
job = Job.objects.get(pk=pk)
sub = Submittal.objects.create(
job=job,
number=job.submittal_set.count() + 1,
)
else:
sub = Submittal.objects.get(pk=pk)
context = {
'sub': sub,
'bodyid': f'scope_sub_{sub.number}'
}
return render(request, 'jobs/sub_scope.html', context=context)
def stair_scope_row(request, pk):
stair = Stair.objects.get(pk=pk)
context = {'stair': stair}
if request.method == 'DELETE':
stair.delete()
messages.success(request, f'Stair {stair.name} deleted')
return HttpResponse(headers={'HX-Trigger': 'getmessages'})
if request.method == 'POST':
if 'delete' in request.POST:
stair.delete()
messages.success(request, f'Stair {stair.name} deleted')
return HttpResponse(headers={'HX-Trigger': 'getmessages'})
form = StairScopeRowForm(request.POST, instance=stair)
if not form.errors:
form.save()
@ -167,12 +186,12 @@ def stair_scope_row(request, pk):
)
response['HX-Trigger'] = 'getmessages'
return response
# get
if 'reset' in request.GET:
return render(request, 'jobs/stair_scope_row.html', context=context)
context['form'] = StairScopeRowForm(instance=stair)
return render(request, 'jobs/stair_scope_row_edit.html', context=context)
def stair_scope_row_add(request):
if request.method == 'DELETE':
return HttpResponse()

Loading…
Cancel
Save