add template preferences

This commit is contained in:
Pete Matsyburka
2024-04-17 16:08:58 +03:00
parent fefd138dfd
commit 1e57c1ace7
18 changed files with 317 additions and 9 deletions
@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M14 6m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
<path d="M4 6l8 0" />
<path d="M16 6l4 0" />
<path d="M8 12m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
<path d="M4 12l2 0" />
<path d="M10 12l10 0" />
<path d="M17 18m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
<path d="M4 18l11 0" />
<path d="M19 18l1 0" />
</svg>

After

Width:  |  Height:  |  Size: 602 B

+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z" />
<path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" />
</svg>

After

Width:  |  Height:  |  Size: 872 B

+1
View File
@@ -12,6 +12,7 @@
</head>
<body>
<turbo-frame id="modal"></turbo-frame>
<turbo-frame id="drawer"></turbo-frame>
<%= render 'shared/navbar' %>
<% if flash.present? %><%= render 'shared/flash' %><% end %>
<div class="max-w-6xl mx-auto px-4 md:px-2 mb-8">
+22
View File
@@ -0,0 +1,22 @@
<turbo-frame id="drawer">
<turbo-modal class="modal modal-open items-start !animate-none justify-end overflow-y-auto !justify-normal md:!justify-end" 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 relative w-full relative overflow-y-auto">
<% if local_assigns[:title] %>
<div class="flex justify-between bg-base-100 py-2 px-4 items-center border-b pb-2 font-medium">
<span>
<%= local_assigns[:title] %>
</span>
<a href="#" class="text-xl" data-action="click:turbo-modal#close">&times;</a>
</div>
<% else %>
<span data-action="click:turbo-modal#close" class="absolute btn border border-base-100 bg-base-100 hover:bg-base-300 hover:border-base-300 btn-primary !text-base btn-sm btn-circle" style="left: -40px; top: 6px">
&times;
</span>
<% end %>
<div class="w-full md:w-[620px] overflow-y-auto" style="max-height: calc(100vh - <%= local_assigns[:title] ? '45px' : '0px' %>)">
<%= yield %>
</div>
</div>
</turbo-modal>
</turbo-frame>
+6 -2
View File
@@ -35,7 +35,7 @@
<div class="form-control space-y-2">
<div class="form-control">
<%= f.label :subject, class: 'label' %>
<%= f.text_field :subject, value: config.value['subject'], required: true, class: '!text-sm base-input w-full', dir: 'auto' %>
<%= f.text_field :subject, value: @template.preferences['request_email_subject'].presence || config.value['subject'], required: true, class: '!text-sm base-input w-full', dir: 'auto' %>
</div>
<div class="form-control">
<div class="flex items-center">
@@ -45,8 +45,12 @@
</span>
</div>
<autoresize-textarea>
<%= f.text_area :body, value: config.value['body'], required: true, class: 'base-textarea w-full', rows: 10, dir: 'auto' %>
<%= f.text_area :body, value: @template.preferences['request_email_body'].presence || config.value['body'], required: true, class: 'base-textarea w-full', rows: 10, dir: 'auto' %>
</autoresize-textarea>
<label for="<%= uuid = SecureRandom.uuid %>" class="flex items-center cursor-pointer">
<%= check_box_tag :save_message, id: uuid, class: 'base-checkbox', checked: false %>
<span class="label">Save as default template message</span>
</label>
</div>
<%= render 'message_fields' %>
</div>
+76 -1
View File
@@ -1,4 +1,4 @@
<toggle-visible data-element-ids="[&quot;js_1&quot;,&quot;react_1&quot;,&quot;vue_1&quot;]" class="block relative" data-catalyst="">
<toggle-visible data-element-ids="[&quot;js_1&quot;,&quot;react_1&quot;,&quot;vue_1&quot;,&quot;angular_1&quot;]" class="block relative">
<ul class="items-center w-full text-sm font-medium text-gray-900 my-4 space-y-2 sm:space-y-0 sm:flex sm:space-x-2">
<li class="w-full h-10 text-sm font-medium flex items-center relative group py-3.5">
<input type="radio" name="option_1" id="js_radio_1" value="js_1" data-action="change:toggle-visible#trigger" class="relative peer z-10 hidden" checked="checked">
@@ -33,6 +33,23 @@
<span>Vue</span>
</label>
</li>
<li class="w-full h-10 text-sm font-medium flex items-center relative group py-3.5">
<input type="radio" name="option_1" id="angular_radio_1" value="angular_1" data-action="change:toggle-visible#trigger" class="relative peer z-10 hidden">
<label for="angular_radio_1" class="absolute border-neutral-focus space-x-2 border rounded-xl left-0 right-0 top-0 bottom-0 flex items-center justify-center group-hover:bg-neutral group-hover:text-white peer-checked:btn-neutral">
<span><svg class="h-5 w-5" width="800px" height="800px" viewBox="-8 0 272 272" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
<g>
<path d="M0.0996108949,45.522179 L125.908171,0.697276265 L255.103502,44.7252918 L234.185214,211.175097 L125.908171,271.140856 L19.3245136,211.971984 L0.0996108949,45.522179 Z" fill="#E23237">
</path>
<path d="M255.103502,44.7252918 L125.908171,0.697276265 L125.908171,271.140856 L234.185214,211.274708 L255.103502,44.7252918 L255.103502,44.7252918 Z" fill="#B52E31">
</path>
<path d="M126.107393,32.27393 L126.107393,32.27393 L47.7136187,206.692607 L76.9992218,206.194553 L92.7377432,166.848249 L126.207004,166.848249 L126.306615,166.848249 L163.063035,166.848249 L180.29572,206.692607 L208.286381,207.190661 L126.107393,32.27393 L126.107393,32.27393 Z M126.306615,88.155642 L152.803113,143.5393 L127.402335,143.5393 L126.107393,143.5393 L102.997665,143.5393 L126.306615,88.155642 L126.306615,88.155642 Z" fill="#FFFFFF">
</path>
</g>
</svg>
</span>
<span>Angular</span>
</label>
</li>
</ul>
</toggle-visible>
<div id="js_1" class="block my-4">
@@ -173,3 +190,61 @@ export default {
</code></pre>
</div>
</div>
<div id="angular_1" class="block my-4 hidden">
<div class="mockup-code overflow-hidden pb-0 mt-4">
<span class="top-0 right-0 absolute flex">
<%= link_to 'Learn More', console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/embedding/form"), target: '_blank', data: { turbo: false }, class: 'btn btn-ghost text-gray-100 flex', rel: 'noopener' %>
<clipboard-copy data-text="import { Component } from '@angular/core';
import { DocusealFormComponent } from '@docuseal/angular';
@Component({
selector: 'app-root',
standalone: true,
imports: [DocusealFormComponent],
template: `
<div class=&quot;app&quot;>
<docuseal-form
[src]=&quot;'<%= start_form_url(slug: template.slug) %>'&quot;>
</docuseal-form>
</div>
`
})
export class AppComponent {}
">
<label class="btn btn-ghost text-white">
<input type="radio" class="peer hidden">
<span class="peer-checked:hidden flex items-center space-x-2">
<%= svg_icon('copy', class: 'w-6 h-6 text-white') %>
<span class="hidden md:inline">
Copy
</span>
</span>
<span class="hidden peer-checked:flex items-center space-x-2">
<%= svg_icon('clipboard_copy', class: 'w-6 h-6 text-white') %>
<span class="hidden md:inline">
Copied
</span>
</span>
</label>
</clipboard-copy>
</span>
<pre class="before:!m-0 pl-6 pb-4 overflow-auto"><code class="overflow-hidden w-full"><span style="color: #aa759f">import</span> <span style="color: #d0d0d0">{</span> <span style="color: #d0d0d0;background-color: #151515">Component</span> <span style="color: #d0d0d0">}</span> <span style="color: #aa759f">from</span> <span style="color: #90a959">'</span><span style="color: #90a959">@angular/core</span><span style="color: #90a959">'</span><span style="color: #d0d0d0">;</span>
<span style="color: #aa759f">import</span> <span style="color: #d0d0d0">{</span> <span style="color: #d0d0d0;background-color: #151515">DocusealFormComponent</span> <span style="color: #d0d0d0">}</span> <span style="color: #aa759f">from</span> <span style="color: #90a959">'</span><span style="color: #90a959">@docuseal/angular</span><span style="color: #90a959">'</span><span style="color: #d0d0d0">;</span>
<span style="color: #d0d0d0">@</span><span style="color: #d0d0d0;background-color: #151515">Component</span><span style="color: #d0d0d0">({</span>
<span style="color: #6a9fb5">selector</span><span style="color: #d0d0d0">:</span> <span style="color: #90a959">'</span><span style="color: #90a959">app-root</span><span style="color: #90a959">'</span><span style="color: #d0d0d0">,</span>
<span style="color: #6a9fb5">standalone</span><span style="color: #d0d0d0">:</span> <span style="color: #d28445">true</span><span style="color: #d0d0d0">,</span>
<span style="color: #6a9fb5">imports</span><span style="color: #d0d0d0">:</span> <span style="color: #d0d0d0">[</span><span style="color: #d0d0d0;background-color: #151515">DocusealFormComponent</span><span style="color: #d0d0d0">],</span>
<span style="color: #6a9fb5">template</span><span style="color: #d0d0d0">:</span> <span style="color: #90a959">`
&lt;div class="app"&gt;
&lt;docuseal-form
[src]="'<%= start_form_url(slug: template.slug) %>'"&gt;
&lt;/docuseal-form&gt;
&lt;/div&gt;
`</span>
<span style="color: #d0d0d0">})</span>
<span style="color: #aa759f">export</span> <span style="color: #d28445">class</span> <span style="color: #f4bf75">AppComponent</span> <span style="color: #d0d0d0">{}</span>
</code></pre>
</div>
</div>
+3 -3
View File
@@ -38,10 +38,10 @@
<% if !template.archived_at? %>
<div class="flex items-center space-x-2">
<% if can?(:update, template) && (Docuseal.multitenant? || current_account.testing? || current_account.id == 1) %>
<div class="tooltip" data-tip="API and Embedding">
<%= link_to template_code_modal_path(template), class: 'btn btn-ghost btn-sm flex-1 hidden md:flex', data: { turbo_frame: :modal } do %>
<div class="tooltip" data-tip="Preferences">
<%= link_to template_preferences_path(template), class: 'btn border border-base-200 bg-base-200 hover:bg-base-300 hover:border-base-300 btn-sm flex-1 hidden md:flex', data: { turbo_frame: :drawer } do %>
<span class="flex items-center justify-center space-x-2">
<%= svg_icon('code', class: 'w-6 h-6') %>
<%= svg_icon('adjustments_horizontal', class: 'w-6 h-6') %>
</span>
<% end %>
</div>
@@ -0,0 +1,100 @@
<%= render 'shared/turbo_drawer', title: 'Preferences', close_after_submit: false do %>
<% options = [['General', 'general'], ['API and Embedding', 'api']] %>
<toggle-visible data-element-ids="<%= options.map(&:last).to_json %>" class="relative text-center mt-3 block">
<div class="join">
<% options.each_with_index do |(label, value), index| %>
<span>
<%= radio_button_tag 'option', value, value == 'general', class: 'peer hidden', data: { action: 'change:toggle-visible#trigger' } %>
<label for="option_<%= value %>" class="<%= '!rounded-s-full' if index.zero? %> btn btn-focus btn-sm join-item md:w-48 peer-checked:btn-active normal-case <%= 'px-8 md:px-0' if value == 'general' %>">
<%= label %>
</label>
</span>
<% end %>
</div>
</toggle-visible>
<div id="general" class="px-4 mb-4">
<%= form_for @template, url: template_preferences_path(@template), method: :post, html: { autocomplete: 'off', class: 'mt-1' } do |f| %>
<toggle-on-submit data-element-id="email_saved_alert"></toggle-on-submit>
<%= f.fields_for :preferences, Struct.new(:request_email_subject, :request_email_body).new(*(@template.preferences.values_at('request_email_subject', 'request_email_body').compact_blank.presence || AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::SUBMITTER_INVITATION_EMAIL_KEY).value.values_at('subject', 'body'))) do |ff| %>
<div class="form-control">
<%= ff.label :request_email_subject, 'Email subject', class: 'label' %>
<%= ff.text_field :request_email_subject, required: true, class: 'base-input', dir: 'auto' %>
</div>
<div class="form-control">
<div class="flex items-center">
<%= ff.label :request_email_body, 'Email body', class: 'label' %>
<span class="tooltip tooltip-right" data-tip="Use following placeholders text: <%= AccountConfig::DEFAULT_VALUES.dig(AccountConfig::SUBMITTER_INVITATION_EMAIL_KEY, 'body').scan(/{{.*?}}/).join(', ') %>">
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
</span>
</div>
<autoresize-textarea>
<%= ff.text_area :request_email_body, required: true, class: 'base-input w-full py-2', dir: 'auto' %>
</autoresize-textarea>
</div>
<% end %>
<div class="form-control pt-2">
<%= f.button button_title(title: 'Save', disabled_with: 'Saving'), class: 'base-button' %>
<div class="flex justify-center">
<span id="email_saved_alert" class="text-sm invisible font-normal mt-0.5">Changes have been saved</span>
</div>
</div>
<% end %>
<%= form_for @template, url: template_preferences_path(@template), method: :post, html: { autocomplete: 'off', class: 'mt-2' } do |f| %>
<toggle-on-submit data-element-id="bcc_saved_alert"></toggle-on-submit>
<%= f.fields_for :preferences, Struct.new(:bcc_completed).new(@template.preferences['bcc_completed']) do |ff| %>
<div class="form-control">
<%= ff.label :bcc_completed, class: 'label' do %>
<span class="flex items-center space-x-1 justify-between w-full">
<span>
Completed documents BCC address
</span>
</span>
<% end %>
<%= ff.email_field :bcc_completed, autocomplete: 'off', class: 'base-input' %>
</div>
<% end %>
<div class="form-control pt-3">
<%= f.button button_title(title: 'Save', disabled_with: 'Updating'), class: 'base-button' %>
<div class="flex justify-center">
<span id="bcc_saved_alert" class="text-sm invisible font-normal mt-0.5">Changes have been saved</span>
</div>
</div>
<% end %>
<%= render 'templates_code_modal/preferences' %>
</div>
<div id="api" class="hidden mt-2 mb-4 px-4">
<div>
<label class="text-sm font-semibold" for="template_id">
Template ID
</label>
<div class="flex gap-2 mb-4 mt-2">
<input id="template_id" type="text" value="<%= @template.id %>" class="base-input w-full" autocomplete="off" readonly>
<%= render 'shared/clipboard_copy', icon: 'copy', text: @template.id, class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy', copied_title: 'Copied' %>
</div>
</div>
<div>
<label class="text-sm font-semibold" for="embedding_url">
Embedding URL
</label>
<div class="flex gap-2 mb-4 mt-2">
<input id="embedding_url" type="text" value="<%= start_form_url(slug: @template.slug) %>" class="base-input w-full" autocomplete="off" readonly>
<%= render 'shared/clipboard_copy', icon: 'copy', text: start_form_url(slug: @template.slug), class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy', copied_title: 'Copied' %>
</div>
</div>
<%= render 'templates_code_modal/placeholder' %>
<%= render 'templates/embedding', template: @template %>
<% if can?(:manage, TemplateSharing.new(template: @template)) %>
<%= form_for '', url: template_sharings_testing_index_path, method: :post, html: { class: 'mt-1' } do |f| %>
<%= f.hidden_field :template_id, value: @template.id %>
<div class="flex items-center justify-between">
<span>
Share template with Test Environment
</span>
<%= f.check_box :value, class: 'toggle', checked: @template.template_sharings.exists?(account_id: current_account.testing_accounts), onchange: 'this.form.requestSubmit()' %>
</div>
<% end %>
<div class="mb-4">
</div>
<% end %>
</div>
<% end %>