Refactoring stores and templates pages to comp. api
This commit is contained in:
parent
3b798c12fd
commit
bb519907f6
|
@ -20,7 +20,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="sm:flex sm:flex-col sm:items-start">
|
<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"
|
<div class="w-14 h-14 rounded-full flex justify-center items-center"
|
||||||
:class="'bg-'+iconColor+'-100 text-'+iconColor+'-600'"
|
:class="'bg-'+iconColor+'-100 text-'+iconColor+'-600'"
|
||||||
>
|
>
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3 text-center sm:mt-0 w-full">
|
<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"
|
class="text-2xl font-semibold text-center text-gray-900"
|
||||||
>
|
>
|
||||||
<slot name="title"/>
|
<slot name="title"/>
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
My Forms
|
My Forms
|
||||||
</NuxtLink>
|
</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"
|
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">
|
<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
|
My Templates
|
||||||
</NuxtLink>
|
</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"
|
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"
|
<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()
|
this.formsStore.resetState()
|
||||||
|
|
||||||
// Redirect to login.
|
// 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: '' }
|
submitButtonClass: { type: String, default: '' }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
isIframe: useIsIframe()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@ -143,11 +149,8 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
isIframe () {
|
|
||||||
return window.location !== window.parent.location || window.frameElement
|
|
||||||
},
|
|
||||||
isEmbedPopup () {
|
isEmbedPopup () {
|
||||||
return window.location.href.includes('popup=true')
|
return process.client && window.location.href.includes('popup=true')
|
||||||
},
|
},
|
||||||
theme () {
|
theme () {
|
||||||
return this.themes[this.themes.hasOwnProperty(this.form.theme) ? this.form.theme : 'default']
|
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'
|
return this.$route.name === 'forms.show_public'
|
||||||
},
|
},
|
||||||
isHideTitle () {
|
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()
|
const workingFormStore = useWorkingFormStore()
|
||||||
return {
|
return {
|
||||||
recordsStore,
|
recordsStore,
|
||||||
workingFormStore
|
workingFormStore,
|
||||||
|
darkModeEnabled: useDark()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -118,7 +119,6 @@ export default {
|
||||||
* Used to force refresh components by changing their keys
|
* Used to force refresh components by changing their keys
|
||||||
*/
|
*/
|
||||||
formVersionId: 1,
|
formVersionId: 1,
|
||||||
darkModeEnabled: document.body.classList.contains('dark'),
|
|
||||||
isAutoSubmit: false,
|
isAutoSubmit: false,
|
||||||
/**
|
/**
|
||||||
* If currently dragging a field
|
* If currently dragging a field
|
||||||
|
@ -259,7 +259,7 @@ export default {
|
||||||
return
|
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.dataForm['h-captcha-response'] = document.getElementsByName('h-captcha-response')[0].value
|
||||||
this.$refs.hcaptcha.reset()
|
this.$refs.hcaptcha.reset()
|
||||||
}
|
}
|
||||||
|
@ -291,6 +291,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scroll to error
|
// Scroll to error
|
||||||
|
if (process.server) return
|
||||||
const elements = document.getElementsByClassName('has-error')
|
const elements = document.getElementsByClassName('has-error')
|
||||||
if (elements.length > 0) {
|
if (elements.length > 0) {
|
||||||
window.scroll({
|
window.scroll({
|
||||||
|
|
|
@ -161,7 +161,7 @@ export default {
|
||||||
if (response.data.message) {
|
if (response.data.message) {
|
||||||
this.alertSuccess(response.data.message)
|
this.alertSuccess(response.data.message)
|
||||||
}
|
}
|
||||||
this.templatesStore.addOrUpdate(response.data.data)
|
this.templatesStore.save(response.data.data)
|
||||||
this.$emit('close')
|
this.$emit('close')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -171,7 +171,7 @@ export default {
|
||||||
if (response.data.message) {
|
if (response.data.message) {
|
||||||
this.alertSuccess(response.data.message)
|
this.alertSuccess(response.data.message)
|
||||||
}
|
}
|
||||||
this.templatesStore.addOrUpdate(response.data.data)
|
this.templatesStore.save(response.data.data)
|
||||||
this.$emit('close')
|
this.$emit('close')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ForgotPasswordModal from '../ForgotPasswordModal.vue'
|
import ForgotPasswordModal from '../ForgotPasswordModal.vue'
|
||||||
|
import {opnFetch} from "~/composables/useOpnApi.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'LoginForm',
|
name: 'LoginForm',
|
||||||
|
@ -78,10 +79,10 @@ export default {
|
||||||
const data = await this.form.post('login')
|
const data = await this.form.post('login')
|
||||||
|
|
||||||
// Save the token.
|
// Save the token.
|
||||||
this.authStore.setToken(data.token, this.remember)
|
this.authStore.setToken(data.token)
|
||||||
|
|
||||||
// Fetch the user.
|
const userData = await opnFetch('user')
|
||||||
await this.authStore.fetchUser()
|
this.authStore.setUser(userData)
|
||||||
|
|
||||||
// Redirect home.
|
// Redirect home.
|
||||||
this.redirect()
|
this.redirect()
|
||||||
|
@ -93,13 +94,14 @@ export default {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const intendedUrl = Cookies.get('intended_url')
|
const intendedUrlCookie = useCookie('intended_url')
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
if (intendedUrl) {
|
if (intendedUrlCookie.value) {
|
||||||
Cookies.remove('intended_url')
|
router.push({ path: intendedUrlCookie.value })
|
||||||
this.$router.push({ path: intendedUrl })
|
useCookie('intended_url').value = null
|
||||||
} else {
|
} 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">
|
<p class="line-clamp-2 mt-2 text-sm font-normal text-gray-600">
|
||||||
{{ cleanQuotes(template.short_description) }}
|
{{ cleanQuotes(template.short_description) }}
|
||||||
</p>
|
</p>
|
||||||
<template-tags :slug="template.slug"
|
<template-tags :template="template"
|
||||||
class="flex mt-4 items-center flex-wrap gap-3"
|
class="flex mt-4 items-center flex-wrap gap-3"
|
||||||
/>
|
/>
|
||||||
<router-link :to="{params:{slug:template.slug},name:'templates-slug'}" title="">
|
<router-link :to="{params:{slug:template.slug},name:'templates-slug'}" title="">
|
||||||
|
@ -46,8 +46,7 @@ export default {
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
template: {
|
template: {
|
||||||
type: Object,
|
type: Object
|
||||||
required: true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,42 +1,42 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="template">
|
<div v-if="template">
|
||||||
<template v-if="displayAll">
|
<!-- <template v-if="displayAll">-->
|
||||||
<span v-if="template.is_new"
|
<!-- <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"
|
<!-- 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"
|
<!-- <svg aria-hidden="true" class="w-3 h-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"-->
|
||||||
fill="currentColor"
|
<!-- fill="currentColor"-->
|
||||||
>
|
<!-- >-->
|
||||||
<path fill-rule="evenodd"
|
<!-- <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"
|
<!-- 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"
|
<!-- clip-rule="evenodd"-->
|
||||||
/>
|
<!-- />-->
|
||||||
</svg>
|
<!-- </svg>-->
|
||||||
New
|
<!-- New-->
|
||||||
</span>
|
<!-- </span>-->
|
||||||
<span v-for="item in types"
|
<!-- <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"
|
<!-- 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 }}
|
<!-- {{ item }}-->
|
||||||
</span>
|
<!-- </span>-->
|
||||||
<span v-for="item in industries"
|
<!-- <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"
|
<!-- 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 }}
|
<!-- {{ item }}-->
|
||||||
</span>
|
<!-- </span>-->
|
||||||
</template>
|
<!-- </template>-->
|
||||||
<template v-else>
|
<!-- <template v-else>-->
|
||||||
<span v-if="types.length > 0"
|
<!-- <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"
|
<!-- 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>
|
<!-- {{ types[0] }} <template v-if="types.length > 1">+{{ types.length - 1 }}</template>-->
|
||||||
</span>
|
<!-- </span>-->
|
||||||
<span v-if="industries.length > 0"
|
<!-- <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"
|
<!-- 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>
|
<!-- {{ industries[0] }} <template v-if="industries.length > 1">+{{ industries.length - 1 }}</template>-->
|
||||||
</span>
|
<!-- </span>-->
|
||||||
</template>
|
<!-- </template>-->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -46,8 +46,8 @@ import { useTemplatesStore } from '../../../stores/templates'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
slug: {
|
template: {
|
||||||
type: String,
|
type: Object,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
displayAll: {
|
displayAll: {
|
||||||
|
@ -66,19 +66,17 @@ export default {
|
||||||
data: () => ({}),
|
data: () => ({}),
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
template () {
|
// template () {
|
||||||
return this.templatesStore.getBySlug(this.slug)
|
// return this.templatesStore.getByKey(this.slug)
|
||||||
},
|
// },
|
||||||
types () {
|
// types () {
|
||||||
if (!this.template) return null
|
// if (!this.template) return null
|
||||||
console.log('template in types',this.template)
|
// return this.templatesStore.getTemplateTypes(this.template.types)
|
||||||
return this.templatesStore.getTemplateTypes(this.template.types)
|
// },
|
||||||
},
|
// industries () {
|
||||||
industries () {
|
// if (!this.template) return null
|
||||||
if (!this.template) return null
|
// return this.templatesStore.getTemplateIndustries(this.template.industries)
|
||||||
console.log('template in types',this.template)
|
// }
|
||||||
return this.templatesStore.getTemplateIndustries(this.template.industries)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {}
|
methods: {}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
</div>
|
</div>
|
||||||
</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"/>
|
<Loader class="h-6 w-6 text-nt-blue mx-auto"/>
|
||||||
</div>
|
</div>
|
||||||
<p v-else-if="enrichedTemplates.length === 0" class="text-center mt-4">
|
<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 Fuse from 'fuse.js'
|
||||||
import SingleTemplate from './SingleTemplate.vue'
|
import SingleTemplate from './SingleTemplate.vue'
|
||||||
|
|
||||||
// const loadTemplates = function (onlyMy) {
|
|
||||||
// const templatesStore = useTemplatesStore()
|
|
||||||
// if(onlyMy){
|
|
||||||
// templatesStore.loadAll({'onlymy':true})
|
|
||||||
// } else {
|
|
||||||
// templatesStore.loadIfEmpty()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TemplatesList',
|
name: 'TemplatesList',
|
||||||
components: {SingleTemplate},
|
components: {SingleTemplate},
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {serialize} from 'object-to-formdata';
|
import {serialize} from 'object-to-formdata';
|
||||||
import Errors from './Errors';
|
import Errors from './Errors';
|
||||||
import cloneDeep from 'clone-deep';
|
import cloneDeep from 'clone-deep';
|
||||||
|
import {opnFetch} from "~/composables/useOpnApi.js";
|
||||||
function hasFiles(data) {
|
function hasFiles(data) {
|
||||||
return data instanceof File ||
|
return data instanceof File ||
|
||||||
data instanceof Blob ||
|
data instanceof Blob ||
|
||||||
|
@ -120,18 +121,14 @@ class Form {
|
||||||
config.transformRequest = [data => serialize(data)];
|
config.transformRequest = [data => serialize(data)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
useOpnApi(config.url, config)
|
opnFetch(config.url, config)
|
||||||
.then(({data, error}) => {
|
.then((data) => {
|
||||||
if (error.value) {
|
|
||||||
this.handleErrors(error);
|
|
||||||
reject(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.finishProcessing();
|
this.finishProcessing();
|
||||||
resolve(data.value);
|
resolve(data);
|
||||||
|
}).catch((error) => {
|
||||||
|
this.handleErrors(error);
|
||||||
|
resolve(error)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -139,8 +136,8 @@ class Form {
|
||||||
handleErrors(error) {
|
handleErrors(error) {
|
||||||
this.busy = false;
|
this.busy = false;
|
||||||
|
|
||||||
if (error.value) {
|
if (error) {
|
||||||
this.errors.set(this.extractErrors(error.value.data));
|
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 = {}) => {
|
export const useOpnApi = (request, opts = {}) => {
|
||||||
return useFetch(request, getOpnRequestsOptions(request, opts))
|
return useFetch(request, getOpnRequestsOptions(request, opts))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import {useWorkspacesStore} from "~/stores/workspaces.js";
|
||||||
|
|
||||||
export default defineNuxtRouteMiddleware(async(to, from) => {
|
export default defineNuxtRouteMiddleware(async(to, from) => {
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
authStore.initStore(useCookie('token').value, useCookie('admin_token').value)
|
authStore.initStore(useCookie('token').value, useCookie('admin_token').value)
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
"js-sha256": "^0.9.0",
|
"js-sha256": "^0.9.0",
|
||||||
"libphonenumber-js": "^1.10.44",
|
"libphonenumber-js": "^1.10.44",
|
||||||
"object-to-formdata": "^4.5.1",
|
"object-to-formdata": "^4.5.1",
|
||||||
|
"pinia": "^2.1.7",
|
||||||
"prismjs": "^1.24.1",
|
"prismjs": "^1.24.1",
|
||||||
"qrcode": "^1.5.1",
|
"qrcode": "^1.5.1",
|
||||||
"query-builder-vue-3": "^1.0.1",
|
"query-builder-vue-3": "^1.0.1",
|
||||||
|
@ -2549,56 +2550,6 @@
|
||||||
"url": "https://github.com/sponsors/posva"
|
"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": {
|
"node_modules/@pkgjs/parseargs": {
|
||||||
"version": "0.11.0",
|
"version": "0.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||||
|
@ -2828,9 +2779,9 @@
|
||||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.1.tgz",
|
||||||
"integrity": "sha512-+1ge/xmaJpm1KVBuIH38Z94zj9fBD+hp+/5WLaHgyY8XLq1ibxk/zj6dTXaqM2cAbYKq8jYlhHd6k05If1W5xA==",
|
"integrity": "sha512-6vMdBZqtq1dVQ4CWdhFwhKZL6E4L1dV6jUjuBvsavvNJSppzi6dLBbuV+3+IyUREaj9ZFvQefnQm28v4OCXlig==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
@ -2840,9 +2791,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm64": {
|
"node_modules/@rollup/rollup-android-arm64": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.1.tgz",
|
||||||
"integrity": "sha512-im6hUEyQ7ZfoZdNvtwgEJvBWZYauC9KVKq1w58LG2Zfz6zMd8gRrbN+xCVoqA2hv/v6fm9lp5LFGJ3za8EQH3A==",
|
"integrity": "sha512-Jto9Fl3YQ9OLsTDWtLFPtaIMSL2kwGyGoVCmPC8Gxvym9TCZm4Sie+cVeblPO66YZsYH8MhBKDMGZ2NDxuk/XQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
@ -2852,9 +2803,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.1.tgz",
|
||||||
"integrity": "sha512-u7aTMskN6Dmg1lCT0QJ+tINRt+ntUrvVkhbPfFz4bCwRZvjItx2nJtwJnJRlKMMaQCHRjrNqHRDYvE4mBm3DlQ==",
|
"integrity": "sha512-LtYcLNM+bhsaKAIGwVkh5IOWhaZhjTfNOkGzGqdHvhiCUVuJDalvDxEdSnhFzAn+g23wgsycmZk1vbnaibZwwA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
@ -2864,9 +2815,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-x64": {
|
"node_modules/@rollup/rollup-darwin-x64": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.1.tgz",
|
||||||
"integrity": "sha512-8FvEl3w2ExmpcOmX5RJD0yqXcVSOqAJJUJ29Lca29Ik+3zPS1yFimr2fr5JSZ4Z5gt8/d7WqycpgkX9nocijSw==",
|
"integrity": "sha512-KyP/byeXu9V+etKO6Lw3E4tW4QdcnzDG/ake031mg42lob5tN+5qfr+lkcT/SGZaH2PdW4Z1NX9GHEkZ8xV7og==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
@ -2876,9 +2827,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.1.tgz",
|
||||||
"integrity": "sha512-lHoKYaRwd4gge+IpqJHCY+8Vc3hhdJfU6ukFnnrJasEBUvVlydP8PuwndbWfGkdgSvZhHfSEw6urrlBj0TSSfg==",
|
"integrity": "sha512-Yqz/Doumf3QTKplwGNrCHe/B2p9xqDghBZSlAY0/hU6ikuDVQuOUIpDP/YcmoT+447tsZTmirmjgG3znvSCR0Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
@ -2888,9 +2839,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.1.tgz",
|
||||||
"integrity": "sha512-JbEPfhndYeWHfOSeh4DOFvNXrj7ls9S/2omijVsao+LBPTPayT1uKcK3dHW3MwDJ7KO11t9m2cVTqXnTKpeaiw==",
|
"integrity": "sha512-u3XkZVvxcvlAOlQJ3UsD1rFvLWqu4Ef/Ggl40WAVCuogf4S1nJPHh5RTgqYFpCOvuGJ7H5yGHabjFKEZGExk5Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
@ -2900,9 +2851,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.1.tgz",
|
||||||
"integrity": "sha512-ahqcSXLlcV2XUBM3/f/C6cRoh7NxYA/W7Yzuv4bDU1YscTFw7ay4LmD7l6OS8EMhTNvcrWGkEettL1Bhjf+B+w==",
|
"integrity": "sha512-0XSYN/rfWShW+i+qjZ0phc6vZ7UWI8XWNz4E/l+6edFt+FxoEghrJHjX1EY/kcUGCnZzYYRCl31SNdfOi450Aw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
@ -2912,9 +2863,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.1.tgz",
|
||||||
"integrity": "sha512-uwvOYNtLw8gVtrExKhdFsYHA/kotURUmZYlinH2VcQxNCQJeJXnkmWgw2hI9Xgzhgu7J9QvWiq9TtTVwWMDa+w==",
|
"integrity": "sha512-LmYIO65oZVfFt9t6cpYkbC4d5lKHLYv5B4CSHRpnANq0VZUQXGcCPXHzbCXCz4RQnx7jvlYB1ISVNCE/omz5cw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
|
@ -2924,9 +2875,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.1.tgz",
|
||||||
"integrity": "sha512-m6pkSwcZZD2LCFHZX/zW2aLIISyzWLU3hrLLzQKMI12+OLEzgruTovAxY5sCZJkipklaZqPy/2bEEBNjp+Y7xg==",
|
"integrity": "sha512-kr8rEPQ6ns/Lmr/hiw8sEVj9aa07gh1/tQF2Y5HrNCCEPiCBGnBUt9tVusrcBBiJfIt1yNaXN6r1CCmpbFEDpg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
@ -2936,9 +2887,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.1.tgz",
|
||||||
"integrity": "sha512-VFAC1RDRSbU3iOF98X42KaVicAfKf0m0OvIu8dbnqhTe26Kh6Ym9JrDulz7Hbk7/9zGc41JkV02g+p3BivOdAg==",
|
"integrity": "sha512-t4QSR7gN+OEZLG0MiCgPqMWZGwmeHhsM4AkegJ0Kiy6TnJ9vZ8dEIwHw1LcZKhbHxTY32hp9eVCMdR3/I8MGRw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
@ -2948,9 +2899,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.1.tgz",
|
||||||
"integrity": "sha512-9jPgMvTKXARz4inw6jezMLA2ihDBvgIU9Ml01hjdVpOcMKyxFBJrn83KVQINnbeqDv0+HdO1c09hgZ8N0s820Q==",
|
"integrity": "sha512-7XI4ZCBN34cb+BH557FJPmh0kmNz2c25SCQeT9OiFWEgf8+dL6ZwJ8f9RnUIit+j01u07Yvrsuu1rZGxJCc51g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
@ -2960,9 +2911,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.1.tgz",
|
||||||
"integrity": "sha512-WE4pT2kTXQN2bAv40Uog0AsV7/s9nT9HBWXAou8+++MBCnY51QS02KYtm6dQxxosKi1VIz/wZIrTQO5UP2EW+Q==",
|
"integrity": "sha512-yE5c2j1lSWOH5jp+Q0qNL3Mdhr8WuqCNVjc6BxbVfS5cAS6zRmdiw7ktb8GNpDCEUJphILY6KACoFoRtKoqNQg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
|
@ -2972,9 +2923,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.1.tgz",
|
||||||
"integrity": "sha512-aPP5Q5AqNGuT0tnuEkK/g4mnt3ZhheiXrDIiSVIHN9mcN21OyXDVbEMqmXPE7e2OplNLDkcvV+ZoGJa2ZImFgw==",
|
"integrity": "sha512-PyJsSsafjmIhVgaI1Zdj7m8BB8mMckFah/xbpplObyHfiXzKcI5UOUXRyOdHW7nz4DpMCuzLnF7v5IWHenCwYA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
@ -3227,9 +3178,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "20.10.4",
|
"version": "20.10.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz",
|
||||||
"integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==",
|
"integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~5.26.4"
|
"undici-types": "~5.26.4"
|
||||||
}
|
}
|
||||||
|
@ -6732,9 +6683,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/libphonenumber-js": {
|
"node_modules/libphonenumber-js": {
|
||||||
"version": "1.10.51",
|
"version": "1.10.52",
|
||||||
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.51.tgz",
|
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.52.tgz",
|
||||||
"integrity": "sha512-vY2I+rQwrDQzoPds0JeTEpeWzbUJgqoV0O4v31PauHBb/e+1KCXKylHcDnBMgJZ9fH9mErsEbROJY3Z3JtqEmg=="
|
"integrity": "sha512-6vCuCHgem+OW1/VCAKgkasfegItCea8zIT7s9/CG/QxdCMIM7GfzbEBG5d7lGO3rzipjt5woOQL3DiHa8Fy78Q=="
|
||||||
},
|
},
|
||||||
"node_modules/lie": {
|
"node_modules/lie": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
|
@ -8195,6 +8146,56 @@
|
||||||
"node": ">=0.10.0"
|
"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": {
|
"node_modules/pirates": {
|
||||||
"version": "4.0.6",
|
"version": "4.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
|
||||||
|
@ -9212,9 +9213,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.1.tgz",
|
||||||
"integrity": "sha512-bUHW/9N21z64gw8s6tP4c88P382Bq/L5uZDowHlHx6s/QWpjJXivIAbEw6LZthgSvlEizZBfLC4OAvWe7aoF7A==",
|
"integrity": "sha512-pgPO9DWzLoW/vIhlSoDByCzcpX92bKEorbgXuZrqxByte3JFk2xSW2JEeAcyLc9Ru9pqcNNW+Ob7ntsk2oT/Xw==",
|
||||||
"bin": {
|
"bin": {
|
||||||
"rollup": "dist/bin/rollup"
|
"rollup": "dist/bin/rollup"
|
||||||
},
|
},
|
||||||
|
@ -9223,19 +9224,19 @@
|
||||||
"npm": ">=8.0.0"
|
"npm": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@rollup/rollup-android-arm-eabi": "4.9.0",
|
"@rollup/rollup-android-arm-eabi": "4.9.1",
|
||||||
"@rollup/rollup-android-arm64": "4.9.0",
|
"@rollup/rollup-android-arm64": "4.9.1",
|
||||||
"@rollup/rollup-darwin-arm64": "4.9.0",
|
"@rollup/rollup-darwin-arm64": "4.9.1",
|
||||||
"@rollup/rollup-darwin-x64": "4.9.0",
|
"@rollup/rollup-darwin-x64": "4.9.1",
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": "4.9.0",
|
"@rollup/rollup-linux-arm-gnueabihf": "4.9.1",
|
||||||
"@rollup/rollup-linux-arm64-gnu": "4.9.0",
|
"@rollup/rollup-linux-arm64-gnu": "4.9.1",
|
||||||
"@rollup/rollup-linux-arm64-musl": "4.9.0",
|
"@rollup/rollup-linux-arm64-musl": "4.9.1",
|
||||||
"@rollup/rollup-linux-riscv64-gnu": "4.9.0",
|
"@rollup/rollup-linux-riscv64-gnu": "4.9.1",
|
||||||
"@rollup/rollup-linux-x64-gnu": "4.9.0",
|
"@rollup/rollup-linux-x64-gnu": "4.9.1",
|
||||||
"@rollup/rollup-linux-x64-musl": "4.9.0",
|
"@rollup/rollup-linux-x64-musl": "4.9.1",
|
||||||
"@rollup/rollup-win32-arm64-msvc": "4.9.0",
|
"@rollup/rollup-win32-arm64-msvc": "4.9.1",
|
||||||
"@rollup/rollup-win32-ia32-msvc": "4.9.0",
|
"@rollup/rollup-win32-ia32-msvc": "4.9.1",
|
||||||
"@rollup/rollup-win32-x64-msvc": "4.9.0",
|
"@rollup/rollup-win32-x64-msvc": "4.9.1",
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
"js-sha256": "^0.9.0",
|
"js-sha256": "^0.9.0",
|
||||||
"libphonenumber-js": "^1.10.44",
|
"libphonenumber-js": "^1.10.44",
|
||||||
"object-to-formdata": "^4.5.1",
|
"object-to-formdata": "^4.5.1",
|
||||||
|
"pinia": "^2.1.7",
|
||||||
"prismjs": "^1.24.1",
|
"prismjs": "^1.24.1",
|
||||||
"qrcode": "^1.5.1",
|
"qrcode": "^1.5.1",
|
||||||
"query-builder-vue-3": "^1.0.1",
|
"query-builder-vue-3": "^1.0.1",
|
||||||
|
|
|
@ -121,7 +121,7 @@ export default {
|
||||||
this.initForm()
|
this.initForm()
|
||||||
this.formInitialHash = this.hashString(JSON.stringify(this.form.data()))
|
this.formInitialHash = this.hashString(JSON.stringify(this.form.data()))
|
||||||
if (this.$route.query.template !== undefined && this.$route.query.template) {
|
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) {
|
if (template && template.structure) {
|
||||||
this.form = new Form({ ...this.form.data(), ...template.structure })
|
this.form = new Form({ ...this.form.data(), ...template.structure })
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ export default {
|
||||||
|
|
||||||
this.initForm()
|
this.initForm()
|
||||||
if (this.$route.query.template !== undefined && this.$route.query.template) {
|
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) {
|
if (template && template.structure) {
|
||||||
this.form = new Form({ ...this.form.data(), ...template.structure })
|
this.form = new Form({ ...this.form.data(), ...template.structure })
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,10 +126,8 @@ const loadForms = function () {
|
||||||
const formsStore = useFormsStore()
|
const formsStore = useFormsStore()
|
||||||
const workspacesStore = useWorkspacesStore()
|
const workspacesStore = useWorkspacesStore()
|
||||||
formsStore.startLoading()
|
formsStore.startLoading()
|
||||||
return workspacesStore.loadIfEmpty().then(() => {
|
workspacesStore.loadIfEmpty().then(() => {
|
||||||
if (process.client) {
|
formsStore.loadIfEmpty(workspacesStore.currentId)
|
||||||
formsStore.loadIfEmpty(workspacesStore.currentId)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col min-h-full">
|
<div class="flex flex-col min-h-full">
|
||||||
<breadcrumb :path="breadcrumbs">
|
<breadcrumb :path="breadcrumbs" v-if="template">
|
||||||
<template #left>
|
<template #left>
|
||||||
<div v-if="canEditTemplate" class="ml-5">
|
<div v-if="canEditTemplate" class="ml-5">
|
||||||
<v-button color="gray" size="small" @click.prevent="showFormTemplateModal=true">
|
<v-button color="gray" size="small" @click.prevent="showFormTemplateModal=true">
|
||||||
Edit Template
|
Edit Template
|
||||||
</v-button>
|
</v-button>
|
||||||
<form-template-modal v-if="form" :form="form" :template="template" :show="showFormTemplateModal"
|
<!-- <form-template-modal v-if="form" :form="form" :template="template" :show="showFormTemplateModal"-->
|
||||||
@close="showFormTemplateModal=false"
|
<!-- @close="showFormTemplateModal=false"-->
|
||||||
/>
|
<!-- />-->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #right>
|
<template #right>
|
||||||
|
@ -25,10 +25,7 @@
|
||||||
</template>
|
</template>
|
||||||
</breadcrumb>
|
</breadcrumb>
|
||||||
|
|
||||||
<div v-if="templatesLoading" class="text-center my-4">
|
<p v-if="template === null || !template" 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">
|
|
||||||
We could not find this template.
|
We could not find this template.
|
||||||
</p>
|
</p>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
@ -48,9 +45,9 @@
|
||||||
<p class="mt-2 text-lg font-normal text-gray-600">
|
<p class="mt-2 text-lg font-normal text-gray-600">
|
||||||
{{ cleanQuotes(template.short_description) }}
|
{{ cleanQuotes(template.short_description) }}
|
||||||
</p>
|
</p>
|
||||||
<template-tags :slug="template.slug" :display-all="true"
|
<!-- <template-tags :slug="template.slug" :display-all="true"-->
|
||||||
class="flex flex-wrap items-center justify-center gap-3 mt-4 md:justify-start"
|
<!-- class="flex flex-wrap items-center justify-center gap-3 mt-4 md:justify-start"-->
|
||||||
/>
|
<!-- />-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -119,7 +116,8 @@
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</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="px-4 mx-auto sm:px-6 lg:px-8 max-w-7xl">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<h4 class="text-xl font-bold tracking-tight text-gray-900 sm:text-2xl">
|
<h4 class="text-xl font-bold tracking-tight text-gray-900 sm:text-2xl">
|
||||||
|
@ -131,7 +129,7 @@
|
||||||
</div>
|
</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">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -196,108 +194,93 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
import Form from 'vform'
|
|
||||||
import {computed} from 'vue'
|
import {computed} from 'vue'
|
||||||
import OpenCompleteForm from '../../components/open/forms/OpenCompleteForm.vue'
|
import OpenCompleteForm from '../../components/open/forms/OpenCompleteForm.vue'
|
||||||
import Breadcrumb from '~/components/global/Breadcrumb.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 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},
|
const route = useRoute()
|
||||||
mixins: [SeoMeta],
|
const slug = computed(() => route.params.slug)
|
||||||
|
|
||||||
setup() {
|
const template = computed(() => templatesStore.getByKey(slug.value))
|
||||||
const authStore = useAuthStore()
|
const form = computed(() => template.value.structure)
|
||||||
const templatesStore = useTemplatesStore()
|
|
||||||
|
|
||||||
const route = useRoute()
|
// Fetch the template
|
||||||
const slug = computed(() => route.params.slug)
|
if (!template.value) {
|
||||||
if (slug) {
|
const {data} = await fetchTemplate(slug.value)
|
||||||
templatesStore.loadTemplate(slug)
|
templatesStore.save(data.value)
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 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>
|
</script>
|
||||||
|
|
||||||
<style lang='scss'>
|
<style lang='scss'>
|
||||||
|
|
|
@ -13,32 +13,28 @@
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<templates-list :templates="templates" :loading="loading" />
|
<templates-list :templates="templates"/>
|
||||||
|
|
||||||
<open-form-footer class="mt-8 border-t"/>
|
<open-form-footer class="mt-8 border-t"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
import SeoMeta from '../../mixins/seo-meta.js'
|
import {fetchAllTemplates} from "~/stores/templates.js";
|
||||||
import {useTemplatesStore} 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: {
|
if (!templatesStore.allLoaded) {
|
||||||
metaTitle: { type: String, default: 'Templates' },
|
templatesStore.startLoading()
|
||||||
metaDescription: { type: String, default: 'Our collection of beautiful templates to create your own forms!' }
|
const {data} = await fetchAllTemplates()
|
||||||
},
|
templatesStore.set(data.value)
|
||||||
|
templatesStore.allLoaded = true
|
||||||
setup() {
|
|
||||||
const templatesStore = useTemplatesStore()
|
|
||||||
templatesStore.loadAll()
|
|
||||||
return {
|
|
||||||
templates: templatesStore.content,
|
|
||||||
loading: templatesStore.loading
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const templates = computed(() => templatesStore.getAll)
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -22,7 +22,7 @@ export const useAuthStore = defineStore('auth', {
|
||||||
stopImpersonating() {
|
stopImpersonating() {
|
||||||
this.token = this.admin_token
|
this.token = this.admin_token
|
||||||
this.admin_token = null
|
this.admin_token = null
|
||||||
this.fetchUser()
|
// TODO: re-fetch user
|
||||||
},
|
},
|
||||||
|
|
||||||
setToken(token) {
|
setToken(token) {
|
||||||
|
@ -79,7 +79,7 @@ export const useAuthStore = defineStore('auth', {
|
||||||
|
|
||||||
async logout() {
|
async logout() {
|
||||||
try {
|
try {
|
||||||
await axios.post('/api/logout')
|
await useOpnApi('logout', {method: 'POST'})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,120 +1,53 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
|
import {useContentStore} from "~/composables/stores/useContentStore.js";
|
||||||
|
|
||||||
export const templatesEndpoint = '/templates'
|
const templatesEndpoint = 'templates'
|
||||||
export const useTemplatesStore = defineStore('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()
|
|
||||||
|
|
||||||
if (this.getBySlug(slug)) {
|
const contentStore = useContentStore('slug')
|
||||||
this.stopLoading()
|
|
||||||
return Promise.resolve()
|
|
||||||
}
|
|
||||||
|
|
||||||
return useOpnApi(templatesEndpoint + '/' + slug).then(({data, error}) => {
|
const allLoaded = ref(false)
|
||||||
this.addOrUpdate(data.value)
|
const industries = ref({})
|
||||||
this.stopLoading()
|
const types = ref({})
|
||||||
}).catch((error) => {
|
|
||||||
this.stopLoading()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
loadAll(options = null) {
|
|
||||||
this.startLoading()
|
|
||||||
this.loadTypesAndIndustries()
|
|
||||||
|
|
||||||
// Prepare with options
|
const getTemplateTypes = computed((state) => (slugs) => {
|
||||||
let queryStr = ''
|
if (state.types.length === 0) return null
|
||||||
if (options !== null) {
|
return Object.values(state.types).filter((val) => slugs.includes(val.slug)).map((item) => {
|
||||||
for (const [key, value] of Object.entries(options)) {
|
return item.name
|
||||||
queryStr += '&' + encodeURIComponent(key) + '=' + encodeURIComponent(value)
|
})
|
||||||
}
|
// todo: use map
|
||||||
queryStr = queryStr.slice(1)
|
})
|
||||||
}
|
const getTemplateIndustries = computed((state) => (slugs) => {
|
||||||
return useOpnApi((queryStr) ? templatesEndpoint + '?' + queryStr : templatesEndpoint).then(({data, error}) => {
|
if (state.industries.length === 0) return null
|
||||||
if (options !== null) {
|
return Object.values(state.industries).filter((val) => slugs.includes(val.slug)).map((item) => {
|
||||||
this.set(data.value)
|
return item.name
|
||||||
this.setAllLoaded(false)
|
})
|
||||||
} else {
|
})
|
||||||
this.append(data.value)
|
|
||||||
this.setAllLoaded(true)
|
const loadTypesAndIndustries = function() {
|
||||||
}
|
if (Object.keys(this.industries).length === 0 || Object.keys(this.types).length === 0) {
|
||||||
this.stopLoading()
|
// const files = import.meta.glob('~/data/forms/templates/*.json')
|
||||||
}).catch((error) => {
|
// console.log(await files['/data/forms/templates/industries.json']())
|
||||||
this.stopLoading()
|
// this.industries = await files['/data/forms/templates/industries.json']()
|
||||||
})
|
// this.types = await files['/data/forms/templates/types.json']()
|
||||||
},
|
|
||||||
loadIfEmpty() {
|
|
||||||
if (!this.allLoaded) {
|
|
||||||
return this.loadAll()
|
|
||||||
}
|
|
||||||
this.stopLoading()
|
|
||||||
return Promise.resolve()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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', {
|
export const useWorkspacesStore = defineStore('workspaces', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
content: [],
|
content: new Map,
|
||||||
currentId: null,
|
currentId: null,
|
||||||
loading: false
|
loading: false
|
||||||
}),
|
}),
|
||||||
|
@ -70,6 +70,7 @@ export const useWorkspacesStore = defineStore('workspaces', {
|
||||||
load() {
|
load() {
|
||||||
this.set([])
|
this.set([])
|
||||||
this.startLoading()
|
this.startLoading()
|
||||||
|
console.log('loaindgworkspaces')
|
||||||
return useOpnApi(workspaceEndpoint).then(({data, error}) => {
|
return useOpnApi(workspaceEndpoint).then(({data, error}) => {
|
||||||
this.set(data.value)
|
this.set(data.value)
|
||||||
this.stopLoading()
|
this.stopLoading()
|
||||||
|
|
Loading…
Reference in New Issue