Update Alpine.js components and initialization

This commit is contained in:
Luis Eduardo Jeréz Girón
2024-07-23 18:03:54 -06:00
parent beb2083da9
commit 6297e0045e
10 changed files with 149 additions and 126 deletions

View File

@@ -0,0 +1,22 @@
export const changeThemeButton = {
name: "changeThemeButton",
fn: () => ({
theme: "",
getCurrentTheme() {
const el = document.querySelector("html")
const theme = el.getAttribute("data-theme")
if (theme) {
this.theme = theme
return
}
this.theme = "system"
},
init() {
setTimeout(() => {
this.getCurrentTheme()
}, 200)
}
})
}

View File

@@ -0,0 +1,16 @@
export const dashboardAsideItem = {
name: "dashboardAsideItem",
fn: (link = '', strict = false) => ({
link: link,
strict: strict,
is_active: false,
init() {
if (this.strict) {
this.is_active = window.location.pathname === this.link
return
}
this.is_active = window.location.pathname.startsWith(this.link)
}
})
}

View File

@@ -0,0 +1,50 @@
export const githubStars = {
name: "githubStars",
fn: () => ({
stars: "",
async init() {
const stars = await this.getGitHubStars()
if (stars !== null) {
this.stars = stars
}
},
async getGitHubStars() {
const cacheKey = 'pbw_gh_stars'
const cachedData = this.getCachedData(cacheKey)
if (cachedData !== null) {
return cachedData
}
const url = 'https://api.github.com/repos/eduardolat/pgbackweb'
try {
const response = await fetch(url)
if (!response.ok) {
return null
}
const data = await response.json()
this.cacheData(cacheKey, data.stargazers_count)
return data.stargazers_count
} catch {
return null
}
},
getCachedData(key) {
const cachedJSON = localStorage.getItem(key)
if (!cachedJSON) {
return null
}
const cached = JSON.parse(cachedJSON)
if (Date.now() - cached.timestamp < 2 * 60 * 1000) {
return cached.value
}
return null
},
cacheData(key, value) {
const data = JSON.stringify({
value: value,
timestamp: Date.now(),
})
localStorage.setItem(key, data)
}
})
}

View File

@@ -1,5 +1,7 @@
import { initNotyf } from './init-notyf.js'
import { initHTMXTriggers } from "./init-htmx-triggers.js";
import { initHTMXTriggers } from "./init-htmx-triggers.js"
import { initAlpineComponents } from './init-alpine-components.js'
initNotyf();
initHTMXTriggers();
initNotyf()
initHTMXTriggers()
initAlpineComponents()

View File

@@ -0,0 +1,11 @@
import { changeThemeButton } from "./alpine-components/change-theme-button.js"
import { githubStars } from "./alpine-components/github-stars.js"
import { dashboardAsideItem } from "./alpine-components/dashboard-aside-item.js"
export function initAlpineComponents() {
document.addEventListener("alpine:init", () => {
Alpine.data(changeThemeButton.name, changeThemeButton.fn)
Alpine.data(githubStars.name, githubStars.fn)
Alpine.data(dashboardAsideItem.name, dashboardAsideItem.fn)
})
}

View File

