Skip to content

Commit a565b0d

Browse files
Refactor message management system and enhance user experience
- Split `scripts/messages/messageList.js` into multiple modular files for better organization and maintainability. - Updated `pages/messageManager.html` to load new script files directly, improving loading efficiency. - Added new helper scripts for message list functionalities, enhancing the overall message management experience. - Updated CSS styles to improve clarity in filter dialogs and message list interactions. - Changed the name of a constant in `constants.json` for better clarity and alignment with the system's terminology.
1 parent 0dcc797 commit a565b0d

13 files changed

Lines changed: 3596 additions & 3037 deletions

pages/messageManager.html

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,15 @@
1313
<script type="text/javascript" src="scripts/controller.js"></script>
1414
<script type="text/javascript" src="scripts/uploader.js"></script>
1515
<script type="text/javascript" src="scripts/messages/messageManager.js"></script>
16-
<script type="text/javascript" src="scripts/messages/messageList.js"></script>
1716
<script type="text/javascript" src="scripts/messages/message.js"></script>
17+
<script type="text/javascript" src="scripts/messages/messageList/helpers.js"></script>
18+
<script type="text/javascript" src="scripts/messages/messageList/messageDetail.widget.js"></script>
19+
<script type="text/javascript" src="scripts/messages/messageList/sendMessageQueue.widget.js"></script>
20+
<script type="text/javascript" src="scripts/messages/messageList/editMessage.widget.js"></script>
21+
<script type="text/javascript" src="scripts/messages/messageList/editQueue.widget.js"></script>
22+
<script type="text/javascript" src="scripts/messages/messageList/loadQueue.widget.js"></script>
23+
<script type="text/javascript" src="scripts/messages/messageList/uploadLog.widget.js"></script>
24+
<script type="text/javascript" src="scripts/messages/messageList/messageList.widget.js"></script>
1825
<script type="text/javascript" src="scripts/messages/doc/messageDoc.js"></script>
1926
<link rel="stylesheet" type="text/css" href="jquery-ui/jquery-ui.css" />
2027
<link rel="stylesheet" type="text/css" href="jquery-ui/jquery-ui.theme.css" />

scripts/messages/messageList.js

