ui-soxo-bootstrap-core 2.4.25-dev.33 → 2.4.25-dev.34

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.
@@ -18,64 +18,69 @@ import { message } from 'antd';
18
18
  * @param {Function} onMaximize - Callback when window is maximized
19
19
  */
20
20
  export function ExternalWindow({
21
- children,
22
- onClose,
23
- title = 'New Window',
24
- width = 600,
25
- height = 400,
26
- left,
27
- top,
28
- copyStyles = true,
29
- centerScreen = false,
30
- shortcuts = {},
31
- onMinimize,
32
- onMaximize
21
+ children,
22
+ onClose,
23
+ onWindowReady,
24
+ title = 'New Window',
25
+ width = 600,
26
+ height = 400,
27
+ left,
28
+ top,
29
+ copyStyles = true,
30
+ centerScreen = false,
31
+ shortcuts = {},
32
+ onMinimize,
33
+ onMaximize,
33
34
  }) {
34
- const [container, setContainer] = useState(null);
35
- const windowRef = useRef(null);
36
-
37
- // Default shortcuts
38
- const defaultShortcuts = useMemo(() => ({
39
- close: 'Escape',
40
- focus: 'Ctrl+Shift+F',
41
- ...shortcuts
42
- }), [shortcuts]);
43
-
44
- // Calculate window position
45
- const { posX, posY } = useMemo(() => {
46
- let posX = left;
47
- let posY = top;
48
-
49
- if (centerScreen) {
50
- const screenWidth = window.screen.availWidth;
51
- const screenHeight = window.screen.availHeight;
52
-
53
- if (centerScreen === 'both' || centerScreen === 'horizontal') {
54
- posX = (screenWidth - width) / 2;
55
- }
56
- if (centerScreen === 'both' || centerScreen === 'vertical') {
57
- posY = (screenHeight - height) / 2;
58
- }
59
- }
60
-
61
- return {
62
- posX: posX ?? 200,
63
- posY: posY ?? 200
64
- };
65
- }, [left, top, width, height, centerScreen]);
66
-
67
- const windowFeatures = useMemo(() =>
68
- `width=${width},height=${height},left=${posX},top=${posY},resizable=yes,scrollbars=yes`,
69
- [width, height, posX, posY]
70
- );
71
-
72
- // Initialize window document
73
- const initializeWindow = useCallback((win) => {
74
- const doc = win.document;
75
-
76
- // Write minimal HTML structure (like your working example)
77
- doc.open();
78
- doc.write(`
35
+ const [container, setContainer] = useState(null);
36
+ const windowRef = useRef(null);
37
+
38
+ // Default shortcuts
39
+ const defaultShortcuts = useMemo(
40
+ () => ({
41
+ close: 'Escape',
42
+ focus: 'Ctrl+Shift+F',
43
+ ...shortcuts,
44
+ }),
45
+ [shortcuts]
46
+ );
47
+
48
+ // Calculate window position
49
+ const { posX, posY } = useMemo(() => {
50
+ let posX = left;
51
+ let posY = top;
52
+
53
+ if (centerScreen) {
54
+ const screenWidth = window.screen.availWidth;
55
+ const screenHeight = window.screen.availHeight;
56
+
57
+ if (centerScreen === 'both' || centerScreen === 'horizontal') {
58
+ posX = (screenWidth - width) / 2;
59
+ }
60
+ if (centerScreen === 'both' || centerScreen === 'vertical') {
61
+ posY = (screenHeight - height) / 2;
62
+ }
63
+ }
64
+
65
+ return {
66
+ posX: posX ?? 200,
67
+ posY: posY ?? 200,
68
+ };
69
+ }, [left, top, width, height, centerScreen]);
70
+
71
+ const windowFeatures = useMemo(
72
+ () => `width=${width},height=${height},left=${posX},top=${posY},resizable=yes,scrollbars=yes`,
73
+ [width, height, posX, posY]
74
+ );
75
+
76
+ // Initialize window document
77
+ const initializeWindow = useCallback(
78
+ (win) => {
79
+ const doc = win.document;
80
+
81
+ // Write minimal HTML structure (like your working example)
82
+ doc.open();
83
+ doc.write(`
79
84
  <!DOCTYPE html>
80
85
  <html>
81
86
  <head>
@@ -112,114 +117,120 @@ export function ExternalWindow({
112
117
  </body>
113
118
  </html>
114
119
  `);
115
- doc.close();
116
-
117
- return doc.getElementById('root');
118
- }, [title]);
119
-
120
- // Copy styles from parent window
121
- const copyStylesToWindow = useCallback((targetWindow) => {
122
- if (!copyStyles) return;
123
-
124
- const fragment = targetWindow.document.createDocumentFragment();
125
-
126
- // Copy all stylesheets from parent
127
- Array.from(document.styleSheets).forEach(sheet => {
128
- try {
129
- if (sheet.href) {
130
- // External stylesheet
131
- const link = targetWindow.document.createElement('link');
132
- link.rel = 'stylesheet';
133
- link.href = sheet.href;
134
- fragment.appendChild(link);
135
- } else if (sheet.cssRules) {
136
- // Inline stylesheet
137
- const style = targetWindow.document.createElement('style');
138
- const cssText = Array.from(sheet.cssRules).map(r => r.cssText).join('\n');
139
- style.textContent = cssText;
140
- fragment.appendChild(style);
141
- }
142
- } catch (e) {
143
- // Silently ignore cross-origin stylesheet errors
144
- console.warn('Could not copy stylesheet:', e);
145
- }
146
- });
147
-
148
- targetWindow.document.head.appendChild(fragment);
149
- }, [copyStyles]);
150
-
151
- // Keyboard shortcut handler
152
- const createKeyDownHandler = useCallback((win) => (e) => {
153
- const key = [
154
- e.ctrlKey && 'Ctrl',
155
- e.shiftKey && 'Shift',
156
- e.altKey && 'Alt',
157
- e.metaKey && 'Meta',
158
- e.key
159
- ].filter(Boolean).join('+');
160
-
161
- if (defaultShortcuts.close && key === defaultShortcuts.close) {
162
- e.preventDefault();
163
- onClose();
164
- } else if (defaultShortcuts.focus && key === defaultShortcuts.focus) {
165
- e.preventDefault();
166
- win.focus();
167
- } else if (defaultShortcuts.minimize && key === defaultShortcuts.minimize) {
168
- e.preventDefault();
169
- win.blur();
170
- onMinimize?.();
171
- } else if (defaultShortcuts.maximize && key === defaultShortcuts.maximize) {
172
- e.preventDefault();
173
- win.moveTo(0, 0);
174
- win.resizeTo(screen.availWidth, screen.availHeight);
175
- onMaximize?.();
120
+ doc.close();
121
+
122
+ return doc.getElementById('root');
123
+ },
124
+ [title]
125
+ );
126
+
127
+ // Copy styles from parent window
128
+ const copyStylesToWindow = useCallback(
129
+ (targetWindow) => {
130
+ if (!copyStyles) return;
131
+
132
+ const fragment = targetWindow.document.createDocumentFragment();
133
+
134
+ // Copy all stylesheets from parent
135
+ Array.from(document.styleSheets).forEach((sheet) => {
136
+ try {
137
+ if (sheet.href) {
138
+ // External stylesheet
139
+ const link = targetWindow.document.createElement('link');
140
+ link.rel = 'stylesheet';
141
+ link.href = sheet.href;
142
+ fragment.appendChild(link);
143
+ } else if (sheet.cssRules) {
144
+ // Inline stylesheet
145
+ const style = targetWindow.document.createElement('style');
146
+ const cssText = Array.from(sheet.cssRules)
147
+ .map((r) => r.cssText)
148
+ .join('\n');
149
+ style.textContent = cssText;
150
+ fragment.appendChild(style);
151
+ }
152
+ } catch (e) {
153
+ // Silently ignore cross-origin stylesheet errors
154
+ console.warn('Could not copy stylesheet:', e);
176
155
  }
177
- }, [defaultShortcuts, onClose, onMinimize, onMaximize]);
178
-
179
- useEffect(() => {
180
- const win = window.open('', '', windowFeatures);
181
-
182
- if (!win) {
183
- message.error('Please allow popups for this site');
184
- onClose();
185
- return;
186
- }
187
-
188
- windowRef.current = win;
189
-
190
- // Initialize window document structure
191
- const root = initializeWindow(win);
192
-
193
- // Copy styles from parent (async to not block)
194
- requestAnimationFrame(() => {
195
- copyStylesToWindow(win);
196
- });
197
-
198
- // Set container for portal immediately
199
- setContainer(root);
200
-
201
- // Setup keyboard shortcuts
202
- const handleKeyDown = createKeyDownHandler(win);
203
- window.addEventListener('keydown', handleKeyDown);
204
- win.addEventListener('keydown', handleKeyDown);
205
-
206
- // Handle window close
207
- const handleClose = () => {
208
- setContainer(null);
209
- onClose();
210
- };
211
- win.addEventListener('beforeunload', handleClose);
212
-
213
- // Cleanup
214
- return () => {
215
- window.removeEventListener('keydown', handleKeyDown);
216
- win.removeEventListener('keydown', handleKeyDown);
217
- win.removeEventListener('beforeunload', handleClose);
218
- if (!win.closed) win.close();
219
- };
220
- // Only re-run if window features change, not on every render
221
- // eslint-disable-next-line react-hooks/exhaustive-deps
222
- }, [windowFeatures]);
223
-
224
- return container ? createPortal(children, container) : null;
225
- }
156
+ });
157
+
158
+ targetWindow.document.head.appendChild(fragment);
159
+ },
160
+ [copyStyles]
161
+ );
162
+
163
+ // Keyboard shortcut handler
164
+ const createKeyDownHandler = useCallback(
165
+ (win) => (e) => {
166
+ const key = [e.ctrlKey && 'Ctrl', e.shiftKey && 'Shift', e.altKey && 'Alt', e.metaKey && 'Meta', e.key].filter(Boolean).join('+');
167
+
168
+ if (defaultShortcuts.close && key === defaultShortcuts.close) {
169
+ e.preventDefault();
170
+ onClose();
171
+ } else if (defaultShortcuts.focus && key === defaultShortcuts.focus) {
172
+ e.preventDefault();
173
+ win.focus();
174
+ } else if (defaultShortcuts.minimize && key === defaultShortcuts.minimize) {
175
+ e.preventDefault();
176
+ win.blur();
177
+ onMinimize?.();
178
+ } else if (defaultShortcuts.maximize && key === defaultShortcuts.maximize) {
179
+ e.preventDefault();
180
+ win.moveTo(0, 0);
181
+ win.resizeTo(screen.availWidth, screen.availHeight);
182
+ onMaximize?.();
183
+ }
184
+ },
185
+ [defaultShortcuts, onClose, onMinimize, onMaximize]
186
+ );
187
+
188
+ useEffect(() => {
189
+ const win = window.open('', '', windowFeatures);
190
+
191
+ if (!win) {
192
+ message.error('Please allow popups for this site');
193
+ onClose();
194
+ return;
195
+ }
196
+ // 🔥 GIVE PARENT ACCESS + FOCUS
197
+ onWindowReady?.(win);
198
+
199
+ windowRef.current = win;
200
+
201
+ // Initialize window document structure
202
+ const root = initializeWindow(win);
203
+
204
+ // Copy styles from parent (async to not block)
205
+ requestAnimationFrame(() => {
206
+ copyStylesToWindow(win);
207
+ });
208
+
209
+ // Set container for portal immediately
210
+ setContainer(root);
211
+
212
+ // Setup keyboard shortcuts
213
+ const handleKeyDown = createKeyDownHandler(win);
214
+ window.addEventListener('keydown', handleKeyDown);
215
+ win.addEventListener('keydown', handleKeyDown);
216
+
217
+ // Handle window close
218
+ const handleClose = () => {
219
+ setContainer(null);
220
+ onClose();
221
+ };
222
+ win.addEventListener('beforeunload', handleClose);
223
+
224
+ // Cleanup
225
+ return () => {
226
+ window.removeEventListener('keydown', handleKeyDown);
227
+ win.removeEventListener('keydown', handleKeyDown);
228
+ win.removeEventListener('beforeunload', handleClose);
229
+ if (!win.closed) win.close();
230
+ };
231
+ // Only re-run if window features change, not on every render
232
+ // eslint-disable-next-line react-hooks/exhaustive-deps
233
+ }, [windowFeatures]);
234
+
235
+ return container ? createPortal(children, container) : null;
236
+ }
@@ -233,7 +233,7 @@ export default function AssignRole() {
233
233
  {/* LEFT PANEL */}
234
234
  <Card className="left-panel" bodyStyle={{ padding: 12 }}>
235
235
  <div size="small" className="user-card">
236
- <Avatar size={40}>{user?.name[0]}</Avatar>
236
+ <Avatar size={40}>{user?.name?.[0] ||''}</Avatar>
237
237
 
238
238
  <div className="user-info">
239
239
  <div>{user?.name || '--'}</div>
@@ -264,7 +264,7 @@ export default function AssignRole() {
264
264
  />,
265
265
  ]}
266
266
  >
267
- <List.Item.Meta avatar={<Avatar size={28}>{role.name[0]}</Avatar>} title={role.name} description={role.description} />
267
+ <List.Item.Meta avatar={<Avatar size={28}>{role?.name?.[0] || '-'}</Avatar>} title={role.name} description={role.description} />
268
268
  </List.Item>
269
269
  )}
270
270
  />
@@ -34,6 +34,8 @@ export default function ProcessStepsPage({ match, CustomComponents = {}, ...prop
34
34
  const [processTimings, setProcessTimings] = useState([]);
35
35
  const [timelineCollapsed, setTimelineCollapsed] = useState(true);
36
36
  const [showExternalWindow, setShowExternalWindow] = useState(false);
37
+ const [externalWin, setExternalWin] = useState(null);
38
+
37
39
  const urlParams = Location.search();
38
40
  let processId = urlParams.processId;
39
41
  const [currentProcessId, setCurrentProcessId] = useState(processId);
@@ -245,25 +247,60 @@ export default function ProcessStepsPage({ match, CustomComponents = {}, ...prop
245
247
  * - Prevents navigation beyond step boundaries.
246
248
  * - Cleans up event listeners on unmount.
247
249
  */
250
+ // useEffect(() => {
251
+ // const handleKeyDown = (event) => {
252
+ // // Handle Left Arrow key press to go to the previous step
253
+ // if (event.key === 'ArrowLeft') {
254
+ // if (activeStep > 0) {
255
+ // handlePrevious();
256
+ // }
257
+ // }
258
+ // // Handle Right Arrow key press to go to the next step
259
+ // else if (event.key === 'ArrowRight') {
260
+ // if (activeStep < steps.length - 1) {
261
+ // handleNext();
262
+ // }
263
+ // }
264
+ // };
265
+
266
+ // // externalWin?.addEventListener('keydown', handleKeyDown);
267
+ // if (externalWin instanceof Window) {
268
+ // console.log("********************************",externalWin.addEventListener)
269
+ // externalWin.addEventListener('keydown', handleKeyDown);
270
+ // }
271
+
272
+ // // showExternalWindow.addEventListener('keydown', handleKeyDown);
273
+ // console.log("LLLLLLLLLLLLLL",window.addEventListener)
274
+ // window.addEventListener('keydown', handleKeyDown);
275
+ // return () => window.removeEventListener('keydown', handleKeyDown);
276
+ // }, [activeStep, steps, handlePrevious, handleNext, externalWin]);
248
277
  useEffect(() => {
249
278
  const handleKeyDown = (event) => {
250
- // Handle Left Arrow key press to go to the previous step
251
- if (event.key === 'ArrowLeft') {
252
- if (activeStep > 0) {
253
- handlePrevious();
254
- }
279
+ if (event.key === 'ArrowLeft' && activeStep > 0) {
280
+ handlePrevious();
255
281
  }
256
- // Handle Right Arrow key press to go to the next step
257
- else if (event.key === 'ArrowRight') {
258
- if (activeStep < steps.length - 1) {
259
- handleNext();
260
- }
282
+
283
+ if (event.key === 'ArrowRight' && activeStep < steps.length - 1) {
284
+ handleNext();
261
285
  }
262
286
  };
263
287
 
264
- window.addEventListener('keydown', handleKeyDown);
265
- return () => window.removeEventListener('keydown', handleKeyDown);
266
- }, [activeStep, steps, handlePrevious, handleNext]);
288
+ // main window (document!)
289
+ document.addEventListener('keydown', handleKeyDown);
290
+
291
+ // external window (document!)
292
+ if (externalWin && externalWin.document) {
293
+ externalWin.document.addEventListener('keydown', handleKeyDown);
294
+ }
295
+
296
+ return () => {
297
+ document.removeEventListener('keydown', handleKeyDown);
298
+
299
+ if (externalWin && externalWin.document) {
300
+ externalWin.document.removeEventListener('keydown', handleKeyDown);
301
+ }
302
+ };
303
+ }, [activeStep, steps, externalWin]);
267
304
 
268
305
  /**
269
306
  * Renders the main process UI including timeline, step details,
@@ -317,6 +354,11 @@ export default function ProcessStepsPage({ match, CustomComponents = {}, ...prop
317
354
  return (
318
355
  <>
319
356
  <ExternalWindow
357
+ onWindowReady={(win) => {
358
+ console.log('>>>>>>>>>>>>>>>>>>>>>', win.addEventListener);
359
+ setExternalWin(win);
360
+ win.focus();
361
+ }}
320
362
  title={steps[activeStep]?.step_name || 'Process Step'}
321
363
  onClose={() => setShowExternalWindow(false)}
322
364
  // left={window.screenX + window.outerWidth}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ui-soxo-bootstrap-core",
3
- "version": "2.4.25-dev.33",
3
+ "version": "2.4.25-dev.34",
4
4
  "description": "All the Core Components for you to start",
5
5
  "keywords": [
6
6
  "all in one"