@@ -1,41 +1,41 @@
export function initHTMXTriggers() {
const triggers = {
ctm_alert: function (evt) {
const message = decodeURIComponent(evt.detail.value);
alert(message);
const message = decodeURIComponent(evt.detail.value)
alert(message)
},
ctm_alert_with_refresh: function (evt) {
const message = decodeURIComponent(evt.detail.value);
alert(message);
location.reload();
const message = decodeURIComponent(evt.detail.value)
alert(message)
location.reload()
},
ctm_alert_with_redirect: function (evt) {
const payload = decodeURIComponent(evt.detail.value);
const parts = payload.split('-::-::-');
const payload = decodeURIComponent(evt.detail.value)
const parts = payload.split('-::-::-')
if (parts.length !== 2) {
return;
return
}
const message = parts[0];
const url = parts[1];
const message = parts[0]
const url = parts[1]
alert(message);
location.href = url;
alert(message)
location.href = url
},
ctm_toast_success: function (evt) {
const message = decodeURIComponent(evt.detail.value);
toaster.success(message);
const message = decodeURIComponent(evt.detail.value)
toaster.success(message)
},
ctm_toast_error: function (evt) {
const message = decodeURIComponent(evt.detail.value);
toaster.error(message);
const message = decodeURIComponent(evt.detail.value)
toaster.error(message)
},
ctm_toast_success_infinite: function (evt) {
const message = decodeURIComponent(evt.detail.value);
toaster.successInfinite(message);
const message = decodeURIComponent(evt.detail.value)
toaster.successInfinite(message)
},
ctm_toast_error_infinite: function (evt) {
const message = decodeURIComponent(evt.detail.value);
toaster.errorInfinite(message);
const message = decodeURIComponent(evt.detail.value)
toaster.errorInfinite(message)
},
}

View File

@@ -1,53 +1,53 @@
export function initNotyf() {
let toastQueue = [];
let toastQueue = []
const toastCfg = {
duration: 5000,
ripple: true,
position: { x: 'right', y: 'bottom' },
dismissible: true,
};
}
const infiniteToastCfg = {
...toastCfg,
duration: 0
};
}
window.toaster = {
success: (message) => {
toastQueue.push({ type: "success", message, config: toastCfg });
toastQueue.push({ type: "success", message, config: toastCfg })
},
error: (message) => {
toastQueue.push({ type: "error", message, config: toastCfg });
toastQueue.push({ type: "error", message, config: toastCfg })
},
successInfinite: (message) => {
toastQueue.push({ type: "success", message, config: infiniteToastCfg });
toastQueue.push({ type: "success", message, config: infiniteToastCfg })
},
errorInfinite: (message) => {
toastQueue.push({ type: "error", message, config: infiniteToastCfg });
toastQueue.push({ type: "error", message, config: infiniteToastCfg })
}
};
}
document.addEventListener('DOMContentLoaded', function () {
var notyf = new Notyf();
var notyf = new Notyf()
toastQueue.forEach(item => {
notyf.open({ type: item.type, message: item.message, ...item.config });
});
notyf.open({ type: item.type, message: item.message, ...item.config })
})
toastQueue = [];
toastQueue = []
window.toaster.success = (message) => {
notyf.open({ type: "success", message, ...toastCfg });
};
notyf.open({ type: "success", message, ...toastCfg })
}
window.toaster.error = (message) => {
notyf.open({ type: "error", message, ...toastCfg });
};
notyf.open({ type: "error", message, ...toastCfg })
}
window.toaster.successInfinite = (message) => {
notyf.open({ type: "success", message, ...infiniteToastCfg });
};
notyf.open({ type: "success", message, ...infiniteToastCfg })
}
window.toaster.errorInfinite = (message) => {
notyf.open({ type: "error", message, ...infiniteToastCfg });
};
});
notyf.open({ type: "error", message, ...infiniteToastCfg })
}
})
}

View File

@@ -16,25 +16,7 @@ type ChangeThemeButtonParams struct {
func ChangeThemeButton(params ChangeThemeButtonParams) gomponents.Node {
return html.Div(
alpine.XData(`{
theme: "",
getCurrentTheme() {
const el = document.querySelector("html");
const theme = el.getAttribute("data-theme");
if (theme) {
this.theme = theme;
return
}
this.theme = "system";
},
init() {
setTimeout(() => {
this.getCurrentTheme();
}, 200)
}
}`),
alpine.XData("changeThemeButton"),
alpine.XCloak(),
alpine.XOn("click", "getCurrentTheme()"),
alpine.XOn("click.outside", "getCurrentTheme()"),

View File

@@ -10,53 +10,7 @@ import (
func StarOnGithub(size size) gomponents.Node {
return html.A(
alpine.XData(`{
stars: "",
async init() {
const stars = await this.getGitHubStars();
if (stars !== null) {
this.stars = stars;
}
},
async getGitHubStars() {
const cacheKey = 'pbw_gh_stars';
const cachedData = this.getCachedData(cacheKey);
if (cachedData !== null) {
return cachedData;
}
const url = 'https://api.github.com/repos/eduardolat/pgbackweb';
try {
const response = await fetch(url);
if (!response.ok) {
return null;
}
const data = await response.json();
this.cacheData(cacheKey, data.stargazers_count);
return data.stargazers_count;
} catch {
return null;
}
},
getCachedData(key) {
const cachedJSON = localStorage.getItem(key);
if (!cachedJSON) {
return null;
}
const cached = JSON.parse(cachedJSON);
if (Date.now() - cached.timestamp < 2 * 60 * 1000) {
return cached.value;
}
return null;
},
cacheData(key, value) {
const data = JSON.stringify({
value: value,
timestamp: Date.now(),
});
localStorage.setItem(key, data);
}
}`),
alpine.XData("githubStars"),
alpine.XCloak(),
components.Classes{
"btn btn-neutral": true,

View File

@@ -99,26 +99,12 @@ func dashboardAsideItem(
text, link string, strict bool,
) gomponents.Node {
return html.A(
alpine.XData(`{
link: "`+link+`",
strict: `+fmt.Sprintf("%t", strict)+`,
is_active: false,
init() {
if (this.strict) {
this.is_active = window.location.pathname === this.link
return
}
this.is_active = window.location.pathname.startsWith(this.link)
}
}`),
alpine.XData(fmt.Sprintf("dashboardAsideItem('%s', %t)", link, strict)),
html.Class("block flex flex-col items-center justify-center"),
html.Href(link),
html.Button(
alpine.XBind("class", `{
'btn-active': is_active,
}`),
alpine.XBind("class", `{'btn-active': is_active}`),
html.Class("btn btn-ghost btn-neutral btn-square"),
icon(html.Class("size-6")),
),