def postJson(url, dataObject)
fetch `${url}` with method:'POST', body:dataObject as JSON, headers:{content-type:'application/json'}
return result
end
def getJsonUrlAsObject(url)
fetch `${url}` with method:'GET', headers:{content-type:'application/json'}
return result as Object
end
def countdownSeconds(el, sec)
set i to sec
set _s to el's textContent
repeat until i is 0
put `${_s} (${i}s)` into el
decrement i by 1
wait 1s
end
end
def setCheckboxes(el, option)
repeat for e in ( in el)
if option == 'all'
set e's @checked to 'true'
set e.checked to true
else if option == 'none'
remove @checked from e
set e.checked to false
else if option == 'invert'
if e.checked
toggle [@checked='false'] on e
set e.checked to false
else
toggle [@checked='true'] on e
set e.checked to true
end
else if option == 'toggle'
toggle [@checked='true'] on e
if e's @checked set e.checked to true else set e.checked to false end
end
end
end
behavior trCheckboxSelect
on click
document.getSelection().removeAllRanges()
if not event.shiftKey
take .select-tr-element from
in closest
for me
call setCheckboxes(me, 'toggle') unless event.target.tagName.toLowerCase() === 'a'
else
document.getSelection().removeAllRanges()
get first .select-tr-element in closest
if it
set toggleTo to 'none'
if checked of first .multiselect in it
set toggleTo to 'all'
end
set selectedTrElement to it
if it.rowIndex < my.rowIndex
repeat while selectedTrElement.nextElementSibling
set selectedTrElement to selectedTrElement.nextElementSibling
call setCheckboxes(selectedTrElement, toggleTo)
if selectedTrElement is me
break
end
end
else
repeat while selectedTrElement.previousElementSibling
call setCheckboxes(selectedTrElement, toggleTo)
if selectedTrElement is me
break
end
set selectedTrElement to selectedTrElement.previousElementSibling
end
end
end
end
end
end
behavior buttonCheckHtmxResponse
on htmx:afterRequest from closest to me
if (closest to me) != (event.target) exit end
set :_v to my textContent unless :_v
if event.detail.successful then
put `👍` into me
else
put `🤖 An error occured` into me
end
wait 1s
put :_v into me
set :_v to null
end
end
behavior confirmButton
init set :inner to my.innerHTML end
on every click
halt the event
end
on click[event.detail==1] from me queue none
set x to 3
repeat until x == 0
put `Confirm ${x}x` into me
wait for a click or 1500ms
if the result's type is 'click'
decrement x
else
put :inner into me
exit
end
end
put :inner into me
trigger confirmedButton
end
end
behavior inlineHtmxRename
init
set :_textContent to my.textContent
end
on click halt the event end
on htmx:afterRequest
if event.detail.successful == true
set :_textContent to my.textContent
end
set my.textContent to :_textContent
end
on htmx:confirm(issueRequest)
halt the event
call confirm(`${:_textContent} to ${my.textContent}?`)
if not result set my.textContent to :_textContent else issueRequest() end
end
on blur
if my.textContent == '' set my.textContent to :_textContent then exit end
if my.textContent == :_textContent exit end
set @hx-vals to `{"${my @data-patch-parameter}": "${my.textContent}"}`
trigger editContent on me
end
on keydown[keyCode == 13]
me.blur()
halt the event
end
end
behavior tresorToggle
def setUnlocked
get #vault-unlock-pin
add @disabled to it
set its @placeholder to 'Tresor is unlocked'
set #vault-unlock's textContent to '🔓'
end
def setLocked
get #vault-unlock-pin
remove @disabled from it
set its @placeholder to 'Tresor password'
set #vault-unlock's textContent to '🔐'
end
def noTresor
get #vault-unlock-pin
add @disabled to it
set its @placeholder to 'No tresor available'
set #vault-unlock's textContent to '⛔'
end
init
if window.vault.isUnlocked()
call setUnlocked()
else
if #vault-unlock's @data-tresor != ""
call setLocked()
else
call noTresor()
end
end
end
on keydown[keyCode == 13] from #vault-unlock-pin
trigger click on #vault-unlock unless #vault-unlock-pin's value is empty
end
on click from #vault-unlock
halt the event
if not window.vault.isUnlocked()
exit unless value of #vault-unlock-pin
call JSON.parse(#vault-unlock's @data-tresor) set keyData to the result
call VaultUnlockPrivateKey(value of #vault-unlock-pin, keyData)
call setUnlocked()
else
call window.vault.lock()
call setLocked()
end
set value of #vault-unlock-pin to ''
on exception(error)
trigger notification(
title: 'Tresor error',
level: 'validationError',
message: 'Could not unlock tresor, check your PIN',
duration: 3000,
locations: ['vault-unlock-pin']
)
end
end
behavior bodydefault
on htmx:wsError or htmx:wsClose
set #ws-indicator's textContent to '⭕'
end
on keydown
exit unless window.vault.isUnlocked()
if navigator.platform.toUpperCase().indexOf('MAC') >= 0
set ctrlOrCmd to event.metaKey
else
set ctrlOrCmd to event.ctrlKey
end
if (event.key is "F5" or (ctrlOrCmd and event.key.toLowerCase() === "r")) or ((ctrlOrCmd and event.shiftKey and event.key.toLowerCase() === "r") or (event.shiftKey and e.key === "F5"))
trigger notification(
title: 'Unlocked session',
level: 'user',
message: 'Preventing window reload due to unlocked session',
duration: 2000,
locations: []
)
halt the event
end
end
on htmx:responseError
set status to event.detail.xhr.status
if status >= 500
trigger notification(title: 'Server error', level: 'error', message: 'The server could not handle the given request', duration: 10000)
else if status == 404
trigger notification(title: 'Not found', level: 'error', message: `Route not found: ${event.detail.xhr.responseURL}`, duration: 3000)
end
end
on htmx:configRequest
if window.vault.isUnlocked()
repeat for p in event.detail.parameters
log p
end
end
end
on htmx:beforeRequest
remove @aria-invalid from <[aria-invalid]/>
end
end
behavior objectFilters(submitForm)
on click from in me
halt the event
put '' into .generated-filters in me
repeat for btn in ( in me)
if (btn is event.target and btn does not match .active) or (btn is not event.target and btn matches .active)
render #filter-item with (value: btn's value)
then put the result at the end of .generated-filters in me
end
end
if length of <.generated-filters input/> is 0
render #filter-item with (value: '')
then put the result at the end of .generated-filters in me
end
trigger submit on submitForm unless submitForm == ''
end
end