Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR introduces V2 event versioning and widget-scoped event communication to the Ubidots React library. Changes include new event constants and handlers, state management for widgetId, hook updates to support widget-specific messaging, comprehensive examples demonstrating the new patterns, and updated types and tests. V1 event compatibility is maintained through dual-emission handlers. Changes
Sequence DiagramssequenceDiagram
participant Widget as Widget/App
participant Provider as UbidotsProvider
participant Reducer as State Reducer
participant Handler as Message Handler
participant Parent as Parent Window
Widget->>Provider: Action (e.g., setDashboardDevice)
Provider->>Handler: Call action creator
Handler->>Parent: postMessage V1 event
Handler->>Parent: postMessage V2 event
Parent-->>Parent: Receive V1 message
Parent->>Handler: Trigger V1 handler
Handler->>Parent: postMessage V2 event
Handler->>Reducer: Dispatch Redux action
Reducer->>Provider: Update state
sequenceDiagram
participant Widget as Widget A
participant Events as useWidgetEvents
participant Listener as Message Listener
participant Parent as Parent Window
participant Widget2 as Widget B
Widget->>Events: Call emitWidgetEvent('customAction')
Events->>Parent: postMessage {event: 'v2:widget:widgetA:customAction', payload}
Widget2->>Events: onWidgetEvent('v2:widget:widgetA:*')
Events->>Listener: Register wildcard listener
Parent-->>Parent: Broadcast to all widgets
Listener->>Listener: Match v2:widget:widgetA:* pattern
Listener->>Events: Invoke callback
Events->>Widget2: Callback fired with event & payload
sequenceDiagram
participant Client as Client Window
participant Provider as UbidotsProvider
participant Handlers as Message Handlers
participant Parent as Parent Frame
Parent->>Client: postMessage V2 event (INBOUND_EVENTS_V2.TOKEN)
Client->>Handlers: handleInboundMessage (V2)
Handlers->>Handlers: Map V2 → Redux action type
Handlers->>Provider: dispatch(RECEIVED_TOKEN)
Provider->>Provider: Update state.token
Handlers->>Client: satisfiedEventsRef.add('v2:auth:token')
Handlers->>Parent: postMessage V2 event (for compatibility)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔍 PR Quality Check Summary
📋 Checks Performed:
|
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/context/messageHandlers.ts (1)
171-244: V2 handlers add only V1 event names tosatisfiedEventsRef, breaking readiness checks when V2 event names are used inreadyEventsconfiguration.The V2 handlers (lines 173–244) all add V1 event names (
'receivedToken','selectedDevices', etc.) tosatisfiedEventsRef, but theReadyEventtype explicitly allows V2 event names like'v2:auth:token'. When a consumer configuresreadyEventswith V2 names, those events will never be satisfied because the handlers only track V1 names. ThecheckReadyStatefunction checks whether each event inreadyEventsexists insatisfiedEventsRef(line 291–293), so this mismatch causes readiness to never be reached.Add the corresponding V2 event name to
satisfiedEventsRefin each V2 handler to support V2-only configurations:[INBOUND_EVENTS_V2.TOKEN]: (payload, dispatch, satisfiedEventsRef) => { dispatch({ type: ACTION_TYPES.RECEIVED_TOKEN, payload: payload as string }); satisfiedEventsRef.current.add('receivedToken'); satisfiedEventsRef.current.add('v2:auth:token'); },Apply the same pattern to all other V2 handlers.
🤖 Fix all issues with AI agents
In `@examples/dev/main.jsx`:
- Around line 5-12: The imports in main.jsx are using default imports but the
example files mostly export named components; update the import statements so
they use named imports matching the actual exports: replace default imports for
BasicUsage, CompleteWidget, WidgetEventsBasic, WidgetEventsMulti, and
WithHocsExample with named imports (e.g., { BasicUsage }, { CompleteWidget }, {
WidgetEventsBasic }, { WidgetEventsMulti }, { WithHocsExample }), and fix the
two misnamed imports by changing DeviceSelector to import {
DeviceSelectorExample } and RealTimeDashboard to import {
RealTimeDashboardExample } while keeping EventVersioningExample as the default
import since it exports default.
In `@examples/shared/EventEmitterPanel.jsx`:
- Around line 8-12: The WidgetEventsBasic component uses the wrong fallback
widgetId ('widget-demo-001') which mismatches EventEmitterPanel.jsx and the
README; update the fallback identifier in WidgetEventsBasic (the widgetId
constant/prop default used when window.widgetId is absent and any hardcoded
event strings like `v2:widget:ready:${widgetId}` or listener suffixes) to
'demo-widget-001' so emitted events and the event monitor/readme examples align
with EventEmitterPanel and documentation.
- Around line 13-17: The emitEvent function currently calls
window.parent.postMessage(message, '*') which weakens origin isolation; update
the EventEmitterPanel component to accept a targetOrigin prop (or add a required
prop) and replace the '*' with that prop when calling postMessage in emitEvent,
providing a sensible default (e.g., a deployment-specific origin or
throw/console.error if missing) and ensure the prop is validated/documented so
callers pass the explicit parent origin (e.g., when rendering <EventEmitterPanel
targetOrigin="https://trusted-parent.example.com" />).
In `@examples/widget-events-multi/README.md`:
- Around line 185-188: Update the README examples run command block that
currently shows "pnpm install" followed by "pnpm dev" to instead use "pnpm
dev:examples" so the docs launch the dedicated Vite-configured examples app;
locate the fenced bash code block containing those two commands and replace the
second line accordingly.
In `@src/context/messageHandlers.ts`:
- Around line 18-22: emitV2Event currently calls window.parent.postMessage with
'*' which leaks sensitive data to any parent; update emitV2Event (and the
postMessage usage in actions.ts) to accept or resolve a specific targetOrigin
instead of '*'—use the parent origin (e.g., window.parent.location.origin) as a
sensible default or read a configured outboundOrigin injected into the provider,
and wire this to the existing validateOrigin callback so outbound messages are
only sent to validated origins; change emitV2Event signature to accept an
optional targetOrigin or use the provider's configured outboundOrigin, and use
that value in postMessage calls.
In `@src/hooks/useWidgetEvents.ts`:
- Around line 52-65: onWidgetEvent currently stores listeners under the raw
event key (e.g., "ready") but incoming events use the full "v2:widget:...:ready"
format, so listeners never match; update onWidgetEvent to normalize the event
name to the same canonical form used by emitWidgetEvent (or accept both forms)
before storing/removing the callback, and emit a console/process warning if a
required widgetId is missing when resolving to the full "v2:widget:..." name;
look for listenersRef and onWidgetEvent in the file and ensure the same
normalization/matching logic is used when emitting in emitWidgetEvent so
callbacks registered via onWidgetEvent('ready', cb) will be invoked.
In `@vite.examples.config.ts`:
- Around line 4-18: The config currently uses __dirname (in the alias
path.resolve(__dirname, './src/index.ts')) which breaks in ESM; replace usage by
deriving a directory from import.meta.url (e.g., use fileURLToPath and
path.dirname on new URL(import.meta.url)) and pass that computed dirname into
path.resolve for the alias; update the top of the file to import or require the
helper (fileURLToPath) and compute const __dirname =
path.dirname(fileURLToPath(new URL(import.meta.url))) before calling
defineConfig so that the alias resolution in resolve.alias uses the correct
ESM-compatible directory.
🧹 Nitpick comments (4)
src/context/UbidotsReducer.ts (1)
95-96: Consider removing the unnecessary intermediate variable.The intermediate variable
radds no value and slightly reduces readability. A direct return would be cleaner and consistent with typical reducer patterns.♻️ Suggested simplification
- const r = handler ? handler(state, action) : state; - return r; + return handler ? handler(state, action) : state;examples/widget-events-basic/README.md (1)
16-18: Add language specifier to fenced code block.The linter flags this code block as missing a language specifier. Since this shows a text pattern rather than executable code, consider using
textorplaintext.♻️ Suggested fix
-``` +```text v2:widget:<eventType>:<widgetId>src/context/ubidots.tsx (1)
71-77: Consider cleanup forwindow.widgetIdon unmount or prop change.When
widgetIdchanges to a falsy value or the component unmounts,window.widgetIdremains set with the stale value. This could cause subtle bugs if multiple widgets or provider instances are used.♻️ Suggested cleanup
// Set widgetId on window and in state useEffect(() => { if (widgetId) { (window as unknown as Record<string, unknown>).widgetId = widgetId; dispatch({ type: ACTION_TYPES.SET_WIDGET_ID, payload: widgetId }); + return () => { + (window as unknown as Record<string, unknown>).widgetId = undefined; + }; } }, [widgetId]);src/context/constants.ts (1)
50-59: Consider deduplicating the shared V2 selected-devices event string.
SET_DASHBOARD_DEVICEandSET_DASHBOARD_MULTIPLE_DEVICESpoint to the same literal; a shared constant makes the intent explicit and prevents drift.♻️ Suggested tweak
+const DASHBOARD_DEVICES_SELECTED_V2 = 'v2:dashboard:devices:selected'; + export const OUTBOUND_EVENTS_V2 = { // Dashboard Events - SET_DASHBOARD_DEVICE: 'v2:dashboard:devices:selected', - SET_DASHBOARD_MULTIPLE_DEVICES: 'v2:dashboard:devices:selected', + SET_DASHBOARD_DEVICE: DASHBOARD_DEVICES_SELECTED_V2, + SET_DASHBOARD_MULTIPLE_DEVICES: DASHBOARD_DEVICES_SELECTED_V2, SET_DASHBOARD_DATE_RANGE: 'v2:dashboard:settings:daterange', SET_REAL_TIME: 'v2:dashboard:settings:rt', REFRESH_DASHBOARD: 'v2:dashboard:settings:refreshed', SET_FULL_SCREEN: 'v2:dashboard:settings:fullscreen', OPEN_DRAWER: 'v2:dashboard:drawer:open', } as const;
There was a problem hiding this comment.
Pull request overview
This PR adds V2 (v2:*) event support to the library (including widget-scoped v2:widget:* events) and expands the examples app with an interactive Event Emitter panel plus new event-focused demos.
Changes:
- Add V2 inbound/outbound event constants and update handlers/actions to emit V1+V2 for backward compatibility.
- Introduce widget event support via
useWidgetEventsand plumbwidgetIdthrough provider/state. - Add an examples gallery (new Vite config + dev entrypoint) and multiple new/updated examples + docs.
Reviewed changes
Copilot reviewed 30 out of 30 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| vite.examples.config.ts | Adds a dedicated Vite config for running the examples gallery. |
| src/types/index.ts | Extends ready event types to include V2 events and adds widgetId to state/actions. |
| src/hooks/useWidgetEvents.ts | New hook for emitting/listening to v2:widget:<event>:<widgetId> messages. |
| src/hooks/useUbidotsSelections.ts | Adds useUbidotsWidgetId selector hook. |
| src/hooks/index.ts | Re-exports the new useWidgetEvents hook. |
| src/context/ubidots.tsx | Adds widgetId prop and writes it into context state (and a window global). |
| src/context/messageHandlers.ts | Adds V2 inbound support and V1→V2 “shadow emission” for inbound events. |
| src/context/constants.ts | Adds V2 inbound/outbound event constant maps and new action type. |
| src/context/actions.ts | Updates outbound actions to emit both V1 and V2 events. |
| src/context/UbidotsReducer.ts | Adds SET_WIDGET_ID reducer handling. |
| package.json | Adds dev:examples script to run examples via the new Vite config. |
| examples/shared/EventEmitterPanel.jsx | New interactive panel to emit V1/V2/widget events for manual testing. |
| examples/shared/EventEmitterPanel.css | Styles for the EventEmitterPanel UI. |
| examples/dev/index.html | New examples gallery HTML entrypoint. |
| examples/dev/main.jsx | New examples gallery/router to render selected demos via query param. |
| examples/widget-events-basic/WidgetEventsBasic.jsx | New single-widget event example with live monitor. |
| examples/widget-events-basic/styles.css | Styles for widget-events-basic example. |
| examples/widget-events-basic/README.md | Documentation for widget-events-basic example. |
| examples/widget-events-multi/WidgetEventsMulti.jsx | New multi-widget isolated-events example with global monitor. |
| examples/widget-events-multi/styles.css | Styles for widget-events-multi example. |
| examples/widget-events-multi/README.md | Documentation for widget-events-multi example. |
| examples/event-versioning/EventVersioningExample.jsx | Updates/creates event versioning example and integrates the emitter panel. |
| examples/basic-usage/BasicUsage.jsx | Integrates the emitter panel into the basic usage example. |
| examples/device-selector/DeviceSelector.jsx | Integrates the emitter panel into the device selector example. |
| examples/real-time-dashboard/RealTimeDashboard.jsx | Integrates the emitter panel into the real-time dashboard example. |
| examples/complete-widget/CompleteWidget.jsx | Integrates the emitter panel into the complete widget example. |
| examples/with-hocs/WithHocsExample.jsx | Integrates the emitter panel into the HOCs example. |
| examples/README.md | Adds new example entries for event-versioning and widget-events demos. |
| docs/EventVersioning.md | Adds a guide describing V1/V2 compatibility and mapping. |
| README.md | Updates main README with local examples running instructions and links. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
🔍 PR Quality Check Summary
📋 Checks Performed:
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@src/context/__tests__/actions.test.ts`:
- Around line 44-47: The TypeScript error comes from accessing properties on
elements of postMessageSpy.mock.calls which are typed as unknown[]; update the
v2Call lookup to assert the call shape (e.g., cast call[0] to a known type) or
introduce a small helper/type (e.g., PostMessageCall and findV2Call) and use
that when searching for OUTBOUND_EVENTS_V2.SET_DASHBOARD_DEVICE so the
expression (call[0] as PostMessageCall).event is valid and the subsequent
expect(v2Call![0].payload) remains type-safe.
- Around line 78-82: The TypeScript compiler cannot infer the tuple type from
postMessageSpy.mock.calls.find, so add a type assertion for v2Call to silence
the error and access payload safely: when locating the call where call[0].event
=== OUTBOUND_EVENTS_V2.SET_DASHBOARD_MULTIPLE_DEVICES, assert the result
(v2Call) to a compatible type (e.g., unknown/any or a typed tuple) before using
v2Call[0].payload so the test compiles; reference the v2Call variable and
OUTBOUND_EVENTS_V2.SET_DASHBOARD_MULTIPLE_DEVICES in your change.
🧹 Nitpick comments (3)
src/hooks/__tests__/useWidgetEvents.test.tsx (3)
85-116: Redundantconsole.warnspy.
console.warnis already mocked inbeforeEach(line 12). Creating another spy here is unnecessary—you can usevi.mocked(console.warn)or simply reference the existing mock directly.Suggested fix
it('should warn and not emit when widgetId is not defined', async () => { let emitFn: ((event: string, payload?: unknown) => void) | null = null; - const consoleWarnSpy = vi.spyOn(console, 'warn'); function TestComponent() { const { emitWidgetEvent } = useWidgetEvents(); emitFn = emitWidgetEvent; return null; } render( <UbidotsProvider> <TestComponent /> </UbidotsProvider> ); await waitFor(() => { expect(emitFn).not.toBeNull(); }); // Clear any previous calls (like from ready event) postMessageSpy.mockClear(); act(() => { emitFn!('some-event', { data: 'test' }); }); - expect(consoleWarnSpy).toHaveBeenCalledWith( + expect(console.warn).toHaveBeenCalledWith( 'Cannot emit widget event: widgetId is not defined' ); expect(postMessageSpy).not.toHaveBeenCalled(); });
354-356: Missing cleanup for registered listener.Unlike the test above (lines 305-329), this test doesn't store or invoke the cleanup function. While
afterEachrestores mocks, explicitly cleaning up listeners maintains consistency and prevents potential leaks if the test setup changes.Suggested fix
+ let cleanup: (() => void) | null = null; act(() => { - onAnyFn!(callback); + cleanup = onAnyFn!(callback); }); // Simulate receiving a non-widget event act(() => { window.dispatchEvent( new MessageEvent('message', { data: { event: 'receivedToken', payload: 'some-token', }, }) ); }); expect(callback).not.toHaveBeenCalled(); + + // Cleanup + act(() => { + cleanup!(); + }); });
449-476: Consider extracting duplicated call search logic.The logic to find the ready event call is repeated twice (lines 451-458 and 461-467). You could extract it into a helper or use the result from
waitFordirectly.Suggested simplification
// Wait for ready event to be emitted + const findReadyCall = () => + postMessageSpy.mock.calls.find( + call => + call[0] && + typeof call[0] === 'object' && + 'event' in call[0] && + call[0].event === 'v2:widget:ready:lifecycle-widget' + ); + await waitFor(() => { - const readyCall = postMessageSpy.mock.calls.find( - call => - call[0] && - typeof call[0] === 'object' && - 'event' in call[0] && - call[0].event === 'v2:widget:ready:lifecycle-widget' - ); - expect(readyCall).toBeDefined(); + expect(findReadyCall()).toBeDefined(); }); - const readyCall = postMessageSpy.mock.calls.find( - call => - call[0] && - typeof call[0] === 'object' && - 'event' in call[0] && - call[0].event === 'v2:widget:ready:lifecycle-widget' - ); + const readyCall = findReadyCall(); expect(readyCall![0]).toMatchObject({
🔍 PR Quality Check Summary
📋 Checks Performed:
🎉 All checks passed! This PR is ready for review. |
🔍 PR Quality Check Summary
📋 Checks Performed:
|
fc06f35 to
d4b83f0
Compare
🔍 PR Quality Check Summary
📋 Checks Performed:
|
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/context/messageHandlers.ts (1)
38-56:⚠️ Potential issue | 🟠 MajorMark both V1 and V2 ready-event aliases when bridging these handlers.
checkReadyState()matchesreadyEventsby exact string, but this block only records the version it received. SoreadyEvents={['selectedFilters']}never resolves when the host sendsv2:dashboard:settings:filters, andreadyEvents={['v2:auth:token']}never resolves when the host still sendsreceivedToken. Emitting the other version back towindow.parentdoes not satisfy the local set.💡 Suggested direction
+function markReady( + satisfiedEventsRef: React.MutableRefObject<Set<ReadyEvent>>, + ...events: ReadyEvent[] +) { + events.forEach(event => satisfiedEventsRef.current.add(event)); +} + const messageHandlers: Record<string, MessageHandler> = { [INBOUND_EVENTS.RECEIVED_TOKEN]: (payload, dispatch, satisfiedEventsRef) => { dispatch({ type: ACTION_TYPES.RECEIVED_TOKEN, payload: payload as string }); - satisfiedEventsRef.current.add('receivedToken'); + markReady(satisfiedEventsRef, 'receivedToken', INBOUND_EVENTS_V2.TOKEN); emitV2Event(INBOUND_EVENTS_V2.TOKEN, payload); }, @@ [INBOUND_EVENTS_V2.SELECTED_FILTERS]: ( payload, dispatch, satisfiedEventsRef ) => { dispatch({ type: ACTION_TYPES.SELECTED_FILTERS, payload: payload as FilterValue[] | null, }); - satisfiedEventsRef.current.add(INBOUND_EVENTS_V2.SELECTED_FILTERS); + markReady( + satisfiedEventsRef, + 'selectedFilters', + INBOUND_EVENTS_V2.SELECTED_FILTERS + ); },Apply the same alias pairing to each V1/V2 equivalent.
Also applies to: 143-169, 174-249
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/context/messageHandlers.ts` around lines 38 - 56, When handling bridged events in messageHandlers (e.g., the INBOUND_EVENTS.RECEIVED_TOKEN and INBOUND_EVENTS.RECEIVED_JWT_TOKEN handlers), record both the V1 and V2 ready-event aliases in satisfiedEventsRef (e.g., call satisfiedEventsRef.current.add('receivedToken') and also add the corresponding V2 alias like 'v2:auth:token' or vice‑versa) so checkReadyState() can match either form; likewise, when you receive a V2 alias add the V1 alias as well. Also emit the counterpart event back to the host in addition to the existing emitV2Event (i.e., emit both versions when bridging). Apply this alias-pairing change consistently to the other bridged handler blocks referenced (around the other ranges).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/context/__tests__/messageHandlers.test.ts`:
- Line 548: The test assertions like
expect(satisfiedEventsRef.current.has('v2:dashboard:devices:selected')).toBe(true)
are too long for Prettier; reflow them into multi-line assertions so the
formatter can wrap them (e.g., break the expect call and the matcher onto
separate lines). Update the occurrences referencing
satisfiedEventsRef.current.has(...) in this test (and the same pattern at the
other noted locations) to use the wrapped/multi-line format so Prettier passes.
In `@src/context/messageHandlers.ts`:
- Around line 223-225: Prettier is failing due to the broken wrap of the add
call; update the call to a single-line call to satisfiedEventsRef.current.add
with INBOUND_EVENTS_V2.SELECTED_DASHBOARD_OBJECT as the single argument (i.e.,
collapse the multi-line invocation into one line) so the invocation of
satisfiedEventsRef.current.add(INBOUND_EVENTS_V2.SELECTED_DASHBOARD_OBJECT)
conforms to the repo formatter.
In `@src/context/ubidots.tsx`:
- Around line 64-80: The reducer initial state is being set after first render
via an effect, causing state.widgetId to be null initially and not cleared when
the prop is removed; instead set widgetId synchronously when calling useReducer
by merging the prop into the initial state (e.g., pass { ...initialState,
...initialStateOverride, widgetId: widgetId ?? null }) so state.widgetId
reflects the prop on first render, and then simplify the useEffect to only
dispatch if the incoming prop actually differs from stateRef.current.widgetId
(or remove the effect entirely if synchronous init is sufficient); reference
ACTION_TYPES.SET_WIDGET_ID, useReducer/ubidotsReducer, initialStateOverride, and
stateRef to locate the changes.
In `@src/hooks/useWidgetEvents.ts`:
- Around line 72-90: The onAnyWidgetEvent listener in useWidgetEvents.ts (and
the other message handler in the same hook) currently trusts any postMessage
with data.event starting with "v2:widget:"; update these handlers
(onAnyWidgetEvent and the effect that registers the other message listener) to
validate the message origin before calling callbacks by either calling the
provider's validateOrigin function (thread it into useWidgetEvents via
props/context and use it to accept/reject events) or at minimum checking
ev.source === window.parent (and comparing ev.origin if available) so only
trusted frames trigger onWidgetEvent/onAnyWidgetEvent.
---
Outside diff comments:
In `@src/context/messageHandlers.ts`:
- Around line 38-56: When handling bridged events in messageHandlers (e.g., the
INBOUND_EVENTS.RECEIVED_TOKEN and INBOUND_EVENTS.RECEIVED_JWT_TOKEN handlers),
record both the V1 and V2 ready-event aliases in satisfiedEventsRef (e.g., call
satisfiedEventsRef.current.add('receivedToken') and also add the corresponding
V2 alias like 'v2:auth:token' or vice‑versa) so checkReadyState() can match
either form; likewise, when you receive a V2 alias add the V1 alias as well.
Also emit the counterpart event back to the host in addition to the existing
emitV2Event (i.e., emit both versions when bridging). Apply this alias-pairing
change consistently to the other bridged handler blocks referenced (around the
other ranges).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: fef8c4ee-4e58-4561-bddd-d1f9d0df0fea
📒 Files selected for processing (9)
src/context/UbidotsReducer.tssrc/context/__tests__/actions.test.tssrc/context/__tests__/messageHandlers.test.tssrc/context/actions.tssrc/context/messageHandlers.tssrc/context/ubidots.tsxsrc/hooks/__tests__/useUbidotsActions.test.tsxsrc/hooks/__tests__/useWidgetEvents.test.tsxsrc/hooks/useWidgetEvents.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/context/UbidotsReducer.ts
🔍 PR Quality Check Summary
📋 Checks Performed:
|
ChristianECG
left a comment
There was a problem hiding this comment.
Queda aprobado, sujeto a que se haga el QA correspondiente de acuerdo con lo conversado con el autor del PR.
🔍 PR Quality Check Summary
📋 Checks Performed:
|
🔍 PR Quality Check Summary
📋 Checks Performed:
|
Pull Request
📝 Descripción
Se agrego soporte para todos los events de V2
Se agregó un Event Emitter Panel interactivo para facilitar el testing de eventos de widgets en los ejemplos de desarrollo. Además, se crearon dos nuevos ejemplos completos que demuestran el uso de eventos de widgets.
Cambios principales:
v2:*🔗 Issues Relacionados
https://app.clickup.com/t/9013371168/PD-284
🧪 Tipo de Cambio
🧪 Testing
pnpm test)pnpm lint)pnpm typecheck)pnpm build)Cómo probar
pnpm dev:exampleshttp://localhost:3000📸 Screenshots
✅ Checklist
📋 Notas Adicionales
Archivos nuevos:
examples/shared/EventEmitterPanel.jsx- Componente reutilizable del panelexamples/shared/EventEmitterPanel.css- Estilos del panelexamples/widget-events-basic/WidgetEventsBasic.jsx- Ejemplo básicoexamples/widget-events-basic/WidgetEventsBasic.css- Estilos del ejemplo básicoexamples/widget-events-multi/WidgetEventsMulti.jsx- Ejemplo multi-widgetexamples/widget-events-multi/WidgetEventsMulti.css- Estilos del ejemplo multiArchivos modificados:
examples/dev/main.jsx- Agregados nuevos ejemplos al router + correcciones ESLintexamples/event-versioning/EventVersioningExample.jsx- Correcciones ESLintEventos V2 implementados:
Autenticación:
v2:auth:token- Token de autenticación V2v2:auth:jwt- JWT token V2Dashboard:
v2:dashboard:self- Información del dashboardv2:dashboard:devices:self- Device propiov2:dashboard:devices:selected- Devices seleccionadosv2:dashboard:settings:daterange- Rango de fechasv2:dashboard:settings:rt- Estado de real-timev2:dashboard:settings:filters- Filtros aplicadosv2:dashboard:settings:refreshed- Dashboard refrescadoWidget:
v2:widget:ready:${widgetId}- Widget listov2:widget:loaded:${widgetId}- Widget cargadov2:widget:error:${widgetId}- Error en widgetv2:widget:customAction:${widgetId}- Acción personalizadaCaracterísticas del EventEmitterPanel:
{ event, payload }Compatibilidad:
Todos los archivos pasan
pnpm lintsin errores ni warnings.Summary by CodeRabbit
New Features
Documentation
Chores