dev: automated commit - 2025-06-17 16:15:21
This commit is contained in:
parent
73e91db78b
commit
27775e6b29
16 changed files with 1860 additions and 1240 deletions
34
templates/alert.templ
Normal file
34
templates/alert.templ
Normal file
|
@ -0,0 +1,34 @@
|
|||
|
||||
package templates
|
||||
|
||||
templ Alert(id, alertType, message string, dismissible bool) {
|
||||
<div
|
||||
id={ id }
|
||||
class={ "alert", "alert-" + alertType, templ.KV("alert-dismissible", dismissible), templ.KV("d-none", message == "") }
|
||||
role="alert"
|
||||
>
|
||||
if message != "" {
|
||||
{ message }
|
||||
}
|
||||
if dismissible {
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
// Helper components for common alert types
|
||||
templ ErrorAlert(id, message string) {
|
||||
@Alert(id, "danger", message, false)
|
||||
}
|
||||
|
||||
templ SuccessAlert(id, message string) {
|
||||
@Alert(id, "success", message, true)
|
||||
}
|
||||
|
||||
templ WarningAlert(id, message string) {
|
||||
@Alert(id, "warning", message, true)
|
||||
}
|
||||
|
||||
templ InfoAlert(id, message string) {
|
||||
@Alert(id, "info", message, true)
|
||||
}
|
214
templates/alert_templ.go
Normal file
214
templates/alert_templ.go
Normal file
|
@ -0,0 +1,214 @@
|
|||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.898
|
||||
|
||||
package templates
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func Alert(id, alertType, message string, dismissible bool) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
var templ_7745c5c3_Var2 = []any{"alert", "alert-" + alertType, templ.KV("alert-dismissible", dismissible), templ.KV("d-none", message == "")}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div id=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(id)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/alert.templ`, Line: 6, Col: 9}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/alert.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\" role=\"alert\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if message != "" {
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(message)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/alert.templ`, Line: 11, Col: 12}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
if dismissible {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Helper components for common alert types
|
||||
func ErrorAlert(id, message string) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var6 == nil {
|
||||
templ_7745c5c3_Var6 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = Alert(id, "danger", message, false).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func SuccessAlert(id, message string) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var7 == nil {
|
||||
templ_7745c5c3_Var7 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = Alert(id, "success", message, true).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func WarningAlert(id, message string) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var8 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var8 == nil {
|
||||
templ_7745c5c3_Var8 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = Alert(id, "warning", message, true).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func InfoAlert(id, message string) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var9 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var9 == nil {
|
||||
templ_7745c5c3_Var9 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = Alert(id, "info", message, true).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
|
@ -43,17 +43,16 @@ templ Index(props IndexProps) {
|
|||
<h1>{ props.Title }</h1>
|
||||
<div class="current-ip d-flex align-items-center">
|
||||
<span class="me-2">Current IP:</span>
|
||||
<span id="current-ip" class="fw-bold">{ props.CurrentIP }</span>
|
||||
<button
|
||||
class="btn btn-sm btn-outline-secondary ms-2"
|
||||
title="Refresh current IP"
|
||||
hx-get="/refresh-ip"
|
||||
hx-target="#current-ip"
|
||||
hx-indicator="#refresh-spinner"
|
||||
<span id="current-ip" x-init class="fw-bold">{ props.CurrentIP }</span>
|
||||
<a
|
||||
href="/refresh-ip"
|
||||
x-target="current-ip"
|
||||
class="btn btn-sm btn-outline-secondary ms-2 d-inline-flex align-items-center"
|
||||
@ajax:before="$el.querySelector('.bi-arrow-clockwise').classList.add('spin')"
|
||||
@ajax:after="$el.querySelector('.bi-arrow-clockwise').classList.remove('spin')"
|
||||
>
|
||||
<i class="bi bi-arrow-clockwise"></i>
|
||||
<span id="refresh-spinner" class="htmx-indicator spinner-border spinner-border-sm ms-1"></span>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
if !props.IsConfigured {
|
||||
|
@ -62,12 +61,9 @@ templ Index(props IndexProps) {
|
|||
@ConfigStatus(props.Config)
|
||||
@DNSRecordsSection(props.Records, props.CurrentIP)
|
||||
}
|
||||
@ConfigModal(props.Config, props.UpdateFreqs)
|
||||
@RecordModal(props.Config.Domain)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="toast-container"></div>
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,16 +82,34 @@ templ ConfigWarning() {
|
|||
}
|
||||
|
||||
templ ConfigStatus(config ConfigData) {
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<div class="card mb-4" id="config-status">
|
||||
<div
|
||||
class="card-header d-flex justify-content-between align-items-center"
|
||||
x-init
|
||||
x-data="{ editLoading: false, deleteLoading: false }"
|
||||
@ajax:success="$dispatch('dialog:open')"
|
||||
>
|
||||
<h5 class="mb-0">Configuration</h5>
|
||||
<button
|
||||
class="btn btn-sm btn-outline-primary"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#configModal"
|
||||
<a
|
||||
href="/config"
|
||||
@ajax:before="editLoading = true"
|
||||
@ajax:success="$dispatch('dialog:open')"
|
||||
@ajax:after="editLoading = false"
|
||||
@ajax:error="editLoading = false"
|
||||
x-target="contact"
|
||||
class="btn btn-sm btn-outline-primary me-2"
|
||||
:disabled="editLoading || deleteLoading"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<template x-if="!editLoading">
|
||||
<span class="ms-1">
|
||||
Edit
|
||||
<i class="bi bi-pencil"></i>
|
||||
</span>
|
||||
</template>
|
||||
<template x-if="editLoading">
|
||||
<span class="spinner-border spinner-border-sm"></span>
|
||||
</template>
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
|
@ -118,25 +132,57 @@ templ DNSRecordsSection(records []DNSRecord, currentIP string) {
|
|||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0">DNS Records</h5>
|
||||
<div>
|
||||
<button
|
||||
class="btn btn-sm btn-success me-2"
|
||||
hx-post="/update-all-records"
|
||||
hx-target="#dns-records-table"
|
||||
hx-confirm="Are you sure you want to update all A records to your current IP?"
|
||||
hx-indicator="#update-all-spinner"
|
||||
<div x-data="{ updating: false, addingRecord: false }">
|
||||
<form
|
||||
method="post"
|
||||
action="/update-all-records"
|
||||
x-target="dns-records-table"
|
||||
@ajax:before="confirm('Are you sure you want to update all A records to your current IP?') || $event.preventDefault(); updating = true"
|
||||
@ajax:after="updating = false"
|
||||
@ajax:error="updating = false"
|
||||
style="display: inline;"
|
||||
>
|
||||
<i class="bi bi-arrow-repeat"></i> Update All to Current IP
|
||||
<span id="update-all-spinner" class="htmx-indicator spinner-border spinner-border-sm ms-1"></span>
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm btn-primary"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#recordModal"
|
||||
onclick="resetRecordForm()"
|
||||
<button
|
||||
class="btn btn-sm btn-success me-2"
|
||||
type="submit"
|
||||
:disabled="updating || addingRecord"
|
||||
>
|
||||
<template x-if="!updating">
|
||||
<span class="d-flex align-items-center">
|
||||
<i class="bi bi-arrow-repeat me-1"></i>
|
||||
Update All to Current IP
|
||||
</span>
|
||||
</template>
|
||||
<template x-if="updating">
|
||||
<span class="d-flex align-items-center">
|
||||
<span class="spinner-border spinner-border-sm me-2"></span>
|
||||
Updating All Records...
|
||||
</span>
|
||||
</template>
|
||||
</button>
|
||||
</form>
|
||||
<a
|
||||
href="/records/new"
|
||||
x-target="contact"
|
||||
@ajax:before="addingRecord = true; $dispatch('dialog:open')"
|
||||
@ajax:after="addingRecord = false"
|
||||
@ajax:error="addingRecord = false"
|
||||
class="btn btn-primary"
|
||||
:disabled="updating || addingRecord"
|
||||
>
|
||||
<i class="bi bi-plus-lg"></i> Add Record
|
||||
</button>
|
||||
<template x-if="!addingRecord">
|
||||
<span class="d-flex align-items-center">
|
||||
<i class="bi bi-plus-lg me-1"></i>
|
||||
Add Record
|
||||
</span>
|
||||
</template>
|
||||
<template x-if="addingRecord">
|
||||
<span class="d-flex align-items-center">
|
||||
<span class="spinner-border spinner-border-sm me-2"></span>
|
||||
Loading...
|
||||
</span>
|
||||
</template>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
|
@ -174,7 +220,7 @@ templ DNSRecordsTable(records []DNSRecord, currentIP string) {
|
|||
}
|
||||
|
||||
templ DNSRecordRow(record DNSRecord, currentIP string) {
|
||||
<tr>
|
||||
<tr x-data="{ editLoading: false, deleteLoading: false }">
|
||||
<td>{ record.Type }</td>
|
||||
<td>{ record.Name }</td>
|
||||
<td>
|
||||
|
@ -200,23 +246,46 @@ templ DNSRecordRow(record DNSRecord, currentIP string) {
|
|||
}
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
class="btn btn-sm btn-outline-primary me-1"
|
||||
hx-get={ fmt.Sprintf("/edit-record/%s", record.ID) }
|
||||
hx-target="#record-modal-content"
|
||||
hx-on::after-request="if(event.detail.successful) bootstrap.Modal.getOrCreateInstance(document.getElementById('recordModal')).show()"
|
||||
<a
|
||||
href={ templ.URL(fmt.Sprintf("/edit-record/%s", record.ID)) }
|
||||
@ajax:before="editLoading = true"
|
||||
@ajax:success="$dispatch('dialog:open')"
|
||||
@ajax:after="editLoading = false"
|
||||
@ajax:error="editLoading = false"
|
||||
x-target="contact"
|
||||
class="btn btn-sm btn-outline-primary me-2"
|
||||
:disabled="editLoading || deleteLoading"
|
||||
>
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm btn-outline-danger"
|
||||
hx-delete={ fmt.Sprintf("/records/%s", record.ID) }
|
||||
hx-target="closest tr"
|
||||
hx-swap="outerHTML"
|
||||
hx-confirm={ fmt.Sprintf("Are you sure you want to delete the record for \"%s\"?", record.Name) }
|
||||
<template x-if="!editLoading">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</template>
|
||||
<template x-if="editLoading">
|
||||
<span class="spinner-border spinner-border-sm"></span>
|
||||
</template>
|
||||
</a>
|
||||
<form
|
||||
method="delete"
|
||||
action={ templ.URL(fmt.Sprintf("/records/%s", record.ID)) }
|
||||
x-target="closest tr"
|
||||
@ajax:before={ fmt.Sprintf(`confirm('Are you sure you want to delete the record for "%s"?') || $event.preventDefault(); deleteLoading = true`, record.Name) }
|
||||
@ajax:after="deleteLoading = false"
|
||||
@ajax:error="deleteLoading = false"
|
||||
@ajax:success="$el.closest('tr').remove()"
|
||||
style="display: inline;"
|
||||
>
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm btn-outline-danger"
|
||||
type="submit"
|
||||
:disabled="editLoading || deleteLoading"
|
||||
>
|
||||
<template x-if="!deleteLoading">
|
||||
<i class="bi bi-trash"></i>
|
||||
</template>
|
||||
<template x-if="deleteLoading">
|
||||
<span class="spinner-border spinner-border-sm"></span>
|
||||
</template>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
|
|
|
@ -88,20 +88,20 @@ func Index(props IndexProps) templ.Component {
|
|||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</h1><div class=\"current-ip d-flex align-items-center\"><span class=\"me-2\">Current IP:</span> <span id=\"current-ip\" class=\"fw-bold\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</h1><div class=\"current-ip d-flex align-items-center\"><span class=\"me-2\">Current IP:</span> <span id=\"current-ip\" x-init class=\"fw-bold\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(props.CurrentIP)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 46, Col: 62}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 46, Col: 69}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span> <button class=\"btn btn-sm btn-outline-secondary ms-2\" title=\"Refresh current IP\" hx-get=\"/refresh-ip\" hx-target=\"#current-ip\" hx-indicator=\"#refresh-spinner\"><i class=\"bi bi-arrow-clockwise\"></i> <span id=\"refresh-spinner\" class=\"htmx-indicator spinner-border spinner-border-sm ms-1\"></span></button></div></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span> <a href=\"/refresh-ip\" x-target=\"current-ip\" class=\"btn btn-sm btn-outline-secondary ms-2 d-inline-flex align-items-center\" @ajax:before=\"$el.querySelector('.bi-arrow-clockwise').classList.add('spin')\" @ajax:after=\"$el.querySelector('.bi-arrow-clockwise').classList.remove('spin')\"><i class=\"bi bi-arrow-clockwise\"></i></a></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -124,15 +124,7 @@ func Index(props IndexProps) templ.Component {
|
|||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = ConfigModal(props.Config, props.UpdateFreqs).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = RecordModal(props.Config.Domain).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div></div></div><div class=\"toast-container\"></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -196,14 +188,14 @@ func ConfigStatus(config ConfigData) templ.Component {
|
|||
templ_7745c5c3_Var6 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<div class=\"card mb-4\"><div class=\"card-header d-flex justify-content-between align-items-center\"><h5 class=\"mb-0\">Configuration</h5><button class=\"btn btn-sm btn-outline-primary\" data-bs-toggle=\"modal\" data-bs-target=\"#configModal\">Edit</button></div><div class=\"card-body\"><div class=\"row\"><div class=\"col-md-4\"><strong>Domain:</strong> <span>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<div class=\"card mb-4\" id=\"config-status\"><div class=\"card-header d-flex justify-content-between align-items-center\" x-init x-data=\"{ editLoading: false, deleteLoading: false }\" @ajax:success=\"$dispatch('dialog:open')\"><h5 class=\"mb-0\">Configuration</h5><a href=\"/config\" @ajax:before=\"editLoading = true\" @ajax:success=\"$dispatch('dialog:open')\" @ajax:after=\"editLoading = false\" @ajax:error=\"editLoading = false\" x-target=\"contact\" class=\"btn btn-sm btn-outline-primary me-2\" :disabled=\"editLoading || deleteLoading\"><template x-if=\"!editLoading\"><span class=\"ms-1\">Edit <i class=\"bi bi-pencil\"></i></span></template><template x-if=\"editLoading\"><span class=\"spinner-border spinner-border-sm\"></span></template></a></div><div class=\"card-body\"><div class=\"row\"><div class=\"col-md-4\"><strong>Domain:</strong> <span>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(config.Domain)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 103, Col: 51}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 117, Col: 51}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
@ -216,7 +208,7 @@ func ConfigStatus(config ConfigData) templ.Component {
|
|||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(config.ZoneID)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 106, Col: 52}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 120, Col: 52}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
@ -229,7 +221,7 @@ func ConfigStatus(config ConfigData) templ.Component {
|
|||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(formatUpdateSchedule(config.UpdatePeriod))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 110, Col: 54}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 124, Col: 54}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
@ -264,7 +256,7 @@ func DNSRecordsSection(records []DNSRecord, currentIP string) templ.Component {
|
|||
templ_7745c5c3_Var10 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"card\"><div class=\"card-header d-flex justify-content-between align-items-center\"><h5 class=\"mb-0\">DNS Records</h5><div><button class=\"btn btn-sm btn-success me-2\" hx-post=\"/update-all-records\" hx-target=\"#dns-records-table\" hx-confirm=\"Are you sure you want to update all A records to your current IP?\" hx-indicator=\"#update-all-spinner\"><i class=\"bi bi-arrow-repeat\"></i> Update All to Current IP <span id=\"update-all-spinner\" class=\"htmx-indicator spinner-border spinner-border-sm ms-1\"></span></button> <button class=\"btn btn-sm btn-primary\" data-bs-toggle=\"modal\" data-bs-target=\"#recordModal\" onclick=\"resetRecordForm()\"><i class=\"bi bi-plus-lg\"></i> Add Record</button></div></div><div class=\"card-body p-0\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"card\"><div class=\"card-header d-flex justify-content-between align-items-center\"><h5 class=\"mb-0\">DNS Records</h5><div x-data=\"{ updating: false, addingRecord: false }\"><form method=\"post\" action=\"/update-all-records\" x-target=\"dns-records-table\" @ajax:before=\"confirm('Are you sure you want to update all A records to your current IP?') || $event.preventDefault(); updating = true\" @ajax:after=\"updating = false\" @ajax:error=\"updating = false\" style=\"display: inline;\"><button class=\"btn btn-sm btn-success me-2\" type=\"submit\" :disabled=\"updating || addingRecord\"><template x-if=\"!updating\"><span class=\"d-flex align-items-center\"><i class=\"bi bi-arrow-repeat me-1\"></i> Update All to Current IP</span></template><template x-if=\"updating\"><span class=\"d-flex align-items-center\"><span class=\"spinner-border spinner-border-sm me-2\"></span> Updating All Records...</span></template></button></form><a href=\"/records/new\" x-target=\"contact\" @ajax:before=\"addingRecord = true; $dispatch('dialog:open')\" @ajax:after=\"addingRecord = false\" @ajax:error=\"addingRecord = false\" class=\"btn btn-primary\" :disabled=\"updating || addingRecord\"><template x-if=\"!addingRecord\"><span class=\"d-flex align-items-center\"><i class=\"bi bi-plus-lg me-1\"></i> Add Record</span></template><template x-if=\"addingRecord\"><span class=\"d-flex align-items-center\"><span class=\"spinner-border spinner-border-sm me-2\"></span> Loading...</span></template></a></div></div><div class=\"card-body p-0\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -347,14 +339,14 @@ func DNSRecordRow(record DNSRecord, currentIP string) templ.Component {
|
|||
templ_7745c5c3_Var12 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<tr><td>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<tr x-data=\"{ editLoading: false, deleteLoading: false }\"><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(record.Type)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 178, Col: 19}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 224, Col: 19}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
@ -367,7 +359,7 @@ func DNSRecordRow(record DNSRecord, currentIP string) templ.Component {
|
|||
var templ_7745c5c3_Var14 string
|
||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(record.Name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 179, Col: 19}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 225, Col: 19}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
@ -380,7 +372,7 @@ func DNSRecordRow(record DNSRecord, currentIP string) templ.Component {
|
|||
var templ_7745c5c3_Var15 string
|
||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(record.Content)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 181, Col: 19}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 227, Col: 19}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
@ -416,7 +408,7 @@ func DNSRecordRow(record DNSRecord, currentIP string) templ.Component {
|
|||
var templ_7745c5c3_Var16 string
|
||||
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%ds", record.TTL))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 194, Col: 36}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 240, Col: 36}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
@ -433,46 +425,46 @@ func DNSRecordRow(record DNSRecord, currentIP string) templ.Component {
|
|||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</td><td><button class=\"btn btn-sm btn-outline-primary me-1\" hx-get=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</td><td><a href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var17 string
|
||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/edit-record/%s", record.ID))
|
||||
var templ_7745c5c3_Var17 templ.SafeURL
|
||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL(fmt.Sprintf("/edit-record/%s", record.ID)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 205, Col: 54}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 250, Col: 63}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "\" hx-target=\"#record-modal-content\" hx-on::after-request=\"if(event.detail.successful) bootstrap.Modal.getOrCreateInstance(document.getElementById('recordModal')).show()\"><i class=\"bi bi-pencil\"></i></button> <button class=\"btn btn-sm btn-outline-danger\" hx-delete=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "\" @ajax:before=\"editLoading = true\" @ajax:success=\"$dispatch('dialog:open')\" @ajax:after=\"editLoading = false\" @ajax:error=\"editLoading = false\" x-target=\"contact\" class=\"btn btn-sm btn-outline-primary me-2\" :disabled=\"editLoading || deleteLoading\"><template x-if=\"!editLoading\"><i class=\"bi bi-pencil\"></i></template><template x-if=\"editLoading\"><span class=\"spinner-border spinner-border-sm\"></span></template></a><form method=\"delete\" action=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var18 string
|
||||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/records/%s", record.ID))
|
||||
var templ_7745c5c3_Var18 templ.SafeURL
|
||||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL(fmt.Sprintf("/records/%s", record.ID)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 213, Col: 53}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 268, Col: 61}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "\" hx-target=\"closest tr\" hx-swap=\"outerHTML\" hx-confirm=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "\" x-target=\"closest tr\" @ajax:before=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var19 string
|
||||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("Are you sure you want to delete the record for \"%s\"?", record.Name))
|
||||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf(`confirm('Are you sure you want to delete the record for "%s"?') || $event.preventDefault(); deleteLoading = true`, record.Name))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 216, Col: 99}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/index.templ`, Line: 270, Col: 159}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "\"><i class=\"bi bi-trash\"></i></button></td></tr>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "\" @ajax:after=\"deleteLoading = false\" @ajax:error=\"deleteLoading = false\" @ajax:success=\"$el.closest('tr').remove()\" style=\"display: inline;\"><button class=\"btn btn-sm btn-outline-danger\" type=\"submit\" :disabled=\"editLoading || deleteLoading\"><template x-if=\"!deleteLoading\"><i class=\"bi bi-trash\"></i></template><template x-if=\"deleteLoading\"><span class=\"spinner-border spinner-border-sm\"></span></template></button></form></td></tr>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
|
|
@ -8,6 +8,16 @@ func Render(w io.Writer, component templ.Component) error {
|
|||
return component.Render(context.Background(), w)
|
||||
}
|
||||
|
||||
// RenderMultiple renders multiple components to an io.Writer in sequence
|
||||
func RenderMultiple(w io.Writer, components ...templ.Component) error {
|
||||
for _, component := range components {
|
||||
if err := component.Render(context.Background(), w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Layout is the base layout for all pages
|
||||
templ Layout(title string) {
|
||||
<!DOCTYPE html>
|
||||
|
@ -16,6 +26,8 @@ templ Layout(title string) {
|
|||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>{ title }</title>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/@imacrayon/alpine-ajax@0.12.2/dist/cdn.min.js"></script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.1/dist/cdn.min.js"></script>
|
||||
<link
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
|
||||
rel="stylesheet"
|
||||
|
@ -24,8 +36,9 @@ templ Layout(title string) {
|
|||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css"
|
||||
/>
|
||||
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<style>
|
||||
/* Base Styles */
|
||||
body {
|
||||
padding-top: 20px;
|
||||
background-color: #f8f9fa;
|
||||
|
@ -47,62 +60,185 @@ templ Layout(title string) {
|
|||
font-size: 0.8em;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.htmx-indicator {
|
||||
opacity: 0;
|
||||
transition: opacity 300ms ease-in;
|
||||
.spin {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
.htmx-request .htmx-indicator {
|
||||
opacity: 1;
|
||||
}
|
||||
.htmx-request.htmx-indicator {
|
||||
opacity: 1;
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Modal Styles */
|
||||
dialog {
|
||||
border: none !important;
|
||||
outline: none !important;
|
||||
border-radius: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
max-width: none;
|
||||
max-height: none;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
dialog[open] {
|
||||
border: none !important;
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
dialog::backdrop {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
backdrop-filter: blur(4px);
|
||||
animation: fadeIn 0.2s ease-out;
|
||||
}
|
||||
|
||||
.modal-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
padding: 1rem;
|
||||
animation: modalShow 0.3s ease-out;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
max-height: 90vh;
|
||||
overflow: hidden;
|
||||
transform: scale(1);
|
||||
animation: modalSlideIn 0.3s ease-out;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
padding: 1.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
margin: 0;
|
||||
font-weight: 600;
|
||||
color: #495057;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 2rem;
|
||||
max-height: 60vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
background: #f8f9fa;
|
||||
border-top: 1px solid #dee2e6;
|
||||
padding: 1.5rem;
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
/* Enhanced form styling within modals */
|
||||
.modal-body .form-label {
|
||||
color: #495057;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.modal-body .form-control,
|
||||
.modal-body .form-select {
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 8px;
|
||||
padding: 0.75rem;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.modal-body .form-control:focus,
|
||||
.modal-body .form-select:focus {
|
||||
border-color: #0d6efd;
|
||||
box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.1);
|
||||
}
|
||||
|
||||
.modal-body .input-group-text {
|
||||
border: 2px solid #e9ecef;
|
||||
border-left: none;
|
||||
background: #f8f9fa;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.modal-body .form-check {
|
||||
border: 1px solid #e9ecef;
|
||||
}
|
||||
|
||||
.modal-body .form-text {
|
||||
font-size: 0.875rem;
|
||||
color: #6c757d;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes modalShow {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes modalSlideIn {
|
||||
from {
|
||||
transform: scale(0.95) translateY(-20px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: scale(1) translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.modal-container {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
max-height: 95vh;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.modal-header,
|
||||
.modal-body,
|
||||
.modal-footer {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
max-height: 70vh;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<body id="body">
|
||||
<div class="toast-container position-fixed top-0 end-0 p-3">
|
||||
<ul x-sync id="notification_list" x-merge="prepend" role="status" class="list-unstyled"></ul>
|
||||
</div>
|
||||
{ children... }
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
// Simple toast function for HTMX responses
|
||||
document.body.addEventListener('htmx:afterRequest', function(evt) {
|
||||
const xhr = evt.detail.xhr;
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
const successMessage = xhr.getResponseHeader('HX-Success-Message');
|
||||
if (successMessage) {
|
||||
showToast(successMessage, 'success');
|
||||
}
|
||||
} else {
|
||||
const errorMessage = xhr.getResponseHeader('HX-Error-Message') || 'An error occurred';
|
||||
showToast(errorMessage, 'danger');
|
||||
}
|
||||
});
|
||||
|
||||
function showToast(message, type = "success") {
|
||||
const toastContainer = document.querySelector(".toast-container");
|
||||
const toast = document.createElement("div");
|
||||
toast.className = `toast align-items-center text-white bg-${type}`;
|
||||
toast.setAttribute("role", "alert");
|
||||
toast.setAttribute("aria-live", "assertive");
|
||||
toast.setAttribute("aria-atomic", "true");
|
||||
|
||||
toast.innerHTML = `
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">${message}</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
toastContainer.appendChild(toast);
|
||||
const bsToast = new bootstrap.Toast(toast);
|
||||
bsToast.show();
|
||||
|
||||
toast.addEventListener("hidden.bs.toast", () => {
|
||||
toast.remove();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<dialog id="global-dialog" x-init @dialog:open.window="$el.showModal()">
|
||||
<div id="contact"></div>
|
||||
</dialog>
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -3,253 +3,314 @@ package templates
|
|||
import "fmt"
|
||||
|
||||
templ ConfigModal(config ConfigData, frequencies []UpdateFrequency) {
|
||||
<div
|
||||
class="modal fade"
|
||||
id="configModal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="configModalLabel"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="configModalLabel">Configuration</h5>
|
||||
<div id="contact" class="modal-container">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Configuration Settings</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close"
|
||||
@click="$el.closest('dialog').close()"
|
||||
aria-label="Close"
|
||||
></button>
|
||||
</div>
|
||||
<form
|
||||
x-target="config-status"
|
||||
method="post"
|
||||
action="/config"
|
||||
@ajax:success="$el.closest('dialog').close()"
|
||||
x-data="{ saving: false }"
|
||||
@ajax:before="saving = true"
|
||||
@ajax:after="saving = false"
|
||||
@ajax:error="saving = false"
|
||||
>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label for="api-token" class="form-label fw-semibold">
|
||||
<i class="bi bi-key-fill text-primary me-2"></i>
|
||||
Cloudflare API Token
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
id="api-token"
|
||||
name="api_token"
|
||||
value={ config.ApiToken }
|
||||
placeholder="Enter your Cloudflare API token"
|
||||
required
|
||||
/>
|
||||
<div class="form-text">
|
||||
<i class="bi bi-info-circle me-1"></i>
|
||||
Create a token with <code>Zone.DNS:Edit</code> permissions in
|
||||
the Cloudflare dashboard.
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="zone-id-input" class="form-label fw-semibold">
|
||||
<i class="bi bi-globe text-info me-2"></i>
|
||||
Zone ID
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="zone-id-input"
|
||||
name="zone_id"
|
||||
value={ config.ZoneID }
|
||||
placeholder="e.g., 1234567890abcdef1234567890abcdef"
|
||||
required
|
||||
/>
|
||||
<div class="form-text">
|
||||
<i class="bi bi-info-circle me-1"></i>
|
||||
Found in the Cloudflare dashboard under your domain's overview page.
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="domain-input" class="form-label fw-semibold">
|
||||
<i class="bi bi-link-45deg text-success me-2"></i>
|
||||
Domain
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="domain-input"
|
||||
name="domain"
|
||||
value={ config.Domain }
|
||||
placeholder="e.g., example.com"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="update-period" class="form-label fw-semibold">
|
||||
<i class="bi bi-clock text-warning me-2"></i>
|
||||
Update Frequency
|
||||
</label>
|
||||
<select class="form-select" id="update-period" name="update_period">
|
||||
for _, freq := range frequencies {
|
||||
<option value={ freq.Value } selected?={ freq.Value == config.UpdatePeriod }>
|
||||
{ freq.Label }
|
||||
</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close"
|
||||
data-bs-dismiss="modal"
|
||||
aria-label="Close"
|
||||
></button>
|
||||
class="btn btn-secondary"
|
||||
@click="$el.closest('dialog').close()"
|
||||
>
|
||||
<i class="bi bi-x-lg me-1"></i>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
:disabled="saving"
|
||||
>
|
||||
<template x-if="!saving">
|
||||
<span class="d-flex align-items-center">
|
||||
<i class="bi bi-check-lg me-2"></i>
|
||||
Save Configuration
|
||||
</span>
|
||||
</template>
|
||||
<template x-if="saving">
|
||||
<span class="d-flex align-items-center">
|
||||
<span class="spinner-border spinner-border-sm me-2"></span>
|
||||
Saving...
|
||||
</span>
|
||||
</template>
|
||||
</button>
|
||||
</div>
|
||||
<form hx-post="/config" hx-target="body" hx-swap="outerHTML">
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label for="api-token" class="form-label">Cloudflare API Token</label>
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
id="api-token"
|
||||
name="api_token"
|
||||
value={ config.ApiToken }
|
||||
required
|
||||
/>
|
||||
<div class="form-text">
|
||||
Create a token with <code>Zone.DNS:Edit</code> permissions in
|
||||
the Cloudflare dashboard.
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="zone-id-input" class="form-label">Zone ID</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="zone-id-input"
|
||||
name="zone_id"
|
||||
value={ config.ZoneID }
|
||||
required
|
||||
/>
|
||||
<div class="form-text">
|
||||
Found in the Cloudflare dashboard under your domain's overview page.
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="domain-input" class="form-label">Domain</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="domain-input"
|
||||
name="domain"
|
||||
value={ config.Domain }
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="update-period" class="form-label">Update Frequency</label>
|
||||
<select class="form-select" id="update-period" name="update_period">
|
||||
for _, freq := range frequencies {
|
||||
<option value={ freq.Value } selected?={ freq.Value == config.UpdatePeriod }>
|
||||
{ freq.Label }
|
||||
</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
data-bs-dismiss="modal"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
Save
|
||||
<span class="htmx-indicator spinner-border spinner-border-sm ms-1"></span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
templ RecordModal(domain string) {
|
||||
<div
|
||||
class="modal fade"
|
||||
id="recordModal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="recordModalLabel"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<div id="record-modal-content" class="modal-content">
|
||||
@RecordForm("Add DNS Record", "", domain, DNSRecord{Type: "A", TTL: 1})
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
templ RecordForm(title, recordID, domain string, record DNSRecord) {
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">{ title }</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close"
|
||||
data-bs-dismiss="modal"
|
||||
aria-label="Close"
|
||||
></button>
|
||||
</div>
|
||||
<form
|
||||
if recordID != "" {
|
||||
hx-put={ fmt.Sprintf("/records/%s", recordID) }
|
||||
} else {
|
||||
hx-post="/records"
|
||||
}
|
||||
hx-target="#dns-records-table"
|
||||
hx-on::after-request="if(event.detail.successful) bootstrap.Modal.getInstance(document.getElementById('recordModal')).hide()"
|
||||
>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label for="record-name" class="form-label">Name</label>
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="record-name"
|
||||
name="name"
|
||||
placeholder="subdomain"
|
||||
value={ getRecordName(record.Name, domain) }
|
||||
required
|
||||
/>
|
||||
<span class="input-group-text">.{ domain }</span>
|
||||
</div>
|
||||
<div class="form-text">Use @ for the root domain</div>
|
||||
<div id="contact" class="modal-container">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<i class="bi bi-dns text-primary me-2"></i>
|
||||
{ title }
|
||||
</h5>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close"
|
||||
@click="$el.closest('dialog').close()"
|
||||
aria-label="Close"
|
||||
></button>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="record-type" class="form-label">Type</label>
|
||||
<select
|
||||
class="form-select"
|
||||
id="record-type"
|
||||
name="type"
|
||||
onchange="toggleMyIPOption()"
|
||||
>
|
||||
<option value="A" selected?={ record.Type == "A" }>A</option>
|
||||
<option value="AAAA" selected?={ record.Type == "AAAA" }>AAAA</option>
|
||||
<option value="CNAME" selected?={ record.Type == "CNAME" }>CNAME</option>
|
||||
<option value="TXT" selected?={ record.Type == "TXT" }>TXT</option>
|
||||
<option value="MX" selected?={ record.Type == "MX" }>MX</option>
|
||||
</select>
|
||||
<div id="error-message" class="alert alert-danger d-none mx-3 mt-3" role="alert">
|
||||
<i class="bi bi-exclamation-triangle-fill me-2"></i>
|
||||
<span class="error-text"></span>
|
||||
</div>
|
||||
<div class="mb-3" id="content-group">
|
||||
<label for="record-content" class="form-label">Content</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="record-content"
|
||||
name="content"
|
||||
value={ record.Content }
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-3 form-check" id="use-my-ip-group" style="display: none;">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="form-check-input"
|
||||
id="use-my-ip"
|
||||
name="use_my_ip"
|
||||
onchange="toggleContentField()"
|
||||
/>
|
||||
<label class="form-check-label" for="use-my-ip">Use my current IP address</label>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="record-ttl" class="form-label">TTL</label>
|
||||
<select class="form-select" id="record-ttl" name="ttl">
|
||||
<option value="1" selected?={ record.TTL == 1 }>Auto</option>
|
||||
<option value="120" selected?={ record.TTL == 120 }>2 minutes</option>
|
||||
<option value="300" selected?={ record.TTL == 300 }>5 minutes</option>
|
||||
<option value="600" selected?={ record.TTL == 600 }>10 minutes</option>
|
||||
<option value="1800" selected?={ record.TTL == 1800 }>30 minutes</option>
|
||||
<option value="3600" selected?={ record.TTL == 3600 }>1 hour</option>
|
||||
<option value="7200" selected?={ record.TTL == 7200 }>2 hours</option>
|
||||
<option value="18000" selected?={ record.TTL == 18000 }>5 hours</option>
|
||||
<option value="43200" selected?={ record.TTL == 43200 }>12 hours</option>
|
||||
<option value="86400" selected?={ record.TTL == 86400 }>1 day</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3 form-check">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="form-check-input"
|
||||
id="record-proxied"
|
||||
name="proxied"
|
||||
checked?={ record.Proxied }
|
||||
/>
|
||||
<label class="form-check-label" for="record-proxied">Proxied through Cloudflare</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
data-bs-dismiss="modal"
|
||||
<form
|
||||
if recordID != "" {
|
||||
method="put"
|
||||
action={ templ.URL(fmt.Sprintf("/records/%s", recordID)) }
|
||||
} else {
|
||||
method="post"
|
||||
action="/records"
|
||||
}
|
||||
x-target="dns-records-table"
|
||||
x-target.error="none"
|
||||
@ajax:success="$el.closest('dialog').close()"
|
||||
x-data="{ saving: false }"
|
||||
@ajax:before="saving = true"
|
||||
@ajax:after="saving = false"
|
||||
@ajax:error="saving = false"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
Save
|
||||
<span class="htmx-indicator spinner-border spinner-border-sm ms-1"></span>
|
||||
</button>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-md-8 mb-3">
|
||||
<label for="record-name" class="form-label fw-semibold">
|
||||
<i class="bi bi-tag text-info me-2"></i>
|
||||
Record Name
|
||||
</label>
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="record-name"
|
||||
name="name"
|
||||
placeholder="subdomain"
|
||||
value={ getRecordName(record.Name, domain) }
|
||||
required
|
||||
/>
|
||||
<span class="input-group-text bg-light text-muted">.{ domain }</span>
|
||||
</div>
|
||||
<div class="form-text">
|
||||
<i class="bi bi-info-circle me-1"></i>
|
||||
Use <code>{ "@" }</code> { "for" } the root domain
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label for="record-type" class="form-label fw-semibold">
|
||||
<i class="bi bi-diagram-3 text-success me-2"></i>
|
||||
Type
|
||||
</label>
|
||||
<select
|
||||
class="form-select"
|
||||
id="record-type"
|
||||
name="type"
|
||||
onchange="toggleMyIPOption()"
|
||||
>
|
||||
<option value="A" selected?={ record.Type == "A" }>A (IPv4)</option>
|
||||
<option value="AAAA" selected?={ record.Type == "AAAA" }>AAAA (IPv6)</option>
|
||||
<option value="CNAME" selected?={ record.Type == "CNAME" }>CNAME</option>
|
||||
<option value="TXT" selected?={ record.Type == "TXT" }>TXT</option>
|
||||
<option value="MX" selected?={ record.Type == "MX" }>MX</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3" id="content-group">
|
||||
<label for="record-content" class="form-label fw-semibold">
|
||||
<i class="bi bi-file-text text-warning me-2"></i>
|
||||
Content
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="record-content"
|
||||
name="content"
|
||||
value={ record.Content }
|
||||
placeholder="Enter the record value"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-3 form-check bg-light p-3 rounded" id="use-my-ip-group" style="display: none;">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="form-check-input"
|
||||
id="use-my-ip"
|
||||
name="use_my_ip"
|
||||
onchange="toggleContentField()"
|
||||
/>
|
||||
<label class="form-check-label fw-semibold" for="use-my-ip">
|
||||
<i class="bi bi-geo-alt text-primary me-2"></i>
|
||||
Use my current IP address
|
||||
</label>
|
||||
<div class="form-text">
|
||||
Automatically use your current public IP address
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="record-ttl" class="form-label fw-semibold">
|
||||
<i class="bi bi-clock-history text-secondary me-2"></i>
|
||||
TTL (Time to Live)
|
||||
</label>
|
||||
<select class="form-select" id="record-ttl" name="ttl">
|
||||
<option value="1" selected?={ record.TTL == 1 }>Auto</option>
|
||||
<option value="120" selected?={ record.TTL == 120 }>2 minutes</option>
|
||||
<option value="300" selected?={ record.TTL == 300 }>5 minutes</option>
|
||||
<option value="600" selected?={ record.TTL == 600 }>10 minutes</option>
|
||||
<option value="1800" selected?={ record.TTL == 1800 }>30 minutes</option>
|
||||
<option value="3600" selected?={ record.TTL == 3600 }>1 hour</option>
|
||||
<option value="7200" selected?={ record.TTL == 7200 }>2 hours</option>
|
||||
<option value="18000" selected?={ record.TTL == 18000 }>5 hours</option>
|
||||
<option value="43200" selected?={ record.TTL == 43200 }>12 hours</option>
|
||||
<option value="86400" selected?={ record.TTL == 86400 }>1 day</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3 d-flex align-items-end">
|
||||
<div class="form-check bg-light p-3 rounded w-100">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="form-check-input"
|
||||
id="record-proxied"
|
||||
name="proxied"
|
||||
checked?={ record.Proxied }
|
||||
/>
|
||||
<label class="form-check-label fw-semibold" for="record-proxied">
|
||||
<i class="bi bi-shield-check text-success me-2"></i>
|
||||
Proxied through Cloudflare
|
||||
</label>
|
||||
<div class="form-text">
|
||||
Enable Cloudflare's proxy and security features
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
@click="$el.closest('dialog').close()"
|
||||
>
|
||||
<i class="bi bi-x-lg me-1"></i>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
:disabled="saving"
|
||||
>
|
||||
<template x-if="!saving">
|
||||
<span class="d-flex align-items-center">
|
||||
<i class="bi bi-check-lg me-2"></i>
|
||||
if recordID != "" {
|
||||
Update Record
|
||||
} else {
|
||||
Create Record
|
||||
}
|
||||
</span>
|
||||
</template>
|
||||
<template x-if="saving">
|
||||
<span class="d-flex align-items-center">
|
||||
<span class="spinner-border spinner-border-sm me-2"></span>
|
||||
if recordID != "" {
|
||||
Updating...
|
||||
} else {
|
||||
Creating...
|
||||
}
|
||||
</span>
|
||||
</template>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
<script>
|
||||
function toggleMyIPOption() {
|
||||
const recordType = document.getElementById('record-type').value;
|
||||
const useMyIPGroup = document.getElementById('use-my-ip-group');
|
||||
const contentGroup = document.getElementById('content-group');
|
||||
|
||||
if (recordType === 'A') {
|
||||
useMyIPGroup.style.display = 'block';
|
||||
} else {
|
||||
useMyIPGroup.style.display = 'none';
|
||||
contentGroup.style.display = 'block';
|
||||
document.getElementById('use-my-ip').checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleContentField() {
|
||||
const useMyIP = document.getElementById('use-my-ip').checked;
|
||||
const contentGroup = document.getElementById('content-group');
|
||||
contentGroup.style.display = useMyIP ? 'none' : 'block';
|
||||
}
|
||||
|
||||
function resetRecordForm() {
|
||||
setTimeout(() => {
|
||||
document.getElementById('record-type').value = 'A';
|
||||
toggleMyIPOption();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Initialize the form state
|
||||
toggleMyIPOption();
|
||||
</script>
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -31,46 +31,46 @@ func ConfigModal(config ConfigData, frequencies []UpdateFrequency) templ.Compone
|
|||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"modal fade\" id=\"configModal\" tabindex=\"-1\" aria-labelledby=\"configModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"configModalLabel\">Configuration</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><form hx-post=\"/config\" hx-target=\"body\" hx-swap=\"outerHTML\"><div class=\"modal-body\"><div class=\"mb-3\"><label for=\"api-token\" class=\"form-label\">Cloudflare API Token</label> <input type=\"password\" class=\"form-control\" id=\"api-token\" name=\"api_token\" value=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div id=\"contact\" class=\"modal-container\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\">Configuration Settings</h5><button type=\"button\" class=\"btn-close\" @click=\"$el.closest('dialog').close()\" aria-label=\"Close\"></button></div><form x-target=\"config-status\" method=\"post\" action=\"/config\" @ajax:success=\"$el.closest('dialog').close()\" x-data=\"{ saving: false }\" @ajax:before=\"saving = true\" @ajax:after=\"saving = false\" @ajax:error=\"saving = false\"><div class=\"modal-body\"><div class=\"mb-3\"><label for=\"api-token\" class=\"form-label fw-semibold\"><i class=\"bi bi-key-fill text-primary me-2\"></i> Cloudflare API Token</label> <input type=\"password\" class=\"form-control\" id=\"api-token\" name=\"api_token\" value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(config.ApiToken)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 33, Col: 31}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 38, Col: 30}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" required><div class=\"form-text\">Create a token with <code>Zone.DNS:Edit</code> permissions in the Cloudflare dashboard.</div></div><div class=\"mb-3\"><label for=\"zone-id-input\" class=\"form-label\">Zone ID</label> <input type=\"text\" class=\"form-control\" id=\"zone-id-input\" name=\"zone_id\" value=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" placeholder=\"Enter your Cloudflare API token\" required><div class=\"form-text\"><i class=\"bi bi-info-circle me-1\"></i> Create a token with <code>Zone.DNS:Edit</code> permissions in the Cloudflare dashboard.</div></div><div class=\"mb-3\"><label for=\"zone-id-input\" class=\"form-label fw-semibold\"><i class=\"bi bi-globe text-info me-2\"></i> Zone ID</label> <input type=\"text\" class=\"form-control\" id=\"zone-id-input\" name=\"zone_id\" value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(config.ZoneID)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 48, Col: 29}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 58, Col: 28}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\" required><div class=\"form-text\">Found in the Cloudflare dashboard under your domain's overview page.</div></div><div class=\"mb-3\"><label for=\"domain-input\" class=\"form-label\">Domain</label> <input type=\"text\" class=\"form-control\" id=\"domain-input\" name=\"domain\" value=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\" placeholder=\"e.g., 1234567890abcdef1234567890abcdef\" required><div class=\"form-text\"><i class=\"bi bi-info-circle me-1\"></i> Found in the Cloudflare dashboard under your domain's overview page.</div></div><div class=\"mb-3\"><label for=\"domain-input\" class=\"form-label fw-semibold\"><i class=\"bi bi-link-45deg text-success me-2\"></i> Domain</label> <input type=\"text\" class=\"form-control\" id=\"domain-input\" name=\"domain\" value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(config.Domain)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 62, Col: 29}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 77, Col: 28}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" required></div><div class=\"mb-3\"><label for=\"update-period\" class=\"form-label\">Update Frequency</label> <select class=\"form-select\" id=\"update-period\" name=\"update_period\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" placeholder=\"e.g., example.com\" required></div><div class=\"mb-3\"><label for=\"update-period\" class=\"form-label fw-semibold\"><i class=\"bi bi-clock text-warning me-2\"></i> Update Frequency</label> <select class=\"form-select\" id=\"update-period\" name=\"update_period\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ func ConfigModal(config ConfigData, frequencies []UpdateFrequency) templ.Compone
|
|||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(freq.Value)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 70, Col: 35}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 89, Col: 34}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
@ -105,7 +105,7 @@ func ConfigModal(config ConfigData, frequencies []UpdateFrequency) templ.Compone
|
|||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(freq.Label)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 71, Col: 22}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 90, Col: 21}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
@ -116,44 +116,7 @@ func ConfigModal(config ConfigData, frequencies []UpdateFrequency) templ.Compone
|
|||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</select></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"submit\" class=\"btn btn-primary\">Save <span class=\"htmx-indicator spinner-border spinner-border-sm ms-1\"></span></button></div></form></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func RecordModal(domain string) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var7 == nil {
|
||||
templ_7745c5c3_Var7 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"modal fade\" id=\"recordModal\" tabindex=\"-1\" aria-labelledby=\"recordModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog\"><div id=\"record-modal-content\" class=\"modal-content\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = RecordForm("Add DNS Record", "", domain, DNSRecord{Type: "A", TTL: 1}).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div></div></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</select></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" @click=\"$el.closest('dialog').close()\"><i class=\"bi bi-x-lg me-1\"></i> Cancel</button> <button type=\"submit\" class=\"btn btn-primary\" :disabled=\"saving\"><template x-if=\"!saving\"><span class=\"d-flex align-items-center\"><i class=\"bi bi-check-lg me-2\"></i> Save Configuration</span></template><template x-if=\"saving\"><span class=\"d-flex align-items-center\"><span class=\"spinner-border spinner-border-sm me-2\"></span> Saving...</span></template></button></div></form></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -177,79 +140,105 @@ func RecordForm(title, recordID, domain string, record DNSRecord) templ.Componen
|
|||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var8 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var8 == nil {
|
||||
templ_7745c5c3_Var8 = templ.NopComponent
|
||||
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var7 == nil {
|
||||
templ_7745c5c3_Var7 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<div class=\"modal-header\"><h5 class=\"modal-title\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div id=\"contact\" class=\"modal-container\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\"><i class=\"bi bi-dns text-primary me-2\"></i> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 114, Col: 33}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 135, Col: 12}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button></div><form")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</h5><button type=\"button\" class=\"btn-close\" @click=\"$el.closest('dialog').close()\" aria-label=\"Close\"></button></div><div id=\"error-message\" class=\"alert alert-danger d-none mx-3 mt-3\" role=\"alert\"><i class=\"bi bi-exclamation-triangle-fill me-2\"></i> <span class=\"error-text\"></span></div><form")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if recordID != "" {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, " hx-put=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, " method=\"put\" action=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/records/%s", recordID))
|
||||
var templ_7745c5c3_Var9 templ.SafeURL
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL(fmt.Sprintf("/records/%s", recordID)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 124, Col: 48}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 151, Col: 61}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, " hx-post=\"/records\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, " method=\"post\" action=\"/records\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, " hx-target=\"#dns-records-table\" hx-on::after-request=\"if(event.detail.successful) bootstrap.Modal.getInstance(document.getElementById('recordModal')).hide()\"><div class=\"modal-body\"><div class=\"mb-3\"><label for=\"record-name\" class=\"form-label\">Name</label><div class=\"input-group\"><input type=\"text\" class=\"form-control\" id=\"record-name\" name=\"name\" placeholder=\"subdomain\" value=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, " x-target=\"dns-records-table\" x-target.error=\"none\" @ajax:success=\"$el.closest('dialog').close()\" x-data=\"{ saving: false }\" @ajax:before=\"saving = true\" @ajax:after=\"saving = false\" @ajax:error=\"saving = false\"><div class=\"modal-body\"><div class=\"row\"><div class=\"col-md-8 mb-3\"><label for=\"record-name\" class=\"form-label fw-semibold\"><i class=\"bi bi-tag text-info me-2\"></i> Record Name</label><div class=\"input-group\"><input type=\"text\" class=\"form-control\" id=\"record-name\" name=\"name\" placeholder=\"subdomain\" value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(getRecordName(record.Name, domain))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 178, Col: 51}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\" required> <span class=\"input-group-text bg-light text-muted\">.")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var11 string
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(getRecordName(record.Name, domain))
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(domain)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 141, Col: 48}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 181, Col: 68}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\" required> <span class=\"input-group-text\">.")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</span></div><div class=\"form-text\"><i class=\"bi bi-info-circle me-1\"></i> Use <code>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(domain)
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs("@")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 144, Col: 45}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 185, Col: 23}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</span></div><div class=\"form-text\">Use @ for the root domain</div></div><div class=\"mb-3\"><label for=\"record-type\" class=\"form-label\">Type</label> <select class=\"form-select\" id=\"record-type\" name=\"type\" onchange=\"toggleMyIPOption()\"><option value=\"A\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</code> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs("for")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 185, Col: 40}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, " the root domain</div></div><div class=\"col-md-4 mb-3\"><label for=\"record-type\" class=\"form-label fw-semibold\"><i class=\"bi bi-diagram-3 text-success me-2\"></i> Type</label> <select class=\"form-select\" id=\"record-type\" name=\"type\" onchange=\"toggleMyIPOption()\"><option value=\"A\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -259,7 +248,7 @@ func RecordForm(title, recordID, domain string, record DNSRecord) templ.Componen
|
|||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, ">A</option> <option value=\"AAAA\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, ">A (IPv4)</option> <option value=\"AAAA\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -269,7 +258,7 @@ func RecordForm(title, recordID, domain string, record DNSRecord) templ.Componen
|
|||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, ">AAAA</option> <option value=\"CNAME\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, ">AAAA (IPv6)</option> <option value=\"CNAME\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -299,20 +288,20 @@ func RecordForm(title, recordID, domain string, record DNSRecord) templ.Componen
|
|||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, ">MX</option></select></div><div class=\"mb-3\" id=\"content-group\"><label for=\"record-content\" class=\"form-label\">Content</label> <input type=\"text\" class=\"form-control\" id=\"record-content\" name=\"content\" value=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, ">MX</option></select></div></div><div class=\"mb-3\" id=\"content-group\"><label for=\"record-content\" class=\"form-label fw-semibold\"><i class=\"bi bi-file-text text-warning me-2\"></i> Content</label> <input type=\"text\" class=\"form-control\" id=\"record-content\" name=\"content\" value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(record.Content)
|
||||
var templ_7745c5c3_Var14 string
|
||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(record.Content)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 170, Col: 27}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/modal.templ`, Line: 217, Col: 29}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\" required></div><div class=\"mb-3 form-check\" id=\"use-my-ip-group\" style=\"display: none;\"><input type=\"checkbox\" class=\"form-check-input\" id=\"use-my-ip\" name=\"use_my_ip\" onchange=\"toggleContentField()\"> <label class=\"form-check-label\" for=\"use-my-ip\">Use my current IP address</label></div><div class=\"mb-3\"><label for=\"record-ttl\" class=\"form-label\">TTL</label> <select class=\"form-select\" id=\"record-ttl\" name=\"ttl\"><option value=\"1\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\" placeholder=\"Enter the record value\" required></div><div class=\"mb-3 form-check bg-light p-3 rounded\" id=\"use-my-ip-group\" style=\"display: none;\"><input type=\"checkbox\" class=\"form-check-input\" id=\"use-my-ip\" name=\"use_my_ip\" onchange=\"toggleContentField()\"> <label class=\"form-check-label fw-semibold\" for=\"use-my-ip\"><i class=\"bi bi-geo-alt text-primary me-2\"></i> Use my current IP address</label><div class=\"form-text\">Automatically use your current public IP address</div></div><div class=\"row\"><div class=\"col-md-6 mb-3\"><label for=\"record-ttl\" class=\"form-label fw-semibold\"><i class=\"bi bi-clock-history text-secondary me-2\"></i> TTL (Time to Live)</label> <select class=\"form-select\" id=\"record-ttl\" name=\"ttl\"><option value=\"1\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -412,7 +401,7 @@ func RecordForm(title, recordID, domain string, record DNSRecord) templ.Componen
|
|||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, ">1 day</option></select></div><div class=\"mb-3 form-check\"><input type=\"checkbox\" class=\"form-check-input\" id=\"record-proxied\" name=\"proxied\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, ">1 day</option></select></div><div class=\"col-md-6 mb-3 d-flex align-items-end\"><div class=\"form-check bg-light p-3 rounded w-100\"><input type=\"checkbox\" class=\"form-check-input\" id=\"record-proxied\" name=\"proxied\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -422,7 +411,37 @@ func RecordForm(title, recordID, domain string, record DNSRecord) templ.Componen
|
|||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "> <label class=\"form-check-label\" for=\"record-proxied\">Proxied through Cloudflare</label></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Cancel</button> <button type=\"submit\" class=\"btn btn-primary\">Save <span class=\"htmx-indicator spinner-border spinner-border-sm ms-1\"></span></button></div></form><script>\n\t\tfunction toggleMyIPOption() {\n\t\t\tconst recordType = document.getElementById('record-type').value;\n\t\t\tconst useMyIPGroup = document.getElementById('use-my-ip-group');\n\t\t\tconst contentGroup = document.getElementById('content-group');\n\n\t\t\tif (recordType === 'A') {\n\t\t\t\tuseMyIPGroup.style.display = 'block';\n\t\t\t} else {\n\t\t\t\tuseMyIPGroup.style.display = 'none';\n\t\t\t\tcontentGroup.style.display = 'block';\n\t\t\t\tdocument.getElementById('use-my-ip').checked = false;\n\t\t\t}\n\t\t}\n\n\t\tfunction toggleContentField() {\n\t\t\tconst useMyIP = document.getElementById('use-my-ip').checked;\n\t\t\tconst contentGroup = document.getElementById('content-group');\n\t\t\tcontentGroup.style.display = useMyIP ? 'none' : 'block';\n\t\t}\n\n\t\tfunction resetRecordForm() {\n\t\t\tsetTimeout(() => {\n\t\t\t\tdocument.getElementById('record-type').value = 'A';\n\t\t\t\ttoggleMyIPOption();\n\t\t\t}, 100);\n\t\t}\n\n\t\t// Initialize the form state\n\t\ttoggleMyIPOption();\n\t</script>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "> <label class=\"form-check-label fw-semibold\" for=\"record-proxied\"><i class=\"bi bi-shield-check text-success me-2\"></i> Proxied through Cloudflare</label><div class=\"form-text\">Enable Cloudflare's proxy and security features</div></div></div></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" @click=\"$el.closest('dialog').close()\"><i class=\"bi bi-x-lg me-1\"></i> Cancel</button> <button type=\"submit\" class=\"btn btn-primary\" :disabled=\"saving\"><template x-if=\"!saving\"><span class=\"d-flex align-items-center\"><i class=\"bi bi-check-lg me-2\"></i> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if recordID != "" {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "Update Record")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "Create Record")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "</span></template><template x-if=\"saving\"><span class=\"d-flex align-items-center\"><span class=\"spinner-border spinner-border-sm me-2\"></span> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if recordID != "" {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "Updating...")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "Creating...")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "</span></template></button></div></form></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
|
73
templates/toast.templ
Normal file
73
templates/toast.templ
Normal file
|
@ -0,0 +1,73 @@
|
|||
|
||||
package templates
|
||||
|
||||
import "fmt"
|
||||
|
||||
// NotificationList renders the container for notifications
|
||||
templ NotificationList() {
|
||||
<ul x-sync id="notification_list" x-merge="prepend" role="status" class="list-unstyled">
|
||||
{ children... }
|
||||
</ul>
|
||||
}
|
||||
|
||||
// NotificationToast renders a single notification toast
|
||||
templ NotificationToast(message, notificationType string) {
|
||||
<li>
|
||||
<div
|
||||
class={ fmt.Sprintf("toast align-items-center text-white bg-%s show", notificationType) }
|
||||
role="alert"
|
||||
aria-live="assertive"
|
||||
aria-atomic="true"
|
||||
x-data="{
|
||||
show: false,
|
||||
init() {
|
||||
this.$nextTick(() => this.show = true);
|
||||
setTimeout(() => this.dismiss(), 6000);
|
||||
},
|
||||
dismiss() {
|
||||
this.show = false;
|
||||
setTimeout(() => this.$root.remove(), 500);
|
||||
}
|
||||
}"
|
||||
x-show="show"
|
||||
x-transition.duration.500ms
|
||||
>
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">{ message }</div>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close btn-close-white me-2 m-auto"
|
||||
@click="dismiss()"
|
||||
aria-label="Close"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
|
||||
// Helper functions for common notification types
|
||||
templ SuccessNotification(message string) {
|
||||
@NotificationList() {
|
||||
@NotificationToast(message, "success")
|
||||
}
|
||||
}
|
||||
|
||||
templ ErrorNotification(message string) {
|
||||
@NotificationList() {
|
||||
@NotificationToast(message, "danger")
|
||||
}
|
||||
}
|
||||
|
||||
templ WarningNotification(message string) {
|
||||
@NotificationList() {
|
||||
@NotificationToast(message, "warning")
|
||||
}
|
||||
}
|
||||
|
||||
templ InfoNotification(message string) {
|
||||
@NotificationList() {
|
||||
@NotificationToast(message, "info")
|
||||
}
|
||||
}
|
306
templates/toast_templ.go
Normal file
306
templates/toast_templ.go
Normal file
|
@ -0,0 +1,306 @@
|
|||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.898
|
||||
|
||||
package templates
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import "fmt"
|
||||
|
||||
// NotificationList renders the container for notifications
|
||||
func NotificationList() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<ul x-sync id=\"notification_list\" x-merge=\"prepend\" role=\"status\" class=\"list-unstyled\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</ul>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// NotificationToast renders a single notification toast
|
||||
func NotificationToast(message, notificationType string) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var2 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var2 == nil {
|
||||
templ_7745c5c3_Var2 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 = []any{fmt.Sprintf("toast align-items-center text-white bg-%s show", notificationType)}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var3).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/toast.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\" role=\"alert\" aria-live=\"assertive\" aria-atomic=\"true\" x-data=\"{\n\t\t\t\tshow: false,\n\t\t\t\tinit() {\n\t\t\t\t\tthis.$nextTick(() => this.show = true);\n\t\t\t\t\tsetTimeout(() => this.dismiss(), 6000);\n\t\t\t\t},\n\t\t\t\tdismiss() {\n\t\t\t\t\tthis.show = false;\n\t\t\t\t\tsetTimeout(() => this.$root.remove(), 500);\n\t\t\t\t}\n\t\t\t}\" x-show=\"show\" x-transition.duration.500ms><div class=\"d-flex\"><div class=\"toast-body\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(message)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/toast.templ`, Line: 36, Col: 37}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</div><button type=\"button\" class=\"btn-close btn-close-white me-2 m-auto\" @click=\"dismiss()\" aria-label=\"Close\">×</button></div></div></li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Helper functions for common notification types
|
||||
func SuccessNotification(message string) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var6 == nil {
|
||||
templ_7745c5c3_Var6 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var7 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = NotificationToast(message, "success").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = NotificationList().Render(templ.WithChildren(ctx, templ_7745c5c3_Var7), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func ErrorNotification(message string) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var8 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var8 == nil {
|
||||
templ_7745c5c3_Var8 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var9 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = NotificationToast(message, "danger").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = NotificationList().Render(templ.WithChildren(ctx, templ_7745c5c3_Var9), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func WarningNotification(message string) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var10 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var10 == nil {
|
||||
templ_7745c5c3_Var10 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var11 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = NotificationToast(message, "warning").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = NotificationList().Render(templ.WithChildren(ctx, templ_7745c5c3_Var11), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func InfoNotification(message string) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var12 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var12 == nil {
|
||||
templ_7745c5c3_Var12 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var13 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = NotificationToast(message, "info").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = NotificationList().Render(templ.WithChildren(ctx, templ_7745c5c3_Var13), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
Loading…
Add table
Add a link
Reference in a new issue