From 14a9536a9dbf6503d8e49cc157ecfb7bb4ba8660 Mon Sep 17 00:00:00 2001 From: Jared Lockhart <119884+jaredlockhart@users.noreply.github.com> Date: Mon, 15 Apr 2024 14:06:14 -0400 Subject: [PATCH] chore(nimbus): move new ui into nimbus_ui_new (#10544) Because * We're starting a new UI for Nimbus using Django Views/Forms/Templates * Let's collect all the templates, static assets, views, tests in one folder so it's easier to collect and find things This commit * Moves all the new UI folders into nimbus_ui_new fixes #10542 --- docker-compose.yml | 6 +-- experimenter/Dockerfile | 18 ++++----- .../changelog/tests/test_views.py | 40 ------------------- experimenter/experimenter/changelog/urls.py | 9 ----- .../AppLayoutSidebarLaunched/index.tsx | 2 +- .../AppLayoutWithSidebar/index.test.tsx | 2 +- .../components/AppLayoutWithSidebar/index.tsx | 2 +- .../tests => nimbus_ui_new}/__init__.py | 0 .../nimbus_ui_new/static/scripts/bundle.js | 1 + .../templates/changelog/overview.html | 0 .../common/experiment_details_sidebar.html | 0 .../templates/common/footer.html | 0 .../templates/common/header.html | 0 .../templates/components/change_card.html | 0 .../components/sidebar_navigation_button.html | 0 .../components/sidebar_redirect_button.html | 0 .../templates/experimenter_base.html | 0 .../templates/layout/with_sidebar.html | 0 .../nimbus_ui_new/tests/__init__.py | 0 .../nimbus_ui_new/tests/test_views.py | 20 ++++++++++ .../nimbus_ui_new/theme/__init__.py | 1 + .../{ => nimbus_ui_new}/theme/apps.py | 2 +- .../theme/static_src/package.json | 0 .../theme/static_src/postcss.config.js | 0 .../theme/static_src/rollup.config.mjs | 0 .../theme/static_src/src/index.js | 0 .../theme/static_src/src/styles.css | 0 .../theme/static_src/tailwind.config.js | 0 .../theme/static_src/yarn.lock | 0 .../experimenter/nimbus_ui_new/urls.py | 11 +++++ .../{changelog => nimbus_ui_new}/views.py | 0 experimenter/experimenter/settings.py | 5 ++- experimenter/experimenter/theme/__init__.py | 1 - experimenter/experimenter/urls.py | 2 +- 34 files changed, 53 insertions(+), 69 deletions(-) delete mode 100644 experimenter/experimenter/changelog/tests/test_views.py delete mode 100644 experimenter/experimenter/changelog/urls.py rename experimenter/experimenter/{changelog/tests => nimbus_ui_new}/__init__.py (100%) create mode 100644 experimenter/experimenter/nimbus_ui_new/static/scripts/bundle.js rename experimenter/experimenter/{ => nimbus_ui_new}/templates/changelog/overview.html (100%) rename experimenter/experimenter/{ => nimbus_ui_new}/templates/common/experiment_details_sidebar.html (100%) rename experimenter/experimenter/{ => nimbus_ui_new}/templates/common/footer.html (100%) rename experimenter/experimenter/{ => nimbus_ui_new}/templates/common/header.html (100%) rename experimenter/experimenter/{ => nimbus_ui_new}/templates/components/change_card.html (100%) rename experimenter/experimenter/{ => nimbus_ui_new}/templates/components/sidebar_navigation_button.html (100%) rename experimenter/experimenter/{ => nimbus_ui_new}/templates/components/sidebar_redirect_button.html (100%) rename experimenter/experimenter/{ => nimbus_ui_new}/templates/experimenter_base.html (100%) rename experimenter/experimenter/{ => nimbus_ui_new}/templates/layout/with_sidebar.html (100%) create mode 100644 experimenter/experimenter/nimbus_ui_new/tests/__init__.py create mode 100644 experimenter/experimenter/nimbus_ui_new/tests/test_views.py create mode 100644 experimenter/experimenter/nimbus_ui_new/theme/__init__.py rename experimenter/experimenter/{ => nimbus_ui_new}/theme/apps.py (58%) rename experimenter/experimenter/{ => nimbus_ui_new}/theme/static_src/package.json (100%) rename experimenter/experimenter/{ => nimbus_ui_new}/theme/static_src/postcss.config.js (100%) rename experimenter/experimenter/{ => nimbus_ui_new}/theme/static_src/rollup.config.mjs (100%) rename experimenter/experimenter/{ => nimbus_ui_new}/theme/static_src/src/index.js (100%) rename experimenter/experimenter/{ => nimbus_ui_new}/theme/static_src/src/styles.css (100%) rename experimenter/experimenter/{ => nimbus_ui_new}/theme/static_src/tailwind.config.js (100%) rename experimenter/experimenter/{ => nimbus_ui_new}/theme/static_src/yarn.lock (100%) create mode 100644 experimenter/experimenter/nimbus_ui_new/urls.py rename experimenter/experimenter/{changelog => nimbus_ui_new}/views.py (100%) delete mode 100644 experimenter/experimenter/theme/__init__.py diff --git a/docker-compose.yml b/docker-compose.yml index 6597ead68..069ee172f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,7 +18,7 @@ services: - media_volume:/experimenter/experimenter/media - /experimenter/experimenter/legacy/legacy-ui/core/.cache/ - /experimenter/experimenter/legacy/legacy-ui/core/node_modules/ - - /experimenter/experimenter/theme/static_src/node_modules/ + - /experimenter/experimenter/nimbus_ui_new/theme/static_src/node_modules/ - /experimenter/experimenter/nimbus-ui/node_modules/ - /experimenter/experimenter/served/ - /experimenter/node_modules/ @@ -31,8 +31,8 @@ services: tty: true volumes: - ./experimenter:/experimenter - - /experimenter/experimenter/theme/static_src/node_modules/ - command: "yarn --cwd /experimenter/experimenter/theme/static_src run dev" + - /experimenter/experimenter/nimbus_ui_new/theme/static_src/node_modules/ + command: "yarn --cwd /experimenter/experimenter/nimbus_ui_new/theme/static_src run dev" yarn-nimbus-ui: image: experimenter:dev diff --git a/experimenter/Dockerfile b/experimenter/Dockerfile index 71a8c3000..072fe7c93 100644 --- a/experimenter/Dockerfile +++ b/experimenter/Dockerfile @@ -68,9 +68,9 @@ COPY --from=file-loader /experimenter/experimenter/nimbus-ui/package.json /exper RUN yarn install --frozen-lockfile # Node packages for htmx ui -COPY --from=file-loader /experimenter/experimenter/theme/static_src/package.json /experimenter/experimenter/theme/static_src/package.json -COPY --from=file-loader /experimenter/experimenter/theme/static_src/yarn.lock /experimenter/experimenter/theme/static_src/yarn.lock -RUN yarn install --frozen-lockfile --cwd /experimenter/experimenter/theme/static_src +COPY --from=file-loader /experimenter/experimenter/nimbus_ui_new/theme/static_src/package.json /experimenter/experimenter/nimbus_ui_new/theme/static_src/package.json +COPY --from=file-loader /experimenter/experimenter/nimbus_ui_new/theme/static_src/yarn.lock /experimenter/experimenter/nimbus_ui_new/theme/static_src/yarn.lock +RUN yarn install --frozen-lockfile --cwd /experimenter/experimenter/nimbus_ui_new/theme/static_src # Dev image @@ -88,7 +88,7 @@ COPY --from=python-builder /usr/local/lib/python3.11/site-packages/ /usr/local/l # Node packages COPY --from=node-builder /experimenter/experimenter/legacy/legacy-ui/core/node_modules/ /experimenter/experimenter/legacy/legacy-ui/core/node_modules/ -COPY --from=node-builder /experimenter/experimenter/theme/static_src/node_modules/ /experimenter/experimenter/theme/static_src/node_modules/ +COPY --from=node-builder /experimenter/experimenter/nimbus_ui_new/theme/static_src/node_modules/ /experimenter/experimenter/nimbus_ui_new/theme/static_src/node_modules/ COPY --from=node-builder /experimenter/experimenter/nimbus-ui/node_modules/ /experimenter/experimenter/nimbus-ui/node_modules/ COPY --from=node-builder /experimenter/node_modules/ /experimenter/node_modules/ @@ -122,9 +122,9 @@ COPY --from=file-loader /experimenter/experimenter/nimbus-ui/ /experimenter/expe RUN yarn workspace @experimenter/nimbus-ui build # Build static assets -COPY --from=file-loader /experimenter/experimenter/theme/ /experimenter/experimenter/theme/ -COPY --from=file-loader /experimenter/experimenter/templates/ /experimenter/experimenter/templates/ -RUN yarn --cwd /experimenter/experimenter/theme/static_src build +COPY --from=file-loader /experimenter/experimenter/nimbus_ui_new/theme/ /experimenter/experimenter/nimbus_ui_new/theme/ +COPY --from=file-loader /experimenter/experimenter/nimbus_ui_new/templates/ /experimenter/experimenter/nimbus_ui_new/templates/ +RUN yarn --cwd /experimenter/experimenter/nimbus_ui_new/theme/static_src build # Deploy image @@ -154,6 +154,6 @@ COPY --from=file-loader /experimenter/experimenter/ /experimenter/experimenter/ COPY --from=file-loader /experimenter/manifesttool/ /experimenter/manifesttool/ COPY --from=ui /experimenter/experimenter/legacy/legacy-ui/assets/ /experimenter/experimenter/legacy/legacy-ui/assets/ COPY --from=ui /experimenter/experimenter/nimbus-ui/build/ /experimenter/experimenter/nimbus-ui/build/ -COPY --from=ui /experimenter/experimenter/theme/static/ /experimenter/experimenter/theme/static/ -COPY --from=ui /experimenter/experimenter/static/scripts/ /experimenter/experimenter/static/scripts/ +COPY --from=ui /experimenter/experimenter/nimbus_ui_new/theme/static/ /experimenter/experimenter/nimbus_ui_new/theme/static/ +COPY --from=ui /experimenter/experimenter/nimbus_ui_new/static/scripts/ /experimenter/experimenter/nimbus_ui_new/static/scripts/ ENV PYTHONPATH=$PYTHONPATH:/application-services/ diff --git a/experimenter/experimenter/changelog/tests/test_views.py b/experimenter/experimenter/changelog/tests/test_views.py deleted file mode 100644 index 0579f3568..000000000 --- a/experimenter/experimenter/changelog/tests/test_views.py +++ /dev/null @@ -1,40 +0,0 @@ -from django.test import RequestFactory, TestCase -from django.urls import reverse - -from experimenter.changelog.views import NimbusChangeLogsView -from experimenter.experiments.tests.factories import ( - NimbusChangeLogFactory, - NimbusExperimentFactory, -) -from experimenter.openidc.tests.factories import UserFactory - - -class NimbusChangeLogsViewTest(TestCase): - def setUp(self): - self.factory = RequestFactory() - self.user = UserFactory.create() - self.experiment = NimbusExperimentFactory.create(slug="test-experiment") - self.changelog1 = NimbusChangeLogFactory.create( - experiment=self.experiment, message="Change log 1" - ) - self.changelog2 = NimbusChangeLogFactory.create( - experiment=self.experiment, message="Change log 2" - ) - self.view = NimbusChangeLogsView.as_view() - - def test_render_to_response(self): - request = self.factory.get( - reverse("changelogs-by-slug", kwargs={"slug": self.experiment.slug}) - ) - request.user = self.user - response = self.view(request, slug=self.experiment.slug) - self.assertEqual(response.status_code, 200) - - def test_get_context_data(self): - request = self.factory.get( - reverse("changelogs-by-slug", kwargs={"slug": self.experiment.slug}) - ) - request.user = self.user - response = self.view(request, slug=self.experiment.slug) - context = response.context_data - self.assertEqual(context["experiment"], self.experiment) diff --git a/experimenter/experimenter/changelog/urls.py b/experimenter/experimenter/changelog/urls.py deleted file mode 100644 index b96d983dd..000000000 --- a/experimenter/experimenter/changelog/urls.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.urls import re_path - -from experimenter.changelog.views import NimbusChangeLogsView - -urlpatterns = [ - re_path( - r"^(?P[\w-]+)/$", NimbusChangeLogsView.as_view(), name="changelogs-by-slug" - ), -] diff --git a/experimenter/experimenter/nimbus-ui/src/components/AppLayoutSidebarLaunched/index.tsx b/experimenter/experimenter/nimbus-ui/src/components/AppLayoutSidebarLaunched/index.tsx index 2d4fd25fe..b75973a53 100644 --- a/experimenter/experimenter/nimbus-ui/src/components/AppLayoutSidebarLaunched/index.tsx +++ b/experimenter/experimenter/nimbus-ui/src/components/AppLayoutSidebarLaunched/index.tsx @@ -197,7 +197,7 @@ export const AppLayoutSidebarLaunched = ({ /> { ); expect( screen.getByTestId("history-page-my-special-slug"), - ).toHaveAttribute("href", `/history/my-special-slug`); + ).toHaveAttribute("href", `/nimbus_new/my-special-slug/history/`); }); it("renders information about missing experiment details", async () => { diff --git a/experimenter/experimenter/nimbus-ui/src/components/AppLayoutWithSidebar/index.tsx b/experimenter/experimenter/nimbus-ui/src/components/AppLayoutWithSidebar/index.tsx index f8570ee05..c47d35110 100644 --- a/experimenter/experimenter/nimbus-ui/src/components/AppLayoutWithSidebar/index.tsx +++ b/experimenter/experimenter/nimbus-ui/src/components/AppLayoutWithSidebar/index.tsx @@ -100,7 +100,7 @@ export const AppLayoutWithSidebar = ({ /> s&&a.splice(t,1)}function u(){i=!1,o=!0;for(let e=0;e{(void 0===t||t.includes(n))&&(r.forEach((e=>e())),delete e._x_attributeCleanups[n])}))}var m=new MutationObserver(S),v=!1;function y(){m.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),v=!0}function b(){(w=w.concat(m.takeRecords())).length&&!E&&(E=!0,queueMicrotask((()=>{S(w),w.length=0,E=!1}))),m.disconnect(),v=!1}var w=[],E=!1;function A(e){if(!v)return e();b();let t=e();return y(),t}var k=!1,O=[];function S(e){if(k)return void(O=O.concat(e));let t=[],n=[],r=new Map,i=new Map;for(let o=0;o1===e.nodeType&&t.push(e))),e[o].removedNodes.forEach((e=>1===e.nodeType&&n.push(e)))),"attributes"===e[o].type)){let t=e[o].target,n=e[o].attributeName,a=e[o].oldValue,s=()=>{r.has(t)||r.set(t,[]),r.get(t).push({name:n,value:t.getAttribute(n)})},l=()=>{i.has(t)||i.set(t,[]),i.get(t).push(n)};t.hasAttribute(n)&&null===a?s():t.hasAttribute(n)?(l(),s()):l()}i.forEach(((e,t)=>{g(t,e)})),r.forEach(((e,t)=>{_.forEach((n=>n(t,e)))}));for(let e of n)if(!t.includes(e)&&(p.forEach((t=>t(e))),e._x_cleanups))for(;e._x_cleanups.length;)e._x_cleanups.pop()();t.forEach((e=>{e._x_ignoreSelf=!0,e._x_ignore=!0}));for(let e of t)n.includes(e)||e.isConnected&&(delete e._x_ignoreSelf,delete e._x_ignore,h.forEach((t=>t(e))),e._x_ignore=!0,e._x_ignoreSelf=!0);t.forEach((e=>{delete e._x_ignoreSelf,delete e._x_ignore})),t=null,n=null,r=null,i=null}function C(e){return N(j(e))}function $(e,t,n){return e._x_dataStack=[t,...j(n||e)],()=>{e._x_dataStack=e._x_dataStack.filter((e=>e!==t))}}function j(e){return e._x_dataStack?e._x_dataStack:"function"==typeof ShadowRoot&&e instanceof ShadowRoot?j(e.host):e.parentNode?j(e.parentNode):[]}function N(e){let t=new Proxy({},{ownKeys:()=>Array.from(new Set(e.flatMap((e=>Object.keys(e))))),has:(t,n)=>e.some((e=>e.hasOwnProperty(n))),get:(n,r)=>(e.find((e=>{if(e.hasOwnProperty(r)){let n=Object.getOwnPropertyDescriptor(e,r);if(n.get&&n.get._x_alreadyBound||n.set&&n.set._x_alreadyBound)return!0;if((n.get||n.set)&&n.enumerable){let i=n.get,o=n.set,a=n;i=i&&i.bind(t),o=o&&o.bind(t),i&&(i._x_alreadyBound=!0),o&&(o._x_alreadyBound=!0),Object.defineProperty(e,r,{...a,get:i,set:o})}return!0}return!1}))||{})[r],set:(t,n,r)=>{let i=e.find((e=>e.hasOwnProperty(n)));return i?i[n]=r:e[e.length-1][n]=r,!0}});return t}function L(e){let t=(n,r="")=>{Object.entries(Object.getOwnPropertyDescriptors(n)).forEach((([i,{value:o,enumerable:a}])=>{if(!1===a||void 0===o)return;let s=""===r?i:`${r}.${i}`;var l;"object"==typeof o&&null!==o&&o._x_interceptor?n[i]=o.initialize(e,s,i):"object"!=typeof(l=o)||Array.isArray(l)||null===l||o===n||o instanceof Element||t(o,s)}))};return t(e)}function M(e,t=(()=>{})){let n={initialValue:void 0,_x_interceptor:!0,initialize(t,n,r){return e(this.initialValue,(()=>function(e,t){return t.split(".").reduce(((e,t)=>e[t]),e)}(t,n)),(e=>P(t,n,e)),n,r)}};return t(n),e=>{if("object"==typeof e&&null!==e&&e._x_interceptor){let t=n.initialize.bind(n);n.initialize=(r,i,o)=>{let a=e.initialize(r,i,o);return n.initialValue=a,t(r,i,o)}}else n.initialValue=e;return n}}function P(e,t,n){if("string"==typeof t&&(t=t.split(".")),1!==t.length){if(0===t.length)throw error;return e[t[0]]||(e[t[0]]={}),P(e[t[0]],t.slice(1),n)}e[t[0]]=n}var T={};function R(e,t){T[e]=t}function B(e,t){return Object.entries(T).forEach((([n,r])=>{let i=null;Object.defineProperty(e,`$${n}`,{get:()=>r(t,function(){if(i)return i;{let[e,n]=re(t);return i={interceptor:M,...e},x(t,n),i}}()),enumerable:!1})})),e}function I(e,t,n,...r){try{return n(...r)}catch(n){z(n,e,t)}}function z(e,t,n=void 0){Object.assign(e,{el:t,expression:n}),console.warn(`Alpine Expression Error: ${e.message}\n\n${n?'Expression: "'+n+'"\n\n':""}`,t),setTimeout((()=>{throw e}),0)}var D=!0;function q(e){let t=D;D=!1;let n=e();return D=t,n}function F(e,t,n={}){let r;return W(e,t)((e=>r=e),n),r}function W(...e){return V(...e)}var V=K;function K(e,t){let n={};B(n,e);let r=[n,...j(e)],i="function"==typeof t?function(e,t){return(n=(()=>{}),{scope:r={},params:i=[]}={})=>{H(n,t.apply(N([r,...e]),i))}}(r,t):function(e,t,n){let r=function(e,t){if(U[e])return U[e];let n=Object.getPrototypeOf((async function(){})).constructor,r=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(async()=>{ ${e} })()`:e;const i=()=>{try{return new n(["__self","scope"],`with (scope) { __self.result = ${r} }; __self.finished = true; return __self.result;`)}catch(n){return z(n,t,e),Promise.resolve()}};let o=i();return U[e]=o,o}(t,n);return(i=(()=>{}),{scope:o={},params:a=[]}={})=>{r.result=void 0,r.finished=!1;let s=N([o,...e]);if("function"==typeof r){let e=r(r,s).catch((e=>z(e,n,t)));r.finished?(H(i,r.result,s,a,n),r.result=void 0):e.then((e=>{H(i,e,s,a,n)})).catch((e=>z(e,n,t))).finally((()=>r.result=void 0))}}}(r,t,e);return I.bind(null,e,t,i)}var U={};function H(e,t,n,r,i){if(D&&"function"==typeof t){let o=t.apply(n,r);o instanceof Promise?o.then((t=>H(e,t,n,r))).catch((e=>z(e,i,t))):e(o)}else"object"==typeof t&&t instanceof Promise?t.then((t=>e(t))):e(t)}var J="x-";function X(e=""){return J+e}var Z={};function Y(e,t){return Z[e]=t,{before(t){if(!Z[t])return void console.warn("Cannot find directive `${directive}`. `${name}` will use the default order of execution");const n=fe.indexOf(t);fe.splice(n>=0?n:fe.indexOf("DEFAULT"),0,e)}}}function G(e,t,n){if(t=Array.from(t),e._x_virtualDirectives){let n=Object.entries(e._x_virtualDirectives).map((([e,t])=>({name:e,value:t}))),r=Q(n);n=n.map((e=>r.find((t=>t.name===e.name))?{name:`x-bind:${e.name}`,value:`"${e.value}"`}:e)),t=t.concat(n)}let r={},i=t.map(oe(((e,t)=>r[e]=t))).filter(le).map(function(e,t){return({name:n,value:r})=>{let i=n.match(ce()),o=n.match(/:([a-zA-Z0-9\-:]+)/),a=n.match(/\.[^.\]]+(?=[^\]]*$)/g)||[],s=t||e[n]||n;return{type:i?i[1]:null,value:o?o[1]:null,modifiers:a.map((e=>e.replace(".",""))),expression:r,original:s}}}(r,n)).sort(de);return i.map((t=>function(e,t){let n=()=>{},r=Z[t.type]||n,[i,o]=re(e);!function(e,t,n){e._x_attributeCleanups||(e._x_attributeCleanups={}),e._x_attributeCleanups[t]||(e._x_attributeCleanups[t]=[]),e._x_attributeCleanups[t].push(n)}(e,t.original,o);let a=()=>{e._x_ignore||e._x_ignoreSelf||(r.inline&&r.inline(e,t,i),r=r.bind(r,e,t,i),ee?te.get(ne).push(r):r())};return a.runCleanups=o,a}(e,t)))}function Q(e){return Array.from(e).map(oe()).filter((e=>!le(e)))}var ee=!1,te=new Map,ne=Symbol();function re(e){let r=[],[i,o]=function(e){let r=()=>{};return[i=>{let o=t(i);return e._x_effects||(e._x_effects=new Set,e._x_runEffects=()=>{e._x_effects.forEach((e=>e()))}),e._x_effects.add(o),r=()=>{void 0!==o&&(e._x_effects.delete(o),n(o))},o},()=>{r()}]}(e);r.push(o);return[{Alpine:et,effect:i,cleanup:e=>r.push(e),evaluateLater:W.bind(W,e),evaluate:F.bind(F,e)},()=>r.forEach((e=>e()))]}var ie=(e,t)=>({name:n,value:r})=>(n.startsWith(e)&&(n=n.replace(e,t)),{name:n,value:r});function oe(e=(()=>{})){return({name:t,value:n})=>{let{name:r,value:i}=ae.reduce(((e,t)=>t(e)),{name:t,value:n});return r!==t&&e(r,t),{name:r,value:i}}}var ae=[];function se(e){ae.push(e)}function le({name:e}){return ce().test(e)}var ce=()=>new RegExp(`^${J}([^:^.]+)\\b`);var ue="DEFAULT",fe=["ignore","ref","data","id","bind","init","for","model","modelable","transition","show","if",ue,"teleport"];function de(e,t){let n=-1===fe.indexOf(e.type)?ue:e.type,r=-1===fe.indexOf(t.type)?ue:t.type;return fe.indexOf(n)-fe.indexOf(r)}function _e(e,t,n={}){e.dispatchEvent(new CustomEvent(t,{detail:n,bubbles:!0,composed:!0,cancelable:!0}))}function pe(e,t){if("function"==typeof ShadowRoot&&e instanceof ShadowRoot)return void Array.from(e.children).forEach((e=>pe(e,t)));let n=!1;if(t(e,(()=>n=!0)),n)return;let r=e.firstElementChild;for(;r;)pe(r,t),r=r.nextElementSibling}function he(e,...t){console.warn(`Alpine Warning: ${e}`,...t)}var xe=!1;var ge=[],me=[];function ve(){return ge.map((e=>e()))}function ye(){return ge.concat(me).map((e=>e()))}function be(e){ge.push(e)}function we(e){me.push(e)}function Ee(e,t=!1){return Ae(e,(e=>{if((t?ye():ve()).some((t=>e.matches(t))))return!0}))}function Ae(e,t){if(e){if(t(e))return e;if(e._x_teleportBack&&(e=e._x_teleportBack),e.parentElement)return Ae(e.parentElement,t)}}var ke=[];function Oe(e,t=pe,n=(()=>{})){!function(e){ee=!0;let t=Symbol();ne=t,te.set(t,[]);let n=()=>{for(;te.get(t).length;)te.get(t).shift()();te.delete(t)};e(n),ee=!1,n()}((()=>{t(e,((e,t)=>{n(e,t),ke.forEach((n=>n(e,t))),G(e,e.attributes).forEach((e=>e())),e._x_ignore&&t()}))}))}function Se(e){pe(e,(e=>g(e)))}var Ce=[],$e=!1;function je(e=(()=>{})){return queueMicrotask((()=>{$e||setTimeout((()=>{Ne()}))})),new Promise((t=>{Ce.push((()=>{e(),t()}))}))}function Ne(){for($e=!1;Ce.length;)Ce.shift()()}function Le(e,t){return Array.isArray(t)?Me(e,t.join(" ")):"object"==typeof t&&null!==t?function(e,t){let n=e=>e.split(" ").filter(Boolean),r=Object.entries(t).flatMap((([e,t])=>!!t&&n(e))).filter(Boolean),i=Object.entries(t).flatMap((([e,t])=>!t&&n(e))).filter(Boolean),o=[],a=[];return i.forEach((t=>{e.classList.contains(t)&&(e.classList.remove(t),a.push(t))})),r.forEach((t=>{e.classList.contains(t)||(e.classList.add(t),o.push(t))})),()=>{a.forEach((t=>e.classList.add(t))),o.forEach((t=>e.classList.remove(t)))}}(e,t):"function"==typeof t?Le(e,t()):Me(e,t)}function Me(e,t){return t=!0===t?t="":t||"",n=t.split(" ").filter((t=>!e.classList.contains(t))).filter(Boolean),e.classList.add(...n),()=>{e.classList.remove(...n)};var n}function Pe(e,t){return"object"==typeof t&&null!==t?function(e,t){let n={};return Object.entries(t).forEach((([t,r])=>{n[t]=e.style[t],t.startsWith("--")||(t=t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()),e.style.setProperty(t,r)})),setTimeout((()=>{0===e.style.length&&e.removeAttribute("style")})),()=>{Pe(e,n)}}(e,t):function(e,t){let n=e.getAttribute("style",t);return e.setAttribute("style",t),()=>{e.setAttribute("style",n||"")}}(e,t)}function Te(e,t=(()=>{})){let n=!1;return function(){n?t.apply(this,arguments):(n=!0,e.apply(this,arguments))}}function Re(e,t,n={}){e._x_transition||(e._x_transition={enter:{during:n,start:n,end:n},leave:{during:n,start:n,end:n},in(n=(()=>{}),r=(()=>{})){Ie(e,t,{during:this.enter.during,start:this.enter.start,end:this.enter.end},n,r)},out(n=(()=>{}),r=(()=>{})){Ie(e,t,{during:this.leave.during,start:this.leave.start,end:this.leave.end},n,r)}})}function Be(e){let t=e.parentNode;if(t)return t._x_hidePromise?t:Be(t)}function Ie(e,t,{during:n,start:r,end:i}={},o=(()=>{}),a=(()=>{})){if(e._x_transitioning&&e._x_transitioning.cancel(),0===Object.keys(n).length&&0===Object.keys(r).length&&0===Object.keys(i).length)return o(),void a();let s,l,c;!function(e,t){let n,r,i,o=Te((()=>{A((()=>{n=!0,r||t.before(),i||(t.end(),Ne()),t.after(),e.isConnected&&t.cleanup(),delete e._x_transitioning}))}));e._x_transitioning={beforeCancels:[],beforeCancel(e){this.beforeCancels.push(e)},cancel:Te((function(){for(;this.beforeCancels.length;)this.beforeCancels.shift()();o()})),finish:o},A((()=>{t.start(),t.during()})),$e=!0,requestAnimationFrame((()=>{if(n)return;let o=1e3*Number(getComputedStyle(e).transitionDuration.replace(/,.*/,"").replace("s","")),a=1e3*Number(getComputedStyle(e).transitionDelay.replace(/,.*/,"").replace("s",""));0===o&&(o=1e3*Number(getComputedStyle(e).animationDuration.replace("s",""))),A((()=>{t.before()})),r=!0,requestAnimationFrame((()=>{n||(A((()=>{t.end()})),Ne(),setTimeout(e._x_transitioning.finish,o+a),i=!0)}))}))}(e,{start(){s=t(e,r)},during(){l=t(e,n)},before:o,end(){s(),c=t(e,i)},after:a,cleanup(){l(),c()}})}function ze(e,t,n){if(-1===e.indexOf(t))return n;const r=e[e.indexOf(t)+1];if(!r)return n;if("scale"===t&&isNaN(r))return n;if("duration"===t||"delay"===t){let e=r.match(/([0-9]+)ms/);if(e)return e[1]}return"origin"===t&&["top","right","left","center","bottom"].includes(e[e.indexOf(t)+2])?[r,e[e.indexOf(t)+2]].join(" "):r}Y("transition",((e,{value:t,modifiers:n,expression:r},{evaluate:i})=>{"function"==typeof r&&(r=i(r)),!1!==r&&(r&&"boolean"!=typeof r?function(e,t,n){Re(e,Le,"");let r={enter:t=>{e._x_transition.enter.during=t},"enter-start":t=>{e._x_transition.enter.start=t},"enter-end":t=>{e._x_transition.enter.end=t},leave:t=>{e._x_transition.leave.during=t},"leave-start":t=>{e._x_transition.leave.start=t},"leave-end":t=>{e._x_transition.leave.end=t}};r[n](t)}(e,r,t):function(e,t,n){Re(e,Pe);let r=!t.includes("in")&&!t.includes("out")&&!n,i=r||t.includes("in")||["enter"].includes(n),o=r||t.includes("out")||["leave"].includes(n);t.includes("in")&&!r&&(t=t.filter(((e,n)=>nn>t.indexOf("out"))));let a=!t.includes("opacity")&&!t.includes("scale"),s=a||t.includes("opacity"),l=a||t.includes("scale"),c=s?0:1,u=l?ze(t,"scale",95)/100:1,f=ze(t,"delay",0)/1e3,d=ze(t,"origin","center"),_="opacity, transform",p=ze(t,"duration",150)/1e3,h=ze(t,"duration",75)/1e3,x="cubic-bezier(0.4, 0.0, 0.2, 1)";i&&(e._x_transition.enter.during={transformOrigin:d,transitionDelay:`${f}s`,transitionProperty:_,transitionDuration:`${p}s`,transitionTimingFunction:x},e._x_transition.enter.start={opacity:c,transform:`scale(${u})`},e._x_transition.enter.end={opacity:1,transform:"scale(1)"});o&&(e._x_transition.leave.during={transformOrigin:d,transitionDelay:`${f}s`,transitionProperty:_,transitionDuration:`${h}s`,transitionTimingFunction:x},e._x_transition.leave.start={opacity:1,transform:"scale(1)"},e._x_transition.leave.end={opacity:c,transform:`scale(${u})`})}(e,n,t))})),window.Element.prototype._x_toggleAndCascadeWithTransitions=function(e,t,n,r){const i="visible"===document.visibilityState?requestAnimationFrame:setTimeout;let o=()=>i(n);t?e._x_transition&&(e._x_transition.enter||e._x_transition.leave)?e._x_transition.enter&&(Object.entries(e._x_transition.enter.during).length||Object.entries(e._x_transition.enter.start).length||Object.entries(e._x_transition.enter.end).length)?e._x_transition.in(n):o():e._x_transition?e._x_transition.in(n):o():(e._x_hidePromise=e._x_transition?new Promise(((t,n)=>{e._x_transition.out((()=>{}),(()=>t(r))),e._x_transitioning.beforeCancel((()=>n({isFromCancelledTransition:!0})))})):Promise.resolve(r),queueMicrotask((()=>{let t=Be(e);t?(t._x_hideChildren||(t._x_hideChildren=[]),t._x_hideChildren.push(e)):i((()=>{let t=e=>{let n=Promise.all([e._x_hidePromise,...(e._x_hideChildren||[]).map(t)]).then((([e])=>e()));return delete e._x_hidePromise,delete e._x_hideChildren,n};t(e).catch((e=>{if(!e.isFromCancelledTransition)throw e}))}))})))};var De=!1;function qe(e,t=(()=>{})){return(...n)=>De?t(...n):e(...n)}function Fe(t,n,r,i=[]){switch(t._x_bindings||(t._x_bindings=e({})),t._x_bindings[n]=r,n=i.includes("camel")?n.toLowerCase().replace(/-(\w)/g,((e,t)=>t.toUpperCase())):n){case"value":!function(e,t){if("radio"===e.type)void 0===e.attributes.value&&(e.value=t),window.fromModel&&(e.checked=Ve(e.value,t));else if("checkbox"===e.type)Number.isInteger(t)?e.value=t:Number.isInteger(t)||Array.isArray(t)||"boolean"==typeof t||[null,void 0].includes(t)?Array.isArray(t)?e.checked=t.some((t=>Ve(t,e.value))):e.checked=!!t:e.value=String(t);else if("SELECT"===e.tagName)!function(e,t){const n=[].concat(t).map((e=>e+""));Array.from(e.options).forEach((e=>{e.selected=n.includes(e.value)}))}(e,t);else{if(e.value===t)return;e.value=t}}(t,r);break;case"style":!function(e,t){e._x_undoAddedStyles&&e._x_undoAddedStyles();e._x_undoAddedStyles=Pe(e,t)}(t,r);break;case"class":!function(e,t){e._x_undoAddedClasses&&e._x_undoAddedClasses();e._x_undoAddedClasses=Le(e,t)}(t,r);break;case"selected":case"checked":!function(e,t,n){We(e,t,n),function(e,t,n){e[t]!==n&&(e[t]=n)}(e,t,n)}(t,n,r);break;default:We(t,n,r)}}function We(e,t,n){[null,void 0,!1].includes(n)&&function(e){return!["aria-pressed","aria-checked","aria-expanded","aria-selected"].includes(e)}(t)?e.removeAttribute(t):(Ke(t)&&(n=t),function(e,t,n){e.getAttribute(t)!=n&&e.setAttribute(t,n)}(e,t,n))}function Ve(e,t){return e==t}function Ke(e){return["disabled","checked","required","readonly","hidden","open","selected","autofocus","itemscope","multiple","novalidate","allowfullscreen","allowpaymentrequest","formnovalidate","autoplay","controls","loop","muted","playsinline","default","ismap","reversed","async","defer","nomodule"].includes(e)}function Ue(e,t,n){let r=e.getAttribute(t);return null===r?"function"==typeof n?n():n:""===r||(Ke(t)?!![t,"true"].includes(r):r)}function He(e,t){var n;return function(){var r=this,i=arguments;clearTimeout(n),n=setTimeout((function(){n=null,e.apply(r,i)}),t)}}function Je(e,t){let n;return function(){let r=this,i=arguments;n||(e.apply(r,i),n=!0,setTimeout((()=>n=!1),t))}}var Xe={},Ze=!1;var Ye={};function Ge(e,t,n){let r=[];for(;r.length;)r.pop()();let i=Object.entries(t).map((([e,t])=>({name:e,value:t}))),o=Q(i);i=i.map((e=>o.find((t=>t.name===e.name))?{name:`x-bind:${e.name}`,value:`"${e.value}"`}:e)),G(e,i,n).map((e=>{r.push(e.runCleanups),e()}))}var Qe={};var et={get reactive(){return e},get release(){return n},get effect(){return t},get raw(){return r},version:"3.12.3",flushAndStopDeferringMutations:function(){k=!1,S(O),O=[]},dontAutoEvaluateFunctions:q,disableEffectScheduling:function(e){f=!1,e(),f=!0},startObservingMutations:y,stopObservingMutations:b,setReactivityEngine:function(i){e=i.reactive,n=i.release,t=e=>i.effect(e,{scheduler:e=>{f?l(e):e()}}),r=i.raw},closestDataStack:j,skipDuringClone:qe,onlyDuringClone:function(e){return(...t)=>De&&e(...t)},addRootSelector:be,addInitSelector:we,addScopeToNode:$,deferMutations:function(){k=!0},mapAttributes:se,evaluateLater:W,interceptInit:function(e){ke.push(e)},setEvaluator:function(e){V=e},mergeProxies:N,extractProp:function(e,t,n,r=!0){if(e._x_bindings&&void 0!==e._x_bindings[t])return e._x_bindings[t];if(e._x_inlineBindings&&void 0!==e._x_inlineBindings[t]){let n=e._x_inlineBindings[t];return n.extract=r,q((()=>F(e,n.expression)))}return Ue(e,t,n)},findClosest:Ae,closestRoot:Ee,destroyTree:Se,interceptor:M,transition:Ie,setStyles:Pe,mutateDom:A,directive:Y,throttle:Je,debounce:He,evaluate:F,initTree:Oe,nextTick:je,prefixed:X,prefix:function(e){J=e},plugin:function(e){(Array.isArray(e)?e:[e]).forEach((e=>e(et)))},magic:R,store:function(t,n){if(Ze||(Xe=e(Xe),Ze=!0),void 0===n)return Xe[t];Xe[t]=n,"object"==typeof n&&null!==n&&n.hasOwnProperty("init")&&"function"==typeof n.init&&Xe[t].init(),L(Xe[t])},start:function(){var e;xe&&he("Alpine has already been initialized on this page. Calling Alpine.start() more than once can cause problems."),xe=!0,document.body||he("Unable to initialize. Trying to load Alpine before `` is available. Did you forget to add `defer` in Alpine's `