mirror of
https://github.com/Doodle3D/doodle3d-client.git
synced 2024-11-22 09:17:56 +01:00
Merge branch 'feature/printerdriver' of https://github.com/Doodle3D/doodle3d-client into feature/printerdriver
# By peteruithoven # Via peteruithoven * 'feature/printerdriver' of https://github.com/Doodle3D/doodle3d-client: Small css tweak Messages! Showing info about buffering, connection to wifibox and printer Leave warning while sending Added heatup in startgcode and replace {printingTemp} and {preheatTemp} for settings Added network reconnect hint Integrated progressbar Save settings before connect to network / create access point and display validation errors and only close settings when settings are saved Conflicts: css/styles.min.css js/main.js
This commit is contained in:
commit
66271c5287
@ -94,3 +94,11 @@ form .button {
|
|||||||
form #passwordLabel, form #password {
|
form #passwordLabel, form #password {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form input.error, form textarea.error, form select.error {
|
||||||
|
border: #f00 solid 2px;
|
||||||
|
}
|
||||||
|
form .errorMsg {
|
||||||
|
color: #f00;
|
||||||
|
margin: 0 0 0 1em;
|
||||||
|
}
|
@ -658,6 +658,40 @@ SETTINGS POPUP
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#message {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
padding: 0.4em 0.5em;
|
||||||
|
border-radius: 0 0 0 10px;
|
||||||
|
border: 2px solid #333;
|
||||||
|
border-width: 0 0 2px 2px;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
-webkit-box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);
|
||||||
|
box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);
|
||||||
|
color: #333;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#message.error {
|
||||||
|
background: #EB313C;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#message.warning {
|
||||||
|
background: #E9A86E;
|
||||||
|
}
|
||||||
|
|
||||||
|
#message.notice {
|
||||||
|
background: #93CAF4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#message.info {
|
||||||
|
background: #97DD8A;
|
||||||
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 480px),only screen and (max-width: 720px) and (min-device-pixel-ratio: 1.5),only screen and (max-width: 720px) and (-webkit-min-device-pixel-ratio: 1.5) {
|
@media only screen and (max-width: 480px),only screen and (max-width: 720px) and (min-device-pixel-ratio: 1.5),only screen and (max-width: 720px) and (-webkit-min-device-pixel-ratio: 1.5) {
|
||||||
/*
|
/*
|
||||||
TOP LOGO
|
TOP LOGO
|
||||||
|
@ -66,6 +66,8 @@
|
|||||||
<img class="btnSettings btn" src="img/buttons/btnSettings.png">
|
<img class="btnSettings btn" src="img/buttons/btnSettings.png">
|
||||||
<img class="btnInfo btn" src="img/buttons/btnInfo.png">
|
<img class="btnInfo btn" src="img/buttons/btnInfo.png">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="message"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- center panel -->
|
<!-- center panel -->
|
||||||
@ -141,6 +143,7 @@
|
|||||||
<script src="js/Thermometer.js"></script>
|
<script src="js/Thermometer.js"></script>
|
||||||
<script src="js/utils.js"></script>
|
<script src="js/utils.js"></script>
|
||||||
<script src="js/sidebar.js"></script>
|
<script src="js/sidebar.js"></script>
|
||||||
|
<script src="js/message.js"></script>
|
||||||
<script src="js/main.js"></script>
|
<script src="js/main.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
@ -12,13 +12,16 @@ function setPrintprogress(val) {
|
|||||||
|
|
||||||
function Printer() {
|
function Printer() {
|
||||||
|
|
||||||
Printer.UNKNOWN_STATE = "unknown";
|
Printer.WIFIBOX_DISCONNECTED_STATE = "wifibox disconnected";
|
||||||
Printer.DISCONNECTED_STATE = "disconnected";
|
Printer.UNKNOWN_STATE = "unknown"; // happens when a printer is connection but there isn't communication yet
|
||||||
|
Printer.DISCONNECTED_STATE = "disconnected"; // printer disconnected
|
||||||
Printer.IDLE_STATE = "idle"; // printer found, but idle
|
Printer.IDLE_STATE = "idle"; // printer found, but idle
|
||||||
Printer.BUFFERING_STATE = "buffering"; // printer is buffering (recieving) data, but not yet printing
|
Printer.BUFFERING_STATE = "buffering"; // printer is buffering (recieving) data, but not yet printing
|
||||||
Printer.PRINTING_STATE = "printing";
|
Printer.PRINTING_STATE = "printing";
|
||||||
Printer.STOPPING_STATE = "stopping"; // when you stop (abort) a print it prints the endcode
|
Printer.STOPPING_STATE = "stopping"; // when you stop (abort) a print it prints the endcode
|
||||||
|
|
||||||
|
Printer.ON_BEFORE_UNLOAD_MESSAGE = "You're doodle is still being send to the printer, leaving will result in a incomplete 3D print";
|
||||||
|
|
||||||
this.temperature = 0;
|
this.temperature = 0;
|
||||||
this.targetTemperature = 0;
|
this.targetTemperature = 0;
|
||||||
this.currentLine = 0;
|
this.currentLine = 0;
|
||||||
@ -95,6 +98,9 @@ function Printer() {
|
|||||||
console.log("Printer:print");
|
console.log("Printer:print");
|
||||||
console.log(" gcode total # of lines: " + gcode.length);
|
console.log(" gcode total # of lines: " + gcode.length);
|
||||||
|
|
||||||
|
message.set("Sending doodle to printer...",Message.NOTICE);
|
||||||
|
self.addLeaveWarning();
|
||||||
|
|
||||||
/*for (i = 0; i < gcode.length; i++) {
|
/*for (i = 0; i < gcode.length; i++) {
|
||||||
gcode[i] += " (" + i + ")";
|
gcode[i] += " (" + i + ")";
|
||||||
}*/
|
}*/
|
||||||
@ -152,6 +158,8 @@ function Printer() {
|
|||||||
console.log("Printer:sendPrintPart:gcode sending completed");
|
console.log("Printer:sendPrintPart:gcode sending completed");
|
||||||
this.gcode = [];
|
this.gcode = [];
|
||||||
btnStop.css("display","block"); // hack
|
btnStop.css("display","block"); // hack
|
||||||
|
self.removeLeaveWarning();
|
||||||
|
message.set("Doodle is send to printer...",Message.INFO,true);
|
||||||
//self.targetTemperature = settings["printer.temperature"]; // slight hack
|
//self.targetTemperature = settings["printer.temperature"]; // slight hack
|
||||||
} else {
|
} else {
|
||||||
// only if the state hasn't bin changed (by for example pressing stop) we send more gcode
|
// only if the state hasn't bin changed (by for example pressing stop) we send more gcode
|
||||||
@ -234,7 +242,7 @@ function Printer() {
|
|||||||
this.checkStatus = function() {
|
this.checkStatus = function() {
|
||||||
console.log("Printer:checkStatus");
|
console.log("Printer:checkStatus");
|
||||||
this.stateOverruled = false;
|
this.stateOverruled = false;
|
||||||
console.log(" stateOverruled: ",this.stateOverruled);
|
//console.log(" stateOverruled: ",this.stateOverruled);
|
||||||
var self = this;
|
var self = this;
|
||||||
if (communicateWithWifibox) {
|
if (communicateWithWifibox) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@ -242,7 +250,7 @@ function Printer() {
|
|||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
timeout: this.timeoutTime,
|
timeout: this.timeoutTime,
|
||||||
success: function(response){
|
success: function(response){
|
||||||
console.log(" Printer:status: ",response.data.state); //," response: ",response);
|
//console.log(" Printer:status: ",response.data.state); //," response: ",response);
|
||||||
|
|
||||||
self.handleStatusUpdate(response);
|
self.handleStatusUpdate(response);
|
||||||
|
|
||||||
@ -252,26 +260,27 @@ function Printer() {
|
|||||||
}
|
}
|
||||||
}).fail(function() {
|
}).fail(function() {
|
||||||
console.log("Printer:checkStatus: failed");
|
console.log("Printer:checkStatus: failed");
|
||||||
self.state = Printer.UNKNOWN_STATE;
|
self.state = Printer.WIFIBOX_DISCONNECTED_STATE;
|
||||||
clearTimeout(self.checkStatusDelay);
|
clearTimeout(self.checkStatusDelay);
|
||||||
clearTimeout(self.retryCheckStatusDelay);
|
clearTimeout(self.retryCheckStatusDelay);
|
||||||
self.retryCheckStatusDelay = setTimeout(function() { self.checkStatus() },self.retryDelay); // retry after delay
|
self.retryCheckStatusDelay = setTimeout(function() { self.checkStatus() },self.retryDelay); // retry after delay
|
||||||
|
$(document).trigger(Printer.UPDATE);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log ("Printer >> f:checkStatus() >> communicateWithWifibox is false, so not executing this function");
|
console.log ("Printer >> f:checkStatus() >> communicateWithWifibox is false, so not executing this function");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.handleStatusUpdate = function(response) {
|
this.handleStatusUpdate = function(response) {
|
||||||
console.log("Printer:handleStatusUpdate");
|
console.log("Printer:handleStatusUpdate response: ",response);
|
||||||
var data = response.data;
|
var data = response.data;
|
||||||
if(response.status != "success") {
|
if(response.status != "success") {
|
||||||
self.state = Printer.UNKNOWN_STATE;
|
self.state = Printer.UNKNOWN_STATE;
|
||||||
} else {
|
} else {
|
||||||
// state
|
// state
|
||||||
console.log(" stateOverruled: ",this.stateOverruled);
|
//console.log(" stateOverruled: ",this.stateOverruled);
|
||||||
if(!this.stateOverruled) {
|
if(!this.stateOverruled) {
|
||||||
self.state = data.state;
|
self.state = data.state;
|
||||||
console.log(" state > ",self.state);
|
//console.log(" state > ",self.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// temperature
|
// temperature
|
||||||
@ -302,4 +311,13 @@ function Printer() {
|
|||||||
|
|
||||||
this.stopStatusCheckInterval();
|
this.stopStatusCheckInterval();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.removeLeaveWarning = function() {
|
||||||
|
window.onbeforeunload = null;
|
||||||
|
}
|
||||||
|
this.addLeaveWarning = function() {
|
||||||
|
window.onbeforeunload = function() {
|
||||||
|
return Printer.ON_BEFORE_UNLOAD_MESSAGE;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
@ -49,7 +49,7 @@ function Progressbar() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.update = function(part, total) {
|
this.update = function(part, total) {
|
||||||
console.log("Progressbar.update(" + part + "," + total + ")");
|
//console.log("Progressbar.update(" + part + "," + total + ")");
|
||||||
|
|
||||||
var pct = part / total;
|
var pct = part / total;
|
||||||
if (this.isInitted) {
|
if (this.isInitted) {
|
||||||
@ -59,7 +59,7 @@ function Progressbar() {
|
|||||||
var progress = part / total;
|
var progress = part / total;
|
||||||
progress = Math.min(progress, 1.0);
|
progress = Math.min(progress, 1.0);
|
||||||
progress = Math.max(progress, 0);
|
progress = Math.max(progress, 0);
|
||||||
console.log("progressbar >> f:update() >> progress: " + progress);
|
//console.log("progressbar >> f:update() >> progress: " + progress);
|
||||||
|
|
||||||
// clear
|
// clear
|
||||||
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||||
|
@ -113,8 +113,9 @@ function SettingsWindow() {
|
|||||||
this.submitwindow = function(e) {
|
this.submitwindow = function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
self.saveSettings();
|
self.saveSettings(self.readForm(),function(){
|
||||||
self.hideSettings();
|
self.hideSettings();
|
||||||
|
});
|
||||||
|
|
||||||
clearTimeout(self.retryRetrieveNetworkStatusDelay);
|
clearTimeout(self.retryRetrieveNetworkStatusDelay);
|
||||||
}
|
}
|
||||||
@ -146,9 +147,9 @@ function SettingsWindow() {
|
|||||||
url: this.wifiboxURL + "/config/all",
|
url: this.wifiboxURL + "/config/all",
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
timeout: this.timeoutTime,
|
timeout: this.timeoutTime,
|
||||||
success: function(data){
|
success: function(response){
|
||||||
console.log("Settings:loadSettings response: ",data);
|
console.log("Settings:loadSettings response: ",response);
|
||||||
settings = data.data;
|
settings = response.data;
|
||||||
console.log(" settings: ",settings);
|
console.log(" settings: ",settings);
|
||||||
self.fillForm();
|
self.fillForm();
|
||||||
$(document).trigger(SettingsWindow.SETTINGS_LOADED);
|
$(document).trigger(SettingsWindow.SETTINGS_LOADED);
|
||||||
@ -162,45 +163,6 @@ function SettingsWindow() {
|
|||||||
this.refreshNetworks();
|
this.refreshNetworks();
|
||||||
this.retrieveNetworkStatus(false);
|
this.retrieveNetworkStatus(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.saveSettings = function(callback) {
|
|
||||||
console.log("Settings:saveSettings");
|
|
||||||
|
|
||||||
this.readForm();
|
|
||||||
|
|
||||||
if (communicateWithWifibox) {
|
|
||||||
$.ajax({
|
|
||||||
url: this.wifiboxURL + "/config",
|
|
||||||
type: "POST",
|
|
||||||
data: settings,
|
|
||||||
dataType: 'json',
|
|
||||||
timeout: this.timeoutTime,
|
|
||||||
success: function(data){
|
|
||||||
console.log("Settings:saveSettings response: ",data);
|
|
||||||
if(data.status == "error") {
|
|
||||||
clearTimeout(self.retrySaveSettingsDelay);
|
|
||||||
self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
|
|
||||||
} else {
|
|
||||||
var savedSettings = data.data;
|
|
||||||
$.each(savedSettings, function(index, val) {
|
|
||||||
if (val != "ok") {
|
|
||||||
console.log("ERROR: value '" + index + "' not successfully set. Message: " + val);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// TODO something like a callback or feedback that saving went well / or failed
|
|
||||||
if (callback != undefined) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).fail(function() {
|
|
||||||
console.log("Settings:saveSettings: failed");
|
|
||||||
clearTimeout(self.retrySaveSettingsDelay);
|
|
||||||
self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fillForm = function() {
|
this.fillForm = function() {
|
||||||
console.log("SettingsWindow:fillForm");
|
console.log("SettingsWindow:fillForm");
|
||||||
|
|
||||||
@ -232,15 +194,68 @@ function SettingsWindow() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.saveSettings = function(newSettings,complete) {
|
||||||
|
if (communicateWithWifibox) {
|
||||||
|
$.ajax({
|
||||||
|
url: this.wifiboxURL + "/config",
|
||||||
|
type: "POST",
|
||||||
|
data: newSettings,
|
||||||
|
dataType: 'json',
|
||||||
|
timeout: this.timeoutTime,
|
||||||
|
success: function(response){
|
||||||
|
console.log("Settings:saveSettings response: ",response);
|
||||||
|
if(response.status == "error") {
|
||||||
|
clearTimeout(self.retrySaveSettingsDelay);
|
||||||
|
self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings(settings) },self.retryDelay); // retry after delay
|
||||||
|
} else {
|
||||||
|
var data = response.data;
|
||||||
|
var validation = data.validation;
|
||||||
|
self.clearValidationErrors();
|
||||||
|
var validated = true;
|
||||||
|
$.each(validation, function(key, val) {
|
||||||
|
if (val != "ok") {
|
||||||
|
console.log("ERROR: setting '" + key + "' not successfully set. Message: " + val);
|
||||||
|
self.displayValidationError(key,val);
|
||||||
|
validated = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
settings.substituted_ssid = data.substituted_ssid;
|
||||||
|
if(complete && validated) complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).fail(function() {
|
||||||
|
console.log("Settings:saveSettings: failed");
|
||||||
|
clearTimeout(self.retrySaveSettingsDelay);
|
||||||
|
self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings(settings) },self.retryDelay); // retry after delay
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.displayValidationError = function(key,msg) {
|
||||||
|
var formElement = self.form.find("[name|='"+key+"']");
|
||||||
|
console.log("formElement: ",formElement);
|
||||||
|
formElement.addClass("error");
|
||||||
|
var errorMsg = "<p class='errorMsg'>"+msg+"</p>"
|
||||||
|
formElement.after(errorMsg);
|
||||||
|
}
|
||||||
|
this.clearValidationErrors = function() {
|
||||||
|
var formElements = self.form.find(".error");
|
||||||
|
formElements.each( function(index,element) {
|
||||||
|
$(element).removeClass("error");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.readForm = function() {
|
this.readForm = function() {
|
||||||
console.log("SettingsWindow:readForm");
|
//console.log("SettingsWindow:readForm");
|
||||||
var selects = this.form.find("select");
|
var settings = {};
|
||||||
|
var selects = self.form.find("select");
|
||||||
selects.each( function(index,element) {
|
selects.each( function(index,element) {
|
||||||
var element = $(element);
|
var element = $(element);
|
||||||
|
if(element.attr('name') != "network.client.network") {
|
||||||
settings[element.attr('name')] = element.val();
|
settings[element.attr('name')] = element.val();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var inputs = this.form.find("input");
|
var inputs = self.form.find("input");
|
||||||
inputs.each( function(index,element) {
|
inputs.each( function(index,element) {
|
||||||
var element = $(element);
|
var element = $(element);
|
||||||
switch(element.attr("type")) {
|
switch(element.attr("type")) {
|
||||||
@ -254,15 +269,15 @@ function SettingsWindow() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var textareas = this.form.find("textarea");
|
var textareas = self.form.find("textarea");
|
||||||
textareas.each( function(index,element) {
|
textareas.each( function(index,element) {
|
||||||
var element = $(element);
|
var element = $(element);
|
||||||
settings[element.attr('name')] = element.val();
|
settings[element.attr('name')] = element.val();
|
||||||
});
|
});
|
||||||
console.log(settings);
|
//console.log(settings);
|
||||||
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Networks ui
|
* Networks ui
|
||||||
*/
|
*/
|
||||||
@ -379,7 +394,7 @@ function SettingsWindow() {
|
|||||||
var networkSelector = self.form.find("#network");
|
var networkSelector = self.form.find("#network");
|
||||||
networkSelector.val(SettingsWindow.NOT_CONNECTED);
|
networkSelector.val(SettingsWindow.NOT_CONNECTED);
|
||||||
|
|
||||||
if(data.ssid) {
|
if(data.ssid && data.status == SettingsWindow.API_CREATED) {
|
||||||
self.currentAP = data.ssid;
|
self.currentAP = data.ssid;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -473,16 +488,16 @@ function SettingsWindow() {
|
|||||||
case SettingsWindow.CONNECTED:
|
case SettingsWindow.CONNECTED:
|
||||||
btnConnect.removeAttr("disabled");
|
btnConnect.removeAttr("disabled");
|
||||||
|
|
||||||
var fieldText = "Connected to: "+this.currentNetwork+".";
|
var fieldText = "Connected to: <b>"+this.currentNetwork+"</b>.";
|
||||||
if(this.currentLocalIP != undefined && this.currentLocalIP != "") {
|
if(this.currentLocalIP != undefined && this.currentLocalIP != "") {
|
||||||
var a = "<a href='http://"+this.currentLocalIP+"' target='_black'>"+this.currentLocalIP+"</a>";
|
var a = "<a href='http://"+this.currentLocalIP+"' target='_black'>"+this.currentLocalIP+"</a>";
|
||||||
fieldText += " Local ip: "+a;
|
fieldText += " (IP: "+a+")";
|
||||||
}
|
}
|
||||||
field.html(fieldText);
|
field.html(fieldText);
|
||||||
break;
|
break;
|
||||||
case SettingsWindow.CONNECTING:
|
case SettingsWindow.CONNECTING:
|
||||||
btnConnect.attr("disabled", true);
|
btnConnect.attr("disabled", true);
|
||||||
field.html("Connecting...");
|
field.html("Connecting... Reconnect by connecting your device to <b>"+this.selectedNetwork+"</b> and going to <a href='http://connect.doodle3d.com'>connect.doodle3d.com</a>");
|
||||||
break;
|
break;
|
||||||
case SettingsWindow.CONNECTING_FAILED:
|
case SettingsWindow.CONNECTING_FAILED:
|
||||||
btnConnect.removeAttr("disabled");
|
btnConnect.removeAttr("disabled");
|
||||||
@ -501,11 +516,11 @@ function SettingsWindow() {
|
|||||||
break;
|
break;
|
||||||
case SettingsWindow.AP:
|
case SettingsWindow.AP:
|
||||||
btnCreate.removeAttr("disabled");
|
btnCreate.removeAttr("disabled");
|
||||||
field.html("Is access point: "+this.currentAP);
|
field.html("Is access point: <b>"+this.currentAP+"</b>");
|
||||||
break;
|
break;
|
||||||
case SettingsWindow.CREATING_AP:
|
case SettingsWindow.CREATING_AP:
|
||||||
btnCreate.attr("disabled", true);
|
btnCreate.attr("disabled", true);
|
||||||
field.html("Creating access point...");
|
field.html("Creating access point... Reconnect by connecting your device to <b>"+settings.substituted_ssid+"</b> and going to <a href='http://draw.doodle3d.com'>draw.doodle3d.com</a>");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.apModeState = state;
|
this.apModeState = state;
|
||||||
@ -514,13 +529,17 @@ function SettingsWindow() {
|
|||||||
this.connectToNetwork = function() {
|
this.connectToNetwork = function() {
|
||||||
console.log("connectToNetwork");
|
console.log("connectToNetwork");
|
||||||
if(self.selectedNetwork == undefined) return;
|
if(self.selectedNetwork == undefined) return;
|
||||||
postData = {
|
var postData = {
|
||||||
ssid:self.selectedNetwork,
|
ssid:self.selectedNetwork,
|
||||||
phrase:self.form.find("#password").val(),
|
phrase:self.form.find("#password").val(),
|
||||||
recreate:true
|
recreate:true
|
||||||
}
|
}
|
||||||
console.log(" postData: ",postData);
|
console.log(" postData: ",postData);
|
||||||
if (communicateWithWifibox) {
|
if (communicateWithWifibox) {
|
||||||
|
|
||||||
|
// save network related settings and on complete, connect to network
|
||||||
|
self.saveSettings(self.readForm(),function() {
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: self.wifiboxCGIBinURL + "/network/associate",
|
url: self.wifiboxCGIBinURL + "/network/associate",
|
||||||
type: "POST",
|
type: "POST",
|
||||||
@ -535,6 +554,7 @@ function SettingsWindow() {
|
|||||||
//clearTimeout(self.retrySaveSettingsDelay);
|
//clearTimeout(self.retrySaveSettingsDelay);
|
||||||
//self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
|
//self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
self.setClientModeState(SettingsWindow.CONNECTING,"");
|
self.setClientModeState(SettingsWindow.CONNECTING,"");
|
||||||
|
|
||||||
@ -545,7 +565,12 @@ function SettingsWindow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.createAP = function() {
|
this.createAP = function() {
|
||||||
|
console.log("createAP");
|
||||||
if (communicateWithWifibox) {
|
if (communicateWithWifibox) {
|
||||||
|
|
||||||
|
// save network related settings and on complete, create access point
|
||||||
|
self.saveSettings(self.readForm(),function() {
|
||||||
|
self.setAPModeState(SettingsWindow.CREATING_AP); // get latest substituted ssid
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: self.wifiboxCGIBinURL + "/network/openap",
|
url: self.wifiboxCGIBinURL + "/network/openap",
|
||||||
type: "POST",
|
type: "POST",
|
||||||
@ -553,20 +578,21 @@ function SettingsWindow() {
|
|||||||
timeout: self.timeoutTime,
|
timeout: self.timeoutTime,
|
||||||
success: function(response){
|
success: function(response){
|
||||||
console.log("Settings:createAP response: ",response);
|
console.log("Settings:createAP response: ",response);
|
||||||
|
|
||||||
}
|
}
|
||||||
}).fail(function() {
|
}).fail(function() {
|
||||||
console.log("Settings:createAP: timeout (normal behavior)");
|
console.log("Settings:createAP: timeout (normal behavior)");
|
||||||
//clearTimeout(self.retrySaveSettingsDelay);
|
//clearTimeout(self.retrySaveSettingsDelay);
|
||||||
//self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
|
//self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
|
||||||
});
|
});
|
||||||
}
|
|
||||||
self.setAPModeState(SettingsWindow.CREATING_AP,"");
|
self.setAPModeState(SettingsWindow.CREATING_AP,"");
|
||||||
|
|
||||||
// after switching wifi network or creating a access point we delay the status retrieval
|
// after switching wifi network or creating a access point we delay the status retrieval
|
||||||
// because the webserver needs time to switch
|
// because the webserver needs time to switch
|
||||||
clearTimeout(self.retrieveNetworkStatusDelay);
|
clearTimeout(self.retrieveNetworkStatusDelay);
|
||||||
self.retrieveNetworkStatusDelay = setTimeout(function() { self.retrieveNetworkStatus(true) },self.retrieveNetworkStatusDelayTime);
|
self.retrieveNetworkStatusDelay = setTimeout(function() { self.retrieveNetworkStatus(true) },self.retrieveNetworkStatusDelayTime);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ var btnOops, btnStop, btnClear;
|
|||||||
var btnMoveUp, btnMoveDown, btnTwistLeft, btnTwistRight;
|
var btnMoveUp, btnMoveDown, btnTwistLeft, btnTwistRight;
|
||||||
var btnInfo, btnSettings;
|
var btnInfo, btnSettings;
|
||||||
//var btnDebug; // debug
|
//var btnDebug; // debug
|
||||||
var displayTemp, displayProgress;
|
|
||||||
|
|
||||||
var state;
|
var state;
|
||||||
var prevState;
|
var prevState;
|
||||||
@ -35,8 +34,6 @@ function initButtonBehavior() {
|
|||||||
btnNew = $(".btnNew");
|
btnNew = $(".btnNew");
|
||||||
btnPrint= $(".btnPrint");
|
btnPrint= $(".btnPrint");
|
||||||
btnStop = $(".btnStop");
|
btnStop = $(".btnStop");
|
||||||
displayTemp = $("#thermometerContainer");
|
|
||||||
displayProgress = $("#printProgressContainer");
|
|
||||||
|
|
||||||
btnPrevious = $(".btnPrevious");
|
btnPrevious = $(".btnPrevious");
|
||||||
btnNext = $(".btnNext");
|
btnNext = $(".btnNext");
|
||||||
@ -317,13 +314,15 @@ function update() {
|
|||||||
setState(printer.state,printer.hasControl);
|
setState(printer.state,printer.hasControl);
|
||||||
|
|
||||||
thermometer.update(printer.temperature, printer.targetTemperature);
|
thermometer.update(printer.temperature, printer.targetTemperature);
|
||||||
//TODO: update progress
|
progressbar.update(printer.currentLine, printer.totalLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setState(newState,newHasControl) { //TODO add hasControl
|
function setState(newState,newHasControl) {
|
||||||
if(newState == state && newHasControl == hasControl) return;
|
if(newState == state && newHasControl == hasControl) return;
|
||||||
|
|
||||||
console.log("setState: ",state," > ",newState," ( ",newHasControl,")");
|
prevState = state;
|
||||||
|
|
||||||
|
console.log("setState: ",prevState," > ",newState," ( ",newHasControl,")");
|
||||||
setDebugText("State: "+newState);
|
setDebugText("State: "+newState);
|
||||||
|
|
||||||
// print button
|
// print button
|
||||||
@ -350,26 +349,38 @@ function setState(newState,newHasControl) { //TODO add hasControl
|
|||||||
|
|
||||||
// thermometer
|
// thermometer
|
||||||
switch(newState) {
|
switch(newState) {
|
||||||
case Printer.UNKNOWN_STATE:
|
case Printer.IDLE_STATE:
|
||||||
case Printer.DISCONNECTED_STATE:
|
case Printer.BUFFERING_STATE:
|
||||||
thermometer.hide();
|
case Printer.PRINTING_STATE:
|
||||||
|
case Printer.STOPPING_STATE:
|
||||||
|
thermometer.show();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
thermometer.show();
|
thermometer.hide();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// progress indicator
|
// progress indicator
|
||||||
switch(newState) {
|
switch(newState) {
|
||||||
case Printer.PRINTING_STATE:
|
case Printer.PRINTING_STATE:
|
||||||
displayProgress.show(); // TODO: Show progress
|
progressbar.show();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
displayProgress.hide(); // TODO: hide progress
|
progressbar.hide();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
prevState = state;
|
if(newState == Printer.WIFIBOX_DISCONNECTED_STATE) {
|
||||||
|
message.set("Lost connection to WiFi box",Message.ERROR);
|
||||||
|
} else if(prevState == Printer.WIFIBOX_DISCONNECTED_STATE) {
|
||||||
|
message.set("Connected to WiFi box",Message.INFO,true);
|
||||||
|
} else if(newState == Printer.DISCONNECTED_STATE) {
|
||||||
|
message.set("Printer disconnected",Message.WARNING,true);
|
||||||
|
} else if(prevState == Printer.DISCONNECTED_STATE && newState == Printer.IDLE_STATE ||
|
||||||
|
prevState == Printer.UNKNOWN_STATE && newState == Printer.IDLE_STATE) {
|
||||||
|
message.set("Printer connected",Message.INFO,true);
|
||||||
|
}
|
||||||
|
|
||||||
state = newState;
|
state = newState;
|
||||||
hasControl = newHasControl;
|
hasControl = newHasControl;
|
||||||
}
|
}
|
||||||
|
@ -31,39 +31,6 @@ var gcode = [];
|
|||||||
function generate_gcode() {
|
function generate_gcode() {
|
||||||
console.log("f:generategcode()");
|
console.log("f:generategcode()");
|
||||||
|
|
||||||
var startGcode = [];
|
|
||||||
var endGcode = [];
|
|
||||||
|
|
||||||
// get gcode start statements
|
|
||||||
/*console.log("settings['printer.startgcode']: ",settings["printer.startgcode"]);
|
|
||||||
console.log("settings['printer.endgcode']: ",settings["printer.endgcode"]);
|
|
||||||
|
|
||||||
if ($("#startgcode").val().trim().length != 0) {
|
|
||||||
console.log(" found contents for start-gcode in settings.html")
|
|
||||||
startGcode = $("#startgcode").val().trim().split("\n");
|
|
||||||
} else {
|
|
||||||
console.log(" no start-gcode in settings.html, using defaults")
|
|
||||||
startGcode = startGcode.concat(gcodeStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get gcode end statements
|
|
||||||
if ($("#endgcode").val().trim().length != 0) {
|
|
||||||
console.log(" found contents for end-gcode in settings.html")
|
|
||||||
endGcode = $("#endgcode").val().trim().split("\n");
|
|
||||||
} else {
|
|
||||||
console.log(" no end-gcode in settings.html, using defaults")
|
|
||||||
endGcode = endGcode.concat(gcodeEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("f:generate_gcode() >> startGcode:");
|
|
||||||
console.log(startGcode);
|
|
||||||
console.log("");
|
|
||||||
console.log("f:generate_gcode() >> endGcode:");
|
|
||||||
console.log(endGcode);*/
|
|
||||||
|
|
||||||
startGcode = settings["printer.startgcode"].split("\n");
|
|
||||||
endGcode = settings["printer.endgcode"].split("\n");
|
|
||||||
|
|
||||||
// TODO 2013-09-18 evaluate if this should stay here
|
// TODO 2013-09-18 evaluate if this should stay here
|
||||||
// this was added when Rick mailed us wrt the Ultimaker delivery of Doodle3D
|
// this was added when Rick mailed us wrt the Ultimaker delivery of Doodle3D
|
||||||
var gCodeOffsetX = 110; // mm
|
var gCodeOffsetX = 110; // mm
|
||||||
@ -88,6 +55,17 @@ function generate_gcode() {
|
|||||||
var retractionspeed = settings["printer.retraction.speed"];
|
var retractionspeed = settings["printer.retraction.speed"];
|
||||||
var retractionminDistance = settings["printer.retraction.minDistance"];
|
var retractionminDistance = settings["printer.retraction.minDistance"];
|
||||||
var retractionamount = settings["printer.retraction.amount"];
|
var retractionamount = settings["printer.retraction.amount"];
|
||||||
|
var preheatTemperature = settings["printer.heatup.temperature"];
|
||||||
|
|
||||||
|
var startGcode = settings["printer.startgcode"];
|
||||||
|
startGcode = startGcode.replace("{printingTemp}",temperature);
|
||||||
|
startGcode = startGcode.replace("{preheatTemp}",preheatTemperature);
|
||||||
|
startGcode = startGcode.split("\n");
|
||||||
|
|
||||||
|
var endGcode = settings["printer.endgcode"];
|
||||||
|
endGcode = endGcode.replace("{printingTemp}",temperature);
|
||||||
|
endGcode = endGcode.replace("{preheatTemp}",preheatTemperature);
|
||||||
|
endGcode = endGcode.split("\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
console.log("f:generate_gcode >> EFFE CHECKEN:");
|
console.log("f:generate_gcode >> EFFE CHECKEN:");
|
||||||
@ -131,9 +109,9 @@ function generate_gcode() {
|
|||||||
// console.log("paths.toString(): " + paths.toString());
|
// console.log("paths.toString(): " + paths.toString());
|
||||||
// return;
|
// return;
|
||||||
|
|
||||||
console.log("printer temperature: ",temperature);
|
|
||||||
//gcode.push("M104 S" + temperature); // set target temperature and do not wait for the extruder to reach it
|
//gcode.push("M104 S" + temperature); // set target temperature and do not wait for the extruder to reach it
|
||||||
gcode.push("M109 S" + temperature); // set target temperature and wait for the extruder to reach it
|
//gcode.push("M109 S" + temperature); // set target temperature and wait for the extruder to reach it
|
||||||
|
|
||||||
// add gcode begin commands
|
// add gcode begin commands
|
||||||
gcode = gcode.concat(startGcode);
|
gcode = gcode.concat(startGcode);
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ var printer = new Printer();
|
|||||||
var progressbar = new Progressbar();
|
var progressbar = new Progressbar();
|
||||||
var thermometer = new Thermometer();
|
var thermometer = new Thermometer();
|
||||||
var settingsWindow = new SettingsWindow();
|
var settingsWindow = new SettingsWindow();
|
||||||
|
var message = new Message();
|
||||||
|
|
||||||
var firstTimeSettingsLoaded = true;
|
var firstTimeSettingsLoaded = true;
|
||||||
|
|
||||||
@ -53,10 +54,9 @@ $(function() {
|
|||||||
initVerticalShapes();
|
initVerticalShapes();
|
||||||
|
|
||||||
thermometer.init($("#thermometerCanvas"), $("#thermometerContainer"));
|
thermometer.init($("#thermometerCanvas"), $("#thermometerContainer"));
|
||||||
|
|
||||||
progressbar = new Progressbar();
|
|
||||||
progressbar.init($("#progressbarCanvas"), $("#progressbarCanvasContainer"));
|
progressbar.init($("#progressbarCanvas"), $("#progressbarCanvasContainer"));
|
||||||
|
|
||||||
|
message.init($("#message"));
|
||||||
|
|
||||||
printer.init();
|
printer.init();
|
||||||
$(document).on(Printer.UPDATE,update);
|
$(document).on(Printer.UPDATE,update);
|
||||||
|
52
js/message.js
Normal file
52
js/message.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
function Message() {
|
||||||
|
|
||||||
|
Message.ERROR = "error";
|
||||||
|
Message.WARNING = "warning";
|
||||||
|
Message.NOTICE = "notice";
|
||||||
|
Message.INFO = "info";
|
||||||
|
|
||||||
|
this.mode = "";
|
||||||
|
|
||||||
|
this.$element;
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
var autoHideDelay = 2000;
|
||||||
|
var autohideTimeout;
|
||||||
|
|
||||||
|
this.init = function($element) {
|
||||||
|
console.log("Message:init");
|
||||||
|
|
||||||
|
this.$element = $element;
|
||||||
|
console.log("$element: ",$element);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.set = function(text,mode,autoHide) {
|
||||||
|
console.log("Message:set: ",text,mode,autoHide);
|
||||||
|
self.hide(function() {
|
||||||
|
self.show();
|
||||||
|
self.clear();
|
||||||
|
|
||||||
|
self.$element.text(text);
|
||||||
|
self.$element.addClass(mode);
|
||||||
|
self.show();
|
||||||
|
|
||||||
|
self.mode = mode;
|
||||||
|
|
||||||
|
clearTimeout(autohideTimeout);
|
||||||
|
if(autoHide) {
|
||||||
|
autohideTimeout = setTimeout(function(){ self.hide()},autoHideDelay);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.clear = function($element) {
|
||||||
|
this.$element.text("");
|
||||||
|
this.$element.removeClass(this.mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.show = function() {
|
||||||
|
this.$element.fadeIn(200);
|
||||||
|
}
|
||||||
|
this.hide = function(complete) {
|
||||||
|
this.$element.fadeOut(200,complete);
|
||||||
|
}
|
||||||
|
}
|
31
less/message.less
Normal file
31
less/message.less
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#message {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
padding: 0.4em 0.5em;
|
||||||
|
border-radius: 0 0 0 10px;
|
||||||
|
border: 2px solid #333;
|
||||||
|
border-width: 0 0 2px 2px;
|
||||||
|
font-weight: bold;
|
||||||
|
box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);
|
||||||
|
|
||||||
|
color: #333;
|
||||||
|
white-space:nowrap;
|
||||||
|
|
||||||
|
display:none;
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
background: #EB313C;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
&.warning {
|
||||||
|
background: #E9A86E;
|
||||||
|
}
|
||||||
|
&.notice {
|
||||||
|
background: #93CAF4;
|
||||||
|
}
|
||||||
|
&.info {
|
||||||
|
background: #97DD8A;
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
//@import "normalize.min.less";
|
//@import "normalize.min.less";
|
||||||
@import "base.less";
|
@import "base.less";
|
||||||
@import "settingsPopup.less";
|
@import "settingsPopup.less";
|
||||||
|
@import "message.less";
|
||||||
|
|
||||||
|
|
||||||
// MOBILE
|
// MOBILE
|
||||||
|
@ -97,16 +97,23 @@
|
|||||||
<legend>Access point settings</legend>
|
<legend>Access point settings</legend>
|
||||||
<label for="ssid">Wi-Fi box ssid*:</label><input type="text" class="large" name="network.ap.ssid" id="ssid"> <br>
|
<label for="ssid">Wi-Fi box ssid*:</label><input type="text" class="large" name="network.ap.ssid" id="ssid"> <br>
|
||||||
<small>* The text <em>%%MAC_ADDR_TAIL%%</em> will be replaced by the last 6 digits of your Doodle3D Wi-Fi box's MAC address.</small>
|
<small>* The text <em>%%MAC_ADDR_TAIL%%</em> will be replaced by the last 6 digits of your Doodle3D Wi-Fi box's MAC address.</small>
|
||||||
|
<br>
|
||||||
<label for="apKey">Password:</label><input type="text" class="large" name="network.ap.key" id="apKey"> <br>
|
<label for="apKey">Password:</label><input type="text" class="large" name="network.ap.key" id="apKey"> <br>
|
||||||
<label for="ipaddress">Wi-Fi box IP address:</label><input type="text" name="network.ap.address" id="ipaddress"><br>
|
<label for="ipaddress">Wi-Fi box IP address:</label><input type="text" name="network.ap.address" id="ipaddress"><br>
|
||||||
<label for="netmask">Wi-Fi box netmask:</label><input type="text" name="network.ap.netmask" id="netmask"><br>
|
<label for="netmask">Wi-Fi box netmask:</label><input type="text" name="network.ap.netmask" id="netmask"><br>
|
||||||
<input type="button" name="create" value="Create" class="button" id="createAP"/>
|
<input type="button" name="create" value="Create" class="button" id="createAP"/>
|
||||||
<span id="apModeState"></span>
|
<span id="apModeState"></span><br/>
|
||||||
|
<br/>
|
||||||
|
<small>When you can't connect to your device, you can always use an ethernet cable and go to <a href="http://connect.doodle3d.com">connect.doodle3d.com</a>.</small>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset id="clientSettings">
|
<fieldset id="clientSettings">
|
||||||
<legend>Client mode settings</legend>
|
<legend>Client mode settings</legend>
|
||||||
|
|
||||||
|
<label for="wifiboxid">Wi-Fi box id*:</label><input type="text" name="network.cl.wifiboxid" id="wifiboxid"><br>
|
||||||
|
<small>* Is used on <a href="http://connect.doodle3d.com">connect.doodle3d.com</a>. <br/>
|
||||||
|
The text <em>%%MAC_ADDR_TAIL%%</em> will be replaced by the last 6 digits of your Doodle3D Wi-Fi box's MAC address.</small>
|
||||||
|
<br>
|
||||||
<label for="network">Network:</label>
|
<label for="network">Network:</label>
|
||||||
<select id="network" name="network.client.network">
|
<select id="network" name="network.client.network">
|
||||||
</select>
|
</select>
|
||||||
@ -115,9 +122,7 @@
|
|||||||
<input type="button" name="connect" value="Connect" class="button" id="connectToNetwork"/>
|
<input type="button" name="connect" value="Connect" class="button" id="connectToNetwork"/>
|
||||||
<span id="clientModeState"></span><br/>
|
<span id="clientModeState"></span><br/>
|
||||||
<br/>
|
<br/>
|
||||||
<label for="wifiboxid">Wi-Fi box id*:</label><input type="text" name="network.cl.wifiboxid" id="wifiboxid"><br>
|
<small>When you can't connect to your device, you can always use an ethernet cable and go to <a href="http://connect.doodle3d.com">connect.doodle3d.com</a>.</small>
|
||||||
<small>* Is used on <a href="http://connect.doodle3d.com">connect.doodle3d.com</a>. <br/>
|
|
||||||
The text <em>%%MAC_ADDR_TAIL%%</em> will be replaced by the last 6 digits of your Doodle3D Wi-Fi box's MAC address.</small>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
@ -134,23 +139,7 @@
|
|||||||
<textarea id="endgcode" class="gcode" name="printer.endgcode">
|
<textarea id="endgcode" class="gcode" name="printer.endgcode">
|
||||||
</textarea>
|
</textarea>
|
||||||
</div>
|
</div>
|
||||||
<!-- 2013-10-09 replaced by DIV solution (but keeping here in comments temporarily as lookup...)
|
<small>The text <em>{printingTemp}</em> will be replaced by the printing temperature and <em>{preheatTemp}</em> will be replaced by the preaheat temperature.</small>
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<label for="startgcode">Start:</label><br>
|
|
||||||
<textarea id="startgcode" class="gcode" name="printer.startgcode">
|
|
||||||
</textarea>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<label for="endgcode">End:</label><br>
|
|
||||||
<textarea id="endgcode" class="gcode" name="printer.endgcode">
|
|
||||||
</textarea>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
-->
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form><br/>
|
</form><br/>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user