Skip to content

Commit b6afda1

Browse files
committed
Remove the Python GUI window to select sketch or compiler paths
Before this change when the "compiler" or "sketch" options were selected in the settings the server launched a GUI file or folder browser window to get the user to navigate the server filesystem. This means that the server needed to be run on a desktop environment and this feature of the application could only be used in the same computer that is executing the Python server. This commit removes this GUI window from the Python server, it now expects the path to be sent from the front end interface. So for the text inputs the user has to manually enter the file or directory paths. This can then be extended to either offer a file browser in the html page, or to add Electron hooks to use the native application browser.
1 parent dce68b1 commit b6afda1

File tree

9 files changed

+232
-370
lines changed

9 files changed

+232
-370
lines changed

ardublockly/ardublockly.js

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -93,18 +93,32 @@ Ardublockly.bindActionFunctions = function() {
9393
Ardublockly.bindClick_('button_toggle_toolbox', Ardublockly.toogleToolbox);
9494

9595
// Settings modal input field listeners
96-
Ardublockly.bindClick_('settings_compiler_location', function() {
97-
ArdublocklyServer.requestNewCompilerLocation(function(jsonObj) {
98-
Ardublockly.setCompilerLocationHtml(
99-
ArdublocklyServer.jsonToHtmlTextInput(jsonObj));
100-
});
101-
});
102-
Ardublockly.bindClick_('settings_sketch_location', function() {
103-
ArdublocklyServer.requestNewSketchLocation(function(jsonObj) {
104-
Ardublockly.setSketchLocationHtml(
105-
ArdublocklyServer.jsonToHtmlTextInput(jsonObj));
106-
});
107-
});
96+
var settingsPathInputListeners = function(elId, setValFunc, setHtmlCallback) {
97+
var el = document.getElementById(elId);
98+
// Event listener that send the data when the user presses 'Enter'
99+
el.onkeypress = function(e) {
100+
if (!e) e = window.event;
101+
var keyCode = e.keyCode || e.which;
102+
if (keyCode == '13') {
103+
setValFunc(el.value, function(jsonObj) {
104+
setHtmlCallback(ArdublocklyServer.jsonToHtmlTextInput(jsonObj));
105+
});
106+
return false;
107+
}
108+
};
109+
// Event listener that send the data when moving out of the input field
110+
el.onblur = function(e) {
111+
setValFunc(el.value, function(jsonObj) {
112+
setHtmlCallback(ArdublocklyServer.jsonToHtmlTextInput(jsonObj));
113+
});
114+
};
115+
};
116+
settingsPathInputListeners('settings_compiler_location',
117+
ArdublocklyServer.setCompilerLocation,
118+
Ardublockly.setCompilerLocationHtml);
119+
settingsPathInputListeners('settings_sketch_location',
120+
ArdublocklyServer.setSketchLocation,
121+
Ardublockly.setSketchLocationHtml);
108122
};
109123

