Stuck at changing routes
This commit is contained in:
@@ -1,41 +0,0 @@
|
||||
<template>
|
||||
<Dropdown v-if="Object.keys(locales).length > 1"
|
||||
dropdown-class="origin-top-right absolute right-0 mt-2 w-20 rounded-md shadow-lg bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5">
|
||||
<template #trigger="{toggle}">
|
||||
<a class="text-gray-300 hover:text-gray-800 dark:hover:text-white px-3 py-2 rounded-md text-sm font-medium" href="#" role="button" @click.prevent="toggle"
|
||||
>
|
||||
{{ locales[locale] }}
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<a v-for="(value, key) in locales" :key="key" class="block block text-center 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 z-10" href="#"
|
||||
@click.prevent="setLocale(key)"
|
||||
>
|
||||
{{ value }}
|
||||
</a>
|
||||
</Dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { loadMessages } from '~/plugins/i18n.js'
|
||||
import Dropdown from './common/Dropdown.vue'
|
||||
|
||||
export default {
|
||||
components: { Dropdown },
|
||||
computed: mapGetters({
|
||||
locale: 'lang/locale',
|
||||
locales: 'lang/locales'
|
||||
}),
|
||||
|
||||
methods: {
|
||||
setLocale (locale) {
|
||||
if (this.$i18n.locale !== locale) {
|
||||
loadMessages(locale)
|
||||
|
||||
this.$store.dispatch('lang/setLocale', { locale })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,11 +1,13 @@
|
||||
<template>
|
||||
<v-button v-if="githubAuth" color="gray" type="button" @click="login">
|
||||
<div class="flex justify-center">
|
||||
{{ $t('login_with') }}
|
||||
Login with
|
||||
<svg class="w-6 h-6 text-white ml-2" xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24">
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
||||
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</v-button>
|
||||
@@ -24,13 +26,13 @@ export default {
|
||||
window.addEventListener('message', this.onMessage, false)
|
||||
},
|
||||
|
||||
beforeDestroy () {
|
||||
beforeUnmount () {
|
||||
window.removeEventListener('message', this.onMessage)
|
||||
},
|
||||
|
||||
methods: {
|
||||
async login () {
|
||||
const newWindow = openWindow('', this.$t('login'))
|
||||
const newWindow = openWindow('', 'Login')
|
||||
|
||||
const url = await this.$store.dispatch('auth/fetchOauthUrl', {
|
||||
provider: 'github'
|
||||
|
||||
@@ -128,7 +128,7 @@ export default {
|
||||
|
||||
document.addEventListener('keydown', closeOnEscape)
|
||||
|
||||
this.$once('hook:destroyed', () => {
|
||||
this.$once('hook:unmounted', () => {
|
||||
document.removeEventListener('keydown', closeOnEscape)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -10,34 +10,37 @@
|
||||
>
|
||||
{{ appName }}</span>
|
||||
</router-link>
|
||||
<workspace-dropdown class="ml-6"/>
|
||||
<workspace-dropdown class="ml-6" />
|
||||
</div>
|
||||
<div v-if="showAuth" class="hidden md:block ml-auto relative">
|
||||
<router-link :to="{name:'templates'}" v-if="$route.name !== 'templates'"
|
||||
class="text-sm text-gray-600 dark:text-white hover:text-gray-800 cursor-pointer mt-1 mr-8">
|
||||
<router-link v-if="$route.name !== 'templates'" :to="{name:'templates'}"
|
||||
class="text-sm text-gray-600 dark:text-white hover:text-gray-800 cursor-pointer mt-1 mr-8"
|
||||
>
|
||||
Templates
|
||||
</router-link>
|
||||
<router-link :to="{name:'aiformbuilder'}" v-if="$route.name !== 'aiformbuilder'"
|
||||
class="text-sm text-gray-600 dark:text-white hidden lg:inline hover:text-gray-800 cursor-pointer mt-1 mr-8">
|
||||
<router-link v-if="$route.name !== 'aiformbuilder'" :to="{name:'aiformbuilder'}"
|
||||
class="text-sm text-gray-600 dark:text-white hidden lg:inline hover:text-gray-800 cursor-pointer mt-1 mr-8"
|
||||
>
|
||||
AI Form Builder
|
||||
</router-link>
|
||||
<router-link :to="{name:'pricing'}" v-if="paidPlansEnabled && (user===null || (user && workspace && !workspace.is_pro)) && $route.name !== 'pricing'"
|
||||
class="text-sm text-gray-600 dark:text-white hover:text-gray-800 cursor-pointer mt-1 mr-8">
|
||||
<router-link v-if="paidPlansEnabled && (user===null || (user && workspace && !workspace.is_pro)) && $route.name !== 'pricing'" :to="{name:'pricing'}"
|
||||
class="text-sm text-gray-600 dark:text-white hover:text-gray-800 cursor-pointer mt-1 mr-8"
|
||||
>
|
||||
<span v-if="user">Upgrade</span>
|
||||
<span v-else>Pricing</span>
|
||||
</router-link>
|
||||
<a href="#" class="text-sm text-gray-600 dark:text-white hover:text-gray-800 cursor-pointer mt-1"
|
||||
@click.prevent="openCrisp" v-if="hasCrisp"
|
||||
<a v-if="hasCrisp" href="#"
|
||||
class="text-sm text-gray-600 dark:text-white hover:text-gray-800 cursor-pointer mt-1" @click.prevent="openCrisp"
|
||||
>
|
||||
Help
|
||||
</a>
|
||||
<a :href="helpUrl" class="text-sm text-gray-600 dark:text-white hover:text-gray-800 cursor-pointer mt-1"
|
||||
target="_blank" v-else
|
||||
<a v-else :href="helpUrl"
|
||||
class="text-sm text-gray-600 dark:text-white hover:text-gray-800 cursor-pointer mt-1" target="_blank"
|
||||
>
|
||||
Help
|
||||
</a>
|
||||
</div>
|
||||
<div v-if="showAuth" class="hidden md:block pl-5 border-gray-300 border-r h-5"></div>
|
||||
<div v-if="showAuth" class="hidden md:block pl-5 border-gray-300 border-r h-5" />
|
||||
<div v-if="showAuth" class="block">
|
||||
<div class="flex items-center">
|
||||
<div class="ml-3 mr-4 relative">
|
||||
@@ -90,7 +93,7 @@
|
||||
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
</svg>
|
||||
{{ $t('settings') }}
|
||||
Settings
|
||||
</router-link>
|
||||
|
||||
<a href="#"
|
||||
@@ -104,21 +107,20 @@
|
||||
d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"
|
||||
/>
|
||||
</svg>
|
||||
{{ $t('logout') }}
|
||||
Logout
|
||||
</a>
|
||||
</dropdown>
|
||||
<div class="flex gap-2" v-else>
|
||||
<div v-else class="flex gap-2">
|
||||
<router-link v-if="$route.name !== 'login'" :to="{ name: 'login' }"
|
||||
class="text-gray-600 dark:text-white hover:text-gray-800 dark:hover:text-white px-0 sm:px-3 py-2 rounded-md text-sm"
|
||||
active-class="text-gray-800 dark:text-white"
|
||||
>
|
||||
{{ $t('login') }}
|
||||
Login
|
||||
</router-link>
|
||||
|
||||
<v-button size="small" :to="{ name: 'forms.create.guest' }" color="outline-blue" v-track.nav_create_form_click :arrow="true">
|
||||
<v-button v-track.nav_create_form_click size="small" :to="{ name: 'forms.create.guest' }" color="outline-blue" :arrow="true">
|
||||
Create a form
|
||||
</v-button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -130,7 +132,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters} from 'vuex'
|
||||
import { mapGetters } from 'vuex'
|
||||
import Dropdown from './common/Dropdown.vue'
|
||||
import WorkspaceDropdown from './WorkspaceDropdown.vue'
|
||||
|
||||
@@ -141,13 +143,13 @@ export default {
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
appName: window.config.appName,
|
||||
appName: window.config.appName
|
||||
}),
|
||||
|
||||
computed: {
|
||||
githubUrl: () => window.config.links.github_url,
|
||||
helpUrl: () => window.config.links.help_url,
|
||||
form() {
|
||||
form () {
|
||||
if (this.$route.name && this.$route.name.startsWith('forms.show_public')) {
|
||||
return this.$store.getters['open/forms/getBySlug'](this.$route.params.slug)
|
||||
}
|
||||
@@ -156,13 +158,13 @@ export default {
|
||||
workspace () {
|
||||
return this.$store.getters['open/workspaces/getCurrent']()
|
||||
},
|
||||
paidPlansEnabled() {
|
||||
paidPlansEnabled () {
|
||||
return window.config.paid_plans_enabled
|
||||
},
|
||||
showAuth() {
|
||||
showAuth () {
|
||||
return this.$route.name && !this.$route.name.startsWith('forms.show_public')
|
||||
},
|
||||
hasNavbar() {
|
||||
hasNavbar () {
|
||||
if (this.isIframe) return false
|
||||
|
||||
if (this.$route.name && this.$route.name.startsWith('forms.show_public')) {
|
||||
@@ -177,22 +179,22 @@ export default {
|
||||
}
|
||||
return !this.$root.navbarHidden
|
||||
},
|
||||
isIframe() {
|
||||
isIframe () {
|
||||
return window.location !== window.parent.location || window.frameElement
|
||||
},
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
}),
|
||||
userOnboarded() {
|
||||
userOnboarded () {
|
||||
return this.user && this.user.workspaces_count > 0
|
||||
},
|
||||
hasCrisp() {
|
||||
hasCrisp () {
|
||||
return window.config.crisp_website_id
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
async logout() {
|
||||
async logout () {
|
||||
// Log out the user.
|
||||
await this.$store.dispatch('auth/logout')
|
||||
|
||||
@@ -201,7 +203,7 @@ export default {
|
||||
this.$store.dispatch('open/forms/resetState')
|
||||
|
||||
// Redirect to login.
|
||||
this.$router.push({name: 'login'})
|
||||
this.$router.push({ name: 'login' })
|
||||
},
|
||||
openCrisp () {
|
||||
window.$crisp.push(['do', 'chat:show'])
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
<template>
|
||||
<transition enter-active-class="linear duration-500 overflow-hidden"
|
||||
enter-from-class="max-h-0 opacity-0"
|
||||
enter-to-class="max-h-screen opacity-100"
|
||||
leave-active-class="linear duration-500 overflow-hidden"
|
||||
leave-from-class="max-h-screen opacity-100"
|
||||
leave-to-class="max-h-0 opacity-0"
|
||||
>
|
||||
<div :class="alertClasses" class="border shadow-sm p-2 flex items-center rounded-md">
|
||||
<div class="flex-grow">
|
||||
<p class="mb-0 py-2 px-4" :class="textClasses" v-html="message" />
|
||||
</div>
|
||||
|
||||
<div class="justify-end">
|
||||
<v-button v-if="type == 'error'" color="red" shade="light" @click="close">
|
||||
Close
|
||||
</v-button>
|
||||
<v-button v-if="type == 'success'" color="green" shade="light" @click="close">
|
||||
OK
|
||||
</v-button>
|
||||
<v-button v-if="type == 'warning'" color="yellow" shade="light" @click="close">
|
||||
OK
|
||||
</v-button>
|
||||
<v-button v-if="type == 'confirmation'" class="mr-1 mb-1" @click="confirm">
|
||||
Yes
|
||||
</v-button>
|
||||
<v-button v-if="type == 'confirmation'" color="gray" shade="light" @click="cancel">
|
||||
No, cancel
|
||||
</v-button>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Alert',
|
||||
props: ['type', 'message', 'autoClose', 'confirmationProceed', 'confirmationCancel'],
|
||||
|
||||
data () {
|
||||
return {
|
||||
timeout: null
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
alertClasses () {
|
||||
if (this.type === 'error') return 'bg-red-100 border-red-500'
|
||||
if (this.type === 'success') return 'bg-green-100 border-green-500'
|
||||
if (this.type === 'warning') return 'bg-yellow-100 border-yellow-500'
|
||||
return 'bg-blue-50 border-nt-blue-light'
|
||||
},
|
||||
textClasses () {
|
||||
if (this.type === 'error') return 'text-red-600'
|
||||
if (this.type === 'success') return 'text-green-600'
|
||||
if (this.type === 'warning') return 'text-yellow-600'
|
||||
return 'text-nt-blue'
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
if (this.autoClose) {
|
||||
this.timeout = setTimeout(() => {
|
||||
this.close()
|
||||
}, this.autoClose)
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Close the modal.
|
||||
*/
|
||||
close () {
|
||||
clearTimeout(this.timeout)
|
||||
this.$emit('close')
|
||||
},
|
||||
/**
|
||||
* Confirm and close the modal.
|
||||
*/
|
||||
confirm () {
|
||||
this.confirmationProceed()
|
||||
this.close()
|
||||
},
|
||||
/**
|
||||
* Cancel and close the modal.
|
||||
*/
|
||||
cancel () {
|
||||
if (this.confirmationCancel) {
|
||||
this.confirmationCancel()
|
||||
}
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -60,19 +60,19 @@ export default {
|
||||
const scrollContainerObserver = newResizeObserver(this.toggleShadow)
|
||||
if (scrollContainerObserver) {
|
||||
scrollContainerObserver.observe(this.$refs.scrollContainer)
|
||||
// Cleanup when the component is destroyed.
|
||||
this.$once('hook:destroyed', () => scrollContainerObserver.disconnect())
|
||||
// Cleanup when the component is unmounted.
|
||||
this.$once('hook:unmounted', () => scrollContainerObserver.disconnect())
|
||||
}
|
||||
|
||||
// Recalculate the container dimensions when the wrapper is resized.
|
||||
const wrapObserver = newResizeObserver(this.calcDimensions)
|
||||
if (wrapObserver) {
|
||||
wrapObserver.observe(this.$el)
|
||||
// Cleanup when the component is destroyed.
|
||||
this.$once('hook:destroyed', () => wrapObserver.disconnect())
|
||||
// Cleanup when the component is unmounted.
|
||||
this.$once('hook:unmounted', () => wrapObserver.disconnect())
|
||||
}
|
||||
},
|
||||
destroyed () {
|
||||
unmounted () {
|
||||
window.removeEventListener('resize', this.calcDimensions)
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -55,21 +55,21 @@
|
||||
Please create this form on a device with a larger screen. That will allow you to preview your form changes.
|
||||
</div>
|
||||
|
||||
<form-information/>
|
||||
<form-structure/>
|
||||
<form-customization/>
|
||||
<form-about-submission/>
|
||||
<form-notifications/>
|
||||
<form-security-privacy/>
|
||||
<form-information />
|
||||
<form-structure />
|
||||
<form-customization />
|
||||
<form-about-submission />
|
||||
<form-notifications />
|
||||
<form-security-privacy />
|
||||
<form-custom-seo />
|
||||
<form-custom-code/>
|
||||
<form-integrations/>
|
||||
<form-custom-code />
|
||||
<form-integrations />
|
||||
</div>
|
||||
|
||||
<form-editor-preview/>
|
||||
<form-editor-preview />
|
||||
|
||||
<form-field-edit-sidebar/>
|
||||
<add-form-block-sidebar/>
|
||||
<form-field-edit-sidebar />
|
||||
<add-form-block-sidebar />
|
||||
|
||||
<!-- Form Error Modal -->
|
||||
<form-error-modal
|
||||
@@ -80,12 +80,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex justify-center items-center">
|
||||
<loader class="w-6 h-6"/>
|
||||
<loader class="w-6 h-6" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters} from 'vuex'
|
||||
import { mapGetters } from 'vuex'
|
||||
import AddFormBlockSidebar from './form-components/AddFormBlockSidebar.vue'
|
||||
import FormFieldEditSidebar from '../fields/FormFieldEditSidebar.vue'
|
||||
import FormErrorModal from './form-components/FormErrorModal.vue'
|
||||
@@ -143,7 +143,7 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
data () {
|
||||
return {
|
||||
showFormErrorModal: false,
|
||||
validationErrorResponse: null,
|
||||
@@ -157,21 +157,21 @@ export default {
|
||||
user: 'auth/user'
|
||||
}),
|
||||
form: {
|
||||
get() {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
},
|
||||
/* We add a setter */
|
||||
set(value) {
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
}
|
||||
},
|
||||
createdForm() {
|
||||
createdForm () {
|
||||
return this.$store.getters['open/forms/getById'](this.createdFormId)
|
||||
},
|
||||
workspace() {
|
||||
workspace () {
|
||||
return this.$store.getters['open/workspaces/getCurrent']()
|
||||
},
|
||||
steps() {
|
||||
steps () {
|
||||
return [
|
||||
{
|
||||
target: '#v-step-0',
|
||||
@@ -211,12 +211,12 @@ export default {
|
||||
|
||||
watch: {},
|
||||
|
||||
mounted() {
|
||||
mounted () {
|
||||
this.$emit('mounted')
|
||||
this.$root.hideNavbar()
|
||||
},
|
||||
|
||||
beforeDestroy () {
|
||||
beforeUnmount () {
|
||||
this.$root.hideNavbar(false)
|
||||
},
|
||||
|
||||
@@ -225,12 +225,12 @@ export default {
|
||||
window.$crisp.push(['do', 'chat:show'])
|
||||
window.$crisp.push(['do', 'chat:open'])
|
||||
},
|
||||
showValidationErrors() {
|
||||
showValidationErrors () {
|
||||
this.showFormErrorModal = true
|
||||
},
|
||||
saveForm() {
|
||||
saveForm () {
|
||||
this.form.properties = this.validateFieldsLogic(this.form.properties)
|
||||
if(this.isGuest) {
|
||||
if (this.isGuest) {
|
||||
this.saveFormGuest()
|
||||
} else if (this.isEdit) {
|
||||
this.saveFormEdit()
|
||||
@@ -238,7 +238,7 @@ export default {
|
||||
this.saveFormCreate()
|
||||
}
|
||||
},
|
||||
saveFormEdit() {
|
||||
saveFormEdit () {
|
||||
if (this.updateFormLoading) return
|
||||
|
||||
this.updateFormLoading = true
|
||||
@@ -247,8 +247,8 @@ export default {
|
||||
const data = response.data
|
||||
this.$store.commit('open/forms/addOrUpdate', data.form)
|
||||
this.$emit('on-save')
|
||||
this.$router.push({name: 'forms.show', params: {slug: this.form.slug}})
|
||||
this.$logEvent('form_saved', {form_id: this.form.id, form_slug: this.form.slug})
|
||||
this.$router.push({ name: 'forms.show', params: { slug: this.form.slug } })
|
||||
this.$logEvent('form_saved', { form_id: this.form.id, form_slug: this.form.slug })
|
||||
this.displayFormModificationAlert(data)
|
||||
}).catch((error) => {
|
||||
if (error.response.status === 422) {
|
||||
@@ -259,7 +259,7 @@ export default {
|
||||
this.updateFormLoading = false
|
||||
})
|
||||
},
|
||||
saveFormCreate() {
|
||||
saveFormCreate () {
|
||||
if (this.updateFormLoading) return
|
||||
this.form.workspace_id = this.workspace.id
|
||||
this.validationErrorResponse = null
|
||||
@@ -270,7 +270,7 @@ export default {
|
||||
this.$emit('on-save')
|
||||
this.createdFormId = response.data.form.id
|
||||
|
||||
this.$logEvent('form_created', {form_id: response.data.form.id, form_slug: response.data.form.slug})
|
||||
this.$logEvent('form_created', { form_id: response.data.form.id, form_slug: response.data.form.slug })
|
||||
this.$crisp.push(['set', 'session:event', [[['form_created', {
|
||||
form_id: response.data.form.id,
|
||||
form_slug: response.data.form.slug
|
||||
@@ -292,7 +292,7 @@ export default {
|
||||
this.updateFormLoading = false
|
||||
})
|
||||
},
|
||||
saveFormGuest() {
|
||||
saveFormGuest () {
|
||||
this.$emit('openRegister')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,71 +7,72 @@
|
||||
:class="{'absolute': data.length !== 0}"
|
||||
style="will-change: transform; transform: translate3d(0px, 0px, 0px)"
|
||||
>
|
||||
<tr class="n-table-row overflow-x-hidden">
|
||||
<resizable-th v-for="col, index in form.properties" :id="'table-head-cell-' + col.id" :key="col.id"
|
||||
scope="col" :allow-resize="allowResize" :width="(col.cell_width ? col.cell_width + 'px':'auto')"
|
||||
class="n-table-cell p-0 relative"
|
||||
@resize-width="resizeCol(col, $event)"
|
||||
>
|
||||
<p
|
||||
:class="{'border-r': index < form.properties.length - 1 || hasActions}"
|
||||
class="bg-gray-50 dark:bg-notion-dark truncate sticky top-0 border-b border-gray-200 dark:border-gray-800 px-4 py-2 text-gray-500 font-semibold tracking-wider uppercase text-xs"
|
||||
<tr class="n-table-row overflow-x-hidden">
|
||||
<resizable-th v-for="col, index in form.properties" :id="'table-head-cell-' + col.id" :key="col.id"
|
||||
scope="col" :allow-resize="allowResize" :width="(col.cell_width ? col.cell_width + 'px':'auto')"
|
||||
class="n-table-cell p-0 relative"
|
||||
@resize-width="resizeCol(col, $event)"
|
||||
>
|
||||
{{ col.name }}
|
||||
</p>
|
||||
</resizable-th>
|
||||
<th v-if="hasActions" class="n-table-cell p-0 relative" style="width: 100px">
|
||||
<p
|
||||
class="bg-gray-50 dark:bg-notion-dark truncate sticky top-0 border-b border-gray-200 dark:border-gray-800 px-4 py-2 text-gray-500 font-semibold tracking-wider uppercase text-xs">
|
||||
Actions
|
||||
</p>
|
||||
</th>
|
||||
</tr>
|
||||
<p
|
||||
:class="{'border-r': index < form.properties.length - 1 || hasActions}"
|
||||
class="bg-gray-50 dark:bg-notion-dark truncate sticky top-0 border-b border-gray-200 dark:border-gray-800 px-4 py-2 text-gray-500 font-semibold tracking-wider uppercase text-xs"
|
||||
>
|
||||
{{ col.name }}
|
||||
</p>
|
||||
</resizable-th>
|
||||
<th v-if="hasActions" class="n-table-cell p-0 relative" style="width: 100px">
|
||||
<p
|
||||
class="bg-gray-50 dark:bg-notion-dark truncate sticky top-0 border-b border-gray-200 dark:border-gray-800 px-4 py-2 text-gray-500 font-semibold tracking-wider uppercase text-xs"
|
||||
>
|
||||
Actions
|
||||
</p>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody v-if="data.length > 0" class="n-table-body bg-white dark:bg-notion-dark-light">
|
||||
<tr v-if="$slots.hasOwnProperty('actions')"
|
||||
:id="'table-actions-'+tableHash"
|
||||
ref="actions-row"
|
||||
class="action-row absolute w-full"
|
||||
style="will-change: transform; transform: translate3d(0px, 32px, 0px)"
|
||||
>
|
||||
<td :colspan="form.properties.length" class="p-1">
|
||||
<slot name="actions"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-for="row, index in data" :key="index" class="n-table-row" :class="{'first':index===0}">
|
||||
<td v-for="col, colIndex in form.properties"
|
||||
:key="col.id"
|
||||
:style="{width: col.cell_width + 'px'}"
|
||||
class="n-table-cell border-gray-100 dark:border-gray-900 text-sm p-2 overflow-hidden"
|
||||
:class="[{'border-b': index !== data.length - 1, 'border-r': colIndex !== form.properties.length - 1 || hasActions},
|
||||
<tr v-if="$slots.hasOwnProperty('actions')"
|
||||
:id="'table-actions-'+tableHash"
|
||||
ref="actions-row"
|
||||
class="action-row absolute w-full"
|
||||
style="will-change: transform; transform: translate3d(0px, 32px, 0px)"
|
||||
>
|
||||
<td :colspan="form.properties.length" class="p-1">
|
||||
<slot name="actions" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-for="row, index in data" :key="index" class="n-table-row" :class="{'first':index===0}">
|
||||
<td v-for="col, colIndex in form.properties"
|
||||
:key="col.id"
|
||||
:style="{width: col.cell_width + 'px'}"
|
||||
class="n-table-cell border-gray-100 dark:border-gray-900 text-sm p-2 overflow-hidden"
|
||||
:class="[{'border-b': index !== data.length - 1, 'border-r': colIndex !== form.properties.length - 1 || hasActions},
|
||||
colClasses(col)]"
|
||||
>
|
||||
<component :is="fieldComponents[col.type]" class="border-gray-100 dark:border-gray-900"
|
||||
:property="col" :value="row[col.id]"
|
||||
/>
|
||||
</td>
|
||||
<td v-if="hasActions" class="n-table-cell border-gray-100 dark:border-gray-900 text-sm p-2 border-b"
|
||||
style="width: 100px"
|
||||
>
|
||||
<record-operations :form="form" :structure="form.properties" :rowid="row.id" @deleted="$emit('deleted')" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="loading" class="n-table-row border-t bg-gray-50 dark:bg-gray-900">
|
||||
<td :colspan="form.properties.length" class="p-8 w-full">
|
||||
<loader class="w-4 h-4 mx-auto"/>
|
||||
</td>
|
||||
</tr>
|
||||
>
|
||||
<component :is="fieldComponents[col.type]" class="border-gray-100 dark:border-gray-900"
|
||||
:property="col" :value="row[col.id]"
|
||||
/>
|
||||
</td>
|
||||
<td v-if="hasActions" class="n-table-cell border-gray-100 dark:border-gray-900 text-sm p-2 border-b"
|
||||
style="width: 100px"
|
||||
>
|
||||
<record-operations :form="form" :structure="form.properties" :rowid="row.id" @deleted="$emit('deleted')" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="loading" class="n-table-row border-t bg-gray-50 dark:bg-gray-900">
|
||||
<td :colspan="form.properties.length" class="p-8 w-full">
|
||||
<loader class="w-4 h-4 mx-auto" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody v-else key="body-content" class="n-table-body">
|
||||
<tr class="n-table-row loader w-full">
|
||||
<td :colspan="form.properties.length" class="n-table-cell w-full p-8">
|
||||
<loader v-if="loading" class="w-4 h-4 mx-auto"/>
|
||||
<p v-else class="text-gray-500 text-center">
|
||||
No data found.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="n-table-row loader w-full">
|
||||
<td :colspan="form.properties.length" class="n-table-cell w-full p-8">
|
||||
<loader v-if="loading" class="w-4 h-4 mx-auto" />
|
||||
<p v-else class="text-gray-500 text-center">
|
||||
No data found.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
@@ -101,7 +102,7 @@ const cyrb53 = function (str, seed = 0) {
|
||||
}
|
||||
|
||||
export default {
|
||||
components: {ResizableTh, RecordOperations},
|
||||
components: { ResizableTh, RecordOperations },
|
||||
props: {
|
||||
data: {
|
||||
type: Array,
|
||||
@@ -115,10 +116,10 @@ export default {
|
||||
required: false,
|
||||
default: true,
|
||||
type: Boolean
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
data () {
|
||||
return {
|
||||
tableHash: null,
|
||||
skip: false
|
||||
@@ -127,18 +128,18 @@ export default {
|
||||
|
||||
computed: {
|
||||
form: {
|
||||
get() {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
},
|
||||
set(value) {
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
}
|
||||
},
|
||||
hasActions() {
|
||||
hasActions () {
|
||||
// In future if want to hide based on condition
|
||||
return true
|
||||
},
|
||||
fieldComponents() {
|
||||
fieldComponents () {
|
||||
return {
|
||||
text: OpenText,
|
||||
number: OpenText,
|
||||
@@ -150,35 +151,35 @@ export default {
|
||||
url: OpenUrl,
|
||||
email: OpenText,
|
||||
phone_number: OpenText,
|
||||
signature: OpenFile,
|
||||
signature: OpenFile
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
'form.properties': {
|
||||
handler() {
|
||||
handler () {
|
||||
this.onStructureChange()
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
data() {
|
||||
data () {
|
||||
this.$nextTick(() => {
|
||||
this.handleScroll()
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
mounted () {
|
||||
const parent = document.getElementById('table-page')
|
||||
this.tableHash = cyrb53(JSON.stringify(this.form.properties))
|
||||
parent.addEventListener('scroll', this.handleScroll, {passive: true})
|
||||
parent.addEventListener('scroll', this.handleScroll, { passive: true })
|
||||
window.addEventListener('resize', this.handleScroll)
|
||||
this.onStructureChange()
|
||||
this.handleScroll()
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
beforeUnmount () {
|
||||
const parent = document.getElementById('table-page')
|
||||
if (parent) {
|
||||
parent.removeEventListener('scroll', this.handleScroll)
|
||||
@@ -187,7 +188,7 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
colClasses(col) {
|
||||
colClasses (col) {
|
||||
let colAlign, colColor, colFontWeight, colWrap
|
||||
|
||||
// Column align
|
||||
@@ -212,7 +213,7 @@ export default {
|
||||
|
||||
return [colAlign, colColor, colWrap, colFontWeight]
|
||||
},
|
||||
onStructureChange() {
|
||||
onStructureChange () {
|
||||
if (this.form && this.form.properties) {
|
||||
this.$nextTick(() => {
|
||||
this.form.properties.forEach(col => {
|
||||
@@ -226,7 +227,7 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
resizeCol(col, width) {
|
||||
resizeCol (col, width) {
|
||||
if (!this.form) return
|
||||
const columns = clonedeep(this.form.properties)
|
||||
const index = this.form.properties.findIndex(c => c.id === col.id)
|
||||
@@ -236,7 +237,7 @@ export default {
|
||||
this.$emit('resize')
|
||||
})
|
||||
},
|
||||
handleScroll() {
|
||||
handleScroll () {
|
||||
const parent = document.getElementById('table-page')
|
||||
const posTop = parent.getBoundingClientRect().top
|
||||
const tablePosition = Math.max(0, posTop - this.$refs.table.getBoundingClientRect().top)
|
||||
@@ -264,7 +265,7 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user