Skip to content

Commit

Permalink
beer-garden#325 - implement toasts
Browse files Browse the repository at this point in the history
  • Loading branch information
obr42 committed Apr 17, 2023
1 parent f24c4e2 commit 9ede19b
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 33 deletions.
2 changes: 1 addition & 1 deletion functionary/ui/static/css/custom_bootstrap.css.map

Large diffs are not rendered by default.

26 changes: 2 additions & 24 deletions functionary/ui/static/css/functionary.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
.logo-blue {
filter: brightness(0) saturate(100%) invert(29%) sepia(87%) saturate(1396%) hue-rotate(214deg) brightness(88%) contrast(80%);
}
.functionary-logo {
margin-bottom: -1px;
margin-right: -1rem;
}
.functionary-title {
margin-left: -1rem;
}
Expand All @@ -14,15 +7,6 @@
flex-direction: column;
justify-content: space-between;
}
.environment-select {
border: none;
background: none;
color:white;
font-size:1em;
}
.environment-select * {
color: black;
}
.errorlist > li {
color: var(--bs-text-danger);
}
Expand All @@ -35,12 +19,6 @@
.form-fill {
background-color: #F2F2F2; /* --bs-table-striped-bg over white */
}
details > summary {
font-size: 1.75rem;
}
details > summary > * {
display: inline;
}
.navbar .btn {
color: var(--bs-navbar-color);
}
Expand Down Expand Up @@ -103,8 +81,8 @@ tr.htmx-swapping td {
opacity: 0;
transition: opacity 1s ease-out;
}
body div aside {
max-width: fit-content;
.col-88 {
min-width: 88px;
}
/* Re-apply backdrop color because table wipes it */
table .modal-backdrop {
Expand Down
86 changes: 86 additions & 0 deletions functionary/ui/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,62 @@ <h1 class="mb-0">
</div>
</div>
</div>
<div aria-live="polite"
aria-atomic="true"
class="toast-container position-fixed top-0 start-50 translate-middle-x p-3">
<div id="toast-success"
class="toast align-items-center text-success-emphasis bg-success-subtle border-success"
role="status"
aria-live="polite"
aria-atomic="true">
<div class="d-flex">
<div id="toast-success-body" class="toast-body"></div>
<button type="button"
class="btn-close me-2 m-auto"
data-bs-dismiss="toast"
aria-label="Close"></button>
</div>
</div>
<div id="toast-error"
class="toast align-items-center text-danger-emphasis bg-danger-subtle border-danger"
role="alert"
aria-live="assertive"
aria-atomic="true">
<div class="d-flex">
<div id="toast-error-body" class="toast-body"></div>
<button type="button"
class="btn-close me-2 m-auto"
data-bs-dismiss="toast"
aria-label="Close"></button>
</div>
</div>
<div id="toast-warn"
class="toast align-items-center text-warning-emphasis bg-warning-subtle border-warning"
role="status"
aria-live="polite"
aria-atomic="true">
<div class="d-flex">
<div id="toast-warn-body" class="toast-body"></div>
<button type="button"
class="btn-close me-2 m-auto"
data-bs-dismiss="toast"
aria-label="Close"></button>
</div>
</div>
<div id="toast-info"
class="toast align-items-center text-info-emphasis bg-info-subtle border-info"
role="status"
aria-live="polite"
aria-atomic="true">
<div class="d-flex">
<div id="toast-info-body" class="toast-body"></div>
<button type="button"
class="btn-close me-2 m-auto"
data-bs-dismiss="toast"
aria-label="Close"></button>
</div>
</div>
</div>
<script>
// Show an error message when a bad status comes back from an HTMX call
document.body.addEventListener('htmx:beforeOnLoad', (event) => {
Expand All @@ -144,10 +200,40 @@ <h1 class="mb-0">
</script>
<script type="module">
import 'bootstrap'
// Initialize dropdowns, popovers, toasts
const dropdownElementList = document.querySelectorAll('.dropdown-toggle')
const dropdownList = [...dropdownElementList].map(dropdownToggleEl => new bootstrap.Dropdown(dropdownToggleEl))
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
const toastElList = document.querySelectorAll('.toast')
const toastList = [...toastElList].map(toastEl => new bootstrap.Toast(toastEl))

// Register toast listener
htmx.on("showMessage", (e) => {
var toastElement, toastBody
switch(e.detail.level) {
case 'success':
toastElement = document.getElementById("toast-success")
toastBody = document.getElementById("toast-success-body")
break;
case 'error':
toastElement = document.getElementById("toast-error")
toastBody = document.getElementById("toast-error-body")
break;
case 'warning':
toastElement = document.getElementById("toast-warn")
toastBody = document.getElementById("toast-warn-body")
break;
case 'info':
default:
toastElement = document.getElementById("toast-info")
toastBody = document.getElementById("toast-info-body")
break;
}
const toast = new bootstrap.Toast(toastElement, { delay: 7000 })
toastBody.innerText = e.detail.msg
toast.show()
})
</script>
</body>
</html>
2 changes: 1 addition & 1 deletion functionary/ui/templates/forms/workflow/workflow_edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ <h2 class="my-2">
<button class="btn btn-primary"
type="submit"
form="workflow-form"
title="{% if workflow %}Save{% else %}Next{% endif %}">
title="Save name and description{% if not workflow %}; proceed to adding steps and parameters{% endif %}">
{% if workflow %}
Save
{% else %}
Expand Down
2 changes: 1 addition & 1 deletion functionary/ui/templates/partials/workflows/step_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<tbody id="steps">
{% for step in workflow.ordered_steps %}
<tr id="step-{{ step.id }}">
<td>
<td class="col-88">
{% with previous=step.previous next=step.next %}
<div class="d-flex {% if previous is None %}justify-content-end{% elif next is None %}justify-content-start{% else %}justify-content-between{% endif %}">
<button class="btn btn-small text-primary fa fa-chevron-up border-0"
Expand Down
15 changes: 14 additions & 1 deletion functionary/ui/views/workflow/parameter/delete.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import json

from django.http import HttpResponse
from django.shortcuts import get_object_or_404

Expand All @@ -21,4 +23,15 @@ def delete(self, request, workflow_pk, pk):
parameter = self._get_object()
parameter.delete()

return HttpResponse()
return HttpResponse(
headers={
"HX-Trigger": json.dumps(
{
"showMessage": {
"level": "success",
"msg": f"{parameter.name} removed from workflow.",
}
}
),
},
)
17 changes: 16 additions & 1 deletion functionary/ui/views/workflow/parameter/edit.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import json

from django.shortcuts import get_object_or_404
from django.urls import reverse
from django_htmx.http import HttpResponseClientRedirect
Expand All @@ -22,8 +24,21 @@ def form_valid(self, form):
success_url = reverse(
"ui:workflow-update", kwargs={"pk": parameter.workflow.pk}
)
action = "updaded in" if self.post_action == "UPDATE" else "added to"

return HttpResponseClientRedirect(success_url)
return HttpResponseClientRedirect(
success_url,
headers={
"HX-Trigger": json.dumps(
{
"showMessage": {
"level": "success",
"msg": f"{parameter.name} {action} workflow.",
}
}
),
},
)

def get_context_data(self, **kwargs):
"""Custom context which includes the Workflow"""
Expand Down
18 changes: 16 additions & 2 deletions functionary/ui/views/workflow/step/create.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import json

from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django_htmx.http import HttpResponseClientRedirect
Expand Down Expand Up @@ -47,12 +49,24 @@ def post(self, request, workflow_pk):
if step_form.is_valid() and parameter_form.is_valid():
step = add_step(
**step_form.cleaned_data,
parameter_template=parameter_form.parameter_template
parameter_template=parameter_form.parameter_template,
)

success_url = reverse("ui:workflow-update", kwargs={"pk": step.workflow.pk})

return HttpResponseClientRedirect(success_url)
return HttpResponseClientRedirect(
success_url,
headers={
"HX-Trigger": json.dumps(
{
"showMessage": {
"level": "success",
"msg": f"{step.name} added to workflow.",
}
}
),
},
)
else:
context = self.get_context_data()
context["parameter_form"] = parameter_form
Expand Down
13 changes: 12 additions & 1 deletion functionary/ui/views/workflow/step/delete.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import json

from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.shortcuts import get_object_or_404, render
from django.views.generic import View
Expand All @@ -22,7 +24,16 @@ def delete(self, request, workflow_pk, pk):
context = {"workflow": step.workflow}
remove_step(step)

return render(request, "partials/workflows/step_list.html", context)
response = render(request, "partials/workflows/step_list.html", context)
response["HX-Trigger"] = json.dumps(
{
"showMessage": {
"level": "success",
"msg": f"{step.name} removed from workflow.",
}
}
)
return response

def test_func(self):
"""Permission check for access to the view"""
Expand Down
15 changes: 14 additions & 1 deletion functionary/ui/views/workflow/step/update.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
from uuid import UUID

from django.contrib.auth.decorators import login_required
Expand Down Expand Up @@ -57,7 +58,19 @@ def post(self, request, workflow_pk, pk):

success_url = reverse("ui:workflow-update", kwargs={"pk": step.workflow.pk})

return HttpResponseClientRedirect(success_url)
return HttpResponseClientRedirect(
success_url,
headers={
"HX-Trigger": json.dumps(
{
"showMessage": {
"level": "success",
"msg": f"{step.name} updated in workflow.",
}
}
),
},
)
else:
context = self.get_context_data()
context["parameter_form"] = parameter_form
Expand Down

0 comments on commit 9ede19b

Please sign in to comment.