slicejs-web-framework 2.3.1 → 2.3.2

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.
@@ -0,0 +1,238 @@
1
+ /**
2
+ * EventManager debug panel.
3
+ */
4
+ export default class EventManagerDebugger extends HTMLElement {
5
+ constructor() {
6
+ super();
7
+ this.isOpen = false;
8
+ this.filterText = '';
9
+ this.refreshInterval = null;
10
+ }
11
+
12
+ /**
13
+ * Initialize panel UI.
14
+ * @returns {Promise<void>}
15
+ */
16
+ async init() {
17
+ this.innerHTML = this.renderTemplate();
18
+ slice.stylesManager.registerComponentStyles('EventManagerDebugger', this.renderStyles());
19
+ this.cacheElements();
20
+ this.bindEvents();
21
+ this.renderList();
22
+ }
23
+
24
+ /**
25
+ * Toggle panel visibility.
26
+ * @returns {void}
27
+ */
28
+ toggle() {
29
+ this.isOpen = !this.isOpen;
30
+ this.container.classList.toggle('active', this.isOpen);
31
+ if (this.isOpen) {
32
+ this.renderList();
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Show panel.
38
+ * @returns {void}
39
+ */
40
+ open() {
41
+ this.isOpen = true;
42
+ this.container.classList.add('active');
43
+ this.renderList();
44
+ }
45
+
46
+ /**
47
+ * Hide panel.
48
+ * @returns {void}
49
+ */
50
+ close() {
51
+ this.isOpen = false;
52
+ this.container.classList.remove('active');
53
+ }
54
+
55
+ cacheElements() {
56
+ this.container = this.querySelector('#events-debugger');
57
+ this.list = this.querySelector('#events-list');
58
+ this.filterInput = this.querySelector('#events-filter');
59
+ this.countLabel = this.querySelector('#events-count');
60
+ this.refreshButton = this.querySelector('#events-refresh');
61
+ this.closeButton = this.querySelector('#events-close');
62
+ }
63
+
64
+ bindEvents() {
65
+ this.refreshButton.addEventListener('click', () => this.renderList());
66
+ this.closeButton.addEventListener('click', () => this.close());
67
+ this.filterInput.addEventListener('input', (event) => {
68
+ this.filterText = event.target.value.trim().toLowerCase();
69
+ this.renderList();
70
+ });
71
+ }
72
+
73
+ renderList() {
74
+ if (!slice?.events?.subscriptions) {
75
+ this.list.textContent = 'EventManager not available.';
76
+ this.countLabel.textContent = '0';
77
+ return;
78
+ }
79
+
80
+ const items = [];
81
+ slice.events.subscriptions.forEach((subs, eventName) => {
82
+ const count = subs.size;
83
+ if (this.filterText && !eventName.toLowerCase().includes(this.filterText)) {
84
+ return;
85
+ }
86
+ items.push({ eventName, count });
87
+ });
88
+
89
+ items.sort((a, b) => a.eventName.localeCompare(b.eventName));
90
+
91
+ this.countLabel.textContent = String(items.length);
92
+ this.list.innerHTML = items.length
93
+ ? items.map((item) => {
94
+ return `
95
+ <div class="event-row">
96
+ <div class="event-name">${item.eventName}</div>
97
+ <div class="event-count">${item.count}</div>
98
+ </div>
99
+ `;
100
+ }).join('')
101
+ : '<div class="empty">No events</div>';
102
+ }
103
+
104
+ renderTemplate() {
105
+ return `
106
+ <div id="events-debugger">
107
+ <div class="events-header">
108
+ <div class="title">Events</div>
109
+ <div class="actions">
110
+ <button id="events-refresh" class="btn">Refresh</button>
111
+ <button id="events-close" class="btn">Close</button>
112
+ </div>
113
+ </div>
114
+ <div class="events-toolbar">
115
+ <input id="events-filter" type="text" placeholder="Filter events" />
116
+ <div class="count">Total: <span id="events-count">0</span></div>
117
+ </div>
118
+ <div class="events-list" id="events-list"></div>
119
+ </div>
120
+ `;
121
+ }
122
+
123
+ renderStyles() {
124
+ return `
125
+ #events-debugger {
126
+ position: fixed;
127
+ bottom: 20px;
128
+ right: 20px;
129
+ width: min(360px, calc(100vw - 40px));
130
+ max-height: 60vh;
131
+ background: var(--primary-background-color);
132
+ border: 1px solid var(--medium-color);
133
+ border-radius: 12px;
134
+ box-shadow: 0 16px 32px rgba(0, 0, 0, 0.15);
135
+ display: none;
136
+ flex-direction: column;
137
+ z-index: 10001;
138
+ overflow: hidden;
139
+ }
140
+
141
+ #events-debugger.active {
142
+ display: flex;
143
+ }
144
+
145
+ #events-debugger * {
146
+ box-sizing: border-box;
147
+ }
148
+
149
+ .events-header {
150
+ display: flex;
151
+ justify-content: space-between;
152
+ align-items: center;
153
+ padding: 12px 14px;
154
+ background: var(--tertiary-background-color);
155
+ border-bottom: 1px solid var(--medium-color);
156
+ }
157
+
158
+ .events-header .title {
159
+ font-weight: 600;
160
+ color: var(--font-primary-color);
161
+ }
162
+
163
+ .events-header .actions {
164
+ display: flex;
165
+ gap: 8px;
166
+ }
167
+
168
+ .events-header .btn {
169
+ padding: 6px 10px;
170
+ border-radius: 6px;
171
+ border: 1px solid var(--medium-color);
172
+ background: var(--primary-background-color);
173
+ color: var(--font-primary-color);
174
+ cursor: pointer;
175
+ font-size: 12px;
176
+ }
177
+
178
+ .events-toolbar {
179
+ display: flex;
180
+ gap: 10px;
181
+ align-items: center;
182
+ padding: 10px 12px;
183
+ border-bottom: 1px solid var(--medium-color);
184
+ }
185
+
186
+ .events-toolbar input {
187
+ flex: 1;
188
+ min-width: 0;
189
+ padding: 6px 8px;
190
+ border-radius: 6px;
191
+ border: 1px solid var(--medium-color);
192
+ background: var(--primary-background-color);
193
+ color: var(--font-primary-color);
194
+ }
195
+
196
+ .events-list {
197
+ padding: 10px 12px;
198
+ overflow: auto;
199
+ display: flex;
200
+ flex-direction: column;
201
+ gap: 8px;
202
+ }
203
+
204
+ .event-row {
205
+ display: flex;
206
+ justify-content: space-between;
207
+ padding: 8px 10px;
208
+ background: var(--tertiary-background-color);
209
+ border-radius: 6px;
210
+ border: 1px solid var(--medium-color);
211
+ gap: 8px;
212
+ }
213
+
214
+ .event-name {
215
+ font-family: monospace;
216
+ font-size: 12px;
217
+ color: var(--font-primary-color);
218
+ overflow: hidden;
219
+ text-overflow: ellipsis;
220
+ white-space: nowrap;
221
+ }
222
+
223
+ .event-count {
224
+ font-weight: 600;
225
+ color: var(--primary-color);
226
+ }
227
+
228
+ .empty {
229
+ color: var(--font-secondary-color);
230
+ font-size: 12px;
231
+ text-align: center;
232
+ padding: 12px 0;
233
+ }
234
+ `;
235
+ }
236
+ }
237
+
238
+ customElements.define('slice-eventmanager-debugger', EventManagerDebugger);
@@ -1,104 +1,146 @@
1
- import Log from './Log.js';
2
-
3
- export default class Logger {
4
- constructor() {
5
- this.logs = [];
6
- this.logEnabled = slice.loggerConfig.enabled;
7
- this.showLogsConfig = slice.loggerConfig.showLogs;
8
- console.log(slice.loggerConfig)
9
-
10
- this.showLog = function showLog(log) {
11
- if (!this.showLogsConfig) return;
12
-
13
- const logType = log.logType;
14
-
15
- Object.keys(this.showLogsConfig).forEach((logConfig) => {
16
- if (this.showLogsConfig[logConfig][logType] === true) {
17
- switch (logConfig) {
18
- case 'console':
19
- switch (logType) {
20
- case logTypes.ERROR:
21
- console.error(
22
- `\x1b[31mERROR\x1b[0m - ${log.componentCategory} - ${log.componentSliceId} - ${log.message} - ${log.error}`
23
- );
24
- break;
25
- case logTypes.WARNING:
26
- console.warn(
27
- `\x1b[33m⚠ WARNING\x1b[0m - ${log.componentCategory} - ${log.componentSliceId} - ${log.message}`
28
- );
29
- break;
30
- case logTypes.INFO:
31
- console.log(
32
- `\x1b[32m✔ INFO\x1b[0m - ${log.componentCategory} - ${log.componentSliceId} - ${log.message}`
33
- );
34
- break;
35
- default:
36
- console.log(
37
- `\x1b[37mUNKNOWN\x1b[0m - ${log.componentCategory} - ${log.componentSliceId} - ${log.message}`
38
- );
39
- }
40
- break;
41
- }
42
- }
43
- });
44
- };
45
- }
46
-
47
- createLog(logType, componentSliceId, message, error = null) {
48
- if (!this.logEnabled) return;
49
- let componentName;
50
-
51
- try {
52
- componentName = slice.controller.activeComponents.get(componentSliceId).constructor.name;
53
- } catch (error) {
54
- componentName = componentSliceId;
55
- }
56
-
57
- let componentCategory = slice.controller.getComponentCategory(componentName);
58
- if (componentSliceId === 'Slice' || componentSliceId === 'ThemeManager') componentCategory = 'Structural';
59
- const log = new Log(logType, componentCategory, componentSliceId, message, error);
60
- this.logs.push(log);
61
- this.showLog(log);
62
- }
63
-
64
- logError(componentSliceId, message, error) {
65
- this.createLog(logTypes.ERROR, componentSliceId, message, error);
66
- }
67
-
68
- logWarning(componentSliceId, message) {
69
- this.createLog(logTypes.WARNING, componentSliceId, message);
70
- }
71
-
72
- logInfo(componentSliceId, message) {
73
- this.createLog(logTypes.INFO, componentSliceId, message);
74
- }
75
-
76
- getLogs() {
77
- return this.logs;
78
- }
79
-
80
- clearLogs() {
81
- this.logs = [];
82
- }
83
-
84
- getLogsByLogType(type) {
85
- return this.logs.filter((log) => log.logType === type);
86
- }
87
-
88
- getLogsByComponentCategory(componentCategory) {
89
- return this.logs.filter((log) => log.componentCategory === componentCategory);
90
- }
91
-
92
- getLogsByComponent(componentSliceId) {
93
- return this.logs.filter((log) => log.componentSliceId === componentSliceId);
94
- }
95
- }
96
-
97
- // En esta misma idea, se tiene que tomar en cuenta que el componente de ToastAlert será un toastProvider y que solo debe
98
- // haber un toastProvider en la página, por lo que se debe implementar un Singleton para el ToastProvider
99
-
100
- const logTypes = {
101
- ERROR: 'error',
102
- WARNING: 'warning',
103
- INFO: 'info',
104
- };
1
+ import Log from './Log.js';
2
+
3
+ export default class Logger {
4
+ constructor() {
5
+ this.logs = [];
6
+ this.logEnabled = slice.loggerConfig.enabled;
7
+ this.showLogsConfig = slice.loggerConfig.showLogs;
8
+ console.log(slice.loggerConfig)
9
+
10
+ this.showLog = function showLog(log) {
11
+ if (!this.showLogsConfig) return;
12
+
13
+ const logType = log.logType;
14
+
15
+ Object.keys(this.showLogsConfig).forEach((logConfig) => {
16
+ if (this.showLogsConfig[logConfig][logType] === true) {
17
+ switch (logConfig) {
18
+ case 'console':
19
+ switch (logType) {
20
+ case logTypes.ERROR:
21
+ console.error(
22
+ `\x1b[31mERROR\x1b[0m - ${log.componentCategory} - ${log.componentSliceId} - ${log.message} - ${log.error}`
23
+ );
24
+ break;
25
+ case logTypes.WARNING:
26
+ console.warn(
27
+ `\x1b[33m⚠ WARNING\x1b[0m - ${log.componentCategory} - ${log.componentSliceId} - ${log.message}`
28
+ );
29
+ break;
30
+ case logTypes.INFO:
31
+ console.log(
32
+ `\x1b[32m✔ INFO\x1b[0m - ${log.componentCategory} - ${log.componentSliceId} - ${log.message}`
33
+ );
34
+ break;
35
+ default:
36
+ console.log(
37
+ `\x1b[37mUNKNOWN\x1b[0m - ${log.componentCategory} - ${log.componentSliceId} - ${log.message}`
38
+ );
39
+ }
40
+ break;
41
+ }
42
+ }
43
+ });
44
+ };
45
+ }
46
+
47
+ createLog(logType, componentSliceId, message, error = null) {
48
+ if (!this.logEnabled) return;
49
+ let componentName;
50
+
51
+ try {
52
+ componentName = slice.controller.activeComponents.get(componentSliceId).constructor.name;
53
+ } catch (error) {
54
+ componentName = componentSliceId;
55
+ }
56
+
57
+ let componentCategory = slice.controller.getComponentCategory(componentName);
58
+ if (componentSliceId === 'Slice' || componentSliceId === 'ThemeManager') componentCategory = 'Structural';
59
+ const log = new Log(logType, componentCategory, componentSliceId, message, error);
60
+ this.logs.push(log);
61
+ this.showLog(log);
62
+ }
63
+
64
+ /**
65
+ * Log an error message.
66
+ * @param {string} componentSliceId
67
+ * @param {string} message
68
+ * @param {any} [error]
69
+ * @returns {void}
70
+ */
71
+ logError(componentSliceId, message, error) {
72
+ this.createLog(logTypes.ERROR, componentSliceId, message, error);
73
+ }
74
+
75
+ /**
76
+ * Log a warning message.
77
+ * @param {string} componentSliceId
78
+ * @param {string} message
79
+ * @returns {void}
80
+ */
81
+ logWarning(componentSliceId, message) {
82
+ this.createLog(logTypes.WARNING, componentSliceId, message);
83
+ }
84
+
85
+ /**
86
+ * Log an info message.
87
+ * @param {string} componentSliceId
88
+ * @param {string} message
89
+ * @returns {void}
90
+ */
91
+ logInfo(componentSliceId, message) {
92
+ this.createLog(logTypes.INFO, componentSliceId, message);
93
+ }
94
+
95
+ /**
96
+ * Get all logs.
97
+ * @returns {Array}
98
+ */
99
+ getLogs() {
100
+ return this.logs;
101
+ }
102
+
103
+ /**
104
+ * Clear all logs.
105
+ * @returns {void}
106
+ */
107
+ clearLogs() {
108
+ this.logs = [];
109
+ }
110
+
111
+ /**
112
+ * Filter logs by type.
113
+ * @param {string} type
114
+ * @returns {Array}
115
+ */
116
+ getLogsByLogType(type) {
117
+ return this.logs.filter((log) => log.logType === type);
118
+ }
119
+
120
+ /**
121
+ * Filter logs by component category.
122
+ * @param {string} componentCategory
123
+ * @returns {Array}
124
+ */
125
+ getLogsByComponentCategory(componentCategory) {
126
+ return this.logs.filter((log) => log.componentCategory === componentCategory);
127
+ }
128
+
129
+ /**
130
+ * Filter logs by component sliceId.
131
+ * @param {string} componentSliceId
132
+ * @returns {Array}
133
+ */
134
+ getLogsByComponent(componentSliceId) {
135
+ return this.logs.filter((log) => log.componentSliceId === componentSliceId);
136
+ }
137
+ }
138
+
139
+ // En esta misma idea, se tiene que tomar en cuenta que el componente de ToastAlert será un toastProvider y que solo debe
140
+ // haber un toastProvider en la página, por lo que se debe implementar un Singleton para el ToastProvider
141
+
142
+ const logTypes = {
143
+ ERROR: 'error',
144
+ WARNING: 'warning',
145
+ INFO: 'info',
146
+ };