upload native files via the page form

This commit is contained in:
Alex Turchyn authored and Pete Matsyburka committed 2026-09-23 10:59:54 +03:00
1 parent 3ed15e383b
commit 0609a70544
3 files changed
+55

No files matched your search

+2
View File
@@ -13,6 +13,7 @@ import NativeAction from './elements/native_action'
import NativeSearch from './elements/native_search' import NativeSearch from './elements/native_search'
import NativeModal from './elements/native_modal' import NativeModal from './elements/native_modal'
import NativeEvent from './elements/native_event' import NativeEvent from './elements/native_event'
import NativeUpload from './elements/native_upload'
import FormPrompt from './elements/form_prompt' import FormPrompt from './elements/form_prompt'
import InfiniteScroll from './elements/infinite_scroll' import InfiniteScroll from './elements/infinite_scroll'
import ModalButton from './elements/modal_button' import ModalButton from './elements/modal_button'
@@ -129,6 +130,7 @@ safeRegisterElement('native-action', NativeAction)
safeRegisterElement('native-search', NativeSearch) safeRegisterElement('native-search', NativeSearch)
safeRegisterElement('native-modal', NativeModal) safeRegisterElement('native-modal', NativeModal)
safeRegisterElement('native-event', NativeEvent) safeRegisterElement('native-event', NativeEvent)
safeRegisterElement('native-upload', NativeUpload)
safeRegisterElement('form-prompt', FormPrompt) safeRegisterElement('form-prompt', FormPrompt)
safeRegisterElement('infinite-scroll', InfiniteScroll) safeRegisterElement('infinite-scroll', InfiniteScroll)
safeRegisterElement('modal-button', ModalButton) safeRegisterElement('modal-button', ModalButton)
+45
View File
@@ -0,0 +1,45 @@
import { convertImagesInInput } from './convert_upload'
export default class extends HTMLElement {
connectedCallback () {
this.files = []
document.addEventListener('turbo:submit-end', this.onSubmitEnd)
}
disconnectedCallback () {
document.removeEventListener('turbo:submit-end', this.onSubmitEnd)
}
get form () {
return this.querySelector('form')
}
append (index, name, type, base64) {
const file = this.files[index] ||= { name, type, chunks: [] }
file.chunks.push(Uint8Array.from(atob(base64), (char) => char.charCodeAt(0)))
}
async submit (url) {
const dataTransfer = new DataTransfer()
this.files.forEach(({ name, type, chunks }) => dataTransfer.items.add(new File(chunks, name, { type })))
this.files = []
const input = this.form.querySelector('[type="file"]')
input.files = dataTransfer.files
await convertImagesInInput(input)
this.form.action = url
this.form.requestSubmit()
}
onSubmitEnd = (e) => {
if (e.detail.formSubmission?.formElement !== this.form) return
window.webkit?.messageHandlers?.native?.postMessage({ type: 'upload', success: e.detail.success })
}
}
+8
View File
@@ -11,6 +11,14 @@
</native-action> </native-action>
<% end %> <% end %>
<native-action data-placement="profile" data-icon="logout" data-native="sign_out" data-label="<%= t('sign_out') %>" data-destructive="true"></native-action> <native-action data-placement="profile" data-icon="logout" data-native="sign_out" data-label="<%= t('sign_out') %>" data-destructive="true"></native-action>
<% if can?(:create, ::Template) %>
<native-upload class="hidden">
<%= form_for '', url: templates_upload_path, id: form_id = SecureRandom.uuid, method: :post, html: { enctype: 'multipart/form-data' } do %>
<input type="hidden" name="form_id" value="<%= form_id %>">
<input name="files[]" type="file" multiple>
<% end %>
</native-upload>
<% end %>
<% if can?(:create, ::Template) && controller_name.in?(%w[templates_dashboard submissions_dashboard template_folders templates_archived submissions_archived]) %> <% if can?(:create, ::Template) && controller_name.in?(%w[templates_dashboard submissions_dashboard template_folders templates_archived submissions_archived]) %>
<% folder_name = @template_folder&.full_name %> <% folder_name = @template_folder&.full_name %>
<native-action data-placement="create" data-icon="upload" data-native="upload" data-label="<%= t('upload') %>" data-url="<%= templates_upload_path(folder_name: folder_name) %>" data-accept="image/*, application/pdf, application/zip, application/json<%= ", #{Templates::CreateAttachments::DOCUMENT_EXTENSIONS.join(', ')}" if Docuseal.advanced_formats? %>"></native-action> <native-action data-placement="create" data-icon="upload" data-native="upload" data-label="<%= t('upload') %>" data-url="<%= templates_upload_path(folder_name: folder_name) %>" data-accept="image/*, application/pdf, application/zip, application/json<%= ", #{Templates::CreateAttachments::DOCUMENT_EXTENSIONS.join(', ')}" if Docuseal.advanced_formats? %>"></native-action>