profoundjs 7.20.4 → 7.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/auto-testing/static/test-runs/index.html +46 -0
  2. package/auto-testing/static/test-runs/script.js +477 -0
  3. package/auto-testing/static/test-runs/style.css +237 -0
  4. package/htdocs/profoundui/proddata/css/markdown.css +23 -0
  5. package/htdocs/profoundui/proddata/css/plogic.css +4976 -0
  6. package/htdocs/profoundui/proddata/css/profoundui.css +3 -2
  7. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-700.eot +0 -0
  8. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-700.svg +276 -0
  9. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-700.ttf +0 -0
  10. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-700.woff +0 -0
  11. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-700.woff2 +0 -0
  12. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-italic.eot +0 -0
  13. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-italic.svg +301 -0
  14. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-italic.ttf +0 -0
  15. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-italic.woff +0 -0
  16. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-italic.woff2 +0 -0
  17. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-regular.eot +0 -0
  18. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-regular.svg +281 -0
  19. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-regular.ttf +0 -0
  20. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-regular.woff +0 -0
  21. package/htdocs/profoundui/proddata/fonts/gudea-v10-latin-regular.woff2 +0 -0
  22. package/htdocs/profoundui/proddata/fonts/material_icons.woff2 +0 -0
  23. package/htdocs/profoundui/proddata/images/FlatIcons/24x24/capture-changes.png +0 -0
  24. package/htdocs/profoundui/proddata/js/atrium.js +190 -188
  25. package/htdocs/profoundui/proddata/js/designer.js +4391 -4366
  26. package/htdocs/profoundui/proddata/js/genie.js +2558 -2549
  27. package/htdocs/profoundui/proddata/js/plogic.grids.js +326 -0
  28. package/htdocs/profoundui/proddata/js/runtime.js +1418 -1414
  29. package/htdocs/profoundui/proddata/js/signon.js +101 -99
  30. package/htdocs/profoundui/userdata/html/atrium_login.html +4 -1
  31. package/package.json +3 -1
  32. package/profound.jse +1 -1
  33. package/setup/completeInstall.js +7 -0
  34. package/setup/modules/puiscreens.json +283 -0
  35. package/setup/pjsdist.savf +0 -0
