Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 0 additions & 49 deletions app/javascript/controllers/admin_sso_form_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,29 +65,6 @@ export default class extends Controller {
this.samlCallbackUrlTarget.textContent = `${baseUrl}/auth/${providerName}/callback`
}

copySamlCallback(event) {
event.preventDefault()

if (!this.hasSamlCallbackUrlTarget) return

const callbackUrl = this.samlCallbackUrlTarget.textContent

navigator.clipboard.writeText(callbackUrl).then(() => {
const button = event.currentTarget
const originalText = button.innerHTML
button.innerHTML = '<svg class="w-4 h-4 inline" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg> Copied!'
button.classList.add('text-green-600')

setTimeout(() => {
button.innerHTML = originalText
button.classList.remove('text-green-600')
}, 2000)
}).catch(err => {
console.error('Failed to copy:', err)
alert('Failed to copy to clipboard')
})
}

async validateIssuer(event) {
const issuerInput = event.target
const issuer = issuerInput.value.trim()
Expand Down Expand Up @@ -129,32 +106,6 @@ export default class extends Controller {
}
}

copyCallback(event) {
event.preventDefault()

const callbackDisplay = this.callbackUrlTarget
if (!callbackDisplay) return

const callbackUrl = callbackDisplay.textContent

// Copy to clipboard
navigator.clipboard.writeText(callbackUrl).then(() => {
// Show success feedback
const button = event.currentTarget
const originalText = button.innerHTML
button.innerHTML = '<svg class="w-4 h-4 inline" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg> Copied!'
button.classList.add('text-green-600')

setTimeout(() => {
button.innerHTML = originalText
button.classList.remove('text-green-600')
}, 2000)
}).catch(err => {
console.error('Failed to copy:', err)
alert('Failed to copy to clipboard')
})
}

showValidationMessage(input, message, type) {
// Remove any existing validation message
const existingMessage = input.parentElement.querySelector('.validation-message')
Expand Down
22 changes: 12 additions & 10 deletions app/views/admin/sso_providers/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,12 @@

<div data-oidc-field class="<%= "hidden" unless sso_provider.strategy == "openid_connect" %>">
<label class="block text-sm font-medium text-primary mb-1">Callback URL</label>
<div class="flex items-center gap-2">
<code class="flex-1 bg-surface px-3 py-2 rounded text-sm text-secondary overflow-x-auto"
data-admin-sso-form-target="callbackUrl"><%= "#{request.base_url}/auth/#{sso_provider.name.presence || 'PROVIDER_NAME'}/callback" %></code>
<div class="flex items-center gap-2 min-w-0" data-controller="clipboard">
<code class="flex-1 min-w-0 bg-surface px-3 py-2 rounded text-sm text-secondary overflow-x-auto break-all whitespace-pre-wrap"
data-admin-sso-form-target="callbackUrl"
data-clipboard-target="source"><%= "#{request.base_url}/auth/#{sso_provider.name.presence || 'PROVIDER_NAME'}/callback" %></code>
<button type="button"
data-action="click->admin-sso-form#copyCallback"
data-action="clipboard#copy"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Provide required clipboard icon targets

clipboard#copy now handles these SSO buttons, but this markup only defines data-clipboard-target="source". The shared controller’s showSuccess method unconditionally reads iconDefaultTarget/iconSuccessTarget (app/javascript/controllers/clipboard_controller.js), so clicking this button throws a missing-target error after writeText resolves and falls into the catch path. In practice this produces a false “copy failed” error and no success feedback on every click for the new SSO callback copy UI.

Useful? React with 👍 / 👎.

class="p-2 text-secondary hover:text-primary shrink-0"
title="Copy to clipboard">
<%= icon "copy", class: "w-4 h-4" %>
Expand Down Expand Up @@ -173,11 +174,12 @@

<div>
<label class="block text-sm font-medium text-primary mb-1">SP Callback URL (ACS URL)</label>
<div class="flex items-center gap-2">
<code class="flex-1 bg-surface px-3 py-2 rounded text-sm text-secondary overflow-x-auto"
data-admin-sso-form-target="samlCallbackUrl"><%= "#{request.base_url}/auth/#{sso_provider.name.presence || 'PROVIDER_NAME'}/callback" %></code>
<div class="flex items-center gap-2 min-w-0" data-controller="clipboard">
<code class="flex-1 min-w-0 bg-surface px-3 py-2 rounded text-sm text-secondary overflow-x-auto break-all whitespace-pre-wrap"
data-admin-sso-form-target="samlCallbackUrl"
data-clipboard-target="source"><%= "#{request.base_url}/auth/#{sso_provider.name.presence || 'PROVIDER_NAME'}/callback" %></code>
<button type="button"
data-action="click->admin-sso-form#copySamlCallback"
data-action="clipboard#copy"
class="p-2 text-secondary hover:text-primary shrink-0"
title="Copy to clipboard">
<%= icon "copy", class: "w-4 h-4" %>
Expand Down Expand Up @@ -268,7 +270,7 @@
<p class="text-xs text-secondary -mt-2"><%= t("admin.sso_providers.form.prompt_help") %></p>
</div>

<div class="flex justify-between items-center gap-3 pt-4 border-t border-primary">
<div class="flex flex-wrap justify-between items-center gap-3 pt-4 border-t border-primary">
<div>
<% if sso_provider.persisted? %>
<button type="button"
Expand All @@ -281,7 +283,7 @@
<% end %>
</div>

<div class="flex gap-3">
<div class="flex flex-wrap gap-3">
<%= link_to "Cancel", admin_sso_providers_path, class: "px-4 py-2 text-sm font-medium text-secondary hover:text-primary" %>
<%= form.submit sso_provider.persisted? ? "Update Provider" : "Create Provider",
class: "px-4 py-2 bg-primary text-inverse rounded-lg text-sm font-medium hover:bg-primary/90" %>
Expand Down
10 changes: 5 additions & 5 deletions app/views/layouts/settings.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
</div>
</div>

<main class="grow flex h-full">
<div class="relative max-w-4xl mx-auto flex flex-col w-full h-full">
<div class="grow flex flex-col overflow-y-auto overflow-x-hidden overscroll-contain [-webkit-overflow-scrolling:touch]">
<main class="grow flex h-full min-w-0">
<div class="relative max-w-4xl mx-auto flex flex-col w-full h-full min-w-0">
<div class="grow flex flex-col overflow-y-auto overflow-x-hidden overscroll-contain [-webkit-overflow-scrolling:touch] min-w-0">
<div class="sticky top-0 z-10 px-3 md:px-10 pt-1.5 md:pt-3 pb-3 bg-surface border-b border-tertiary shrink-0">
<% if content_for?(:breadcrumbs) %>
<%= yield :breadcrumbs %>
<% else %>
<%= render "layouts/shared/breadcrumbs", breadcrumbs: @breadcrumbs %>
<% end %>

<div class="flex items-center justify-between gap-4 mt-1.5 min-h-9">
<div class="flex flex-wrap items-center justify-between gap-3 mt-1.5 min-h-9">
<% if content_for?(:page_title) %>
<h1 class="text-primary text-xl font-medium">
<%= content_for :page_title %>
Expand All @@ -25,7 +25,7 @@
<div></div>
<% end %>
<% if content_for?(:page_actions) %>
<div class="flex items-center gap-2 shrink-0">
<div class="flex items-center gap-2 max-w-full">
<%= yield :page_actions %>
</div>
<% end %>
Expand Down