128 lines
6.4 KiB
Django/Jinja
128 lines
6.4 KiB
Django/Jinja
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
<title>{% block title %}{% endblock %}</title>
|
|
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
|
{% block head_scripts %}{% endblock %}
|
|
{% if config['ENV'] == 'production' %}
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='sigl.dist.css') }}">
|
|
{% else %}
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
{% endif %}
|
|
<style>
|
|
:root {
|
|
/* Match with TailWind border-gray-200 */
|
|
--jt-control-border-color: rgb(229 231 235);
|
|
--jt-control-border-hover-color: rgb(229 231 235);
|
|
--jt-control-focus-outline-color: #07f;
|
|
}
|
|
</style>
|
|
{% block head_styles %}{% endblock %}
|
|
</head>
|
|
<body class="h-full bg-gray-200">
|
|
<header>
|
|
<nav class="bg-gray-800 border-b border-gray-600">
|
|
<div class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div class="flex items-center justify-between h-12">
|
|
<div class="flex items-center">
|
|
<div class="flex-shrink-0">
|
|
<img class="h-8 w-8" src="https://tailwindui.com/img/logos/workflow-mark-indigo-500.svg" alt="Workflow">
|
|
</div>
|
|
<div>
|
|
<div class="ml-4 flex items-baseline space-x-4">
|
|
<a href="{{ url_for('lists.home') }}" class="{% if request.blueprint == 'lists' %}text-white border-b border-white mx-2 py-1 text-sm font-medium{% else %}text-gray-300 hover:bg-gray-700 hover:text-white px-2 py-1 rounded-md text-sm font-medium{% endif %}" aria-current="page">Shopping Lists</a>
|
|
<a href="{{ url_for('products.home') }}" class="{% if request.blueprint == 'products' %}text-white border-b border-white mx-2 py-1 text-sm font-medium{% else %}text-gray-300 hover:bg-gray-700 hover:text-white px-2 py-1 rounded-md text-sm font-medium{% endif %}">Products</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="-mr-2 flex">
|
|
<!-- Mobile menu button -->
|
|
<button type="button" class="bg-gray-800 inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-800 focus:ring-white" aria-expanded="false">
|
|
<span class="sr-only">App Settings</span>
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
<section class="max-w-3xl mx-auto px-2 bg-white md:border-l md:border-r border-b border-gray-300">
|
|
{% block header %}{% endblock %}
|
|
</section>
|
|
</header>
|
|
<main class="max-w-3xl mx-auto bg-white md:border-l md:border-r border-b md:rounded-b border-gray-300">
|
|
{% block main %}{% endblock %}
|
|
</main>
|
|
<footer class="max-w-3xl mx-auto flex flex-col mt-1 mb-24 px-2 text-xs text-gray-600">
|
|
<p>Sigl | Simple Grocery List | Version {{ config['APP_VERSION'] }}</p>
|
|
<p>Copyright ©2022 Asymworks, LLC. All Rights Reserved.</p>
|
|
</footer>
|
|
{% block body_scripts %}{% endblock %}
|
|
<div
|
|
x-data="noticesHandler()"
|
|
class="fixed inset-0 flex flex-col items-end justify-start h-screen w-screen"
|
|
style="pointer-events:none"
|
|
@notice.document="add($event.detail)"
|
|
>
|
|
<template x-for="notice of notices" :key="notice.id">
|
|
<div
|
|
x-show="visible.includes(notice)"
|
|
x-transition:enter="transition ease-in duration-200"
|
|
x-transition:enter-start="transform opacity-0 translate-y-2"
|
|
x-transition:enter-end="transform opacity-100"
|
|
x-transition:leave="transition ease-out duration-500"
|
|
x-transition:leave-start="transform translate-x-0 opacity-100"
|
|
x-transition:leave-end="transform translate-x-full opacity-0"
|
|
@click="remove(notice.id)"
|
|
class="rounded max-w-[75%] mt-4 mr-6 px-1 py-1 flex items-center justify-center text-white shadow-lg font-bold text-sm cursor-pointer"
|
|
:class="{
|
|
'bg-green-500': notice.type === 'success',
|
|
'bg-blue-500': notice.type === 'info',
|
|
'bg-orange-500': notice.type === 'warning',
|
|
'bg-red-500': notice.type === 'error',
|
|
}"
|
|
style="pointer-events:all"
|
|
x-text="notice.text"
|
|
>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
<script language="javascript">
|
|
document.addEventListener('alpine:init', function () {
|
|
Alpine.data('noticesHandler', () => ({
|
|
notices: [],
|
|
visible: [],
|
|
add(notice) {
|
|
notice.id = Date.now()
|
|
this.notices.push(notice)
|
|
this.fire(notice.id)
|
|
},
|
|
fire(id) {
|
|
this.visible.push(this.notices.find(notice => notice.id == id))
|
|
const timeShown = 2000 * this.visible.length
|
|
setTimeout(() => {
|
|
this.remove(id)
|
|
}, timeShown)
|
|
},
|
|
remove(id) {
|
|
const notice = this.visible.find(notice => notice.id == id)
|
|
const index = this.visible.indexOf(notice)
|
|
this.visible.splice(index, 1)
|
|
},
|
|
}));
|
|
});
|
|
document.addEventListener('alpine:initialized', function () {
|
|
{% for category, message in get_flashed_messages(with_categories=True) %}
|
|
document.dispatchEvent(new CustomEvent('notice', { detail: { type: {{ category|tojson }}, text: {{ message|tojson }} } }));
|
|
{% endfor %}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |