This commit is contained in:
roberto 2024-12-18 18:01:59 +01:00
parent 4018db0e17
commit 582ff4ac91
11 changed files with 107 additions and 42 deletions

View File

@ -650,6 +650,21 @@ th.operations, td.operations {
text-align: center text-align: center
} }
.field {
display:flex;
align-items:center;
flex-direction: row;
}
.field-value {
flex-grow:1;
margin-right: 5px;
}
.field-buttons {
width: 50px;
}
.col, .col,
.half, .half,
.third, .third,
@ -954,6 +969,20 @@ dialog .content {
overflow: auto; overflow: auto;
} }
dialog .content h5 {
font-size: 16px;
}
#message {
position: fixed;
bottom: 5px;
}
#message p {
padding: 0;
margin: 0;
}
#dialog-confirm { #dialog-confirm {
min-width: 300px; min-width: 300px;
} }

View File

@ -144,12 +144,22 @@ function bm_show_confirm_delete(sender, title, message) {
document.querySelector("#dialog-confirm-delete h5").innerHTML = title; document.querySelector("#dialog-confirm-delete h5").innerHTML = title;
document.querySelector("#dialog-confirm-delete p").innerHTML = message; document.querySelector("#dialog-confirm-delete p").innerHTML = message;
document.querySelector("#dialog-confirm-delete").showModal(); document.querySelector("#dialog-confirm-delete").showModal();
document.getElementById("modal-confirm-ok").addEventListener('click', (event) => { document.getElementById("modal-confirm-delete").addEventListener('click', (event) => {
htmx.trigger(sender, 'confirmed', null); htmx.trigger(sender, 'confirmed', null);
document.querySelector("#dialog-confirm-delete").close(); document.querySelector("#dialog-confirm-delete").close();
}); });
} }
function bm_show_confirm(sender, title, message) {
document.querySelector("#dialog-confirm h5").innerHTML = title;
document.querySelector("#dialog-confirm p").innerHTML = message;
document.querySelector("#dialog-confirm").showModal();
document.getElementById("modal-confirm").addEventListener('click', (event) => {
htmx.trigger(sender, 'confirmed', null);
document.querySelector("#dialog-confirm").close();
});
}
function bm_item_field_add(type_field_id, widget) { function bm_item_field_add(type_field_id, widget) {
let template = Handlebars.templates['items/field-' + widget] let template = Handlebars.templates['items/field-' + widget]
let fields_list = document.getElementById('fields-' + type_field_id); let fields_list = document.getElementById('fields-' + type_field_id);
@ -176,8 +186,14 @@ document.addEventListener("DOMContentLoaded", function(event){
); );
*/ */
document.querySelector('.dialog-confirm').addEventListener('click', (event) => { document.getElementById('dialog-confirm').addEventListener('click', (event) => {
if (event.target.classList.contains("close-dialog")) { if (event.target.classList.contains("close-dialog-confirm")) {
event.target.closest('dialog').close();
}
});
document.getElementById('dialog-confirm-delete').addEventListener('click', (event) => {
if (event.target.classList.contains("close-dialog-confirm")) {
event.target.closest('dialog').close(); event.target.closest('dialog').close();
} }
}); });
@ -198,7 +214,8 @@ document.addEventListener("DOMContentLoaded", function(event){
}); });
document.body.addEventListener("closeQuickboxTransformModal", function(evt){ document.body.addEventListener("closeQuickboxTransformModal", function(evt){
document.getElementById("modal").remove(); document.getElementById('dialog').close();
document.getElementById('dialog').remove();
if(evt.detail.keepQuickNote == 0){ if(evt.detail.keepQuickNote == 0){
htmx.ajax('DELETE', '/quickbox/delete/' + evt.detail.quickNoteId, {target:'#quicknote-' + evt.detail.quickNoteId, swap:'outerHTML swap:1s'}) htmx.ajax('DELETE', '/quickbox/delete/' + evt.detail.quickNoteId, {target:'#quicknote-' + evt.detail.quickNoteId, swap:'outerHTML swap:1s'})
} }
@ -208,8 +225,15 @@ document.addEventListener("DOMContentLoaded", function(event){
const easyMDE = new EasyMDE({element: document.getElementById(evt.detail.value), forceSync: true}); const easyMDE = new EasyMDE({element: document.getElementById(evt.detail.value), forceSync: true});
}); });
new SlimSelect({select: '.slim-select'}); document.body.addEventListener("showMessage", function(evt){
document.getElementById('message').show();
setTimeout(() => {
document.getElementById('message').close();
document.getElementById('message').innerHTML = '';
}, "5000");
});
new SlimSelect({select: '.slim-select'});
htmx.on('htmx:afterSettle', (event) => { htmx.on('htmx:afterSettle', (event) => {
new SlimSelect({select: '.slim-select'}); new SlimSelect({select: '.slim-select'});
}); });

View File

@ -43,19 +43,31 @@
</div> </div>
{{template "partial:footer" .}} {{template "partial:footer" .}}
<div id="message"></div>
<div id="overlay" onclick="bm_overlay_off('main-sidebar')"></div> <div id="overlay" onclick="bm_overlay_off('main-sidebar')"></div>
<dialog class="dialog-confirm" id="dialog-confirm-delete"> <dialog class="dialog-confirm" id="dialog-confirm-delete">
<header> <header>
<h5></h5> <h5></h5>
<span class="close-dialog button close"><i class='close-dialog bi bi-x-circle-fill'></i></span> <span class="close-dialog-confirm button close"><i class='close-dialog-confirm bi bi-x-circle-fill'></i></span>
</header> </header>
<p style="clear: both"></p> <p style="clear: both"></p>
<div id="footer-navbar"> <div id="footer-navbar">
<button id="modal-confirm-ok" class="delete">Delete</button> <button id="modal-confirm-delete" class="delete">Delete</button>
</div>
</dialog>
<dialog class="dialog-confirm" id="dialog-confirm">
<header>
<h5></h5>
<span class="close-dialog-confirm button close"><i class='close-dialog-confirm bi bi-x-circle-fill'></i></span>
</header>
<p style="clear: both"></p>
<div id="footer-navbar">
<button id="modal-confirm" class="delete">Confirm</button>
</div> </div>
</dialog> </dialog>
@ -85,6 +97,7 @@
</div><!-- quickbox --> </div><!-- quickbox -->
<script>{{block "jscode" .}}{{end}}</script> <script>{{block "jscode" .}}{{end}}</script>
<dialog id="message"></dialog>
</body> </body>
</html> </html>
{{ end }} {{ end }}

View File

@ -1,6 +1,7 @@
{{define "page:title"}} {{define "page:title"}}
<div id="page-title-title"><h5>All Items</h5></div> <div id="page-title-title"><h5>All Items</h5></div>
<div class="hide-medium hide-large" id="top-toolbar"> <div class="hide-medium hide-large" id="top-toolbar">
<a class="button" href="#" onclick="bm_toggle_visibility('all_items_search'); return false;" ><i class="bi bi-search"></i></a>
<a href="#" onclick="bm_toggle_quickbox(); return false;" class="button"><i class='bi bi-inbox-fill'></i></a> <a href="#" onclick="bm_toggle_quickbox(); return false;" class="button"><i class='bi bi-inbox-fill'></i></a>
</div> </div>
{{end}} {{end}}

View File

@ -11,32 +11,12 @@
<div id="fields-{{ .Type_field_id }}"> <div id="fields-{{ .Type_field_id }}">
{{ $g_counter := 0 }} {{ $g_counter := 0 }}
{{ range $counter, $value := $values}} {{ range $counter, $value := $values}}
<input <input type="hidden" id="FieldsValuesToRemove-{{$field.Type_field_id}}-{{$counter}}" name="FieldsValuesToRemove-{{$field.Type_field_id}}-{{$counter}}" value="0"/>
type="hidden" <div class="field">
id="FieldsValuesToRemove-{{$field.Type_field_id}}-{{$counter}}" <div id="FieldsValues-{{$field.Type_field_id}}-{{$counter}}" class="field-value">{{ field_widget $field.Widget $field.Type_field_id $counter "" $value $field.Valid_values ""}}</div>
name="FieldsValuesToRemove-{{$field.Type_field_id}}-{{$counter}}" <div class="field-buttons">
value="0" <button id="Delete-{{$field.Type_field_id}}-{{$counter}}" class="delete" type="button" _="on click set {value: '1'} on #FieldsValuesToRemove-{{$field.Type_field_id}}-{{$counter}} then hide me then show #Undelete-{{$field.Type_field_id}}-{{$counter}} then add .w3-opacity-max to #FieldsValues-{{$field.Type_field_id}}-{{$counter}}" ><i class="bi bi-dash-square" title="Remove"></i></button>
/> <button id="Undelete-{{$field.Type_field_id}}-{{$counter}}" style="margin-right: 5px; display: none" class="delete" type="button" _="on click set {value: ''} on #FieldsValuesToRemove-{{$field.Type_field_id}}-{{$counter}} then hide me then show #Delete-{{$field.Type_field_id}}-{{$counter}} then remove .w3-opacity-max from #FieldsValues-{{$field.Type_field_id}}-{{$counter}}"><i class="bi bi-arrow-counterclockwise" title="Undo"></i></button>
<div class="w3-row w3-section">
<div id="FieldsValues-{{$field.Type_field_id}}-{{$counter}}" class="w3-col s10 m11 l11" style="padding-right: 4px;">{{ field_widget $field.Widget $field.Type_field_id $counter "" $value $field.Valid_values ""}}</div>
<div class="w3-col w3-right-align s2 m1 l1">
<button
id="Delete-{{$field.Type_field_id}}-{{$counter}}"
class="w3-button w3-small w3-delete w3-border w3-round-large"
type="button"
_="on click set {value: '1'} on #FieldsValuesToRemove-{{$field.Type_field_id}}-{{$counter}} then hide me then show #Undelete-{{$field.Type_field_id}}-{{$counter}} then add .w3-opacity-max to #FieldsValues-{{$field.Type_field_id}}-{{$counter}}"
>
<i class="bi bi-dash-square" title="Remove"></i>
</button>
<button
id="Undelete-{{$field.Type_field_id}}-{{$counter}}"
style="margin-right: 5px; display: none"
class="w3-button w3-small w3-delete w3-border w3-round-large"
type="button"
_="on click set {value: ''} on #FieldsValuesToRemove-{{$field.Type_field_id}}-{{$counter}} then hide me then show #Delete-{{$field.Type_field_id}}-{{$counter}} then remove .w3-opacity-max from #FieldsValues-{{$field.Type_field_id}}-{{$counter}}">
<i class="bi bi-arrow-counterclockwise" title="Undo"></i>
</button>
</div> </div>
</div> </div>
{{ $g_counter = $counter}} {{ $g_counter = $counter}}
@ -44,7 +24,7 @@
</div> </div>
<span class="hide" id="fields-{{.Type_field_id}}-counter">{{incr $g_counter }}</span> <span class="hide" id="fields-{{.Type_field_id}}-counter">{{incr $g_counter }}</span>
<button type="button" onclick="bm_item_field_add('{{.Type_field_id}}', '{{.Widget}}')" class="w3-button w3-edit w3-border w3-round-large"><i class='bi bi-plus-square-fill'></i> <span class="hide-small"> Add value</span></button> <button type="button" onclick="bm_item_field_add('{{.Type_field_id}}', '{{.Widget}}')" class="main"><i class='bi bi-plus-square-fill'></i> <span> Add value</span></button>
</fieldset> </fieldset>
{{ else }} {{ else }}
<p> <p>

View File

@ -4,7 +4,7 @@
{{if eq .messageType "success"}} {{ $messageClass = "alert-success"}} {{if eq .messageType "success"}} {{ $messageClass = "alert-success"}}
{{else if eq .messageType "failure"}} {{ $messageClass = "alert-failure"}} {{else if eq .messageType "failure"}} {{ $messageClass = "alert-failure"}}
{{ end }} {{ end }}
<div _="init add .show to #message then wait 5s then remove .show from #message" class="hide {{ $messageClass }}"> <div class="{{ $messageClass }}">
<p><i class="bi bi-check-circle"></i> {{.messageContent}}</p> <p><i class="bi bi-check-circle"></i> {{.messageContent}}</p>
<ul> <ul>
{{ range $field, $fieldMessage := .messageFieldErrors }} {{ range $field, $fieldMessage := .messageFieldErrors }}

View File

@ -26,6 +26,7 @@ func (form *categoryForm) Validate(w http.ResponseWriter, r *http.Request, app *
if form.Validator.HasErrors() { if form.Validator.HasErrors() {
w.Header().Add("HX-Retarget", "#message") w.Header().Add("HX-Retarget", "#message")
w.Header().Add("HX-Trigger-After-Settle", `{"showMessage":""}`)
data["messageType"] = "failure" data["messageType"] = "failure"
data["messageContent"] = "Impossible to save the type" data["messageContent"] = "Impossible to save the type"
@ -143,7 +144,7 @@ func (app *application) categoryCreate(w http.ResponseWriter, r *http.Request) {
} }
data["formAction"] = fmt.Sprint("/category/update/", category_id) data["formAction"] = fmt.Sprint("/category/update/", category_id)
data["formTarget"] = "#message" data["formTarget"] = "#page-content"
data["category"] = categoryForm{ data["category"] = categoryForm{
Id: category_id, Id: category_id,
@ -168,6 +169,7 @@ func (app *application) categoryCreate(w http.ResponseWriter, r *http.Request) {
app.serverError(w, r, err) app.serverError(w, r, err)
} }
w.Header().Add("HX-Trigger-After-Settle", `{"showMessage":""}`)
w.Header().Add("HX-Replace-Url", fmt.Sprint("/type/update/", category_id)) w.Header().Add("HX-Replace-Url", fmt.Sprint("/type/update/", category_id))
fullBuf.WriteTo(w) fullBuf.WriteTo(w)
@ -255,6 +257,7 @@ func (app *application) categoryUpdate(w http.ResponseWriter, r *http.Request) {
app.serverError(w, r, err) app.serverError(w, r, err)
} }
w.Header().Add("HX-Trigger-After-Settle", `{"showMessage":""}`)
fullBuf.WriteTo(w) fullBuf.WriteTo(w)
w.WriteHeader(http.StatusUnprocessableEntity) w.WriteHeader(http.StatusUnprocessableEntity)

View File

@ -54,6 +54,7 @@ func (form *itemForm) Validate(w http.ResponseWriter, r *http.Request, app *appl
if form.Validator.HasErrors() { if form.Validator.HasErrors() {
w.Header().Add("HX-Retarget", "#message") w.Header().Add("HX-Retarget", "#message")
w.Header().Add("HX-Trigger-After-Settle", `{"showMessage":""}`)
data["messageType"] = "failure" data["messageType"] = "failure"
data["messageContent"] = "Impossible to save the item" data["messageContent"] = "Impossible to save the item"
@ -80,6 +81,7 @@ func (form *itemShareForm) Validate(w http.ResponseWriter, r *http.Request, app
if form.Validator.HasErrors() { if form.Validator.HasErrors() {
w.Header().Add("HX-Retarget", "#message") w.Header().Add("HX-Retarget", "#message")
w.Header().Add("HX-Trigger-After-Settle", `{"showMessage":""}`)
data["messageType"] = "failure" data["messageType"] = "failure"
data["messageContent"] = "Impossible to save the item" data["messageContent"] = "Impossible to save the item"
@ -127,6 +129,7 @@ func (app *application) itemsSearch(w http.ResponseWriter, r *http.Request) {
case http.MethodPost: case http.MethodPost:
categoryModel := &models.CategoryModel{DB: app.db} categoryModel := &models.CategoryModel{DB: app.db}
data["categoriesMap"] = categoryModel.AllAsMap() data["categoriesMap"] = categoryModel.AllAsMap()
data["offset"] = 0
err := r.ParseForm() err := r.ParseForm()
if err != nil { if err != nil {
@ -597,7 +600,7 @@ func (app *application) itemCreate(w http.ResponseWriter, r *http.Request) {
app.serverError(w, r, err) app.serverError(w, r, err)
} }
w.Header().Add("HX-Trigger-After-Settle", `{"activateEasyMDE":"item-description"}`) w.Header().Add("HX-Trigger-After-Settle", `{"activateEasyMDE":"item-description","showMessage":""}`)
w.Header().Add("HX-Replace-Url", fmt.Sprint("/item/update/", item_id)) w.Header().Add("HX-Replace-Url", fmt.Sprint("/item/update/", item_id))
fullBuf.WriteTo(w) fullBuf.WriteTo(w)
@ -879,6 +882,9 @@ func (app *application) itemUpdate(w http.ResponseWriter, r *http.Request) {
} }
} }
w.Header().Add("HX-Reswap", `beforeend`)
w.Header().Add("HX-Trigger-After-Settle", `{"showMessage": ""}`)
fullBuf.WriteTo(w) fullBuf.WriteTo(w)
w.WriteHeader(http.StatusUnprocessableEntity) w.WriteHeader(http.StatusUnprocessableEntity)

View File

@ -36,6 +36,7 @@ func (form *typeForm) Validate(w http.ResponseWriter, r *http.Request, app *appl
if form.Validator.HasErrors() { if form.Validator.HasErrors() {
w.Header().Add("HX-Retarget", "#message") w.Header().Add("HX-Retarget", "#message")
w.Header().Add("HX-Trigger-After-Settle", `{"showMessage":""}`)
data["messageType"] = "failure" data["messageType"] = "failure"
data["messageContent"] = "Impossible to save the type" data["messageContent"] = "Impossible to save the type"
@ -215,6 +216,8 @@ func (app *application) typeCreate(w http.ResponseWriter, r *http.Request) {
} }
w.Header().Add("HX-Replace-Url", fmt.Sprint("/type/update/", type_id)) w.Header().Add("HX-Replace-Url", fmt.Sprint("/type/update/", type_id))
w.Header().Add("HX-Trigger-After-Settle", `{"showMessage":""}`)
fullBuf.WriteTo(w) fullBuf.WriteTo(w)
w.WriteHeader(http.StatusUnprocessableEntity) w.WriteHeader(http.StatusUnprocessableEntity)
@ -370,7 +373,7 @@ func (app *application) typeUpdate(w http.ResponseWriter, r *http.Request) {
dataMessage := make(map[string]string) dataMessage := make(map[string]string)
dataMessage["messageType"] = "success" dataMessage["messageType"] = "success"
dataMessage["messageContent"] = "Type saved succesfully" dataMessage["messageContent"] = "Type saved successfully"
err = response.HXFragment(fullBuf, []string{"partials/message.tmpl"}, "message", dataMessage) err = response.HXFragment(fullBuf, []string{"partials/message.tmpl"}, "message", dataMessage)
if err != nil { if err != nil {
app.serverError(w, r, err) app.serverError(w, r, err)
@ -393,6 +396,8 @@ func (app *application) typeUpdate(w http.ResponseWriter, r *http.Request) {
app.serverError(w, r, err) app.serverError(w, r, err)
} }
w.Header().Add("HX-Trigger-After-Settle", `{"showMessage":""}`)
fullBuf.WriteTo(w) fullBuf.WriteTo(w)
w.WriteHeader(http.StatusUnprocessableEntity) w.WriteHeader(http.StatusUnprocessableEntity)

View File

@ -21,10 +21,14 @@ func HXFragment(fullBuf *bytes.Buffer, pagePaths []string, templateName string,
func HXFragmentOOB(fullBuf *bytes.Buffer, pagePaths []string, templateName string, data any, div_id string) error { func HXFragmentOOB(fullBuf *bytes.Buffer, pagePaths []string, templateName string, data any, div_id string) error {
var err error var err error
var buf *bytes.Buffer var buf *bytes.Buffer
fullBuf.WriteString(fmt.Sprintf("<div hx-swap-oob=\"true\" id=\"%s\">", div_id)) var tag string = "div"
if div_id == "message" {
tag = "dialog"
}
fullBuf.WriteString(fmt.Sprintf("<%s hx-swap-oob=\"true\" id=\"%s\">", tag, div_id))
buf, err = Fragment(pagePaths, templateName, data) buf, err = Fragment(pagePaths, templateName, data)
fullBuf.Write(buf.Bytes()) fullBuf.Write(buf.Bytes())
fullBuf.WriteString("</div>") fullBuf.WriteString(fmt.Sprintf("</%s>", tag))
return err return err
} }