From 158b6129935b734e8ac91316ec7a15f6c0593fe7 Mon Sep 17 00:00:00 2001 From: ahdan15 Date: Wed, 28 May 2025 08:10:10 +0700 Subject: [PATCH] commit doble databse --- Dockerfile | 26 +- cmd/api/main.go | 3 +- cmd/web/assets/css/input.css | 3 - cmd/web/assets/css/output.css | 30 - cmd/web/assets/js/htmx.min.js | 3476 ----------------------- cmd/web/base.templ | 18 - cmd/web/efs.go | 6 - cmd/web/hello.go | 21 - cmd/web/hello.templ | 17 - docker-compose.yml | 35 +- docker-push.sh | 27 + go.mod | 17 +- go.sum | 38 +- internal/database/database.go | 197 +- internal/server/routes.go | 36 +- pkg/database/mongo/database.go | 6 +- pkg/database/mongo/login.go | 52 + pkg/database/mongo/master_data.go | 24 - pkg/database/mongo/mongo.go | 29 - pkg/database/mongo/patient.go | 36 - pkg/database/mongo/user.go | 88 - pkg/handlers/login/login.go | 57 + pkg/handlers/master_data/master_data.go | 33 - pkg/handlers/mongo/mongo.go | 42 - pkg/handlers/patient/patient.go | 54 - pkg/handlers/user/user.go | 168 -- pkg/models/encounter/encounter.go | 1 - pkg/models/local/local.go | 72 - pkg/models/login/login.go | 23 + pkg/models/master_data/master_data.go | 16 - pkg/models/patient/patient.go | 167 -- pkg/models/user/user.go | 33 - tailwind.config.js | 11 - 33 files changed, 408 insertions(+), 4454 deletions(-) delete mode 100644 cmd/web/assets/css/input.css delete mode 100644 cmd/web/assets/css/output.css delete mode 100644 cmd/web/assets/js/htmx.min.js delete mode 100644 cmd/web/base.templ delete mode 100644 cmd/web/efs.go delete mode 100644 cmd/web/hello.go delete mode 100644 cmd/web/hello.templ create mode 100644 docker-push.sh create mode 100644 pkg/database/mongo/login.go delete mode 100644 pkg/database/mongo/master_data.go delete mode 100644 pkg/database/mongo/mongo.go delete mode 100644 pkg/database/mongo/patient.go delete mode 100644 pkg/database/mongo/user.go create mode 100644 pkg/handlers/login/login.go delete mode 100644 pkg/handlers/master_data/master_data.go delete mode 100644 pkg/handlers/mongo/mongo.go delete mode 100644 pkg/handlers/patient/patient.go delete mode 100644 pkg/handlers/user/user.go delete mode 100644 pkg/models/encounter/encounter.go delete mode 100644 pkg/models/local/local.go create mode 100644 pkg/models/login/login.go delete mode 100644 pkg/models/master_data/master_data.go delete mode 100644 pkg/models/patient/patient.go delete mode 100644 pkg/models/user/user.go delete mode 100644 tailwind.config.js diff --git a/Dockerfile b/Dockerfile index ea82372..617d88c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,42 +1,26 @@ -FROM golang:1.23 AS builder -# Install curl dan Tailwind dependencies -RUN apt-get update && apt-get install -y curl ca-certificates +FROM golang:1.23-alpine AS builder WORKDIR /app -# Copy go.mod dan go.sum untuk dependency management COPY go.mod go.sum ./ -RUN go mod download +RUN go mod tidy -# Copy seluruh project COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main ./cmd/api - -# Install Tailwind CSS untuk generate output.css -RUN go install github.com/a-h/templ/cmd/templ@latest && \ - templ generate && \ - curl -sL https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-linux-x64 -o tailwindcss && \ - chmod +x tailwindcss && \ - ./tailwindcss -i cmd/web/assets/css/input.css -o cmd/web/assets/css/output.css +# RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . FROM alpine:latest # Set timezone ke Asia/Jakarta ENV TZ=Asia/Jakarta -# Install dependensi runtime yang diperlukan RUN apk --no-cache add ca-certificates tzdata WORKDIR /root/ -# Copy binary yang sudah ter-build dari stage sebelumnya COPY --from=builder /app/main . COPY --from=builder /app/.env . - -# Expose port aplikasi -EXPOSE 8803 - -# Jalankan aplikasi -CMD ["./main"] +EXPOSE 8080 +CMD ["./main"] \ No newline at end of file diff --git a/cmd/api/main.go b/cmd/api/main.go index e88d59e..ad1a7fc 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -7,9 +7,8 @@ import ( "net/http" "os/signal" "syscall" - "time" - "template_blueprint/internal/server" + "time" ) func gracefulShutdown(apiServer *http.Server, done chan bool) { diff --git a/cmd/web/assets/css/input.css b/cmd/web/assets/css/input.css deleted file mode 100644 index b5c61c9..0000000 --- a/cmd/web/assets/css/input.css +++ /dev/null @@ -1,3 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; diff --git a/cmd/web/assets/css/output.css b/cmd/web/assets/css/output.css deleted file mode 100644 index f679793..0000000 --- a/cmd/web/assets/css/output.css +++ /dev/null @@ -1,30 +0,0 @@ -/*! tailwindcss v4.0.13 | MIT License | https://tailwindcss.com */ -.container { - width: 100%; -} -.mx-auto { - margin-inline: auto; -} -.block { - display: block; -} -.h-screen { - height: 100vh; -} -.resize { - resize: both; -} -.border { - border-style: var(--tw-border-style); - border-width: 1px; -} -.transition { - transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter; - transition-timing-function: var(--tw-ease, ease); - transition-duration: var(--tw-duration, 0s); -} -@property --tw-border-style { - syntax: "*"; - inherits: false; - initial-value: solid; -} diff --git a/cmd/web/assets/js/htmx.min.js b/cmd/web/assets/js/htmx.min.js deleted file mode 100644 index c909e02..0000000 --- a/cmd/web/assets/js/htmx.min.js +++ /dev/null @@ -1,3476 +0,0 @@ -var htmx = (function () { - "use strict"; - const Q = { - onLoad: null, - process: null, - on: null, - off: null, - trigger: null, - ajax: null, - find: null, - findAll: null, - closest: null, - values: function (e, t) { - const n = cn(e, t || "post"); - return n.values; - }, - remove: null, - addClass: null, - removeClass: null, - toggleClass: null, - takeClass: null, - swap: null, - defineExtension: null, - removeExtension: null, - logAll: null, - logNone: null, - logger: null, - config: { - historyEnabled: true, - historyCacheSize: 10, - refreshOnHistoryMiss: false, - defaultSwapStyle: "innerHTML", - defaultSwapDelay: 0, - defaultSettleDelay: 20, - includeIndicatorStyles: true, - indicatorClass: "htmx-indicator", - requestClass: "htmx-request", - addedClass: "htmx-added", - settlingClass: "htmx-settling", - swappingClass: "htmx-swapping", - allowEval: true, - allowScriptTags: true, - inlineScriptNonce: "", - inlineStyleNonce: "", - attributesToSettle: ["class", "style", "width", "height"], - withCredentials: false, - timeout: 0, - wsReconnectDelay: "full-jitter", - wsBinaryType: "blob", - disableSelector: "[hx-disable], [data-hx-disable]", - scrollBehavior: "instant", - defaultFocusScroll: false, - getCacheBusterParam: false, - globalViewTransitions: false, - methodsThatUseUrlParams: ["get", "delete"], - selfRequestsOnly: true, - ignoreTitle: false, - scrollIntoViewOnBoost: true, - triggerSpecsCache: null, - disableInheritance: false, - responseHandling: [ - { code: "204", swap: false }, - { code: "[23]..", swap: true }, - { code: "[45]..", swap: false, error: true }, - ], - allowNestedOobSwaps: true, - }, - parseInterval: null, - _: null, - version: "2.0.3", - }; - Q.onLoad = j; - Q.process = kt; - Q.on = ye; - Q.off = be; - Q.trigger = de; - Q.ajax = Rn; - Q.find = r; - Q.findAll = x; - Q.closest = g; - Q.remove = z; - Q.addClass = K; - Q.removeClass = G; - Q.toggleClass = W; - Q.takeClass = Z; - Q.swap = $e; - Q.defineExtension = Fn; - Q.removeExtension = Bn; - Q.logAll = V; - Q.logNone = _; - Q.parseInterval = h; - Q._ = e; - const n = { - addTriggerHandler: St, - bodyContains: le, - canAccessLocalStorage: B, - findThisElement: Se, - filterValues: dn, - swap: $e, - hasAttribute: s, - getAttributeValue: te, - getClosestAttributeValue: re, - getClosestMatch: i, - getExpressionVars: En, - getHeaders: fn, - getInputValues: cn, - getInternalData: ie, - getSwapSpecification: gn, - getTriggerSpecs: st, - getTarget: Ee, - makeFragment: P, - mergeObjects: ce, - makeSettleInfo: xn, - oobSwap: He, - querySelectorExt: ae, - settleImmediately: Kt, - shouldCancel: dt, - triggerEvent: de, - triggerErrorEvent: fe, - withExtensions: Ft, - }; - const o = ["get", "post", "put", "delete", "patch"]; - const R = o - .map(function (e) { - return "[hx-" + e + "], [data-hx-" + e + "]"; - }) - .join(", "); - function h(e) { - if (e == undefined) { - return undefined; - } - let t = NaN; - if (e.slice(-2) == "ms") { - t = parseFloat(e.slice(0, -2)); - } else if (e.slice(-1) == "s") { - t = parseFloat(e.slice(0, -1)) * 1e3; - } else if (e.slice(-1) == "m") { - t = parseFloat(e.slice(0, -1)) * 1e3 * 60; - } else { - t = parseFloat(e); - } - return isNaN(t) ? undefined : t; - } - function ee(e, t) { - return e instanceof Element && e.getAttribute(t); - } - function s(e, t) { - return ( - !!e.hasAttribute && (e.hasAttribute(t) || e.hasAttribute("data-" + t)) - ); - } - function te(e, t) { - return ee(e, t) || ee(e, "data-" + t); - } - function c(e) { - const t = e.parentElement; - if (!t && e.parentNode instanceof ShadowRoot) return e.parentNode; - return t; - } - function ne() { - return document; - } - function m(e, t) { - return e.getRootNode ? e.getRootNode({ composed: t }) : ne(); - } - function i(e, t) { - while (e && !t(e)) { - e = c(e); - } - return e || null; - } - function H(e, t, n) { - const r = te(t, n); - const o = te(t, "hx-disinherit"); - var i = te(t, "hx-inherit"); - if (e !== t) { - if (Q.config.disableInheritance) { - if (i && (i === "*" || i.split(" ").indexOf(n) >= 0)) { - return r; - } else { - return null; - } - } - if (o && (o === "*" || o.split(" ").indexOf(n) >= 0)) { - return "unset"; - } - } - return r; - } - function re(t, n) { - let r = null; - i(t, function (e) { - return !!(r = H(t, ue(e), n)); - }); - if (r !== "unset") { - return r; - } - } - function d(e, t) { - const n = - e instanceof Element && - (e.matches || - e.matchesSelector || - e.msMatchesSelector || - e.mozMatchesSelector || - e.webkitMatchesSelector || - e.oMatchesSelector); - return !!n && n.call(e, t); - } - function T(e) { - const t = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i; - const n = t.exec(e); - if (n) { - return n[1].toLowerCase(); - } else { - return ""; - } - } - function q(e) { - const t = new DOMParser(); - return t.parseFromString(e, "text/html"); - } - function L(e, t) { - while (t.childNodes.length > 0) { - e.append(t.childNodes[0]); - } - } - function N(e) { - const t = ne().createElement("script"); - se(e.attributes, function (e) { - t.setAttribute(e.name, e.value); - }); - t.textContent = e.textContent; - t.async = false; - if (Q.config.inlineScriptNonce) { - t.nonce = Q.config.inlineScriptNonce; - } - return t; - } - function A(e) { - return ( - e.matches("script") && - (e.type === "text/javascript" || e.type === "module" || e.type === "") - ); - } - function I(e) { - Array.from(e.querySelectorAll("script")).forEach((e) => { - if (A(e)) { - const t = N(e); - const n = e.parentNode; - try { - n.insertBefore(t, e); - } catch (e) { - C(e); - } finally { - e.remove(); - } - } - }); - } - function P(e) { - const t = e.replace(/]*)?>[\s\S]*?<\/head>/i, ""); - const n = T(t); - let r; - if (n === "html") { - r = new DocumentFragment(); - const i = q(e); - L(r, i.body); - r.title = i.title; - } else if (n === "body") { - r = new DocumentFragment(); - const i = q(t); - L(r, i.body); - r.title = i.title; - } else { - const i = q( - '", - ); - r = i.querySelector("template").content; - r.title = i.title; - var o = r.querySelector("title"); - if (o && o.parentNode === r) { - o.remove(); - r.title = o.innerText; - } - } - if (r) { - if (Q.config.allowScriptTags) { - I(r); - } else { - r.querySelectorAll("script").forEach((e) => e.remove()); - } - } - return r; - } - function oe(e) { - if (e) { - e(); - } - } - function t(e, t) { - return Object.prototype.toString.call(e) === "[object " + t + "]"; - } - function k(e) { - return typeof e === "function"; - } - function D(e) { - return t(e, "Object"); - } - function ie(e) { - const t = "htmx-internal-data"; - let n = e[t]; - if (!n) { - n = e[t] = {}; - } - return n; - } - function M(t) { - const n = []; - if (t) { - for (let e = 0; e < t.length; e++) { - n.push(t[e]); - } - } - return n; - } - function se(t, n) { - if (t) { - for (let e = 0; e < t.length; e++) { - n(t[e]); - } - } - } - function X(e) { - const t = e.getBoundingClientRect(); - const n = t.top; - const r = t.bottom; - return n < window.innerHeight && r >= 0; - } - function le(e) { - const t = e.getRootNode && e.getRootNode(); - if (t && t instanceof window.ShadowRoot) { - return ne().body.contains(t.host); - } else { - return ne().body.contains(e); - } - } - function F(e) { - return e.trim().split(/\s+/); - } - function ce(e, t) { - for (const n in t) { - if (t.hasOwnProperty(n)) { - e[n] = t[n]; - } - } - return e; - } - function S(e) { - try { - return JSON.parse(e); - } catch (e) { - C(e); - return null; - } - } - function B() { - const e = "htmx:localStorageTest"; - try { - localStorage.setItem(e, e); - localStorage.removeItem(e); - return true; - } catch (e) { - return false; - } - } - function U(t) { - try { - const e = new URL(t); - if (e) { - t = e.pathname + e.search; - } - if (!/^\/$/.test(t)) { - t = t.replace(/\/+$/, ""); - } - return t; - } catch (e) { - return t; - } - } - function e(e) { - return vn(ne().body, function () { - return eval(e); - }); - } - function j(t) { - const e = Q.on("htmx:load", function (e) { - t(e.detail.elt); - }); - return e; - } - function V() { - Q.logger = function (e, t, n) { - if (console) { - console.log(t, e, n); - } - }; - } - function _() { - Q.logger = null; - } - function r(e, t) { - if (typeof e !== "string") { - return e.querySelector(t); - } else { - return r(ne(), e); - } - } - function x(e, t) { - if (typeof e !== "string") { - return e.querySelectorAll(t); - } else { - return x(ne(), e); - } - } - function E() { - return window; - } - function z(e, t) { - e = y(e); - if (t) { - E().setTimeout(function () { - z(e); - e = null; - }, t); - } else { - c(e).removeChild(e); - } - } - function ue(e) { - return e instanceof Element ? e : null; - } - function $(e) { - return e instanceof HTMLElement ? e : null; - } - function J(e) { - return typeof e === "string" ? e : null; - } - function f(e) { - return e instanceof Element || - e instanceof Document || - e instanceof DocumentFragment - ? e - : null; - } - function K(e, t, n) { - e = ue(y(e)); - if (!e) { - return; - } - if (n) { - E().setTimeout(function () { - K(e, t); - e = null; - }, n); - } else { - e.classList && e.classList.add(t); - } - } - function G(e, t, n) { - let r = ue(y(e)); - if (!r) { - return; - } - if (n) { - E().setTimeout(function () { - G(r, t); - r = null; - }, n); - } else { - if (r.classList) { - r.classList.remove(t); - if (r.classList.length === 0) { - r.removeAttribute("class"); - } - } - } - } - function W(e, t) { - e = y(e); - e.classList.toggle(t); - } - function Z(e, t) { - e = y(e); - se(e.parentElement.children, function (e) { - G(e, t); - }); - K(ue(e), t); - } - function g(e, t) { - e = ue(y(e)); - if (e && e.closest) { - return e.closest(t); - } else { - do { - if (e == null || d(e, t)) { - return e; - } - } while ((e = e && ue(c(e)))); - return null; - } - } - function l(e, t) { - return e.substring(0, t.length) === t; - } - function Y(e, t) { - return e.substring(e.length - t.length) === t; - } - function ge(e) { - const t = e.trim(); - if (l(t, "<") && Y(t, "/>")) { - return t.substring(1, t.length - 2); - } else { - return t; - } - } - function p(e, t, n) { - e = y(e); - if (t.indexOf("closest ") === 0) { - return [g(ue(e), ge(t.substr(8)))]; - } else if (t.indexOf("find ") === 0) { - return [r(f(e), ge(t.substr(5)))]; - } else if (t === "next") { - return [ue(e).nextElementSibling]; - } else if (t.indexOf("next ") === 0) { - return [pe(e, ge(t.substr(5)), !!n)]; - } else if (t === "previous") { - return [ue(e).previousElementSibling]; - } else if (t.indexOf("previous ") === 0) { - return [me(e, ge(t.substr(9)), !!n)]; - } else if (t === "document") { - return [document]; - } else if (t === "window") { - return [window]; - } else if (t === "body") { - return [document.body]; - } else if (t === "root") { - return [m(e, !!n)]; - } else if (t === "host") { - return [e.getRootNode().host]; - } else if (t.indexOf("global ") === 0) { - return p(e, t.slice(7), true); - } else { - return M(f(m(e, !!n)).querySelectorAll(ge(t))); - } - } - var pe = function (t, e, n) { - const r = f(m(t, n)).querySelectorAll(e); - for (let e = 0; e < r.length; e++) { - const o = r[e]; - if (o.compareDocumentPosition(t) === Node.DOCUMENT_POSITION_PRECEDING) { - return o; - } - } - }; - var me = function (t, e, n) { - const r = f(m(t, n)).querySelectorAll(e); - for (let e = r.length - 1; e >= 0; e--) { - const o = r[e]; - if (o.compareDocumentPosition(t) === Node.DOCUMENT_POSITION_FOLLOWING) { - return o; - } - } - }; - function ae(e, t) { - if (typeof e !== "string") { - return p(e, t)[0]; - } else { - return p(ne().body, e)[0]; - } - } - function y(e, t) { - if (typeof e === "string") { - return r(f(t) || document, e); - } else { - return e; - } - } - function xe(e, t, n, r) { - if (k(t)) { - return { target: ne().body, event: J(e), listener: t, options: n }; - } else { - return { target: y(e), event: J(t), listener: n, options: r }; - } - } - function ye(t, n, r, o) { - Vn(function () { - const e = xe(t, n, r, o); - e.target.addEventListener(e.event, e.listener, e.options); - }); - const e = k(n); - return e ? n : r; - } - function be(t, n, r) { - Vn(function () { - const e = xe(t, n, r); - e.target.removeEventListener(e.event, e.listener); - }); - return k(n) ? n : r; - } - const ve = ne().createElement("output"); - function we(e, t) { - const n = re(e, t); - if (n) { - if (n === "this") { - return [Se(e, t)]; - } else { - const r = p(e, n); - if (r.length === 0) { - C('The selector "' + n + '" on ' + t + " returned no matches!"); - return [ve]; - } else { - return r; - } - } - } - } - function Se(e, t) { - return ue( - i(e, function (e) { - return te(ue(e), t) != null; - }), - ); - } - function Ee(e) { - const t = re(e, "hx-target"); - if (t) { - if (t === "this") { - return Se(e, "hx-target"); - } else { - return ae(e, t); - } - } else { - const n = ie(e); - if (n.boosted) { - return ne().body; - } else { - return e; - } - } - } - function Ce(t) { - const n = Q.config.attributesToSettle; - for (let e = 0; e < n.length; e++) { - if (t === n[e]) { - return true; - } - } - return false; - } - function Oe(t, n) { - se(t.attributes, function (e) { - if (!n.hasAttribute(e.name) && Ce(e.name)) { - t.removeAttribute(e.name); - } - }); - se(n.attributes, function (e) { - if (Ce(e.name)) { - t.setAttribute(e.name, e.value); - } - }); - } - function Re(t, e) { - const n = Un(e); - for (let e = 0; e < n.length; e++) { - const r = n[e]; - try { - if (r.isInlineSwap(t)) { - return true; - } - } catch (e) { - C(e); - } - } - return t === "outerHTML"; - } - function He(e, o, i, t) { - t = t || ne(); - let n = "#" + ee(o, "id"); - let s = "outerHTML"; - if (e === "true") { - } else if (e.indexOf(":") > 0) { - s = e.substr(0, e.indexOf(":")); - n = e.substr(e.indexOf(":") + 1, e.length); - } else { - s = e; - } - o.removeAttribute("hx-swap-oob"); - o.removeAttribute("data-hx-swap-oob"); - const r = p(t, n, false); - if (r) { - se(r, function (e) { - let t; - const n = o.cloneNode(true); - t = ne().createDocumentFragment(); - t.appendChild(n); - if (!Re(s, e)) { - t = f(n); - } - const r = { shouldSwap: true, target: e, fragment: t }; - if (!de(e, "htmx:oobBeforeSwap", r)) return; - e = r.target; - if (r.shouldSwap) { - qe(t); - _e(s, e, e, t, i); - Te(); - } - se(i.elts, function (e) { - de(e, "htmx:oobAfterSwap", r); - }); - }); - o.parentNode.removeChild(o); - } else { - o.parentNode.removeChild(o); - fe(ne().body, "htmx:oobErrorNoTarget", { content: o }); - } - return e; - } - function Te() { - const e = r("#--htmx-preserve-pantry--"); - if (e) { - for (const t of [...e.children]) { - const n = r("#" + t.id); - n.parentNode.moveBefore(t, n); - n.remove(); - } - e.remove(); - } - } - function qe(e) { - se(x(e, "[hx-preserve], [data-hx-preserve]"), function (e) { - const t = te(e, "id"); - const n = ne().getElementById(t); - if (n != null) { - if (e.moveBefore) { - let e = r("#--htmx-preserve-pantry--"); - if (e == null) { - ne().body.insertAdjacentHTML( - "afterend", - "
", - ); - e = r("#--htmx-preserve-pantry--"); - } - e.moveBefore(n, null); - } else { - e.parentNode.replaceChild(n, e); - } - } - }); - } - function Le(l, e, c) { - se(e.querySelectorAll("[id]"), function (t) { - const n = ee(t, "id"); - if (n && n.length > 0) { - const r = n.replace("'", "\\'"); - const o = t.tagName.replace(":", "\\:"); - const e = f(l); - const i = e && e.querySelector(o + "[id='" + r + "']"); - if (i && i !== e) { - const s = t.cloneNode(); - Oe(t, i); - c.tasks.push(function () { - Oe(t, s); - }); - } - } - }); - } - function Ne(e) { - return function () { - G(e, Q.config.addedClass); - kt(ue(e)); - Ae(f(e)); - de(e, "htmx:load"); - }; - } - function Ae(e) { - const t = "[autofocus]"; - const n = $(d(e, t) ? e : e.querySelector(t)); - if (n != null) { - n.focus(); - } - } - function u(e, t, n, r) { - Le(e, n, r); - while (n.childNodes.length > 0) { - const o = n.firstChild; - K(ue(o), Q.config.addedClass); - e.insertBefore(o, t); - if (o.nodeType !== Node.TEXT_NODE && o.nodeType !== Node.COMMENT_NODE) { - r.tasks.push(Ne(o)); - } - } - } - function Ie(e, t) { - let n = 0; - while (n < e.length) { - t = ((t << 5) - t + e.charCodeAt(n++)) | 0; - } - return t; - } - function Pe(t) { - let n = 0; - if (t.attributes) { - for (let e = 0; e < t.attributes.length; e++) { - const r = t.attributes[e]; - if (r.value) { - n = Ie(r.name, n); - n = Ie(r.value, n); - } - } - } - return n; - } - function ke(t) { - const n = ie(t); - if (n.onHandlers) { - for (let e = 0; e < n.onHandlers.length; e++) { - const r = n.onHandlers[e]; - be(t, r.event, r.listener); - } - delete n.onHandlers; - } - } - function De(e) { - const t = ie(e); - if (t.timeout) { - clearTimeout(t.timeout); - } - if (t.listenerInfos) { - se(t.listenerInfos, function (e) { - if (e.on) { - be(e.on, e.trigger, e.listener); - } - }); - } - ke(e); - se(Object.keys(t), function (e) { - delete t[e]; - }); - } - function a(e) { - de(e, "htmx:beforeCleanupElement"); - De(e); - if (e.children) { - se(e.children, function (e) { - a(e); - }); - } - } - function Me(t, e, n) { - if (t instanceof Element && t.tagName === "BODY") { - return Ve(t, e, n); - } - let r; - const o = t.previousSibling; - const i = c(t); - if (!i) { - return; - } - u(i, t, e, n); - if (o == null) { - r = i.firstChild; - } else { - r = o.nextSibling; - } - n.elts = n.elts.filter(function (e) { - return e !== t; - }); - while (r && r !== t) { - if (r instanceof Element) { - n.elts.push(r); - } - r = r.nextSibling; - } - a(t); - if (t instanceof Element) { - t.remove(); - } else { - t.parentNode.removeChild(t); - } - } - function Xe(e, t, n) { - return u(e, e.firstChild, t, n); - } - function Fe(e, t, n) { - return u(c(e), e, t, n); - } - function Be(e, t, n) { - return u(e, null, t, n); - } - function Ue(e, t, n) { - return u(c(e), e.nextSibling, t, n); - } - function je(e) { - a(e); - const t = c(e); - if (t) { - return t.removeChild(e); - } - } - function Ve(e, t, n) { - const r = e.firstChild; - u(e, r, t, n); - if (r) { - while (r.nextSibling) { - a(r.nextSibling); - e.removeChild(r.nextSibling); - } - a(r); - e.removeChild(r); - } - } - function _e(t, e, n, r, o) { - switch (t) { - case "none": - return; - case "outerHTML": - Me(n, r, o); - return; - case "afterbegin": - Xe(n, r, o); - return; - case "beforebegin": - Fe(n, r, o); - return; - case "beforeend": - Be(n, r, o); - return; - case "afterend": - Ue(n, r, o); - return; - case "delete": - je(n); - return; - default: - var i = Un(e); - for (let e = 0; e < i.length; e++) { - const s = i[e]; - try { - const l = s.handleSwap(t, n, r, o); - if (l) { - if (Array.isArray(l)) { - for (let e = 0; e < l.length; e++) { - const c = l[e]; - if ( - c.nodeType !== Node.TEXT_NODE && - c.nodeType !== Node.COMMENT_NODE - ) { - o.tasks.push(Ne(c)); - } - } - } - return; - } - } catch (e) { - C(e); - } - } - if (t === "innerHTML") { - Ve(n, r, o); - } else { - _e(Q.config.defaultSwapStyle, e, n, r, o); - } - } - } - function ze(e, n, r) { - var t = x(e, "[hx-swap-oob], [data-hx-swap-oob]"); - se(t, function (e) { - if (Q.config.allowNestedOobSwaps || e.parentElement === null) { - const t = te(e, "hx-swap-oob"); - if (t != null) { - He(t, e, n, r); - } - } else { - e.removeAttribute("hx-swap-oob"); - e.removeAttribute("data-hx-swap-oob"); - } - }); - return t.length > 0; - } - function $e(e, t, r, o) { - if (!o) { - o = {}; - } - e = y(e); - const i = o.contextElement ? m(o.contextElement, false) : ne(); - const n = document.activeElement; - let s = {}; - try { - s = { - elt: n, - start: n ? n.selectionStart : null, - end: n ? n.selectionEnd : null, - }; - } catch (e) {} - const l = xn(e); - if (r.swapStyle === "textContent") { - e.textContent = t; - } else { - let n = P(t); - l.title = n.title; - if (o.selectOOB) { - const u = o.selectOOB.split(","); - for (let t = 0; t < u.length; t++) { - const a = u[t].split(":", 2); - let e = a[0].trim(); - if (e.indexOf("#") === 0) { - e = e.substring(1); - } - const f = a[1] || "true"; - const d = n.querySelector("#" + e); - if (d) { - He(f, d, l, i); - } - } - } - ze(n, l, i); - se(x(n, "template"), function (e) { - if (ze(e.content, l, i)) { - e.remove(); - } - }); - if (o.select) { - const h = ne().createDocumentFragment(); - se(n.querySelectorAll(o.select), function (e) { - h.appendChild(e); - }); - n = h; - } - qe(n); - _e(r.swapStyle, o.contextElement, e, n, l); - Te(); - } - if (s.elt && !le(s.elt) && ee(s.elt, "id")) { - const g = document.getElementById(ee(s.elt, "id")); - const p = { - preventScroll: - r.focusScroll !== undefined - ? !r.focusScroll - : !Q.config.defaultFocusScroll, - }; - if (g) { - if (s.start && g.setSelectionRange) { - try { - g.setSelectionRange(s.start, s.end); - } catch (e) {} - } - g.focus(p); - } - } - e.classList.remove(Q.config.swappingClass); - se(l.elts, function (e) { - if (e.classList) { - e.classList.add(Q.config.settlingClass); - } - de(e, "htmx:afterSwap", o.eventInfo); - }); - if (o.afterSwapCallback) { - o.afterSwapCallback(); - } - if (!r.ignoreTitle) { - kn(l.title); - } - const c = function () { - se(l.tasks, function (e) { - e.call(); - }); - se(l.elts, function (e) { - if (e.classList) { - e.classList.remove(Q.config.settlingClass); - } - de(e, "htmx:afterSettle", o.eventInfo); - }); - if (o.anchor) { - const e = ue(y("#" + o.anchor)); - if (e) { - e.scrollIntoView({ block: "start", behavior: "auto" }); - } - } - yn(l.elts, r); - if (o.afterSettleCallback) { - o.afterSettleCallback(); - } - }; - if (r.settleDelay > 0) { - E().setTimeout(c, r.settleDelay); - } else { - c(); - } - } - function Je(e, t, n) { - const r = e.getResponseHeader(t); - if (r.indexOf("{") === 0) { - const o = S(r); - for (const i in o) { - if (o.hasOwnProperty(i)) { - let e = o[i]; - if (D(e)) { - n = e.target !== undefined ? e.target : n; - } else { - e = { value: e }; - } - de(n, i, e); - } - } - } else { - const s = r.split(","); - for (let e = 0; e < s.length; e++) { - de(n, s[e].trim(), []); - } - } - } - const Ke = /\s/; - const b = /[\s,]/; - const Ge = /[_$a-zA-Z]/; - const We = /[_$a-zA-Z0-9]/; - const Ze = ['"', "'", "/"]; - const v = /[^\s]/; - const Ye = /[{(]/; - const Qe = /[})]/; - function et(e) { - const t = []; - let n = 0; - while (n < e.length) { - if (Ge.exec(e.charAt(n))) { - var r = n; - while (We.exec(e.charAt(n + 1))) { - n++; - } - t.push(e.substr(r, n - r + 1)); - } else if (Ze.indexOf(e.charAt(n)) !== -1) { - const o = e.charAt(n); - var r = n; - n++; - while (n < e.length && e.charAt(n) !== o) { - if (e.charAt(n) === "\\") { - n++; - } - n++; - } - t.push(e.substr(r, n - r + 1)); - } else { - const i = e.charAt(n); - t.push(i); - } - n++; - } - return t; - } - function tt(e, t, n) { - return ( - Ge.exec(e.charAt(0)) && - e !== "true" && - e !== "false" && - e !== "this" && - e !== n && - t !== "." - ); - } - function nt(r, o, i) { - if (o[0] === "[") { - o.shift(); - let e = 1; - let t = " return (function(" + i + "){ return ("; - let n = null; - while (o.length > 0) { - const s = o[0]; - if (s === "]") { - e--; - if (e === 0) { - if (n === null) { - t = t + "true"; - } - o.shift(); - t += ")})"; - try { - const l = vn( - r, - function () { - return Function(t)(); - }, - function () { - return true; - }, - ); - l.source = t; - return l; - } catch (e) { - fe(ne().body, "htmx:syntax:error", { error: e, source: t }); - return null; - } - } - } else if (s === "[") { - e++; - } - if (tt(s, n, i)) { - t += - "((" + - i + - "." + - s + - ") ? (" + - i + - "." + - s + - ") : (window." + - s + - "))"; - } else { - t = t + s; - } - n = o.shift(); - } - } - } - function w(e, t) { - let n = ""; - while (e.length > 0 && !t.test(e[0])) { - n += e.shift(); - } - return n; - } - function rt(e) { - let t; - if (e.length > 0 && Ye.test(e[0])) { - e.shift(); - t = w(e, Qe).trim(); - e.shift(); - } else { - t = w(e, b); - } - return t; - } - const ot = "input, textarea, select"; - function it(e, t, n) { - const r = []; - const o = et(t); - do { - w(o, v); - const l = o.length; - const c = w(o, /[,\[\s]/); - if (c !== "") { - if (c === "every") { - const u = { trigger: "every" }; - w(o, v); - u.pollInterval = h(w(o, /[,\[\s]/)); - w(o, v); - var i = nt(e, o, "event"); - if (i) { - u.eventFilter = i; - } - r.push(u); - } else { - const a = { trigger: c }; - var i = nt(e, o, "event"); - if (i) { - a.eventFilter = i; - } - w(o, v); - while (o.length > 0 && o[0] !== ",") { - const f = o.shift(); - if (f === "changed") { - a.changed = true; - } else if (f === "once") { - a.once = true; - } else if (f === "consume") { - a.consume = true; - } else if (f === "delay" && o[0] === ":") { - o.shift(); - a.delay = h(w(o, b)); - } else if (f === "from" && o[0] === ":") { - o.shift(); - if (Ye.test(o[0])) { - var s = rt(o); - } else { - var s = w(o, b); - if ( - s === "closest" || - s === "find" || - s === "next" || - s === "previous" - ) { - o.shift(); - const d = rt(o); - if (d.length > 0) { - s += " " + d; - } - } - } - a.from = s; - } else if (f === "target" && o[0] === ":") { - o.shift(); - a.target = rt(o); - } else if (f === "throttle" && o[0] === ":") { - o.shift(); - a.throttle = h(w(o, b)); - } else if (f === "queue" && o[0] === ":") { - o.shift(); - a.queue = w(o, b); - } else if (f === "root" && o[0] === ":") { - o.shift(); - a[f] = rt(o); - } else if (f === "threshold" && o[0] === ":") { - o.shift(); - a[f] = w(o, b); - } else { - fe(e, "htmx:syntax:error", { token: o.shift() }); - } - w(o, v); - } - r.push(a); - } - } - if (o.length === l) { - fe(e, "htmx:syntax:error", { token: o.shift() }); - } - w(o, v); - } while (o[0] === "," && o.shift()); - if (n) { - n[t] = r; - } - return r; - } - function st(e) { - const t = te(e, "hx-trigger"); - let n = []; - if (t) { - const r = Q.config.triggerSpecsCache; - n = (r && r[t]) || it(e, t, r); - } - if (n.length > 0) { - return n; - } else if (d(e, "form")) { - return [{ trigger: "submit" }]; - } else if (d(e, 'input[type="button"], input[type="submit"]')) { - return [{ trigger: "click" }]; - } else if (d(e, ot)) { - return [{ trigger: "change" }]; - } else { - return [{ trigger: "click" }]; - } - } - function lt(e) { - ie(e).cancelled = true; - } - function ct(e, t, n) { - const r = ie(e); - r.timeout = E().setTimeout(function () { - if (le(e) && r.cancelled !== true) { - if (!gt(n, e, Mt("hx:poll:trigger", { triggerSpec: n, target: e }))) { - t(e); - } - ct(e, t, n); - } - }, n.pollInterval); - } - function ut(e) { - return ( - location.hostname === e.hostname && - ee(e, "href") && - ee(e, "href").indexOf("#") !== 0 - ); - } - function at(e) { - return g(e, Q.config.disableSelector); - } - function ft(t, n, e) { - if ( - (t instanceof HTMLAnchorElement && - ut(t) && - (t.target === "" || t.target === "_self")) || - (t.tagName === "FORM" && - String(ee(t, "method")).toLowerCase() !== "dialog") - ) { - n.boosted = true; - let r, o; - if (t.tagName === "A") { - r = "get"; - o = ee(t, "href"); - } else { - const i = ee(t, "method"); - r = i ? i.toLowerCase() : "get"; - o = ee(t, "action"); - if (r === "get" && o.includes("?")) { - o = o.replace(/\?[^#]+/, ""); - } - } - e.forEach(function (e) { - pt( - t, - function (e, t) { - const n = ue(e); - if (at(n)) { - a(n); - return; - } - he(r, o, n, t); - }, - n, - e, - true, - ); - }); - } - } - function dt(e, t) { - const n = ue(t); - if (!n) { - return false; - } - if (e.type === "submit" || e.type === "click") { - if (n.tagName === "FORM") { - return true; - } - if (d(n, 'input[type="submit"], button') && g(n, "form") !== null) { - return true; - } - if ( - n instanceof HTMLAnchorElement && - n.href && - (n.getAttribute("href") === "#" || - n.getAttribute("href").indexOf("#") !== 0) - ) { - return true; - } - } - return false; - } - function ht(e, t) { - return ( - ie(e).boosted && - e instanceof HTMLAnchorElement && - t.type === "click" && - (t.ctrlKey || t.metaKey) - ); - } - function gt(e, t, n) { - const r = e.eventFilter; - if (r) { - try { - return r.call(t, n) !== true; - } catch (e) { - const o = r.source; - fe(ne().body, "htmx:eventFilter:error", { error: e, source: o }); - return true; - } - } - return false; - } - function pt(l, c, e, u, a) { - const f = ie(l); - let t; - if (u.from) { - t = p(l, u.from); - } else { - t = [l]; - } - if (u.changed) { - if (!("lastValue" in f)) { - f.lastValue = new WeakMap(); - } - t.forEach(function (e) { - if (!f.lastValue.has(u)) { - f.lastValue.set(u, new WeakMap()); - } - f.lastValue.get(u).set(e, e.value); - }); - } - se(t, function (i) { - const s = function (e) { - if (!le(l)) { - i.removeEventListener(u.trigger, s); - return; - } - if (ht(l, e)) { - return; - } - if (a || dt(e, l)) { - e.preventDefault(); - } - if (gt(u, l, e)) { - return; - } - const t = ie(e); - t.triggerSpec = u; - if (t.handledFor == null) { - t.handledFor = []; - } - if (t.handledFor.indexOf(l) < 0) { - t.handledFor.push(l); - if (u.consume) { - e.stopPropagation(); - } - if (u.target && e.target) { - if (!d(ue(e.target), u.target)) { - return; - } - } - if (u.once) { - if (f.triggeredOnce) { - return; - } else { - f.triggeredOnce = true; - } - } - if (u.changed) { - const n = event.target; - const r = n.value; - const o = f.lastValue.get(u); - if (o.has(n) && o.get(n) === r) { - return; - } - o.set(n, r); - } - if (f.delayed) { - clearTimeout(f.delayed); - } - if (f.throttle) { - return; - } - if (u.throttle > 0) { - if (!f.throttle) { - de(l, "htmx:trigger"); - c(l, e); - f.throttle = E().setTimeout(function () { - f.throttle = null; - }, u.throttle); - } - } else if (u.delay > 0) { - f.delayed = E().setTimeout(function () { - de(l, "htmx:trigger"); - c(l, e); - }, u.delay); - } else { - de(l, "htmx:trigger"); - c(l, e); - } - } - }; - if (e.listenerInfos == null) { - e.listenerInfos = []; - } - e.listenerInfos.push({ trigger: u.trigger, listener: s, on: i }); - i.addEventListener(u.trigger, s); - }); - } - let mt = false; - let xt = null; - function yt() { - if (!xt) { - xt = function () { - mt = true; - }; - window.addEventListener("scroll", xt); - window.addEventListener("resize", xt); - setInterval(function () { - if (mt) { - mt = false; - se( - ne().querySelectorAll( - "[hx-trigger*='revealed'],[data-hx-trigger*='revealed']", - ), - function (e) { - bt(e); - }, - ); - } - }, 200); - } - } - function bt(e) { - if (!s(e, "data-hx-revealed") && X(e)) { - e.setAttribute("data-hx-revealed", "true"); - const t = ie(e); - if (t.initHash) { - de(e, "revealed"); - } else { - e.addEventListener( - "htmx:afterProcessNode", - function () { - de(e, "revealed"); - }, - { once: true }, - ); - } - } - } - function vt(e, t, n, r) { - const o = function () { - if (!n.loaded) { - n.loaded = true; - t(e); - } - }; - if (r > 0) { - E().setTimeout(o, r); - } else { - o(); - } - } - function wt(t, n, e) { - let i = false; - se(o, function (r) { - if (s(t, "hx-" + r)) { - const o = te(t, "hx-" + r); - i = true; - n.path = o; - n.verb = r; - e.forEach(function (e) { - St(t, e, n, function (e, t) { - const n = ue(e); - if (g(n, Q.config.disableSelector)) { - a(n); - return; - } - he(r, o, n, t); - }); - }); - } - }); - return i; - } - function St(r, e, t, n) { - if (e.trigger === "revealed") { - yt(); - pt(r, n, t, e); - bt(ue(r)); - } else if (e.trigger === "intersect") { - const o = {}; - if (e.root) { - o.root = ae(r, e.root); - } - if (e.threshold) { - o.threshold = parseFloat(e.threshold); - } - const i = new IntersectionObserver(function (t) { - for (let e = 0; e < t.length; e++) { - const n = t[e]; - if (n.isIntersecting) { - de(r, "intersect"); - break; - } - } - }, o); - i.observe(ue(r)); - pt(ue(r), n, t, e); - } else if (e.trigger === "load") { - if (!gt(e, r, Mt("load", { elt: r }))) { - vt(ue(r), n, t, e.delay); - } - } else if (e.pollInterval > 0) { - t.polling = true; - ct(ue(r), n, e); - } else { - pt(r, n, t, e); - } - } - function Et(e) { - const t = ue(e); - if (!t) { - return false; - } - const n = t.attributes; - for (let e = 0; e < n.length; e++) { - const r = n[e].name; - if ( - l(r, "hx-on:") || - l(r, "data-hx-on:") || - l(r, "hx-on-") || - l(r, "data-hx-on-") - ) { - return true; - } - } - return false; - } - const Ct = new XPathEvaluator().createExpression( - './/*[@*[ starts-with(name(), "hx-on:") or starts-with(name(), "data-hx-on:") or' + - ' starts-with(name(), "hx-on-") or starts-with(name(), "data-hx-on-") ]]', - ); - function Ot(e, t) { - if (Et(e)) { - t.push(ue(e)); - } - const n = Ct.evaluate(e); - let r = null; - while ((r = n.iterateNext())) t.push(ue(r)); - } - function Rt(e) { - const t = []; - if (e instanceof DocumentFragment) { - for (const n of e.childNodes) { - Ot(n, t); - } - } else { - Ot(e, t); - } - return t; - } - function Ht(e) { - if (e.querySelectorAll) { - const n = - ", [hx-boost] a, [data-hx-boost] a, a[hx-boost], a[data-hx-boost]"; - const r = []; - for (const i in Mn) { - const s = Mn[i]; - if (s.getSelectors) { - var t = s.getSelectors(); - if (t) { - r.push(t); - } - } - } - const o = e.querySelectorAll( - R + - n + - ", form, [type='submit']," + - " [hx-ext], [data-hx-ext], [hx-trigger], [data-hx-trigger]" + - r - .flat() - .map((e) => ", " + e) - .join(""), - ); - return o; - } else { - return []; - } - } - function Tt(e) { - const t = g(ue(e.target), "button, input[type='submit']"); - const n = Lt(e); - if (n) { - n.lastButtonClicked = t; - } - } - function qt(e) { - const t = Lt(e); - if (t) { - t.lastButtonClicked = null; - } - } - function Lt(e) { - const t = g(ue(e.target), "button, input[type='submit']"); - if (!t) { - return; - } - const n = y("#" + ee(t, "form"), t.getRootNode()) || g(t, "form"); - if (!n) { - return; - } - return ie(n); - } - function Nt(e) { - e.addEventListener("click", Tt); - e.addEventListener("focusin", Tt); - e.addEventListener("focusout", qt); - } - function At(t, e, n) { - const r = ie(t); - if (!Array.isArray(r.onHandlers)) { - r.onHandlers = []; - } - let o; - const i = function (e) { - vn(t, function () { - if (at(t)) { - return; - } - if (!o) { - o = new Function("event", n); - } - o.call(t, e); - }); - }; - t.addEventListener(e, i); - r.onHandlers.push({ event: e, listener: i }); - } - function It(t) { - ke(t); - for (let e = 0; e < t.attributes.length; e++) { - const n = t.attributes[e].name; - const r = t.attributes[e].value; - if (l(n, "hx-on") || l(n, "data-hx-on")) { - const o = n.indexOf("-on") + 3; - const i = n.slice(o, o + 1); - if (i === "-" || i === ":") { - let e = n.slice(o + 1); - if (l(e, ":")) { - e = "htmx" + e; - } else if (l(e, "-")) { - e = "htmx:" + e.slice(1); - } else if (l(e, "htmx-")) { - e = "htmx:" + e.slice(5); - } - At(t, e, r); - } - } - } - } - function Pt(t) { - if (g(t, Q.config.disableSelector)) { - a(t); - return; - } - const n = ie(t); - if (n.initHash !== Pe(t)) { - De(t); - n.initHash = Pe(t); - de(t, "htmx:beforeProcessNode"); - const e = st(t); - const r = wt(t, n, e); - if (!r) { - if (re(t, "hx-boost") === "true") { - ft(t, n, e); - } else if (s(t, "hx-trigger")) { - e.forEach(function (e) { - St(t, e, n, function () {}); - }); - } - } - if ( - t.tagName === "FORM" || - (ee(t, "type") === "submit" && s(t, "form")) - ) { - Nt(t); - } - de(t, "htmx:afterProcessNode"); - } - } - function kt(e) { - e = y(e); - if (g(e, Q.config.disableSelector)) { - a(e); - return; - } - Pt(e); - se(Ht(e), function (e) { - Pt(e); - }); - se(Rt(e), It); - } - function Dt(e) { - return e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(); - } - function Mt(e, t) { - let n; - if (window.CustomEvent && typeof window.CustomEvent === "function") { - n = new CustomEvent(e, { - bubbles: true, - cancelable: true, - composed: true, - detail: t, - }); - } else { - n = ne().createEvent("CustomEvent"); - n.initCustomEvent(e, true, true, t); - } - return n; - } - function fe(e, t, n) { - de(e, t, ce({ error: t }, n)); - } - function Xt(e) { - return e === "htmx:afterProcessNode"; - } - function Ft(e, t) { - se(Un(e), function (e) { - try { - t(e); - } catch (e) { - C(e); - } - }); - } - function C(e) { - if (console.error) { - console.error(e); - } else if (console.log) { - console.log("ERROR: ", e); - } - } - function de(e, t, n) { - e = y(e); - if (n == null) { - n = {}; - } - n.elt = e; - const r = Mt(t, n); - if (Q.logger && !Xt(t)) { - Q.logger(e, t, n); - } - if (n.error) { - C(n.error); - de(e, "htmx:error", { errorInfo: n }); - } - let o = e.dispatchEvent(r); - const i = Dt(t); - if (o && i !== t) { - const s = Mt(i, r.detail); - o = o && e.dispatchEvent(s); - } - Ft(ue(e), function (e) { - o = o && e.onEvent(t, r) !== false && !r.defaultPrevented; - }); - return o; - } - let Bt = location.pathname + location.search; - function Ut() { - const e = ne().querySelector("[hx-history-elt],[data-hx-history-elt]"); - return e || ne().body; - } - function jt(t, e) { - if (!B()) { - return; - } - const n = _t(e); - const r = ne().title; - const o = window.scrollY; - if (Q.config.historyCacheSize <= 0) { - localStorage.removeItem("htmx-history-cache"); - return; - } - t = U(t); - const i = S(localStorage.getItem("htmx-history-cache")) || []; - for (let e = 0; e < i.length; e++) { - if (i[e].url === t) { - i.splice(e, 1); - break; - } - } - const s = { url: t, content: n, title: r, scroll: o }; - de(ne().body, "htmx:historyItemCreated", { item: s, cache: i }); - i.push(s); - while (i.length > Q.config.historyCacheSize) { - i.shift(); - } - while (i.length > 0) { - try { - localStorage.setItem("htmx-history-cache", JSON.stringify(i)); - break; - } catch (e) { - fe(ne().body, "htmx:historyCacheError", { cause: e, cache: i }); - i.shift(); - } - } - } - function Vt(t) { - if (!B()) { - return null; - } - t = U(t); - const n = S(localStorage.getItem("htmx-history-cache")) || []; - for (let e = 0; e < n.length; e++) { - if (n[e].url === t) { - return n[e]; - } - } - return null; - } - function _t(e) { - const t = Q.config.requestClass; - const n = e.cloneNode(true); - se(x(n, "." + t), function (e) { - G(e, t); - }); - se(x(n, "[data-disabled-by-htmx]"), function (e) { - e.removeAttribute("disabled"); - }); - return n.innerHTML; - } - function zt() { - const e = Ut(); - const t = Bt || location.pathname + location.search; - let n; - try { - n = ne().querySelector( - '[hx-history="false" i],[data-hx-history="false" i]', - ); - } catch (e) { - n = ne().querySelector('[hx-history="false"],[data-hx-history="false"]'); - } - if (!n) { - de(ne().body, "htmx:beforeHistorySave", { path: t, historyElt: e }); - jt(t, e); - } - if (Q.config.historyEnabled) - history.replaceState({ htmx: true }, ne().title, window.location.href); - } - function $t(e) { - if (Q.config.getCacheBusterParam) { - e = e.replace(/org\.htmx\.cache-buster=[^&]*&?/, ""); - if (Y(e, "&") || Y(e, "?")) { - e = e.slice(0, -1); - } - } - if (Q.config.historyEnabled) { - history.pushState({ htmx: true }, "", e); - } - Bt = e; - } - function Jt(e) { - if (Q.config.historyEnabled) history.replaceState({ htmx: true }, "", e); - Bt = e; - } - function Kt(e) { - se(e, function (e) { - e.call(undefined); - }); - } - function Gt(o) { - const e = new XMLHttpRequest(); - const i = { path: o, xhr: e }; - de(ne().body, "htmx:historyCacheMiss", i); - e.open("GET", o, true); - e.setRequestHeader("HX-Request", "true"); - e.setRequestHeader("HX-History-Restore-Request", "true"); - e.setRequestHeader("HX-Current-URL", ne().location.href); - e.onload = function () { - if (this.status >= 200 && this.status < 400) { - de(ne().body, "htmx:historyCacheMissLoad", i); - const e = P(this.response); - const t = - e.querySelector("[hx-history-elt],[data-hx-history-elt]") || e; - const n = Ut(); - const r = xn(n); - kn(e.title); - qe(e); - Ve(n, t, r); - Te(); - Kt(r.tasks); - Bt = o; - de(ne().body, "htmx:historyRestore", { - path: o, - cacheMiss: true, - serverResponse: this.response, - }); - } else { - fe(ne().body, "htmx:historyCacheMissLoadError", i); - } - }; - e.send(); - } - function Wt(e) { - zt(); - e = e || location.pathname + location.search; - const t = Vt(e); - if (t) { - const n = P(t.content); - const r = Ut(); - const o = xn(r); - kn(t.title); - qe(n); - Ve(r, n, o); - Te(); - Kt(o.tasks); - E().setTimeout(function () { - window.scrollTo(0, t.scroll); - }, 0); - Bt = e; - de(ne().body, "htmx:historyRestore", { path: e, item: t }); - } else { - if (Q.config.refreshOnHistoryMiss) { - window.location.reload(true); - } else { - Gt(e); - } - } - } - function Zt(e) { - let t = we(e, "hx-indicator"); - if (t == null) { - t = [e]; - } - se(t, function (e) { - const t = ie(e); - t.requestCount = (t.requestCount || 0) + 1; - e.classList.add.call(e.classList, Q.config.requestClass); - }); - return t; - } - function Yt(e) { - let t = we(e, "hx-disabled-elt"); - if (t == null) { - t = []; - } - se(t, function (e) { - const t = ie(e); - t.requestCount = (t.requestCount || 0) + 1; - e.setAttribute("disabled", ""); - e.setAttribute("data-disabled-by-htmx", ""); - }); - return t; - } - function Qt(e, t) { - se(e.concat(t), function (e) { - const t = ie(e); - t.requestCount = (t.requestCount || 1) - 1; - }); - se(e, function (e) { - const t = ie(e); - if (t.requestCount === 0) { - e.classList.remove.call(e.classList, Q.config.requestClass); - } - }); - se(t, function (e) { - const t = ie(e); - if (t.requestCount === 0) { - e.removeAttribute("disabled"); - e.removeAttribute("data-disabled-by-htmx"); - } - }); - } - function en(t, n) { - for (let e = 0; e < t.length; e++) { - const r = t[e]; - if (r.isSameNode(n)) { - return true; - } - } - return false; - } - function tn(e) { - const t = e; - if ( - t.name === "" || - t.name == null || - t.disabled || - g(t, "fieldset[disabled]") - ) { - return false; - } - if ( - t.type === "button" || - t.type === "submit" || - t.tagName === "image" || - t.tagName === "reset" || - t.tagName === "file" - ) { - return false; - } - if (t.type === "checkbox" || t.type === "radio") { - return t.checked; - } - return true; - } - function nn(t, e, n) { - if (t != null && e != null) { - if (Array.isArray(e)) { - e.forEach(function (e) { - n.append(t, e); - }); - } else { - n.append(t, e); - } - } - } - function rn(t, n, r) { - if (t != null && n != null) { - let e = r.getAll(t); - if (Array.isArray(n)) { - e = e.filter((e) => n.indexOf(e) < 0); - } else { - e = e.filter((e) => e !== n); - } - r.delete(t); - se(e, (e) => r.append(t, e)); - } - } - function on(t, n, r, o, i) { - if (o == null || en(t, o)) { - return; - } else { - t.push(o); - } - if (tn(o)) { - const s = ee(o, "name"); - let e = o.value; - if (o instanceof HTMLSelectElement && o.multiple) { - e = M(o.querySelectorAll("option:checked")).map(function (e) { - return e.value; - }); - } - if (o instanceof HTMLInputElement && o.files) { - e = M(o.files); - } - nn(s, e, n); - if (i) { - sn(o, r); - } - } - if (o instanceof HTMLFormElement) { - se(o.elements, function (e) { - if (t.indexOf(e) >= 0) { - rn(e.name, e.value, n); - } else { - t.push(e); - } - if (i) { - sn(e, r); - } - }); - new FormData(o).forEach(function (e, t) { - if (e instanceof File && e.name === "") { - return; - } - nn(t, e, n); - }); - } - } - function sn(e, t) { - const n = e; - if (n.willValidate) { - de(n, "htmx:validation:validate"); - if (!n.checkValidity()) { - t.push({ elt: n, message: n.validationMessage, validity: n.validity }); - de(n, "htmx:validation:failed", { - message: n.validationMessage, - validity: n.validity, - }); - } - } - } - function ln(n, e) { - for (const t of e.keys()) { - n.delete(t); - } - e.forEach(function (e, t) { - n.append(t, e); - }); - return n; - } - function cn(e, t) { - const n = []; - const r = new FormData(); - const o = new FormData(); - const i = []; - const s = ie(e); - if (s.lastButtonClicked && !le(s.lastButtonClicked)) { - s.lastButtonClicked = null; - } - let l = - (e instanceof HTMLFormElement && e.noValidate !== true) || - te(e, "hx-validate") === "true"; - if (s.lastButtonClicked) { - l = l && s.lastButtonClicked.formNoValidate !== true; - } - if (t !== "get") { - on(n, o, i, g(e, "form"), l); - } - on(n, r, i, e, l); - if ( - s.lastButtonClicked || - e.tagName === "BUTTON" || - (e.tagName === "INPUT" && ee(e, "type") === "submit") - ) { - const u = s.lastButtonClicked || e; - const a = ee(u, "name"); - nn(a, u.value, o); - } - const c = we(e, "hx-include"); - se(c, function (e) { - on(n, r, i, ue(e), l); - if (!d(e, "form")) { - se(f(e).querySelectorAll(ot), function (e) { - on(n, r, i, e, l); - }); - } - }); - ln(r, o); - return { errors: i, formData: r, values: Nn(r) }; - } - function un(e, t, n) { - if (e !== "") { - e += "&"; - } - if (String(n) === "[object Object]") { - n = JSON.stringify(n); - } - const r = encodeURIComponent(n); - e += encodeURIComponent(t) + "=" + r; - return e; - } - function an(e) { - e = qn(e); - let n = ""; - e.forEach(function (e, t) { - n = un(n, t, e); - }); - return n; - } - function fn(e, t, n) { - const r = { - "HX-Request": "true", - "HX-Trigger": ee(e, "id"), - "HX-Trigger-Name": ee(e, "name"), - "HX-Target": te(t, "id"), - "HX-Current-URL": ne().location.href, - }; - bn(e, "hx-headers", false, r); - if (n !== undefined) { - r["HX-Prompt"] = n; - } - if (ie(e).boosted) { - r["HX-Boosted"] = "true"; - } - return r; - } - function dn(n, e) { - const t = re(e, "hx-params"); - if (t) { - if (t === "none") { - return new FormData(); - } else if (t === "*") { - return n; - } else if (t.indexOf("not ") === 0) { - se(t.substr(4).split(","), function (e) { - e = e.trim(); - n.delete(e); - }); - return n; - } else { - const r = new FormData(); - se(t.split(","), function (t) { - t = t.trim(); - if (n.has(t)) { - n.getAll(t).forEach(function (e) { - r.append(t, e); - }); - } - }); - return r; - } - } else { - return n; - } - } - function hn(e) { - return !!ee(e, "href") && ee(e, "href").indexOf("#") >= 0; - } - function gn(e, t) { - const n = t || re(e, "hx-swap"); - const r = { - swapStyle: ie(e).boosted ? "innerHTML" : Q.config.defaultSwapStyle, - swapDelay: Q.config.defaultSwapDelay, - settleDelay: Q.config.defaultSettleDelay, - }; - if (Q.config.scrollIntoViewOnBoost && ie(e).boosted && !hn(e)) { - r.show = "top"; - } - if (n) { - const s = F(n); - if (s.length > 0) { - for (let e = 0; e < s.length; e++) { - const l = s[e]; - if (l.indexOf("swap:") === 0) { - r.swapDelay = h(l.substr(5)); - } else if (l.indexOf("settle:") === 0) { - r.settleDelay = h(l.substr(7)); - } else if (l.indexOf("transition:") === 0) { - r.transition = l.substr(11) === "true"; - } else if (l.indexOf("ignoreTitle:") === 0) { - r.ignoreTitle = l.substr(12) === "true"; - } else if (l.indexOf("scroll:") === 0) { - const c = l.substr(7); - var o = c.split(":"); - const u = o.pop(); - var i = o.length > 0 ? o.join(":") : null; - r.scroll = u; - r.scrollTarget = i; - } else if (l.indexOf("show:") === 0) { - const a = l.substr(5); - var o = a.split(":"); - const f = o.pop(); - var i = o.length > 0 ? o.join(":") : null; - r.show = f; - r.showTarget = i; - } else if (l.indexOf("focus-scroll:") === 0) { - const d = l.substr("focus-scroll:".length); - r.focusScroll = d == "true"; - } else if (e == 0) { - r.swapStyle = l; - } else { - C("Unknown modifier in hx-swap: " + l); - } - } - } - } - return r; - } - function pn(e) { - return ( - re(e, "hx-encoding") === "multipart/form-data" || - (d(e, "form") && ee(e, "enctype") === "multipart/form-data") - ); - } - function mn(t, n, r) { - let o = null; - Ft(n, function (e) { - if (o == null) { - o = e.encodeParameters(t, r, n); - } - }); - if (o != null) { - return o; - } else { - if (pn(n)) { - return ln(new FormData(), qn(r)); - } else { - return an(r); - } - } - } - function xn(e) { - return { tasks: [], elts: [e] }; - } - function yn(e, t) { - const n = e[0]; - const r = e[e.length - 1]; - if (t.scroll) { - var o = null; - if (t.scrollTarget) { - o = ue(ae(n, t.scrollTarget)); - } - if (t.scroll === "top" && (n || o)) { - o = o || n; - o.scrollTop = 0; - } - if (t.scroll === "bottom" && (r || o)) { - o = o || r; - o.scrollTop = o.scrollHeight; - } - } - if (t.show) { - var o = null; - if (t.showTarget) { - let e = t.showTarget; - if (t.showTarget === "window") { - e = "body"; - } - o = ue(ae(n, e)); - } - if (t.show === "top" && (n || o)) { - o = o || n; - o.scrollIntoView({ block: "start", behavior: Q.config.scrollBehavior }); - } - if (t.show === "bottom" && (r || o)) { - o = o || r; - o.scrollIntoView({ block: "end", behavior: Q.config.scrollBehavior }); - } - } - } - function bn(r, e, o, i) { - if (i == null) { - i = {}; - } - if (r == null) { - return i; - } - const s = te(r, e); - if (s) { - let e = s.trim(); - let t = o; - if (e === "unset") { - return null; - } - if (e.indexOf("javascript:") === 0) { - e = e.substr(11); - t = true; - } else if (e.indexOf("js:") === 0) { - e = e.substr(3); - t = true; - } - if (e.indexOf("{") !== 0) { - e = "{" + e + "}"; - } - let n; - if (t) { - n = vn( - r, - function () { - return Function("return (" + e + ")")(); - }, - {}, - ); - } else { - n = S(e); - } - for (const l in n) { - if (n.hasOwnProperty(l)) { - if (i[l] == null) { - i[l] = n[l]; - } - } - } - } - return bn(ue(c(r)), e, o, i); - } - function vn(e, t, n) { - if (Q.config.allowEval) { - return t(); - } else { - fe(e, "htmx:evalDisallowedError"); - return n; - } - } - function wn(e, t) { - return bn(e, "hx-vars", true, t); - } - function Sn(e, t) { - return bn(e, "hx-vals", false, t); - } - function En(e) { - return ce(wn(e), Sn(e)); - } - function Cn(t, n, r) { - if (r !== null) { - try { - t.setRequestHeader(n, r); - } catch (e) { - t.setRequestHeader(n, encodeURIComponent(r)); - t.setRequestHeader(n + "-URI-AutoEncoded", "true"); - } - } - } - function On(t) { - if (t.responseURL && typeof URL !== "undefined") { - try { - const e = new URL(t.responseURL); - return e.pathname + e.search; - } catch (e) { - fe(ne().body, "htmx:badResponseUrl", { url: t.responseURL }); - } - } - } - function O(e, t) { - return t.test(e.getAllResponseHeaders()); - } - function Rn(t, n, r) { - t = t.toLowerCase(); - if (r) { - if (r instanceof Element || typeof r === "string") { - return he(t, n, null, null, { - targetOverride: y(r) || ve, - returnPromise: true, - }); - } else { - let e = y(r.target); - if ((r.target && !e) || (!e && !y(r.source))) { - e = ve; - } - return he(t, n, y(r.source), r.event, { - handler: r.handler, - headers: r.headers, - values: r.values, - targetOverride: e, - swapOverride: r.swap, - select: r.select, - returnPromise: true, - }); - } - } else { - return he(t, n, null, null, { returnPromise: true }); - } - } - function Hn(e) { - const t = []; - while (e) { - t.push(e); - e = e.parentElement; - } - return t; - } - function Tn(e, t, n) { - let r; - let o; - if (typeof URL === "function") { - o = new URL(t, document.location.href); - const i = document.location.origin; - r = i === o.origin; - } else { - o = t; - r = l(t, document.location.origin); - } - if (Q.config.selfRequestsOnly) { - if (!r) { - return false; - } - } - return de(e, "htmx:validateUrl", ce({ url: o, sameHost: r }, n)); - } - function qn(e) { - if (e instanceof FormData) return e; - const t = new FormData(); - for (const n in e) { - if (e.hasOwnProperty(n)) { - if (e[n] && typeof e[n].forEach === "function") { - e[n].forEach(function (e) { - t.append(n, e); - }); - } else if (typeof e[n] === "object" && !(e[n] instanceof Blob)) { - t.append(n, JSON.stringify(e[n])); - } else { - t.append(n, e[n]); - } - } - } - return t; - } - function Ln(r, o, e) { - return new Proxy(e, { - get: function (t, e) { - if (typeof e === "number") return t[e]; - if (e === "length") return t.length; - if (e === "push") { - return function (e) { - t.push(e); - r.append(o, e); - }; - } - if (typeof t[e] === "function") { - return function () { - t[e].apply(t, arguments); - r.delete(o); - t.forEach(function (e) { - r.append(o, e); - }); - }; - } - if (t[e] && t[e].length === 1) { - return t[e][0]; - } else { - return t[e]; - } - }, - set: function (e, t, n) { - e[t] = n; - r.delete(o); - e.forEach(function (e) { - r.append(o, e); - }); - return true; - }, - }); - } - function Nn(r) { - return new Proxy(r, { - get: function (e, t) { - if (typeof t === "symbol") { - return Reflect.get(e, t); - } - if (t === "toJSON") { - return () => Object.fromEntries(r); - } - if (t in e) { - if (typeof e[t] === "function") { - return function () { - return r[t].apply(r, arguments); - }; - } else { - return e[t]; - } - } - const n = r.getAll(t); - if (n.length === 0) { - return undefined; - } else if (n.length === 1) { - return n[0]; - } else { - return Ln(e, t, n); - } - }, - set: function (t, n, e) { - if (typeof n !== "string") { - return false; - } - t.delete(n); - if (e && typeof e.forEach === "function") { - e.forEach(function (e) { - t.append(n, e); - }); - } else if (typeof e === "object" && !(e instanceof Blob)) { - t.append(n, JSON.stringify(e)); - } else { - t.append(n, e); - } - return true; - }, - deleteProperty: function (e, t) { - if (typeof t === "string") { - e.delete(t); - } - return true; - }, - ownKeys: function (e) { - return Reflect.ownKeys(Object.fromEntries(e)); - }, - getOwnPropertyDescriptor: function (e, t) { - return Reflect.getOwnPropertyDescriptor(Object.fromEntries(e), t); - }, - }); - } - function he(t, n, r, o, i, D) { - let s = null; - let l = null; - i = i != null ? i : {}; - if (i.returnPromise && typeof Promise !== "undefined") { - var e = new Promise(function (e, t) { - s = e; - l = t; - }); - } - if (r == null) { - r = ne().body; - } - const M = i.handler || Dn; - const X = i.select || null; - if (!le(r)) { - oe(s); - return e; - } - const c = i.targetOverride || ue(Ee(r)); - if (c == null || c == ve) { - fe(r, "htmx:targetError", { target: te(r, "hx-target") }); - oe(l); - return e; - } - let u = ie(r); - const a = u.lastButtonClicked; - if (a) { - const L = ee(a, "formaction"); - if (L != null) { - n = L; - } - const N = ee(a, "formmethod"); - if (N != null) { - if (N.toLowerCase() !== "dialog") { - t = N; - } - } - } - const f = re(r, "hx-confirm"); - if (D === undefined) { - const K = function (e) { - return he(t, n, r, o, i, !!e); - }; - const G = { - target: c, - elt: r, - path: n, - verb: t, - triggeringEvent: o, - etc: i, - issueRequest: K, - question: f, - }; - if (de(r, "htmx:confirm", G) === false) { - oe(s); - return e; - } - } - let d = r; - let h = re(r, "hx-sync"); - let g = null; - let F = false; - if (h) { - const A = h.split(":"); - const I = A[0].trim(); - if (I === "this") { - d = Se(r, "hx-sync"); - } else { - d = ue(ae(r, I)); - } - h = (A[1] || "drop").trim(); - u = ie(d); - if (h === "drop" && u.xhr && u.abortable !== true) { - oe(s); - return e; - } else if (h === "abort") { - if (u.xhr) { - oe(s); - return e; - } else { - F = true; - } - } else if (h === "replace") { - de(d, "htmx:abort"); - } else if (h.indexOf("queue") === 0) { - const W = h.split(" "); - g = (W[1] || "last").trim(); - } - } - if (u.xhr) { - if (u.abortable) { - de(d, "htmx:abort"); - } else { - if (g == null) { - if (o) { - const P = ie(o); - if (P && P.triggerSpec && P.triggerSpec.queue) { - g = P.triggerSpec.queue; - } - } - if (g == null) { - g = "last"; - } - } - if (u.queuedRequests == null) { - u.queuedRequests = []; - } - if (g === "first" && u.queuedRequests.length === 0) { - u.queuedRequests.push(function () { - he(t, n, r, o, i); - }); - } else if (g === "all") { - u.queuedRequests.push(function () { - he(t, n, r, o, i); - }); - } else if (g === "last") { - u.queuedRequests = []; - u.queuedRequests.push(function () { - he(t, n, r, o, i); - }); - } - oe(s); - return e; - } - } - const p = new XMLHttpRequest(); - u.xhr = p; - u.abortable = F; - const m = function () { - u.xhr = null; - u.abortable = false; - if (u.queuedRequests != null && u.queuedRequests.length > 0) { - const e = u.queuedRequests.shift(); - e(); - } - }; - const B = re(r, "hx-prompt"); - if (B) { - var x = prompt(B); - if (x === null || !de(r, "htmx:prompt", { prompt: x, target: c })) { - oe(s); - m(); - return e; - } - } - if (f && !D) { - if (!confirm(f)) { - oe(s); - m(); - return e; - } - } - let y = fn(r, c, x); - if (t !== "get" && !pn(r)) { - y["Content-Type"] = "application/x-www-form-urlencoded"; - } - if (i.headers) { - y = ce(y, i.headers); - } - const U = cn(r, t); - let b = U.errors; - const j = U.formData; - if (i.values) { - ln(j, qn(i.values)); - } - const V = qn(En(r)); - const v = ln(j, V); - let w = dn(v, r); - if (Q.config.getCacheBusterParam && t === "get") { - w.set("org.htmx.cache-buster", ee(c, "id") || "true"); - } - if (n == null || n === "") { - n = ne().location.href; - } - const S = bn(r, "hx-request"); - const _ = ie(r).boosted; - let E = Q.config.methodsThatUseUrlParams.indexOf(t) >= 0; - const C = { - boosted: _, - useUrlParams: E, - formData: w, - parameters: Nn(w), - unfilteredFormData: v, - unfilteredParameters: Nn(v), - headers: y, - target: c, - verb: t, - errors: b, - withCredentials: - i.credentials || S.credentials || Q.config.withCredentials, - timeout: i.timeout || S.timeout || Q.config.timeout, - path: n, - triggeringEvent: o, - }; - if (!de(r, "htmx:configRequest", C)) { - oe(s); - m(); - return e; - } - n = C.path; - t = C.verb; - y = C.headers; - w = qn(C.parameters); - b = C.errors; - E = C.useUrlParams; - if (b && b.length > 0) { - de(r, "htmx:validation:halted", C); - oe(s); - m(); - return e; - } - const z = n.split("#"); - const $ = z[0]; - const O = z[1]; - let R = n; - if (E) { - R = $; - const Z = !w.keys().next().done; - if (Z) { - if (R.indexOf("?") < 0) { - R += "?"; - } else { - R += "&"; - } - R += an(w); - if (O) { - R += "#" + O; - } - } - } - if (!Tn(r, R, C)) { - fe(r, "htmx:invalidPath", C); - oe(l); - return e; - } - p.open(t.toUpperCase(), R, true); - p.overrideMimeType("text/html"); - p.withCredentials = C.withCredentials; - p.timeout = C.timeout; - if (S.noHeaders) { - } else { - for (const k in y) { - if (y.hasOwnProperty(k)) { - const Y = y[k]; - Cn(p, k, Y); - } - } - } - const H = { - xhr: p, - target: c, - requestConfig: C, - etc: i, - boosted: _, - select: X, - pathInfo: { - requestPath: n, - finalRequestPath: R, - responsePath: null, - anchor: O, - }, - }; - p.onload = function () { - try { - const t = Hn(r); - H.pathInfo.responsePath = On(p); - M(r, H); - if (H.keepIndicators !== true) { - Qt(T, q); - } - de(r, "htmx:afterRequest", H); - de(r, "htmx:afterOnLoad", H); - if (!le(r)) { - let e = null; - while (t.length > 0 && e == null) { - const n = t.shift(); - if (le(n)) { - e = n; - } - } - if (e) { - de(e, "htmx:afterRequest", H); - de(e, "htmx:afterOnLoad", H); - } - } - oe(s); - m(); - } catch (e) { - fe(r, "htmx:onLoadError", ce({ error: e }, H)); - throw e; - } - }; - p.onerror = function () { - Qt(T, q); - fe(r, "htmx:afterRequest", H); - fe(r, "htmx:sendError", H); - oe(l); - m(); - }; - p.onabort = function () { - Qt(T, q); - fe(r, "htmx:afterRequest", H); - fe(r, "htmx:sendAbort", H); - oe(l); - m(); - }; - p.ontimeout = function () { - Qt(T, q); - fe(r, "htmx:afterRequest", H); - fe(r, "htmx:timeout", H); - oe(l); - m(); - }; - if (!de(r, "htmx:beforeRequest", H)) { - oe(s); - m(); - return e; - } - var T = Zt(r); - var q = Yt(r); - se(["loadstart", "loadend", "progress", "abort"], function (t) { - se([p, p.upload], function (e) { - e.addEventListener(t, function (e) { - de(r, "htmx:xhr:" + t, { - lengthComputable: e.lengthComputable, - loaded: e.loaded, - total: e.total, - }); - }); - }); - }); - de(r, "htmx:beforeSend", H); - const J = E ? null : mn(p, r, w); - p.send(J); - return e; - } - function An(e, t) { - const n = t.xhr; - let r = null; - let o = null; - if (O(n, /HX-Push:/i)) { - r = n.getResponseHeader("HX-Push"); - o = "push"; - } else if (O(n, /HX-Push-Url:/i)) { - r = n.getResponseHeader("HX-Push-Url"); - o = "push"; - } else if (O(n, /HX-Replace-Url:/i)) { - r = n.getResponseHeader("HX-Replace-Url"); - o = "replace"; - } - if (r) { - if (r === "false") { - return {}; - } else { - return { type: o, path: r }; - } - } - const i = t.pathInfo.finalRequestPath; - const s = t.pathInfo.responsePath; - const l = re(e, "hx-push-url"); - const c = re(e, "hx-replace-url"); - const u = ie(e).boosted; - let a = null; - let f = null; - if (l) { - a = "push"; - f = l; - } else if (c) { - a = "replace"; - f = c; - } else if (u) { - a = "push"; - f = s || i; - } - if (f) { - if (f === "false") { - return {}; - } - if (f === "true") { - f = s || i; - } - if (t.pathInfo.anchor && f.indexOf("#") === -1) { - f = f + "#" + t.pathInfo.anchor; - } - return { type: a, path: f }; - } else { - return {}; - } - } - function In(e, t) { - var n = new RegExp(e.code); - return n.test(t.toString(10)); - } - function Pn(e) { - for (var t = 0; t < Q.config.responseHandling.length; t++) { - var n = Q.config.responseHandling[t]; - if (In(n, e.status)) { - return n; - } - } - return { swap: false }; - } - function kn(e) { - if (e) { - const t = r("title"); - if (t) { - t.innerHTML = e; - } else { - window.document.title = e; - } - } - } - function Dn(o, i) { - const s = i.xhr; - let l = i.target; - const e = i.etc; - const c = i.select; - if (!de(o, "htmx:beforeOnLoad", i)) return; - if (O(s, /HX-Trigger:/i)) { - Je(s, "HX-Trigger", o); - } - if (O(s, /HX-Location:/i)) { - zt(); - let e = s.getResponseHeader("HX-Location"); - var t; - if (e.indexOf("{") === 0) { - t = S(e); - e = t.path; - delete t.path; - } - Rn("get", e, t).then(function () { - $t(e); - }); - return; - } - const n = - O(s, /HX-Refresh:/i) && s.getResponseHeader("HX-Refresh") === "true"; - if (O(s, /HX-Redirect:/i)) { - i.keepIndicators = true; - location.href = s.getResponseHeader("HX-Redirect"); - n && location.reload(); - return; - } - if (n) { - i.keepIndicators = true; - location.reload(); - return; - } - if (O(s, /HX-Retarget:/i)) { - if (s.getResponseHeader("HX-Retarget") === "this") { - i.target = o; - } else { - i.target = ue(ae(o, s.getResponseHeader("HX-Retarget"))); - } - } - const u = An(o, i); - const r = Pn(s); - const a = r.swap; - let f = !!r.error; - let d = Q.config.ignoreTitle || r.ignoreTitle; - let h = r.select; - if (r.target) { - i.target = ue(ae(o, r.target)); - } - var g = e.swapOverride; - if (g == null && r.swapOverride) { - g = r.swapOverride; - } - if (O(s, /HX-Retarget:/i)) { - if (s.getResponseHeader("HX-Retarget") === "this") { - i.target = o; - } else { - i.target = ue(ae(o, s.getResponseHeader("HX-Retarget"))); - } - } - if (O(s, /HX-Reswap:/i)) { - g = s.getResponseHeader("HX-Reswap"); - } - var p = s.response; - var m = ce( - { - shouldSwap: a, - serverResponse: p, - isError: f, - ignoreTitle: d, - selectOverride: h, - swapOverride: g, - }, - i, - ); - if (r.event && !de(l, r.event, m)) return; - if (!de(l, "htmx:beforeSwap", m)) return; - l = m.target; - p = m.serverResponse; - f = m.isError; - d = m.ignoreTitle; - h = m.selectOverride; - g = m.swapOverride; - i.target = l; - i.failed = f; - i.successful = !f; - if (m.shouldSwap) { - if (s.status === 286) { - lt(o); - } - Ft(o, function (e) { - p = e.transformResponse(p, s, o); - }); - if (u.type) { - zt(); - } - var x = gn(o, g); - if (!x.hasOwnProperty("ignoreTitle")) { - x.ignoreTitle = d; - } - l.classList.add(Q.config.swappingClass); - let n = null; - let r = null; - if (c) { - h = c; - } - if (O(s, /HX-Reselect:/i)) { - h = s.getResponseHeader("HX-Reselect"); - } - const y = re(o, "hx-select-oob"); - const b = re(o, "hx-select"); - let e = function () { - try { - if (u.type) { - de(ne().body, "htmx:beforeHistoryUpdate", ce({ history: u }, i)); - if (u.type === "push") { - $t(u.path); - de(ne().body, "htmx:pushedIntoHistory", { path: u.path }); - } else { - Jt(u.path); - de(ne().body, "htmx:replacedInHistory", { path: u.path }); - } - } - $e(l, p, x, { - select: h || b, - selectOOB: y, - eventInfo: i, - anchor: i.pathInfo.anchor, - contextElement: o, - afterSwapCallback: function () { - if (O(s, /HX-Trigger-After-Swap:/i)) { - let e = o; - if (!le(o)) { - e = ne().body; - } - Je(s, "HX-Trigger-After-Swap", e); - } - }, - afterSettleCallback: function () { - if (O(s, /HX-Trigger-After-Settle:/i)) { - let e = o; - if (!le(o)) { - e = ne().body; - } - Je(s, "HX-Trigger-After-Settle", e); - } - oe(n); - }, - }); - } catch (e) { - fe(o, "htmx:swapError", i); - oe(r); - throw e; - } - }; - let t = Q.config.globalViewTransitions; - if (x.hasOwnProperty("transition")) { - t = x.transition; - } - if ( - t && - de(o, "htmx:beforeTransition", i) && - typeof Promise !== "undefined" && - document.startViewTransition - ) { - const v = new Promise(function (e, t) { - n = e; - r = t; - }); - const w = e; - e = function () { - document.startViewTransition(function () { - w(); - return v; - }); - }; - } - if (x.swapDelay > 0) { - E().setTimeout(e, x.swapDelay); - } else { - e(); - } - } - if (f) { - fe( - o, - "htmx:responseError", - ce( - { - error: - "Response Status Error Code " + - s.status + - " from " + - i.pathInfo.requestPath, - }, - i, - ), - ); - } - } - const Mn = {}; - function Xn() { - return { - init: function (e) { - return null; - }, - getSelectors: function () { - return null; - }, - onEvent: function (e, t) { - return true; - }, - transformResponse: function (e, t, n) { - return e; - }, - isInlineSwap: function (e) { - return false; - }, - handleSwap: function (e, t, n, r) { - return false; - }, - encodeParameters: function (e, t, n) { - return null; - }, - }; - } - function Fn(e, t) { - if (t.init) { - t.init(n); - } - Mn[e] = ce(Xn(), t); - } - function Bn(e) { - delete Mn[e]; - } - function Un(e, n, r) { - if (n == undefined) { - n = []; - } - if (e == undefined) { - return n; - } - if (r == undefined) { - r = []; - } - const t = te(e, "hx-ext"); - if (t) { - se(t.split(","), function (e) { - e = e.replace(/ /g, ""); - if (e.slice(0, 7) == "ignore:") { - r.push(e.slice(7)); - return; - } - if (r.indexOf(e) < 0) { - const t = Mn[e]; - if (t && n.indexOf(t) < 0) { - n.push(t); - } - } - }); - } - return Un(ue(c(e)), n, r); - } - var jn = false; - ne().addEventListener("DOMContentLoaded", function () { - jn = true; - }); - function Vn(e) { - if (jn || ne().readyState === "complete") { - e(); - } else { - ne().addEventListener("DOMContentLoaded", e); - } - } - function _n() { - if (Q.config.includeIndicatorStyles !== false) { - const e = Q.config.inlineStyleNonce - ? ` nonce="${Q.config.inlineStyleNonce}"` - : ""; - ne().head.insertAdjacentHTML( - "beforeend", - " ." + - Q.config.indicatorClass + - "{opacity:0} ." + - Q.config.requestClass + - " ." + - Q.config.indicatorClass + - "{opacity:1; transition: opacity 200ms ease-in;} ." + - Q.config.requestClass + - "." + - Q.config.indicatorClass + - "{opacity:1; transition: opacity 200ms ease-in;} ", - ); - } - } - function zn() { - const e = ne().querySelector('meta[name="htmx-config"]'); - if (e) { - return S(e.content); - } else { - return null; - } - } - function $n() { - const e = zn(); - if (e) { - Q.config = ce(Q.config, e); - } - } - Vn(function () { - $n(); - _n(); - let e = ne().body; - kt(e); - const t = ne().querySelectorAll( - "[hx-trigger='restored'],[data-hx-trigger='restored']", - ); - e.addEventListener("htmx:abort", function (e) { - const t = e.target; - const n = ie(t); - if (n && n.xhr) { - n.xhr.abort(); - } - }); - const n = window.onpopstate ? window.onpopstate.bind(window) : null; - window.onpopstate = function (e) { - if (e.state && e.state.htmx) { - Wt(); - se(t, function (e) { - de(e, "htmx:restored", { document: ne(), triggerEvent: de }); - }); - } else { - if (n) { - n(e); - } - } - }; - E().setTimeout(function () { - de(e, "htmx:load", {}); - e = null; - }, 0); - }); - return Q; -})(); diff --git a/cmd/web/base.templ b/cmd/web/base.templ deleted file mode 100644 index 7484dba..0000000 --- a/cmd/web/base.templ +++ /dev/null @@ -1,18 +0,0 @@ -package web - -templ Base() { - - - - - Go Blueprint Hello - - - - -
- { children... } -
- - -} diff --git a/cmd/web/efs.go b/cmd/web/efs.go deleted file mode 100644 index 57b9761..0000000 --- a/cmd/web/efs.go +++ /dev/null @@ -1,6 +0,0 @@ -package web - -import "embed" - -//go:embed "assets" -var Files embed.FS diff --git a/cmd/web/hello.go b/cmd/web/hello.go deleted file mode 100644 index 98cd24e..0000000 --- a/cmd/web/hello.go +++ /dev/null @@ -1,21 +0,0 @@ -package web - -import ( - "log" - "net/http" -) - -func HelloWebHandler(w http.ResponseWriter, r *http.Request) { - err := r.ParseForm() - if err != nil { - http.Error(w, "Bad Request", http.StatusBadRequest) - } - - name := r.FormValue("name") - component := HelloPost(name) - err = component.Render(r.Context(), w) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - log.Fatalf("Error rendering in HelloWebHandler: %e", err) - } -} diff --git a/cmd/web/hello.templ b/cmd/web/hello.templ deleted file mode 100644 index f5f5d72..0000000 --- a/cmd/web/hello.templ +++ /dev/null @@ -1,17 +0,0 @@ -package web - -templ HelloForm() { - @Base() { -
- - -
-
- } -} - -templ HelloPost(name string) { -
-

Hello, { name }

-
-} diff --git a/docker-compose.yml b/docker-compose.yml index b11a95a..b27ce7f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,14 +3,33 @@ services: build: context: . dockerfile: Dockerfile + container_name: api-keuangan restart: always ports: - - 8803:8803 + - 8080:8080 + volumes: + - .:/app + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro environment: - TZ: Asia/Jakarta - MONGODB_DEV_HOST: 10.10.123.206 - MONGODB_DEV_PORT: 27017 - MONGODB_DEV_USER: admin - MONGODB_DEV_PASS: stim*rs54 - MONGODB_DEV_MASTER: master - MONGODB_DEV_LOCAL: local \ No newline at end of file + # TIMEZONE + - TZ=Asia/Jakarta + # DATABASE SIMRS V3.0 + - SIMRS_STAG_HOST=10.10.123.223 + - SIMRS_STAG_PORT=5432 + - SIMRS_STAG_NAME=simrs-stag + - SIMRS_STAG_USER=simtest + - SIMRS_STAG_PASS=12345 + # DATABASE SATU DATA + - SATUDATA_HOST=10.10.123.165 + - SATUDATA_USER=stim + - SATUDATA_PASS=stim*RS54 + - SATUDATA_NAME=satu_db + - SATUDATA_PORT=5000 + # MONGODB DEV + - MONGODB_DEV_HOST=10.10.123.206 + - MONGODB_DEV_PORT=27017 + - MONGODB_DEV_USER=admin + - MONGODB_DEV_PASS=stim*rs54 + - MONGODB_DEV_MASTER=master + - MONGODB_DEV_LOCAL=local \ No newline at end of file diff --git a/docker-push.sh b/docker-push.sh new file mode 100644 index 0000000..0510d0d --- /dev/null +++ b/docker-push.sh @@ -0,0 +1,27 @@ +!/bin/bash + +#get image name +remote_url=$(git remote get-url origin) +image=$(echo $remote_url | sed 's|https://||g; s|.git||g') + +#get branch name +branch_name=$(git rev-parse --abbrev-ref HEAD) +clean_branch_name=${branch_name##*/} + +#get timestamp for the tag +timestamp=$(date +%Y%m%d%H%M%S) + +tag=$image:$timestamp-$clean_branch_name +latest=$image:latest-$clean_branch_name + +#build image +docker build -t $tag . +docker tag $tag $latest + +#push to dockerhub +docker login git.rssa.top -u stim -p 4fde63b07906e7bfa6b3493d76d153a3981039b9 +docker push $tag +docker push $latest + +#remove dangling images +docker system prune -f diff --git a/go.mod b/go.mod index 3dc6c39..da173bb 100644 --- a/go.mod +++ b/go.mod @@ -3,14 +3,16 @@ module template_blueprint go 1.23.1 require ( - github.com/a-h/templ v0.3.833 github.com/coder/websocket v1.8.12 github.com/gin-contrib/cors v1.7.4 github.com/gin-gonic/gin v1.10.0 github.com/google/uuid v1.6.0 + github.com/jackc/pgx/v5 v5.7.5 github.com/joho/godotenv v1.5.1 github.com/testcontainers/testcontainers-go/modules/mongodb v0.35.0 go.mongodb.org/mongo-driver v1.17.3 + gorm.io/driver/postgres v1.5.11 + gorm.io/gorm v1.30.0 ) require ( @@ -42,6 +44,11 @@ require ( github.com/goccy/go-json v0.10.5 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.17.4 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect @@ -83,11 +90,11 @@ require ( go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect golang.org/x/arch v0.15.0 // indirect - golang.org/x/crypto v0.36.0 // indirect + golang.org/x/crypto v0.38.0 // indirect golang.org/x/net v0.37.0 // indirect - golang.org/x/sync v0.12.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/sync v0.14.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/text v0.25.0 // indirect google.golang.org/protobuf v1.36.5 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index fb880df..6d8ccb2 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,6 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOEl github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/a-h/templ v0.3.833 h1:L/KOk/0VvVTBegtE0fp2RJQiBm7/52Zxv5fqlEHiQUU= -github.com/a-h/templ v0.3.833/go.mod h1:cAu4AiZhtJfBjMY0HASlyzvkrtjnHWPeEsyGK2YYmfk= github.com/bytedance/sonic v1.12.10 h1:uVCQr6oS5669E9ZVW0HyksTLfNS7Q/9hV6IVS4nEMsI= github.com/bytedance/sonic v1.12.10/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= @@ -81,6 +79,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs= +github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -208,8 +218,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -225,8 +235,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -242,18 +252,18 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -280,6 +290,10 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314= +gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= +gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs= +gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= diff --git a/internal/database/database.go b/internal/database/database.go index a82bffd..582ef6b 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -3,38 +3,100 @@ package database import ( "context" "fmt" - "go.mongodb.org/mongo-driver/mongo/readpref" - "log" - "os" - "time" - + _ "github.com/jackc/pgx/v5/stdlib" + _ "github.com/joho/godotenv/autoload" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/mongo/readpref" + "gorm.io/driver/postgres" + "gorm.io/gorm" + "log" + "os" + "strconv" + "strings" + "time" ) +// Service represents a service that interacts with a database. type Service interface { Health() map[string]string - GetDB() *mongo.Database + Close() error + GetDB(database string) *gorm.DB + GetMongoDB() *mongo.Database } type service struct { - client *mongo.Client - db *mongo.Database + simrsDB *gorm.DB + satuDataDB *gorm.DB + client *mongo.Client + mongoDB *mongo.Database } var ( - host = os.Getenv("MONGODB_DEV_HOST") - port = os.Getenv("MONGODB_DEV_PORT") - user = os.Getenv("MONGODB_DEV_USER") - pass = os.Getenv("MONGODB_DEV_PASS") + hostSimrs = os.Getenv("SIMRS_STAG_HOST") + userNameSimrs = os.Getenv("SIMRS_STAG_USER") + passwordSimrs = os.Getenv("SIMRS_STAG_PASS") + dbNameSimrs = os.Getenv("SIMRS_STAG_NAME") + portSimrs = os.Getenv("SIMRS_STAG_PORT") + + hostSatudata = os.Getenv("SATUDATA_HOST") + userNameSatudata = os.Getenv("SATUDATA_USER") + passwordSatudata = os.Getenv("SATUDATA_PASS") + dbNameSatudata = os.Getenv("SATUDATA_NAME") + portSatudata = os.Getenv("SATUDATA_PORT") + + hostMongo = os.Getenv("MONGODB_DEV_HOST") + portMongo = os.Getenv("MONGODB_DEV_PORT") + userMongo = os.Getenv("MONGODB_DEV_USER") + passMongo = os.Getenv("MONGODB_DEV_PASS") + dbInstance *service ) -func New(database string) Service { - mongoURI := fmt.Sprintf("mongodb://%s:%s@%s:%s/%s?authSource=admin", - user, pass, host, port, database) +func New(database ...string) Service { + mongoDBName := os.Getenv("MONGODB_DEV_MASTER") + if len(database) > 0 { + mongoDBName = database[0] + } + if dbInstance != nil { + if database != nil { + mongoURI := fmt.Sprintf("mongodb://%s:%s@%s:%s/%s?authSource=admin", + userMongo, passMongo, hostMongo, portMongo, mongoDBName) + log.Println("Connecting to MongoDB...") + log.Println(mongoURI) + clientOptions := options.Client().ApplyURI(mongoURI) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + client, err := mongo.Connect(ctx, clientOptions) + if err == nil { + log.Println("Connected to MongoDB") + } + if err = client.Ping(ctx, readpref.Primary()); err != nil { + log.Println("Failed to connect to MongoDB!!!") + log.Fatalf("Failed to connect to database: %v", err) + } + dbInstance.mongoDB = client.Database(mongoDBName) + } + return dbInstance + } + simrs := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Jakarta", hostSimrs, userNameSimrs, passwordSimrs, dbNameSimrs, portSimrs) + SimrsDB, err := gorm.Open(postgres.Open(simrs), &gorm.Config{}) + if err != nil { + log.Fatal("Failed to connect to SIM database: ", err) + } else { + log.Println("Successfully connected to the database") + } + satudata := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Jakarta", hostSatudata, userNameSatudata, passwordSatudata, dbNameSatudata, portSatudata) + + SatudataDB, err := gorm.Open(postgres.Open(satudata), &gorm.Config{}) + if err != nil { + log.Fatal("Failed to connect to SIM database: ", err) + } else { + log.Println("Successfully connected to the database") + } + mongoURI := fmt.Sprintf("mongodb://%s:%s@%s:%s/%s?authSource=admin", + userMongo, passMongo, hostMongo, portMongo, database) var client *mongo.Client - var err error log.Println("Connecting to MongoDB...") log.Println(mongoURI) clientOptions := options.Client().ApplyURI(mongoURI) @@ -63,31 +125,104 @@ func New(database string) Service { } log.Println("Successfully connected to MongoDB!") - - return &service{ - client: client, - db: client.Database(database), + dbInstance = &service{ + simrsDB: SimrsDB, + satuDataDB: SatudataDB, + mongoDB: client.Database(mongoDBName), } + return dbInstance } +// Health checks the health of the database connection by pinging the database. +// It returns a map with keys indicating various health statistics. func (s *service) Health() map[string]string { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - status := map[string]string{ - "status": "up", - "message": "MongoDB connection is healthy", + stats := make(map[string]string) + + // Ping the database using GORM + db, err := s.simrsDB.DB() // Retrieve the underlying sql.DB instance from GORM + if err != nil { + stats["status"] = "down" + stats["error"] = fmt.Sprintf("failed to get sql.DB from GORM: %v", err) + log.Fatalf("failed to get sql.DB from GORM: %v", err) // Log the error and terminate the program + return stats } - if err := s.client.Ping(ctx, nil); err != nil { - status["status"] = "down" - status["error"] = err.Error() - status["message"] = "Connection to MongoDB failed" + err = db.PingContext(ctx) + if err != nil { + stats["status"] = "down" + stats["error"] = fmt.Sprintf("db down: %v", err) + log.Fatalf("db down: %v", err) // Log the error and terminate the program + return stats } - return status + // Database is up, add more statistics + stats["status"] = "up" + stats["message"] = "It's healthy" + + // Get database stats + dbStats := db.Stats() + stats["open_connections"] = strconv.Itoa(dbStats.OpenConnections) + stats["in_use"] = strconv.Itoa(dbStats.InUse) + stats["idle"] = strconv.Itoa(dbStats.Idle) + stats["wait_count"] = strconv.FormatInt(dbStats.WaitCount, 10) + stats["wait_duration"] = dbStats.WaitDuration.String() + stats["max_idle_closed"] = strconv.FormatInt(dbStats.MaxIdleClosed, 10) + stats["max_lifetime_closed"] = strconv.FormatInt(dbStats.MaxLifetimeClosed, 10) + + // Evaluate stats to provide a health message + if dbStats.OpenConnections > 40 { // Assuming 50 is the max for this example + stats["message"] = "The database is experiencing heavy load." + } + + if dbStats.WaitCount > 1000 { + stats["message"] = "The database has a high number of wait events, indicating potential bottlenecks." + } + + if dbStats.MaxIdleClosed > int64(dbStats.OpenConnections)/2 { + stats["message"] = "Many idle connections are being closed, consider revising the connection pool settings." + } + + if dbStats.MaxLifetimeClosed > int64(dbStats.OpenConnections)/2 { + stats["message"] = "Many connections are being closed due to max lifetime, consider increasing max lifetime or revising the connection usage pattern." + } + + return stats } -func (s *service) GetDB() *mongo.Database { - return s.db +// Close closes the database connection. +// It logs a message indicating the disconnection from the specific database. +// If the connection is successfully closed, it returns nil. +// If an error occurs while closing the connection, it returns the error. +func (s *service) Close() error { + db, err := s.simrsDB.DB() // Retrieve the underlying sql.DB instance from GORM + if err != nil { + log.Printf("Failed to retrieve sql.DB from GORM: %v", err) + return err + } + + err = db.Close() + if err != nil { + log.Printf("Error closing the database connection: %v", err) + return err + } + + log.Printf("Disconnected from database successfully") + return nil +} + +func (s *service) GetDB(database string) *gorm.DB { + if strings.ToLower(database) == "simrs" { + return s.simrsDB + } else if strings.ToLower(database) == "satudata" { + return s.satuDataDB + } + log.Println("Database tidak ditemukan") + return nil +} + +func (s *service) GetMongoDB() *mongo.Database { + return s.mongoDB } diff --git a/internal/server/routes.go b/internal/server/routes.go index f22c1d6..e413188 100644 --- a/internal/server/routes.go +++ b/internal/server/routes.go @@ -1,22 +1,14 @@ package server import ( - "net/http" - "fmt" - "log" - "time" - - "github.com/gin-gonic/gin" - - "github.com/a-h/templ" - "io/fs" - "template_blueprint/cmd/web" - "github.com/coder/websocket" - "github.com/gin-contrib/cors" - patientHandler "template_blueprint/pkg/handlers/patient" + "github.com/gin-gonic/gin" + "log" + "net/http" + LoginHandler "template_blueprint/pkg/handlers/login" + "time" ) func (s *Server) RegisterRoutes() http.Handler { @@ -26,23 +18,13 @@ func (s *Server) RegisterRoutes() http.Handler { r.GET("/websocket", s.websocketHandler) - staticFiles, _ := fs.Sub(web.Files, "assets") - r.StaticFS("/assets", http.FS(staticFiles)) - - r.GET("/web", func(c *gin.Context) { - templ.Handler(web.HelloForm()).ServeHTTP(c.Writer, c.Request) - }) - - r.POST("/hello", func(c *gin.Context) { - web.HelloWebHandler(c.Writer, c.Request) - }) - api := r.Group("/api") - patient := api.Group("/patient") + login := api.Group("/login") { - patient.POST("/insertpatient", patientHandler.InsertPatient) - patient.GET("/getallpatient", patientHandler.GetAllPatient) + login.GET("/get", LoginHandler.Getlogin) + login.GET("/:id", LoginHandler.GetloginbyID) } + r.Use(cors.New(cors.Config{ AllowOrigins: []string{"*"}, // or specific domains like "http://example.com" AllowMethods: []string{"GET", "POST", "PUT", "DELETE"}, diff --git a/pkg/database/mongo/database.go b/pkg/database/mongo/database.go index e6b82cb..4cebe32 100644 --- a/pkg/database/mongo/database.go +++ b/pkg/database/mongo/database.go @@ -5,9 +5,9 @@ import ( ) type DatabaseService struct { - DB *mongo.Database + DBMongo *mongo.Database } -func NewDatabaseService(db *mongo.Database) *DatabaseService { - return &DatabaseService{DB: db} +func NewDatabaseServiceMongo(db *mongo.Database) *DatabaseService { + return &DatabaseService{DBMongo: db} } diff --git a/pkg/database/mongo/login.go b/pkg/database/mongo/login.go new file mode 100644 index 0000000..0cf50ee --- /dev/null +++ b/pkg/database/mongo/login.go @@ -0,0 +1,52 @@ +package mongo + +import ( + "context" + "fmt" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo" + "log" + loginHandler "template_blueprint/pkg/models/login" + "time" +) + +func (s *DatabaseService) Getlogin() ([]*loginHandler.Menu, error) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + datalogin, err := s.DBMongo.Collection("role_menu_ex").Find(ctx, bson.D{}) + if err != nil { + log.Println(err) + } + var login []*loginHandler.Menu + err = datalogin.All(ctx, &login) + if err != nil { + log.Println(err) + return nil, err + } + return login, nil +} + +func (s *DatabaseService) GetByid(id string) (*loginHandler.Menu, error) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + objectID, err := primitive.ObjectIDFromHex(id) + if err != nil { + return nil, fmt.Errorf("invalid ID format: %v", err) + } + filter := bson.M{ + "_id": objectID, + } + + var result loginHandler.Menu + err = s.DBMongo.Collection("role_menu_ex").FindOne(ctx, filter).Decode(&result) + if err != nil { + if err == mongo.ErrNoDocuments { + return nil, fmt.Errorf("ID %s tidak ditemukan", id) + } + return nil, err + } + + return &result, nil +} diff --git a/pkg/database/mongo/master_data.go b/pkg/database/mongo/master_data.go deleted file mode 100644 index 5cb3257..0000000 --- a/pkg/database/mongo/master_data.go +++ /dev/null @@ -1,24 +0,0 @@ -package mongo - -import ( - "context" - "log" - "template_blueprint/pkg/models/master_data" - "time" -) - -func (s *DatabaseService) InsertDataMaster(req master_data.ReqInsertData) error { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - _, err := s.DB.Collection(req.Table).InsertOne(ctx, master_data.ReqInsertDataMaster{ - ID: req.ID, - System: req.System, - Code: req.Code, - Display: req.Display, - }) - if err != nil { - log.Println(err) - return err - } - return nil -} diff --git a/pkg/database/mongo/mongo.go b/pkg/database/mongo/mongo.go deleted file mode 100644 index a166cbe..0000000 --- a/pkg/database/mongo/mongo.go +++ /dev/null @@ -1,29 +0,0 @@ -package mongo - -import ( - "context" - "go.mongodb.org/mongo-driver/bson" - "log" - "template_blueprint/pkg/models/local" - "time" -) - -func (s *DatabaseService) GetDataLog() ([]*local.StartUpLog, error) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - dataLog, err := s.DB.Collection("startup_log").Find(ctx, bson.M{}) - if err != nil { - log.Println("MASUK SINI") - log.Println(err) - return nil, err - } - log.Println("Data", dataLog.Current) - var logs []*local.StartUpLog - errDecode := dataLog.All(ctx, &logs) - if errDecode != nil { - log.Println(errDecode) - return nil, errDecode - } - log.Println("LOGS :", logs) - return logs, nil -} diff --git a/pkg/database/mongo/patient.go b/pkg/database/mongo/patient.go deleted file mode 100644 index 1c7b36c..0000000 --- a/pkg/database/mongo/patient.go +++ /dev/null @@ -1,36 +0,0 @@ -package mongo - -import ( - "context" - "go.mongodb.org/mongo-driver/bson" - "log" - "template_blueprint/pkg/models/patient" - "time" -) - -func (s *DatabaseService) InsertPatient(req *patient.Patient) error { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - _, err := s.DB.Collection("patient").InsertOne(ctx, req) - if err != nil { - log.Println(err) - return err - } - return nil -} - -func (s *DatabaseService) GetAllDataPatient() ([]*patient.Patient, error) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - dataUser, err := s.DB.Collection("patient").Find(ctx, bson.D{}) - if err != nil { - log.Println(err) - } - var users []*patient.Patient - err = dataUser.All(ctx, &users) - if err != nil { - log.Println(err) - return nil, err - } - return users, nil -} diff --git a/pkg/database/mongo/user.go b/pkg/database/mongo/user.go deleted file mode 100644 index c3eef89..0000000 --- a/pkg/database/mongo/user.go +++ /dev/null @@ -1,88 +0,0 @@ -package mongo - -import ( - "context" - "go.mongodb.org/mongo-driver/bson" - "log" - "template_blueprint/pkg/models/user" - "time" -) - -func (s *DatabaseService) InsertUser(req user.ReqInsertUser) error { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - _, err := s.DB.Collection("user").InsertOne(ctx, user.ReqInsertUser{ - ID: req.ID, - Name: req.Name, - Age: req.Age, - Address: req.Address, - Gender: req.Gender, - Religion: req.Religion, - }) - if err != nil { - log.Println(err) - return err - } - return nil -} - -func (s *DatabaseService) GetAllDataUser() ([]*user.User, error) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - dataUser, err := s.DB.Collection("user").Find(ctx, bson.D{}) - if err != nil { - log.Println(err) - } - var users []*user.User - err = dataUser.All(ctx, &users) - if err != nil { - log.Println(err) - return nil, err - } - return users, nil -} - -func (s *DatabaseService) GetUserById(id string) (*user.User, error) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - dataUser := s.DB.Collection("user").FindOne(ctx, bson.D{{Key: "_id", Value: id}}) - var user *user.User - err := dataUser.Decode(&user) - if err != nil { - log.Println(err) - return nil, err - } - return user, nil -} - -func (s *DatabaseService) UpdateUser(reqUpdate *user.ReqUpdateUser) error { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - log.Println(reqUpdate.ID) - filter := bson.M{"_id": reqUpdate.ID} - update := bson.M{"$set": bson.M{ - "name": reqUpdate.Name, - "age": reqUpdate.Age, - "address": reqUpdate.Address, - "gender": reqUpdate.Gender, - "religion": reqUpdate.Religion, - }} - updatedData, err := s.DB.Collection("user").UpdateOne(ctx, filter, update) - if err != nil { - log.Println(err) - return err - } - log.Println(updatedData) - return nil -} - -func (s *DatabaseService) DeleteUserById(id string) error { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - _, err := s.DB.Collection("user").DeleteOne(ctx, bson.D{{Key: "_id", Value: id}}) - if err != nil { - log.Println(err) - return err - } - return nil -} diff --git a/pkg/handlers/login/login.go b/pkg/handlers/login/login.go new file mode 100644 index 0000000..588afb5 --- /dev/null +++ b/pkg/handlers/login/login.go @@ -0,0 +1,57 @@ +package login + +import ( + "github.com/gin-gonic/gin" + "net/http" + "os" + "template_blueprint/internal/database" + "template_blueprint/pkg/database/mongo" +) + +func Getlogin(c *gin.Context) { + local := os.Getenv("MONGODB_DEV_MASTER") + db := database.New(local).GetMongoDB() + if db == nil { + c.JSON(http.StatusInternalServerError, gin.H{"message": "Database connection failed"}) + return + } + + mongoDB := mongo.NewDatabaseServiceMongo(db) + dataEncounter, errSelect := mongoDB.Getlogin() + if errSelect != nil { + c.JSON(http.StatusInternalServerError, gin.H{"message": errSelect.Error()}) + return + } + c.JSON(http.StatusOK, gin.H{ + "data": dataEncounter, + "message": "login Sukses Ter-ambil ", + }) +} + +func GetloginbyID(c *gin.Context) { + local := os.Getenv("MONGODB_DEV_MASTER") + db := database.New(local).GetMongoDB() + if db == nil { + c.JSON(http.StatusInternalServerError, gin.H{"message": "Database connection failed"}) + return + } + + id := c.Param("id") + + if id == "" { + c.JSON(http.StatusBadRequest, gin.H{"message": "Parameter 'id' dibutuhkan"}) + return + } + + mongoDB := mongo.NewDatabaseServiceMongo(db) + dataID, err := mongoDB.GetByid(id) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"message": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{ + "data": dataID, + "message": "ID berhasil di cari", + }) +} diff --git a/pkg/handlers/master_data/master_data.go b/pkg/handlers/master_data/master_data.go deleted file mode 100644 index da6b291..0000000 --- a/pkg/handlers/master_data/master_data.go +++ /dev/null @@ -1,33 +0,0 @@ -package master_data - -import ( - "github.com/gin-gonic/gin" - "github.com/google/uuid" - "net/http" - "os" - "template_blueprint/internal/database" - "template_blueprint/pkg/database/mongo" - "template_blueprint/pkg/models/master_data" -) - -func InsertDataMaster(c *gin.Context) { - master := os.Getenv("BLUEPRINT_DB_MASTER") - var ReqInsertData master_data.ReqInsertData - errBind := c.Bind(&ReqInsertData) - if errBind != nil { - c.JSON(400, gin.H{ - "code": 400, - }) - } - db := database.New(master).GetDB() - mongoDB := mongo.NewDatabaseService(db) - ReqInsertData.ID = uuid.New().String() - errInsert := mongoDB.InsertDataMaster(ReqInsertData) - if errInsert != nil { - c.JSON(400, gin.H{ - "message": "Failed Insert User", - }) - return - } - c.JSON(http.StatusOK, gin.H{"message": "Successfully Inserted User"}) -} diff --git a/pkg/handlers/mongo/mongo.go b/pkg/handlers/mongo/mongo.go deleted file mode 100644 index 8c7f565..0000000 --- a/pkg/handlers/mongo/mongo.go +++ /dev/null @@ -1,42 +0,0 @@ -package mongo - -import ( - "context" - "github.com/gin-gonic/gin" - "go.mongodb.org/mongo-driver/bson" - "log" - "net/http" - "os" - "template_blueprint/internal/database" - "template_blueprint/pkg/database/mongo" - "template_blueprint/pkg/models/local" - "time" -) - -func GetDataLog(c *gin.Context) { - locals := os.Getenv("BLUEPRINT_DB_LOCAL") - db := database.New(locals).GetDB() - if db == nil { - c.JSON(http.StatusInternalServerError, gin.H{"message": "Database connection failed"}) - return - } - mongoDB := mongo.NewDatabaseService(db) - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - - cursor, err := mongoDB.DB.Collection("startup_log").Find(ctx, bson.M{}) - if err != nil { - log.Println(err) - c.JSON(http.StatusInternalServerError, gin.H{"message": "Database query failed"}) - return - } - - var dataLog []*local.StartUpLog - errDecode := cursor.All(ctx, &dataLog) - if errDecode != nil { - log.Println(errDecode) - c.JSON(http.StatusInternalServerError, gin.H{"message": "Database query failed"}) - return - } - c.JSON(http.StatusOK, dataLog) -} diff --git a/pkg/handlers/patient/patient.go b/pkg/handlers/patient/patient.go deleted file mode 100644 index 172bede..0000000 --- a/pkg/handlers/patient/patient.go +++ /dev/null @@ -1,54 +0,0 @@ -package patient - -import ( - "github.com/gin-gonic/gin" - "net/http" - "os" - "template_blueprint/internal/database" - "template_blueprint/pkg/database/mongo" - "template_blueprint/pkg/models/patient" - "time" -) - -func InsertPatient(c *gin.Context) { - local := os.Getenv("MONGODB_DEV_LOCAL") - db := database.New(local).GetDB() - if db == nil { - c.JSON(http.StatusInternalServerError, gin.H{"message": "Database connection failed"}) - return - } - mongoDB := mongo.NewDatabaseService(db) - var req *patient.Patient - err := c.Bind(&req) - if err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"message": err.Error()}) - return - } - - dateCreated := time.Now().Format("2006-01-02 15:04:05") - req.ResourceType = "Patient" - req.CreatedAt = dateCreated - - errInsert := mongoDB.InsertPatient(req) - if errInsert != nil { - c.JSON(http.StatusInternalServerError, gin.H{"message": errInsert.Error()}) - return - } - c.JSON(http.StatusOK, gin.H{"message": "Patient successfully inserted"}) -} - -func GetAllPatient(c *gin.Context) { - local := os.Getenv("MONGODB_DEV_LOCAL") - db := database.New(local).GetDB() - if db == nil { - c.JSON(http.StatusInternalServerError, gin.H{"message": "Database connection failed"}) - return - } - mongoDB := mongo.NewDatabaseService(db) - dataPatient, errSelect := mongoDB.GetAllDataPatient() - if errSelect != nil { - c.JSON(http.StatusInternalServerError, gin.H{"message": errSelect.Error()}) - return - } - c.JSON(http.StatusOK, dataPatient) -} diff --git a/pkg/handlers/user/user.go b/pkg/handlers/user/user.go deleted file mode 100644 index 2b332f0..0000000 --- a/pkg/handlers/user/user.go +++ /dev/null @@ -1,168 +0,0 @@ -package user - -import ( - "github.com/gin-gonic/gin" - "github.com/google/uuid" - "log" - "net/http" - "os" - "template_blueprint/internal/database" - "template_blueprint/pkg/database/mongo" - "template_blueprint/pkg/models/user" -) - -// InsertUser godoc -// @Summary Insert a new user -// @Description Adds a new user to the database -// @Tags users -// @Accept json -// @Produce json -// @Param request body user.ReqInsertUser true "User Data" -// @Success 200 {object} map[string]string "Successfully Inserted User" -// @Failure 400 {object} map[string]string "Bad Request" -// @Failure 500 {object} map[string]string "Database connection failed" -// @Router /api/localinsertuser [post] -func InsertUser(c *gin.Context) { - local := os.Getenv("BLUEPRINT_DB_LOCAL") - db := database.New(local).GetDB() - if db == nil { - c.JSON(http.StatusInternalServerError, gin.H{"message": "Database connection failed"}) - return - } - mongoDB := mongo.NewDatabaseService(db) - var reqInsert user.ReqInsertUser - - errBind := c.Bind(&reqInsert) - if errBind != nil { - c.JSON(400, gin.H{ - "message": errBind.Error(), - }) - return - } - id := uuid.New().String() - reqInsert.ID = id - errInsert := mongoDB.InsertUser(reqInsert) - if errInsert != nil { - c.JSON(400, gin.H{ - "message": errInsert.Error(), - }) - return - } - c.JSON(http.StatusOK, gin.H{"message": "Successfully Inserted User"}) -} - -// GetAllUser godoc -// @Summary Get all users -// @Description Retrieves all users from the database -// @Tags users -// @Produce json -// @Success 200 {array} user.User "List of users" -// @Failure 500 {object} map[string]string "Database connection failed" -// @Router /api/local/getalluser [get] -func GetAllUser(c *gin.Context) { - local := os.Getenv("BLUEPRINT_DB_LOCAL") - db := database.New(local).GetDB() - if db == nil { - c.JSON(http.StatusInternalServerError, gin.H{"message": "Database connection failed"}) - return - } - mongoDB := mongo.NewDatabaseService(db) - dataUser, errSelect := mongoDB.GetAllDataUser() - if errSelect != nil { - c.JSON(400, gin.H{ - "message": errSelect.Error(), - }) - return - } - c.JSON(http.StatusOK, dataUser) -} - -// GetUserByID godoc -// @Summary Get user by ID -// @Description Retrieves a user by their ID -// @Tags users -// @Produce json -// @Param id path string true "User ID" -// @Success 200 {object} user.User "User data" -// @Failure 400 {object} map[string]string "Bad Request" -// @Router /api/local/getuser/{id} [get] -func GetUserByID(c *gin.Context) { - local := os.Getenv("BLUEPRINT_DB_LOCAL") - db := database.New(local).GetDB() - if db == nil { - c.JSON(http.StatusInternalServerError, gin.H{"message": "Database connection failed"}) - return - } - id := c.Param("id") - log.Println("ID", id) - mongoDB := mongo.NewDatabaseService(db) - dataUser, errSelect := mongoDB.GetUserById(id) - if errSelect != nil { - c.JSON(400, gin.H{ - "message": errSelect.Error(), - }) - return - } - c.JSON(http.StatusOK, dataUser) -} - -// UpdateUser godoc -// @Summary Update a user -// @Description Updates user information -// @Tags users -// @Accept json -// @Produce json -// @Param request body user.User true "User Data" -// @Success 200 {object} map[string]string "Successfully Updated User" -// @Failure 400 {object} map[string]string "Bad Request" -// @Failure 500 {object} map[string]string "Database connection failed" -// @Router /users [put] -func UpdateUser(c *gin.Context) { - local := os.Getenv("BLUEPRINT_DB_LOCAL") - db := database.New(local).GetDB() - if db == nil { - c.JSON(http.StatusInternalServerError, gin.H{"message": "Database connection failed"}) - return - } - mongoDB := mongo.NewDatabaseService(db) - var reqUpdate *user.ReqUpdateUser - errBind := c.Bind(&reqUpdate) - if errBind != nil { - c.JSON(400, gin.H{ - "message": errBind.Error(), - }) - return - } - log.Println("REQ UPDATE", reqUpdate) - errUpdate := mongoDB.UpdateUser(reqUpdate) - if errUpdate != nil { - c.JSON(400, gin.H{ - "message": errUpdate.Error(), - }) - return - } - c.JSON(http.StatusOK, gin.H{"message": "Successfully Updated User"}) -} - -func DeleteUser(c *gin.Context) { - local := os.Getenv("BLUEPRINT_DB_LOCAL") - db := database.New(local).GetDB() - if db == nil { - c.JSON(http.StatusInternalServerError, gin.H{"message": "Database connection failed"}) - return - } - mongoDB := mongo.NewDatabaseService(db) - var reqDelete *user.ReqDeleteUser - errBind := c.Bind(&reqDelete) - if errBind != nil { - c.JSON(400, gin.H{}) - return - } - log.Println("REQ DELETE", reqDelete) - errDelete := mongoDB.DeleteUserById(reqDelete.ID) - if errDelete != nil { - c.JSON(400, gin.H{"message": "Failed to Delete User"}) - return - } - c.JSON(http.StatusOK, gin.H{"message": "Successfully Deleted User"}) -} diff --git a/pkg/models/encounter/encounter.go b/pkg/models/encounter/encounter.go deleted file mode 100644 index 22e9e0a..0000000 --- a/pkg/models/encounter/encounter.go +++ /dev/null @@ -1 +0,0 @@ -package encounter diff --git a/pkg/models/local/local.go b/pkg/models/local/local.go deleted file mode 100644 index c9be22c..0000000 --- a/pkg/models/local/local.go +++ /dev/null @@ -1,72 +0,0 @@ -package local - -type StartUpLog struct { - ID string `bson:"_id"` - HostName string `bson:"hostname"` - StartTime string `bson:"start_time"` - StartTimeLocal string `bson:"start_time_local"` - CmdLine CmdLine `bson:"cmdline"` - Pid int `bson:"pid"` - BuildInfo BuildInfo `bson:"buildinfo"` -} - -type CmdLine struct { - Net Net `bson:"net"` - ProcessManagement ProcessManagement `bson:"processManagement"` - SystemLog SystemLog `bson:"systemLog"` -} - -type Net struct { - BindIP string `bson:"bindIp"` - Port int `bson:"port"` - Tls TLS `bson:"tls"` -} - -type TLS struct { - Mode string `bson:"mode"` -} - -type ProcessManagement struct { - Fork bool `bson:"fork"` - PidFilePath string `bson:"pidFilePath"` -} - -type SystemLog struct { - Destination string `bson:"destination"` - LogAppend bool `bson:"logAppend"` - Path string `bson:"path"` -} - -type BuildInfo struct { - Version string `bson:"version"` - GitVersion string `bson:"gitVersion"` - Modules []string `bson:"modules"` - Allocator string `bson:"allocator"` - JavaScriptEngine string `bson:"javaScriptEngine"` - SysInfo string `bson:"sysInfo"` - VersionArray []int `bson:"versionArray"` - OpenSSL OpenSSL `bson:"openssl"` - BuildEnvironment BuildEnvironment `bson:"buildEnvironment"` - Bits int `bson:"bits"` - Debug bool `bson:"debug"` - MaxBsonObjectSize int `bson:"maxBsonObjectSize"` - StorageEngines []string `bson:"storageEngines"` -} - -type OpenSSL struct { - Running string `bson:"running"` - Compiled string `bson:"compiled"` -} - -type BuildEnvironment struct { - DistMod string `bson:"distmod"` - Distarch string `bson:"distarch"` - CC string `bson:"cc"` - CCFlags string `bson:"ccflags"` - CXX string `bson:"cxx"` - CXXFlags string `bson:"cxxflags"` - LinkFlags string `bson:"linkflags"` - TargetArch string `bson:"target_arch"` - TargetOS string `bson:"target_os"` - CPPDefines string `bson:"cppdefines"` -} diff --git a/pkg/models/login/login.go b/pkg/models/login/login.go new file mode 100644 index 0000000..2e69793 --- /dev/null +++ b/pkg/models/login/login.go @@ -0,0 +1,23 @@ +package login + +import "go.mongodb.org/mongo-driver/bson/primitive" + +type Menu struct { + ID primitive.ObjectID `bson:"_id" json:"_id"` + Items []MenuItem `bson:"items" json:"items"` +} + +type MenuItem struct { + Header string `bson:"header,omitempty" json:"header,omitempty"` + Title string `bson:"title,omitempty" json:"title,omitempty"` + Icon string `bson:"icon,omitempty" json:"icon,omitempty"` + To string `bson:"to,omitempty" json:"to,omitempty"` + Children []SubItem `bson:"children,omitempty" json:"children,omitempty"` +} + +type SubItem struct { + Title string `bson:"title,omitempty" json:"title,omitempty"` + To string `bson:"to,omitempty" json:"to,omitempty"` + Chip string `bson:"chip,omitempty" json:"chip,omitempty"` + External bool `bson:"external,omitempty" json:"external,omitempty"` +} diff --git a/pkg/models/master_data/master_data.go b/pkg/models/master_data/master_data.go deleted file mode 100644 index e6ba46b..0000000 --- a/pkg/models/master_data/master_data.go +++ /dev/null @@ -1,16 +0,0 @@ -package master_data - -type ReqInsertData struct { - ID string `bson:"_id"` - Table string `bson:"table"` - System string `bson:"system"` - Code string `bson:"code"` - Display string `bson:"display"` -} - -type ReqInsertDataMaster struct { - ID string `bson:"_id"` - System string `bson:"system"` - Code string `bson:"code"` - Display string `bson:"display"` -} diff --git a/pkg/models/patient/patient.go b/pkg/models/patient/patient.go deleted file mode 100644 index fe81d03..0000000 --- a/pkg/models/patient/patient.go +++ /dev/null @@ -1,167 +0,0 @@ -package patient - -type Coding struct { - System string `bson:"system,omitempty"` - Version string `bson:"version,omitempty"` - Code string `bson:"code,omitempty"` - Display string `bson:"display,omitempty"` - UserSelected bool `bson:"userSelected,omitempty"` -} - -type Identifier struct { - Use string `bson:"use,omitempty"` - Type CodeableConcept `bson:"type,omitempty"` - System string `bson:"system,omitempty"` - Value string `bson:"value,omitempty"` - Period Period `bson:"period,omitempty"` - Assigner struct{} `bson:"assigner,omitempty"` -} - -type CodeableConcept struct { - Coding []Coding `bson:"coding,omitempty"` - Text string `bson:"text,omitempty"` -} - -type Period struct { - Start string `bson:"start,omitempty"` - End string `bson:"end,omitempty"` -} - -type ContactPoint struct { - System string `bson:"system,omitempty"` - Value string `bson:"value,omitempty"` - Use string `bson:"use,omitempty"` - Rank int `bson:"rank,omitempty"` - Period Period `bson:"period,omitempty"` -} - -type HumanName struct { - Use string `bson:"use,omitempty"` - Text string `bson:"text,omitempty"` - Family string `bson:"family,omitempty"` - Given []string `bson:"given,omitempty"` - Prefix []string `bson:"prefix,omitempty"` - Suffix []string `bson:"suffix,omitempty"` - Period Period `bson:"period,omitempty"` -} - -type Address struct { - Use string `bson:"use,omitempty"` - Type string `bson:"type,omitempty"` - Text string `bson:"text,omitempty"` - Line []string `bson:"line,omitempty"` - City string `bson:"city,omitempty"` - District string `bson:"district,omitempty"` - State string `bson:"state,omitempty"` - PostalCode string `bson:"postalCode,omitempty"` - Country string `bson:"country,omitempty"` - Period Period `bson:"period,omitempty"` -} - -type Organization struct { - Reference string `bson:"reference,omitempty"` -} - -type Contact struct { - Relationship []CodeableConcept `bson:"relationship,omitempty"` - Name []HumanName `bson:"name,omitempty"` - Telecom []ContactPoint `bson:"telecom,omitempty"` - Address Address `bson:"address,omitempty"` - Organization Organization `bson:"organization,omitempty"` - Gender string `bson:"gender,omitempty"` - Period Period `bson:"period,omitempty"` -} - -type Communication struct { - Language CodeableConcept `bson:"language,omitempty"` - Preferred bool `bson:"preferred,omitempty"` -} - -type ReqInsertCommunication struct { - Language Coding `bson:"language,omitempty"` - Preferred bool `bson:"preferred,omitempty"` -} - -type Link struct { - RelatePerson []RelatePerson `bson:"relatePerson,omitempty"` -} - -type RelatePerson struct { - Identifier []Identifier `bson:"identifier,omitempty"` - Active bool `bson:"active"` - Patient string `bson:"patient"` - Relationship CodeableConcept `bson:"relationship"` - Name []HumanName `bson:"name,omitempty"` - Telecom []ContactPoint `bson:"telecom,omitempty"` - Gender string `bson:"gender,omitempty"` - BirthDate string `bson:"birthDate,omitempty"` - Address []Address `bson:"address,omitempty"` - Photo string `bson:"photo,omitempty"` - Period Period `bson:"period,omitempty"` - Communication []Communication `bson:"communication,omitempty"` - Preferred bool `bson:"preferred"` -} - -type Deceased struct { - DeceasedBoolean bool `bson:"deceasedBoolean,omitempty"` - DeceasedDateTime string `bson:"deceasedDateTime,omitempty"` -} - -type MultipleBirth struct { - MultipleBirthBoolean bool `bson:"multipleBirthBoolean,omitempty"` - MultipleBirthInteger int `bson:"multipleBirthInteger,omitempty"` -} - -type Patient struct { - ResourceType string `bson:"resourceType"` - ID string `bson:"_id"` - Identifier []Identifier `bson:"identifier,omitempty"` - Active bool `bson:"active"` - Name []HumanName `bson:"name,omitempty"` - Telecom []ContactPoint `bson:"telecom,omitempty"` - Gender string `bson:"gender,omitempty"` - BirthPlace string `bson:"birthPlace,omitempty"` - BirthDate string `bson:"birthDate,omitempty"` - Address []Address `bson:"address,omitempty"` - MaritalStatus CodeableConcept `bson:"maritalStatus,omitempty"` - Job CodeableConcept `bson:"job,omitempty"` - Religion CodeableConcept `bson:"religion,omitempty"` - Tribe CodeableConcept `bson:"tribe,omitempty"` - Link Link `bson:"link,omitempty"` - Communication []Communication `bson:"communication,omitempty"` - Disability bool `bson:"disability,omitempty"` - National string `bson:"national,omitempty"` - Deceased Deceased `bson:"deceased,omitempty"` - MultipleBirth MultipleBirth `bson:"multipleBirth,omitempty"` - CreatedAt string `bson:"createdAt"` - UpdatedAt string `bson:"updatedAt"` -} - -type ReqInsertIdentifier struct { - Use string `bson:"use,omitempty"` - Type Coding `bson:"type,omitempty"` - System string `bson:"system,omitempty"` - Value string `bson:"value,omitempty"` - Period Period `bson:"period,omitempty"` -} - -type ReqInsertPatient struct { - Identifier []ReqInsertIdentifier `bson:"identifier,omitempty"` - Active bool `bson:"active"` - Name []HumanName `bson:"name,omitempty"` - Telecom []ContactPoint `bson:"telecom,omitempty"` - Gender string `bson:"gender,omitempty"` - BirthPlace string `bson:"birthPlace,omitempty"` - BirthDate string `bson:"birthDate,omitempty"` - Address []Address `bson:"address,omitempty"` - MaritalStatus []CodeableConcept `bson:"maritalStatus,omitempty"` - Job []CodeableConcept `bson:"job,omitempty"` - Religion []CodeableConcept `bson:"religion,omitempty"` - Tribe []CodeableConcept `bson:"tribe,omitempty"` - Link Link `bson:"link,omitempty"` - Communication []Communication `bson:"communication,omitempty"` - Disability bool `bson:"disability,omitempty"` - National string `bson:"national,omitempty"` - Deceased Deceased `bson:"deceased,omitempty"` - MultipleBirth MultipleBirth `bson:"multipleBirth,omitempty"` -} diff --git a/pkg/models/user/user.go b/pkg/models/user/user.go deleted file mode 100644 index ef26d9a..0000000 --- a/pkg/models/user/user.go +++ /dev/null @@ -1,33 +0,0 @@ -package user - -type User struct { - ID string `bson:"_id"` - Name string `bson:"name"` - Age int `bson:"age"` - Address string `bson:"address"` - Gender string `bson:"gender"` - Religion string `bson:"religion"` -} - -type ReqInsertUser struct { - ID string `bson:"_id"` - Name string `bson:"name"` - Age int `bson:"age"` - Address string `bson:"address"` - Gender string `bson:"gender"` - Religion string `bson:"religion"` -} - -// USING INSERT AND UPDATE -type ReqUpdateUser struct { - ID string `json:"_id"` - Name string `json:"name"` - Age int `json:"age"` - Address string `json:"address"` - Gender string `json:"gender"` - Religion string `json:"religion"` -} - -type ReqDeleteUser struct { - ID string `json:"_id"` -} diff --git a/tailwind.config.js b/tailwind.config.js deleted file mode 100644 index 4ec3451..0000000 --- a/tailwind.config.js +++ /dev/null @@ -1,11 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: [ - "./cmd/web/**/*.html", "./cmd/web/**/*.templ", - ], - theme: { - extend: {}, - }, - plugins: [], -} -