diff --git a/app/controllers/templates_versions_controller.rb b/app/controllers/templates_versions_controller.rb
index 6cd75c618..0dbd20aaa 100644
--- a/app/controllers/templates_versions_controller.rb
+++ b/app/controllers/templates_versions_controller.rb
@@ -4,12 +4,9 @@ class TemplatesVersionsController < ApplicationController
load_and_authorize_resource :template
def index
- @versions = @template.template_versions.order(id: :desc).preload(:author)
+ versions = @template.template_versions.order(id: :desc).preload(:author)
- respond_to do |format|
- format.json { render json: @versions.as_json(TemplateVersions::SERIALIZE_PARAMS) }
- format.html
- end
+ render json: versions.as_json(TemplateVersions::SERIALIZE_PARAMS)
end
def show
diff --git a/app/javascript/application.js b/app/javascript/application.js
index d93919ff0..6f2dbdd21 100644
--- a/app/javascript/application.js
+++ b/app/javascript/application.js
@@ -189,6 +189,10 @@ safeRegisterElement('template-builder', class extends HTMLElement {
connectedCallback () {
document.addEventListener('turbo:submit-end', this.onSubmit)
document.addEventListener('template-builder:update', this.onSheetSubmit)
+ document.addEventListener('template-builder:sync', this.onSync)
+ document.addEventListener('template-builder:scroll-to', this.onScrollTo)
+ document.addEventListener('template-builder:select-field', this.onSelectField)
+ document.addEventListener('template-builder:draw-field', this.onDrawField)
document.addEventListener('turbo:before-cache', this.onBeforeCache)
this.appElem = document.createElement('div')
@@ -233,7 +237,8 @@ safeRegisterElement('template-builder', class extends HTMLElement {
currencies: (this.dataset.currencies || '').split(',').filter(Boolean),
acceptFileTypes: this.dataset.acceptFileTypes,
showTourStartForm: this.dataset.showTourStartForm === 'true',
- nativePlatform: this.dataset.nativePlatform
+ nativePlatform: this.dataset.nativePlatform,
+ view: this.dataset.view
})
this.component = this.app.mount(this.appElem)
@@ -257,6 +262,40 @@ safeRegisterElement('template-builder', class extends HTMLElement {
this.applySubmission(e.detail.form, e.detail.action, e.detail.body, {})
}
+ onSync = (e) => {
+ const { schema, documents, fields, submitters } = e.detail
+
+ Object.assign(this.component.template, { schema, documents, fields, submitters })
+ }
+
+ onScrollTo = (e) => {
+ this.component.scrollIntoDocument(e.detail)
+ }
+
+ onSelectField = (e) => {
+ const { uuid, attachment_uuid: attachmentUuid, page, x, y } = e.detail
+ const field = this.component.template.fields.find((f) => f.uuid === uuid)
+ const areas = field?.areas || []
+ const area = areas.find((a) => a.attachment_uuid === attachmentUuid && a.page === page && a.x === x && a.y === y) || areas[0]
+
+ if (area) this.component.scrollToArea(area)
+ }
+
+ onDrawField = (e) => {
+ const { uuid, type, option } = e.detail
+
+ if (uuid) {
+ const field = this.component.template.fields.find((f) => f.uuid === uuid)
+
+ if (field) {
+ this.component.drawField = field
+ this.component.drawOption = option || null
+ }
+ } else if (type) {
+ this.component.startFieldDraw({ type })
+ }
+ }
+
applySubmission (formId, action, body, data) {
if (formId === 'submitters_form') {
this.component.template.submitters = JSON.parse(body).submitters
@@ -294,6 +333,10 @@ safeRegisterElement('template-builder', class extends HTMLElement {
disconnectedCallback () {
document.removeEventListener('turbo:submit-end', this.onSubmit)
document.removeEventListener('template-builder:update', this.onSheetSubmit)
+ document.removeEventListener('template-builder:sync', this.onSync)
+ document.removeEventListener('template-builder:scroll-to', this.onScrollTo)
+ document.removeEventListener('template-builder:select-field', this.onSelectField)
+ document.removeEventListener('template-builder:draw-field', this.onDrawField)
document.removeEventListener('turbo:before-cache', this.onBeforeCache)
this.app?.unmount()
diff --git a/app/javascript/elements/native_action.js b/app/javascript/elements/native_action.js
index e193709a6..f018224d0 100644
--- a/app/javascript/elements/native_action.js
+++ b/app/javascript/elements/native_action.js
@@ -21,6 +21,8 @@ export default class extends HTMLElement {
title: this.dataset.label || target?.textContent.trim(),
icon: this.dataset.icon,
placement: this.dataset.placement || 'menu',
+ side: this.dataset.side,
+ view: this.dataset.view,
section: this.dataset.section,
menu: this.dataset.menu,
menuIcon: this.dataset.menuIcon,
diff --git a/app/javascript/template_builder/builder.vue b/app/javascript/template_builder/builder.vue
index 00b98851b..82601835e 100644
--- a/app/javascript/template_builder/builder.vue
+++ b/app/javascript/template_builder/builder.vue
@@ -2,7 +2,7 @@
@@ -25,6 +25,85 @@
:is-default="defaultFields.includes(toRaw(dragField))"
:is-required="defaultRequiredFields.includes(toRaw(dragField))"
/>
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
0 && /AppleWebKit/i.test(navigator.userAgent)
@@ -1472,6 +1604,10 @@ export default {
this.selectedSubmitter = this.template.submitters[0]
},
mounted () {
+ if (this.isRevisionsView) {
+ this.openRevisionsModal()
+ }
+
this.undoStack = [JSON.stringify(this.template)]
this.redoStack = []
@@ -2265,7 +2401,25 @@ export default {
scrollIntoDocument (item) {
const ref = this.documentRefs.find((e) => e.document.uuid === item.attachment_uuid)
- ref.$el.scrollIntoView({ behavior: 'smooth', block: 'start' })
+ ref?.$el.scrollIntoView({ behavior: 'smooth', block: 'start' })
+ },
+ postNativeEvent (name, detail, dismiss = false) {
+ window.webkit?.messageHandlers?.modal?.postMessage({ action: 'dispatch', name, detail: JSON.stringify(detail), dismiss: dismiss ? 'true' : 'false' })
+ },
+ onDrawerScrollToArea (area) {
+ const field = this.template.fields.find((f) => (f.areas || []).includes(area))
+
+ this.postNativeEvent('template-builder:select-field', { uuid: field?.uuid, attachment_uuid: area.attachment_uuid, page: area.page, x: area.x, y: area.y }, true)
+ },
+ syncNative () {
+ const { schema, documents, fields, submitters } = this.template
+ const detail = JSON.stringify({ schema, documents, fields, submitters })
+
+ if (this.isNativeView) {
+ window.webkit?.messageHandlers?.modal?.postMessage({ action: 'dispatch', name: 'template-builder:sync', detail, dismiss: 'false' })
+ } else {
+ window.webkit?.messageHandlers?.native?.postMessage({ type: 'drawer', op: 'sync', detail })
+ }
},
clearDrawField () {
this.drawField = null
@@ -3651,6 +3805,10 @@ export default {
this.pushUndo()
+ if (this.nativePlatform) {
+ this.syncNative()
+ }
+
if (!this.autosave && !force) {
return Promise.resolve({})
}
diff --git a/app/javascript/template_builder/contenteditable.vue b/app/javascript/template_builder/contenteditable.vue
index c17724fb2..7c6686029 100644
--- a/app/javascript/template_builder/contenteditable.vue
+++ b/app/javascript/template_builder/contenteditable.vue
@@ -23,7 +23,7 @@
{{ value }}
@@ -48,7 +48,7 @@ export default {
components: {
IconPencil
},
- inject: ['t'],
+ inject: ['t', 'isMobile'],
props: {
modelValue: {
type: String,
diff --git a/app/javascript/template_builder/field.vue b/app/javascript/template_builder/field.vue
index 8ffacee8c..821b23664 100644
--- a/app/javascript/template_builder/field.vue
+++ b/app/javascript/template_builder/field.vue
@@ -20,7 +20,7 @@
:menu-classes="'mt-1.5'"
:menu-style="{ backgroundColor: dropdownBgColor }"
@update:model-value="[maybeUpdateOptions(), $emit('save')]"
- @click="scrollToFirstArea"
+ @click="scrollOnEdit && scrollToFirstArea()"
/>
@@ -60,7 +60,8 @@