You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
17 KiB

<main class="bg-white dark:bg-gray-600 grow">
<section class="bg-gray-300 dark:bg-gray-600 p-3 sm:p-5 antialiased">
<div class="mx-auto max-w-screen-2xl px-4 lg:px-12">
<div class="bg-white dark:bg-gray-800 relative shadow-md sm:rounded-lg overflow-hidden">
<div class="flex flex-col md:flex-row md:items-center md:justify-between space-y-3 md:space-y-0 md:space-x-4 p-4">
<div class="flex-1 flex items-center space-x-2">
<h5>
<span class="text-gray-500">All articles:</span>
<span class="dark:text-white"
x-data="{ count: document.getElementById('articles').children.length }"
x-on:htmx:load.window="count = document.getElementById('articles').children.length"
@delete_row.window="count = document.getElementById('articles').children.length"
x-text="count">
</span>
</h5>
</div>
</div>
<div class="flex flex-col md:flex-row items-stretch md:items-center md:space-x-3 space-y-3 md:space-y-0 justify-between mx-4 py-4 border-t dark:border-gray-700">
<div class="w-full md:w-1/2"
x-data="{
search: new URLSearchParams(location.search).get('search')
}"
x-init="$watch('search', (value) => {
const url = new URL(window.location.href);
url.searchParams.set('search', value);
history.replaceState(null, null, '?'+url.searchParams.toString());
})"
>
<div class="flex items-center">
<div class="relative w-full">
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<svg aria-hidden="true" class="w-5 h-5 text-gray-500 dark:text-gray-400" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" />
</svg>
</div>
<input type="text"
id="search"
name="search"
x-model="search"
hx-post="/htmx/admin/search/articles/"
hx-trigger="input changed delay:500ms, search"
hx-target="#articles"
hx-swap="outerHTML"
placeholder="Search articles by title or content"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full pl-10 p-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500">
</div>
</div>
</div>
<div class="w-full md:w-auto flex flex-col md:flex-row space-y-2 md:space-y-0 items-stretch md:items-center justify-end md:space-x-3 flex-shrink-0">
<button type="button"
id="createArticleButton"
data-modal-target="createArticleModal"
data-modal-toggle="createArticleModal"
class="flex items-center justify-center text-white bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 font-medium rounded-lg text-sm px-4 py-2 dark:bg-primary-600 dark:hover:bg-primary-700 focus:outline-none dark:focus:ring-primary-800">
<svg class="h-3.5 w-3.5 mr-1.5 -ml-1" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path clip-rule="evenodd" fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" />
</svg>
Add article
</button>
</div>
</div>
<div class="overflow-x-auto">
<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th scope="col" class="p-4">Title</th>
<th scope="col" class="p-4">Brief content</th>
<th scope="col" class="p-4">Created/Update</th>
<th scope="col" class="p-4"></th>
</tr>
</thead>
{{> article_rows articles=articles }}
</table>
</div>
<nav class="flex flex-col md:flex-row justify-between items-start md:items-center space-y-3 md:space-y-0 p-4" aria-label="Table navigation">
<span class="text-sm font-normal text-gray-500 dark:text-gray-400">
Showing
<span class="font-semibold text-gray-900 dark:text-white"
x-data="{ count: document.getElementById('articles').children.length }"
x-on:htmx:load.window="count = document.getElementById('articles').children.length"
@delete_row.window="count = document.getElementById('articles').children.length"
x-text="count">
</span>
</span>
</nav>
</div>
</div>
</section>
<!-- Create modal -->
<div id="createArticleModal" tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
<div class="relative p-4 w-full max-w-2xl max-h-full">
<!-- Modal content -->
<div class="relative p-4 bg-white rounded-lg shadow dark:bg-gray-800 sm:p-5">
<!-- Modal header -->
<div class="flex justify-between items-center pb-4 mb-4 rounded-t border-b sm:mb-5 dark:border-gray-600">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Add Article</h3>
<button type="button" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white" data-modal-target="createArticleModal" data-modal-toggle="createArticleModal">
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
<span class="sr-only">Close modal</span>
</button>
</div>
<!-- Modal body -->
<form>
<div class="grid gap-4 mb-4 sm:grid-cols-1">
<div>
<label for="title" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Title</label>
<input type="text" name="title" id="title" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" placeholder="Type article title" required="">
</div>
<div><label for="content" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Content</label><textarea id="content" name="content" rows="4" class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" placeholder="Write article here"></textarea></div>
</div>
<button type="submit"
hx-post="/htmx/articles/"
hx-target="#articles"
hx-swap="afterbegin"
data-modal-target="createArticleModal"
data-modal-toggle="createArticleModal"
class="text-white inline-flex items-center bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800">
<svg class="mr-1 -ml-1 w-6 h-6" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M10 5a1 1 0 011 1v3h3a1 1 0 110 2h-3v3a1 1 0 11-2 0v-3H6a1 1 0 110-2h3V6a1 1 0 011-1z" clip-rule="evenodd" />
</svg>
Add new article
</button>
</form>
</div>
</div>
</div>
<!-- Update modal -->
<form id="drawer-update-article"
x-data="{ id: null, title: '', created: '' }"
@update_article.window="id = $event.detail.id; title = $event.detail.title; created = $event.detail.created;"
x-init="$watch('id', () => htmx.process(htmx.find('#confirmUpdateButton')))"
tabindex="-1"
aria-labelledby="drawer-update-article-label"
aria-hidden="true"
class="fixed top-0 left-0 z-40 w-full h-screen max-w-3xl p-4 overflow-y-auto transition-transform -translate-x-full bg-white dark:bg-gray-800">
<h5 id="drawer-label" class="inline-flex items-center mb-6 text-sm font-semibold text-gray-500 uppercase dark:text-gray-400">Update Article</h5>
<button type="button" data-drawer-dismiss="drawer-update-article" aria-controls="drawer-update-article" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 absolute top-2.5 right-2.5 inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white">
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
<span class="sr-only">Close menu</span>
</button>
<div class="grid gap-4 sm:grid-cols-1 sm:gap-6 ">
<div class="space-y-4 sm:col-span-1 sm:space-y-6">
<div>
<label for="title" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Title</label>
<input type="text"
name="title"
x-model="title"
id="update-title"
placeholder="Type article title"
required=""
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500">
</div>
<div>
<label for="content" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Content</label>
<textarea id="update-drawer-content" name="content" rows="4" class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" placeholder="Write article here"></textarea>
</div>
</div>
</div>
<div class="grid grid-cols-2 gap-4 mt-6 sm:w-1/2">
<button id="confirmUpdateButton"
data-drawer-toggle="drawer-update-article"
aria-controls="drawer-update-article"
type="submit"
hx-swap="outerHTML"
x-bind:hx-patch="`/htmx/admin/rows/article/${id}`"
x-bind:hx-target="`#row-${id}`"
class="text-white bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800">Update</button>
<button type="button"
data-drawer-dismiss="drawer-update-article"
aria-controls="drawer-update-article"
class="text-sm font-medium text-center text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700">
Cancel
</button>
</div>
</form>
<!-- Preview Drawer -->
<div id="drawer-read-article-advanced"
x-data="{ title: '', created: '' }"
@preview_article.window="title = $event.detail.title; created = $event.detail.created;"
class="overflow-y-auto fixed top-0 left-0 z-40 p-4 w-full max-w-lg h-screen bg-white transition-transform -translate-x-full dark:bg-gray-800" tabindex="-1" aria-labelledby="drawer-label" aria-hidden="true">
<div>
<h4 id="read-drawer-label" class="mb-1.5 leading-none text-xl font-semibold text-gray-900 dark:text-white" x-text="title"></h4>
</div>
<button type="button" data-drawer-dismiss="drawer-read-article-advanced" aria-controls="drawer-read-article-advanced" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 absolute top-2.5 right-2.5 inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white">
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
<span class="sr-only">Close menu</span>
</button>
<h2 class="mb-2 font-semibold leading-none text-gray-900 dark:text-white" x-text="created"></h2>
<p id="read-drawer-content" class="mb-4 font-light text-gray-500 sm:mb-5 dark:text-gray-400">
</p>
</div>
<!-- Delete Modal -->
<div id="delete-modal"
x-data="{ deleteId: null }"
@show_delete_modal.window="deleteId = $event.detail.id;"
tabindex="-1"
class="fixed top-0 left-0 right-0 z-50 hidden p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-[calc(100%-1rem)] max-h-full">
<div class="relative w-full h-auto max-w-md max-h-full">
<div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
<button type="button" class="absolute top-3 right-2.5 text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-800 dark:hover:text-white" data-modal-toggle="delete-modal">
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
<span class="sr-only">Close modal</span>
</button>
<div class="p-6 text-center">
<svg aria-hidden="true" class="mx-auto mb-4 text-gray-400 w-14 h-14 dark:text-gray-200" fill="none" stroke="currentColor" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<h3 class="mb-5 text-lg font-normal text-gray-500 dark:text-gray-400">Are you sure you want to delete this article?</h3>
<button id="confirmDeleteButton"
x-init="$watch('deleteId', () => htmx.process(htmx.find('#confirmDeleteButton')))"
@click="$dispatch('delete_row');"
hx-swap="outerHTML"
x-bind:hx-delete="`/htmx/admin/rows/article/${deleteId}`"
x-bind:hx-target="`#row-${deleteId}`"
data-modal-toggle="delete-modal"
type="button"
class="text-white bg-red-600 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 dark:focus:ring-red-800 font-medium rounded-lg text-sm inline-flex items-center px-5 py-2.5 text-center mr-2">
Yes, I'm sure
</button>
<button data-modal-toggle="delete-modal" type="button" class="text-gray-500 bg-white hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-gray-200 rounded-lg border border-gray-200 text-sm font-medium px-5 py-2.5 hover:text-gray-900 focus:z-10 dark:bg-gray-700 dark:text-gray-300 dark:border-gray-500 dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-gray-600">No, cancel</button>
</div>
</div>
</div>
</div>
</main>