@@ -0,0 +1,326 @@
1
+ if (!window.plogic) window.plogic = {};
2
+
3
+ plogic.grid = {
4
+ // Used by option_buttons widget
5
+ // gridId = option_buttons["user defined data"]
6
+ // selectionFieldName = option_buttons["user defined data 2"] (optional - default value is "sopt")
7
+ doOption: (opt, gridId, selectionFieldName) => {
8
+ selectionFieldName = selectionFieldName || "option";
9
+ // Is there more than 1 grid?
10
+ arrGridId = gridId.split(",");
11
+ // Is there more than 1 selection fieldName?
12
+ arrSelectionFieldName = selectionFieldName.split(",");
13
+ if (arrGridId.length !== arrSelectionFieldName.length) {
14
+ alert(`The Option Buttons Widget "user defined data" & "user defined data 2" properties must have the same number of elements.`);
15
+ return;
16
+ }
17
+ for (let i = 0; i < arrGridId.length; i += 1) {
18
+ const gridObj = getObj(arrGridId[i]);
19
+ if (gridObj !== null) {
20
+ const count = gridObj.grid.getRecordCount();
21
+ for (let j = 1; j <= count; j += 1) {
22
+ if (gridObj.grid.getDataValue(j, plogic.string.up("schecked")) === "1") {
23
+ gridObj.grid.setDataValue(j, plogic.string.up(arrSelectionFieldName[i]), opt);
24
+ }
25
+ }
26
+ }
27
+ }
28
+ plogic.button.pressKey("Enter");
29
+ },
30
+
31
+ // Grid - Handle keyboard Mode changed
32
+ handleKeyboardModeChanged: (panel) => {
33
+ const isKeyboard = plogic.keyboardMode.getMode();
34
+ const iconKeyboardModeOn = "list_alt";
35
+ const iconKeyboardModeOff = "check_box";
36
+ panel = panel || document;
37
+
38
+ for (const gridWidget of panel.querySelectorAll('div[puiwdgt="grid"]')) {
39
+ // If there is an icon in the 1st colum of the grid, change it to match the keyboard mode state.
40
+ if (gridWidget.pui.properties["column headings"] && gridWidget.pui.properties["column headings"].split(",")[0].startsWith("<icon class=")) {
41
+ const arrColumnHeadings = gridWidget.pui.properties["column headings"].split(",");
42
+ arrColumnHeadings[0] = `<icon class="plogic--header pui-material-icons">${isKeyboard ? iconKeyboardModeOn : iconKeyboardModeOff}</icon>`;
43
+ gridWidget.grid.setProperty("column headings", arrColumnHeadings.toString());
44
+ }
45
+
46
+ const optionButtons = plogic.optionButtons.getforGrid(gridWidget);
47
+ if (!optionButtons) continue;
48
+
49
+ for (let row = 1; row <= gridWidget.grid.getRecordCount(); row += 1) {
50
+ if (gridWidget.pui.properties["display subfile"] !== "false") {
51
+ gridWidget.grid.setDataValue(row, plogic.string.up("keybrdmode"), isKeyboard);
52
+ }
53
+ }
54
+ }
55
+ },
56
+
57
+ // Check if the grid has active filters.
58
+ isFiltered: (gridObj) => {
59
+ if (get("filterAllId") === "") {
60
+ // Set the filterAll field with the retrieved filterAll value.
61
+ pui.set(`${gridObj.id}_filterAll`, gridObj.grid.getFilter("*all"));
62
+ }
63
+ let isFiltered = gridObj.grid.getFilter("*all") !== null && gridObj.grid.getFilter("*all") !== "";
64
+ if (!isFiltered) {
65
+ // Loop on all columns
66
+ for (let i = 0; i < gridObj.pui.properties["number of columns"]; i += 1) {
67
+ isFiltered = gridObj.grid.getFilter(i) !== null && gridObj.grid.getFilter(i) !== "";
68
+ if (isFiltered) break;
69
+ }
70
+ }
71
+ return isFiltered;
72
+ },
73
+
74
+ // Do onfilterchange action
75
+ onFilterChanged: (gridObj) => {
76
+ if (!gridObj) {
77
+ return;
78
+ }
79
+ // Check if the grid has active filters.
80
+ const gridIsFiltered = plogic.grid.isFiltered(gridObj);
81
+ const filterAllObj = getObj(`${gridObj.id}_filterAll`);
82
+ if (filterAllObj) {
83
+ // Add or remove the Remove Filters button depending on if grid has filtered rows or not.
84
+ plogic.button.toggleRemoveFiltersButton(gridIsFiltered, gridObj, filterAllObj);
85
+ }
86
+ },
87
+
88
+ // Position message subfile based on "messages" output field
89
+ positionMessageSubfile: (config) => {
90
+ // Is there an error messages grid ?
91
+ const msgGridItem = config.metaData.items.filter((item) => item["css class 2"] === "plogic--grid--messages")[0];
92
+ if (msgGridItem) {
93
+ const myGridParent = getObj(msgGridItem.layout); // The grid container
94
+ const myGrid = getObj(msgGridItem.id).grid; // The grid object
95
+ if (myGridParent && myGrid) {
96
+ // Update grid width based on its container width
97
+ const newWidth = `${myGridParent.clientWidth - parseInt(msgGridItem.left, 10) - 20}px`;
98
+ myGrid.setProperty("column widths", `${newWidth}`);
99
+ myGrid.setProperty("width", `${newWidth}px`);
100
+ myGrid.render();
101
+ }
102
+ }
103
+ },
104
+
105
+ // Remove all filters
106
+ removeFilter: (gridObj, filterAllObj, removeFilterButton) => {
107
+ pui.set(filterAllObj.id, ""); // Clear the filterAll field
108
+ if (gridObj && gridObj.grid) {
109
+ gridObj.grid.removeAllFilters();
110
+ }
111
+ },
112
+
113
+ // Resize a grid based on its parent width
114
+ resizeGrid: (gridObj) => {
115
+ const myGridParent = gridObj.parentElement; // The grid container
116
+ const myGrid = gridObj.grid;
117
+ // Update grid width based on its container width
118
+ const newWidth = `${myGridParent.clientWidth - parseInt(gridObj.style.left, 10) - 20}px`;
119
+ myGrid.setProperty("column widths", `${newWidth}`);
120
+ myGrid.setProperty("width", `${newWidth}px`);
121
+ myGrid.render();
122
+ },
123
+
124
+ // Row click -> is there a checkbox to select ?
125
+ rowClick: (row, rowNumber, event) => {
126
+ const gridWidget = event.srcElement.closest('div[puiwdgt="grid"]');
127
+ // Don't do anything on blank rows
128
+ if (row > gridWidget.grid.getRecordCount()) return;
129
+
130
+ let checkBox = getObj(`schecked.${row}`);
131
+ const simpleSelector = getObj(`${gridWidget.id.toLowerCase()}_selector.${row}`);
132
+ if (simpleSelector) {
133
+ simpleSelector.focus();
134
+ }
135
+ else {
136
+ const comboBox = checkBox && checkBox.previousElementSibling;
137
+ // Don't do anything if the selectors (combo box AND checkbox) are protected
138
+ if (
139
+ checkBox &&
140
+ (checkBox.classList.contains("PR") || checkBox.pui.properties["read only"] === "true") &&
141
+ comboBox &&
142
+ (comboBox.classList.contains("PR") || comboBox.pui.properties["read only"] === "true")
143
+ ) {
144
+ return;
145
+ }
146
+
147
+ // Don't do anything if the selectors (combo box AND checkbox) are hidden
148
+ if (
149
+ checkBox &&
150
+ (checkBox.classList.contains("hidden") || checkBox.pui.properties.visibility === "hidden") &&
151
+ comboBox &&
152
+ (comboBox.classList.contains("hidden") || comboBox.pui.properties.visibility === "hidden")
153
+ ) {
154
+ return;
155
+ }
156
+
157
+ // Don't do anything if the selector is protected
158
+ if (getObj(`schecked.${row}`) && getObj(`schecked.${row}`).pui.properties["read only"] === "true") return;
159
+
160
+ // Don't set the option if keyboard mode and row is selected
161
+ if (plogic.keyboardMode.getMode() && event && event.detail === 1) return;
162
+
163
+ // Do not select when not keyboard mode, single click and checkbox does not exist
164
+ if (!plogic.keyboardMode.getMode() && event && event.detail === 1 && !checkBox) return;
165
+ }
166
+
167
+ let makeSelected = event && event.detail === 2;
168
+ if (!makeSelected) {
169
+ const data = gridWidget.grid.getAllDataValues();
170
+ // We use rowNumber because of possible filtered or sorted rows.
171
+ makeSelected = !(data[rowNumber - 1][plogic.string.up("schecked")] == "1" ? true : false);
172
+ }
173
+
174
+ if (!simpleSelector) {
175
+ if (makeSelected) plogic.grid.setOption(gridWidget, row);
176
+ else plogic.grid.setOption(gridWidget, row, "");
177
+ }
178
+
179
+ // Double-click
180
+ if (event && event.detail === 2) plogic.button.pressKey("Enter");
181
+ },
182
+
183
+ // Sometimes, grids have column headings built with variables. Those headings have been temporary tagged by the conversion theme as @[item_fieldName].
184
+ // This function will build "column headings" property based on those individuals fields.
185
+ setColumnHeadings: (format) => {
186
+ const arrGrids = format.metaData.items.filter((item) => item["field type"] === "grid" && !item["subfile message key"]);
187
+ for (const gridWidget of arrGrids) {
188
+ if (gridWidget["column headings"]) {
189
+ const arrHeadings = gridWidget["column headings"].split(",");
190
+ let arrTempFieldNames = [];
191
+ for (let j = 0; j < arrHeadings.length; j += 1) {
192
+ // If the heading corresponds to an individual field, let's replace the dummy value with the field value.
193
+ if (arrHeadings[j].includes("@[") && arrHeadings[j].includes("]")) {
194
+ const heading = arrHeadings[j];
195
+ const posStart = heading.indexOf("@[") + 2;
196
+ const posEnd = heading.indexOf("]");
197
+ if (posStart >= posEnd) return;
198
+ const tempFieldName = arrHeadings[j].substring(posStart, posEnd);
199
+ // If there is more than one variable inside the brackets, the separator has to be ";;".
200
+ if (tempFieldName.includes(";;")) {
201
+ arrTempFieldNames = tempFieldName.split(";;");
202
+ }
203
+ else {
204
+ arrTempFieldNames = [];
205
+ arrTempFieldNames.push(tempFieldName);
206
+ }
207
+ let tempHeading;
208
+ arrHeadings[j] = "";
209
+ for (let k = 0; k < arrTempFieldNames.length; k += 1) {
210
+ let currentItem = format.metaData.items.find((item) => item.value && item.value.fieldName && item.value.fieldName === arrTempFieldNames[k]);
211
+ if (!currentItem) {
212
+ currentItem = format.metaData.items.find((item) => item.id.endsWith(arrTempFieldNames[k]));
213
+ }
214
+ if (currentItem) {
215
+ tempHeading = plogic.fields.getItemValue(currentItem, format);
216
+ }
217
+ // If the field has a conditioned visibility
218
+ if (
219
+ currentItem &&
220
+ currentItem.visibility &&
221
+ currentItem.visibility.fieldName &&
222
+ currentItem.visibility.dataType === "expression" &&
223
+ currentItem.visibility.formatting === "Indicator"
224
+ ) {
225
+ const indicatorValue = format.data[`*IN${currentItem.visibility.fieldName.trim("N")}`];
226
+ // If not visible, search for the opposite field
227
+ if (
228
+ (indicatorValue === "0" && currentItem.visibility.indFormat === "visible / hidden") ||
229
+ (indicatorValue === "1" && currentItem.visibility.indFormat === "hidden / visible")
230
+ ) {
231
+ // Opposite item = if the current item has a visibility conditioned by an indicator, we search the item with the same row/column and with opposite visibility.
232
+ const oppositeItem = plogic.fields.getOppositeItem(currentItem, format.metaData.items);
233
+ if (oppositeItem) {
234
+ tempHeading = plogic.fields.getItemValue(oppositeItem, format);
235
+ }
236
+ }
237
+ }
238
+ if (k > 0) tempHeading = ` ${tempHeading}`; // Add a space between labels
239
+ // Does currentItem have a "display attribute" property?
240
+ // If yes, let's add the corresponding CSS class.
241
+ if (currentItem && currentItem["display attribute field"] && currentItem["display attribute field"].fieldName) {
242
+ const tempCSS = plogic.string.getClassFromHexcode(format.data[plogic.string.up(currentItem["display attribute field"].fieldName)]);
243
+ tempHeading = `<div class="${tempCSS}">${tempHeading}</div>`;
244
+ }
245
+ arrHeadings[j] += tempHeading;
246
+ // If last pass
247
+ if (k === arrTempFieldNames.length - 1) {
248
+ arrHeadings[j] = heading.replace(`@[${tempFieldName}]`, arrHeadings[j]);
249
+ // If there is another variable like @[xxx]
250
+ if (arrHeadings[j].includes("@[")) j -= 1;
251
+ }
252
+ }
253
+ }
254
+ }
255
+ gridWidget["column headings"] = arrHeadings.toString();
256
+ }
257
+ }
258
+ },
259
+
260
+ // Grid filter Textbox
261
+ setFilter: (gridId, filterObj) => {
262
+ if (getObj(gridId) && getObj(gridId).grid) {
263
+ getObj(gridId).grid.setFilter("*all", filterObj.value);
264
+ }
265
+ },
266
+
267
+ setOption: (gridWidget, row, value) => {
268
+ const optionButtons = plogic.optionButtons.getforGrid(gridWidget);
269
+ if (!optionButtons) return;
270
+ let selecting = false;
271
+ if (value == null) {
272
+ value = optionButtons.pui.optionButtons.getDefaultOption();
273
+ // Not passing the 'value' parm means we are selecting records and the value takes the default value retruned by getDefaultOption().
274
+ // But this default value can only be 1, 2 or 5. If these 3 options are not authorized/available, it will return blank.
275
+ // Therefore, we need an indicator saying that we are "selecting" records.
276
+ selecting = true;
277
+ }
278
+ // selectionFieldName = option_buttons["user defined data 2"] (optional - default value is "sopt")
279
+ let selectionFieldName = optionButtons.pui.properties["user defined data 2"] || "option";
280
+ // Is there more than 1 selection fieldName?
281
+ arrSelectionFieldName = selectionFieldName.split(",");
282
+ for (let i = 0; i < arrSelectionFieldName.length; i += 1) {
283
+ // Do not change the selector value on blank rows
284
+ if (row <= gridWidget.grid.getRecordCount()) {
285
+ gridWidget.grid.setDataValue(row, plogic.string.up(arrSelectionFieldName[i]), value);
286
+ gridWidget.grid.setDataValue(row, plogic.string.up("schecked"), value.length > 0 || selecting ? "1" : "0");
287
+ }
288
+ }
289
+ },
290
+
291
+ setSelection: (gridWidget, row, value) => {
292
+ const schecked = plogic.string.up("schecked");
293
+ // Do not change the selector value on blank rows
294
+ if (row <= gridWidget.grid.getRecordCount()) {
295
+ // Only change the value if selecting/deselecting the row
296
+ if (
297
+ gridWidget.grid.getDataValue(row, schecked) !== undefined &&
298
+ (
299
+ (gridWidget.grid.getDataValue(row, schecked) === "1" && value === "0") ||
300
+ (gridWidget.grid.getDataValue(row, schecked) === "0" && [undefined, "1"].includes(value))
301
+ )
302
+ ) {
303
+ gridWidget.grid.setDataValue(row, schecked, value);
304
+ }
305
+ }
306
+ },
307
+
308
+ // Update grid column headings css class
309
+ updateHeadingsClass: (gridObj) => {
310
+ // Grid column headings cells
311
+ const arrGridHeaders = Array.prototype.slice.call(gridObj.querySelectorAll(".cell.header-cell"));
312
+ // Grid 1st row cells
313
+ const arrGridRow1Cells = Array.prototype.slice.call(gridObj.querySelectorAll(".cell.odd")).slice(0, arrGridHeaders.length);
314
+ for (let i = 0; i < arrGridRow1Cells.length; i += 1) {
315
+ // List elements of the grid cell
316
+ const arrCellChildren = Array.prototype.slice.call(arrGridRow1Cells[i].children);
317
+ if (arrCellChildren) {
318
+ // Check if the cell content has the "plogic--monospace" css class. If yes, add that class to the header.
319
+ const arrElems = arrCellChildren.find((elem) => elem.className.includes("plogic--monospace"));
320
+ if (arrElems) {
321
+ arrGridHeaders[i].className += " plogic--monospace";
322
+ }
323
+ }
324
+ }
325
+ }
326
+ };