Lines changed: 12 additions & 3034 deletions
Large diffs are not rendered by default.
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
(function ($) {
2+
$.widget("pic.editMessage", {
3+
options: { isBinding: false },
4+
_create: function () {
5+
var self = this, o = self.options, el = self.element;
6+
self._initMessage();
7+
self.bindMessage(o.message);
8+
o.message = undefined;
9+
},
10+
_fromWindow(showError) {
11+
var self = this, o = self.options, el = self.element;
12+
var m = dataBinder.fromElement(el);
13+
var valid = dataBinder.checkRequired(el, showError);
14+
if (!valid && showError) return;
15+
var msg = { protocol: m.protocol, payload: [], preamble: [255, 0, 255], term: [], isValid: true, direction: 'out', delay: m.delay };
16+
var arrPayload = m.payloadBytes.split(',');
17+
var source = parseInt(m.source || 0, 10);
18+
var dest = parseInt(m.dest, 10);
19+
var action = parseInt(m.action, 10);
20+
var controller = parseInt(m.controller || 0, 10);
21+
if (isNaN(controller) || controller < 0 || controller > 256) {
22+
if (showError) {
23+
$('<div></div>').appendTo(el.find('div.picPickList[data-bind$=controller]:first')).fieldTip({
24+
message: 'Invalid controller: ' + arrPayload[i] + '<br></br>Values must be between 0 and 256'
25+
});
26+
return;
27+
}
28+
controller = 0;
29+
}
30+
if (isNaN(action) || action < 0 || action > 256) {
31+
if (showError) {
32+
$('<div></div>').appendTo(el.find('div.picPickList[data-bind$=action]:first')).fieldTip({
33+
message: 'Invalid action: ' + arrPayload[i] + '<br></br>Values must be between 0 and 256'
34+
});
35+
return;
36+
}
37+
action = 0;
38+
}
39+
if (isNaN(dest) || dest < 0 || dest > 256) {
40+
if (showError) {
41+
$('<div></div>').appendTo(el.find('div.picPickList[data-bind$=source]:first')).fieldTip({
42+
message: 'Invalid source: ' + arrPayload[i] + '<br></br>Values must be between 0 and 256'
43+
});
44+
return;
45+
}
46+
source = 0;
47+
}
48+
if (isNaN(dest) || dest < 0 || dest > 256) {
49+
if (showError) {
50+
$('<div></div>').appendTo(el.find('div.picPickList[data-bind$=dest]:first')).fieldTip({
51+
message: 'Invalid destination: ' + arrPayload[i] + '<br></br>Values must be between 0 and 256'
52+
});
53+
return;
54+
}
55+
dest = 0;
56+
}
57+
if (m.payloadBytes.length > 0) {
58+
//console.log({ m: 'Checking payload', bytes: m.payloadBytes, arr: arrPayload, showError: showError });
59+
for (var i = 0; i < arrPayload.length; i++) {
60+
var byte = parseInt(arrPayload[i].trim(), 10);
61+
if (isNaN(byte) || byte < 0 || byte > 256) {
62+
if (showError) {
63+
$('<div></div>').appendTo(el.find('div.picInputField[data-bind$=payloadBytes]:first')).fieldTip({
64+
message: '<div style="width:270px">Invalid payload byte: ' + arrPayload[i] + '<br></br>Values must be between 0 and 256</div>'
65+
});
66+
return;
67+
}
68+
byte = 0;
69+
}
70+
msg.payload.push(byte);
71+
}
72+
}
73+
switch (msg.protocol) {
74+
case 'chlorinator':
75+
msg.header = [16, 2, dest, action];
76+
break;
77+
default:
78+
msg.header = [165, controller, dest, source, action, msg.payload.length];
79+
break;
80+
}
81+
mhelper.setMessageTerm(msg);
82+
msg.key = msg.header.join('_');
83+
console.log(msg);
84+
return msg;
85+
},
86+
_initMessage: function () {
87+
var self = this, o = self.options, el = self.element;
88+
var div = $('<div></div>').appendTo(el).addClass('edit-message-protocol');
89+
var line = $('<div></div>').appendTo(div);
90+
var proto = $('<div></div>').appendTo(line).pickList({
91+
labelText: 'Protocol', binding: 'protocol',
92+
displayColumn: 1,
93+
columns: [{ binding: 'val', hidden: true, text: 'Id', style: { whiteSpace: 'nowrap' } }, { binding: 'desc', text: 'Protocol', style: { whiteSpace: 'nowrap' } }],
94+
items: [{ val: 'broadcast', desc: 'Broadcast' },
95+
{ val: 'chlorinator', desc: 'Chlorinator' },
96+
{ val: 'pump', desc: 'Pump' },
97+
{ val: 'intellivalve', desc: 'Intellivalve' },
98+
{ val: 'intellichem', desc: 'Intellichem' },
99+
{ val: 'regalmodbus', desc: 'Regal Modbus' }],
100+
inputAttrs: { style: { width: '7rem' } }, labelAttrs: { style: { width: '4rem' } }
101+
});
102+
proto.on('selchanged', function (evt) {
103+
if (!o.isBinding) {
104+
var msg = self._fromWindow(false);
105+
console.log({ m: 'Sel Changed', msg: msg });
106+
switch (evt.newItem.val) {
107+
case 'chlorinator':
108+
self._initChlorinator();
109+
break;
110+
default:
111+
self._initBroadcast();
112+
}
113+
self.bindMessage(msg);
114+
}
115+
});
116+
$('<div></div>').appendTo(line).inputField({ required: false, dataType:'int', labelText: 'Delay', binding: 'delay', inputAttrs: { maxlength: 7, style: { width: '4rem' } }, labelAttrs: { style: { width: '2.5rem', paddingLeft: '.25rem' } } });
117+
118+
$('<div></div>').addClass('edit-message-panel').appendTo(el);
119+
var pnlPayload = $('<div></div>').addClass('edit-message-payload').appendTo(el);
120+
$('<div></div>').appendTo(pnlPayload).inputField({ required: false, labelText: 'Payload', binding: 'payloadBytes', inputAttrs: { style: { width: '44rem' } }, labelAttrs: { style: { width: '4rem' } } });
121+
var btnPnl = $('<div class="picBtnPanel btn-panel"></div>').appendTo(el);
122+
$('<div></div>').appendTo(btnPnl).actionButton({ text: 'Save Message', icon: '<i class="far fa-save"></i>' }).on('click', function (e) {
123+
var msg = self._fromWindow(true);
124+
if (msg) {
125+
$('div.picSendMessageQueue').each(function () {
126+
this.saveMessage(msg);
127+
});
128+
// Close the window.
129+
el.parents('div.picPopover:first')[0].close();
130+
}
131+
});
132+
el.on('changed', 'div.picPickList[data-bind="controller"]', function (evt) {
133+
if (!o.isBinding) {
134+
var msg = self._fromWindow(false);
135+
var actions;
136+
switch (msg.protocol) {
137+
case 'intellichem':
138+
actions = mhelper.chemActions;
139+
break;
140+
case 'pump':
141+
actions = mhelper.pumpActions;
142+
break;
143+
case 'intellivalve':
144+
actions = mhelper.valveActions;
145+
break;
146+
case 'chlorinator':
147+
actions = mhelper.chlorActions;
148+
break;
149+
default:
150+
switch (mhelper.getControllerByte(msg)) {
151+
case 63:
152+
actions = mhelper.centerActions;
153+
break;
154+
case 16:
155+
actions = mhelper.touchActions;
156+
break;
157+
}
158+
break;
159+
}
160+
el.find('div.picPickList[data-bind=action').each(function () { this.items(actions); });
161+
}
162+
});
163+
},
164+
_initChlorinator: function () {
165+
var self = this, o = self.options, el = self.element;
166+
var div = el.find('div.edit-message-panel');
167+
if (div.attr('data-paneltype') === 'chlorinator') return;
168+
div.attr('data-paneltype', 'chlorinator');
169+
div.empty();
170+
var line = $('<div></div>').appendTo(div);
171+
$('<div></div>').appendTo(line).pickList({
172+
canEdit: true,
173+
dataType: 'int',
174+
labelText: 'Dest', binding: 'dest',
175+
displayColumn: 1,
176+
columns: [{ binding: 'val', hidden: false, text: 'byte', style: { whiteSpace: 'nowrap' } }, { binding: 'desc', text: 'Address', style: { whiteSpace: 'nowrap' } }],
177+
items: mhelper.chlorAddrs,
178+
inputAttrs: { maxlength: 3, style: { width: '2.25rem' } }, labelAttrs: { style: { width: '4rem' } }
179+
});
180+
$('<div></div>').appendTo(line).pickList({
181+
canEdit: true,
182+
dataType: 'int',
183+
labelText: 'Action', binding: 'action',
184+
displayColumn: 1,
185+
columns: [{ binding: 'val', hidden: false, text: 'byte', style: { whiteSpace: 'nowrap' } }, { binding: 'desc', text: 'Action', style: { whiteSpace: 'nowrap' } }],
186+
items:[],
187+
inputAttrs: { maxlength: 3, style: { width: '2.25rem' } }, labelAttrs: { style: { width: '2.7rem', paddingLeft: '.25rem' } }
188+
});
189+
190+
},
191+
_initBroadcast: function () {
192+
var self = this, o = self.options, el = self.element;
193+
var div = el.find('div.edit-message-panel');
194+
if (div.attr('data-paneltype') === 'broadcast') return;
195+
div.attr('data-paneltype', 'broadcast');
196+
div.empty();
197+
var line = $('<div></div>').appendTo(div);
198+
$('<div></div>').appendTo(line).pickList({
199+
canEdit: true,
200+
dataType: 'int',
201+
labelText: 'Controller', binding: 'controller',
202+
displayColumn: 1,
203+
columns: [{ binding: 'val', hidden: false, text: 'byte', style: { whiteSpace: 'nowrap' } }, { binding: 'desc', text: 'Controller', style: { whiteSpace: 'nowrap' } }],
204+
items: mhelper.controllerBytes,
205+
inputAttrs: { maxlength: 3, style: { width: '2.25rem' } }, labelAttrs: { style: { width: '4rem' } }
206+
});
207+
line = $('<div></div>').appendTo(div);
208+
$('<div></div>').appendTo(line).pickList({
209+
canEdit: true,
210+
dataType: 'int',
211+
labelText: 'Source', binding: 'source',
212+
displayColumn: 1,
213+
columns: [{ binding: 'val', hidden: false, text: 'byte', style: { whiteSpace: 'nowrap' } }, { binding: 'desc', text: 'Address', style: { whiteSpace: 'nowrap' } }],
214+
items: [],
215+
inputAttrs: { maxlength: 3, style: { width: '2.25rem' } }, labelAttrs: { style: { width: '4rem' } }
216+
});
217+
218+
$('<div></div>').appendTo(line).pickList({
219+
canEdit: true,
220+
dataType: 'int',
221+
labelText: 'Dest', binding: 'dest',
222+
displayColumn: 1,
223+
columns: [{ binding: 'val', hidden: false, text: 'byte', style: { whiteSpace: 'nowrap' } }, { binding: 'desc', text: 'Address', style: { whiteSpace: 'nowrap' } }],
224+
items: [],
225+
inputAttrs: { maxlength: 3, style: { width: '2.25rem' } }, labelAttrs: { style: { width: '2.7rem', paddingLeft: '.25rem' } }
226+
});
227+
$('<div></div>').appendTo(line).pickList({
228+
canEdit: true,
229+
dataType: 'int',
230+
labelText: 'Action', binding: 'action',
231+
displayColumn: 1,
232+
columns: [{ binding: 'val', hidden: false, text: 'byte', style: { whiteSpace: 'nowrap' } }, { binding: 'desc', text: 'Action', style: { whiteSpace: 'nowrap' } }],
233+
items: [],
234+
inputAttrs: { maxlength: 3, style: { width: '2.25rem' } }, labelAttrs: { style: { width: '2.7rem', paddingLeft: '.25rem' } }
235+
});
236+
},
237+
bindMessage: function (msg) {
238+
var self = this, o = self.options, el = self.element;
239+
var copy = $.extend(true, {}, msg);
240+
if (typeof copy.controller === 'undefined') copy.controller = mhelper.getControllerByte(copy);
241+
if (typeof copy.source === 'undefined') copy.source = mhelper.getSourceByte(copy);
242+
if (typeof copy.dest === 'undefined') copy.dest = mhelper.getDestByte(copy);
243+
if (typeof copy.action === 'undefined') copy.action = mhelper.getActionByte(copy);
244+
if (typeof copy.payloadBytes === 'undefined') copy.payloadBytes = copy.payload.join(',');
245+
o.isBinding = true;
246+
copy.dataLen = msg.payload.length;
247+
var actions = mhelper.broadcastActions;
248+
if (msg.protocol === 'chlorinator') {
249+
self._initChlorinator();
250+
addrs = mhelper.chlorAddrs;
251+
actions = mhelper.chlorActions;
252+
}
253+
else {
254+
self._initBroadcast();
255+
var addrs = mhelper.broadcastAddrs;
256+
switch (msg.protocol) {
257+
case 'intellichem':
258+
addrs = mhelper.chemAddrs;
259+
actions = mhelper.chemActions;
260+
break;
261+
case 'pump':
262+
addrs = mhelper.pumpAddrs;
263+
actions = mhelper.pumpActions;
264+
break;
265+
case 'intellivalve':
266+
addrs = mhelper.valveAddrs;
267+
actions = mhelper.valveActions;
268+
break;
269+
default:
270+
switch (mhelper.getControllerByte(msg)) {
271+
case 63:
272+
actions = mhelper.centerActions;
273+
break;
274+
case 16:
275+
actions = mhelper.touchActions;
276+
break;
277+
}
278+
break;
279+
}
280+
el.find('div.picPickList[data-bind=source').each(function () { this.items(addrs); });
281+
el.find('div.picPickList[data-bind=dest').each(function () { this.items(addrs); });
282+
el.find('div.picPickList[data-bind=action').each(function () { this.items(actions); });
283+
}
284+
dataBinder.bind(el.find('div.edit-message-protocol:first'), copy);
285+
dataBinder.bind(el.find('div.edit-message-panel:first'), copy);
286+
dataBinder.bind(el.find('div.edit-message-payload:first'), copy);
287+
o.isBinding = false;
288+
}
289+
});
290+
})(jQuery);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
(function ($) {
2+
$.widget("pic.editQueue", {
3+
options: { isBinding: false },
4+
_create: function () {
5+
var self = this, o = self.options, el = self.element;
6+
self._initQueue();
7+
self.bindQueue(o.queue);
8+
},
9+
_fromWindow(showError) {
10+
var self = this, o = self.options, el = self.element;
11+
var q = dataBinder.fromElement(el);
12+
var valid = dataBinder.checkRequired(el, showError);
13+
if (!valid && showError) return;
14+
return q;
15+
},
16+
_initQueue: function () {
17+
var self = this, o = self.options, el = self.element;
18+
var div = $('<div></div>').appendTo(el).addClass('edit-queue');
19+
var line = $('<div></div>').appendTo(div);
20+
$('<input type="hidden" data-datatype="int" data-bind="id"></input>').appendTo(line);
21+
$('<div></div>').appendTo(line).inputField({ required: true, labelText: 'Name', binding: 'name', inputAttrs: { maxlength: 27, style: { width: '12rem' } }, labelAttrs: { style: { width: '5.5rem', paddingLeft: '.25rem' } } });
22+
line = $('<div></div>').appendTo(div);
23+
$('<div></div>').appendTo(line).inputField({ required: false, multiLine:true, labelText: 'Description', binding: 'description', inputAttrs: { maxlength: 100, style: { width: '19rem', height:'4rem' } }, labelAttrs: { style: { width: '5.5rem', paddingLeft: '.25rem' } } });
24+
25+
var btnPnl = $('<div class="picBtnPanel btn-panel"></div>').appendTo(el);
26+
$('<div></div>').appendTo(btnPnl).actionButton({ text: 'Save Queue', icon: '<i class="far fa-save"></i>' }).on('click', function (e) {
27+
var queue = self._fromWindow(true);
28+
29+
if (queue) {
30+
$('div.picSendMessageQueue').each(function () {
31+
this.bindQueue(queue);
32+
this.saveMessage();
33+
});
34+
// Close the window.
35+
el.parents('div.picPopover:first')[0].close();
36+
}
37+
});
38+
},
39+
bindQueue: function (queue) {
40+
var self = this, o = self.options, el = self.element;
41+
if (typeof queue.id !== 'number' || queue.id <= 0) el.parents('div.picPopover:first')[0].titleText('Create Queue');
42+
dataBinder.bind(el, queue);
43+
}
44+
});
45+
})(jQuery);

0 commit comments

Comments
 (0)