190 lines
4.6 KiB
TypeScript
190 lines
4.6 KiB
TypeScript
/*
|
|
* SPDX-FileCopyrightText: 2023 Sascha Nitsch (@grumpydevelop@contentnation.net) https://contentnation.net/en/grumpydevelop
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*/
|
|
|
|
/// <reference path="forminfo.ts" />
|
|
/// <reference path="loader.ts" />
|
|
/// <reference path="view.ts" />
|
|
/// <reference path="toast.d.ts" />
|
|
/// <reference path="api.ts" />
|
|
|
|
interface Wifi {
|
|
mode:string;
|
|
ssid:string;
|
|
}
|
|
|
|
type PinMappings = Record<string,[string, string, boolean]>;
|
|
|
|
class CameraTrigger {
|
|
public form:FormInfo;
|
|
public lang: any;
|
|
public loader: Loader;
|
|
public routing: any;
|
|
public oldhash: string;
|
|
public view: View;
|
|
public wifi: Wifi;
|
|
public pinMapping: PinMappings;
|
|
|
|
constructor() {
|
|
this.routing = {
|
|
"": "MainView",
|
|
"#wifi": "WifiView",
|
|
"#pinmapping": "PinMappingView",
|
|
"#update": "UpdateView"
|
|
};
|
|
|
|
this.loader = new Loader(this);
|
|
this.loadConfig();
|
|
this.loader.template("base", this, this.start, null);
|
|
}
|
|
|
|
public getVersion() : string {
|
|
return "beta1";
|
|
}
|
|
|
|
/**
|
|
* default error function
|
|
* - disables loading indicator
|
|
* - fills in fields with class errormsg
|
|
* - show error toaster
|
|
*/
|
|
public error(jqXHR, textStatus, errorThrown) {
|
|
var error="error";
|
|
if (jqXHR.responseJSON) {
|
|
error = jqXHR.responseJSON.error;
|
|
} else {
|
|
if (errorThrown in app.lang.error) {
|
|
error = app.lang.error[errorThrown];
|
|
} else {
|
|
error = errorThrown;
|
|
}
|
|
}
|
|
if (this.form) {
|
|
$(this.form.target).removeClass("loading");
|
|
$(this.form.target).find('.errormsg').text(error);
|
|
}
|
|
$.toast({
|
|
text: error,
|
|
position: 'top-right',
|
|
icon: 'error'
|
|
});
|
|
};
|
|
|
|
/**
|
|
* default success function
|
|
* - disables loading indicator
|
|
* - fills in fields with class successmsg
|
|
* - show toaster
|
|
*/
|
|
public success(jqXHR, textStatus, errorThrown) {
|
|
var message="ok";
|
|
if (jqXHR.responseJSON) {
|
|
message = jqXHR.responseJSON.message;
|
|
if (message in app.lang.message) {
|
|
message = app.lang.message[message];
|
|
}
|
|
}
|
|
if (this.form) {
|
|
$(this.form.target).removeClass("loading");
|
|
$(this.form.target).find('.successmsg').text(message);
|
|
}
|
|
$.toast({
|
|
text: message,
|
|
position: 'top-right',
|
|
icon: 'success'
|
|
});
|
|
};
|
|
|
|
loadConfig() {
|
|
Api.get("config.json", {}, this, this.applyConfig, this.error);
|
|
}
|
|
|
|
applyConfig(config) {
|
|
// load language file
|
|
this.loader.addLang("en", "main", this, this.start, this.error);
|
|
this.wifi = {mode: config.wifimode, ssid: config.ssid};
|
|
}
|
|
|
|
start() {
|
|
if (!this.lang || $("#tplMenu").length == 0) {
|
|
// try again the next time
|
|
return;
|
|
}
|
|
// render menu
|
|
var template = $("#tplMenu").html();
|
|
var data:any = {};
|
|
data.l = this.lang;
|
|
var html = Mustache.render(template, data);
|
|
$("#menu").prepend(html);
|
|
$(window).on('hashchange', this, this.doRouting);
|
|
this.doRouting();
|
|
}
|
|
|
|
doRouting(event?: JQuery.TriggeredEvent) {
|
|
if (event && event.data) {
|
|
event.data.doRouting();
|
|
return false;
|
|
}
|
|
var hash = document.location.hash;
|
|
if (hash != this.oldhash && this.view) {
|
|
this.view.finish();
|
|
}
|
|
this. oldhash = hash;
|
|
var className = this.routing[hash];
|
|
if (className) {
|
|
this.newClass(className);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* create a new instance of given classname with optional construction parameter
|
|
* - loads class if not yet known, filename: js/lowerCaseClassName.min.js
|
|
* - creates instance of class
|
|
* @param {any} classname class name
|
|
* @param {object} parameter optional parameter for new instance
|
|
* @private
|
|
*/
|
|
newClass(classname: any, parameter?: object) : any {
|
|
if (typeof classname === "object") {
|
|
let newclass: any = window[classname.name];
|
|
new newclass(this, classname.parameter);
|
|
return;
|
|
}
|
|
if (!window[classname]) {
|
|
this.loader.js(classname.toLowerCase(), this, this.newClass, {
|
|
name : classname,
|
|
parameter : parameter
|
|
});
|
|
return;
|
|
}
|
|
let newclass: any = window[classname];
|
|
new newclass(this, parameter);
|
|
};
|
|
|
|
getPinMapping(context: any, callback: any) {
|
|
Api.get("pinmapping.json",{}, {t:this, context:context, callback:callback}, this.gotPinMapping, this.error);
|
|
}
|
|
|
|
gotPinMapping(this:any, data: any) {
|
|
var self = this.t;
|
|
var cbcontext = this.context;
|
|
var callback = this.callback;
|
|
self.pinMapping = data;
|
|
if (callback) {
|
|
callback.call(cbcontext);
|
|
}
|
|
}
|
|
|
|
setPinMapping(data: PinMappings) {
|
|
this.pinMapping = data;
|
|
}
|
|
|
|
}
|
|
|
|
var app: CameraTrigger;
|
|
$(document).ready(function() {
|
|
app = new CameraTrigger();
|
|
});
|