From dbc6f5e08ca363898fe8bb305e3c3decc2dba4af Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Tue, 4 Aug 2026 19:36:36 +0200 Subject: [PATCH] fix(realtime): force-WS option and polish connection popup UI Add PUSHER_FORCE_WS so Echo/Pusher can prefer plain WebSocket transports, redesign the real-time connection warning popup, and give copy-button inputs durable right padding in settings forms. --- config/constants.php | 2 + docker-compose-maxio.dev.yml | 1 + docker-compose.dev.yml | 1 + resources/css/app.css | 11 +- .../deployment/configuration-diff.blade.php | 2 +- .../components/forms/copy-button.blade.php | 9 +- resources/views/layouts/base.blade.php | 14 +- .../views/livewire/layout-popups.blade.php | 121 ++++++++++++------ resources/views/v5/app.blade.php | 12 +- tests/Feature/LayoutPopupsUiTest.php | 27 ++++ .../PasswordVisibilityComponentTest.php | 24 ++++ .../Feature/ResourceDetailsVisibilityTest.php | 16 ++- 12 files changed, 188 insertions(+), 52 deletions(-) create mode 100644 tests/Feature/LayoutPopupsUiTest.php diff --git a/config/constants.php b/config/constants.php index 051cc6833..64d8afcc1 100644 --- a/config/constants.php +++ b/config/constants.php @@ -42,6 +42,8 @@ return [ 'host' => env('PUSHER_HOST'), 'port' => env('PUSHER_PORT'), 'app_key' => env('PUSHER_APP_KEY'), + 'scheme' => env('PUSHER_SCHEME', 'http'), + 'force_ws' => filter_var(env('PUSHER_FORCE_WS', false), FILTER_VALIDATE_BOOLEAN), ], 'migration' => [ diff --git a/docker-compose-maxio.dev.yml b/docker-compose-maxio.dev.yml index 0e59e158c..08c7fa20f 100644 --- a/docker-compose-maxio.dev.yml +++ b/docker-compose-maxio.dev.yml @@ -21,6 +21,7 @@ services: PUSHER_HOST: "${PUSHER_HOST:-}" PUSHER_PORT: "${PUSHER_PORT:-}" PUSHER_SCHEME: "${PUSHER_SCHEME:-http}" + PUSHER_FORCE_WS: "${PUSHER_FORCE_WS:-false}" PUSHER_APP_ID: "${PUSHER_APP_ID:-coolify}" PUSHER_APP_KEY: "${PUSHER_APP_KEY:-coolify}" PUSHER_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}" diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 7519a599b..063e66f4a 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -29,6 +29,7 @@ services: PUSHER_HOST: "${PUSHER_HOST:-}" PUSHER_PORT: "${PUSHER_PORT:-}" PUSHER_SCHEME: "${PUSHER_SCHEME:-http}" + PUSHER_FORCE_WS: "${PUSHER_FORCE_WS:-false}" PUSHER_APP_ID: "${PUSHER_APP_ID:-coolify}" PUSHER_APP_KEY: "${PUSHER_APP_KEY:-coolify}" PUSHER_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}" diff --git a/resources/css/app.css b/resources/css/app.css index e9e86a83e..dcebc2354 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -364,6 +364,11 @@ tr td:first-child { padding-right: 2.5rem; } +/* Same durable clearance for copy-affordance inputs (utility pr-* loses to settings CSS). */ +.input.input-with-copy-button { + padding-right: 2.5rem; +} + .lds-heart { animation: lds-heart 1.2s infinite cubic-bezier(0.215, 0.61, 0.355, 1); } @@ -1075,11 +1080,13 @@ body.terminal-is-fullscreen .terminal-fullscreen-shell [data-terminal-mobile-too box-shadow: none !important; } -/* Keep password toggle clear of the value inside denser settings inputs */ +/* Keep password toggle / copy button clear of the value inside denser settings inputs */ .application-settings-workspace .input.input-with-password-toggle, .application-settings-workspace .input[type="password"], +.application-settings-workspace .input.input-with-copy-button, .application-settings-form .input.input-with-password-toggle, -.application-settings-form .input[type="password"] { +.application-settings-form .input[type="password"], +.application-settings-form .input.input-with-copy-button { padding-right: 2.5rem; } diff --git a/resources/views/components/deployment/configuration-diff.blade.php b/resources/views/components/deployment/configuration-diff.blade.php index 8b304e6a2..53edf455c 100644 --- a/resources/views/components/deployment/configuration-diff.blade.php +++ b/resources/views/components/deployment/configuration-diff.blade.php @@ -90,7 +90,7 @@ - diff --git a/resources/views/components/forms/copy-button.blade.php b/resources/views/components/forms/copy-button.blade.php index 61233b2ca..e89203902 100644 --- a/resources/views/components/forms/copy-button.blade.php +++ b/resources/views/components/forms/copy-button.blade.php @@ -6,21 +6,22 @@ @endif
diff --git a/resources/views/layouts/base.blade.php b/resources/views/layouts/base.blade.php index 650865721..3ee2ff5f2 100644 --- a/resources/views/layouts/base.blade.php +++ b/resources/views/layouts/base.blade.php @@ -171,7 +171,15 @@ } } @auth + @php + $pusherForceWs = (bool) config('constants.pusher.force_ws'); + @endphp window.Pusher = Pusher; + @if ($pusherForceWs) + if (window.Pusher && window.Pusher.Runtime) { + window.Pusher.Runtime.getProtocol = function () { return 'http:'; }; + } + @endif const EchoConstructor = typeof Echo === 'function' ? Echo : Echo.default; window.Echo = new EchoConstructor({ broadcaster: 'pusher', @@ -181,13 +189,11 @@ wsPort: "{{ getRealtime() }}", wssPort: "{{ getRealtime() }}", forceTLS: false, - encrypted: true, + encrypted: @json($pusherForceWs ? false : true), enableStats: false, enableLogging: true, - enabledTransports: ['ws', 'wss'], disableStats: true, - // Add auto reconnection settings - enabledTransports: ['ws', 'wss'], + enabledTransports: @json($pusherForceWs ? ['ws'] : ['ws', 'wss']), disabledTransports: ['sockjs', 'xhr_streaming', 'xhr_polling'], // Attempt to reconnect on connection lost autoReconnect: true, diff --git a/resources/views/livewire/layout-popups.blade.php b/resources/views/livewire/layout-popups.blade.php index 210b91075..5e0ed3116 100644 --- a/resources/views/livewire/layout-popups.blade.php +++ b/resources/views/livewire/layout-popups.blade.php @@ -67,21 +67,51 @@ @if (!isCloud()) - - WARNING: Cannot connect to real-time service - - -
This will cause unusual problems on the - UI!

- Please ensure that you have opened the - required ports or get - help on Discord. + +
+ + +
+ +
+

+ Cannot connect to real-time service +

+

+ This will cause unusual problems on the UI. Open the + required ports + or get help on + Discord. +

+
+
+ +
+ + View docs + + +
- - - Acknowledge & Disable This Popup - +
@endif @@ -192,28 +222,47 @@ @if (!currentTeam()->isAnyNotificationEnabled()) - - No notifications enabled. - - - - - - - - It is - highly recommended to enable at least - one - notification channel to receive important alerts.
Visit /notification to - enable notifications.
- - - Accept and Close - - + +
+ + +
+ +
+

+ No notifications enabled +

+

+ Enable at least one notification channel so you receive important alerts. + Visit + notifications + to get started. +

+
+
+ +
+ + Open notifications + + +
+
+
+ @endif diff --git a/tests/Feature/LayoutPopupsUiTest.php b/tests/Feature/LayoutPopupsUiTest.php new file mode 100644 index 000000000..6154a25f6 --- /dev/null +++ b/tests/Feature/LayoutPopupsUiTest.php @@ -0,0 +1,27 @@ +toContain('Cannot connect to real-time service') + ->toContain('Acknowledge & disable') + ->toContain('customActions') + ->toContain('rounded-2xl border border-red-200') + ->toContain('name="alert-triangle"') + ->not->toContain('WARNING: Cannot connect to real-time service') + ->not->toContain('Acknowledge & Disable This Popup'); +}); + +test('notification reminder uses the redesigned popup shell', function () { + $view = file_get_contents(resource_path('views/livewire/layout-popups.blade.php')); + + expect($view) + ->toContain('No notifications enabled') + ->toContain('Accept and close') + ->toContain('Open notifications') + ->not->toContain('Accept and Close'); +}); diff --git a/tests/Feature/PasswordVisibilityComponentTest.php b/tests/Feature/PasswordVisibilityComponentTest.php index edbc38481..bfb4371a4 100644 --- a/tests/Feature/PasswordVisibilityComponentTest.php +++ b/tests/Feature/PasswordVisibilityComponentTest.php @@ -107,6 +107,30 @@ it('registers the eye-off2 reicon used when password value is visible', function ->toContain('M2.53033 1.46967'); }); +it('uses the same eye-off2 icon in configuration changes expand toggle', function () { + $html = view('components.deployment.configuration-diff', [ + 'diff' => [ + 'changes' => [ + [ + 'key' => 'env.SECRET', + 'section_label' => 'Environment', + 'label' => 'SECRET', + 'expandable' => true, + 'old_display_value' => 'old-***', + 'new_display_value' => 'new-***', + 'old_full_value' => 'old-secret-value', + 'new_full_value' => 'new-secret-value', + ], + ], + ], + ])->render(); + + // eye-off2 path (password inputs); not the older eye-off glyph. + expect($html) + ->toContain('M2.53033 1.46967') + ->not->toContain('M22.2954 6.31083'); +}); + it('renders env var password input before visibility toggle in tab order', function () { $html = Blade::render(''); diff --git a/tests/Feature/ResourceDetailsVisibilityTest.php b/tests/Feature/ResourceDetailsVisibilityTest.php index 762683447..90e167f13 100644 --- a/tests/Feature/ResourceDetailsVisibilityTest.php +++ b/tests/Feature/ResourceDetailsVisibilityTest.php @@ -38,9 +38,19 @@ it('renders copy fields as visible readonly controls with an accessible copy act expect($html) ->toContain('label class="flex gap-1 items-center mb-1 text-sm font-medium text-black dark:text-white"') ->toContain('readonly') - ->toContain('class="input pr-11 bg-white dark:bg-coolgray-100 dark:read-only:bg-coolgray-100 dark:read-only:text-white"') + ->toContain('input-with-copy-button') + ->toContain('copy-button') ->toContain('aria-label="Copy to clipboard"') ->toContain('title="Copy to clipboard"') - ->toContain('rounded-sm p-1.5 text-neutral-500 transition-colors hover:text-neutral-700 focus-visible:ring-2 focus-visible:ring-coollabs focus-visible:ring-offset-2 dark:text-neutral-400 dark:hover:text-white dark:focus-visible:ring-warning dark:focus-visible:ring-offset-base') - ->toContain('class="w-5 h-5 text-green-500"'); + ->toContain('class="size-[18px] text-green-500"'); +}); + +it('keeps copy button padding above settings-workspace input overrides', function () { + $css = file_get_contents(resource_path('css/app.css')); + + expect($css) + ->toContain('.input.input-with-copy-button') + ->toContain('.application-settings-workspace .input.input-with-copy-button') + ->toContain('.application-settings-form .input.input-with-copy-button') + ->toContain('padding-right: 2.5rem'); });