snow-flow 2.0.4 → 2.0.6

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 (74) hide show
  1. package/dist/config/snow-flow-config.d.ts +1492 -0
  2. package/dist/config/snow-flow-config.js +938 -0
  3. package/dist/coordination/coordination-engine.d.ts +41 -0
  4. package/dist/coordination/coordination-engine.js +324 -0
  5. package/dist/coordination/coordination.test.d.ts +6 -0
  6. package/dist/coordination/example.d.ts +31 -0
  7. package/dist/coordination/example.js +394 -0
  8. package/dist/coordination/execution-patterns.d.ts +43 -0
  9. package/dist/coordination/execution-patterns.js +507 -0
  10. package/dist/coordination/factory.d.ts +94 -0
  11. package/dist/coordination/factory.js +433 -0
  12. package/dist/coordination/index.d.ts +71 -0
  13. package/dist/coordination/index.js +135 -0
  14. package/dist/coordination/progress-monitor.d.ts +71 -0
  15. package/dist/coordination/progress-monitor.js +505 -0
  16. package/dist/coordination/quality-gates.d.ts +124 -0
  17. package/dist/coordination/quality-gates.js +577 -0
  18. package/dist/coordination/shared-memory.d.ts +39 -0
  19. package/dist/coordination/shared-memory.js +289 -0
  20. package/dist/coordination/task-dependencies.d.ts +50 -0
  21. package/dist/coordination/task-dependencies.js +407 -0
  22. package/dist/coordination/team-coordinator.d.ts +59 -0
  23. package/dist/coordination/team-coordinator.js +550 -0
  24. package/dist/coordination/types.d.ts +152 -0
  25. package/dist/coordination/types.js +3 -0
  26. package/dist/memory/hierarchical-memory-system.d.ts +90 -0
  27. package/dist/memory/hierarchical-memory-system.js +400 -0
  28. package/dist/memory/index.d.ts +9 -0
  29. package/dist/memory/index.js +20 -0
  30. package/dist/memory/mcp-integration-example.d.ts +6 -0
  31. package/dist/memory/mcp-integration-example.js +281 -0
  32. package/dist/memory/memory-client.d.ts +199 -0
  33. package/dist/memory/memory-client.js +364 -0
  34. package/dist/memory/memory-manager.d.ts +29 -0
  35. package/dist/memory/memory-manager.js +280 -0
  36. package/dist/memory/memory-operations.d.ts +179 -0
  37. package/dist/memory/memory-operations.js +691 -0
  38. package/dist/memory/memory-system.d.ts +152 -0
  39. package/dist/memory/memory-system.js +632 -0
  40. package/dist/memory/memory-test.d.ts +6 -0
  41. package/dist/memory/memory-test.js +161 -0
  42. package/dist/memory/servicenow-artifact-indexer.d.ts +119 -0
  43. package/dist/memory/servicenow-artifact-indexer.js +560 -0
  44. package/dist/memory/snow-flow-memory-patterns.d.ts +213 -0
  45. package/dist/memory/snow-flow-memory-patterns.js +200 -0
  46. package/dist/memory/snow-memory.d.ts +54 -0
  47. package/dist/memory/snow-memory.js +301 -0
  48. package/dist/memory/swarm-memory.d.ts +135 -0
  49. package/dist/memory/swarm-memory.js +378 -0
  50. package/memory/claude-flow-data.json +5 -0
  51. package/memory/servicenow_artifacts/000d9224c895221055906c7518aa2d3d.json +30 -0
  52. package/memory/servicenow_artifacts/0196b66173303010e46b4a2214f6a7a2.json +36 -0
  53. package/memory/servicenow_artifacts/125e5d1d837e2a102a7ea130ceaad397.json +30 -0
  54. package/memory/servicenow_artifacts/7637c1f2b7112210a5e5911cde11a972.json +30 -0
  55. package/memory/servicenow_artifacts/default_documentation_tables_1754056582292.json +55 -0
  56. package/memory/servicenow_artifacts/default_documentation_tables_1754057477189.json +55 -0
  57. package/memory/sessions/README.md +32 -0
  58. package/memory/update-set-sessions/01f82af583faea102a7ea130ceaad3d4.json +9 -0
  59. package/memory/update-set-sessions/27718fb983faea102a7ea130ceaad34b.json +9 -0
  60. package/memory/update-set-sessions/412e9bf6833e22502a7ea130ceaad30a.json +8 -0
  61. package/memory/update-set-sessions/66fc5a79837aea102a7ea130ceaad3ab.json +9 -0
  62. package/memory/update-set-sessions/71a30ff5837eea102a7ea130ceaad37f.json +9 -0
  63. package/memory/update-set-sessions/74fba27983faea102a7ea130ceaad3bd.json +9 -0
  64. package/memory/update-set-sessions/a0b147b5837eea102a7ea130ceaad344.json +58 -0
  65. package/memory/update-set-sessions/b13f5eb983baea102a7ea130ceaad33e.json +9 -0
  66. package/package.json +1 -1
  67. package/reports/swarm-auto-centralized-1752649029776.json +13 -0
  68. package/scripts/postinstall.js +30 -0
  69. package/scripts/update-version.js +31 -0
  70. package/servicenow/widgets/openai_incident_classifier/client_controller.js +284 -0
  71. package/servicenow/widgets/openai_incident_classifier/server_script.js +314 -0
  72. package/servicenow/widgets/openai_incident_classifier/style.css +354 -0
  73. package/servicenow/widgets/openai_incident_classifier/template.html +167 -0
  74. package/servicenow/widgets/openai_incident_classifier/widget.json +86 -0
