Skip to content

[72373]: Edited offline status banner and add header indicator#22206

Open
ihordubas99 wants to merge 1 commit intodevfrom
feature/72373-offline-mode-banner-text
Open

[72373]: Edited offline status banner and add header indicator#22206
ihordubas99 wants to merge 1 commit intodevfrom
feature/72373-offline-mode-banner-text

Conversation

@ihordubas99
Copy link
Copy Markdown
Collaborator

Ticket

https://community.openproject.org/projects/communicator-stream/work_packages/72373/activity

What are you trying to accomplish?

Add user-facing feedback for connection state in the collaborative document editor.
When the editor loses connection to the Hocuspocus server, users now see:

  1. A warning flash banner with a "Retry" button that reloads the page
  2. A "Currently offline" indicator with a cloud icon in the document page header

What approach did you choose and why?

The offline/online state is already tracked in the React useCollaboration hook via connectionError. To communicate this state to the Stimulus-based page header without tight coupling, a custom DOM event documents:connection-status-changed is dispatched from OpBlockNoteContainer whenever the connection state changes.

A new Stimulus controller documents--connection-status listens for this event and toggles the visibility of the LiveConnectionStatusComponent in the header.

The flash banners are rendered server-side via existing turbo stream infrastructure (render_warning_flash_message_via_turbo_stream / render_success_flash_message_via_turbo_stream), extended to support an optional action button.

Merge checklist

  • Added/updated tests
  • Added/updated documentation in Lookbook (patterns, previews, etc)
  • Tested major browsers (Chrome, Firefox, Edge, ...)

@ihordubas99 ihordubas99 self-assigned this Mar 5, 2026
Copy link
Copy Markdown
Member

@akabiru akabiru left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed- we'll need to:

  1. Rebase off #22125
  2. Retrieve updated designs that cater for true offline support: we cannot fetch the connection templates server side when network is offline. Proposal was to cache the connection templates server side.

Comment on lines +140 to +160
.flash-warn,
.flash-success
position: fixed
top: 10%
z-index: 999
left: 50%
transform: translateX(-50%)
width: 90%
max-width: 934px
align-items: center
border-radius: 6px

.Banner-visual
align-self: center

#connection-error-retry-button
border-radius: 6px
background-color: #F6F8FA
border: 1px solid #D0D7DE
font-size: 14px
font-weight: 600
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally when we introduce new patterns, we prefer that design team & UX team are aligned- ideally the changes also go into https://github.com/opf/primer_view_components so that they're easily reusable.


def render_success_flash_message_via_turbo_stream(**)
render_flash_message_via_turbo_stream(**, scheme: :success)
render_flash_message_via_turbo_stream(**, scheme: :success, icon: :"check")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Changing this here enforces the icon: :check on application wide as this is a shared helper. The change should be limited to our use case. The (**) arguments means we can pass the icon: :check within documents controller:

render_success_flas_message_via_turbo_stream(message:, icon: :check)

end

def render_warning_flash_message_via_turbo_stream(**)
render_flash_message_via_turbo_stream(**, scheme: :warning, icon: :"cloud-offline")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto: we should not enforce the icon: :"cloud-offline" within this shared helper

OpenProjectStimulusApplication.preregister('check-all', CheckAllController);
OpenProjectStimulusApplication.preregister('checkable', CheckableController);
OpenProjectStimulusApplication.preregister('truncation', TruncationController);
OpenProjectStimulusApplication.preregister('documents--connection-status', ConnectionStatusController);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dynamic stimulus controllers should not be pre-registered. They are lazy-loaded. See https://www.openproject.org/docs/development/concepts/stimulus/

Comment on lines +81 to +88
// Dispatch a custom DOM event to notify the Stimulus connection-status controller
// about the current connection state. This bridges React (BlockNote editor) and
// Stimulus, allowing the header indicator to show/hide without direct coupling.
useEffect(() => {
document.dispatchEvent(new CustomEvent('documents:connection-status-changed', {
detail:{ offline:connectionError }
}));
}, [connectionError]);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we need a new event based mechanism as we already introduced https://github.com/opf/openproject/blob/dev/frontend/src/react/helpers/connection-template-fetcher.ts that should react to connectionError state already- and conventionally we want to encapsulate effects within the useCollaboration hook.

const { offline } = (event as CustomEvent<{ offline:boolean }>).detail;
this.indicatorTarget.style.display = offline ? '' : 'none';
};
} No newline at end of file
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@judithroth judithroth removed their request for review April 23, 2026 07:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants