PluginProbe
The Innovative Form Builder – IvyForms / 1.5
The Innovative Form Builder – IvyForms v1.5
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
← All changes | frontend/src/assets/js/admin/admin.ts +90 -18 0.9 → 1.5 View file →
@@ -3,8 +3,9 @@
3 3 import * as Vue from 'vue'
4 4 import { createApp } from 'vue'
5 5 import { createPinia } from 'pinia'
6 6 import App from '../../../views/admin/App.vue'
7 +import EntryPage from '@/views/admin/entries/entry-page/EntryPage.vue'
7 8 import router from '@/router'
8 9 import '@/assets/scss/main.scss'
9 10 import 'element-plus/dist/index.css'
10 11 import { useLabelsStore } from '@/stores/labels'
@@ -11,10 +12,14 @@
11 12 import { useLabels } from '@/composables/useLabels'
12 13 import api, { dispatchIvyReady, installIvyGlobals } from '@/composables/IvyFormAPI'
13 14 import { useProFeatures } from '@/composables/useProFeatures'
14 15 import { useFormBuilder } from '@/stores/useFormBuilder'
16 +import { useEntry } from '@/stores/useEntry'
17 +import { useNavigation } from '@/composables/useNavigation'
15 18 import { registerLiteComponents } from '@/composables/registerLiteComponents'
16 19 import { registerLiteFieldOptions } from '@/views/admin/form-builder/form-builder-page/form-builder/panel/tabs/field-options/registerLiteFieldOptions'
20 +import { registerSquareIntegration } from '@/integrations/registerSquare'
21 +import { registerLiteStyleSectionPromos } from '@/views/admin/form-builder/form-builder-page/form-builder/panel/tabs/style-controls/registerLiteStyleSectionPromos'
17 22 import * as LiteTypes from '@/types/index'
18 23 import type { IvyProFeatures } from '@/types/global'
19 24 import { useWcagColors } from '@/composables/useWcagColors'
20 25 import { useSettingsStore } from '@/stores/useSettingsStore'
@@ -19,8 +24,27 @@
19 24 import { useWcagColors } from '@/composables/useWcagColors'
20 25 import { useSettingsStore } from '@/stores/useSettingsStore'
21 26 import IvyMessage from '@/views/_components/message/ivyMessage'
22 27 import { useApiClient } from '@/composables/useApiClient'
28 +import { useActionEntityStore } from '@/stores/actionEntityStore'
29 +import { useUnsavedChangesStore } from '@/stores/useUnsavedChangesStore'
30 +import { useProUpgradeDialogStore } from '@/stores/proUpgradeDialogStore'
31 +import { useGlobalState } from '@/stores/useGlobalState'
32 +import { denormalizeFieldsForApi } from '@/utils/fieldsNormalization'
33 +import { countryList } from '@/constants/countries'
34 +import { isSecurityField } from '@/constants/securityFields'
35 +import { useProFeatureUpgrade } from '@/composables/useProFeatureUpgrade'
36 +import { useConfirmationMultiSetting } from '@/stores/useConfirmationMultiSetting'
37 +import { useGoogleSheetsFormIntegrations } from '@/integrations/google-sheets/composables/useGoogleSheetsFormIntegrations'
38 +import {
39 + registerFormBuilderExtension,
40 + getFormBuilderExtensions,
41 +} from '@/extensions/formBuilderExtensions'
42 +import { useAllEntries } from '@/stores/useAllEntries'
43 +import { getPreviewFieldComponent } from '@/composables/useFieldPreviewComponents'
44 +import { normalizeFieldsForBuilder } from '@/utils/fieldsNormalization'
45 +import { registerLitePublicFieldComponents } from '@/entries/publicFieldComponentRegistry'
46 +import { registerGoogleSheetsAdmin } from '@/integrations/google-sheets/registerGoogleSheetsAdmin'
23 47
24 48 // Note: Window interface extensions are now defined in src/types/global.d.ts
25 49 // No need to duplicate declarations here
26 50
@@ -28,8 +52,12 @@
28 52 const pinia = createPinia()
29 53 app.use(pinia)
30 54 app.use(router)
31 55
56 +// Shared settings store: must exist before mount so Pro views (e.g. Zapier) can read the same
57 +// `settings/all` payload as the rest of admin via `window.IvyForms.settingsStore`.
58 +const settingsStore = useSettingsStore()
59 +
32 60 // Initialize the labels store with WordPress data
33 61 const labelsStore = useLabelsStore()
34 62 labelsStore.initialize()
35 63
@@ -42,8 +70,9 @@
42 70 installIvyGlobals()
43 71 const w = window
44 72 const { getLabel } = useLabels()
45 73 const formBuilder = useFormBuilder()
74 + const globalState = useGlobalState()
46 75
47 76 // Proxy to resolve labels dynamically via getLabel
48 77 const labelsProxy = new Proxy(
49 78 {},
@@ -59,26 +88,17 @@
59 88 )
60 89
61 90 w.IvyForms = w.IvyForms || { api, hooks: api.hooks, fields: api.fields }
62 91 w.IvyForms.api = api
63 - // Expose hooks & fields for external (Pro / add-ons) integration.
64 - // These were previously commented out which prevented Pro from registering filters via IvyForms.hooks.*
65 - // Keep backward compatibility by only setting if not already provided.
66 - if (!w.IvyForms.hooks) {
67 - w.IvyForms.hooks = api.hooks
68 - }
92 + // Always sync to canonical api.hooks so third-party registrations land on the same registry.
93 + w.IvyForms.hooks = api.hooks
69 94
70 - // Add triggerUpdate method for Pro plugins to notify when they add hooks
71 - if (!w.IvyForms.hooks.triggerUpdate) {
72 - w.IvyForms.hooks.triggerUpdate = () => {
73 - // This is a no-op by default, but components can override it
74 - // to trigger re-computation when Pro plugins register
75 - }
95 + // Ensure hook registration triggers reactive updates in Lite components
96 + if (w.IvyForms.hooks === api.hooks && api.hooks.triggerUpdate) {
97 + w.IvyForms.hooks.triggerUpdate = api.hooks.triggerUpdate.bind(api.hooks)
76 98 }
77 99
78 - if (!w.IvyForms.fields) {
79 - w.IvyForms.fields = api.fields
80 - }
100 + w.IvyForms.fields = api.fields
81 101 // Expose label helpers for Pro plugin and other extenders
82 102 w.IvyForms.getLabel = getLabel
83 103 w.IvyForms.labels = labelsProxy
84 104 // Set WordPress admin URL
@@ -89,12 +109,44 @@
89 109 // Expose IvyMessage utility for Pro plugin
90 110 w.IvyForms.IvyMessage = IvyMessage
91 111 // Expose useApiClient for Pro plugin (call it once to prevent tree-shaking)
92 112 w.IvyForms.useApiClient = useApiClient
113 + // Shared Google Sheets form-builder CRUD for Lite single + Pro multi shells
114 + w.IvyForms.useGoogleSheetsFormIntegrations = useGoogleSheetsFormIntegrations
115 + // Expose stores for Pro plugin to use dialogs and entity actions
116 + w.IvyForms.useActionEntityStore = useActionEntityStore
117 + // Expose the actual store instance (not the function) so Pro uses the same instance
118 + w.IvyForms.unsavedChangesStore = useUnsavedChangesStore()
119 + w.IvyForms.useProUpgradeDialogStore = useProUpgradeDialogStore
93 120 // Expose the form builder store so external components can read/write fields
94 121 w.IvyForms.formBuilder = formBuilder
122 + w.IvyForms.registerFormBuilderExtension = registerFormBuilderExtension
123 + w.IvyForms.getFormBuilderExtensions = getFormBuilderExtensions
124 + w.IvyForms.useEntry = useEntry
125 + // Expose global state for Pro plugins to set page title and active page
126 + w.IvyForms.globalState = globalState
95 127 // Expose shared types for Pro plugin and other extenders
96 128 w.IvyForms.types = LiteTypes
129 + // Expose shared utility helpers for Pro plugin and other extenders
130 + const { showUpgradeDialog } = useProFeatureUpgrade()
131 + w.IvyForms.helpers = {
132 + isSecurityField,
133 + showUpgradeDialog,
134 + getPreviewFieldComponent: getPreviewFieldComponent as (fieldType: string) => unknown,
135 + normalizeFieldsForBuilder: normalizeFieldsForBuilder as (fields: unknown[]) => unknown[],
136 + denormalizeFieldsForApi,
137 + countryList,
138 + registerLitePublicFieldComponents,
139 + }
140 + w.IvyForms.confirmationMulti = {
141 + refreshTable: async (formId: number) => {
142 + await useConfirmationMultiSetting().searchConfirmations({ formId })
143 + },
144 + }
145 +
146 + // Expose entry stores so Pro can read/refresh entries (add-entry is a Pro feature).
147 + w.IvyForms.useAllEntries = useAllEntries
148 + w.IvyForms.useEntry = useEntry
97 149 // Create a callable components registry:
98 150 // - Use as function: w.IvyForms.components('MyComp', Comp)
99 151 // - Or as object map: w.IvyForms.components.MyComp
100 152 // - Or helper alias: w.IvyForms.registerComponent('MyComp', Comp)
@@ -107,8 +159,12 @@
107 159 app.component(name, component)
108 160 ;(componentsRegistry as Record<string, Component>)[name] = component
109 161 return component
110 162 }
163 + // If only name is provided, return the component
164 + if (name) {
165 + return (componentsRegistry as Record<string, Component>)[name]
166 + }
111 167 return componentsRegistry
112 168 }) as ComponentRegistry
113 169
114 170 // Register all Lite components for Pro plugin access
@@ -116,9 +172,14 @@
116 172
117 173 w.IvyForms.components = componentsRegistry
118 174 w.IvyForms.registerComponent = (name: string, component: Component) =>
119 175 componentsRegistry(name, component)
176 + w.IvyForms.registerComponent('EntryPage', EntryPage)
120 177
178 + registerSquareIntegration((name, component) => {
179 + componentsRegistry(name, component)
180 + })
181 +
121 182 // Expose router for Pro plugins to add routes dynamically
122 183 w.IvyForms._router = router
123 184
124 185 // Initialize pro features bridge if not already provided by Pro plugin
@@ -204,17 +265,28 @@
204 265 return false
205 266 }
206 267 }
207 268 }
269 +
270 + // Pinia settings store (same instance as Lite admin) — Pro reads `integrations.*` here.
271 + w.IvyForms.settingsStore = settingsStore
208 272 })()
209 273
274 +// Register Google Sheets after hooks + router are exposed
275 +registerGoogleSheetsAdmin()
276 +
210 277 // Register Lite field options
211 278 registerLiteFieldOptions()
212 279
280 +// Register Lite advanced style section promos (replaced by Pro via hook when available)
281 +registerLiteStyleSectionPromos()
282 +
283 +// Bind navigation helper under app context so useRouter() resolves correctly.
284 +app.runWithContext(() => {
285 + window.IvyForms.navigateToAdminPage = useNavigation().navigateToAdminPage
286 +})
287 +
213 288 app.mount('#ivyforms-app')
214 -
215 -// Initialize settings store and load settings before starting WCAG watcher
216 -const settingsStore = useSettingsStore()
217 289
218 290 // Load settings from backend first, then initialize WCAG colors
219 291 settingsStore
220 292 .loadAllSettings()