In the middle of refactoring but need to save this first attempt at a dynamic table. It's terrible, so going to try an alternative and compare.

master
Zed A. Shaw 4 days ago
parent ccd8977d40
commit 0c09308dd4
  1. 1
      static/js/alpine-intersect.js
  2. 5
      static/js/alpine.js
  3. 22
      static/js/jzed.js
  4. 53
      views/admin/table/contents.html
  5. 21
      views/admin/table/index.html
  6. 1
      views/admin/table/new.html
  7. 1
      views/admin/table/view.html
  8. 28
      views/layouts/main.html
  9. 58
      views/shopping/checkout.html
  10. 6
      views/shopping/index.html

@ -1 +0,0 @@
(()=>{function o(e){e.directive("intersect",e.skipDuringClone((t,{value:i,expression:l,modifiers:n},{evaluateLater:r,cleanup:c})=>{let s=r(l),a={rootMargin:x(n),threshold:f(n)},u=new IntersectionObserver(d=>{d.forEach(h=>{h.isIntersecting!==(i==="leave")&&(s(),n.includes("once")&&u.disconnect())})},a);u.observe(t),c(()=>{u.disconnect()})}))}function f(e){if(e.includes("full"))return .99;if(e.includes("half"))return .5;if(!e.includes("threshold"))return 0;let t=e[e.indexOf("threshold")+1];return t==="100"?1:t==="0"?0:Number(`.${t}`)}function p(e){let t=e.match(/^(-?[0-9]+)(px|%)?$/);return t?t[1]+(t[2]||"px"):void 0}function x(e){let t="margin",i="0px 0px 0px 0px",l=e.indexOf(t);if(l===-1)return i;let n=[];for(let r=1;r<5;r++)n.push(p(e[l+r]||""));return n=n.filter(r=>r!==void 0),n.length?n.join(" ").trim():i}document.addEventListener("alpine:init",()=>{window.Alpine.plugin(o)});})();

File diff suppressed because one or more lines are too long

