Refactoring stores and templates pages to comp. api
This commit is contained in:
parent
3b798c12fd
commit
bb519907f6
|
@ -20,7 +20,7 @@
|
|||
</button>
|
||||
</div>
|
||||
<div class="sm:flex sm:flex-col sm:items-start">
|
||||
<div v-if="$scopedSlots.hasOwnProperty('icon')" class="flex w-full justify-center mb-4">
|
||||
<div v-if="$slots.hasOwnProperty('icon')" class="flex w-full justify-center mb-4">
|
||||
<div class="w-14 h-14 rounded-full flex justify-center items-center"
|
||||
:class="'bg-'+iconColor+'-100 text-'+iconColor+'-600'"
|
||||
>
|
||||
|
@ -28,7 +28,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="mt-3 text-center sm:mt-0 w-full">
|
||||
<h2 v-if="$scopedSlots.hasOwnProperty('title')"
|
||||
<h2 v-if="$slots.hasOwnProperty('title')"
|
||||
class="text-2xl font-semibold text-center text-gray-900"
|
||||
>
|
||||
<slot name="title"/>
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
My Forms
|
||||
</NuxtLink>
|
||||
|
||||
<NuxtLink v-if="userOnboarded" :to="{ name: 'my_templates' }"
|
||||
<NuxtLink v-if="userOnboarded" :to="{ name: 'templates-my-templates' }"
|
||||
class="block block px-4 py-2 text-md text-gray-700 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-100 dark:hover:text-white dark:hover:bg-gray-600 flex items-center"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 mr-2" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
|
@ -81,7 +81,7 @@
|
|||
My Templates
|
||||
</NuxtLink>
|
||||
|
||||
<NuxtLink :to="{ name: 'settings.profile' }"
|
||||
<NuxtLink :to="{ name: 'settings-profile' }"
|
||||
class="block block px-4 py-2 text-md text-gray-700 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-100 dark:hover:text-white dark:hover:bg-gray-600 flex items-center"
|
||||
>
|
||||
<svg class="w-4 h-4 mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
||||
|
@ -209,7 +209,8 @@ export default {
|
|||
this.formsStore.resetState()
|
||||
|
||||
// Redirect to login.
|
||||
this.$router.push({ name: 'login' })
|
||||
const router = useRouter()
|
||||
router.push({ name: 'login' })
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,6 +129,12 @@ export default {
|
|||
submitButtonClass: { type: String, default: '' }
|
||||
},
|
||||
|
||||
setup() {
|
||||
return {
|
||||
isIframe: useIsIframe()
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
|
@ -143,11 +149,8 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
isIframe () {
|
||||
return window.location !== window.parent.location || window.frameElement
|
||||
},
|
||||
isEmbedPopup () {
|
||||
return window.location.href.includes('popup=true')
|
||||
return process.client && window.location.href.includes('popup=true')
|
||||
},
|
||||
theme () {
|
||||
return this.themes[this.themes.hasOwnProperty(this.form.theme) ? this.form.theme : 'default']
|
||||
|
@ -156,7 +159,7 @@ export default {
|
|||
return this.$route.name === 'forms.show_public'
|
||||
},
|
||||
isHideTitle () {
|
||||
return this.form.hide_title || window.location.href.includes('hide_title=true')
|
||||
return this.form.hide_title || (process.client && window.location.href.includes('hide_title=true'))
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -106,7 +106,8 @@ export default {
|
|||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
recordsStore,
|
||||
workingFormStore
|
||||
workingFormStore,
|
||||
darkModeEnabled: useDark()
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -118,7 +119,6 @@ export default {
|
|||
* Used to force refresh components by changing their keys
|
||||
*/
|
||||
formVersionId: 1,
|
||||
darkModeEnabled: document.body.classList.contains('dark'),
|
||||
isAutoSubmit: false,
|
||||
/**
|
||||
* If currently dragging a field
|
||||
|
@ -259,7 +259,7 @@ export default {
|
|||
return
|
||||
}
|
||||
|
||||
if (this.form.use_captcha) {
|
||||
if (this.form.use_captcha && process.client) {
|
||||
this.dataForm['h-captcha-response'] = document.getElementsByName('h-captcha-response')[0].value
|
||||
this.$refs.hcaptcha.reset()
|
||||
}
|
||||
|
@ -291,6 +291,7 @@ export default {
|
|||
}
|
||||
|
||||
// Scroll to error
|
||||
if (process.server) return
|
||||
const elements = document.getElementsByClassName('has-error')
|
||||
if (elements.length > 0) {
|
||||
window.scroll({
|
||||
|
|
|
@ -161,7 +161,7 @@ export default {
|
|||
if (response.data.message) {
|
||||
this.alertSuccess(response.data.message)
|
||||
}
|
||||
this.templatesStore.addOrUpdate(response.data.data)
|
||||
this.templatesStore.save(response.data.data)
|
||||
this.$emit('close')
|
||||
})
|
||||
},
|
||||
|
@ -171,7 +171,7 @@ export default {
|
|||
if (response.data.message) {
|
||||
this.alertSuccess(response.data.message)
|
||||
}
|
||||
this.templatesStore.addOrUpdate(response.data.data)
|
||||
this.templatesStore.save(response.data.data)
|
||||
this.$emit('close')
|
||||
})
|
||||
},
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
<script>
|
||||
import ForgotPasswordModal from '../ForgotPasswordModal.vue'
|
||||
import {opnFetch} from "~/composables/useOpnApi.js";
|
||||
|
||||
export default {
|
||||
name: 'LoginForm',
|
||||
|
@ -78,10 +79,10 @@ export default {
|
|||
const data = await this.form.post('login')
|
||||
|
||||
// Save the token.
|
||||
this.authStore.setToken(data.token, this.remember)
|
||||
this.authStore.setToken(data.token)
|
||||
|
||||
// Fetch the user.
|
||||
await this.authStore.fetchUser()
|
||||
const userData = await opnFetch('user')
|
||||
this.authStore.setUser(userData)
|
||||
|
||||
// Redirect home.
|
||||
this.redirect()
|
||||
|
@ -93,13 +94,14 @@ export default {
|
|||
return
|
||||
}
|
||||
|
||||
const intendedUrl = Cookies.get('intended_url')
|
||||
const intendedUrlCookie = useCookie('intended_url')
|
||||
const router = useRouter()
|
||||
|
||||
if (intendedUrl) {
|
||||
Cookies.remove('intended_url')
|
||||
this.$router.push({ path: intendedUrl })
|
||||
if (intendedUrlCookie.value) {
|
||||
router.push({ path: intendedUrlCookie.value })
|
||||
useCookie('intended_url').value = null
|
||||
} else {
|
||||
this.$router.push({ name: 'home' })
|
||||
router.push({ name: 'home' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<p class="line-clamp-2 mt-2 text-sm font-normal text-gray-600">
|
||||
{{ cleanQuotes(template.short_description) }}
|
||||
</p>
|
||||
<template-tags :slug="template.slug"
|
||||
<template-tags :template="template"
|
||||
class="flex mt-4 items-center flex-wrap gap-3"
|
||||
/>
|
||||
<router-link :to="{params:{slug:template.slug},name:'templates-slug'}" title="">
|
||||
|
@ -46,8 +46,7 @@ export default {
|
|||
|
||||
props: {
|
||||
template: {
|
||||
type: Object,
|
||||
required: true
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
<template>
|
||||
<div v-if="template">
|
||||
<template v-if="displayAll">
|
||||
<span v-if="template.is_new"
|
||||
class="inline-flex items-center gap-1 px-2 py-1 text-xs font-medium text-white bg-blue-500 rounded-full"
|
||||
>
|
||||
<svg aria-hidden="true" class="w-3 h-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path fill-rule="evenodd"
|
||||
d="M5 2a1 1 0 011 1v1h1a1 1 0 010 2H6v1a1 1 0 01-2 0V6H3a1 1 0 010-2h1V3a1 1 0 011-1zm0 10a1 1 0 011 1v1h1a1 1 0 110 2H6v1a1 1 0 11-2 0v-1H3a1 1 0 110-2h1v-1a1 1 0 011-1zM12 2a1 1 0 01.967.744L14.146 7.2 17.5 9.134a1 1 0 010 1.732l-3.354 1.935-1.18 4.455a1 1 0 01-1.933 0L9.854 12.8 6.5 10.866a1 1 0 010-1.732l3.354-1.935 1.18-4.455A1 1 0 0112 2z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
New
|
||||
</span>
|
||||
<span v-for="item in types"
|
||||
class="inline-flex items-center rounded-full bg-gray-50 dark:bg-gray-800 dark:text-gray-400 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10"
|
||||
>
|
||||
{{ item }}
|
||||
</span>
|
||||
<span v-for="item in industries"
|
||||
class="inline-flex items-center rounded-full bg-blue-50 dark:bg-blue-900 dark:text-gray-400 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10"
|
||||
>
|
||||
{{ item }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span v-if="types.length > 0"
|
||||
class="inline-flex items-center rounded-full bg-gray-50 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10"
|
||||
>
|
||||
{{ types[0] }} <template v-if="types.length > 1">+{{ types.length - 1 }}</template>
|
||||
</span>
|
||||
<span v-if="industries.length > 0"
|
||||
class="inline-flex items-center rounded-full bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10"
|
||||
>
|
||||
{{ industries[0] }} <template v-if="industries.length > 1">+{{ industries.length - 1 }}</template>
|
||||
</span>
|
||||
</template>
|
||||
<!-- <template v-if="displayAll">-->
|
||||
<!-- <span v-if="template.is_new"-->
|
||||
<!-- class="inline-flex items-center gap-1 px-2 py-1 text-xs font-medium text-white bg-blue-500 rounded-full"-->
|
||||
<!-- >-->
|
||||
<!-- <svg aria-hidden="true" class="w-3 h-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"-->
|
||||
<!-- fill="currentColor"-->
|
||||
<!-- >-->
|
||||
<!-- <path fill-rule="evenodd"-->
|
||||
<!-- d="M5 2a1 1 0 011 1v1h1a1 1 0 010 2H6v1a1 1 0 01-2 0V6H3a1 1 0 010-2h1V3a1 1 0 011-1zm0 10a1 1 0 011 1v1h1a1 1 0 110 2H6v1a1 1 0 11-2 0v-1H3a1 1 0 110-2h1v-1a1 1 0 011-1zM12 2a1 1 0 01.967.744L14.146 7.2 17.5 9.134a1 1 0 010 1.732l-3.354 1.935-1.18 4.455a1 1 0 01-1.933 0L9.854 12.8 6.5 10.866a1 1 0 010-1.732l3.354-1.935 1.18-4.455A1 1 0 0112 2z"-->
|
||||
<!-- clip-rule="evenodd"-->
|
||||
<!-- />-->
|
||||
<!-- </svg>-->
|
||||
<!-- New-->
|
||||
<!-- </span>-->
|
||||
<!-- <span v-for="item in types"-->
|
||||
<!-- class="inline-flex items-center rounded-full bg-gray-50 dark:bg-gray-800 dark:text-gray-400 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10"-->
|
||||
<!-- >-->
|
||||
<!-- {{ item }}-->
|
||||
<!-- </span>-->
|
||||
<!-- <span v-for="item in industries"-->
|
||||
<!-- class="inline-flex items-center rounded-full bg-blue-50 dark:bg-blue-900 dark:text-gray-400 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10"-->
|
||||
<!-- >-->
|
||||
<!-- {{ item }}-->
|
||||
<!-- </span>-->
|
||||
<!-- </template>-->
|
||||
<!-- <template v-else>-->
|
||||
<!-- <span v-if="types.length > 0"-->
|
||||
<!-- class="inline-flex items-center rounded-full bg-gray-50 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10"-->
|
||||
<!-- >-->
|
||||
<!-- {{ types[0] }} <template v-if="types.length > 1">+{{ types.length - 1 }}</template>-->
|
||||
<!-- </span>-->
|
||||
<!-- <span v-if="industries.length > 0"-->
|
||||
<!-- class="inline-flex items-center rounded-full bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10"-->
|
||||
<!-- >-->
|
||||
<!-- {{ industries[0] }} <template v-if="industries.length > 1">+{{ industries.length - 1 }}</template>-->
|
||||
<!-- </span>-->
|
||||
<!-- </template>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -46,8 +46,8 @@ import { useTemplatesStore } from '../../../stores/templates'
|
|||
|
||||
export default {
|
||||
props: {
|
||||
slug: {
|
||||
type: String,
|
||||
template: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
displayAll: {
|
||||
|
@ -66,19 +66,17 @@ export default {
|
|||
data: () => ({}),
|
||||
|
||||
computed: {
|
||||
template () {
|
||||
return this.templatesStore.getBySlug(this.slug)
|
||||
},
|
||||
types () {
|
||||
if (!this.template) return null
|
||||
console.log('template in types',this.template)
|
||||
return this.templatesStore.getTemplateTypes(this.template.types)
|
||||
},
|
||||
industries () {
|
||||
if (!this.template) return null
|
||||
console.log('template in types',this.template)
|
||||
return this.templatesStore.getTemplateIndustries(this.template.industries)
|
||||
}
|
||||
// template () {
|
||||
// return this.templatesStore.getByKey(this.slug)
|
||||
// },
|
||||
// types () {
|
||||
// if (!this.template) return null
|
||||
// return this.templatesStore.getTemplateTypes(this.template.types)
|
||||
// },
|
||||
// industries () {
|
||||
// if (!this.template) return null
|
||||
// return this.templatesStore.getTemplateIndustries(this.template.industries)
|
||||
// }
|
||||
},
|
||||
|
||||
methods: {}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="templatesLoading" class="text-center mt-4">
|
||||
<div v-if="loading" class="text-center mt-4">
|
||||
<Loader class="h-6 w-6 text-nt-blue mx-auto"/>
|
||||
</div>
|
||||
<p v-else-if="enrichedTemplates.length === 0" class="text-center mt-4">
|
||||
|
@ -83,15 +83,6 @@ import Form from 'vform'
|
|||
import Fuse from 'fuse.js'
|
||||
import SingleTemplate from './SingleTemplate.vue'
|
||||
|
||||
// const loadTemplates = function (onlyMy) {
|
||||
// const templatesStore = useTemplatesStore()
|
||||
// if(onlyMy){
|
||||
// templatesStore.loadAll({'onlymy':true})
|
||||
// } else {
|
||||
// templatesStore.loadIfEmpty()
|
||||
// }
|
||||
// }
|
||||
|
||||
export default {
|
||||
name: 'TemplatesList',
|
||||
components: {SingleTemplate},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {serialize} from 'object-to-formdata';
|
||||
import Errors from './Errors';
|
||||
import cloneDeep from 'clone-deep';
|
||||
import {opnFetch} from "~/composables/useOpnApi.js";
|
||||
function hasFiles(data) {
|
||||
return data instanceof File ||
|
||||
data instanceof Blob ||
|
||||
|
@ -120,18 +121,14 @@ class Form {
|
|||
config.transformRequest = [data => serialize(data)];
|
||||
}
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
useOpnApi(config.url, config)
|
||||
.then(({data, error}) => {
|
||||
if (error.value) {
|
||||
this.handleErrors(error);
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
opnFetch(config.url, config)
|
||||
.then((data) => {
|
||||
this.finishProcessing();
|
||||
resolve(data.value);
|
||||
resolve(data);
|
||||
}).catch((error) => {
|
||||
this.handleErrors(error);
|
||||
resolve(error)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
@ -139,8 +136,8 @@ class Form {
|
|||
handleErrors(error) {
|
||||
this.busy = false;
|
||||
|
||||
if (error.value) {
|
||||
this.errors.set(this.extractErrors(error.value.data));
|
||||
if (error) {
|
||||
this.errors.set(this.extractErrors(error.data));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
// Composable with all the logic to encapsulate a default content store
|
||||
|
||||
export const useContentStore = (mapKey = 'id') => {
|
||||
|
||||
const content = ref(new Map())
|
||||
const loading = ref(false)
|
||||
|
||||
// Computed
|
||||
const getAll = computed(() => {
|
||||
return [...content.value.values()]
|
||||
})
|
||||
const getByKey = (key) => {
|
||||
if (Array.isArray(key)) {
|
||||
return key.map((k) => content.value.get(k)).filter((item) => item !== undefined)
|
||||
}
|
||||
return content.value.get(key)
|
||||
}
|
||||
|
||||
// Actions
|
||||
function set(items) {
|
||||
content.value = new Map
|
||||
items.forEach((item) => {
|
||||
content.value.set(item[mapKey], item)
|
||||
})
|
||||
}
|
||||
|
||||
function save(items) {
|
||||
if (!Array.isArray(items)) items = [items]
|
||||
items.forEach((item) => {
|
||||
content.value.set(item[mapKey], item)
|
||||
})
|
||||
}
|
||||
|
||||
function remove(item) {
|
||||
content.value.remove(item[mapKey])
|
||||
}
|
||||
|
||||
function startLoading() {
|
||||
loading.value = true
|
||||
}
|
||||
|
||||
function stopLoading() {
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
function resetState() {
|
||||
set([])
|
||||
stopLoading()
|
||||
}
|
||||
|
||||
return {
|
||||
content,
|
||||
loading,
|
||||
getAll,
|
||||
getByKey,
|
||||
set,
|
||||
save,
|
||||
remove,
|
||||
startLoading,
|
||||
stopLoading,
|
||||
resetState
|
||||
}
|
||||
}
|
|
@ -44,6 +44,10 @@ export function getOpnRequestsOptions(request, opts) {
|
|||
}
|
||||
}
|
||||
|
||||
export const opnFetch = (request, opts = {}) => {
|
||||
return $fetch(request, getOpnRequestsOptions(request, opts))
|
||||
}
|
||||
|
||||
export const useOpnApi = (request, opts = {}) => {
|
||||
return useFetch(request, getOpnRequestsOptions(request, opts))
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import {useWorkspacesStore} from "~/stores/workspaces.js";
|
||||
|
||||
export default defineNuxtRouteMiddleware(async(to, from) => {
|
||||
const authStore = useAuthStore()
|
||||
authStore.initStore(useCookie('token').value, useCookie('admin_token').value)
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
"js-sha256": "^0.9.0",
|
||||
"libphonenumber-js": "^1.10.44",
|
||||
"object-to-formdata": "^4.5.1",
|
||||
"pinia": "^2.1.7",
|
||||
"prismjs": "^1.24.1",
|
||||
"qrcode": "^1.5.1",
|
||||
"query-builder-vue-3": "^1.0.1",
|
||||
|
@ -2549,56 +2550,6 @@
|
|||
"url": "https://github.com/sponsors/posva"
|
||||
}
|
||||
},
|
||||
"node_modules/@pinia/nuxt/node_modules/pinia": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz",
|
||||
"integrity": "sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==",
|
||||
"dependencies": {
|
||||
"@vue/devtools-api": "^6.5.0",
|
||||
"vue-demi": ">=0.14.5"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/posva"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.4.0",
|
||||
"typescript": ">=4.4.4",
|
||||
"vue": "^2.6.14 || ^3.3.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
},
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@pinia/nuxt/node_modules/vue-demi": {
|
||||
"version": "0.14.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
|
||||
"integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.0.0-rc.1",
|
||||
"vue": "^3.0.0-0 || ^2.6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgjs/parseargs": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||
|
@ -2828,9 +2779,9 @@
|
|||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.0.tgz",
|
||||
"integrity": "sha512-+1ge/xmaJpm1KVBuIH38Z94zj9fBD+hp+/5WLaHgyY8XLq1ibxk/zj6dTXaqM2cAbYKq8jYlhHd6k05If1W5xA==",
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.1.tgz",
|
||||
"integrity": "sha512-6vMdBZqtq1dVQ4CWdhFwhKZL6E4L1dV6jUjuBvsavvNJSppzi6dLBbuV+3+IyUREaj9ZFvQefnQm28v4OCXlig==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
|
@ -2840,9 +2791,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.0.tgz",
|
||||
"integrity": "sha512-im6hUEyQ7ZfoZdNvtwgEJvBWZYauC9KVKq1w58LG2Zfz6zMd8gRrbN+xCVoqA2hv/v6fm9lp5LFGJ3za8EQH3A==",
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.1.tgz",
|
||||
"integrity": "sha512-Jto9Fl3YQ9OLsTDWtLFPtaIMSL2kwGyGoVCmPC8Gxvym9TCZm4Sie+cVeblPO66YZsYH8MhBKDMGZ2NDxuk/XQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -2852,9 +2803,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.0.tgz",
|
||||
"integrity": "sha512-u7aTMskN6Dmg1lCT0QJ+tINRt+ntUrvVkhbPfFz4bCwRZvjItx2nJtwJnJRlKMMaQCHRjrNqHRDYvE4mBm3DlQ==",
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.1.tgz",
|
||||
"integrity": "sha512-LtYcLNM+bhsaKAIGwVkh5IOWhaZhjTfNOkGzGqdHvhiCUVuJDalvDxEdSnhFzAn+g23wgsycmZk1vbnaibZwwA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -2864,9 +2815,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.0.tgz",
|
||||
"integrity": "sha512-8FvEl3w2ExmpcOmX5RJD0yqXcVSOqAJJUJ29Lca29Ik+3zPS1yFimr2fr5JSZ4Z5gt8/d7WqycpgkX9nocijSw==",
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.1.tgz",
|
||||
"integrity": "sha512-KyP/byeXu9V+etKO6Lw3E4tW4QdcnzDG/ake031mg42lob5tN+5qfr+lkcT/SGZaH2PdW4Z1NX9GHEkZ8xV7og==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -2876,9 +2827,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.0.tgz",
|
||||
"integrity": "sha512-lHoKYaRwd4gge+IpqJHCY+8Vc3hhdJfU6ukFnnrJasEBUvVlydP8PuwndbWfGkdgSvZhHfSEw6urrlBj0TSSfg==",
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.1.tgz",
|
||||
"integrity": "sha512-Yqz/Doumf3QTKplwGNrCHe/B2p9xqDghBZSlAY0/hU6ikuDVQuOUIpDP/YcmoT+447tsZTmirmjgG3znvSCR0Q==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
|
@ -2888,9 +2839,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.0.tgz",
|
||||
"integrity": "sha512-JbEPfhndYeWHfOSeh4DOFvNXrj7ls9S/2omijVsao+LBPTPayT1uKcK3dHW3MwDJ7KO11t9m2cVTqXnTKpeaiw==",
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.1.tgz",
|
||||
"integrity": "sha512-u3XkZVvxcvlAOlQJ3UsD1rFvLWqu4Ef/Ggl40WAVCuogf4S1nJPHh5RTgqYFpCOvuGJ7H5yGHabjFKEZGExk5Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -2900,9 +2851,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.0.tgz",
|
||||
"integrity": "sha512-ahqcSXLlcV2XUBM3/f/C6cRoh7NxYA/W7Yzuv4bDU1YscTFw7ay4LmD7l6OS8EMhTNvcrWGkEettL1Bhjf+B+w==",
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.1.tgz",
|
||||
"integrity": "sha512-0XSYN/rfWShW+i+qjZ0phc6vZ7UWI8XWNz4E/l+6edFt+FxoEghrJHjX1EY/kcUGCnZzYYRCl31SNdfOi450Aw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -2912,9 +2863,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.0.tgz",
|
||||
"integrity": "sha512-uwvOYNtLw8gVtrExKhdFsYHA/kotURUmZYlinH2VcQxNCQJeJXnkmWgw2hI9Xgzhgu7J9QvWiq9TtTVwWMDa+w==",
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.1.tgz",
|
||||
"integrity": "sha512-LmYIO65oZVfFt9t6cpYkbC4d5lKHLYv5B4CSHRpnANq0VZUQXGcCPXHzbCXCz4RQnx7jvlYB1ISVNCE/omz5cw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
|
@ -2924,9 +2875,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.0.tgz",
|
||||
"integrity": "sha512-m6pkSwcZZD2LCFHZX/zW2aLIISyzWLU3hrLLzQKMI12+OLEzgruTovAxY5sCZJkipklaZqPy/2bEEBNjp+Y7xg==",
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.1.tgz",
|
||||
"integrity": "sha512-kr8rEPQ6ns/Lmr/hiw8sEVj9aa07gh1/tQF2Y5HrNCCEPiCBGnBUt9tVusrcBBiJfIt1yNaXN6r1CCmpbFEDpg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -2936,9 +2887,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.0.tgz",
|
||||
"integrity": "sha512-VFAC1RDRSbU3iOF98X42KaVicAfKf0m0OvIu8dbnqhTe26Kh6Ym9JrDulz7Hbk7/9zGc41JkV02g+p3BivOdAg==",
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.1.tgz",
|
||||
"integrity": "sha512-t4QSR7gN+OEZLG0MiCgPqMWZGwmeHhsM4AkegJ0Kiy6TnJ9vZ8dEIwHw1LcZKhbHxTY32hp9eVCMdR3/I8MGRw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -2948,9 +2899,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.0.tgz",
|
||||
"integrity": "sha512-9jPgMvTKXARz4inw6jezMLA2ihDBvgIU9Ml01hjdVpOcMKyxFBJrn83KVQINnbeqDv0+HdO1c09hgZ8N0s820Q==",
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.1.tgz",
|
||||
"integrity": "sha512-7XI4ZCBN34cb+BH557FJPmh0kmNz2c25SCQeT9OiFWEgf8+dL6ZwJ8f9RnUIit+j01u07Yvrsuu1rZGxJCc51g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -2960,9 +2911,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.0.tgz",
|
||||
"integrity": "sha512-WE4pT2kTXQN2bAv40Uog0AsV7/s9nT9HBWXAou8+++MBCnY51QS02KYtm6dQxxosKi1VIz/wZIrTQO5UP2EW+Q==",
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.1.tgz",
|
||||
"integrity": "sha512-yE5c2j1lSWOH5jp+Q0qNL3Mdhr8WuqCNVjc6BxbVfS5cAS6zRmdiw7ktb8GNpDCEUJphILY6KACoFoRtKoqNQg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
|
@ -2972,9 +2923,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.0.tgz",
|
||||
"integrity": "sha512-aPP5Q5AqNGuT0tnuEkK/g4mnt3ZhheiXrDIiSVIHN9mcN21OyXDVbEMqmXPE7e2OplNLDkcvV+ZoGJa2ZImFgw==",
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.1.tgz",
|
||||
"integrity": "sha512-PyJsSsafjmIhVgaI1Zdj7m8BB8mMckFah/xbpplObyHfiXzKcI5UOUXRyOdHW7nz4DpMCuzLnF7v5IWHenCwYA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -3227,9 +3178,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz",
|
||||
"integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==",
|
||||
"version": "20.10.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz",
|
||||
"integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==",
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
|
@ -6732,9 +6683,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/libphonenumber-js": {
|
||||
"version": "1.10.51",
|
||||
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.51.tgz",
|
||||
"integrity": "sha512-vY2I+rQwrDQzoPds0JeTEpeWzbUJgqoV0O4v31PauHBb/e+1KCXKylHcDnBMgJZ9fH9mErsEbROJY3Z3JtqEmg=="
|
||||
"version": "1.10.52",
|
||||
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.52.tgz",
|
||||
"integrity": "sha512-6vCuCHgem+OW1/VCAKgkasfegItCea8zIT7s9/CG/QxdCMIM7GfzbEBG5d7lGO3rzipjt5woOQL3DiHa8Fy78Q=="
|
||||
},
|
||||
"node_modules/lie": {
|
||||
"version": "3.1.1",
|
||||
|
@ -8195,6 +8146,56 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pinia": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz",
|
||||
"integrity": "sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==",
|
||||
"dependencies": {
|
||||
"@vue/devtools-api": "^6.5.0",
|
||||
"vue-demi": ">=0.14.5"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/posva"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.4.0",
|
||||
"typescript": ">=4.4.4",
|
||||
"vue": "^2.6.14 || ^3.3.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
},
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/pinia/node_modules/vue-demi": {
|
||||
"version": "0.14.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
|
||||
"integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.0.0-rc.1",
|
||||
"vue": "^3.0.0-0 || ^2.6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/pirates": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
|
||||
|
@ -9212,9 +9213,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.0.tgz",
|
||||
"integrity": "sha512-bUHW/9N21z64gw8s6tP4c88P382Bq/L5uZDowHlHx6s/QWpjJXivIAbEw6LZthgSvlEizZBfLC4OAvWe7aoF7A==",
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.1.tgz",
|
||||
"integrity": "sha512-pgPO9DWzLoW/vIhlSoDByCzcpX92bKEorbgXuZrqxByte3JFk2xSW2JEeAcyLc9Ru9pqcNNW+Ob7ntsk2oT/Xw==",
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
|
@ -9223,19 +9224,19 @@
|
|||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.9.0",
|
||||
"@rollup/rollup-android-arm64": "4.9.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.9.0",
|
||||
"@rollup/rollup-darwin-x64": "4.9.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.9.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.9.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.9.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.9.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.9.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.9.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.9.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.9.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.9.0",
|
||||
"@rollup/rollup-android-arm-eabi": "4.9.1",
|
||||
"@rollup/rollup-android-arm64": "4.9.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.9.1",
|
||||
"@rollup/rollup-darwin-x64": "4.9.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.9.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.9.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.9.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.9.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.9.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.9.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.9.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.9.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.9.1",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
"js-sha256": "^0.9.0",
|
||||
"libphonenumber-js": "^1.10.44",
|
||||
"object-to-formdata": "^4.5.1",
|
||||
"pinia": "^2.1.7",
|
||||
"prismjs": "^1.24.1",
|
||||
"qrcode": "^1.5.1",
|
||||
"query-builder-vue-3": "^1.0.1",
|
||||
|
|
|
@ -121,7 +121,7 @@ export default {
|
|||
this.initForm()
|
||||
this.formInitialHash = this.hashString(JSON.stringify(this.form.data()))
|
||||
if (this.$route.query.template !== undefined && this.$route.query.template) {
|
||||
const template = this.templatesStore.getBySlug(this.$route.query.template)
|
||||
const template = this.templatesStore.getByKey(this.$route.query.template)
|
||||
if (template && template.structure) {
|
||||
this.form = new Form({ ...this.form.data(), ...template.structure })
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ export default {
|
|||
|
||||
this.initForm()
|
||||
if (this.$route.query.template !== undefined && this.$route.query.template) {
|
||||
const template = this.templatesStore.getBySlug(this.$route.query.template)
|
||||
const template = this.templatesStore.getByKey(this.$route.query.template)
|
||||
if (template && template.structure) {
|
||||
this.form = new Form({ ...this.form.data(), ...template.structure })
|
||||
}
|
||||
|
|
|
@ -126,10 +126,8 @@ const loadForms = function () {
|
|||
const formsStore = useFormsStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
formsStore.startLoading()
|
||||
return workspacesStore.loadIfEmpty().then(() => {
|
||||
if (process.client) {
|
||||
formsStore.loadIfEmpty(workspacesStore.currentId)
|
||||
}
|
||||
workspacesStore.loadIfEmpty().then(() => {
|
||||
formsStore.loadIfEmpty(workspacesStore.currentId)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<div class="flex flex-col min-h-full">
|
||||
<breadcrumb :path="breadcrumbs">
|
||||
<breadcrumb :path="breadcrumbs" v-if="template">
|
||||
<template #left>
|
||||
<div v-if="canEditTemplate" class="ml-5">
|
||||
<v-button color="gray" size="small" @click.prevent="showFormTemplateModal=true">
|
||||
Edit Template
|
||||
</v-button>
|
||||
<form-template-modal v-if="form" :form="form" :template="template" :show="showFormTemplateModal"
|
||||
@close="showFormTemplateModal=false"
|
||||
/>
|
||||
<!-- <form-template-modal v-if="form" :form="form" :template="template" :show="showFormTemplateModal"-->
|
||||
<!-- @close="showFormTemplateModal=false"-->
|
||||
<!-- />-->
|
||||
</div>
|
||||
</template>
|
||||
<template #right>
|
||||
|
@ -25,10 +25,7 @@
|
|||
</template>
|
||||
</breadcrumb>
|
||||
|
||||
<div v-if="templatesLoading" class="text-center my-4">
|
||||
<Loader class="h-6 w-6 text-nt-blue mx-auto"/>
|
||||
</div>
|
||||
<p v-else-if="template === null || !template" class="text-center my-4">
|
||||
<p v-if="template === null || !template" class="text-center my-4">
|
||||
We could not find this template.
|
||||
</p>
|
||||
<template v-else>
|
||||
|
@ -48,9 +45,9 @@
|
|||
<p class="mt-2 text-lg font-normal text-gray-600">
|
||||
{{ cleanQuotes(template.short_description) }}
|
||||
</p>
|
||||
<template-tags :slug="template.slug" :display-all="true"
|
||||
class="flex flex-wrap items-center justify-center gap-3 mt-4 md:justify-start"
|
||||
/>
|
||||
<!-- <template-tags :slug="template.slug" :display-all="true"-->
|
||||
<!-- class="flex flex-wrap items-center justify-center gap-3 mt-4 md:justify-start"-->
|
||||
<!-- />-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -119,7 +116,8 @@
|
|||
</div>
|
||||
</section>
|
||||
|
||||
<section v-if="template.related_templates.length > 0" class="py-12 bg-white border-t border-gray-200 sm:py-16">
|
||||
<section v-if="relatedTemplates && relatedTemplates.length > 0"
|
||||
class="py-12 bg-white border-t border-gray-200 sm:py-16">
|
||||
<div class="px-4 mx-auto sm:px-6 lg:px-8 max-w-7xl">
|
||||
<div class="flex items-center justify-between">
|
||||
<h4 class="text-xl font-bold tracking-tight text-gray-900 sm:text-2xl">
|
||||
|
@ -131,7 +129,7 @@
|
|||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 gap-8 mt-8 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 sm:gap-y-12">
|
||||
<single-template v-for="related in template.related_templates" :key="related.id" :template="related"/>
|
||||
<single-template v-for="related in relatedTemplates" :key="related.id" :template="related"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -196,108 +194,93 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Form from 'vform'
|
||||
<script setup>
|
||||
import {computed} from 'vue'
|
||||
import OpenCompleteForm from '../../components/open/forms/OpenCompleteForm.vue'
|
||||
import Breadcrumb from '~/components/global/Breadcrumb.vue'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
import TemplateTags from '../../components/pages/templates/TemplateTags.vue'
|
||||
import SingleTemplate from '../../components/pages/templates/SingleTemplate.vue'
|
||||
import FormTemplateModal from '../../components/open/forms/components/templates/FormTemplateModal.vue'
|
||||
import {fetchTemplate} from "~/stores/templates.js";
|
||||
|
||||
export default {
|
||||
const authStore = useAuthStore()
|
||||
const templatesStore = useTemplatesStore()
|
||||
|
||||
components: {Breadcrumb, OpenCompleteForm, TemplateTags, SingleTemplate, FormTemplateModal},
|
||||
mixins: [SeoMeta],
|
||||
const route = useRoute()
|
||||
const slug = computed(() => route.params.slug)
|
||||
|
||||
setup() {
|
||||
const authStore = useAuthStore()
|
||||
const templatesStore = useTemplatesStore()
|
||||
const template = computed(() => templatesStore.getByKey(slug.value))
|
||||
const form = computed(() => template.value.structure)
|
||||
|
||||
const route = useRoute()
|
||||
const slug = computed(() => route.params.slug)
|
||||
if (slug) {
|
||||
templatesStore.loadTemplate(slug)
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
templatesStore,
|
||||
authenticated: computed(() => authStore.check),
|
||||
user: computed(() => authStore.user),
|
||||
templatesLoading: computed(() => templatesStore.loading)
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
showFormTemplateModal: false
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
},
|
||||
|
||||
methods: {
|
||||
cleanQuotes(str) {
|
||||
// Remove starting and ending quotes if any
|
||||
return (str) ? str.replace(/^"/, '').replace(/"$/, '') : ''
|
||||
},
|
||||
copyTemplateUrl() {
|
||||
const str = this.template.share_url
|
||||
const el = document.createElement('textarea')
|
||||
el.value = str
|
||||
document.body.appendChild(el)
|
||||
el.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(el)
|
||||
this.alertSuccess('Copied!')
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
breadcrumbs() {
|
||||
if (!this.template) {
|
||||
return [{route: {name: 'templates'}, label: 'Templates'}]
|
||||
}
|
||||
return [{route: {name: 'templates'}, label: 'Templates'}, {label: this.template.name}]
|
||||
},
|
||||
template() {
|
||||
return this.templatesStore.getBySlug(this.$route.params.slug)
|
||||
},
|
||||
form() {
|
||||
return this.template ? new Form(this.template.structure) : null
|
||||
},
|
||||
canEditTemplate() {
|
||||
return this.user && this.template && (this.user.admin || this.user.template_editor || this.template.creator_id === this.user.id)
|
||||
},
|
||||
metaTitle() {
|
||||
return this.template ? this.template.name : 'Form Template'
|
||||
},
|
||||
metaDescription() {
|
||||
if (!this.template) return null
|
||||
// take the first 140 characters of the description
|
||||
return this.template.short_description?.substring(0, 140) + '... | Customize any template and create your own form in minutes.'
|
||||
},
|
||||
metaImage() {
|
||||
if (!this.template) return null
|
||||
return this.template.image_url
|
||||
},
|
||||
metaTags() {
|
||||
if (!this.template) {
|
||||
return [];
|
||||
}
|
||||
return this.template.publicly_listed ? [] : [{name: 'robots', content: 'noindex'}]
|
||||
},
|
||||
createFormWithTemplateUrl() {
|
||||
if (this.authenticated) {
|
||||
return '/forms/create?template=' + this.template?.slug
|
||||
}
|
||||
return '/forms/create/guest?template=' + this.template?.slug
|
||||
}
|
||||
}
|
||||
// Fetch the template
|
||||
if (!template.value) {
|
||||
const {data} = await fetchTemplate(slug.value)
|
||||
templatesStore.save(data.value)
|
||||
}
|
||||
|
||||
// Fetch related templates
|
||||
const {data: relatedTemplatesData} = await useAsyncData('related-templates', () => {
|
||||
return Promise.all(template.value.related_templates.map((slug) => {
|
||||
if (templatesStore.getByKey(slug)) {
|
||||
return Promise.resolve(templatesStore.getByKey(slug))
|
||||
}
|
||||
return fetchTemplate(slug).then((res) => res.data.value)
|
||||
}))
|
||||
})
|
||||
templatesStore.save(relatedTemplatesData.value)
|
||||
|
||||
// State
|
||||
const showFormTemplateModal = ref(false)
|
||||
|
||||
// Computed
|
||||
const breadcrumbs = computed(() => {
|
||||
if (!template.value) {
|
||||
return [{route: {name: 'templates'}, label: 'Templates'}]
|
||||
}
|
||||
return [{route: {name: 'templates'}, label: 'Templates'}, {label: template.name}]
|
||||
})
|
||||
const relatedTemplates = computed(() => templatesStore.getByKey(template?.value?.related_templates))
|
||||
const canEditTemplate = computed(() => authStore.authenticated && template.value && (authStore.user.admin || authStore.user.template_editor || template.creator_id === authStore.user.id))
|
||||
const createFormWithTemplateUrl = computed(() => {
|
||||
if (authStore.authenticated) {
|
||||
return '/forms/create?template=' + template?.value?.slug
|
||||
}
|
||||
return '/forms/create/guest?template=' + template?.value?.slug
|
||||
})
|
||||
|
||||
// methods
|
||||
const cleanQuotes = (str) => {
|
||||
// Remove starting and ending quotes if any
|
||||
return (str) ? str.replace(/^"/, '').replace(/"$/, '') : ''
|
||||
}
|
||||
|
||||
const copyTemplateUrl = () => {
|
||||
const str = template.value.share_url
|
||||
const el = document.createElement('textarea')
|
||||
el.value = str
|
||||
document.body.appendChild(el)
|
||||
el.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(el)
|
||||
this.alertSuccess('Copied!')
|
||||
}
|
||||
|
||||
// metaTitle() {
|
||||
// return this.template ? this.template.name : 'Form Template'
|
||||
// },
|
||||
// metaDescription() {
|
||||
// if (!this.template) return null
|
||||
// // take the first 140 characters of the description
|
||||
// return this.template.short_description?.substring(0, 140) + '... | Customize any template and create your own form in minutes.'
|
||||
// },
|
||||
// metaImage() {
|
||||
// if (!this.template) return null
|
||||
// return this.template.image_url
|
||||
// },
|
||||
// metaTags() {
|
||||
// if (!this.template) {
|
||||
// return [];
|
||||
// }
|
||||
// return this.template.publicly_listed ? [] : [{name: 'robots', content: 'noindex'}]
|
||||
// },
|
||||
</script>
|
||||
|
||||
<style lang='scss'>
|
||||
|
|
|
@ -13,32 +13,28 @@
|
|||
</div>
|
||||
</section>
|
||||
|
||||
<templates-list :templates="templates" :loading="loading" />
|
||||
<templates-list :templates="templates"/>
|
||||
|
||||
<open-form-footer class="mt-8 border-t"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
import {useTemplatesStore} from "~/stores/templates.js";
|
||||
<script setup>
|
||||
import {fetchAllTemplates} from "~/stores/templates.js";
|
||||
|
||||
export default {
|
||||
// props: {
|
||||
// metaTitle: { type: String, default: 'Templates' },
|
||||
// metaDescription: { type: String, default: 'Our collection of beautiful templates to create your own forms!' }
|
||||
// },
|
||||
|
||||
mixins: [SeoMeta],
|
||||
const templatesStore = useTemplatesStore()
|
||||
|
||||
props: {
|
||||
metaTitle: { type: String, default: 'Templates' },
|
||||
metaDescription: { type: String, default: 'Our collection of beautiful templates to create your own forms!' }
|
||||
},
|
||||
|
||||
setup() {
|
||||
const templatesStore = useTemplatesStore()
|
||||
templatesStore.loadAll()
|
||||
return {
|
||||
templates: templatesStore.content,
|
||||
loading: templatesStore.loading
|
||||
}
|
||||
},
|
||||
if (!templatesStore.allLoaded) {
|
||||
templatesStore.startLoading()
|
||||
const {data} = await fetchAllTemplates()
|
||||
templatesStore.set(data.value)
|
||||
templatesStore.allLoaded = true
|
||||
}
|
||||
|
||||
const templates = computed(() => templatesStore.getAll)
|
||||
</script>
|
||||
|
|
|
@ -22,7 +22,7 @@ export const useAuthStore = defineStore('auth', {
|
|||
stopImpersonating() {
|
||||
this.token = this.admin_token
|
||||
this.admin_token = null
|
||||
this.fetchUser()
|
||||
// TODO: re-fetch user
|
||||
},
|
||||
|
||||
setToken(token) {
|
||||
|
@ -79,7 +79,7 @@ export const useAuthStore = defineStore('auth', {
|
|||
|
||||
async logout() {
|
||||
try {
|
||||
await axios.post('/api/logout')
|
||||
await useOpnApi('logout', {method: 'POST'})
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
|
|
|
@ -1,120 +1,53 @@
|
|||
import {defineStore} from 'pinia'
|
||||
import {useContentStore} from "~/composables/stores/useContentStore.js";
|
||||
|
||||
export const templatesEndpoint = '/templates'
|
||||
export const useTemplatesStore = defineStore('templates', {
|
||||
state: () => ({
|
||||
content: [], // TODO: convert to a map
|
||||
industries: {},
|
||||
types: {},
|
||||
allLoaded: false,
|
||||
loading: false
|
||||
}),
|
||||
getters: {
|
||||
getBySlug: (state) => (slug) => {
|
||||
if (state.content.length === 0) return null
|
||||
return state.content.find(item => item.slug === slug)
|
||||
},
|
||||
getTemplateTypes: (state) => (slugs) => {
|
||||
if (state.types.length === 0) return null
|
||||
return Object.values(state.types).filter((val) => slugs.includes(val.slug)).map((item) => {
|
||||
return item.name
|
||||
})
|
||||
},
|
||||
getTemplateIndustries: (state) => (slugs) => {
|
||||
if (state.industries.length === 0) return null
|
||||
return Object.values(state.industries).filter((val) => slugs.includes(val.slug)).map((item) => {
|
||||
return item.name
|
||||
})
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
set(items) {
|
||||
this.content = items
|
||||
this.allLoaded = true
|
||||
},
|
||||
append(items) {
|
||||
const ids = items.map((item) => {
|
||||
return item.id
|
||||
})
|
||||
this.content = this.content.filter((val) => !ids.includes(val.id))
|
||||
this.content = this.content.concat(items)
|
||||
},
|
||||
addOrUpdate(item) {
|
||||
this.content = this.content.filter((val) => val.id !== item.id)
|
||||
this.content.push(item)
|
||||
},
|
||||
remove(item) {
|
||||
this.content = this.content.filter((val) => val.id !== item.id)
|
||||
},
|
||||
startLoading() {
|
||||
this.loading = true
|
||||
},
|
||||
stopLoading() {
|
||||
this.loading = false
|
||||
},
|
||||
setAllLoaded(val) {
|
||||
this.allLoaded = val
|
||||
},
|
||||
resetState() {
|
||||
this.set([])
|
||||
this.stopLoading()
|
||||
},
|
||||
async loadTypesAndIndustries() {
|
||||
if (Object.keys(this.industries).length === 0 || Object.keys(this.types).length === 0) {
|
||||
// const files = import.meta.glob('~/data/forms/templates/*.json')
|
||||
// console.log(await files['/data/forms/templates/industries.json']())
|
||||
// this.industries = await files['/data/forms/templates/industries.json']()
|
||||
// this.types = await files['/data/forms/templates/types.json']()
|
||||
}
|
||||
},
|
||||
loadTemplate(slug) {
|
||||
console.log('loading template',slug)
|
||||
this.startLoading()
|
||||
this.loadTypesAndIndustries()
|
||||
const templatesEndpoint = 'templates'
|
||||
export const useTemplatesStore = defineStore('templates', () => {
|
||||
|
||||
if (this.getBySlug(slug)) {
|
||||
this.stopLoading()
|
||||
return Promise.resolve()
|
||||
}
|
||||
const contentStore = useContentStore('slug')
|
||||
|
||||
return useOpnApi(templatesEndpoint + '/' + slug).then(({data, error}) => {
|
||||
this.addOrUpdate(data.value)
|
||||
this.stopLoading()
|
||||
}).catch((error) => {
|
||||
this.stopLoading()
|
||||
})
|
||||
},
|
||||
loadAll(options = null) {
|
||||
this.startLoading()
|
||||
this.loadTypesAndIndustries()
|
||||
const allLoaded = ref(false)
|
||||
const industries = ref({})
|
||||
const types = ref({})
|
||||
|
||||
// Prepare with options
|
||||
let queryStr = ''
|
||||
if (options !== null) {
|
||||
for (const [key, value] of Object.entries(options)) {
|
||||
queryStr += '&' + encodeURIComponent(key) + '=' + encodeURIComponent(value)
|
||||
}
|
||||
queryStr = queryStr.slice(1)
|
||||
}
|
||||
return useOpnApi((queryStr) ? templatesEndpoint + '?' + queryStr : templatesEndpoint).then(({data, error}) => {
|
||||
if (options !== null) {
|
||||
this.set(data.value)
|
||||
this.setAllLoaded(false)
|
||||
} else {
|
||||
this.append(data.value)
|
||||
this.setAllLoaded(true)
|
||||
}
|
||||
this.stopLoading()
|
||||
}).catch((error) => {
|
||||
this.stopLoading()
|
||||
})
|
||||
},
|
||||
loadIfEmpty() {
|
||||
if (!this.allLoaded) {
|
||||
return this.loadAll()
|
||||
}
|
||||
this.stopLoading()
|
||||
return Promise.resolve()
|
||||
const getTemplateTypes = computed((state) => (slugs) => {
|
||||
if (state.types.length === 0) return null
|
||||
return Object.values(state.types).filter((val) => slugs.includes(val.slug)).map((item) => {
|
||||
return item.name
|
||||
})
|
||||
// todo: use map
|
||||
})
|
||||
const getTemplateIndustries = computed((state) => (slugs) => {
|
||||
if (state.industries.length === 0) return null
|
||||
return Object.values(state.industries).filter((val) => slugs.includes(val.slug)).map((item) => {
|
||||
return item.name
|
||||
})
|
||||
})
|
||||
|
||||
const loadTypesAndIndustries = function() {
|
||||
if (Object.keys(this.industries).length === 0 || Object.keys(this.types).length === 0) {
|
||||
// const files = import.meta.glob('~/data/forms/templates/*.json')
|
||||
// console.log(await files['/data/forms/templates/industries.json']())
|
||||
// this.industries = await files['/data/forms/templates/industries.json']()
|
||||
// this.types = await files['/data/forms/templates/types.json']()
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...contentStore,
|
||||
industries,
|
||||
types,
|
||||
getTemplateTypes,
|
||||
getTemplateIndustries,
|
||||
loadTypesAndIndustries,
|
||||
}
|
||||
})
|
||||
|
||||
export const fetchTemplate = (slug) => {
|
||||
return useOpnApi(templatesEndpoint + '/' + slug)
|
||||
}
|
||||
|
||||
export const fetchAllTemplates = () => {
|
||||
return useOpnApi(templatesEndpoint)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ const storedWorkspaceId = useStorage('currentWorkspace', 0)
|
|||
|
||||
export const useWorkspacesStore = defineStore('workspaces', {
|
||||
state: () => ({
|
||||
content: [],
|
||||
content: new Map,
|
||||
currentId: null,
|
||||
loading: false
|
||||
}),
|
||||
|
@ -70,6 +70,7 @@ export const useWorkspacesStore = defineStore('workspaces', {
|
|||
load() {
|
||||
this.set([])
|
||||
this.startLoading()
|
||||
console.log('loaindgworkspaces')
|
||||
return useOpnApi(workspaceEndpoint).then(({data, error}) => {
|
||||
this.set(data.value)
|
||||
this.stopLoading()
|
||||
|
|
Loading…
Reference in New Issue