mirror of https://github.com/docusealco/docuseal
commit
a2d8b85549
@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class SettingsController < ApplicationController
|
||||
skip_authorization_check
|
||||
|
||||
def index; end
|
||||
end
|
||||
@ -0,0 +1,15 @@
|
||||
export default class extends HTMLElement {
|
||||
connectedCallback () {
|
||||
this.addEventListener('click', this.onClick)
|
||||
}
|
||||
|
||||
disconnectedCallback () {
|
||||
this.removeEventListener('click', this.onClick)
|
||||
}
|
||||
|
||||
onClick = (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
window.history.back()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
export default class extends HTMLElement {
|
||||
connectedCallback () {
|
||||
if (this.dataset.disabled === 'true') return
|
||||
if (!this.isMobile()) return
|
||||
if (window.innerWidth >= 768) return
|
||||
|
||||
this.querySelectorAll('a[data-turbo-frame]').forEach((link) => {
|
||||
link.dataset.turboFrame = '_top'
|
||||
})
|
||||
}
|
||||
|
||||
isMobile () {
|
||||
const isTouchWebkit = 'ontouchstart' in window && navigator.maxTouchPoints > 0 && /AppleWebKit|android/i.test(navigator.userAgent)
|
||||
|
||||
return isTouchWebkit || /iPhone|iPad|iPod/i.test(navigator.userAgent)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
export default class extends HTMLElement {
|
||||
connectedCallback () {
|
||||
this.addEventListener('scroll', this.updateFade, { passive: true })
|
||||
window.addEventListener('resize', this.updateFade)
|
||||
|
||||
this.updateFade()
|
||||
}
|
||||
|
||||
disconnectedCallback () {
|
||||
window.removeEventListener('resize', this.updateFade)
|
||||
}
|
||||
|
||||
updateFade = () => {
|
||||
const maxScroll = this.scrollWidth - this.clientWidth
|
||||
const fadeGradient = {
|
||||
right: 'linear-gradient(to right, black calc(100% - 24px), transparent)',
|
||||
left: 'linear-gradient(to right, transparent, black 24px)',
|
||||
both: 'linear-gradient(to right, transparent, black 24px, black calc(100% - 24px), transparent)'
|
||||
}
|
||||
|
||||
let state = 'none'
|
||||
|
||||
if (maxScroll > 4) {
|
||||
if (this.scrollLeft <= 4) {
|
||||
state = 'right'
|
||||
} else if (this.scrollLeft >= maxScroll - 4) {
|
||||
state = 'left'
|
||||
} else {
|
||||
state = 'both'
|
||||
}
|
||||
}
|
||||
|
||||
this.applyFade(fadeGradient[state] || '')
|
||||
}
|
||||
|
||||
applyFade (gradient) {
|
||||
this.style.maskImage = gradient
|
||||
this.style.webkitMaskImage = gradient
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
<div class="form-control">
|
||||
<%= label_tag 'user[otp_attempt]', t('two_factor_code_from_authenticator_app'), class: 'label' %>
|
||||
<%= text_field_tag 'user[otp_attempt]', nil, autofocus: true, autocomplete: 'off', placeholder: 'XXX-XXX', required: true, class: 'base-input' %>
|
||||
<%= text_field_tag 'user[otp_attempt]', nil, autofocus: true, autocomplete: 'off', inputmode: 'numeric', placeholder: 'XXXXXX', required: true, class: 'base-input' %>
|
||||
</div>
|
||||
|
||||
|
Before Width: | Height: | Size: 458 B After Width: | Height: | Size: 381 B |
|
Before Width: | Height: | Size: 497 B After Width: | Height: | Size: 447 B |
@ -0,0 +1,7 @@
|
||||
<div class="mb-2 w-full">
|
||||
<a href="<%= root_path %>" class="flex items-center space-x-0.5 font-medium">
|
||||
<%= svg_icon('arrow_left', class: 'w-4 h-4 stroke-2') %>
|
||||
<span><%= t('back') %></span>
|
||||
</a>
|
||||
</div>
|
||||
<%= render 'shared/settings_nav', expanded: true %>
|
||||
@ -1 +1 @@
|
||||
<% 'stats stat stat-figure stat-title stat-value text-accent w-fit hover:bg-white dropdown-open border-base-content/30 before:border-base-content/30' %>
|
||||
<% 'stats stat stat-figure stat-title stat-value text-accent w-fit hover:bg-white dropdown-open border-base-content/30 before:border-base-content/30 order-1 order-2 order-3 order-4 order-5 lg:inline lg:hidden' %>
|
||||
|
||||
@ -1,150 +1,168 @@
|
||||
<div class="block w-full md:w-52 flex-none">
|
||||
<menu-active>
|
||||
<ul id="account_settings_menu" class="menu px-0">
|
||||
<li class="menu-title py-0 !bg-transparent mb-3 -mt-5"><a href="<%= '/' %>" class="!bg-transparent !text-neutral font-medium flex items-center space-x-0.5"><%= svg_icon('arrow_left', class: 'w-4 h-4 stroke-2') %><span><%= t('back') %></span></a></li>
|
||||
<li class="menu-title py-0 !bg-transparent">
|
||||
<span class="!bg-transparent"><%= t('settings') %></span>
|
||||
</li>
|
||||
<li></li>
|
||||
<li>
|
||||
<%= link_to t('profile'), settings_profile_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<li>
|
||||
<%= link_to t('account'), settings_account_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% if (!Docuseal.multitenant? || EncryptedConfig.exists?(key: EncryptedConfig::EMAIL_SMTP_KEY, account: current_account)) && can?(:read, EncryptedConfig.new(key: EncryptedConfig::EMAIL_SMTP_KEY, account: current_account)) && ENV['SMTP_ADDRESS'].blank? && true_user == current_user %>
|
||||
<li>
|
||||
<%= link_to t('email'), settings_email_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% unless Docuseal.multitenant? %>
|
||||
<% if can?(:read, EncryptedConfig.new(key: EncryptedConfig::FILES_STORAGE_KEY, account: current_account)) && true_user == current_user && ENV['S3_ATTACHMENTS_BUCKET'].blank? && ENV['GCS_BUCKET'].blank? && ENV['AZURE_CONTAINER'].blank? %>
|
||||
<li>
|
||||
<%= link_to t('storage'), settings_storage_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can?(:read, EncryptedConfig.new(key: 'submitter_invitation_sms', account: current_account)) && true_user == current_user %>
|
||||
<li>
|
||||
<%= link_to 'SMS', settings_sms_path, class: 'text-base hover:bg-base-300' %>
|
||||
<% expanded = local_assigns[:expanded] %>
|
||||
<div class="<%= expanded ? 'block -mx-3 md:mx-0' : 'w-full md:w-52 flex-none' %>">
|
||||
<% unless expanded %>
|
||||
<div class="md:hidden w-full">
|
||||
<a href="<%= settings_path %>" class="flex items-center space-x-0.5 font-medium">
|
||||
<%= svg_icon('arrow_left', class: 'w-4 h-4 stroke-2') %>
|
||||
<span><%= t('settings') %></span>
|
||||
</a>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="<%= 'hidden md:block' unless expanded %>">
|
||||
<menu-active>
|
||||
<ul id="account_settings_menu" class="menu px-0">
|
||||
<% unless expanded %>
|
||||
<li class="menu-title py-0 !bg-transparent mb-3 -mt-5">
|
||||
<a href="<%= root_path %>" class="!bg-transparent !text-neutral font-medium flex items-center space-x-0.5">
|
||||
<%= svg_icon('arrow_left', class: 'w-4 h-4 stroke-2') %>
|
||||
<span><%= t('back') %></span>
|
||||
</a>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if can?(:read, AccountConfig) %>
|
||||
<li>
|
||||
<%= link_to t('notifications'), settings_notifications_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can?(:read, EncryptedConfig.new(key: EncryptedConfig::ESIGN_CERTS_KEY, account: current_account)) %>
|
||||
<li>
|
||||
<%= link_to t('e_signature'), settings_esign_path, class: 'text-base hover:bg-base-300' %>
|
||||
<li class="menu-title py-0 !bg-transparent">
|
||||
<span class="!bg-transparent"><%= t('settings') %></span>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can?(:read, AccountConfig) %>
|
||||
<li></li>
|
||||
<li>
|
||||
<%= link_to t('personalization'), settings_personalization_path, class: 'text-base hover:bg-base-300' %>
|
||||
<%= link_to t('profile'), settings_profile_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can?(:read, User) %>
|
||||
<li>
|
||||
<%= link_to t('users'), settings_users_path, class: 'text-base hover:bg-base-300' %>
|
||||
<%= link_to t('account'), settings_account_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<%= render 'shared/settings_nav_extra' %>
|
||||
<% if Docuseal.demo? || !Docuseal.multitenant? %>
|
||||
<% if can?(:read, AccessToken) %>
|
||||
<% if (!Docuseal.multitenant? || EncryptedConfig.exists?(key: EncryptedConfig::EMAIL_SMTP_KEY, account: current_account)) && can?(:read, EncryptedConfig.new(key: EncryptedConfig::EMAIL_SMTP_KEY, account: current_account)) && ENV['SMTP_ADDRESS'].blank? && true_user == current_user %>
|
||||
<li>
|
||||
<%= link_to 'API', settings_api_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
<%= link_to t('email'), settings_email_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if Docuseal.demo? || !Docuseal.multitenant? || (current_user != true_user && !current_account.testing?) %>
|
||||
<% if can?(:read, WebhookUrl) %>
|
||||
<% unless Docuseal.multitenant? %>
|
||||
<% if can?(:read, EncryptedConfig.new(key: EncryptedConfig::FILES_STORAGE_KEY, account: current_account)) && true_user == current_user && ENV['S3_ATTACHMENTS_BUCKET'].blank? && ENV['GCS_BUCKET'].blank? && ENV['AZURE_CONTAINER'].blank? %>
|
||||
<li>
|
||||
<%= link_to t('storage'), settings_storage_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can?(:read, EncryptedConfig.new(key: 'submitter_invitation_sms', account: current_account)) && true_user == current_user %>
|
||||
<li>
|
||||
<%= link_to 'SMS', settings_sms_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if can?(:read, AccountConfig) %>
|
||||
<li>
|
||||
<%= link_to 'Webhooks', settings_webhooks_path, class: 'text-base hover:bg-base-300' %>
|
||||
<%= link_to t('notifications'), settings_notifications_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if !Docuseal.demo? && can?(:manage, EncryptedConfig) && (current_user != true_user || !current_account.linked_account_account) %>
|
||||
<li>
|
||||
<%= content_for(:pro_link) || link_to(Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premises" }.to_query}", class: 'text-base hover:bg-base-300', data: { turbo: false }) do %>
|
||||
<%= t('plans') %>
|
||||
<span class="badge badge-warning"><%= t('pro') %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if !Docuseal.demo? && can?(:manage, EncryptedConfig) && (current_user == true_user || current_account.testing?) %>
|
||||
<li>
|
||||
<%= link_to Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}#{'/test' if current_account.testing?}/api") : "#{Docuseal::CONSOLE_URL}/on_premises", class: 'text-base hover:bg-base-300', data: { turbo: false } do %>
|
||||
<% if Docuseal.multitenant? %> API <% else %> <%= t('console') %> <% end %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% if Docuseal.multitenant? %>
|
||||
<% if can?(:read, EncryptedConfig.new(key: EncryptedConfig::ESIGN_CERTS_KEY, account: current_account)) %>
|
||||
<li>
|
||||
<%= link_to console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}#{'/test' if current_account.testing?}/embedding/form"), class: 'text-base hover:bg-base-300', data: { turbo: false } do %>
|
||||
<%= t('embedding') %>
|
||||
<% end %>
|
||||
<%= link_to t('e_signature'), settings_esign_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if (!Docuseal.multitenant? || can?(:manage, :saml_sso)) && can?(:read, EncryptedConfig.new(key: 'saml_configs', account: current_account)) && true_user == current_user %>
|
||||
<% if can?(:read, AccountConfig) %>
|
||||
<li>
|
||||
<%= link_to 'SSO', settings_sso_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
<%= link_to t('personalization'), settings_personalization_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if !Docuseal.multitenant? && can?(:read, McpToken) && can?(:manage, :mcp) %>
|
||||
<% if can?(:read, User) %>
|
||||
<li>
|
||||
<%= link_to 'MCP', settings_mcp_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
<%= link_to t('users'), settings_users_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<%= render 'shared/settings_nav_extra2' %>
|
||||
<% if (can?(:manage, EncryptedConfig) && current_user == true_user) || (current_user != true_user && current_account.testing?) %>
|
||||
<%= form_for '', url: testing_account_path, method: current_account.testing? ? :delete : :post, html: { class: 'w-full' } do |f| %>
|
||||
<%= render 'shared/settings_nav_extra' %>
|
||||
<% if Docuseal.demo? || !Docuseal.multitenant? %>
|
||||
<% if can?(:read, AccessToken) %>
|
||||
<li>
|
||||
<label class="flex items-center text-base hover:bg-base-300 w-full justify-between" for="testing_toggle">
|
||||
<span class="mr-2 w-full">
|
||||
<%= t('test_mode') %>
|
||||
</span>
|
||||
<submit-form data-on="change" class="flex">
|
||||
<%= f.check_box :testing_toggle, class: 'toggle toggle-sm', checked: current_account.testing? %>
|
||||
</submit-form>
|
||||
</label>
|
||||
<%= link_to 'API', settings_api_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</ul>
|
||||
</menu-active>
|
||||
<% if Docuseal.multitenant? || cannot?(:manage, :tenants) %>
|
||||
<div id="support_channels" class="mx-4 border-t border-base-300 hidden md:block">
|
||||
<div class="text-sm mt-3">
|
||||
<%= t('need_help_ask_a_question_') %>
|
||||
</div>
|
||||
<div class="flex mt-3 space-x-3">
|
||||
<div class="tooltip" data-tip="GitHub">
|
||||
<a href="<%= Docuseal::GITHUB_URL %>" target="_blank" class="btn btn-circle btn-primary btn-md">
|
||||
<%= svg_icon('brand_github', class: 'w-8 h-8') %>
|
||||
</a>
|
||||
</div>
|
||||
<div class="tooltip" data-tip="<%= t('discord_community') %>">
|
||||
<a href="<%= Docuseal::DISCORD_URL %>" target="_blank" class="btn btn-circle btn-primary btn-md">
|
||||
<%= svg_icon('brand_discord', class: 'w-8 h-8') %>
|
||||
</a>
|
||||
<% if Docuseal.demo? || !Docuseal.multitenant? || (current_user != true_user && !current_account.testing?) %>
|
||||
<% if can?(:read, WebhookUrl) %>
|
||||
<li>
|
||||
<%= link_to 'Webhooks', settings_webhooks_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if !Docuseal.demo? && can?(:manage, EncryptedConfig) && (current_user != true_user || !current_account.linked_account_account) %>
|
||||
<li>
|
||||
<%= content_for(:pro_link) || link_to(Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premises" }.to_query}", class: 'text-base hover:bg-base-300', data: { turbo: false }) do %>
|
||||
<%= t('plans') %>
|
||||
<span class="badge badge-warning"><%= t('pro') %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if !Docuseal.demo? && can?(:manage, EncryptedConfig) && (current_user == true_user || current_account.testing?) %>
|
||||
<li>
|
||||
<%= link_to Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}#{'/test' if current_account.testing?}/api") : "#{Docuseal::CONSOLE_URL}/on_premises", class: 'text-base hover:bg-base-300', data: { turbo: false } do %>
|
||||
<% if Docuseal.multitenant? %> API <% else %> <%= t('console') %> <% end %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% if Docuseal.multitenant? %>
|
||||
<li>
|
||||
<%= link_to console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}#{'/test' if current_account.testing?}/embedding/form"), class: 'text-base hover:bg-base-300', data: { turbo: false } do %>
|
||||
<%= t('embedding') %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if (!Docuseal.multitenant? || can?(:manage, :saml_sso)) && can?(:read, EncryptedConfig.new(key: 'saml_configs', account: current_account)) && true_user == current_user %>
|
||||
<li>
|
||||
<%= link_to 'SSO', settings_sso_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if !Docuseal.multitenant? && can?(:read, McpToken) && can?(:manage, :mcp) %>
|
||||
<li>
|
||||
<%= link_to 'MCP', settings_mcp_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<%= render 'shared/settings_nav_extra2' %>
|
||||
<% if (can?(:manage, EncryptedConfig) && current_user == true_user) || (current_user != true_user && current_account.testing?) %>
|
||||
<%= form_for '', url: testing_account_path, method: current_account.testing? ? :delete : :post, html: { class: 'w-full' } do |f| %>
|
||||
<li>
|
||||
<label class="flex items-center text-base hover:bg-base-300 w-full justify-between" for="testing_toggle">
|
||||
<span class="mr-2 w-full">
|
||||
<%= t('test_mode') %>
|
||||
</span>
|
||||
<submit-form data-on="change" class="flex">
|
||||
<%= f.check_box :testing_toggle, class: 'toggle toggle-sm', checked: current_account.testing? %>
|
||||
</submit-form>
|
||||
</label>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</ul>
|
||||
</menu-active>
|
||||
<% if Docuseal.multitenant? || cannot?(:manage, :tenants) %>
|
||||
<div id="support_channels" class="mx-4 border-t border-base-300 <%= 'hidden md:block' unless expanded %>">
|
||||
<div class="text-sm mt-3">
|
||||
<%= t('need_help_ask_a_question_') %>
|
||||
</div>
|
||||
<%= capture do %>
|
||||
<div class="tooltip" data-tip="<%= t('ai_assistant') %>">
|
||||
<a href="<%= Docuseal::CHATGPT_URL %>" target="_blank" class="btn btn-circle btn-primary btn-md">
|
||||
<%= svg_icon('message', class: 'w-8 h-8') %>
|
||||
<div class="flex mt-3 space-x-3">
|
||||
<div class="tooltip tooltip-no-touch" data-tip="GitHub">
|
||||
<a href="<%= Docuseal::GITHUB_URL %>" target="_blank" class="btn btn-circle btn-primary btn-md">
|
||||
<%= svg_icon('brand_github', class: 'w-8 h-8') %>
|
||||
</a>
|
||||
</div>
|
||||
<div class="tooltip tooltip-no-touch" data-tip="<%= t('discord_community') %>">
|
||||
<a href="<%= Docuseal::DISCORD_URL %>" target="_blank" class="btn btn-circle btn-primary btn-md">
|
||||
<%= svg_icon('brand_discord', class: 'w-8 h-8') %>
|
||||
</a>
|
||||
</div>
|
||||
<%= capture do %>
|
||||
<div class="tooltip tooltip-no-touch" data-tip="<%= t('ai_assistant') %>">
|
||||
<a href="<%= Docuseal::CHATGPT_URL %>" target="_blank" class="btn btn-circle btn-primary btn-md">
|
||||
<%= svg_icon('message', class: 'w-8 h-8') %>
|
||||
</a>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<a href="mailto:<%= Docuseal::SUPPORT_EMAIL %>" target="_blank" class="w-full block mt-4 underline">
|
||||
<%= Docuseal::SUPPORT_EMAIL %>
|
||||
</a>
|
||||
<% if Docuseal.version.present? && !Docuseal.multitenant? && can?(:manage, EncryptedConfig) %>
|
||||
<a href="https://github.com/docusealco/docuseal/releases" target="_blank" class="badge badge-outline text-xs block mx-auto mt-4">
|
||||
v<%= Docuseal.version %>
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
<a href="mailto:<%= Docuseal::SUPPORT_EMAIL %>" target="_blank" class="w-full block mt-4 underline text-center">
|
||||
<%= Docuseal::SUPPORT_EMAIL %>
|
||||
</a>
|
||||
<% if Docuseal.version.present? && !Docuseal.multitenant? && can?(:manage, EncryptedConfig) %>
|
||||
<a href="https://github.com/docusealco/docuseal/releases" target="_blank" class="badge badge-outline text-xs block mx-auto mt-4">
|
||||
v<%= Docuseal.version %>
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,18 +1,34 @@
|
||||
<turbo-frame id="modal">
|
||||
<turbo-modal class="modal modal-open items-start !animate-none overflow-y-auto !justify-normal md:!justify-center" data-close-after-submit="<%= local_assigns.key?(:close_after_submit) ? local_assigns[:close_after_submit] : true %>">
|
||||
<div class="absolute top-0 bottom-0 right-0 left-0" data-action="click:turbo-modal#close"></div>
|
||||
<div class="bg-base-100 min-h-screen max-h-screen md:min-h-fit md:mt-3 md:rounded-2xl relative w-full relative overflow-y-auto">
|
||||
<% if local_assigns[:title] %>
|
||||
<div class="flex justify-between bg-base-100 py-2 px-5 items-center border-b pb-2 font-medium mt-0.5">
|
||||
<span>
|
||||
<%= local_assigns[:title] %>
|
||||
</span>
|
||||
<a href="#" class="text-xl" data-action="click:turbo-modal#close">×</a>
|
||||
<% if turbo_frame_request? %>
|
||||
<turbo-frame id="modal">
|
||||
<turbo-modal class="modal modal-open items-start !animate-none overflow-y-auto !justify-normal md:!justify-center" data-close-after-submit="<%= local_assigns.key?(:close_after_submit) ? local_assigns[:close_after_submit] : true %>">
|
||||
<div class="absolute top-0 bottom-0 right-0 left-0" data-action="click:turbo-modal#close"></div>
|
||||
<div class="bg-base-100 min-h-screen max-h-screen md:min-h-fit md:mt-3 md:rounded-2xl relative w-full relative overflow-y-auto">
|
||||
<% if local_assigns[:title] %>
|
||||
<div class="flex justify-between bg-base-100 py-2 px-5 items-center border-b pb-2 font-medium mt-0.5">
|
||||
<span>
|
||||
<%= local_assigns[:title] %>
|
||||
</span>
|
||||
<a href="#" class="text-xl" data-action="click:turbo-modal#close">×</a>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="w-full md:w-[590px] overflow-y-auto" style="max-height: calc(100vh - 14px - 45px); max-height: calc(100dvh - 14px - 45px)">
|
||||
<%= yield %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="w-full md:w-[590px] overflow-y-auto" style="max-height: calc(100vh - 14px - 45px)">
|
||||
<%= yield %>
|
||||
</div>
|
||||
</turbo-modal>
|
||||
</turbo-frame>
|
||||
<% else %>
|
||||
<% if local_assigns[:title] %>
|
||||
<div class="sticky top-0 z-10 flex justify-between bg-base-100 py-2 px-5 items-center border-b pb-2 font-medium">
|
||||
<span>
|
||||
<%= local_assigns[:title] %>
|
||||
</span>
|
||||
<history-back>
|
||||
<a href="#" class="text-xl block py-2 px-5 -my-2 -mr-5">×</a>
|
||||
</history-back>
|
||||
</div>
|
||||
</turbo-modal>
|
||||
</turbo-frame>
|
||||
<% end %>
|
||||
<div class="w-full">
|
||||
<%= yield %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<div class="mt-2 mb-1">
|
||||
<div class="tooltip w-full" data-tip="<%= t('unlock_with_docuseal_pro') %>">
|
||||
<div class="tooltip tooltip-no-touch w-full" data-tip="<%= t('unlock_with_docuseal_pro') %>">
|
||||
<%= link_to submitter.sent_at? ? t('re_send_sms') : t('send_sms'), Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premises" }.to_query}", class: 'btn btn-sm btn-primary text-gray-400 w-full' %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,72 +1,136 @@
|
||||
<% query_params = params.permit(:q).merge(filter_params) %>
|
||||
<% if icon = { 'declined' => 'x_circle', 'expired' => 'clock_cancel', 'partially_completed' => 'clock_edit', 'sent' => 'send', 'opened' => 'mail_opened' }[params[:status]] %>
|
||||
<div class="flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-36 border-neutral-700">
|
||||
<%= link_to submissions_filter_path('status', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %>
|
||||
<%= svg_icon(icon, class: 'w-5 h-5 shrink-0') %>
|
||||
<span class="font-normal truncate"><%= t(params[:status]) %></span>
|
||||
<% end %>
|
||||
<%= link_to url_for(params: request.query_parameters.except('status')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %>
|
||||
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if params[:folder].present? %>
|
||||
<div class="tooltip tooltip-bottom flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-36 border-neutral-700" data-tip="<%= t('folder') %>">
|
||||
<%= link_to submissions_filter_path('folder', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %>
|
||||
<%= svg_icon('folder', class: 'w-5 h-5 shrink-0') %>
|
||||
<span class="font-normal truncate"><%= params[:folder] %></span>
|
||||
<% end %>
|
||||
<%= link_to url_for(params: request.query_parameters.except('folder')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %>
|
||||
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if params[:author].present? %>
|
||||
<div class="tooltip tooltip-bottom flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-36 border-neutral-700" data-tip="<%= t('author') %>">
|
||||
<%= link_to submissions_filter_path('author', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %>
|
||||
<%= svg_icon('user', class: 'w-5 h-5 shrink-0') %>
|
||||
<span class="font-normal truncate"><%= current_account.users.accessible_by(current_ability).where(account: current_account).find_by(email: params[:author])&.full_name || 'NA' %></span>
|
||||
<% end %>
|
||||
<%= link_to url_for(params: request.query_parameters.except('author')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %>
|
||||
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% filter_names = %w[status folder author completed_at created_at] %>
|
||||
<% ordered_filters = request.query_parameters.keys.filter_map { |key| filter_names.find { |name| key.start_with?(name) } }.uniq %>
|
||||
<% chip_order = ordered_filters.reverse.each_with_index.to_h { |name, index| [name, index + 1] } %>
|
||||
<% chip_order.default = ordered_filters.size + 1 %>
|
||||
<% status_icon = { 'declined' => 'x_circle', 'expired' => 'clock_cancel', 'partially_completed' => 'clock_edit', 'sent' => 'send', 'opened' => 'mail_opened' }[params[:status]] %>
|
||||
<% status_icons = { 'all' => 'list', 'pending' => 'clock', 'completed' => 'circle_check' } %>
|
||||
<% current_status = status_icons.key?(params[:status].to_s) ? params[:status].to_s : 'all' %>
|
||||
<% with_status_button = local_assigns[:with_status] && status_icon.blank? %>
|
||||
<% chips_html = capture do %>
|
||||
<% if status_icon %>
|
||||
<div class="order-none flex h-10 px-2 py-1 text-base md:text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl shrink-0 max-w-[60vw] md:w-36 border-neutral-700">
|
||||
<%= link_to submissions_filter_path('status', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %>
|
||||
<%= svg_icon(status_icon, class: 'w-5 h-5 shrink-0') %>
|
||||
<span class="font-normal truncate"><%= t(params[:status]) %></span>
|
||||
<% end %>
|
||||
<%= link_to url_for(params: request.query_parameters.except('status')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %>
|
||||
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if params[:folder].present? %>
|
||||
<div class="order-<%= chip_order['folder'] %> md:order-none md:tooltip tooltip-no-touch tooltip-bottom flex md:flex h-10 px-2 py-1 text-base md:text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl shrink-0 max-w-[60vw] md:w-36 border-neutral-700" data-tip="<%= t('folder') %>">
|
||||
<%= link_to submissions_filter_path('folder', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %>
|
||||
<%= svg_icon('folder', class: 'w-5 h-5 shrink-0') %>
|
||||
<span class="font-normal truncate"><%= params[:folder] %></span>
|
||||
<% end %>
|
||||
<%= link_to url_for(params: request.query_parameters.except('folder')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %>
|
||||
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if params[:author].present? %>
|
||||
<div class="order-<%= chip_order['author'] %> md:order-none md:tooltip tooltip-no-touch tooltip-bottom flex md:flex h-10 px-2 py-1 text-base md:text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl shrink-0 max-w-[60vw] md:w-36 border-neutral-700" data-tip="<%= t('author') %>">
|
||||
<%= link_to submissions_filter_path('author', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %>
|
||||
<%= svg_icon('user', class: 'w-5 h-5 shrink-0') %>
|
||||
<span class="font-normal truncate"><%= current_account.users.accessible_by(current_ability).where(account: current_account).find_by(email: params[:author])&.full_name || 'NA' %></span>
|
||||
<% end %>
|
||||
<%= link_to url_for(params: request.query_parameters.except('author')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %>
|
||||
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if query_params[:completed_at_from].present? || query_params[:completed_at_to].present? %>
|
||||
<div class="order-<%= chip_order['completed_at'] %> md:order-none md:tooltip tooltip-no-touch tooltip-bottom flex md:flex h-10 px-2 py-1 text-base md:text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl shrink-0 max-w-[60vw] md:w-36 border-neutral-700" data-tip="<%= t('completed_at') %>">
|
||||
<%= link_to submissions_filter_path('completed_at', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %>
|
||||
<%= svg_icon('calendar_check', class: 'w-5 h-5 shrink-0') %>
|
||||
<span class="flex flex-col font-normal text-left md:text-center text-xs">
|
||||
<% if query_params[:completed_at_from] == query_params[:completed_at_to] %>
|
||||
<span><%= l(Date.parse(query_params[:completed_at_from]), locale: current_account.locale) %></span>
|
||||
<% else %>
|
||||
<span><%= query_params[:completed_at_from].present? ? l(Date.parse(query_params[:completed_at_from]), locale: current_account.locale) : '∞' %></span>
|
||||
<span><%= query_params[:completed_at_to].present? ? l(Date.parse(query_params[:completed_at_to]), locale: current_account.locale) : t('today') %></span>
|
||||
<% end %>
|
||||
</span>
|
||||
<% end %>
|
||||
<%= link_to url_for(params: request.query_parameters.except('completed_at_from', 'completed_at_to')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %>
|
||||
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if query_params[:created_at_from].present? || query_params[:created_at_to].present? %>
|
||||
<div class="order-<%= chip_order['created_at'] %> md:order-none md:tooltip tooltip-no-touch tooltip-bottom flex md:flex h-10 px-2 py-1 text-base md:text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl shrink-0 max-w-[60vw] md:w-36 border-neutral-700" data-tip="<%= t('created_at') %>">
|
||||
<%= link_to submissions_filter_path('created_at', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %>
|
||||
<%= svg_icon('calendar', class: 'w-5 h-5 shrink-0') %>
|
||||
<span class="flex flex-col font-normal text-left md:text-center text-xs">
|
||||
<% if query_params[:created_at_from] == query_params[:created_at_to] %>
|
||||
<span><%= l(Date.parse(query_params[:created_at_from]), locale: current_account.locale) %></span>
|
||||
<% else %>
|
||||
<span><%= query_params[:created_at_from].present? ? l(Date.parse(query_params[:created_at_from]), locale: current_account.locale) : '∞' %></span>
|
||||
<span><%= query_params[:created_at_to].present? ? l(Date.parse(query_params[:created_at_to]), locale: current_account.locale) : t('today') %></span>
|
||||
<% end %>
|
||||
</span>
|
||||
<% end %>
|
||||
<%= link_to url_for(params: request.query_parameters.except('created_at_to', 'created_at_from')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %>
|
||||
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if query_params[:completed_at_from].present? || query_params[:completed_at_to].present? %>
|
||||
<div class="tooltip tooltip-bottom flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-36 border-neutral-700" data-tip="<%= t('completed_at') %>">
|
||||
<%= link_to submissions_filter_path('completed_at', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %>
|
||||
<%= svg_icon('calendar_check', class: 'w-5 h-5 shrink-0') %>
|
||||
<span class="flex flex-row md:flex-col font-normal text-left md:text-center md:text-xs">
|
||||
<% if query_params[:completed_at_from] == query_params[:completed_at_to] %>
|
||||
<span><%= l(Date.parse(query_params[:completed_at_from]), locale: current_account.locale) %></span>
|
||||
<% else %>
|
||||
<span><%= query_params[:completed_at_from].present? ? l(Date.parse(query_params[:completed_at_from]), locale: current_account.locale) : '∞' %></span>
|
||||
<span class="px-1 md:px-0 md:hidden">-</span>
|
||||
<span><%= query_params[:completed_at_to].present? ? l(Date.parse(query_params[:completed_at_to]), locale: current_account.locale) : t('today') %></span>
|
||||
<% if with_status_button && chips_html.blank? %>
|
||||
<div class="dropdown md:hidden shrink-0">
|
||||
<label tabindex="0" class="cursor-pointer flex h-10 px-2 py-1 space-x-1 text-base items-center border text-neutral rounded-xl <%= current_status == 'all' ? 'border-neutral-300' : 'border-neutral-700' %>">
|
||||
<%= svg_icon(status_icons[current_status], class: 'w-5 h-5 shrink-0') %>
|
||||
<span><%= t(current_status) %></span>
|
||||
<%= svg_icon('chevron_down', class: 'w-4 h-4 shrink-0') %>
|
||||
</label>
|
||||
<ul tabindex="0" class="z-10 dropdown-content p-2 mt-2 shadow menu text-base bg-base-100 rounded-box" style="min-width: 180px;">
|
||||
<li>
|
||||
<%= link_to url_for(params: request.query_parameters.except('status')), class: ('bg-base-200' if current_status == 'all') do %>
|
||||
<%= svg_icon('list', class: 'w-5 h-5 shrink-0') %>
|
||||
<span><%= t('all') %></span>
|
||||
<% if local_assigns[:all_count] %>
|
||||
<span class="badge badge-sm badge-ghost font-medium px-2 ml-auto">
|
||||
<%= local_assigns[:all_count] %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</span>
|
||||
<% end %>
|
||||
<%= link_to url_for(params: request.query_parameters.except('completed_at_from', 'completed_at_to')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %>
|
||||
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||
<% end %>
|
||||
</li>
|
||||
<li>
|
||||
<%= link_to url_for(params: request.query_parameters.merge('status' => 'pending')), class: ('bg-base-200' if current_status == 'pending') do %>
|
||||
<%= svg_icon('clock', class: 'w-5 h-5 shrink-0') %>
|
||||
<span><%= t('pending') %></span>
|
||||
<% if local_assigns[:pending_count] %>
|
||||
<span class="badge badge-sm badge-ghost font-medium px-2 ml-auto">
|
||||
<%= local_assigns[:pending_count] %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</li>
|
||||
<li>
|
||||
<%= link_to url_for(params: request.query_parameters.merge('status' => 'completed')), class: ('bg-base-200' if current_status == 'completed') do %>
|
||||
<%= svg_icon('circle_check', class: 'w-5 h-5 shrink-0') %>
|
||||
<span><%= t('completed') %></span>
|
||||
<% if local_assigns[:completed_count] %>
|
||||
<span class="badge badge-sm badge-ghost font-medium px-2 ml-auto">
|
||||
<%= local_assigns[:completed_count] %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if query_params[:created_at_from].present? || query_params[:created_at_to].present? %>
|
||||
<div class="tooltip tooltip-bottom flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-36 border-neutral-700" data-tip="<%= t('created_at') %>">
|
||||
<%= link_to submissions_filter_path('created_at', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %>
|
||||
<%= svg_icon('calendar', class: 'w-5 h-5 shrink-0') %>
|
||||
<span class="flex flex-row md:flex-col font-normal text-left md:text-center md:text-xs">
|
||||
<% if query_params[:created_at_from] == query_params[:created_at_to] %>
|
||||
<span><%= l(Date.parse(query_params[:created_at_from]), locale: current_account.locale) %></span>
|
||||
<% else %>
|
||||
<span><%= query_params[:created_at_from].present? ? l(Date.parse(query_params[:created_at_from]), locale: current_account.locale) : '∞' %></span>
|
||||
<span class="px-1 md:px-0 md:hidden">-</span>
|
||||
<span><%= query_params[:created_at_to].present? ? l(Date.parse(query_params[:created_at_to]), locale: current_account.locale) : t('today') %></span>
|
||||
<% end %>
|
||||
</span>
|
||||
<% if chips_html.present? %>
|
||||
<scroll-fade class="flex items-center gap-2 overflow-x-auto flex-1 min-w-0 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden [&::-webkit-scrollbar]:h-0 [&::-webkit-scrollbar]:w-0 md:contents">
|
||||
<% if with_status_button %>
|
||||
<a href="<%= submissions_filter_path('status', query_params.merge(path: url_for)) %>" data-turbo-frame="modal" class="order-none md:hidden flex h-10 px-2 py-1 space-x-1 text-base items-center border text-neutral rounded-xl shrink-0 <%= current_status == 'all' ? 'border-neutral-300' : 'border-neutral-700' %>">
|
||||
<%= svg_icon(status_icons[current_status], class: 'w-5 h-5 shrink-0') %>
|
||||
<span><%= t(current_status) %></span>
|
||||
<%= svg_icon('chevron_down', class: 'w-4 h-4 shrink-0') %>
|
||||
</a>
|
||||
<% end %>
|
||||
<%= link_to url_for(params: request.query_parameters.except('created_at_to', 'created_at_from')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %>
|
||||
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||
<% end %>
|
||||
</div>
|
||||
<%= chips_html %>
|
||||
</scroll-fade>
|
||||
<% end %>
|
||||
|
||||
Loading…
Reference in new issue