adjust mobile tables

This commit is contained in:
Alex Turchyn authored and Pete Matsyburka committed 2026-09-23 11:00:17 +03:00
1 parent 9e89cb92a9
commit e3e5c237d4
9 files changed
+205 -56

No files matched your search

+64
View File
@@ -170,3 +170,67 @@ markdown-editor [contenteditable] p {
native-action {
display: contents;
}
@media (max-width: 767px) {
.table-stack,
.table-stack tbody,
.table-stack tr,
.table-stack td {
display: block;
}
.table-stack,
div:has(> .table-stack) {
overflow: visible;
}
.table-stack thead {
display: none;
}
.table-stack tr {
@apply bg-base-200 rounded-2xl py-3 mb-3 border-0;
}
.table-stack td {
@apply px-4 py-1;
}
.table-stack td[data-label] {
@apply flow-root text-right;
overflow-wrap: anywhere;
}
.table-stack td[data-label]::before {
content: attr(data-label);
@apply float-left mr-4 text-sm leading-6 text-base-content/60;
}
.table-stack td:first-child {
@apply font-semibold;
}
.table-stack td:last-child {
@apply grid grid-cols-2 gap-2 pt-3;
}
.table-stack td:last-child:has(> .dropdown) {
grid-template-columns: repeat(2, minmax(0, 1fr)) auto;
}
.table-stack td:last-child:not(:has(*)) {
display: none;
}
.table-stack td:last-child > * {
margin-left: 0 !important;
}
.table-stack td:last-child > :last-child:nth-child(odd):not(.dropdown) {
@apply col-span-2;
}
.table-stack td:last-child .btn {
@apply btn-sm w-full;
}
}
@@ -1,20 +1,22 @@
<% unless turbo_native_ios? %>
<tr class="group">
<td class="flex items-center space-x-1">
<%= svg_icon('discount_check_filled', class: 'w-6 h-6 shrink-0 text-green-500') %>
<span class="flex items-center">
<span class="whitespace-nowrap"><%= t('docuseal_trusted_signature') %></span>
<div class="tooltip tooltip-top ml-1 shrink-0 hidden md:flex" data-tip="<%= t('sign_documents_with_trusted_certificate_provided_by_docu_seal_your_documents_and_data_are_never_shared_with_docu_seal_p_d_f_checksum_is_provided_to_generate_a_trusted_signature') %>">
<%= svg_icon('circle_question', class: 'w-4 h-4 stroke-1 shrink-0') %>
</div>
</span>
</td>
<td>
<div class="flex items-center space-x-1">
<%= svg_icon('discount_check_filled', class: 'w-6 h-6 shrink-0 text-green-500') %>
<span class="flex items-center">
<span class="whitespace-nowrap"><%= t('docuseal_trusted_signature') %></span>
<div class="tooltip tooltip-top ml-1 shrink-0 hidden md:flex" data-tip="<%= t('sign_documents_with_trusted_certificate_provided_by_docu_seal_your_documents_and_data_are_never_shared_with_docu_seal_p_d_f_checksum_is_provided_to_generate_a_trusted_signature') %>">
<%= svg_icon('circle_question', class: 'w-4 h-4 stroke-1 shrink-0') %>
</div>
</span>
</div>
</td>
<td data-label="<%= t('valid_to') %>">
<a href="<%= "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premises" }.to_query}" %>" class="btn btn-neutral btn-sm text-white whitespace-nowrap">
<%= t('unlock_with_docuseal_pro') %>
</a>
</td>
<td>
<td data-label="<%= t('status') %>">
<div class="md:tooltip" data-tip="<%= t('unlock_with_docuseal_pro') %>">
<%= button_to settings_esign_path, method: :put, params: { name: Docuseal::AATL_CERT_NAME }, class: 'btn btn-outline btn-neutral btn-xs whitespace-nowrap', title: t('make_default'), disabled: true do %>
<%= t('make_default') %>
+5 -4
View File
@@ -32,7 +32,8 @@
<%= t('verify_signed_pdf') %>
</div>
<div class="text-xs">
<%= t('click_to_upload_or_drag_and_drop_files_html') %>
<span class="md:hidden"><%= t('click_to_upload') %></span>
<span class="hidden md:inline"><%= t('click_to_upload_or_drag_and_drop_files_html') %></span>
</div>
</div>
<input id="file" name="files[]" class="hidden" data-action="change:file-dropzone#onSelectFiles" data-target="file-dropzone.input" type="file" accept="application/pdf" multiple>
@@ -54,7 +55,7 @@
</div>
<%= render 'alert' %>
<div class="overflow-x-auto">
<table class="table w-full table-lg rounded-b-none overflow-hidden">
<table class="table table-stack w-full table-lg rounded-b-none overflow-hidden">
<thead class="bg-base-200">
<tr class="text-neutral uppercase">
<th>
@@ -77,10 +78,10 @@
<td>
<%= item['name'] %>
</td>
<td>
<td data-label="<%= t('valid_to') %>">
<%= l(item['pkcs'].certificate.not_after.to_date, format: :long, locale: current_account.locale) %>
</td>
<td>
<td data-label="<%= t('status') %>">
<% if item['status'] == 'default' %>
<span class="badge badge-lg badge-info badge-outline">
<%= t('default') %>
+17 -16
View File
@@ -2,16 +2,15 @@
<div class="flex-wrap space-y-4 md:flex md:flex-nowrap md:space-y-0 md:space-x-10">
<%= render 'shared/settings_nav' %>
<div class="md:flex-grow">
<div class="flex flex-col md:flex-row md:flex-wrap gap-2 md:justify-between md:items-end mb-4 min-h-12">
<h1 class="text-3xl md:text-4xl font-bold">
<div class="flex flex-row items-center justify-between gap-2 md:items-end mb-4 min-h-12">
<h1 class="text-3xl md:text-4xl font-bold truncate min-w-0">
<%= t('mcp_server') %>
</h1>
<div class="flex flex-col md:flex-row gap-y-2 gap-x-4 md:items-center">
<%= link_to new_settings_mcp_path, class: 'btn btn-primary btn-md gap-2 w-full md:w-fit', aria: { label: t('new_token') }, data: { turbo_frame: 'modal' } do %>
<%= svg_icon('plus', class: 'w-6 h-6') %>
<span><%= t('new_token') %></span>
<% end %>
</div>
<%= link_to new_settings_mcp_path, class: 'shrink-0 btn btn-primary btn-md gap-2', aria: { label: t('new_token') }, data: { turbo_frame: :modal, native_modal: :medium } do %>
<%= svg_icon('plus', class: 'w-6 h-6') %>
<span class="md:hidden"><%= t('new') %></span>
<span class="hidden md:inline"><%= t('new_token') %></span>
<% end %>
</div>
<% if @mcp_token.present? %>
<div class="space-y-4 mb-4">
@@ -48,7 +47,7 @@
</div>
<% end %>
<div class="overflow-x-auto">
<table class="table w-full table-lg rounded-b-none overflow-hidden">
<table class="table table-stack w-full table-lg rounded-b-none overflow-hidden">
<thead class="bg-base-200">
<tr class="text-neutral uppercase">
<th>
@@ -70,14 +69,16 @@
<td>
<%= mcp_token.name %>
</td>
<td>
<% if @mcp_token.present? && mcp_token.id == @mcp_token.id %>
<%= @mcp_token.token %>
<% else %>
<%= "#{mcp_token.token_prefix}#{'*' * 38}" %>
<% end %>
<td data-label="<%= t('token') %>">
<span class="font-mono truncate inline-block max-w-[220px] align-middle">
<% if @mcp_token.present? && mcp_token.id == @mcp_token.id %>
<%= @mcp_token.token %>
<% else %>
<%= "#{mcp_token.token_prefix}#{'*' * 38}" %>
<% end %>
</span>
</td>
<td>
<td data-label="<%= t('created_at') %>">
<%= l(mcp_token.created_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>
</td>
<td class="flex items-center space-x-2 justify-end">
+2 -1
View File
@@ -13,7 +13,8 @@
<%= t('upload_a_new_document') %>
</div>
<div class="text-sm">
<%= t('click_to_upload_or_drag_and_drop_html') %>
<span class="md:hidden"><%= t('click_to_upload') %></span>
<span class="hidden md:inline"><%= t('click_to_upload_or_drag_and_drop_html') %></span>
</div>
<% if Docuseal.multitenant? && !turbo_native_app? %>
<a class="flex absolute bottom-4 items-center text-sm mt-2 pointer-events-auto" href="<%= new_template_path(modal_tab: 'google_drive') %>" data-turbo-frame="modal" data-native-modal="medium">
+2 -1
View File
@@ -40,7 +40,8 @@
<%= t('upload_initials') %>
</div>
<div class="text-xs">
<%= t('click_to_upload_or_drag_and_drop_html') %>
<span class="md:hidden"><%= t('click_to_upload') %></span>
<span class="hidden md:inline"><%= t('click_to_upload_or_drag_and_drop_html') %></span>
</div>
</div>
<input id="file" name="file" class="hidden" data-action="change:file-dropzone#onSelectFiles" data-target="file-dropzone.input" type="file" accept="image/png,image/jpeg,image/jpg">
+2 -1
View File
@@ -40,7 +40,8 @@
<%= t('upload_signature') %>
</div>
<div class="text-xs">
<%= t('click_to_upload_or_drag_and_drop_html') %>
<span class="md:hidden"><%= t('click_to_upload') %></span>
<span class="hidden md:inline"><%= t('click_to_upload_or_drag_and_drop_html') %></span>
</div>
</div>
<input id="file" name="file" class="hidden" data-action="change:file-dropzone#onSelectFiles" data-target="file-dropzone.input" type="file" accept="image/png,image/jpeg,image/jpg">
+87 -23
View File
@@ -2,8 +2,8 @@
<div class="flex-wrap space-y-4 md:flex md:flex-nowrap md:space-y-0 md:space-x-10">
<%= render 'shared/settings_nav' %>
<div class="md:flex-grow">
<div class="flex flex-col md:flex-row md:flex-wrap gap-2 md:justify-between md:items-end mb-4 min-h-12">
<h1 class="text-3xl md:text-4xl font-bold">
<div class="flex flex-wrap items-center md:items-end gap-x-4 gap-y-2 mb-4 min-h-12">
<h1 class="text-3xl md:text-4xl font-bold truncate min-w-0 mr-auto md:order-1">
<% if params[:status] == 'archived' %>
<%= t('archived_users') %>
<% elsif params[:status] == 'integration' %>
@@ -12,30 +12,94 @@
<%= t('users') %>
<% end %>
</h1>
<div class="flex flex-col md:flex-row gap-y-2 gap-x-4 md:items-center">
<% if params[:status].blank? %>
<% if can?(:create, User.new(account: current_account)) %>
<%= render 'users/extra_buttons' %>
<% if content_for(:add_user_button) %>
<%= content_for(:add_user_button) %>
<% else %>
<%= link_to new_user_path, class: 'btn btn-primary btn-md gap-2 w-full md:w-fit', data: { turbo_frame: 'modal' } do %>
<%= svg_icon('plus', class: 'w-6 h-6') %>
<span><%= t('new_user') %></span>
<% end %>
<% end %>
<% else %>
<div class="md:tooltip" data-tip="<%= t('contact_your_administrator_to_add_new_users') %>">
<%= link_to '#', class: 'btn btn-primary btn-md gap-2 w-full md:w-fit btn-disabled', data: { turbo_frame: 'modal' } do %>
<%= svg_icon('plus', class: 'w-6 h-6') %>
<span><%= t('new_user') %></span>
<% end %>
</div>
<% if params[:status].blank? %>
<% if can?(:create, User.new(account: current_account)) %>
<%= link_to new_user_path, class: 'shrink-0 md:order-3 btn btn-primary btn-md gap-2', title: t('new_user'), data: { turbo_frame: 'modal' } do %>
<%= svg_icon('plus', class: 'w-6 h-6') %>
<span class="md:hidden"><%= t('new') %></span>
<span class="hidden md:inline"><%= t('new_user') %></span>
<% end %>
<% else %>
<div class="shrink-0 md:order-3 md:tooltip" data-tip="<%= t('contact_your_administrator_to_add_new_users') %>">
<%= link_to '#', class: 'btn btn-primary btn-md gap-2 btn-disabled', title: t('new_user'), data: { turbo_frame: 'modal' } do %>
<%= svg_icon('plus', class: 'w-6 h-6') %>
<span class="md:hidden"><%= t('new') %></span>
<span class="hidden md:inline"><%= t('new_user') %></span>
<% end %>
</div>
<% end %>
</div>
<% end %>
<% if params[:status].blank? && can?(:create, User.new(account: current_account)) %>
<div class="basis-full md:basis-auto md:order-2 flex flex-col md:flex-row gap-y-2 gap-x-4 md:items-center">
<%= render 'users/extra_buttons' %>
</div>
<% end %>
</div>
<div class="overflow-x-auto">
<div class="md:hidden divide-y divide-base-300">
<% @users.each do |user| %>
<% can_edit = params[:status].blank? && can?(:update, user) && user.archived_at.blank? %>
<% can_remove = params[:status] != 'archived' && can?(:destroy, user) && user != current_user %>
<% can_unarchive = params[:status] == 'archived' && can?(:create, user) && user != current_user && user.archived_at? %>
<div class="flex items-center gap-3 py-4">
<span class="flex items-center justify-center w-10 h-10 rounded-full bg-base-300 text-sm">
<%= user.initials.presence || user.email.first.upcase %>
</span>
<div class="flex-1 min-w-0">
<div class="flex items-center gap-2">
<span class="font-semibold truncate"><%= user.full_name.presence || user.email %></span>
<span class="badge badge-info badge-outline badge-sm whitespace-nowrap shrink-0"><%= t(user.role) %></span>
</div>
<% if user.try(:pending_reconfirmation?) %>
<div class="text-sm text-base-content/70 truncate"><%= user.unconfirmed_email %> (<%= t('unconfirmed') %>)</div>
<% elsif user.full_name.present? %>
<div class="text-sm text-base-content/70 truncate"><%= user.email %></div>
<% end %>
</div>
<% if can_edit || can_remove || can_unarchive %>
<native-menu class="<%= 'dropdown dropdown-end' unless turbo_native_app? %>">
<label tabindex="0" aria-label="<%= t('more') %>" class="btn btn-ghost btn-circle btn-sm">
<%= svg_icon('dots_vertical', class: 'w-5 h-5') %>
</label>
<ul tabindex="0" class="<%= turbo_native_app? ? 'hidden' : 'z-10 dropdown-content p-2 mt-2 shadow menu bg-base-100 rounded-box min-w-[160px]' %>">
<% if can_edit %>
<li>
<native-menu-action data-icon="pencil" data-label="<%= t('edit') %>">
<%= link_to edit_user_path(user), class: 'flex items-center gap-2', data: { turbo_frame: 'modal' } do %>
<%= svg_icon('pencil', class: 'w-5 h-5 flex-shrink-0') %>
<span><%= t('edit') %></span>
<% end %>
</native-menu-action>
</li>
<% end %>
<% if can_remove %>
<li>
<native-menu-action data-icon="trash" data-label="<%= t('remove') %>" data-destructive="true">
<button form="<%= dom_id(user, :remove) %>" class="flex items-center gap-2 w-full text-error" data-turbo-confirm="<%= t('are_you_sure_') %>">
<%= svg_icon('trash', class: 'w-5 h-5 flex-shrink-0') %>
<span><%= t('remove') %></span>
</button>
<%= button_to '', user_path(user), method: :delete, form: { id: dom_id(user, :remove) }, form_class: 'hidden' %>
</native-menu-action>
</li>
<% end %>
<% if can_unarchive %>
<li>
<native-menu-action data-icon="rotate" data-label="<%= t('unarchive') %>">
<button form="<%= dom_id(user, :unarchive) %>" class="flex items-center gap-2 w-full" data-turbo-confirm="<%= t('are_you_sure_') %>">
<%= svg_icon('rotate', class: 'w-5 h-5 flex-shrink-0') %>
<span><%= t('unarchive') %></span>
</button>
<%= button_to '', user_path(user), method: :put, params: { user: { archived_at: nil } }, form: { id: dom_id(user, :unarchive) }, form_class: 'hidden' %>
</native-menu-action>
</li>
<% end %>
</ul>
</native-menu>
<% end %>
</div>
<% end %>
</div>
<div class="hidden md:block overflow-x-auto">
<table class="table w-full table-lg rounded-b-none overflow-hidden">
<thead class="bg-base-200">
<tr class="text-neutral uppercase">
+14
View File
@@ -832,6 +832,7 @@ en: &en
submission_created_by_email_via_source_html: '<b>Submission created</b> by %{email} via %{source}'
submission_created_via_source_html: '<b>Submission created</b> via %{source}'
pro_user_seats_used: Pro user seats used
manage: Manage
manage_plan: Manage plan
this_submission_has_multiple_signers_which_prevents_the_use_of_a_sharing_link_html: This submission has multiple signers, which prevents the use of a sharing link as it's unclear which signer is responsible for specific fields. To resolve this, follow this <a href="https://www.docuseal.com/resources/pre-filling-recipients" class="link font-bold" rel="noopener noreferrer nofollow" target="_blank">guide</a> to define the default signer details.
welcome_to_docuseal: Welcome to DocuSeal
@@ -1021,6 +1022,7 @@ en: &en
failed_to_save_the_scan: Failed to save the scan
failed_to_scan_the_document: Failed to scan the document
document_scanning_is_not_available_on_this_device: Document scanning is not available on this device
click_to_upload: Click to upload
devise:
confirmations:
confirmed: Your email address has been successfully confirmed.
@@ -1162,6 +1164,7 @@ en: &en
detailed: "%B %-d, %Y at %-I:%M:%S %p"
es: &es
click_to_upload: Haz clic para cargar
knowledge_based_authentication: Autenticación basada en el conocimiento
kba_field: KBA
passed: Aprobado
@@ -1980,6 +1983,7 @@ es: &es
submission_created_by_email_via_source_html: '<b>Envío creado</b> por %{email} a través de %{source}'
submission_created_via_source_html: '<b>Envío creado</b> a través de %{source}'
pro_user_seats_used: Plazas de usuario Pro en uso
manage: Gestionar
manage_plan: Gestionar plan
this_submission_has_multiple_signers_which_prevents_the_use_of_a_sharing_link_html: 'Este envío tiene múltiples firmantes, lo que impide el uso de un enlace para compartir, ya que no está claro qué firmante es responsable de los campos específicos. Para resolver esto, sigue esta <a href="https://www.docuseal.com/resources/pre-filling-recipients" class="link font-bold" rel="noopener noreferrer nofollow" target="_blank">guía</a> para definir los detalles predeterminados del firmante.'
welcome_to_docuseal: Bienvenido a DocuSeal
@@ -2317,6 +2321,7 @@ es: &es
detailed: "%-d de %B de %Y a las %-H:%M:%S"
it: &it
click_to_upload: Clicca per caricare
knowledge_based_authentication: Autenticazione basata sulla conoscenza
kba_field: KBA
passed: Superato
@@ -3135,6 +3140,7 @@ it: &it
submission_created_by_email_via_source_html: '<b>Invio creato</b> da %{email} tramite %{source}'
submission_created_via_source_html: '<b>Invio creato</b> tramite %{source}'
pro_user_seats_used: Posti utente Pro in uso
manage: Gestisci
manage_plan: Gestisci piano
this_submission_has_multiple_signers_which_prevents_the_use_of_a_sharing_link_html: "Questa sottomissione ha più firmatari, il che impedisce l'uso di un link di condivisione poiché non è chiaro quale firmatario sia responsabile di specifici campi. Per risolvere questo problema, segui questa <a href=\"https://www.docuseal.com/resources/pre-filling-recipients\" class=\"link font-bold\" rel=\"noopener noreferrer nofollow\" target=\"_blank\">guida</a> per definire i dettagli predefiniti del firmatario."
welcome_to_docuseal: Benvenuto in DocuSeal
@@ -3458,6 +3464,7 @@ it: &it
detailed: "%-d %B %Y alle ore %H:%M:%S"
fr: &fr
click_to_upload: Cliquez pour téléverser
knowledge_based_authentication: Authentification basée sur la connaissance
kba_field: KBA
passed: Réussi
@@ -4276,6 +4283,7 @@ fr: &fr
submission_created_by_email_via_source_html: "<b>Soumission créée</b> par %{email} via %{source}"
submission_created_via_source_html: "<b>Soumission créée</b> via %{source}"
pro_user_seats_used: Places d’utilisateurs Pro utilisées
manage: Gérer
manage_plan: Gérer la formule
this_submission_has_multiple_signers_which_prevents_the_use_of_a_sharing_link_html: Cette soumission comporte plusieurs signataires, ce qui empêche l’utilisation d’un lien de partage car il n’est pas clair quel signataire est responsable de quels champs. Pour résoudre cela, suivez ce <a href="https://www.docuseal.com/resources/pre-filling-recipients" class="link font-bold" rel="noopener noreferrer nofollow" target="_blank">guide</a> pour définir les détails du signataire par défaut.
welcome_to_docuseal: Bienvenue sur DocuSeal
@@ -4609,6 +4617,7 @@ fr: &fr
detailed: "%-d %B %Y à %H:%M:%S"
pt: &pt
click_to_upload: Clique para fazer o upload
knowledge_based_authentication: Autenticação baseada em conhecimento
kba_field: KBA
passed: Aprovado
@@ -5427,6 +5436,7 @@ pt: &pt
submission_created_by_email_via_source_html: '<b>Envio criado</b> por %{email} via %{source}'
submission_created_via_source_html: '<b>Envio criado</b> via %{source}'
pro_user_seats_used: Lugares de usuário Pro em uso
manage: Gerenciar
manage_plan: Gerenciar plano
this_submission_has_multiple_signers_which_prevents_the_use_of_a_sharing_link_html: 'Este envio tem vários signatários, o que impede o uso de um link de compartilhamento, pois não está claro qual signatário é responsável por quais campos. Para resolver isso, siga este <a href="https://www.docuseal.com/resources/pre-filling-recipients" class="link font-bold" rel="noopener noreferrer nofollow" target="_blank">guia</a> para definir os detalhes padrão do signatário.'
welcome_to_docuseal: Bem-vindo ao DocuSeal
@@ -5763,6 +5773,7 @@ pt: &pt
detailed: "%-d de %B de %Y às %H:%M:%S"
de: &de
click_to_upload: Zum Hochladen klicken
knowledge_based_authentication: Wissensbasierte Authentifizierung
kba_field: KBA
passed: Bestanden
@@ -6581,6 +6592,7 @@ de: &de
submission_created_by_email_via_source_html: '<b>Einreichung erstellt</b> von %{email} über %{source}'
submission_created_via_source_html: '<b>Einreichung erstellt</b> über %{source}'
pro_user_seats_used: Verwendete Pro-Benutzerplätze
manage: Verwalten
manage_plan: Plan verwalten
this_submission_has_multiple_signers_which_prevents_the_use_of_a_sharing_link_html: 'Diese Einreichung hat mehrere Unterzeichner, was die Nutzung eines Freigabelinks verhindert, da unklar ist, welcher Unterzeichner für welche Felder verantwortlich ist. Um dies zu lösen, folgen Sie dieser <a href="https://www.docuseal.com/resources/pre-filling-recipients" class="link font-bold" rel="noopener noreferrer nofollow" target="_blank">Anleitung</a>, um die Standarddetails des Unterzeichners festzulegen.'
welcome_to_docuseal: Willkommen bei DocuSeal
@@ -7444,6 +7456,7 @@ he:
too_many_requests_try_again_later: יותר מדי בקשות. נסה שוב מאוחר יותר.
nl: &nl
click_to_upload: Klik om te uploaden
knowledge_based_authentication: Kennisgebaseerde authenticatie
kba_field: KBA
passed: Geslaagd
@@ -8263,6 +8276,7 @@ nl: &nl
submission_created_by_email_via_source_html: "<b>Inzending aangemaakt</b> door %{email} via %{source}"
submission_created_via_source_html: "<b>Inzending aangemaakt</b> via %{source}"
pro_user_seats_used: Gebruikersplaatsen Pro gebruikt
manage: Beheren
manage_plan: Abonnement beheren
this_submission_has_multiple_signers_which_prevents_the_use_of_a_sharing_link_html: Deze inzending heeft meerdere ondertekenaars, waardoor het gebruik van een deellink niet mogelijk is omdat onduidelijk is welke ondertekenaar verantwoordelijk is voor specifieke velden. Volg deze <a href="https://www.docuseal.com/resources/pre-filling-recipients" class="link font-bold" rel="noopener noreferrer nofollow" target="_blank">handleiding</a> om de standaardgegevens van de ondertekenaar te definiëren.
welcome_to_docuseal: Welkom bij DocuSeal