diff --git a/snippets/checkout.html b/snippets/checkout.html
index c71ab06..d1c0446 100644
--- a/snippets/checkout.html
+++ b/snippets/checkout.html
@@ -1,5 +1,5 @@
{{define "header_additions"}}
-
+
{{end}}
{{define "body_content"}}
Checkout
@@ -15,88 +15,5 @@
-
+
{{end}}
diff --git a/snippets/graph.html b/snippets/graph.html
index 1695001..0ef671c 100644
--- a/snippets/graph.html
+++ b/snippets/graph.html
@@ -7,7 +7,7 @@
-
+
-
+
@@ -149,170 +53,9 @@ $(function() {
-
+
-
+
{{ else }}
diff --git a/snippets/scales.html b/snippets/scales.html
index ec3c798..a943620 100644
--- a/snippets/scales.html
+++ b/snippets/scales.html
@@ -192,317 +192,7 @@ Sie erhalten eine E-Mail, sobald die Zahlung erfolgreich abgeschlossen ist.
-
+
{{ else }}
diff --git a/static/js/chart.js b/static/js/chart.js
new file mode 100644
index 0000000..65d5484
--- /dev/null
+++ b/static/js/chart.js
@@ -0,0 +1,159 @@
+var chart;
+
+function drawGraph(deveui, alias, property, start, stop, create_graph) {
+ range = ""
+ range = range + "&start=" + start;
+ range = range + "&stop=" + stop;
+
+ var label;
+ var labels = {};
+ var forceNiceScale = true;
+ $(".button").removeClass("is-success");
+ if (property=="t") {
+ $("#btn_t").addClass("is-success");
+ label = 'Temperatur';
+ mysubtitle = 'Temperatur in °C';
+ minfunc = function(min) { if (min > 0) { return 0 } else { return min } }
+ maxfunc = function(max) { return max + 5 }
+ } else if (property=="vp") {
+ $("#btn_vp").addClass("is-success");
+ label = 'Akkuladung';
+ mysubtitle = 'Akkuladung in Prozent';
+ minfunc = function(min) { return 0 }
+ maxfunc = function(max) { return 100 }
+ forceNiceScale = false;
+ } else if (property=="w") {
+ $("#btn_w").addClass("is-success");
+ label = 'Gewicht';
+ mysubtitle = 'Gewicht in Kilogramm';
+ minfunc = function(min) { if (min > 5000) { return min - 2000 } else { return 0 } }
+ maxfunc = function(max) { return max + 2000 }
+ labels = {
+ formatter: function(val, index) {
+ return (val / 1000.0).toFixed(3);
+ }
+ };
+ } else if (property==="h") {
+ $("#btn_h").addClass("is-success");
+ label = 'Luftfeuchtigkeit';
+ mysubtitle = 'Luftfeuchtigkeit in Prozent';
+ minfunc = function(min) { return 0 }
+ maxfunc = function(max) { return 100 }
+ forceNiceScale = false;
+ } else if (property=="p") {
+ $("#btn_p").addClass("is-success");
+ label = 'Luftdruck';
+ mysubtitle = 'Luftdruck in Hektopascal';
+ minfunc = function(min) { return 900 }
+ maxfunc = function(max) { return 1060 }
+ } else {
+ label = 'Unknown';
+ mysubtitle = 'Unknown';
+ }
+
+ $.getJSON('https://mini-beieli.ch/metrics?deveui=' + deveui + '&alias=' + alias + '&property=' + property + range, function(mydata) {
+ if ("msg" in mydata) {
+ if (mydata.msg.includes("expired")) {
+ $('#chart').html(`
+
+ Abo ist abgelaufen
+
+`);
+ } else if (mydata.msg.includes("error:")) {
+ $('#myselectors').hide();
+ $('#chart').html(`
+
+ Fehler im Aufruf
+
+`);
+ } else {
+ location.reload(true);
+ }
+ return;
+ }
+ var options = {
+ chart: {
+ type: 'line',
+ animations: {
+ enabled: false
+ }
+ },
+ stroke: {
+ curve: 'smooth'
+ },
+ title: {
+ text: urlParams.get('alias'),
+ align: 'center',
+ offsetY: 20,
+ style: {
+ fontSize: '32px'
+ }
+ },
+ subtitle: {
+ text: mysubtitle,
+ align: 'center',
+ offsetY: 60,
+ style: {
+ fontSize: '12px'
+ }
+ },
+ xaxis: {
+ type: "datetime",
+ labels: {
+ rotate: 0,
+ datetimeUTC: false
+ }
+ },
+ yaxis: {
+ min: minfunc,
+ max: maxfunc,
+ forceNiceScale: forceNiceScale,
+ labels: labels
+ },
+ tooltip: {
+ x: {
+ format: 'dd.MM.yyyy HH:mm'
+ }
+ },
+ series: [{
+ name: label,
+ data: mydata
+ }]
+ }
+
+ if (create_graph) {
+ chart = new ApexCharts(document.querySelector("#chart"), options);
+ } else {
+ chart.destroy();
+ chart = new ApexCharts(document.querySelector("#chart"), options);
+ //chart.updateOptions(options);
+ //chart.updateSeries(mydata);
+ }
+
+ chart.render();
+ });
+}
+
+var urlParams = new URLSearchParams(window.location.search);
+var deveui = urlParams.get('deveui');
+var alias = urlParams.get('alias');
+var property = urlParams.get('property');
+var start = urlParams.get('start');
+var stop = urlParams.get('stop');
+
+range="";
+if (start == null) {
+ var dstart = moment({hour: 0});
+ var start = dstart.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
+ range = range + "&start=" + start;
+}
+
+if (stop == null) {
+ var dstop = moment();
+ var stop = dstop.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
+ range = range + "&stop=" + stop;
+}
+
+$('#reportrange span').html(moment(start).locale('de').format('D. MMM YYYY') + ' - ' + moment(stop).locale('de').format('D. MMM YYYY'));
+
+drawGraph(deveui, alias, property, start, stop, true);
diff --git a/static/js/chekout.js b/static/js/chekout.js
new file mode 100644
index 0000000..af9d3ef
--- /dev/null
+++ b/static/js/chekout.js
@@ -0,0 +1,81 @@
+// Set your publishable key: remember to change this to your live publishable key in production
+// See your keys here: https://dashboard.stripe.com/account/apikeys
+var stripe = Stripe('pk_test_YkSGqH3Tk9WKK9HrlY63GhAg');
+var elements = stripe.elements();
+
+// Set up Stripe.js and Elements to use in checkout form
+var style = {
+ base: {
+ color: "#32325d",
+ }
+};
+
+var card = elements.create("card", { style: style });
+card.mount("#card-element");
+
+
+card.addEventListener('change', ({error}) => {
+ const displayError = document.getElementById('card-errors');
+ if (error) {
+ displayError.textContent = error.message;
+ } else {
+ displayError.textContent = '';
+ }
+});
+
+
+var submitButton = document.getElementById('submit');
+
+function GetClientSecret() {
+ var result = "";
+ $.ajax({
+ async: false,
+ url: "getstripepaymentintent",
+ type: "get", //send it through get method
+ dataType: "json",
+ data: {
+ charge_data: $("#charge_data").html()
+ },
+ success: function(response) {
+ console.log('pay success');
+ console.log(response.stripesessionid);
+ console.log('rc: '+response.rc);
+ if (response.rc == 0) {
+ result = response.stripeclientsecret;
+ }
+ },
+ error: function(xhr) {
+ console.log('getstripepaymentintent error');
+ //Do Something to handle error
+ }
+ });
+
+ return result;
+}
+
+submitButton.addEventListener('click', function(ev) {
+ var clientSecret = GetClientSecret();
+ stripe.confirmCardPayment(clientSecret, {
+ payment_method: {
+ card: card,
+ billing_details: {
+ name: 'Jenny Rosen'
+ }
+ }
+ }).then(function(result) {
+ if (result.error) {
+ // Show error to your customer (e.g., insufficient funds)
+ console.log(result.error.message);
+ } else {
+ // The payment has been processed!
+ if (result.paymentIntent.status === 'succeeded') {
+ // Show a success message to your customer
+ // There's a risk of the customer closing the window before callback
+ // execution. Set up a webhook or plugin to listen for the
+ // payment_intent.succeeded event that handles any business critical
+ // post-payment actions.
+ alert("Payment succeeded!!!");
+ }
+ }
+ });
+});
diff --git a/static/js/graph.js b/static/js/graph.js
new file mode 100644
index 0000000..63881b5
--- /dev/null
+++ b/static/js/graph.js
@@ -0,0 +1,94 @@
+$(function() {
+
+ var start = moment({hour: 0});
+ var end = moment();
+ var s_start = start.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
+ var s_end = end.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
+
+ console.log("XXX: "+start.format());
+
+ function cb(start, end) {
+ $('#reportrange span').html(start.locale('de').format('D. MMM YYYY') + ' - ' + end.locale('de').format('D. MMM YYYY'));
+ console.log("A new date selection was made: " + start.format() + ' to ' + end.format());
+ s_start = start.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
+ s_end = end.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
+ console.log("Start: " + s_start + ' End: ' + s_end + ' Property: '+ property);
+ drawGraph(deveui, alias, property, s_start,s_end, false);
+ }
+
+ $('#btn_w').on("click", function() {
+ property = 'w';
+ drawGraph(deveui, alias, property, s_start, s_end, false);
+ });
+
+ $('#btn_t').on("click", function() {
+ property = 't';
+ drawGraph(deveui, alias, property, s_start, s_end, false);
+ });
+
+ $('#btn_h').on("click", function() {
+ property = 'h';
+ drawGraph(deveui, alias, property, s_start, s_end, false);
+ });
+
+ $('#btn_p').on("click", function() {
+ property = 'p';
+ drawGraph(deveui, alias, property, s_start, s_end, false);
+ });
+
+ $('#btn_vp').on("click", function() {
+ property = 'vp';
+ drawGraph(deveui, alias, property, s_start, s_end, false);
+ });
+
+ $('#reportrange').daterangepicker({
+ startDate: start.local(),
+ endDate: end.local(),
+ regional: [ "de" ],
+ "locale": {
+ format: 'DD.MM.YYYY',
+ "separator": " - ",
+ "applyLabel": "Anwenden",
+ "cancelLabel": "Abbrechen",
+ "fromLabel": "Von",
+ "toLabel": "Bis",
+ customRangeLabel: 'Benutzerdefiniert',
+ "weekLabel": "W",
+ "daysOfWeek": [
+ "So",
+ "Mo",
+ "Di",
+ "Mi",
+ "Do",
+ "Fr",
+ "Sa"
+ ],
+ "monthNames": [
+ "Jan",
+ "Feb",
+ "Mär",
+ "Apr",
+ "Mai",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Okt",
+ "Nov",
+ "Dez"
+ ],
+ "firstDay": 1
+ },
+ ranges: {
+ 'Heute': [moment(), moment()],
+ 'Gestern': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
+ 'Letzte 7 Tage': [moment().subtract(6, 'days'), moment()],
+ 'Letzte 30 Tage': [moment().subtract(29, 'days'), moment()],
+ 'Diesen Monat': [moment().startOf('month'), moment().endOf('month')],
+ 'Letzten Monat': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
+ }
+ }, cb);
+
+ //cb(start, end);
+
+});
diff --git a/static/js/scales.js b/static/js/scales.js
new file mode 100644
index 0000000..eee8894
--- /dev/null
+++ b/static/js/scales.js
@@ -0,0 +1,308 @@
+function validate(what, text) {
+ if (what == 'alias') {
+ var re = /^[a-zA-Z0-9 ]{1,25}$/;
+ } else if (what == 'smsnumber') {
+ var re = /^\+[0-9]{11,11}$/;
+ }
+ return re.test(text);
+}
+
+// A $( document ).ready() block.
+$( document ).ready(function() {
+$(".show-modal").click(function() {
+ $("#alias_exclamation").hide();
+ $("#smsnumber_exclamation").hide();
+ var alias = $(this).prev().html();
+ var deveui = $(this).prev().attr('id').replace("alias_","");
+ $('#deveui').html(deveui);
+ var alarmactive = $('#alarmactive_'+deveui).html();
+ var smsnumber = $('#smsnumber_'+deveui).html();
+
+ $("#alias").val(alias);
+ console.log(alarmactive);
+ if (alarmactive == "1") {
+ $('#checkbox').prop('checked', true);
+ } else {
+ $('#checkbox').prop('checked', false);
+ }
+ $("#smsnumber").val(smsnumber);
+ $("#modal").addClass("is-active");
+});
+
+$("#cart-close").click(function() {
+ $("#cart").removeClass("is-active");
+});
+
+$("#payment_notifier_close").click(function() {
+ $("#payment_notifier").removeClass("is-active");
+ location.reload(true);
+});
+
+$(".abo_plus").click(function() {
+ console.log("abo_plus");
+ el = $(this).parent().find(".abo_add_years");
+ el_text = $(this).parent().parent().find(".abo_add_years_text");
+ counter = Number(el.html());
+ if (counter < 3) {
+ counter = counter + 1;
+ el.html(counter);
+ if (counter == 1) {
+ el_text.html("+" + counter + " Jahr");
+ } else {
+ el_text.html("+" + counter + " Jahre");
+ }
+ }
+});
+
+$(".abo_minus").click(function() {
+ console.log("abo_minus");
+ el = $(this).parent().find(".abo_add_years");
+ el_text = $(this).parent().parent().find(".abo_add_years_text");
+ counter = Number(el.html());
+ if (counter > 0) {
+ counter = counter - 1;
+ el.html(counter);
+ if (counter == 0) {
+ el_text.html(" ");
+ } else if (counter == 1) {
+ el_text.html("+" + counter + " Jahr");
+ } else {
+ el_text.html("+" + counter + " Jahre");
+ }
+ }
+});
+
+function add_years(dt,n)
+{
+ return new Date(dt.setFullYear(dt.getFullYear() + n));
+}
+
+$(".abo_pay").click(function() {
+ console.log("pay...");
+ loadStripeLibrary();
+ counter = 0;
+ charge_data = '';
+ abo_table = '';
+ abo_table += '| Alias | verlängern bis | Betrag |
';
+ $(".waage").each(function( index ) {
+ console.log( index + ": " + $( this ).find(".alias").html() );
+ this_count = Number($( this ).find(".abo_add_years").html());
+ if (this_count > 0) {
+ counter += this_count;
+ paid_until = $( this ).find(".paid_until").html();
+ if (moment(paid_until,'DD.MM.YYYY') < moment()) {
+ this_date = moment().format('DD.MM.YYYY');
+ } else {
+ this_date = paid_until;
+ }
+ abo_table += '| ' + $( this ).find('.alias').html() + ' | ' + moment(this_date,'DD.MM.YYYY').add('years', this_count).format('DD.MM.YYYY') + ' | ' + (this_count * 24).toFixed(2) + ' |
';
+ if (charge_data == '') {
+ charge_data = $( this ).find("div").first().attr('id') + ":" + this_count;
+ } else {
+ charge_data += "," + $( this ).find("div").first().attr('id') + ":" + this_count;
+ }
+ }
+ console.log( counter );
+ });
+ abo_table += '| Total CHF | | ' + (counter * 24).toFixed(2) + ' |
';
+ console.log("Counter: "+counter);
+ abo_table += "
";
+ if (counter > 0) {
+ console.log(abo_table);
+ console.log("charge_data: "+charge_data);
+ $("#abos_verlaengern").html(abo_table);
+ $("#charge_data").html(charge_data);
+ $("#cart").addClass("is-active");
+ }
+});
+
+$("#modal-close").click(function() {
+ console.log("blabla");
+ $("#modal").removeClass("is-active");
+});
+
+$("#modal-save").click(function() {
+ var alarmactive = "0";
+ if ($('#checkbox').prop('checked')) {
+ alarmactive = "1";
+ }
+
+ // Validation Code
+ var is_valid = true;
+ if (!validate('alias',$('#alias').val())) {
+ $('#alias_errormsg').html('Ungültige Bezeichnung; erlaubte Zeichen A-Z, 0-9 und Leerschlag');
+ $("#alias").addClass("is-danger");
+ $("#alias_exclamation").show();
+ is_valid = false;
+ } else {
+ $('#alias_errormsg').html('');
+ $("#alias").removeClass("is-danger");
+ $("#alias_exclamation").hide();
+ }
+
+ if (!validate('smsnumber',$('#smsnumber').val())) {
+ $('#smsnumber_errormsg').html('Beispiel einer gültigen SMS Nummer: +41761234567');
+ $("#smsnumber").addClass("is-danger");
+ $("#smsnumber_exclamation").show();
+ is_valid = false;
+ } else {
+ $('#smsnumber_errormsg').html('');
+ $("#smsnumber").removeClass("is-danger");
+ $("#smsnumber_exclamation").hide();
+ }
+
+ if (!(is_valid)) {
+ return;
+ }
+
+ $.ajax({
+ url: "save_scale_settings",
+ type: "get", //send it through get method
+ dataType: "json",
+ data: {
+ deveui: $('#deveui').html(),
+ alias: $('#alias').val(),
+ smsnumber: $("#smsnumber").val(),
+ alarmactive: alarmactive
+ },
+ success: function(response) {
+ console.log('save success');
+ if (response.rc == 0) {
+ $('#alias_'+$('#deveui').html()).html($('#alias').val());
+ var alarmactive = "0";
+ if ($('#checkbox').prop('checked')) {
+ alarmactive = "1";
+ }
+ $('#alarmactive_'+$('#deveui').html()).html(alarmactive);
+ $('#smsnumber_'+$('#deveui').html()).html($('#smsnumber').val());
+ }
+ },
+ error: function(xhr) {
+ console.log('save error');
+ //Do Something to handle error
+ }
+ });
+
+ console.log("save");
+ $("#modal").removeClass("is-active");
+});
+
+});
+
+function loadStripeLibrary() {
+ $.ajax({
+ url: "https://js.stripe.com/v3/",
+ dataType: "script",
+ async: false, // <-- This is the key
+ success: function () {
+ // all good...
+ console.log("loadStripeLibrary called...");
+ SetupStripe();
+ },
+ error: function () {
+ throw new Error("Could not load script " + script);
+ }
+ });
+}
+
+function SetupStripe() {
+ console.log("SetupStripe");
+ // Set your publishable key: remember to change this to your live publishable key in production
+ // See your keys here: https://dashboard.stripe.com/account/apikeys
+ stripe = Stripe('pk_test_YkSGqH3Tk9WKK9HrlY63GhAg');
+ elements = stripe.elements({ locale: "de" });
+
+ // Set up Stripe.js and Elements to use in checkout form
+ style = {
+ base: {
+ color: "#32325d",
+ }
+ };
+
+ card = elements.create("card", { style: style });
+ card.mount("#card-element");
+ $("#card-errors-article").hide();
+
+ card.addEventListener('change', ({error}) => {
+ if (error) {
+ $("#card-errors").text(error.message);
+ $("#card-errors-article").show();
+ } else {
+ $("#card-errors").text("");
+ $("#card-errors-article").hide();
+ }
+ });
+}
+
+function ConfirmPayment(clientSecret) {
+ stripe.confirmCardPayment(clientSecret, {
+ payment_method: {
+ card: card,
+ billing_details: {
+ name: '{{ .UserName }}'
+ }
+ }
+ }).then(function(result) {
+ if (result.error) {
+ // Show error to your customer (e.g., insufficient funds)
+ console.log(result.error.message);
+ $('#card-errors').text(result.error.message);
+ $('#card-errors-article').show();
+ //Do Something to handle error
+ EndPaymentProgress();
+ } else {
+ // The payment has been processed!
+ if (result.paymentIntent.status === 'succeeded') {
+ // Show a success message to your customer
+ // There's a risk of the customer closing the window before callback
+ // execution. Set up a webhook or plugin to listen for the
+ // payment_intent.succeeded event that handles any business critical
+ // post-payment actions.
+ console.log("Payment succeeded!!!");
+ $('#card-errors').text("");
+ $('#card-errors-article').hide();
+ $("#cart").removeClass("is-active");
+ EndPaymentProgress();
+ $('#payment_notifier').addClass('is-active');
+ }
+ }
+ });
+}
+
+function StartPaymentProgress() {
+ $("#cart-pay").attr("disabled", true).addClass("is-loading");
+ $("#cart-close").attr("disabled", true);
+}
+
+function EndPaymentProgress() {
+ $("#cart-pay").attr("disabled", false).removeClass("is-loading");
+ $("#cart-close").attr("disabled", false);
+}
+
+function PayMe() {
+ $.ajax({
+ url: "getstripepaymentintent",
+ type: "get", //send it through get method
+ dataType: "json",
+ data: {
+ charge_data: $("#charge_data").html()
+ },
+ success: function(response) {
+ console.log('pay success');
+ console.log('rc: '+response.rc);
+ if (response.rc == 0) {
+ ConfirmPayment(response.stripeclientsecret);
+ }
+ },
+ error: function(xhr) {
+ console.log('getstripepaymentintent error');
+ //Do Something to handle error
+ EndPaymentProgress();
+ }
+ });
+}
+
+$('#cart-pay').on('click', function(ev) {
+ StartPaymentProgress();
+ PayMe();
+});
diff --git a/templates/layout.html b/templates/layout.html
index c968d87..6885692 100644
--- a/templates/layout.html
+++ b/templates/layout.html
@@ -9,8 +9,8 @@
-
-
+
+
{{template "header_additions" . }}
@@ -83,7 +83,7 @@
{{template "body_content" . }}
-
+