Skip to content

Commit f2a2f3d

Browse files
committed
Minor updates
- Tracker Configuration Schema control now only shows devices in development mode in the device popup. - Also now properly handles pagination for when the product has more than 25 devices. - New control for viewing per-device configuration.
1 parent bcb67ad commit f2a2f3d

File tree

8 files changed

+325
-49
lines changed

8 files changed

+325
-49
lines changed
102 KB
Binary file not shown.
104 KB
Binary file not shown.

src/assets/js/api-helper-config.js

Lines changed: 196 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -94,36 +94,32 @@ apiHelper.downloadSchema = function(filename, product, deviceId, next) {
9494
});
9595
};
9696

97+
apiHelper.getTrackerConfig = function(product, deviceId, completion) {
98+
const deviceIdUrl = (!deviceId || deviceId == 'default') ? '' : '/' + deviceId;
99+
100+
$.ajax({
101+
dataType: 'json',
102+
error: function(err) {
103+
completion();
104+
},
105+
headers: {
106+
'Accept':'application/json'
107+
},
108+
method: 'GET',
109+
success: function (resp) {
110+
completion(resp.configuration);
111+
},
112+
url: 'https://api.particle.io/v1/products/' + product + '/config' + deviceIdUrl + '?access_token=' + apiHelper.auth.access_token
113+
});
114+
115+
};
116+
97117
$(document).ready(function() {
98118
if ($('.apiHelper').length == 0) {
99119
return;
100120
}
101121

102-
103-
104-
if (($('.apiHelperConfigSchema').length > 0 || $('.codeboxConfigSchemaSpan').length > 0) && apiHelper.auth) {
105-
//
106-
const updateDeviceList = function(parentDiv) {
107-
const product = $(parentDiv).find('.apiHelperConfigSchemaProductSelect').val();
108-
if (!product) {
109-
return;
110-
}
111-
112-
apiHelper.particle.listDevices({ auth: apiHelper.auth.access_token, product:product }).then(
113-
function(data) {
114-
let html = '<option value="default">Product Default</option>';
115-
data.body.devices.forEach(function(dev) {
116-
html += '<option value="' + dev.id + '">' + dev.name + '</option>';
117-
});
118-
$(parentDiv).find('.apiHelperConfigSchemaDeviceSelect').html(html);
119-
},
120-
function(err) {
121-
122-
}
123-
);
124-
125-
};
126-
122+
if ($('.apiHelperTrackerProductSelect').length > 0 && apiHelper.auth) {
127123
$.ajax({
128124
data: {
129125
'access_token': apiHelper.auth.access_token
@@ -140,42 +136,199 @@ $(document).ready(function() {
140136
html += '<option value="' + prod.id + '">' + prod.name + ' (' + prod.id + ')</option>';
141137
}
142138
});
139+
$('.apiHelperTrackerProductSelect').html(html);
140+
143141
if (html === '') {
144142
html = '<option disabled>No Tracker products available</option>'
145143
$('.codeboxConfigSchemaSpan').hide();
146144
}
147145
else {
148146
$('.codeboxConfigSchemaProductSelect').html(html);
149147
$('.codeboxConfigSchemaSpan').show();
148+
$('.apiHelperTrackerProductSelect').trigger('change');
149+
}
150+
151+
},
152+
url: 'https://api.particle.io/v1/user/products',
153+
});
154+
}
155+
156+
157+
$('.apiHelperTrackerProductSelect').each(function(index) {
158+
159+
const parentDiv = $(this).closest('div');
160+
161+
$(this).on('change', function() {
162+
const product = $(parentDiv).find('.apiHelperTrackerProductSelect').val();
163+
if (!product) {
164+
return;
165+
}
166+
const selectElem = $(parentDiv).find('.apiHelperTrackerDeviceSelect');
167+
$(selectElem).html('');
168+
169+
if ($(selectElem).attr('data-has-product-default')) {
170+
$(selectElem).append('<option value="default">Product Default</option>');
171+
}
172+
173+
const fetchPage = function(page) {
174+
apiHelper.particle.listDevices({ auth: apiHelper.auth.access_token, product:product, page }).then(
175+
function(data) {
176+
let html = '';
177+
data.body.devices.forEach(function(dev) {
178+
if (dev.development) {
179+
html += '<option value="' + dev.id + '">' + dev.name + '</option>';
180+
}
181+
});
182+
$(selectElem).append(html);
183+
184+
if (page < data.body.meta.total_pages) {
185+
fetchPage(++page);
186+
}
187+
else {
188+
$(selectElem).trigger('change');
189+
}
190+
},
191+
function(err) {
192+
}
193+
);
194+
}
195+
196+
fetchPage(1);
197+
});
198+
});
199+
200+
if ($('.apiHelperTrackerConfig').length > 0 && apiHelper.auth) {
201+
$('.apiHelperTrackerConfig').each(function() {
202+
const trackerConfigElem = $(this);
203+
204+
const setStatus = function(status) {
205+
$(trackerConfigElem).find('.apiHelperTrackerConfigStatus').html(status);
206+
};
207+
208+
const deviceSelectElem = $(trackerConfigElem).find('.apiHelperTrackerDeviceSelect');
209+
210+
211+
const getThisConfig = function() {
212+
const product = $(trackerConfigElem).find('.apiHelperTrackerProductSelect').val();
213+
if (!product) {
214+
return;
215+
}
216+
217+
const deviceId = $(deviceSelectElem).val();
218+
if (!deviceId) {
219+
return;
150220
}
151221

152-
$('.apiHelperConfigSchemaProductSelect').html(html);
222+
apiHelper.getTrackerConfig(product, deviceId, function(configObj) {
223+
224+
const showElem = $(trackerConfigElem).find('.apiHelperTrackerConfigShow');
153225

154-
$('.apiHelperConfigSchemaProductSelect').each(function(index) {
226+
let show = $(trackerConfigElem).find('.apiHelperTrackerConfigShow').val();
155227

156-
const parentDiv = $(this).closest('div');
157-
158-
$(this).on('change', function() {
159-
updateDeviceList(parentDiv);
160-
});
161-
162-
updateDeviceList(parentDiv);
163-
228+
if (!configObj.pending) {
229+
show = 'current';
230+
$(showElem).val(show);
231+
$(showElem).find('option[value="pending"]').attr('disabled', 'disabled');
232+
}
233+
else {
234+
$(showElem).find('option[value="pending"]').removeAttr('disabled');
235+
}
236+
237+
238+
apiHelper.jsonLinterSetValue(trackerConfigElem, JSON.stringify(configObj[show]));
164239
});
240+
};
165241

166-
},
167-
url: 'https://api.particle.io/v1/user/products',
242+
$(deviceSelectElem).on('change', function() {
243+
setStatus('');
244+
getThisConfig();
245+
246+
});
247+
248+
$(trackerConfigElem).find('.apiHelperTrackerConfigShow').on('change', function() {
249+
$(deviceSelectElem).trigger('change');
250+
});
251+
252+
253+
const setConfig = function(data) {
254+
const product = $(trackerConfigElem).find('.apiHelperTrackerProductSelect').val();
255+
if (!product) {
256+
return;
257+
}
258+
259+
const deviceId = $(deviceSelectElem).val();
260+
if (!deviceId) {
261+
return;
262+
}
263+
264+
const deviceIdUrl = (!deviceId || deviceId == 'default') ? '' : '/' + deviceId;
265+
266+
$.ajax({
267+
contentType: 'application/json',
268+
data: data,
269+
dataType: 'json',
270+
error: function(err) {
271+
console.log('setTrackerConfig error', err);
272+
let html = '';
273+
274+
html += '<p>' + err.responseJSON.message + '</p>';
275+
276+
if (err.responseJSON.violations && err.responseJSON.violations.length > 0) {
277+
html += '<ul>';
278+
err.responseJSON.violations.forEach(function(v) {
279+
html += '<li>' + v.message + ' ';
280+
if (v.params) {
281+
html += JSON.stringify(v.params);
282+
}
283+
284+
html += '<br />';
285+
});
286+
html += '</ul>';
287+
}
288+
289+
setStatus(html);
290+
},
291+
method: 'PUT',
292+
success: function (resp) {
293+
console.log('setTrackerConfig success', resp);
294+
let html = '';
295+
html += '<p>' + resp.message + '</p>';
296+
if (resp.details) {
297+
html += '<p>' + resp.details + '</p>';
298+
}
299+
300+
setStatus(html);
301+
302+
getThisConfig();
303+
},
304+
url: 'https://api.particle.io/v1/products/' + product + '/config' + deviceIdUrl + '?access_token=' + apiHelper.auth.access_token
305+
});
306+
307+
};
308+
309+
$(trackerConfigElem).find('.apiHelperTrackerConfigSet').on('click', function() {
310+
const data = apiHelper.jsonLinterGetValue(trackerConfigElem);
311+
setConfig(data);
312+
});
313+
314+
$(trackerConfigElem).find('.apiHelperTrackerConfigDefault').on('click', function() {
315+
setConfig('');
316+
});
168317
});
318+
}
319+
169320

321+
if (($('.apiHelperConfigSchema').length > 0 || $('.codeboxConfigSchemaSpan').length > 0) && apiHelper.auth) {
322+
//
170323
const setStatus = function(configSchemaPartial, status) {
171324
$(configSchemaPartial).find('.apiHelperConfigSchemaStatus').html(status);
172325
};
173326

174327

175328
$('.apiHelperConfigSchemaDownload').on('click', function(ev) {
176329
const configSchemaPartial = $(this).closest('div.apiHelperConfigSchema');
177-
const product = $(configSchemaPartial).find('.apiHelperConfigSchemaProductSelect').val();
178-
const deviceId = $(configSchemaPartial).find('.apiHelperConfigSchemaDeviceSelect').val();
330+
const product = $(configSchemaPartial).find('.apiHelperTrackerProductSelect').val();
331+
const deviceId = $(configSchemaPartial).find('.apiHelperTrackerDeviceSelect').val();
179332

180333
apiHelper.downloadSchema('schema.json', product, deviceId, function(err) {
181334
if (!err) {
@@ -195,8 +348,8 @@ $(document).ready(function() {
195348

196349
$('.apiHelperConfigSchemaUpload').on('click', function() {
197350
const configSchemaPartial = $(this).closest('div.apiHelperConfigSchema');
198-
const product = $(configSchemaPartial).find('.apiHelperConfigSchemaProductSelect').val();
199-
const deviceId = $(configSchemaPartial).find('.apiHelperConfigSchemaDeviceSelect').val();
351+
const product = $(configSchemaPartial).find('.apiHelperTrackerProductSelect').val();
352+
const deviceId = $(configSchemaPartial).find('.apiHelperTrackerDeviceSelect').val();
200353

201354
setStatus(configSchemaPartial, 'Select schema to upload...');
202355

@@ -238,8 +391,8 @@ $(document).ready(function() {
238391

239392
$('.apiHelperConfigSchemaDefault').on('click', function() {
240393
const configSchemaPartial = $(this).closest('div.apiHelperConfigSchema');
241-
const product = $(configSchemaPartial).find('.apiHelperConfigSchemaProductSelect').val();
242-
const deviceId = $(configSchemaPartial).find('.apiHelperConfigSchemaDeviceSelect').val();
394+
const product = $(configSchemaPartial).find('.apiHelperTrackerProductSelect').val();
395+
const deviceId = $(configSchemaPartial).find('.apiHelperTrackerDeviceSelect').val();
243396
const deviceIdUrl = (deviceId == 'default') ? '' : '/' + deviceId;
244397

245398
setStatus(configSchemaPartial, 'Restoring default schema...');

src/assets/js/api-helper-json.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@ $(document).ready(function() {
1919
}
2020
return result;
2121
};
22-
23-
apiHelper.jsonLinterEvent = function(elem, event) {
22+
23+
apiHelper.jsonLinterSetValue = function(elem, data) {
2424
const index = parseInt($(elem).attr('data-index'));
2525
const codeMirror = apiHelper.jsonLinterCodeMirror[index];
2626

27-
let data = event.data;
2827
try {
2928
const jsonObj = JSON.parse(data);
3029
data = JSON.stringify(jsonObj, null, 2);
@@ -34,6 +33,10 @@ $(document).ready(function() {
3433

3534
codeMirror.setValue(data);
3635
};
36+
37+
apiHelper.jsonLinterEvent = function(elem, event) {
38+
apiHelper.jsonLinterSetValue(elem, event.data);
39+
};
3740

3841
apiHelper.jsonLinterCodeMirror = [];
3942

src/content/tutorials/asset-tracking/tracker-configuration.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ columns: two
44
layout: tutorials.hbs
55
order: 32
66
description: Particle Tracker Configuration
7-
includeDefinitions: [api-helper, api-helper-config, api-helper-tracker, zip]
7+
includeDefinitions: [api-helper, api-helper-config, api-helper-json, api-helper-tracker, codemirror, zip]
88
---
99

1010
# Tracker Configuration
@@ -585,3 +585,8 @@ MyConfig &MyConfig::instance() {
585585

586586
The function to get the instance checks to see if it has been allocated. If it has not been allocated, it will be allocated using `new`. This should happen during `setup()`. In either case, the instance is returned.
587587

588+
## Per-device configuration
589+
590+
Tracker devices that are marked as development devices can have per-device configuration that overrides the product default configuration. In addition to using the console or curl, above, this tool makes it easy to view and edit the configuration in JSON format:
591+
592+
{{> tracker-config row="6" cols="70"}}

0 commit comments

Comments
 (0)