snow-flow 2.9.9 → 3.0.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.
- package/.mcp.json +13 -141
- package/.mcp.json.template +11 -25
- package/README.md +18 -0
- package/claude-flow +81 -0
- package/claude-flow.bat +18 -0
- package/claude-flow.config.json +20 -0
- package/claude-flow.ps1 +24 -0
- package/dist/agents/index.d.ts +3 -10
- package/dist/agents/index.js +10 -50
- package/dist/agents/queen-agent.d.ts +0 -2
- package/dist/agents/queen-agent.js +25 -42
- package/dist/cli.js +1 -1
- package/dist/mcp/servicenow-automation-mcp.js +10 -10
- package/dist/mcp/servicenow-deployment-mcp.js +1050 -169
- package/dist/mcp/servicenow-development-assistant-mcp.js +13 -65
- package/dist/mcp/servicenow-integration-mcp.js +10 -10
- package/dist/mcp/servicenow-machine-learning-mcp.js +15 -15
- package/dist/mcp/servicenow-operations-mcp.js +23 -23
- package/dist/mcp/servicenow-platform-development-mcp.js +9 -9
- package/dist/mcp/servicenow-reporting-analytics-mcp.js +11 -11
- package/dist/mcp/servicenow-security-compliance-mcp.js +11 -11
- package/dist/mcp/servicenow-update-set-mcp.js +9 -9
- package/dist/mcp/shared/reliable-memory-manager.d.ts +78 -0
- package/dist/mcp/shared/reliable-memory-manager.js +268 -0
- package/dist/mcp/snow-flow-mcp.js +341 -87
- package/dist/queen/agent-factory.d.ts +4 -2
- package/dist/queen/agent-factory.js +72 -25
- package/dist/services/tensorflow-ml-service.d.ts +105 -0
- package/dist/services/tensorflow-ml-service.js +456 -0
- package/dist/services/widget-deployment-service.d.ts +107 -0
- package/dist/services/widget-deployment-service.js +332 -0
- package/dist/utils/file-storage-fallback.d.ts +62 -0
- package/dist/utils/file-storage-fallback.js +289 -0
- package/dist/utils/mcp-singleton-enforcer.d.ts +36 -0
- package/dist/utils/mcp-singleton-enforcer.js +201 -0
- package/dist/utils/mcp-timeout-fix.d.ts +53 -0
- package/dist/utils/mcp-timeout-fix.js +221 -0
- package/memory/agents/README.md +31 -0
- package/memory/claude-flow-data.json +1 -1
- package/memory/sessions/README.md +1 -1
- package/package.json +4 -2
- package/src/agents/README.md +192 -0
- package/src/health/README.md +161 -0
- package/src/memory/README.md +240 -0
- package/src/queen/README.md +403 -0
- package/src/schemas/deployment.schema.json +58 -0
- package/src/schemas/flow.schema.json +79 -0
- package/src/schemas/widget.schema.json +72 -0
- package/src/templates/base/application.template.json +45 -0
- package/src/templates/base/business_rule.template.json +33 -0
- package/src/templates/base/script_include.template.json +18 -0
- package/src/templates/base/table.template.json +64 -0
- package/src/templates/base/widget.template.json +25 -0
- package/src/templates/patterns/composite.incident-management.template.json +140 -0
- package/src/templates/patterns/widget.dashboard.template.json +238 -0
- package/src/templates/patterns/widget.datatable.template.json +292 -0
- package/dist/mcp/servicenow-graph-memory-mcp.js +0 -728
- package/servicenow/widgets/openai_incident_classifier/client_controller.js +0 -284
- package/servicenow/widgets/openai_incident_classifier/server_script.js +0 -314
- package/servicenow/widgets/openai_incident_classifier/style.css +0 -354
- package/servicenow/widgets/openai_incident_classifier/template.html +0 -167
- package/servicenow/widgets/openai_incident_classifier/widget.json +0 -86
- package/test-ml-improvements.sh +0 -76
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "widget",
|
|
3
|
+
"name": "Data Table Widget Template",
|
|
4
|
+
"description": "Template for creating data table widgets with sorting, filtering, and pagination",
|
|
5
|
+
"category": "patterns/datatable",
|
|
6
|
+
"config": {
|
|
7
|
+
"name": "{{WIDGET_NAME|data_table}}",
|
|
8
|
+
"id": "{{WIDGET_ID|data_table}}",
|
|
9
|
+
"instance_id": "{{INSTANCE_ID|table_}}",
|
|
10
|
+
"data": {
|
|
11
|
+
"title": "{{WIDGET_TITLE|Data Table}}",
|
|
12
|
+
"short_description": "{{WIDGET_DESCRIPTION|Interactive data table with advanced features}}",
|
|
13
|
+
"roles": "{{WIDGET_ROLES|}}"
|
|
14
|
+
},
|
|
15
|
+
"options": [
|
|
16
|
+
{
|
|
17
|
+
"name": "table_name",
|
|
18
|
+
"section": "Data",
|
|
19
|
+
"label": "Table",
|
|
20
|
+
"type": "reference",
|
|
21
|
+
"value": "{{TABLE_NAME|incident}}",
|
|
22
|
+
"ed": "sys_db_object",
|
|
23
|
+
"help": "Select the table to display data from"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"name": "max_records",
|
|
27
|
+
"section": "Data",
|
|
28
|
+
"label": "Maximum Records",
|
|
29
|
+
"type": "integer",
|
|
30
|
+
"value": "100",
|
|
31
|
+
"help": "Maximum number of records to display"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "enable_filter",
|
|
35
|
+
"section": "Features",
|
|
36
|
+
"label": "Enable Filtering",
|
|
37
|
+
"type": "boolean",
|
|
38
|
+
"value": "true"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "enable_export",
|
|
42
|
+
"section": "Features",
|
|
43
|
+
"label": "Enable Export",
|
|
44
|
+
"type": "boolean",
|
|
45
|
+
"value": "true"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "enable_inline_edit",
|
|
49
|
+
"section": "Features",
|
|
50
|
+
"label": "Enable Inline Editing",
|
|
51
|
+
"type": "boolean",
|
|
52
|
+
"value": "false"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "row_actions",
|
|
56
|
+
"section": "Features",
|
|
57
|
+
"label": "Row Actions",
|
|
58
|
+
"type": "json",
|
|
59
|
+
"value": "[{\"label\":\"View\",\"action\":\"view\",\"icon\":\"eye\"},{\"label\":\"Edit\",\"action\":\"edit\",\"icon\":\"pencil\"}]"
|
|
60
|
+
}
|
|
61
|
+
],
|
|
62
|
+
"html": [
|
|
63
|
+
"<div class=\"data-table-widget\">",
|
|
64
|
+
" <div class=\"table-header\">",
|
|
65
|
+
" <h2 class=\"table-title\">{{data.title}}</h2>",
|
|
66
|
+
" <div class=\"table-controls\">",
|
|
67
|
+
" <div class=\"search-box\" ng-if=\"options.enable_filter\">",
|
|
68
|
+
" <i class=\"fa fa-search\"></i>",
|
|
69
|
+
" <input type=\"text\" ng-model=\"c.searchTerm\" ng-change=\"c.filterData()\" placeholder=\"Search...\">",
|
|
70
|
+
" </div>",
|
|
71
|
+
" <button class=\"btn btn-primary\" ng-if=\"options.enable_export\" ng-click=\"c.exportData()\">",
|
|
72
|
+
" <i class=\"fa fa-download\"></i> Export",
|
|
73
|
+
" </button>",
|
|
74
|
+
" </div>",
|
|
75
|
+
" </div>",
|
|
76
|
+
" ",
|
|
77
|
+
" <div class=\"table-container\" ng-if=\"!c.loading\">",
|
|
78
|
+
" <table class=\"table table-striped table-hover\">",
|
|
79
|
+
" <thead>",
|
|
80
|
+
" <tr>",
|
|
81
|
+
" <th ng-repeat=\"column in c.columns\" ng-click=\"c.sort(column.field)\" class=\"sortable\">",
|
|
82
|
+
" {{column.label}}",
|
|
83
|
+
" <i class=\"fa fa-sort\" ng-if=\"c.sortField !== column.field\"></i>",
|
|
84
|
+
" <i class=\"fa fa-sort-asc\" ng-if=\"c.sortField === column.field && c.sortDirection === 'asc'\"></i>",
|
|
85
|
+
" <i class=\"fa fa-sort-desc\" ng-if=\"c.sortField === column.field && c.sortDirection === 'desc'\"></i>",
|
|
86
|
+
" </th>",
|
|
87
|
+
" <th ng-if=\"c.rowActions.length > 0\">Actions</th>",
|
|
88
|
+
" </tr>",
|
|
89
|
+
" </thead>",
|
|
90
|
+
" <tbody>",
|
|
91
|
+
" <tr ng-repeat=\"row in c.displayData\">",
|
|
92
|
+
" <td ng-repeat=\"column in c.columns\">",
|
|
93
|
+
" <span ng-if=\"!c.isEditing(row, column)\" ng-click=\"c.startEdit(row, column)\">",
|
|
94
|
+
" {{c.getCellValue(row, column)}}",
|
|
95
|
+
" </span>",
|
|
96
|
+
" <input ng-if=\"c.isEditing(row, column)\" ",
|
|
97
|
+
" type=\"text\" ",
|
|
98
|
+
" ng-model=\"row[column.field]\" ",
|
|
99
|
+
" ng-blur=\"c.saveEdit(row, column)\"",
|
|
100
|
+
" ng-keypress=\"c.handleEditKeypress($event, row, column)\">",
|
|
101
|
+
" </td>",
|
|
102
|
+
" <td ng-if=\"c.rowActions.length > 0\" class=\"actions-cell\">",
|
|
103
|
+
" <button ng-repeat=\"action in c.rowActions\" ",
|
|
104
|
+
" class=\"btn btn-sm btn-default\" ",
|
|
105
|
+
" ng-click=\"c.performAction(action, row)\"",
|
|
106
|
+
" title=\"{{action.label}}\">",
|
|
107
|
+
" <i class=\"fa fa-{{action.icon}}\"></i>",
|
|
108
|
+
" </button>",
|
|
109
|
+
" </td>",
|
|
110
|
+
" </tr>",
|
|
111
|
+
" </tbody>",
|
|
112
|
+
" </table>",
|
|
113
|
+
" </div>",
|
|
114
|
+
" ",
|
|
115
|
+
" <div class=\"table-pagination\" ng-if=\"c.totalPages > 1\">",
|
|
116
|
+
" <button class=\"btn btn-sm\" ng-click=\"c.previousPage()\" ng-disabled=\"c.currentPage === 1\">",
|
|
117
|
+
" <i class=\"fa fa-chevron-left\"></i>",
|
|
118
|
+
" </button>",
|
|
119
|
+
" <span class=\"page-info\">Page {{c.currentPage}} of {{c.totalPages}}</span>",
|
|
120
|
+
" <button class=\"btn btn-sm\" ng-click=\"c.nextPage()\" ng-disabled=\"c.currentPage === c.totalPages\">",
|
|
121
|
+
" <i class=\"fa fa-chevron-right\"></i>",
|
|
122
|
+
" </button>",
|
|
123
|
+
" </div>",
|
|
124
|
+
" ",
|
|
125
|
+
" <div class=\"table-loading\" ng-if=\"c.loading\">",
|
|
126
|
+
" <i class=\"fa fa-spinner fa-spin fa-3x\"></i>",
|
|
127
|
+
" <p>Loading data...</p>",
|
|
128
|
+
" </div>",
|
|
129
|
+
"</div>"
|
|
130
|
+
],
|
|
131
|
+
"css": [
|
|
132
|
+
".data-table-widget {",
|
|
133
|
+
" background: #fff;",
|
|
134
|
+
" border-radius: 8px;",
|
|
135
|
+
" box-shadow: 0 2px 4px rgba(0,0,0,0.1);",
|
|
136
|
+
" overflow: hidden;",
|
|
137
|
+
"}",
|
|
138
|
+
"",
|
|
139
|
+
".table-header {",
|
|
140
|
+
" display: flex;",
|
|
141
|
+
" justify-content: space-between;",
|
|
142
|
+
" align-items: center;",
|
|
143
|
+
" padding: 20px;",
|
|
144
|
+
" border-bottom: 1px solid #e0e0e0;",
|
|
145
|
+
"}",
|
|
146
|
+
"",
|
|
147
|
+
".table-title {",
|
|
148
|
+
" margin: 0;",
|
|
149
|
+
" font-size: 20px;",
|
|
150
|
+
" font-weight: 600;",
|
|
151
|
+
"}",
|
|
152
|
+
"",
|
|
153
|
+
".table-controls {",
|
|
154
|
+
" display: flex;",
|
|
155
|
+
" align-items: center;",
|
|
156
|
+
" gap: 15px;",
|
|
157
|
+
"}",
|
|
158
|
+
"",
|
|
159
|
+
".search-box {",
|
|
160
|
+
" position: relative;",
|
|
161
|
+
" display: flex;",
|
|
162
|
+
" align-items: center;",
|
|
163
|
+
"}",
|
|
164
|
+
"",
|
|
165
|
+
".search-box i {",
|
|
166
|
+
" position: absolute;",
|
|
167
|
+
" left: 10px;",
|
|
168
|
+
" color: #666;",
|
|
169
|
+
"}",
|
|
170
|
+
"",
|
|
171
|
+
".search-box input {",
|
|
172
|
+
" padding: 8px 8px 8px 35px;",
|
|
173
|
+
" border: 1px solid #ddd;",
|
|
174
|
+
" border-radius: 4px;",
|
|
175
|
+
" width: 250px;",
|
|
176
|
+
"}",
|
|
177
|
+
"",
|
|
178
|
+
".table-container {",
|
|
179
|
+
" overflow-x: auto;",
|
|
180
|
+
"}",
|
|
181
|
+
"",
|
|
182
|
+
"table {",
|
|
183
|
+
" width: 100%;",
|
|
184
|
+
" border-collapse: collapse;",
|
|
185
|
+
"}",
|
|
186
|
+
"",
|
|
187
|
+
"th {",
|
|
188
|
+
" background: #f5f5f5;",
|
|
189
|
+
" padding: 12px;",
|
|
190
|
+
" text-align: left;",
|
|
191
|
+
" font-weight: 600;",
|
|
192
|
+
" color: #333;",
|
|
193
|
+
" white-space: nowrap;",
|
|
194
|
+
"}",
|
|
195
|
+
"",
|
|
196
|
+
"th.sortable {",
|
|
197
|
+
" cursor: pointer;",
|
|
198
|
+
" user-select: none;",
|
|
199
|
+
"}",
|
|
200
|
+
"",
|
|
201
|
+
"th.sortable:hover {",
|
|
202
|
+
" background: #e8e8e8;",
|
|
203
|
+
"}",
|
|
204
|
+
"",
|
|
205
|
+
"th i {",
|
|
206
|
+
" margin-left: 5px;",
|
|
207
|
+
" color: #999;",
|
|
208
|
+
"}",
|
|
209
|
+
"",
|
|
210
|
+
"td {",
|
|
211
|
+
" padding: 12px;",
|
|
212
|
+
" border-bottom: 1px solid #f0f0f0;",
|
|
213
|
+
"}",
|
|
214
|
+
"",
|
|
215
|
+
"td input {",
|
|
216
|
+
" width: 100%;",
|
|
217
|
+
" padding: 4px 8px;",
|
|
218
|
+
" border: 1px solid #007bff;",
|
|
219
|
+
" border-radius: 4px;",
|
|
220
|
+
"}",
|
|
221
|
+
"",
|
|
222
|
+
"tr:hover {",
|
|
223
|
+
" background: #f9f9f9;",
|
|
224
|
+
"}",
|
|
225
|
+
"",
|
|
226
|
+
".actions-cell {",
|
|
227
|
+
" white-space: nowrap;",
|
|
228
|
+
"}",
|
|
229
|
+
"",
|
|
230
|
+
".actions-cell button {",
|
|
231
|
+
" margin-right: 5px;",
|
|
232
|
+
"}",
|
|
233
|
+
"",
|
|
234
|
+
".table-pagination {",
|
|
235
|
+
" display: flex;",
|
|
236
|
+
" justify-content: center;",
|
|
237
|
+
" align-items: center;",
|
|
238
|
+
" padding: 20px;",
|
|
239
|
+
" gap: 15px;",
|
|
240
|
+
" border-top: 1px solid #e0e0e0;",
|
|
241
|
+
"}",
|
|
242
|
+
"",
|
|
243
|
+
".page-info {",
|
|
244
|
+
" color: #666;",
|
|
245
|
+
"}",
|
|
246
|
+
"",
|
|
247
|
+
".table-loading {",
|
|
248
|
+
" text-align: center;",
|
|
249
|
+
" padding: 60px 20px;",
|
|
250
|
+
" color: #666;",
|
|
251
|
+
"}",
|
|
252
|
+
"",
|
|
253
|
+
"@media (max-width: 768px) {",
|
|
254
|
+
" .table-header {",
|
|
255
|
+
" flex-direction: column;",
|
|
256
|
+
" align-items: flex-start;",
|
|
257
|
+
" gap: 15px;",
|
|
258
|
+
" }",
|
|
259
|
+
" ",
|
|
260
|
+
" .search-box input {",
|
|
261
|
+
" width: 200px;",
|
|
262
|
+
" }",
|
|
263
|
+
"}"
|
|
264
|
+
],
|
|
265
|
+
"client_controller": "{{CLIENT_CONTROLLER|datatable_controller}}",
|
|
266
|
+
"script": "{{SERVER_SCRIPT|datatable_server_script}}",
|
|
267
|
+
"link_function": "{{LINK_FUNCTION|}}",
|
|
268
|
+
"demo_data": {
|
|
269
|
+
"columns": [
|
|
270
|
+
{"field": "number", "label": "Number"},
|
|
271
|
+
{"field": "short_description", "label": "Description"},
|
|
272
|
+
{"field": "priority", "label": "Priority"},
|
|
273
|
+
{"field": "state", "label": "State"}
|
|
274
|
+
],
|
|
275
|
+
"data": [
|
|
276
|
+
{"number": "INC0001", "short_description": "Sample incident", "priority": "High", "state": "Open"}
|
|
277
|
+
]
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
"variables": {
|
|
281
|
+
"WIDGET_NAME": "data_table",
|
|
282
|
+
"WIDGET_ID": "data_table",
|
|
283
|
+
"INSTANCE_ID": "table_",
|
|
284
|
+
"WIDGET_TITLE": "Data Table",
|
|
285
|
+
"WIDGET_DESCRIPTION": "Interactive data table with advanced features",
|
|
286
|
+
"WIDGET_ROLES": "",
|
|
287
|
+
"TABLE_NAME": "incident",
|
|
288
|
+
"CLIENT_CONTROLLER": "function($scope, $http, $timeout) {\n var c = this;\n \n c.loading = true;\n c.data = [];\n c.displayData = [];\n c.columns = [];\n c.searchTerm = '';\n c.sortField = null;\n c.sortDirection = 'asc';\n c.currentPage = 1;\n c.pageSize = 20;\n c.totalPages = 1;\n c.editingCell = null;\n c.rowActions = [];\n \n // Parse row actions from options\n try {\n c.rowActions = JSON.parse(c.options.row_actions || '[]');\n } catch(e) {\n c.rowActions = [];\n }\n \n c.getData = function() {\n c.loading = true;\n c.server.get({\n action: 'get_table_data',\n table: c.options.table_name,\n max_records: c.options.max_records\n }).then(function(response) {\n c.columns = response.data.columns || [];\n c.data = response.data.data || [];\n c.filterData();\n c.loading = false;\n });\n };\n \n c.filterData = function() {\n var filtered = c.data;\n \n if (c.searchTerm) {\n filtered = c.data.filter(function(row) {\n return Object.values(row).some(function(value) {\n return String(value).toLowerCase().includes(c.searchTerm.toLowerCase());\n });\n });\n }\n \n // Apply sorting\n if (c.sortField) {\n filtered.sort(function(a, b) {\n var aVal = a[c.sortField] || '';\n var bVal = b[c.sortField] || '';\n var result = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;\n return c.sortDirection === 'desc' ? -result : result;\n });\n }\n \n // Apply pagination\n c.totalPages = Math.ceil(filtered.length / c.pageSize);\n var start = (c.currentPage - 1) * c.pageSize;\n c.displayData = filtered.slice(start, start + c.pageSize);\n };\n \n c.sort = function(field) {\n if (c.sortField === field) {\n c.sortDirection = c.sortDirection === 'asc' ? 'desc' : 'asc';\n } else {\n c.sortField = field;\n c.sortDirection = 'asc';\n }\n c.filterData();\n };\n \n c.previousPage = function() {\n if (c.currentPage > 1) {\n c.currentPage--;\n c.filterData();\n }\n };\n \n c.nextPage = function() {\n if (c.currentPage < c.totalPages) {\n c.currentPage++;\n c.filterData();\n }\n };\n \n c.getCellValue = function(row, column) {\n var value = row[column.field];\n // Format based on field type\n if (column.type === 'date') {\n return value ? new Date(value).toLocaleDateString() : '';\n }\n return value || '';\n };\n \n c.isEditing = function(row, column) {\n return c.options.enable_inline_edit && \n c.editingCell && \n c.editingCell.row === row && \n c.editingCell.column === column;\n };\n \n c.startEdit = function(row, column) {\n if (c.options.enable_inline_edit) {\n c.editingCell = {row: row, column: column};\n }\n };\n \n c.saveEdit = function(row, column) {\n c.editingCell = null;\n // Save to server\n c.server.get({\n action: 'update_record',\n table: c.options.table_name,\n sys_id: row.sys_id,\n field: column.field,\n value: row[column.field]\n });\n };\n \n c.handleEditKeypress = function(event, row, column) {\n if (event.keyCode === 13) { // Enter key\n c.saveEdit(row, column);\n }\n };\n \n c.performAction = function(action, row) {\n switch(action.action) {\n case 'view':\n window.open('/' + c.options.table_name + '.do?sys_id=' + row.sys_id, '_blank');\n break;\n case 'edit':\n window.open('/' + c.options.table_name + '.do?sys_id=' + row.sys_id + '&sysparm_view=edit', '_blank');\n break;\n default:\n // Custom action\n $scope.$emit('widget-action', {action: action, row: row});\n }\n };\n \n c.exportData = function() {\n var csv = c.columns.map(function(col) { return col.label; }).join(',') + '\\n';\n c.displayData.forEach(function(row) {\n csv += c.columns.map(function(col) {\n var val = row[col.field] || '';\n return '\"' + String(val).replace(/\"/g, '\"\"') + '\"';\n }).join(',') + '\\n';\n });\n \n var blob = new Blob([csv], {type: 'text/csv'});\n var url = window.URL.createObjectURL(blob);\n var a = document.createElement('a');\n a.href = url;\n a.download = c.data.title + '.csv';\n a.click();\n };\n \n // Initial load\n c.getData();\n}",
|
|
289
|
+
"SERVER_SCRIPT": "(function() {\n try {\n data.columns = [];\n data.data = [];\n gs.log('DataTable widget server script started', 'datatable_widget');\n \n if (input && input.action === 'get_table_data') {\n var tableName = input.table || 'incident';\n var maxRecords = parseInt(input.max_records) || 100;\n \n gs.log('Getting table data: table=' + tableName + ', maxRecords=' + maxRecords, 'datatable_widget');\n \n // Get table metadata\n var fields = [];\n var gd = new GlideRecord('sys_dictionary');\n gd.addQuery('name', tableName);\n gd.addQuery('internal_type', '!=', 'collection');\n gd.orderBy('column_label');\n gd.setLimit(10); // Limit columns for performance\n gd.query();\n \n while (gd.next()) {\n if (gd.element && !gd.element.startsWith('sys_')) {\n fields.push({\n field: gd.element.toString(),\n label: gd.column_label.toString() || gd.element.toString(),\n type: gd.internal_type.toString()\n });\n }\n }\n \n // Default fields if none found\n if (fields.length === 0) {\n fields = [\n {field: 'number', label: 'Number', type: 'string'},\n {field: 'short_description', label: 'Short Description', type: 'string'},\n {field: 'sys_created_on', label: 'Created', type: 'glide_date_time'}\n ];\n gs.log('Using default fields for table: ' + tableName, 'datatable_widget');\n }\n \n data.columns = fields;\n gs.log('Found ' + fields.length + ' columns for table', 'datatable_widget');\n \n // Get table data\n var gr = new GlideRecord(tableName);\n gr.orderByDesc('sys_created_on');\n gr.setLimit(maxRecords);\n gr.query();\n \n var recordCount = 0;\n while (gr.next()) {\n var row = {sys_id: gr.getUniqueValue()};\n fields.forEach(function(field) {\n row[field.field] = gr.getDisplayValue(field.field) || '';\n });\n data.data.push(row);\n recordCount++;\n }\n \n gs.log('Retrieved ' + recordCount + ' records from ' + tableName, 'datatable_widget');\n \n } else if (input && input.action === 'update_record') {\n // ✅ FIXED: Enhanced update with validation and error handling\n if (!input.table || !input.sys_id || !input.field) {\n throw new Error('Missing required parameters for update: table, sys_id, field');\n }\n \n gs.log('Updating record: table=' + input.table + ', sys_id=' + input.sys_id + ', field=' + input.field, 'datatable_widget');\n \n var gr = new GlideRecord(input.table);\n if (gr.get(input.sys_id)) {\n gr.setValue(input.field, input.value || '');\n gr.update();\n data.success = true;\n data.message = 'Record updated successfully';\n gs.log('Record updated successfully', 'datatable_widget');\n } else {\n data.success = false;\n data.error = 'Record not found: ' + input.sys_id;\n gs.warn('Record not found for update: ' + input.sys_id, 'datatable_widget');\n }\n }\n } catch (error) {\n gs.error('DataTable widget error: ' + error.message, 'datatable_widget');\n data.error = 'Error processing request: ' + error.message;\n data.success = false;\n }\n})()",
|
|
290
|
+
"LINK_FUNCTION": ""
|
|
291
|
+
}
|
|
292
|
+
}
|