diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 3a2d61e6..d785410b 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -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 diff --git a/app/javascript/application.js b/app/javascript/application.js index e527b5fb..07373acf 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -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 () { diff --git a/app/javascript/elements/dynamic_list.js b/app/javascript/elements/dynamic_list.js new file mode 100644 index 00000000..82980d45 --- /dev/null +++ b/app/javascript/elements/dynamic_list.js @@ -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() + } +})) diff --git a/app/views/icons/_trash.html.erb b/app/views/icons/_trash.html.erb new file mode 100644 index 00000000..8ccee7ff --- /dev/null +++ b/app/views/icons/_trash.html.erb @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app/views/icons/_user_plus.html.erb b/app/views/icons/_user_plus.html.erb new file mode 100644 index 00000000..f8f7e66a --- /dev/null +++ b/app/views/icons/_user_plus.html.erb @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app/views/shared/_button_title.html.erb b/app/views/shared/_button_title.html.erb index 9e8e1968..d66746f9 100644 --- a/app/views/shared/_button_title.html.erb +++ b/app/views/shared/_button_title.html.erb @@ -1,11 +1,11 @@ - + <%= icon if icon %> <%= title %> - + <%= svg_icon('loader', class: 'w-6 h-6 animate-spin') %> <%= disabled_with %>... diff --git a/app/views/shared/_turbo_modal.html.erb b/app/views/shared/_turbo_modal.html.erb index 036e7c5b..74fd90f8 100644 --- a/app/views/shared/_turbo_modal.html.erb +++ b/app/views/shared/_turbo_modal.html.erb @@ -7,7 +7,7 @@ <%= local_assigns[:title] %> - × + × <% end %>
diff --git a/app/views/submissions/index.html.erb b/app/views/submissions/index.html.erb index 116b620e..fd20aabc 100644 --- a/app/views/submissions/index.html.erb +++ b/app/views/submissions/index.html.erb @@ -36,6 +36,9 @@ Status + + Share Link + @@ -46,27 +49,40 @@ <% submission.submitters.each do |submitter| %> <%= submitter.email %> - <% end %> - - - <% submission.submitters.each do |submitter| %> -
- - <%= submitter.status %> - - <%= link_to 'Copy', submit_form_url(slug: submitter.slug), title: 'Copy', class: 'btn btn-outline btn-xs' %> -
- <% 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?' } %> - - - <% end %> - - - <% else %> - <%= render 'shared/no_data_banner' %> - <% end %> +
+ <% end %> + + + <% submission.submitters.each do |submitter| %> +
+ + <%= submitter.status %> + +
+ <% end %> + + + <% submission.submitters.each do |submitter| %> + <% share_link_input_id = "share-link-input_#{submitter.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') %> + +
+
+ <% 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?' } %> + + + <% end %> + + +<% else %> + <%= render 'shared/no_data_banner' %> +<% end %>
diff --git a/app/views/submissions/new.html.erb b/app/views/submissions/new.html.erb index e5cffbe5..f956ca78 100644 --- a/app/views/submissions/new.html.erb +++ b/app/views/submissions/new.html.erb @@ -6,35 +6,34 @@ <%= f.text_area :emails, required: true, class: 'base-textarea' %> <% else %> - - - - <% @template.submitters.each do |item| %> - - <% end %> - - - - - - <% @template.submitters.each do |item| %> - - <% end %> - - - -
- <%= item['name'] %> - -
- - - - × -
- + +
+
+
+ +
+ <% @template.submitters.each.with_index(1) do |item, index| %> +
+ + + +
+ <% end %> +
+
+
+
+ + <%= svg_icon('user_plus', class: 'w-4 h-4') %> + Add Recipient + +
<% end %>
<%= f.label :send_email, class: 'flex items-center cursor-pointer' do %> diff --git a/app/views/submissions/show.html.erb b/app/views/submissions/show.html.erb index 089b645b..49e45d42 100644 --- a/app/views/submissions/show.html.erb +++ b/app/views/submissions/show.html.erb @@ -12,18 +12,18 @@ <%= link_to @submission.template.name, template_submissions_path(@submission.template), class: 'link link-hover' %>
- <%- if @submission.completed_at.present? %> + <% @submission.submitters.each do |submitter| %>
-
Completed at
+
<%= submitter.email %>
- <%= l(@submission.completed_at, format: :long) %> + <%= submitter.status %>
<% end %> <% @submission.template.fields.each do |field| %>
- <%= field['name'] %> + <%= field['name'].presence || "[FIELD NAME]" %>
<% if ['image', 'signature'].include?(field['type']) %>