add multiple submitters input form
This commit is contained in:
@@ -57,10 +57,10 @@ class SubmissionsController < ApplicationController
|
||||
end
|
||||
|
||||
def create_submissions_from_submitters
|
||||
submissions_params.map do |attrs|
|
||||
submissions_params[:submission].to_h.map do |_, attrs|
|
||||
submission = @template.submissions.new
|
||||
|
||||
attrs[:submitters].each do |submitter_attrs|
|
||||
attrs[:submitters].each do |_, submitter_attrs|
|
||||
submission.submitters.new(**submitter_attrs, sent_at: params[:send_email] == '1' ? Time.current : nil)
|
||||
end
|
||||
|
||||
@@ -69,7 +69,7 @@ class SubmissionsController < ApplicationController
|
||||
end
|
||||
|
||||
def submissions_params
|
||||
params.require(:submission).map { |param| param.permit(submitters: [%i[uuid email]]) }
|
||||
params.permit(submission: { submitters: %i[uuid email] })
|
||||
end
|
||||
|
||||
def load_template
|
||||
|
||||
@@ -9,6 +9,7 @@ import FileDropzone from './elements/file_dropzone'
|
||||
import MenuActive from './elements/menu_active'
|
||||
import ClipboardCopy from './elements/clipboard_copy'
|
||||
import TemplateBuilder from './template_builder/builder'
|
||||
import DynamicList from './elements/dynamic_list'
|
||||
|
||||
document.addEventListener('turbo:before-cache', () => {
|
||||
window.flash?.remove()
|
||||
@@ -26,6 +27,7 @@ window.customElements.define('turbo-modal', TurboModal)
|
||||
window.customElements.define('file-dropzone', FileDropzone)
|
||||
window.customElements.define('menu-active', MenuActive)
|
||||
window.customElements.define('clipboard-copy', ClipboardCopy)
|
||||
window.customElements.define('dynamic-list', DynamicList)
|
||||
|
||||
window.customElements.define('template-builder', class extends HTMLElement {
|
||||
connectedCallback () {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { actionable } from '@github/catalyst/lib/actionable'
|
||||
import { targets, targetable } from '@github/catalyst/lib/targetable'
|
||||
|
||||
export default actionable(targetable(class extends HTMLElement {
|
||||
static [targets.static] = ['items']
|
||||
|
||||
addItem = (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
const originalItem = this.items[0]
|
||||
const duplicateItem = originalItem.cloneNode(true)
|
||||
const uniqueId = Math.floor(Math.random() * 10 ** 16)
|
||||
|
||||
duplicateItem.querySelectorAll("select, textarea, input:not([type='hidden'])").forEach((input) => {
|
||||
input.value = ''
|
||||
input.checked = false
|
||||
input.removeAttribute('selected')
|
||||
})
|
||||
|
||||
duplicateItem.querySelectorAll('select, textarea, input').forEach((input) => {
|
||||
input.name = input.name.replace('[1]', `[${uniqueId}]`)
|
||||
})
|
||||
|
||||
duplicateItem.querySelectorAll('a.hidden').forEach((button) => button.classList.toggle('hidden'))
|
||||
|
||||
originalItem.parentNode.append(duplicateItem)
|
||||
}
|
||||
|
||||
removeItem = (e) => {
|
||||
e.preventDefault()
|
||||
this.items.find((item) => item.contains(e.target))?.remove()
|
||||
}
|
||||
}))
|
||||
@@ -0,0 +1,8 @@
|
||||
<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="M4 7l16 0" />
|
||||
<path d="M10 11l0 6" />
|
||||
<path d="M14 11l0 6" />
|
||||
<path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12" />
|
||||
<path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 477 B |
@@ -0,0 +1,8 @@
|
||||
<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="M5 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0" />
|
||||
<path d="M3 21v-2a4 4 0 0 1 4 -4h4c.96 0 1.84 .338 2.53 .901" />
|
||||
<path d="M16 3.13a4 4 0 0 1 0 7.75" />
|
||||
<path d="M16 19h6" />
|
||||
<path d="M19 16v6" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 487 B |
@@ -1,11 +1,11 @@
|
||||
<span class="enabled">
|
||||
<span class="flex justify-center space-x-2">
|
||||
<span class="flex items-center justify-center space-x-2">
|
||||
<%= icon if icon %>
|
||||
<span><%= title %></span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="disabled">
|
||||
<span class="flex justify-center space-x-2">
|
||||
<span class="flex items-center justify-center space-x-2">
|
||||
<%= svg_icon('loader', class: 'w-6 h-6 animate-spin') %>
|
||||
<span><%= disabled_with %>...</span>
|
||||
</span>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<span>
|
||||
<%= local_assigns[:title] %>
|
||||
</span>
|
||||
<a href="#" class="text-xl" data-action="click:turbo-modal#close">×</a>
|
||||
<a href="#" class="w-8 h-8 flex items-center justify-center text-xl rounded-lg text-center hover:bg-base-300" data-action="click:turbo-modal#close">×</a>
|
||||
</div>
|
||||
<% end %>
|
||||
<div>
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
<th>
|
||||
Status
|
||||
</th>
|
||||
<th>
|
||||
Share Link
|
||||
</th>
|
||||
<th class="text-right" width="1px">
|
||||
</th>
|
||||
</tr>
|
||||
@@ -46,27 +49,40 @@
|
||||
<td>
|
||||
<% submission.submitters.each do |submitter| %>
|
||||
<%= submitter.email %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td>
|
||||
<% submission.submitters.each do |submitter| %>
|
||||
<div>
|
||||
<span class="badge badge-info badge-outline">
|
||||
<%= submitter.status %>
|
||||
</span>
|
||||
<%= link_to 'Copy', submit_form_url(slug: submitter.slug), title: 'Copy', class: 'btn btn-outline btn-xs' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</td>
|
||||
<td class="flex items-center space-x-2 justify-end">
|
||||
<%= link_to 'View', submission_path(submission), title: 'View', class: 'btn btn-outline btn-xs' %>
|
||||
<%= button_to 'Remove', submission_path(submission), class: 'btn btn-outline btn-error btn-xs', title: 'Delete', method: :delete, data: { turbo_confirm: 'Are you sure?' } %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% else %>
|
||||
<%= render 'shared/no_data_banner' %>
|
||||
<% end %>
|
||||
</br>
|
||||
<% end %>
|
||||
</td>
|
||||
<td>
|
||||
<% submission.submitters.each do |submitter| %>
|
||||
<div>
|
||||
<span class="badge badge-info badge-outline">
|
||||
<%= submitter.status %>
|
||||
</span>
|
||||
</div>
|
||||
<% end %>
|
||||
</td>
|
||||
<td>
|
||||
<% submission.submitters.each do |submitter| %>
|
||||
<% share_link_input_id = "share-link-input_#{submitter.id}" %>
|
||||
<div class="join ">
|
||||
<input id="<%= share_link_input_id %>" autocomplete="off" type="text" class="input input-xs input-bordered join-item" value="<%= submit_form_url(slug: submitter.slug) %>" disabled>
|
||||
<clipboard-copy class="btn btn-xs btn-neutral btn-square join-item text-white font-bold swap swap-active" for="<%= share_link_input_id %>">
|
||||
<%= svg_icon('clipboard', class: 'w-3 h-3 swap-on text-white') %>
|
||||
<%= svg_icon('clipboard_copy', class: 'w-3 h-3 swap-off text-white') %>
|
||||
</clipboard-copy>
|
||||
</div>
|
||||
<br/>
|
||||
<% end %>
|
||||
</td>
|
||||
<td class="flex items-center space-x-2 justify-end">
|
||||
<%= link_to 'View', submission_path(submission), title: 'View', class: 'btn btn-outline btn-xs' %>
|
||||
<%= button_to 'Remove', submission_path(submission), class: 'btn btn-outline btn-error btn-xs', title: 'Delete', method: :delete, data: { turbo_confirm: 'Are you sure?' } %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% else %>
|
||||
<%= render 'shared/no_data_banner' %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -6,35 +6,34 @@
|
||||
<%= f.text_area :emails, required: true, class: 'base-textarea' %>
|
||||
</div>
|
||||
<% else %>
|
||||
<table class="">
|
||||
<thead>
|
||||
<tr>
|
||||
<% @template.submitters.each do |item| %>
|
||||
<th class="w-1/2 text-left">
|
||||
<%= item['name'] %>
|
||||
</th>
|
||||
<% end %>
|
||||
<th>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<% @template.submitters.each do |item| %>
|
||||
<td>
|
||||
<input type="hidden" name="submission[][submitters][][uuid]" value="<%= item['uuid'] %>" >
|
||||
<input type="email" name="submission[][submitters][][email]" value="<%= item['email'] %>" required>
|
||||
</td>
|
||||
<% end %>
|
||||
<td>
|
||||
×
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<button>
|
||||
+ Add new
|
||||
</button>
|
||||
<dynamic-list class="space-y-4">
|
||||
<div class="space-y-4">
|
||||
<div class="card card-compact bg-base-200" data-targets="dynamic-list.items">
|
||||
<div class="card-body">
|
||||
<div class="absolute right-4 top-5">
|
||||
<a href="#" data-action="click:dynamic-list#removeItem" class="block w-6 h-6 rounded-lg text-neutral-700 text-center bg-base-300 p-1 hidden hover:bg-neutral hover:text-white">
|
||||
<%= svg_icon('trash', class: 'w-4 h-4') %>
|
||||
</a>
|
||||
</div>
|
||||
<div class="grid md:grid-cols-2 gap-4">
|
||||
<% @template.submitters.each.with_index(1) do |item, index| %>
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text"> <%= item['name'] %></span>
|
||||
</label>
|
||||
<input type="hidden" name="submission[1][submitters][<%= index %>][uuid]" value="<%= item['uuid'] %>" >
|
||||
<input type="email" name="submission[1][submitters][<%= index %>][email]" value="<%= item['email'] %>" class="input input-sm input-bordered" placeholder="Email" required>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="#" class="btn btn-primary btn-sm w-full flex items-center justify-center" data-action="click:dynamic-list#addItem">
|
||||
<%= svg_icon('user_plus', class: 'w-4 h-4') %>
|
||||
<span>Add Recipient</span>
|
||||
</a>
|
||||
</dynamic-list>
|
||||
<% end %>
|
||||
<div class="form-control">
|
||||
<%= f.label :send_email, class: 'flex items-center cursor-pointer' do %>
|
||||
|
||||
@@ -12,18 +12,18 @@
|
||||
<%= link_to @submission.template.name, template_submissions_path(@submission.template), class: 'link link-hover' %>
|
||||
</dd>
|
||||
</div>
|
||||
<%- if @submission.completed_at.present? %>
|
||||
<% @submission.submitters.each do |submitter| %>
|
||||
<div class="py-6 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
<dt class="text-sm font-medium leading-6 text-gray-900">Completed at</dt>
|
||||
<dt class="text-sm font-medium leading-6 text-gray-900"><%= submitter.email %></dt>
|
||||
<dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
|
||||
<%= l(@submission.completed_at, format: :long) %>
|
||||
<%= submitter.status %>
|
||||
</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
<% @submission.template.fields.each do |field| %>
|
||||
<div class="py-6 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
<dt class="text-sm font-medium leading-6 text-gray-900">
|
||||
<%= field['name'] %>
|
||||
<%= field['name'].presence || "[FIELD NAME]" %>
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
|
||||
<% if ['image', 'signature'].include?(field['type']) %>
|
||||
|
||||
Reference in New Issue
Block a user