add multiple submitters input form
This commit is contained in:
@@ -57,10 +57,10 @@ class SubmissionsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def create_submissions_from_submitters
|
def create_submissions_from_submitters
|
||||||
submissions_params.map do |attrs|
|
submissions_params[:submission].to_h.map do |_, attrs|
|
||||||
submission = @template.submissions.new
|
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)
|
submission.submitters.new(**submitter_attrs, sent_at: params[:send_email] == '1' ? Time.current : nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ class SubmissionsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def submissions_params
|
def submissions_params
|
||||||
params.require(:submission).map { |param| param.permit(submitters: [%i[uuid email]]) }
|
params.permit(submission: { submitters: %i[uuid email] })
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_template
|
def load_template
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import FileDropzone from './elements/file_dropzone'
|
|||||||
import MenuActive from './elements/menu_active'
|
import MenuActive from './elements/menu_active'
|
||||||
import ClipboardCopy from './elements/clipboard_copy'
|
import ClipboardCopy from './elements/clipboard_copy'
|
||||||
import TemplateBuilder from './template_builder/builder'
|
import TemplateBuilder from './template_builder/builder'
|
||||||
|
import DynamicList from './elements/dynamic_list'
|
||||||
|
|
||||||
document.addEventListener('turbo:before-cache', () => {
|
document.addEventListener('turbo:before-cache', () => {
|
||||||
window.flash?.remove()
|
window.flash?.remove()
|
||||||
@@ -26,6 +27,7 @@ window.customElements.define('turbo-modal', TurboModal)
|
|||||||
window.customElements.define('file-dropzone', FileDropzone)
|
window.customElements.define('file-dropzone', FileDropzone)
|
||||||
window.customElements.define('menu-active', MenuActive)
|
window.customElements.define('menu-active', MenuActive)
|
||||||
window.customElements.define('clipboard-copy', ClipboardCopy)
|
window.customElements.define('clipboard-copy', ClipboardCopy)
|
||||||
|
window.customElements.define('dynamic-list', DynamicList)
|
||||||
|
|
||||||
window.customElements.define('template-builder', class extends HTMLElement {
|
window.customElements.define('template-builder', class extends HTMLElement {
|
||||||
connectedCallback () {
|
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="enabled">
|
||||||
<span class="flex justify-center space-x-2">
|
<span class="flex items-center justify-center space-x-2">
|
||||||
<%= icon if icon %>
|
<%= icon if icon %>
|
||||||
<span><%= title %></span>
|
<span><%= title %></span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="disabled">
|
<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') %>
|
<%= svg_icon('loader', class: 'w-6 h-6 animate-spin') %>
|
||||||
<span><%= disabled_with %>...</span>
|
<span><%= disabled_with %>...</span>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<span>
|
<span>
|
||||||
<%= local_assigns[:title] %>
|
<%= local_assigns[:title] %>
|
||||||
</span>
|
</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>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -36,6 +36,9 @@
|
|||||||
<th>
|
<th>
|
||||||
Status
|
Status
|
||||||
</th>
|
</th>
|
||||||
|
<th>
|
||||||
|
Share Link
|
||||||
|
</th>
|
||||||
<th class="text-right" width="1px">
|
<th class="text-right" width="1px">
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -46,27 +49,40 @@
|
|||||||
<td>
|
<td>
|
||||||
<% submission.submitters.each do |submitter| %>
|
<% submission.submitters.each do |submitter| %>
|
||||||
<%= submitter.email %>
|
<%= submitter.email %>
|
||||||
<% end %>
|
</br>
|
||||||
</td>
|
<% end %>
|
||||||
<td>
|
</td>
|
||||||
<% submission.submitters.each do |submitter| %>
|
<td>
|
||||||
<div>
|
<% submission.submitters.each do |submitter| %>
|
||||||
<span class="badge badge-info badge-outline">
|
<div>
|
||||||
<%= submitter.status %>
|
<span class="badge badge-info badge-outline">
|
||||||
</span>
|
<%= submitter.status %>
|
||||||
<%= link_to 'Copy', submit_form_url(slug: submitter.slug), title: 'Copy', class: 'btn btn-outline btn-xs' %>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
<td class="flex items-center space-x-2 justify-end">
|
<td>
|
||||||
<%= link_to 'View', submission_path(submission), title: 'View', class: 'btn btn-outline btn-xs' %>
|
<% submission.submitters.each do |submitter| %>
|
||||||
<%= button_to 'Remove', submission_path(submission), class: 'btn btn-outline btn-error btn-xs', title: 'Delete', method: :delete, data: { turbo_confirm: 'Are you sure?' } %>
|
<% share_link_input_id = "share-link-input_#{submitter.id}" %>
|
||||||
</td>
|
<div class="join ">
|
||||||
</tr>
|
<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>
|
||||||
<% end %>
|
<clipboard-copy class="btn btn-xs btn-neutral btn-square join-item text-white font-bold swap swap-active" for="<%= share_link_input_id %>">
|
||||||
</tbody>
|
<%= svg_icon('clipboard', class: 'w-3 h-3 swap-on text-white') %>
|
||||||
</table>
|
<%= svg_icon('clipboard_copy', class: 'w-3 h-3 swap-off text-white') %>
|
||||||
<% else %>
|
</clipboard-copy>
|
||||||
<%= render 'shared/no_data_banner' %>
|
</div>
|
||||||
<% end %>
|
<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>
|
</div>
|
||||||
|
|||||||
@@ -6,35 +6,34 @@
|
|||||||
<%= f.text_area :emails, required: true, class: 'base-textarea' %>
|
<%= f.text_area :emails, required: true, class: 'base-textarea' %>
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<table class="">
|
<dynamic-list class="space-y-4">
|
||||||
<thead>
|
<div class="space-y-4">
|
||||||
<tr>
|
<div class="card card-compact bg-base-200" data-targets="dynamic-list.items">
|
||||||
<% @template.submitters.each do |item| %>
|
<div class="card-body">
|
||||||
<th class="w-1/2 text-left">
|
<div class="absolute right-4 top-5">
|
||||||
<%= item['name'] %>
|
<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">
|
||||||
</th>
|
<%= svg_icon('trash', class: 'w-4 h-4') %>
|
||||||
<% end %>
|
</a>
|
||||||
<th>
|
</div>
|
||||||
</th>
|
<div class="grid md:grid-cols-2 gap-4">
|
||||||
</tr>
|
<% @template.submitters.each.with_index(1) do |item, index| %>
|
||||||
</thead>
|
<div class="form-control">
|
||||||
<tbody>
|
<label class="label">
|
||||||
<tr>
|
<span class="label-text"> <%= item['name'] %></span>
|
||||||
<% @template.submitters.each do |item| %>
|
</label>
|
||||||
<td>
|
<input type="hidden" name="submission[1][submitters][<%= index %>][uuid]" value="<%= item['uuid'] %>" >
|
||||||
<input type="hidden" name="submission[][submitters][][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>
|
||||||
<input type="email" name="submission[][submitters][][email]" value="<%= item['email'] %>" required>
|
</div>
|
||||||
</td>
|
<% end %>
|
||||||
<% end %>
|
</div>
|
||||||
<td>
|
</div>
|
||||||
×
|
</div>
|
||||||
</td>
|
</div>
|
||||||
</tr>
|
<a href="#" class="btn btn-primary btn-sm w-full flex items-center justify-center" data-action="click:dynamic-list#addItem">
|
||||||
</tbody>
|
<%= svg_icon('user_plus', class: 'w-4 h-4') %>
|
||||||
</table>
|
<span>Add Recipient</span>
|
||||||
<button>
|
</a>
|
||||||
+ Add new
|
</dynamic-list>
|
||||||
</button>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= f.label :send_email, class: 'flex items-center cursor-pointer' do %>
|
<%= 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' %>
|
<%= link_to @submission.template.name, template_submissions_path(@submission.template), class: 'link link-hover' %>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<%- if @submission.completed_at.present? %>
|
<% @submission.submitters.each do |submitter| %>
|
||||||
<div class="py-6 sm:grid sm:grid-cols-3 sm:gap-4">
|
<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">
|
<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>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% @submission.template.fields.each do |field| %>
|
<% @submission.template.fields.each do |field| %>
|
||||||
<div class="py-6 sm:grid sm:grid-cols-3 sm:gap-4">
|
<div class="py-6 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||||
<dt class="text-sm font-medium leading-6 text-gray-900">
|
<dt class="text-sm font-medium leading-6 text-gray-900">
|
||||||
<%= field['name'] %>
|
<%= field['name'].presence || "[FIELD NAME]" %>
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
|
<dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
|
||||||
<% if ['image', 'signature'].include?(field['type']) %>
|
<% if ['image', 'signature'].include?(field['type']) %>
|
||||||
|
|||||||
Reference in New Issue
Block a user