@ -19,7 +19,7 @@ const $sanitize_data = (data) => {
return JSON.parse(sanitized); return JSON.parse(sanitized);
} }
const $render = (template, data) => { const $render = (template, data={}) => {
const sanitized = $sanitize_data(data); const sanitized = $sanitize_data(data);
const args = Object.keys(sanitized); const args = Object.keys(sanitized);
@ -43,7 +43,6 @@ const $render_data = (template_id, target_id, data) => {
return $render(template, {i, item}); return $render(template, {i, item});
}); });
} else if(data instanceof Object) { } else if(data instanceof Object) {
console.log("object rendering", data);
new_data.push($render(template, data)); new_data.push($render(template, data));
} else { } else {
console.error("$render only works with {} or [] data", data); console.error("$render only works with {} or [] data", data);
@ -178,7 +177,11 @@ const $outer_html = (node) => {
} }
const $replace_with = (node, newNodes) => { const $replace_with = (node, newNodes) => {
if(Array.isArray(newNodes)) {
node.replaceChildren(...newNodes); node.replaceChildren(...newNodes);
} else {
node.replaceChildren(newNodes);
}
} }
const $matches = (node, selector) => { const $matches = (node, selector) => {
@ -231,3 +234,18 @@ const $observe = (node_id, cb) => {
const observer = new IntersectionObserver(callback, options); const observer = new IntersectionObserver(callback, options);
observer.observe($id(node_id)); observer.observe($id(node_id));
} }
const $switch = (template_id, data) => {
let tmpl = $id(template_id);
let to_replace = $render(tmpl).children;
for(let child of to_replace) {
let when = JSON.parse($attribute_of(child, 'x-when'));
if(when === data) {
return child;
}
}
return null;
}

@ -1,5 +1,28 @@
<script> <script>
let thePage = new PaginateTable("/api/admin/table/{{ .table }}"); let thePage = new PaginateTable("/api/admin/table/{{ .table }}");
const craftTemplate = (example) => {
const tmpl = $id('table-row');
const tr = tmpl.content.children[0];
for(let header of Object.keys(example)) {
$append(tr,
$html("<td><a style='text-decoration: none' href='/admin/table/{{.table}}/${item.Id}/'>${item['" + header + "']}</a></td>"));
}
return tmpl;
}
$boot(async () => {
const items = await thePage.contents();
const tmpl = craftTemplate(items[0]);
const rows = $id('table-items');
for(let item of items) {
console.log("ITEM", item);
$append(rows, $render(tmpl, {item}));
}
});
</script> </script>
<h1><a href="/admin/table/">&laquo;</a> Admin {{ .table }}</h1> <h1><a href="/admin/table/">&laquo;</a> Admin {{ .table }}</h1>
@ -7,29 +30,15 @@
<block x-data="thePage"> <block x-data="thePage">
<bar> <bar>
<button type="button"><a href="/admin/table/new/{{ .table }}/">New</a></button> <button type="button"><a href="/admin/table/new/{{ .table }}/">New</a></button>
<button type="button" @click="page -= 1">Prev</button> <button type="button">Prev</button>
<button type="button" @click="page += 1">Next</button> <button type="button">Next</button>
<input type="text" x-model.debounce="search_query" name="search" size="40" placeholder="Search" /> <input type="text" name="search" size="40" placeholder="Search" />
</bar> </bar>
<table> <table id="table-items">
<tr class="table-header">
<th>#</th>
<template x-for="header in headers">
<th x-text="header"></th>
</template>
</tr>
<template x-for="item in contents" :key="item.Id">
<tr class="table-row">
<td>
<a x-bind:href="'/admin/table/{{ .table }}/' + item.Id + '/'">
#
</a>
</td>
<template x-for="(value, key) in item">
<td x-text="value"></td>
</template>
</tr>
</template>
</table> </table>
<template id="table-row">
<tr class="table-row"></tr>
</template>
</block> </block>

@ -1,16 +1,27 @@
<!-- HAS_ALPINE -->
<script> <script>
let Data = new PaginateTable("/api/admin/table") let Data = new PaginateTable("/api/admin/table")
$boot(async () => {
const items = await Data.contents();
const list = $id('table-list');
const tmpl = $id('table-row');
for(let i in items) {
$append(list, $render(tmpl, {i, item: items[i]}));
}
});
</script> </script>
<div class="p-4"> <div class="p-4">
<h1>Admin Rows</h1> <h1>Admin Rows</h1>
<block x-data="Data"> <block>
<ul> <ul id="table-list">
<template x-for="item in contents"> <template id='table-row'>
<li> <li>
<a x-bind:href="`/admin/table/${item}/`"> <a href="/admin/table/${item}/">
<span x-text="item"></span> <span>${item}</span>
</a> </a>
</li> </li>
</template> </template>

@ -1,3 +1,4 @@
<!-- HAS_ALPINE -->
<h1><a href="/admin/table/{{ .table }}/">&laquo;</a>Admin {{ .table }}</h1> <h1><a href="/admin/table/{{ .table }}/">&laquo;</a>Admin {{ .table }}</h1>
<block x-data="{item: {}}" <block x-data="{item: {}}"

@ -1,3 +1,4 @@
<!-- HAS_ALPINE -->
<h1><a href="/admin/table/{{ .table }}/">&laquo;</a>Admin {{ .table }}</h1> <h1><a href="/admin/table/{{ .table }}/">&laquo;</a>Admin {{ .table }}</h1>
<block x-data="{item: {}}" <block x-data="{item: {}}"

@ -8,17 +8,22 @@
<meta name="description" content="My Go learning project, which is a Twitch support thing." /> <meta name="description" content="My Go learning project, which is a Twitch support thing." />
<link rel="icon" href="/favicon.ico" type="image/x-icon" /> <link rel="icon" href="/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="/style.css"> <link rel="stylesheet" href="/style.css">
<!-- all alpine plugins come first to register into alpine:init event -->
<script defer src="/js/alpine-intersect.js"></script>
<!-- then alpine runs, triggers init, and tada you get no-build plugins -->
<script defer src="/js/alpine.js"></script>
<script src="/js/code.js"></script> <script src="/js/code.js"></script>
<script src="/js/jzed.js"></script> <script src="/js/jzed.js"></script>
<title>Go Web Dev Starter Kit</title> <title>Go Web Dev Starter Kit</title>
<script>
$boot(async () => {
let auth = await GetJson('/api/authcheck');
let opt = $switch('is-authed-switch', auth.is_authed);
if(opt) {
$replace_with($id('login-logout'), opt);
}
});
</script>
</head> </head>
<body id="top" data-testid="{{.PageId}}"> <body id="top" data-testid="{{.PageId}}">
<header x-data="{auth: false}" <header>
x-init="auth = await GetJson('/api/authcheck')">
<nav> <nav>
<a id="home" href="/"> <a id="home" href="/">
<svg xmlns="http://www.w3.org/2000/svg" <svg xmlns="http://www.w3.org/2000/svg"
@ -36,12 +41,13 @@
<use href="/icons/user-plus.svg#img" /> <use href="/icons/user-plus.svg#img" />
</svg> </svg>
</a> </a>
<template x-if="auth.is_authed">
<a id="logout" href="/api/logout">Logout</a> <div id="login-logout">
</template> <template id='is-authed-switch'>
<template x-if="!auth.is_authed"> <a x-when="true" href="/api/logout">Logout</a>
<a id="login" href="/login/">Login</a> <a x-when="false" href="/login">Login</a>
</template> </template>
</div>
</nav> </nav>
</header> </header>

@ -1,17 +1,63 @@
<script>
let Data = new PaginateTable("/api/shopping/products");
let cartItems = [];
const update = () => {
let total = cartItems.reduce((a, v) => a + v.Price, 0.0);
$render_data('cart-item', 'cart', cartItems);
if(cartItems.length > 0) {
$style_del($id('cart'), 'hidden');
} else {
$style_add($id('cart'), 'hidden');
}
$text($id('cart-total'), `$${total}`);
}
const remove = (item_number) => {
cartItems.splice(item_number, 1);
update();
}
$boot(async () => {
cartItems = await Data.contents();
update();
});
</script>
<style>
#cart-empty.hidden {
display: none;
}
</style>
<h1>Checkout</h1> <h1>Checkout</h1>
<bar class="bg-gray-800"> <block id="cart">
<aside>I'm baby pork belly blackbird spyplane vape, bodega boys farm-to-table taxidermy JOMO chia copper mug intelligentsia distillery.</aside> </block>
<block id='cart-empty' class='hidden'>
<h4>Cart Empty</h4>
<p>Your cart is empty.</p>
</block>
<template id="cart-item">
<bar class="bg-gray-800">
<aside>${item.Title}</aside>
<bar class="justify-between" style="padding:30px"> <bar class="justify-between" style="padding:30px">
<div class="text-2xl">Price: $100.00</div> <div class="text-2xl">Price: ${item.Price}</div>
<a href="/api/shopping/cart/remove/1"><button type="button">X</button></a> <button onclick="remove(${i})" type="button">X</button>
</bar> </bar>
</bar> </bar>
</template>
<table> <table>
<tr><th>Subtotal:</th><td>$100.00</td></tr> <tr><th>Subtotal:</th><td>$100.00</td></tr>
<tr><th>Total:</th><td>$50.00</td></tr> <tr><th>Total:</th><td id='cart-total'></td></tr>
</table> </table>
<bar> <bar>

@ -6,7 +6,7 @@
* - can't accidentally rename the function because it's const * - can't accidentally rename the function because it's const
* - callbacks with function are fucking stupid. * - callbacks with function are fucking stupid.
*/ */
let Data = new ForeverScroll("/api/shopping/products"); let Data = new PaginateTable("/api/shopping/products");
const cartItems = []; const cartItems = [];
@ -37,8 +37,7 @@
} }
$boot(async () => { $boot(async () => {
// kind of not good so revisit how Data works const items = await Data.contents();
const items = await Data.init();
const list = $id('product-list'); const list = $id('product-list');
const tmpl = $id('product-row'); const tmpl = $id('product-row');
@ -46,7 +45,6 @@
$append(list, $render(tmpl, {i, item: items[i]})); $append(list, $render(tmpl, {i, item: items[i]}));
} }
}); });
</script> </script>
<style> <style>

Loading…
Cancel
Save