@@ -0,0 +1,314 @@
1
+ (function() {
2
+ // Server-side script for OpenAI Incident Classification Widget
3
+
4
+ var OpenAIIncidentClassifier = {
5
+
6
+ // Main data processing function
7
+ processRequest: function(action, params) {
8
+ try {
9
+ switch (action) {
10
+ case 'get_incidents':
11
+ return this.getIncidents(params);
12
+ case 'reclassify_incident':
13
+ return this.reclassifyIncident(params.incident_id);
14
+ default:
15
+ return { success: false, error: 'Invalid action' };
16
+ }
17
+ } catch (error) {
18
+ gs.error('OpenAI Incident Classifier Error: ' + error.message);
19
+ return { success: false, error: error.message };
20
+ }
21
+ },
22
+
23
+ // Get incidents with classification data
24
+ getIncidents: function(params) {
25
+ var startTime = new Date().getTime();
26
+
27
+ try {
28
+ // Parse parameters
29
+ var startDate = params.start_date || this.getDateDaysAgo(7);
30
+ var endDate = params.end_date || this.getDateToday();
31
+ var priority = params.priority || '';
32
+ var page = parseInt(params.page) || 1;
33
+ var pageSize = parseInt(params.page_size) || 10;
34
+
35
+ gs.log('Getting incidents: startDate=' + startDate + ', endDate=' + endDate + ', priority=' + priority, 'OpenAIIncidentClassifier');
36
+
37
+ // Build query for incidents
38
+ var incidentGR = new GlideRecord('incident');
39
+ incidentGR.addQuery('sys_created_on', '>=', startDate);
40
+ incidentGR.addQuery('sys_created_on', '<=', endDate + ' 23:59:59');
41
+
42
+ if (priority) {
43
+ incidentGR.addQuery('priority', priority);
44
+ }
45
+
46
+ incidentGR.orderByDesc('sys_created_on');
47
+ incidentGR.query();
48
+
49
+ var totalRecords = incidentGR.getRowCount();
50
+ var incidents = [];
51
+ var skip = (page - 1) * pageSize;
52
+ var count = 0;
53
+
54
+ gs.log('Processing ' + totalRecords + ' total records, skip=' + skip + ', pageSize=' + pageSize, 'OpenAIIncidentClassifier');
55
+
56
+ while (incidentGR.next()) {
57
+ if (count < skip) {
58
+ count++;
59
+ continue;
60
+ }
61
+
62
+ if (incidents.length >= pageSize) {
63
+ break;
64
+ }
65
+
66
+ var incident = this.processIncident(incidentGR);
67
+ incidents.push(incident);
68
+ count++;
69
+ }
70
+
71
+ // Calculate statistics
72
+ var statistics = this.calculateStatistics(incidents);
73
+ statistics.processingTime = ((new Date().getTime() - startTime) / 1000).toFixed(2);
74
+
75
+ gs.log('Successfully processed ' + incidents.length + ' incidents in ' + statistics.processingTime + 's', 'OpenAIIncidentClassifier');
76
+
77
+ return {
78
+ success: true,
79
+ incidents: incidents,
80
+ statistics: statistics,
81
+ total_records: totalRecords
82
+ };
83
+ } catch (error) {
84
+ gs.error('Error getting incidents: ' + error.message, 'OpenAIIncidentClassifier');
85
+ return {
86
+ success: false,
87
+ error: 'Failed to get incidents: ' + error.message,
88
+ incidents: [],
89
+ statistics: { totalIncidents: 0, processingTime: 0 },
90
+ total_records: 0
91
+ };
92
+ }
93
+ },
94
+
95
+ // Process individual incident
96
+ processIncident: function(incidentGR) {
97
+ var incident = {
98
+ sys_id: incidentGR.getUniqueValue(),
99
+ number: incidentGR.getDisplayValue('number'),
100
+ short_description: incidentGR.getDisplayValue('short_description'),
101
+ description: incidentGR.getDisplayValue('description'),
102
+ priority: incidentGR.getValue('priority'),
103
+ priority_label: incidentGR.getDisplayValue('priority'),
104
+ created_date: incidentGR.getDisplayValue('sys_created_on'),
105
+ ai_classification: incidentGR.getValue('u_ai_classification'),
106
+ ai_confidence: parseFloat(incidentGR.getValue('u_ai_confidence')) || 0,
107
+ ai_classification_date: incidentGR.getDisplayValue('u_ai_classification_date')
108
+ };
109
+
110
+ // Classify if not already classified
111
+ if (!incident.ai_classification) {
112
+ var classification = this.classifyIncident(incident);
113
+ if (classification.success) {
114
+ incident.ai_classification = classification.category;
115
+ incident.ai_confidence = classification.confidence;
116
+
117
+ // Update the incident record
118
+ this.updateIncidentClassification(incident.sys_id, classification);
119
+ } else {
120
+ incident.ai_classification = 'Other';
121
+ incident.ai_confidence = 50;
122
+ }
123
+ }
124
+
125
+ return incident;
126
+ },
127
+
128
+ // Classify incident using OpenAI or fallback logic
129
+ classifyIncident: function(incident) {
130
+ // Try OpenAI classification first
131
+ var openaiResult = this.classifyWithOpenAI(incident);
132
+ if (openaiResult.success) {
133
+ return openaiResult;
134
+ }
135
+
136
+ // Fallback to rule-based classification
137
+ return this.classifyWithRules(incident);
138
+ },
139
+
140
+ // Classify incident using OpenAI API
141
+ classifyWithOpenAI: function(incident) {
142
+ try {
143
+ var apiKey = gs.getProperty('x_openai.api_key');
144
+ if (!apiKey) {
145
+ return { success: false, error: 'OpenAI API key not configured' };
146
+ }
147
+
148
+ var requestBody = {
149
+ model: 'gpt-3.5-turbo',
150
+ messages: [
151
+ {
152
+ role: 'system',
153
+ content: 'You are an IT incident classification expert. Classify incidents into these categories: Hardware, Software, Network, Security, Access, Other. Respond with JSON format: {"category": "category_name", "confidence": confidence_score_0_to_100, "reasoning": "brief_explanation"}'
154
+ },
155
+ {
156
+ role: 'user',
157
+ content: 'Classify this incident:\nTitle: ' + incident.short_description + '\nDescription: ' + incident.description
158
+ }
159
+ ],
160
+ max_tokens: 150,
161
+ temperature: 0.3
162
+ };
163
+
164
+ var request = new sn_ws.RESTMessageV2();
165
+ request.setEndpoint('https://api.openai.com/v1/chat/completions');
166
+ request.setHttpMethod('POST');
167
+ request.setRequestHeader('Authorization', 'Bearer ' + apiKey);
168
+ request.setRequestHeader('Content-Type', 'application/json');
169
+ request.setRequestBody(JSON.stringify(requestBody));
170
+
171
+ var response = request.execute();
172
+ var responseCode = response.getStatusCode();
173
+
174
+ if (responseCode === 200) {
175
+ var responseBody = JSON.parse(response.getBody());
176
+ var content = responseBody.choices[0].message.content;
177
+
178
+ try {
179
+ var result = JSON.parse(content);
180
+ return {
181
+ success: true,
182
+ category: result.category,
183
+ confidence: result.confidence,
184
+ reasoning: result.reasoning
185
+ };
186
+ } catch (parseError) {
187
+ return { success: false, error: 'Failed to parse OpenAI response' };
188
+ }
189
+ } else {
190
+ return { success: false, error: 'OpenAI API error: ' + responseCode };
191
+ }
192
+ } catch (error) {
193
+ return { success: false, error: 'OpenAI classification failed: ' + error.message };
194
+ }
195
+ },
196
+
197
+ // Fallback rule-based classification
198
+ classifyWithRules: function(incident) {
199
+ var text = (incident.short_description + ' ' + incident.description).toLowerCase();
200
+
201
+ // Hardware keywords
202
+ if (text.match(/hardware|computer|laptop|desktop|monitor|printer|mouse|keyboard|server|disk|memory|cpu/)) {
203
+ return { success: true, category: 'Hardware', confidence: 70, reasoning: 'Keyword-based classification' };
204
+ }
205
+
206
+ // Software keywords
207
+ if (text.match(/software|application|program|system|error|bug|crash|install|update|patch/)) {
208
+ return { success: true, category: 'Software', confidence: 70, reasoning: 'Keyword-based classification' };
209
+ }
210
+
211
+ // Network keywords
212
+ if (text.match(/network|internet|connection|wifi|ethernet|vpn|firewall|router|switch|bandwidth/)) {
213
+ return { success: true, category: 'Network', confidence: 70, reasoning: 'Keyword-based classification' };
214
+ }
215
+
216
+ // Security keywords
217
+ if (text.match(/security|virus|malware|phishing|breach|unauthorized|password|access|permissions/)) {
218
+ return { success: true, category: 'Security', confidence: 70, reasoning: 'Keyword-based classification' };
219
+ }
220
+
221
+ // Access keywords
222
+ if (text.match(/access|login|password|account|user|authentication|authorization|permission/)) {
223
+ return { success: true, category: 'Access', confidence: 70, reasoning: 'Keyword-based classification' };
224
+ }
225
+
226
+ // Default to Other
227
+ return { success: true, category: 'Other', confidence: 50, reasoning: 'No specific keywords found' };
228
+ },
229
+
230
+ // Update incident classification in database
231
+ updateIncidentClassification: function(incidentId, classification) {
232
+ var incidentGR = new GlideRecord('incident');
233
+ if (incidentGR.get(incidentId)) {
234
+ incidentGR.setValue('u_ai_classification', classification.category);
235
+ incidentGR.setValue('u_ai_confidence', classification.confidence);
236
+ incidentGR.setValue('u_ai_classification_date', new GlideDateTime());
237
+ incidentGR.update();
238
+ }
239
+ },
240
+
241
+ // Reclassify incident
242
+ reclassifyIncident: function(incidentId) {
243
+ var incidentGR = new GlideRecord('incident');
244
+ if (!incidentGR.get(incidentId)) {
245
+ return { success: false, error: 'Incident not found' };
246
+ }
247
+
248
+ var incident = {
249
+ sys_id: incidentGR.getUniqueValue(),
250
+ short_description: incidentGR.getDisplayValue('short_description'),
251
+ description: incidentGR.getDisplayValue('description')
252
+ };
253
+
254
+ var classification = this.classifyIncident(incident);
255
+ if (classification.success) {
256
+ this.updateIncidentClassification(incidentId, classification);
257
+ return { success: true, message: 'Incident reclassified successfully' };
258
+ } else {
259
+ return { success: false, error: 'Failed to reclassify incident' };
260
+ }
261
+ },
262
+
263
+ // Calculate statistics
264
+ calculateStatistics: function(incidents) {
265
+ var stats = {
266
+ totalIncidents: incidents.length,
267
+ classifiedIncidents: 0,
268
+ averageConfidence: 0,
269
+ processingTime: 0
270
+ };
271
+
272
+ var totalConfidence = 0;
273
+ incidents.forEach(function(incident) {
274
+ if (incident.ai_classification && incident.ai_classification !== 'Other') {
275
+ stats.classifiedIncidents++;
276
+ }
277
+ totalConfidence += incident.ai_confidence;
278
+ });
279
+
280
+ if (incidents.length > 0) {
281
+ stats.averageConfidence = Math.round(totalConfidence / incidents.length);
282
+ }
283
+
284
+ return stats;
285
+ },
286
+
287
+ // Utility functions
288
+ getDateDaysAgo: function(days) {
289
+ var date = new Date();
290
+ date.setDate(date.getDate() - days);
291
+ return date.toISOString().split('T')[0];
292
+ },
293
+
294
+ getDateToday: function() {
295
+ return new Date().toISOString().split('T')[0];
296
+ }
297
+ };
298
+
299
+ // Main execution based on input
300
+ if (input && input.action) {
301
+ data.result = OpenAIIncidentClassifier.processRequest(input.action, input.params || {});
302
+ } else {
303
+ // Default initialization
304
+ data.result = {
305
+ success: true,
306
+ message: 'Widget initialized successfully',
307
+ config: {
308
+ supports_openai: !!gs.getProperty('x_openai.api_key'),
309
+ fallback_enabled: true
310
+ }
311
+ };
312
+ }
313
+
314
+ })();
@@ -0,0 +1,354 @@
1
+ .openai-incident-classifier-widget {
2
+ padding: 20px;
3
+ background: #ffffff;
4
+ border-radius: 8px;
5
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
6
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
7
+ }
8
+
9
+ .widget-header {
10
+ display: flex;
11
+ justify-content: space-between;
12
+ align-items: center;
13
+ margin-bottom: 20px;
14
+ padding-bottom: 15px;
15
+ border-bottom: 1px solid #e0e0e0;
16
+ }
17
+
18
+ .widget-header h3 {
19
+ margin: 0;
20
+ color: #333;
21
+ font-size: 24px;
22
+ font-weight: 600;
23
+ }
24
+
25
+ .header-controls .btn {
26
+ padding: 8px 16px;
27
+ border-radius: 4px;
28
+ border: none;
29
+ cursor: pointer;
30
+ font-size: 14px;
31
+ transition: all 0.3s ease;
32
+ }
33
+
34
+ .btn-primary {
35
+ background-color: #007bff;
36
+ color: white;
37
+ }
38
+
39
+ .btn-primary:hover {
40
+ background-color: #0056b3;
41
+ }
42
+
43
+ .btn-primary:disabled {
44
+ background-color: #6c757d;
45
+ cursor: not-allowed;
46
+ }
47
+
48
+ .filters-section {
49
+ margin-bottom: 20px;
50
+ padding: 15px;
51
+ background: #f8f9fa;
52
+ border-radius: 6px;
53
+ }
54
+
55
+ .filters-section label {
56
+ font-weight: 500;
57
+ margin-bottom: 5px;
58
+ display: block;
59
+ color: #495057;
60
+ }
61
+
62
+ .form-control {
63
+ width: 100%;
64
+ padding: 8px 12px;
65
+ border: 1px solid #ced4da;
66
+ border-radius: 4px;
67
+ font-size: 14px;
68
+ transition: border-color 0.3s ease;
69
+ }
70
+
71
+ .form-control:focus {
72
+ outline: none;
73
+ border-color: #007bff;
74
+ box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
75
+ }
76
+
77
+ .loading-overlay {
78
+ display: flex;
79
+ flex-direction: column;
80
+ align-items: center;
81
+ justify-content: center;
82
+ padding: 40px;
83
+ background: #f8f9fa;
84
+ border-radius: 6px;
85
+ margin: 20px 0;
86
+ }
87
+
88
+ .spinner {
89
+ width: 40px;
90
+ height: 40px;
91
+ border: 4px solid #f3f3f3;
92
+ border-top: 4px solid #007bff;
93
+ border-radius: 50%;
94
+ animation: spin 1s linear infinite;
95
+ margin-bottom: 15px;
96
+ }
97
+
98
+ @keyframes spin {
99
+ 0% { transform: rotate(0deg); }
100
+ 100% { transform: rotate(360deg); }
101
+ }
102
+
103
+ .error-message {
104
+ background: #f8d7da;
105
+ color: #721c24;
106
+ padding: 15px;
107
+ border-radius: 4px;
108
+ margin: 20px 0;
109
+ border: 1px solid #f5c6cb;
110
+ }
111
+
112
+ .error-message i {
113
+ margin-right: 8px;
114
+ }
115
+
116
+ .statistics-cards {
117
+ margin-bottom: 30px;
118
+ }
119
+
120
+ .stat-card {
121
+ background: white;
122
+ border: 1px solid #e0e0e0;
123
+ border-radius: 8px;
124
+ padding: 20px;
125
+ text-align: center;
126
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
127
+ height: 100px;
128
+ }
129
+
130
+ .stat-card:hover {
131
+ transform: translateY(-2px);
132
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
133
+ }
134
+
135
+ .stat-value {
136
+ font-size: 28px;
137
+ font-weight: 700;
138
+ color: #007bff;
139
+ margin-bottom: 8px;
140
+ }
141
+
142
+ .stat-label {
143
+ font-size: 14px;
144
+ color: #6c757d;
145
+ font-weight: 500;
146
+ }
147
+
148
+ .charts-section {
149
+ margin-bottom: 30px;
150
+ }
151
+
152
+ .chart-container {
153
+ background: white;
154
+ border: 1px solid #e0e0e0;
155
+ border-radius: 8px;
156
+ padding: 20px;
157
+ margin-bottom: 20px;
158
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
159
+ }
160
+
161
+ .chart-container h4 {
162
+ margin: 0 0 15px 0;
163
+ color: #333;
164
+ font-size: 18px;
165
+ font-weight: 600;
166
+ text-align: center;
167
+ }
168
+
169
+ .data-table-section {
170
+ margin-bottom: 20px;
171
+ }
172
+
173
+ .table {
174
+ width: 100%;
175
+ border-collapse: collapse;
176
+ margin-top: 15px;
177
+ }
178
+
179
+ .table th,
180
+ .table td {
181
+ padding: 12px;
182
+ text-align: left;
183
+ border-bottom: 1px solid #e0e0e0;
184
+ font-size: 14px;
185
+ }
186
+
187
+ .table th {
188
+ background-color: #f8f9fa;
189
+ font-weight: 600;
190
+ color: #495057;
191
+ }
192
+
193
+ .table tbody tr:hover {
194
+ background-color: #f8f9fa;
195
+ }
196
+
197
+ .classification-badge {
198
+ display: inline-block;
199
+ padding: 4px 8px;
200
+ border-radius: 4px;
201
+ font-size: 12px;
202
+ font-weight: 500;
203
+ color: white;
204
+ text-transform: uppercase;
205
+ }
206
+
207
+ .badge-hardware { background-color: #dc3545; }
208
+ .badge-software { background-color: #007bff; }
209
+ .badge-network { background-color: #28a745; }
210
+ .badge-security { background-color: #fd7e14; }
211
+ .badge-access { background-color: #6f42c1; }
212
+ .badge-other { background-color: #6c757d; }
213
+
214
+ .confidence-bar {
215
+ position: relative;
216
+ height: 20px;
217
+ background: #e9ecef;
218
+ border-radius: 10px;
219
+ overflow: hidden;
220
+ min-width: 80px;
221
+ }
222
+
223
+ .confidence-fill {
224
+ height: 100%;
225
+ background: linear-gradient(90deg, #dc3545 0%, #ffc107 50%, #28a745 100%);
226
+ transition: width 0.3s ease;
227
+ }
228
+
229
+ .confidence-text {
230
+ position: absolute;
231
+ top: 50%;
232
+ left: 50%;
233
+ transform: translate(-50%, -50%);
234
+ font-size: 12px;
235
+ font-weight: 500;
236
+ color: #333;
237
+ }
238
+
239
+ .priority-badge {
240
+ display: inline-block;
241
+ padding: 4px 8px;
242
+ border-radius: 4px;
243
+ font-size: 12px;
244
+ font-weight: 500;
245
+ color: white;
246
+ }
247
+
248
+ .priority-1 { background-color: #dc3545; }
249
+ .priority-2 { background-color: #fd7e14; }
250
+ .priority-3 { background-color: #ffc107; color: #333; }
251
+ .priority-4 { background-color: #28a745; }
252
+
253
+ .btn-sm {
254
+ padding: 4px 8px;
255
+ font-size: 12px;
256
+ }
257
+
258
+ .btn-secondary {
259
+ background-color: #6c757d;
260
+ color: white;
261
+ }
262
+
263
+ .btn-secondary:hover {
264
+ background-color: #5a6268;
265
+ }
266
+
267
+ .pagination-section {
268
+ margin-top: 20px;
269
+ }
270
+
271
+ .pagination {
272
+ display: flex;
273
+ justify-content: center;
274
+ list-style: none;
275
+ padding: 0;
276
+ margin: 0;
277
+ }
278
+
279
+ .page-item {
280
+ margin: 0 2px;
281
+ }
282
+
283
+ .page-link {
284
+ display: block;
285
+ padding: 8px 12px;
286
+ text-decoration: none;
287
+ background: white;
288
+ border: 1px solid #dee2e6;
289
+ color: #007bff;
290
+ border-radius: 4px;
291
+ transition: all 0.3s ease;
292
+ }
293
+
294
+ .page-link:hover {
295
+ background-color: #e9ecef;
296
+ color: #0056b3;
297
+ }
298
+
299
+ .page-item.active .page-link {
300
+ background-color: #007bff;
301
+ color: white;
302
+ border-color: #007bff;
303
+ }
304
+
305
+ .page-item.disabled .page-link {
306
+ color: #6c757d;
307
+ pointer-events: none;
308
+ background-color: #fff;
309
+ border-color: #dee2e6;
310
+ }
311
+
312
+ .row {
313
+ display: flex;
314
+ flex-wrap: wrap;
315
+ margin: 0 -15px;
316
+ }
317
+
318
+ .col-md-3, .col-md-4 {
319
+ flex: 0 0 auto;
320
+ padding: 0 15px;
321
+ }
322
+
323
+ .col-md-3 {
324
+ width: 25%;
325
+ }
326
+
327
+ .col-md-4 {
328
+ width: 33.333333%;
329
+ }
330
+
331
+ @media (max-width: 768px) {
332
+ .col-md-3, .col-md-4 {
333
+ width: 100%;
334
+ margin-bottom: 15px;
335
+ }
336
+
337
+ .widget-header {
338
+ flex-direction: column;
339
+ align-items: flex-start;
340
+ }
341
+
342
+ .header-controls {
343
+ margin-top: 10px;
344
+ }
345
+
346
+ .table {
347
+ font-size: 12px;
348
+ }
349
+
350
+ .table th,
351
+ .table td {
352
+ padding: 8px;
353
+ }
354
+ }