110124
/** Sets the Ardublockly server IDE setting to upload and sends the code. */
@@ -358,8 +372,11 @@ Ardublockly.setCompilerLocationHtml = function(newEl) {
358372
if (newEl === null) return Ardublockly.openNotConnectedModal();
359373

360374
var compLocIp = document.getElementById('settings_compiler_location');
361-
if (compLocIp != null && newEl.value) {
362-
compLocIp.value = newEl.value;
375+
if (compLocIp != null) {
376+
if (newEl.value) {
377+
compLocIp.value = newEl.value;
378+
}
379+
compLocIp.style.cssText = newEl.style.cssText;
363380
}
364381
};
365382

@@ -373,7 +390,10 @@ Ardublockly.setSketchLocationHtml = function(newEl) {
373390

374391
var sketchLocIp = document.getElementById('settings_sketch_location');
375392
if (sketchLocIp != null) {
376-
sketchLocIp.value = newEl.value;
393+
if (newEl.value) {
394+
sketchLocIp.value = newEl.value;
395+
}
396+
sketchLocIp.style.cssText = newEl.style.cssText;
377397
}
378398
};
379399

ardublockly/ardublocklyserver_ajax.js

Lines changed: 42 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,31 @@ ArdublocklyServer.putJson = function(url, json, callback) {
2929
};
3030

3131
/**
32-
* Sends a request to the Ardubloockly Server.
32+
* Sends a request to the Ardubloockly Server that returns a JSON response.
3333
* @param {!string} url Requestor URL.
3434
* @param {!string} method HTTP method.
3535
* @param {!string} contentType HTTP content type.
36-
* @param {string} data Plain text JSON content to send.
37-
* @param {!function} cb Request callback function.
36+
* @param {string} jsonObjSend JavaScript object to be parsed into JSON to send.
37+
* @param {!function} cb Request callback function, takes a single input for a
38+
* parsed JSON object.
3839
*/
39-
ArdublocklyServer.sendRequest = function(url, method, contentType, data, cb) {
40+
ArdublocklyServer.sendRequest = function(
41+
url, method, contentType, jsonObjSend, cb) {
4042
var request = ArdublocklyServer.createRequest();
4143

4244
// The data received is JSON, so it needs to be converted into the right
4345
// format to be displayed in the page.
4446
var onReady = function() {
4547
if (request.readyState == 4) {
4648
if (request.status == 200) {
47-
var jsonObj = null;
49+
var jsonObjReceived = null;
4850
try {
49-
jsonObj = JSON.parse(request.responseText);
51+
jsonObjReceived = JSON.parse(request.responseText);
5052
} catch(e) {
5153
console.error('Incorrectly formatted JSON data from ' + url);
5254
throw e;
5355
}
54-
cb(jsonObj);
56+
cb(jsonObjReceived);
5557
} else {
5658
// return a null element which will be dealt with in the front end
5759
cb(null);
@@ -63,7 +65,7 @@ ArdublocklyServer.sendRequest = function(url, method, contentType, data, cb) {
6365
request.open(method, url, true);
6466
request.setRequestHeader('Content-type', contentType);
6567
request.onreadystatechange = onReady;
66-
request.send(data);
68+
request.send(JSON.stringify(jsonObjSend));
6769
} catch (e) {
6870
// Nullify callback to indicate error
6971
cb(null);
@@ -171,8 +173,14 @@ ArdublocklyServer.jsonToHtmlTextInput = function(jsonObj) {
171173
// Simple text input
172174
element = document.createElement('input');
173175
element.setAttribute('type', 'text');
174-
element.setAttribute(
175-
'value', jsonObj.selected || 'Please insert valid input here.');
176+
element.style.cssText = '';
177+
if (jsonObj.errors) {
178+
element.setAttribute('value', '');
179+
element.style.cssText = 'border-bottom: 1px solid #f75c51;' +
180+
'box-shadow: 0 1px 0 0 #d73c30;';
181+
} else {
182+
element.setAttribute('value', jsonObj.selected || '');
183+
}
176184
}
177185
return element;
178186
};
@@ -204,47 +212,41 @@ ArdublocklyServer.jsonToHtmlDropdown = function(jsonObj) {
204212
/**
205213
* Gets the current Compiler location from the ArdublocklyServer settings.
206214
* @param {!function} callback Callback function for the server request, must
207-
* one argument to receive the new location within
208-
* an HTML element of type input text.
215+
* have one argument to receive the JSON response.
209216
*/
210217
ArdublocklyServer.requestCompilerLocation = function(callback) {
211218
ArdublocklyServer.getJson('/settings/compiler', callback);
212219
};
213220

214221
/**
215-
* Request to the Ardublockly Server to prompt the user for a new compiler
216-
* location. Done by the Python server because a 'file browse' triggered by
217-
* the browser with JS will obscure the user information for security reasons.
222+
* Sends a string to the Ardublockly Server for a the Arduino IDE executable
223+
* path.
218224
* @param {!function} callback Callback function for the server request, must
219-
* one argument to receive the new location within
220-
* an HTML element of type input text.
225+
* have one argument to receive the JSON response.
221226
*/
222-
ArdublocklyServer.requestNewCompilerLocation = function(callback) {
227+
ArdublocklyServer.setCompilerLocation = function(new_path, callback) {
223228
ArdublocklyServer.putJson(
224-
'/settings/compiler', '{ "new_value": "TODO replace this" }', callback);
229+
'/settings/compiler', {"new_value": new_path}, callback);
225230
};
226231

227232
/**
228233
* Gets the current Sketch location from the Ardublockly Server settings.
229234
* @param {!function} callback Callback function for the server request, must
230-
* one argument to receive the new location within
231-
* an HTML element of type input text.
235+
* have one argument to receive the JSON response.
232236
*/
233237
ArdublocklyServer.requestSketchLocation = function(callback) {
234238
ArdublocklyServer.getJson('/settings/sketch', callback);
235239
};
236240

237241
/**
238-
* Request to the Ardublockly Server to prompt the user for a new sketch
239-
* location. Done by the Python server because a 'file browse' triggered by
240-
* the browser with JS will obscure the user information for security reasons.
242+
* Sends a string to the Ardublockly Server for a the Arduino sketch folder.
243+
* @param {!string} new_path New Sketch location path..
241244
* @param {!function} callback Callback function for the server request, must
242-
* have one argument to receive the new location
243-
* within an HTML element of type input text.
245+
* have one argument to receive the JSON response.
244246
*/
245-
ArdublocklyServer.requestNewSketchLocation = function(callback) {
247+
ArdublocklyServer.setSketchLocation = function(new_path, callback) {
246248
ArdublocklyServer.putJson(
247-
'/settings/sketch', '{ "new_value": "TODO replace this" }', callback);
249+
'/settings/sketch', {"new_value": new_path}, callback);
248250
};
249251

250252
/**
@@ -253,8 +255,7 @@ ArdublocklyServer.requestNewSketchLocation = function(callback) {
253255
* The data is then processed into an HTML element and sent to the callback
254256
* function as an argument.
255257
* @param {!function} callback Callback function for the server request, must
256-
* have one argument to receive the new setting as
257-
* an HTML select element.
258+
* have one argument to receive the JSON response.
258259
*/
259260
ArdublocklyServer.requestArduinoBoards = function(callback) {
260261
ArdublocklyServer.getJson('/settings/board', callback);
@@ -266,12 +267,11 @@ ArdublocklyServer.requestArduinoBoards = function(callback) {
266267
* element and sent to the callback function as an argument.
267268
* @param {!string} new_board Indicates which board has been selected.
268269
* @param {!function} callback Callback function for the server request, must
269-
* have one argument to receive the new setting as
270-
* an HTML select element.
270+
* have one argument to receive the JSON response.
271271
*/
272272
ArdublocklyServer.setArduinoBoard = function(new_board, callback) {
273273
ArdublocklyServer.putJson(
274-
'/settings/board', '{ "new_value": "' + new_board + '" }', callback);
274+
'/settings/board', {"new_value": new_board}, callback);
275275
};
276276

277277
/**
@@ -280,8 +280,7 @@ ArdublocklyServer.setArduinoBoard = function(new_board, callback) {
280280
* settings. The data is then processed into an HTML element and sent to the
281281
* callback function as an argument.
282282
* @param {!function} callback Callback function for the server request, must
283-
* have one argument to receive the new setting as
284-
* an HTML select element.
283+
* have one argument to receive the JSON response.
285284
*/
286285
ArdublocklyServer.requestSerialPorts = function(callback) {
287286
ArdublocklyServer.getJson('/settings/serial', callback);
@@ -293,21 +292,19 @@ ArdublocklyServer.requestSerialPorts = function(callback) {
293292
* and sent to the callback function as an argument.
294293
* @param {!string} new_port Indicates which port has been selected.
295294
* @param {!function} callback Callback function for the server request, must
296-
* have one argument to receive the new setting as
297-
* an HTML select element.
295+
* have one argument to receive the JSON response.
298296
*/
299297
ArdublocklyServer.setSerialPort = function(new_port, callback) {
300298
ArdublocklyServer.putJson(
301-
'/settings/serial','{ "new_value": "' + new_port + '" }', callback);
299+
'/settings/serial', {"new_value": new_port}, callback);
302300
};
303301

304302
/**
305303
* Gets the current IDE setting from the Ardublockly Server settings. The new
306304
* settings menu for the IDE options is then processed into an HTML element
307305
* and sent to the callback function as an argument.
308306
* @param {!function} callback Callback function for the server request, must
309-
* have one argument to receive the new setting as
310-
* an HTML select element.
307+
* have one argument to receive the JSON response.
311308
*/
312309
ArdublocklyServer.requestIdeOptions = function(callback) {
313310
ArdublocklyServer.getJson('/settings/ide', callback);
@@ -319,12 +316,11 @@ ArdublocklyServer.requestIdeOptions = function(callback) {
319316
* and sent to the callback function as an argument.
320317
* @param {!string} ide_option Indicates which option has been selected.
321318
* @param {!function} callback Callback function for the server request, must
322-
* have one argument to receive the new setting as
323-
* an HTML select element.
319+
* have one argument to receive the JSON response.
324320
*/
325321
ArdublocklyServer.setIdeOptions = function(ide_option, callback) {
326322
ArdublocklyServer.putJson(
327-
'/settings/ide','{ "new_value": "' + ide_option + '" }', callback);
323+
'/settings/ide', {"new_value": ide_option}, callback);
328324
};
329325

330326

@@ -333,11 +329,9 @@ ArdublocklyServer.setIdeOptions = function(ide_option, callback) {
333329
* by the settings.
334330
* @param {!string} code Arduino code in a single string format.
335331
* @param {!function} callback Callback function for the server request, must
336-
* have one argument to receive the new setting as
337-
* an HTML select element.
332+
* have one argument to receive the JSON response.
338333
*/
339334
ArdublocklyServer.sendSketchToServer = function(code, callback) {
340-
ArdublocklyServer.sendRequest('/code', 'POST', 'application/json',
341-
JSON.stringify({"sketch_code": code}),
342-
callback);
335+
ArdublocklyServer.sendRequest(
336+
'/code', 'POST', 'application/json', {"sketch_code": code}, callback);
343337
};

ardublockly/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,11 @@
217217
<h4><span class="translatable_settings">Settings</span></h4>
218218
<div class="modal_section">
219219
<label><span class="translatable_compilerLocation">Compiler Location</span>:</label>
220-
<input type="text" id="settings_compiler_location" readonly>
220+
<input type="text" id="settings_compiler_location">
221221
</div>
222222
<div class="modal_section">
223223
<label><span class="translatable_sketchFolder">Sketch Folder</span>:</label>
224-
<input type="text" id="settings_sketch_location" readonly>
224+
<input type="text" id="settings_sketch_location">
225225
</div>
226226
<div class="modal_section">
227227
<label><span class="translatable_arduinoBoard">Arduino Board</span>:</label>

ardublocklyserver/actions.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
# This package modules
1616
from ardublocklyserver.compilersettings import ServerCompilerSettings
1717
from ardublocklyserver import sketchcreator
18-
import ardublocklyserver.gui as gui
1918

2019

2120
#
@@ -146,16 +145,15 @@ def load_arduino_cli(sketch_path):
146145
#
147146
# Compiler Settings
148147
#
149-
def set_compiler_path():
148+
def set_compiler_path(new_path):
150149
"""Open the file browser to select an Arduino IDE executable.
151150
152151
The new file path is saved into ServerCompilerSettings.
153152
153+
:param new_path: New path for the Arduino IDE executable.
154154
:return: Same as get_compiler_path().
155155
"""
156-
new_path = gui.browse_file_dialog()
157-
if new_path:
158-
ServerCompilerSettings().compiler_dir = new_path
156+
ServerCompilerSettings().compiler_dir = new_path
159157
return get_compiler_path()
160158

161159

@@ -174,16 +172,15 @@ def get_compiler_path():
174172
#
175173
# Sketch settings
176174
#
177-
def set_sketch_path():
175+
def set_sketch_path(new_path):
178176
"""Open the file browser to select an folder to store the Arduino Sketch.
179177
180178
The new file path is saved into ServerCompilerSettings.
181179
180+
:param new_path: New path to store the Arduino Sketch.
182181
:return: Same as get_sketch_path().
183182
"""
184-
new_directory = gui.browse_dir_dialog()
185-
if new_directory != '':
186-
ServerCompilerSettings().sketch_dir = new_directory
183+
ServerCompilerSettings().sketch_dir = new_path
187184
return get_sketch_path()
188185

189186

@@ -206,8 +203,8 @@ def set_arduino_board(new_value):
206203
"""Set new Arduino board value in the Settings.
207204
208205
:param new_value: New Arduino board value, must be the board name, not the
209-
flag (so 'Uno', not 'arduino:avr:uno')
210-
:return: Same as the get_arduino_board_selected() function
206+
flag (so 'Uno', not 'arduino:avr:uno').
207+
:return: Same as the get_arduino_board_selected() function.
211208
"""
212209
ServerCompilerSettings().arduino_board = new_value
213210
return get_arduino_board_selected()
@@ -265,7 +262,7 @@ def set_load_ide_only(new_value):
265262
"""Set a new Arduino IDE load option.
266263
267264
:param new_value: New IDE load option to save in the Settings.
268-
:return: Same as the get_load_ide_selected() function
265+
:return: Same as the get_load_ide_selected() function.
269266
"""
270267
ServerCompilerSettings().load_ide_option = new_value
271268
return get_load_ide_selected()

0 commit comments

Comments
 (0)