Moving fast and breaking things
This is a first commit in preparation for 2.0 - now using prototempaltes™ - updated README - makefile for some nice shortcuts - add new tikettes - remove tikettes Things that don't work (yet) - authentication on the main frontend (there is none) - generating PDFs
This commit is contained in:
@@ -1 +1 @@
|
||||
const backend_api = 'http://jenova.ponteilla.net:8001/'
|
||||
const backend_api = 'http://localhost:8000/'
|
||||
|
@@ -3,15 +3,19 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<title>zetikettes 0.2</title>
|
||||
<title>Zětikwett's</title>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<!--Import Google Icon Font-->
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<!-- Compiled and minified CSS -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
|
||||
<link rel="stylesheet" href="placeholder.css">
|
||||
|
||||
<!-- Compiled and minified JavaScript -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
|
||||
|
||||
<script src="jscolor.min.js"></script>
|
||||
<script src="config.js"></script>
|
||||
<script src="zetikettes.js"></script>
|
||||
|
||||
@@ -28,15 +32,70 @@ main {
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="container center orange-text">
|
||||
<h1>Zétikwett's</h1>
|
||||
</header>
|
||||
<nav class="light-blue">
|
||||
<div class="nav-wrapper container">
|
||||
<a href="#" class="brand-logo">Zětikwett's</a>
|
||||
<ul id="nav-mobile" class="right hide-on-med-and-down">
|
||||
<li>
|
||||
<a class="modal-trigger btn orange" href="#newproduct">
|
||||
<i class="material-icons left">add</i>Nouveau produit
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="container row">
|
||||
<p></p>
|
||||
<div class="col m6 offset-m3 s12">
|
||||
<ul class="collapsible" id="appbody"></ul>
|
||||
<a class="modal-trigger btn orange hide-on-large-only" href="#newproduct"><i class="material-icons left">add</i>Nouveau produit</a>
|
||||
<ul class="collapsible" id="appbody">
|
||||
<div class="shimmer">
|
||||
<li><div class="collapsible-header"><h6 class="faux-text short"></h6></div></li>
|
||||
<li><div class="collapsible-header"><h6 class="faux-text"></h6></div></li>
|
||||
<li><div class="collapsible-header"><h6 class="faux-text shorter"></h6></div></li>
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Modal Structure -->
|
||||
<div id="newproduct" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="input-field">
|
||||
<input id="new-name" type="text">
|
||||
<label>Nom interne du produit</label>
|
||||
</div>
|
||||
<div class="input-field">
|
||||
<select id="new-type">
|
||||
</select>
|
||||
<label>Type de produit</label>
|
||||
</div>
|
||||
<div class="input-field">
|
||||
<input id="new-designation" type="text">
|
||||
<label>Désignation</label>
|
||||
</div>
|
||||
<div class="input-field">
|
||||
<textarea id="new-ingredients" class="materialize-textarea"></textarea>
|
||||
<label>Ingrédients</label>
|
||||
</div>
|
||||
<div class="input-field">
|
||||
<textarea id="new-description" class="materialize-textarea"></textarea>
|
||||
<label>Description</label>
|
||||
</div>
|
||||
<div class="input-field">
|
||||
<input value="#97A1CC" data-jscolor="{previewSize: 0}" id="new-color" type="text">
|
||||
<label>Couleur</label>
|
||||
</div>
|
||||
<label>
|
||||
<input type="checkbox" id="new-organic">
|
||||
<span>Bio</span>
|
||||
</label>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="modal-close waves-effect waves-green btn" id="new-add">Ajouter</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="page-footer">
|
||||
<footer class="page-footer orange">
|
||||
<div class="container row">
|
||||
<span class="col right">displayed with recycled electrons.</span>
|
||||
</div>
|
||||
|
1
frontend/jscolor.min.js
vendored
Normal file
1
frontend/jscolor.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
47
frontend/placeholder.css
Normal file
47
frontend/placeholder.css
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Read the blog post here:
|
||||
* https://letsbuildui.dev/articles/how-to-build-a-skeleton-loading-placeholder
|
||||
*/
|
||||
.faux-text {
|
||||
background: #dddddd;
|
||||
border-radius: 4px;
|
||||
height: 20px;
|
||||
margin-bottom: 5px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.faux-text.short {
|
||||
width: 75%;
|
||||
}
|
||||
.faux-text.shorter {
|
||||
width: 55%;
|
||||
}
|
||||
|
||||
.shimmer {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.shimmer::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.4) 50%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
animation: shimmer 1s infinite;
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
@@ -7,58 +7,112 @@ const params = {
|
||||
'fruit': 'Quantité de fruits pour 100g (g)',
|
||||
}
|
||||
|
||||
var tikats;
|
||||
|
||||
function addProduct(tikette) {
|
||||
const zett = tikette;
|
||||
const appbody = $("#appbody");
|
||||
const block = $('<div class="section">');
|
||||
for (let sub in zett.subs) {
|
||||
block.append($(`<div class="input-field"><label class="active">${params[sub]}</label><input type="text" name="${sub}" value="${zett.subs[sub]}">`));
|
||||
}
|
||||
const loader = $('<div class="progress"><div class="indeterminate"></div></div>')
|
||||
.hide();
|
||||
|
||||
const action = $('<div class="section">')
|
||||
.append($('<a class="btn">generate<a>')
|
||||
.click(() => {
|
||||
const subs = block.find(':text')
|
||||
.toArray()
|
||||
.reduce((obj, el) => ({...obj, [el.name]: el.value}), {});
|
||||
const req = {
|
||||
sticker: zett.sticker,
|
||||
subs,
|
||||
landscape: zett.landscape,
|
||||
};
|
||||
|
||||
loader.show();
|
||||
$('.btn').addClass("disabled");
|
||||
|
||||
$.post(backend_api + 'generate', JSON.stringify(req))
|
||||
.then(data => {
|
||||
const pdfbtn = $(`<a class="btn" href="${backend_api}data/${data.file}" target="_blank">open pdf</a>`);
|
||||
action.append(pdfbtn);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
})
|
||||
.always(() => {
|
||||
loader.hide();
|
||||
$('.btn').removeClass('disabled');
|
||||
});
|
||||
})
|
||||
.append(loader));
|
||||
|
||||
const deleteAction = $('<a class="btn-flat grey-text"><b class="material-icons">delete</b>');
|
||||
deleteAction.click(() => {
|
||||
const req = {
|
||||
id: zett.id,
|
||||
};
|
||||
$.post(backend_api + 'deletetikette', JSON.stringify(req)).then(reload);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
appbody
|
||||
.append($('<li>')
|
||||
.append($('<div class="collapsible-header valign-wrapper">')
|
||||
.append(`<h6 class="blue-text">${zett.title}</h6>`)
|
||||
.append($('<span class="badge">')
|
||||
.append(deleteAction)))
|
||||
.append($('<div class="collapsible-body">')
|
||||
.append(block)
|
||||
.append(action)));
|
||||
}
|
||||
|
||||
function setCategories() {
|
||||
const katsel = $('#new-type');
|
||||
katsel.empty();
|
||||
|
||||
for (let kat of tikats) {
|
||||
katsel.append($(`<option value="${kat.id}">${kat.name}</option>`));
|
||||
}
|
||||
}
|
||||
|
||||
function loadAll(zetikettes) {
|
||||
const appbody = $("#appbody");
|
||||
appbody.empty();
|
||||
for (let zett of zetikettes) {
|
||||
const block = $('<div class="section">');
|
||||
for (let sub in zett.subs) {
|
||||
block.append($(`<div class="input-field"><label class="active">${params[sub]}</label><input type="text" name="${sub}" value="${zett.subs[sub]}">`));
|
||||
}
|
||||
const loader = $('<div class="progress"><div class="indeterminate"></div></div>')
|
||||
.hide();
|
||||
|
||||
const action = $('<div class="section">')
|
||||
.append($('<a class="btn">generate<a>')
|
||||
.click(() => {
|
||||
const subs = block.find(':text')
|
||||
.toArray()
|
||||
.reduce((obj, el) => ({...obj, [el.name]: el.value}), {});
|
||||
const req = {
|
||||
sticker: zett.sticker,
|
||||
subs,
|
||||
landscape: zett.landscape,
|
||||
};
|
||||
|
||||
loader.show();
|
||||
$('.btn').addClass("disabled");
|
||||
|
||||
$.post(backend_api, JSON.stringify(req))
|
||||
.then(data => {
|
||||
console.log(data);
|
||||
const pdfbtn = $(`<a class="btn" href="${backend_api}data/${data.file}" target="_blank">open pdf</a>`);
|
||||
action.append(pdfbtn);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
})
|
||||
.always(() => {
|
||||
loader.hide();
|
||||
$('.btn').removeClass('disabled');
|
||||
});
|
||||
})
|
||||
.append(loader));
|
||||
|
||||
appbody
|
||||
.append($('<li>')
|
||||
.append($(`<div class="collapsible-header"><h6 class="blue-text">${zett.title}</h6></div>`))
|
||||
.append($('<div class="collapsible-body">')
|
||||
.append(block)
|
||||
.append(action)));
|
||||
addProduct(zett);
|
||||
}
|
||||
setCategories();
|
||||
|
||||
$('.collapsible').collapsible();
|
||||
$('.modal').modal();
|
||||
$('select').formSelect();
|
||||
|
||||
konami();
|
||||
|
||||
$('#new-add').off('click').click(() => {
|
||||
const title = $("#new-name").val();
|
||||
const category_id = $("#new-type").val();
|
||||
const designation = $("#new-designation").val();
|
||||
const ingredients = $("#new-ingredients").val();
|
||||
const description = $("#new-description").val();
|
||||
const color = $("#new-color").val().substring(1);
|
||||
const ab = $("#new-organic").is(":checked") ? 'visible' : 'none';
|
||||
|
||||
const req = {
|
||||
title,
|
||||
category_id,
|
||||
designation,
|
||||
ingredients,
|
||||
description,
|
||||
color,
|
||||
ab,
|
||||
};
|
||||
$.post(backend_api + 'newtikette', JSON.stringify(req)).then(reload);
|
||||
});
|
||||
}
|
||||
|
||||
function konami() {
|
||||
@@ -76,16 +130,22 @@ function konami() {
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(async () => {
|
||||
async function reload() {
|
||||
try {
|
||||
const resp = await $.ajax({
|
||||
url: backend_api + 'list',
|
||||
timeout: 1000,
|
||||
});
|
||||
tikats = (await $.ajax({
|
||||
url: backend_api + 'categories',
|
||||
timeout: 1000,
|
||||
})).tikats.sort((a, b) => a.name > b.name ? 1 : -1);
|
||||
loadAll(resp.tikettes.sort((a, b) => (a.title < b.title) ? -1 : 1));
|
||||
} catch(e) {
|
||||
const appbody = $("#appbody");
|
||||
appbody.append(`<li>Could not reach backend server`);
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(reload);
|
||||
|
Reference in New Issue
Block a user