Vue3: migrating from vuex to Pinia (#249)
* Vue3: migrating from vuex to Pinia * toggle input fixes * update configureCompat --------- Co-authored-by: Forms Dev <chirag+new@notionforms.io>
This commit is contained in:
parent
af30067eda
commit
47653ebe64
File diff suppressed because it is too large
Load Diff
|
@ -21,6 +21,7 @@
|
|||
"js-cookie": "^2.2.1",
|
||||
"js-sha256": "^0.9.0",
|
||||
"libphonenumber-js": "^1.10.44",
|
||||
"pinia": "^2.1.7",
|
||||
"prismjs": "^1.24.1",
|
||||
"qrcode": "^1.5.1",
|
||||
"query-builder-vue": "^1.2.0",
|
||||
|
@ -38,8 +39,7 @@
|
|||
"vue-signature-pad": "^3.0.2",
|
||||
"vue3-editor": "^0.1.1",
|
||||
"vue3-vt-notifications": "^1.0.0",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"vuex": "^4.1.0"
|
||||
"vuedraggable": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.12",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { createApp, configureCompat, ref } from 'vue'
|
||||
import store from '~/store'
|
||||
import { createPinia } from 'pinia'
|
||||
import router from '~/router'
|
||||
import App from '~/components/App.vue'
|
||||
import Base from './base.js'
|
||||
|
@ -11,9 +11,10 @@ import '~/components'
|
|||
|
||||
import '../sass/app.scss'
|
||||
|
||||
const pinia = createPinia()
|
||||
const app = createApp(App)
|
||||
.use(router)
|
||||
.use(store)
|
||||
.use(pinia)
|
||||
.mixin(Base)
|
||||
|
||||
registerPlugin(app)
|
||||
|
@ -25,7 +26,9 @@ configureCompat({
|
|||
// GLOBAL_MOUNT: false,
|
||||
COMPONENT_V_MODEL: false,
|
||||
INSTANCE_SET: false,
|
||||
INSTANCE_DELETE: false
|
||||
INSTANCE_DELETE: false,
|
||||
ATTR_FALSE_VALUE: false,
|
||||
WATCH_ARRAY: false
|
||||
})
|
||||
|
||||
router.app = app
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from 'vue'
|
||||
import { useAppStore } from '../stores/app'
|
||||
import Loading from './Loading.vue'
|
||||
import Hotjar from './service/Hotjar.vue'
|
||||
import Amplitude from './service/Amplitude.vue'
|
||||
|
@ -44,7 +46,6 @@ import Crisp from './service/Crisp.vue'
|
|||
import StopImpersonation from './pages/StopImpersonation.vue'
|
||||
import Notifications from './common/Notifications.vue'
|
||||
import SeoMeta from '../mixins/seo-meta.js'
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
// Load layout components dynamically.
|
||||
const requireContext = import.meta.glob('../layouts/**.vue', { eager: true })
|
||||
|
@ -74,6 +75,13 @@ export default {
|
|||
|
||||
mixins: [SeoMeta],
|
||||
|
||||
setup () {
|
||||
const appStore = useAppStore()
|
||||
return {
|
||||
layout : computed(() => appStore.layout)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
metaTitle: 'OpnForm',
|
||||
metaDescription: 'Create beautiful forms for free. Unlimited fields, unlimited submissions. It\'s free and it takes less than 1 minute to create your first form.',
|
||||
|
@ -95,9 +103,6 @@ export default {
|
|||
isOnboardingPage () {
|
||||
return this.$route.name === 'onboarding'
|
||||
},
|
||||
...mapState({
|
||||
layout: state => state.app.layout
|
||||
}),
|
||||
layoutComponent () {
|
||||
return layouts[this.layout]
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
<script>
|
||||
// https://github.com/nuxt/nuxt.js/blob/master/lib/app/components/nuxt-loading.vue
|
||||
import { mapState } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAppStore } from '../stores/app';
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
|
@ -19,12 +20,13 @@ export default {
|
|||
failedColor: 'red'
|
||||
}),
|
||||
|
||||
computed: {
|
||||
...mapState({
|
||||
percent: state => state.app.loader.percent,
|
||||
canSuccess: state => state.app.loader.canSuccess,
|
||||
show: state => state.app.loader.show
|
||||
})
|
||||
setup () {
|
||||
const appStore = useAppStore()
|
||||
return {
|
||||
percent : computed(() => appStore.loader.percent),
|
||||
canSuccess : computed(() => appStore.loader.canSuccess),
|
||||
show : computed(() => appStore.loader.show)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -14,9 +14,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
|
||||
export default {
|
||||
name: 'LoginWithGithub',
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
authStore
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
githubAuth: () => window.config.githubAuth,
|
||||
url: () => '/api/oauth/github'
|
||||
|
@ -34,9 +43,7 @@ export default {
|
|||
async login () {
|
||||
const newWindow = openWindow('', 'Login')
|
||||
|
||||
const url = await this.$store.dispatch('auth/fetchOauthUrl', {
|
||||
provider: 'github'
|
||||
})
|
||||
const url = await this.authStore.fetchOauthUrl('github')
|
||||
|
||||
newWindow.location.href = url
|
||||
},
|
||||
|
@ -49,9 +56,7 @@ export default {
|
|||
return
|
||||
}
|
||||
|
||||
this.$store.dispatch('auth/saveToken', {
|
||||
token: e.data.token
|
||||
})
|
||||
this.authStore.saveToken(e.data.token)
|
||||
|
||||
this.$router.push({ name: 'home' })
|
||||
}
|
||||
|
|
|
@ -132,7 +132,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../stores/auth';
|
||||
import { useFormsStore } from '../stores/forms';
|
||||
import { useWorkspacesStore } from '../stores/workspaces';
|
||||
import Dropdown from './common/Dropdown.vue'
|
||||
import WorkspaceDropdown from './WorkspaceDropdown.vue'
|
||||
|
||||
|
@ -142,6 +145,18 @@ export default {
|
|||
Dropdown
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const formsStore = useFormsStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
return {
|
||||
authStore,
|
||||
formsStore,
|
||||
workspacesStore,
|
||||
user : computed(() => authStore.user)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
appName: window.config.appName
|
||||
}),
|
||||
|
@ -151,12 +166,12 @@ export default {
|
|||
helpUrl: () => window.config.links.help_url,
|
||||
form () {
|
||||
if (this.$route.name && this.$route.name.startsWith('forms.show_public')) {
|
||||
return this.$store.getters['open/forms/getBySlug'](this.$route.params.slug)
|
||||
return this.formsStore.getBySlug(this.$route.params.slug)
|
||||
}
|
||||
return null
|
||||
},
|
||||
workspace () {
|
||||
return this.$store.getters['open/workspaces/getCurrent']()
|
||||
return this.workspacesStore.getCurrent()
|
||||
},
|
||||
paidPlansEnabled () {
|
||||
return window.config.paid_plans_enabled
|
||||
|
@ -182,9 +197,6 @@ export default {
|
|||
isIframe () {
|
||||
return window.location !== window.parent.location || window.frameElement
|
||||
},
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
}),
|
||||
userOnboarded () {
|
||||
return this.user && this.user.workspaces_count > 0
|
||||
},
|
||||
|
@ -196,11 +208,11 @@ export default {
|
|||
methods: {
|
||||
async logout () {
|
||||
// Log out the user.
|
||||
await this.$store.dispatch('auth/logout')
|
||||
await this.authStore.logout()
|
||||
|
||||
// Reset store
|
||||
this.$store.dispatch('open/workspaces/resetState')
|
||||
this.$store.dispatch('open/forms/resetState')
|
||||
this.workspacesStore.resetState()
|
||||
this.formsStore.resetState()
|
||||
|
||||
// Redirect to login.
|
||||
this.$router.push({ name: 'login' })
|
||||
|
|
|
@ -41,8 +41,11 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
import { useFormsStore } from '../stores/forms'
|
||||
import { useWorkspacesStore } from '../stores/workspaces'
|
||||
import Dropdown from './common/Dropdown.vue'
|
||||
import { mapGetters, mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
|
||||
|
@ -51,20 +54,26 @@ export default {
|
|||
Dropdown
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const formsStore = useFormsStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
return {
|
||||
formsStore,
|
||||
workspacesStore,
|
||||
user : computed(() => authStore.user),
|
||||
workspaces : computed(() => workspacesStore.content),
|
||||
loading : computed(() => workspacesStore.loading)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
appName: window.config.appName
|
||||
}),
|
||||
|
||||
computed: {
|
||||
...mapState({
|
||||
workspaces: state => state['open/workspaces'].content,
|
||||
loading: state => state['open/workspaces'].loading
|
||||
}),
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
}),
|
||||
workspace () {
|
||||
return this.$store.getters['open/workspaces/getCurrent']()
|
||||
return this.workspacesStore.getCurrent()
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -76,12 +85,12 @@ export default {
|
|||
|
||||
methods: {
|
||||
switchWorkspace (workspace) {
|
||||
this.$store.commit('open/workspaces/setCurrentId', workspace.id)
|
||||
this.workspacesStore.setCurrentId(workspace.id)
|
||||
this.$refs.dropdown.close()
|
||||
if (this.$route.name !== 'home') {
|
||||
this.$router.push({ name: 'home' })
|
||||
}
|
||||
this.$store.dispatch('open/forms/load', workspace.id)
|
||||
this.formsStore.load(workspace.id)
|
||||
},
|
||||
isUrl (str) {
|
||||
try {
|
||||
|
|
|
@ -54,7 +54,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth';
|
||||
|
||||
export default {
|
||||
name: 'Breadcrumb',
|
||||
|
@ -66,20 +67,22 @@ export default {
|
|||
path: { type: Array }
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
authenticated : computed(() => authStore.check)
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
displayHome: true
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
authenticated: 'auth/check'
|
||||
})
|
||||
},
|
||||
computed: {},
|
||||
|
||||
mounted () {
|
||||
},
|
||||
mounted () {},
|
||||
|
||||
methods: {}
|
||||
}
|
||||
|
|
|
@ -37,8 +37,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from 'vue'
|
||||
import Modal from '../Modal.vue'
|
||||
import {mapGetters} from 'vuex'
|
||||
import { useAuthStore } from '../../stores/auth';
|
||||
import { useWorkspacesStore } from '../../stores/workspaces';
|
||||
import PricingTable from "../pages/pricing/PricingTable.vue";
|
||||
|
||||
export default {
|
||||
|
@ -46,6 +48,15 @@ export default {
|
|||
components: {PricingTable, Modal},
|
||||
props: {},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
return {
|
||||
user : computed(() => authStore.user),
|
||||
currentWorkSpace : computed(() => workspacesStore.getCurrent())
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
showPremiumModal: false,
|
||||
|
@ -54,10 +65,6 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
user: 'auth/user',
|
||||
currentWorkSpace: 'open/workspaces/getCurrent',
|
||||
}),
|
||||
shouldDisplayProTag() {
|
||||
if (!window.config.paid_plans_enabled) return false
|
||||
if (!this.user || !this.currentWorkSpace) return true
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
:data="countries"
|
||||
:disabled="disabled || countries.length===1" :searchable="true" :search-keys="['name']" :option-key="'code'" :color="color"
|
||||
:has-error="hasValidation && form.errors.has(name)"
|
||||
:placeholder="'Select a country'" :uppercase-labels="true" :theme="theme" @input="onChangeCountryCode"
|
||||
:placeholder="'Select a country'" :uppercase-labels="true" :theme="theme" @update:model-value="onChangeCountryCode"
|
||||
>
|
||||
<template #option="props">
|
||||
<div class="flex items-center space-x-2 hover:text-white">
|
||||
|
@ -29,7 +29,7 @@
|
|||
</v-select>
|
||||
<input v-model="inputVal" type="text" class="inline-flex-grow !border-l-0 !rounded-l-none" :disabled="disabled"
|
||||
:class="[theme.default.input, { '!ring-red-500 !ring-2': hasValidation && form.errors.has(name), '!cursor-not-allowed !bg-gray-200': disabled }]"
|
||||
:placeholder="placeholder" :style="inputStyle" @input="onInput"
|
||||
:placeholder="placeholder" :style="inputStyle" @update:model-value="onInput"
|
||||
>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
</input-help>
|
||||
</slot>
|
||||
<slot name="error">
|
||||
<has-error v-if="hasValidation" :form="form" :field="name" />
|
||||
<has-error v-if="hasValidation && form" :form="form" :field="name" />
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import store from '~/store'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
|
|
|
@ -62,6 +62,9 @@
|
|||
<script>
|
||||
import axios from 'axios'
|
||||
import Form from 'vform'
|
||||
import { computed } from 'vue'
|
||||
import { useRecordsStore } from '../../../stores/records'
|
||||
import { useWorkingFormStore } from '../../../stores/working_form'
|
||||
import OpenFormButton from './OpenFormButton.vue'
|
||||
import clonedeep from 'clone-deep'
|
||||
import FormLogicPropertyResolver from '../../../forms/FormLogicPropertyResolver.js'
|
||||
|
@ -100,6 +103,16 @@ export default {
|
|||
},
|
||||
adminPreview: { type: Boolean, default: false } // If used in FormEditorPreview
|
||||
},
|
||||
|
||||
setup () {
|
||||
const recordsStore = useRecordsStore()
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
recordsStore,
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
dataForm: null,
|
||||
|
@ -154,8 +167,8 @@ export default {
|
|||
newFields.push(...group)
|
||||
}
|
||||
})
|
||||
// set the properties on working_form vuex
|
||||
this.$store.commit('open/working_form/setProperties', newFields)
|
||||
// set the properties on working_form store
|
||||
this.workingFormStore.setProperties(newFields)
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
@ -293,12 +306,12 @@ export default {
|
|||
if (!this.form || !this.form.editable_submissions || !this.form.submission_id) {
|
||||
return null
|
||||
}
|
||||
await this.$store.dispatch('open/records/loadRecord',
|
||||
await this.recordsStore.loadRecord(
|
||||
axios.get('/api/forms/' + this.form.slug + '/submissions/' + this.form.submission_id).then((response) => {
|
||||
return { submission_id: this.form.submission_id, ...response.data.data }
|
||||
})
|
||||
)
|
||||
return this.$store.getters['open/records/getById'](this.form.submission_id)
|
||||
return this.recordsStore.getById(this.form.submission_id)
|
||||
},
|
||||
async initForm () {
|
||||
if (this.isPublicFormPage && this.form.editable_submissions) {
|
||||
|
|
|
@ -78,9 +78,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from 'vue'
|
||||
import { useWorkingFormStore } from '../../../stores/working_form';
|
||||
import FormLogicPropertyResolver from '../../../forms/FormLogicPropertyResolver.js'
|
||||
import FormPendingSubmissionKey from '../../../mixins/forms/form-pending-submission-key.js'
|
||||
import {mapState} from "vuex";
|
||||
|
||||
export default {
|
||||
name: 'OpenFormField',
|
||||
|
@ -113,15 +114,21 @@ export default {
|
|||
},
|
||||
adminPreview: {type: Boolean, default: false} // If used in FormEditorPreview
|
||||
},
|
||||
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore,
|
||||
selectedFieldIndex : computed(() => workingFormStore.selectedFieldIndex),
|
||||
showEditFieldSidebar : computed(() => workingFormStore.showEditFieldSidebar)
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState({
|
||||
selectedFieldIndex: state => state['open/working_form'].selectedFieldIndex,
|
||||
showEditFieldSidebar: state => state['open/working_form'].showEditFieldSidebar
|
||||
}),
|
||||
fieldComponents() {
|
||||
return {
|
||||
text: 'TextInput',
|
||||
|
@ -214,10 +221,10 @@ export default {
|
|||
|
||||
methods: {
|
||||
editFieldOptions() {
|
||||
this.$store.commit('open/working_form/openSettingsForField', this.field)
|
||||
this.workingFormStore.openSettingsForField(this.field)
|
||||
},
|
||||
openAddFieldSidebar() {
|
||||
this.$store.commit('open/working_form/openAddFieldSidebar', this.field)
|
||||
this.workingFormStore.openAddFieldSidebar(this.field)
|
||||
},
|
||||
/**
|
||||
* Get the right input component for the field/options combination
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
label="Hide Form Title"
|
||||
:disabled="form.hide_title===true"
|
||||
:help="hideTitleHelp"
|
||||
@input="onChangeHideTitle"
|
||||
@update:model-value="onChangeHideTitle"
|
||||
/>
|
||||
<toggle-switch-input :value="value.auto_submit" name="auto_submit" class="mt-4"
|
||||
label="Auto Submit Form"
|
||||
help="Form will auto submit immediate after open URL"
|
||||
@input="onChangeAutoSubmit"
|
||||
@update:model-value="onChangeAutoSubmit"
|
||||
/>
|
||||
</collapse>
|
||||
</template>
|
||||
|
|
|
@ -85,7 +85,11 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../../../stores/auth';
|
||||
import { useFormsStore } from '../../../../stores/forms';
|
||||
import { useWorkingFormStore } from '../../../../stores/working_form';
|
||||
import { useWorkspacesStore } from '../../../../stores/workspaces';
|
||||
import AddFormBlockSidebar from './form-components/AddFormBlockSidebar.vue'
|
||||
import FormFieldEditSidebar from '../fields/FormFieldEditSidebar.vue'
|
||||
import FormErrorModal from './form-components/FormErrorModal.vue'
|
||||
|
@ -143,6 +147,19 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const formsStore = useFormsStore()
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
return {
|
||||
formsStore,
|
||||
workingFormStore,
|
||||
workspacesStore,
|
||||
user : computed(() => authStore.user)
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
showFormErrorModal: false,
|
||||
|
@ -153,23 +170,20 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
}),
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
createdForm () {
|
||||
return this.$store.getters['open/forms/getById'](this.createdFormId)
|
||||
return this.formsStore.getById(this.createdFormId)
|
||||
},
|
||||
workspace () {
|
||||
return this.$store.getters['open/workspaces/getCurrent']()
|
||||
return this.workspacesStore.getCurrent()
|
||||
},
|
||||
steps () {
|
||||
return [
|
||||
|
@ -245,7 +259,7 @@ export default {
|
|||
this.validationErrorResponse = null
|
||||
this.form.put('/api/open/forms/{id}/'.replace('{id}', this.form.id)).then((response) => {
|
||||
const data = response.data
|
||||
this.$store.commit('open/forms/addOrUpdate', data.form)
|
||||
this.formsStore.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 })
|
||||
|
@ -266,7 +280,7 @@ export default {
|
|||
|
||||
this.updateFormLoading = true
|
||||
this.form.post('/api/open/forms').then((response) => {
|
||||
this.$store.commit('open/forms/addOrUpdate', response.data.form)
|
||||
this.formsStore.addOrUpdate(response.data.form)
|
||||
this.$emit('on-save')
|
||||
this.createdFormId = response.data.form.id
|
||||
|
||||
|
|
|
@ -166,6 +166,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from 'vue'
|
||||
import { useWorkingFormStore } from '../../../../stores/working_form'
|
||||
import draggable from 'vuedraggable'
|
||||
import ProTag from '../../../common/ProTag.vue'
|
||||
import clonedeep from 'clone-deep'
|
||||
|
@ -182,6 +184,13 @@ export default {
|
|||
EditableDiv
|
||||
},
|
||||
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
formFields: [],
|
||||
|
@ -192,11 +201,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -313,7 +322,7 @@ export default {
|
|||
return type
|
||||
},
|
||||
editOptions (index) {
|
||||
this.$store.commit('open/working_form/openSettingsForField', index)
|
||||
this.workingFormStore.openSettingsForField(index)
|
||||
},
|
||||
removeBlock (blockIndex) {
|
||||
const newFields = clonedeep(this.formFields)
|
||||
|
@ -322,10 +331,10 @@ export default {
|
|||
this.closeSidebar()
|
||||
},
|
||||
closeSidebar () {
|
||||
this.$store.commit('open/working_form/closeEditFieldSidebar')
|
||||
this.workingFormStore.closeEditFieldSidebar()
|
||||
},
|
||||
openAddFieldSidebar () {
|
||||
this.$store.commit('open/working_form/openAddFieldSidebar', null)
|
||||
this.workingFormStore.openAddFieldSidebar(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
</h4>
|
||||
<div v-for="field in properties" :key="field.id" class="p-2 border">
|
||||
{{ field.name }}
|
||||
<v-switch v-model="displayColumns[field.id]" class="float-right" @input="onChangeDisplayColumns" />
|
||||
<v-switch v-model="displayColumns[field.id]" class="float-right" @update:model-value="onChangeDisplayColumns" />
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="removed_properties.length > 0">
|
||||
|
@ -34,7 +34,7 @@
|
|||
</h4>
|
||||
<div v-for="field in removed_properties" :key="field.id" class="p-2 border">
|
||||
{{ field.name }}
|
||||
<v-switch v-model="displayColumns[field.id]" class="float-right" @input="onChangeDisplayColumns" />
|
||||
<v-switch v-model="displayColumns[field.id]" class="float-right" @update:model-value="onChangeDisplayColumns" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
@ -83,6 +83,7 @@
|
|||
import axios from 'axios'
|
||||
import Fuse from 'fuse.js'
|
||||
import Form from 'vform'
|
||||
import { useWorkingFormStore } from '../../../../stores/working_form'
|
||||
import ScrollShadow from '../../../common/ScrollShadow.vue'
|
||||
import OpenTable from '../../tables/OpenTable.vue'
|
||||
import clonedeep from 'clone-deep'
|
||||
|
@ -92,6 +93,15 @@ export default {
|
|||
name: 'FormSubmissions',
|
||||
components: { ScrollShadow, OpenTable, VSwitch },
|
||||
props: {},
|
||||
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
data () {
|
||||
return {
|
||||
formInitDone: false,
|
||||
|
@ -111,10 +121,10 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
exportUrl () {
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<div class="mx-auto">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-gray-500" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor" stroke-width="2" v-html="block.icon"
|
||||
/>
|
||||
></svg>
|
||||
</div>
|
||||
<p class="w-full text-xs text-gray-500 uppercase text-center font-semibold mt-1">
|
||||
{{ block.title }}
|
||||
|
@ -50,7 +50,7 @@
|
|||
<div class="mx-auto">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-gray-500" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor" stroke-width="2" v-html="block.icon"
|
||||
/>
|
||||
></svg>
|
||||
</div>
|
||||
<p class="w-full text-xs text-gray-500 uppercase text-center font-semibold mt-1">
|
||||
{{ block.title }}
|
||||
|
@ -63,14 +63,26 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import Form from 'vform'
|
||||
import clonedeep from 'clone-deep'
|
||||
import { computed } from 'vue'
|
||||
import { useWorkingFormStore } from '../../../../../stores/working_form'
|
||||
|
||||
export default {
|
||||
name: 'AddFormBlockSidebar',
|
||||
components: {},
|
||||
props: {},
|
||||
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore,
|
||||
selectedFieldIndex : computed(() => workingFormStore.selectedFieldIndex),
|
||||
showAddFieldSidebar : computed(() => workingFormStore.showAddFieldSidebar)
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
data () {
|
||||
return {
|
||||
blockForm: null,
|
||||
|
@ -162,17 +174,13 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapState({
|
||||
selectedFieldIndex: state => state['open/working_form'].selectedFieldIndex,
|
||||
showAddFieldSidebar: state => state['open/working_form'].showAddFieldSidebar
|
||||
}),
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
showSidebar () {
|
||||
|
@ -209,7 +217,7 @@ export default {
|
|||
|
||||
methods: {
|
||||
closeSidebar () {
|
||||
this.$store.commit('open/working_form/closeAddFieldSidebar')
|
||||
this.workingFormStore.closeAddFieldSidebar()
|
||||
},
|
||||
reset () {
|
||||
this.blockForm = new Form({
|
||||
|
@ -231,12 +239,12 @@ export default {
|
|||
const newFields = clonedeep(this.form.properties)
|
||||
newFields.push(newBlock)
|
||||
this.form.properties = newFields
|
||||
this.$store.commit('open/working_form/openSettingsForField', this.form.properties.length - 1)
|
||||
this.workingFormStore.openSettingsForField(this.form.properties.length - 1)
|
||||
} else {
|
||||
const newFields = clonedeep(this.form.properties)
|
||||
newFields.splice(this.selectedFieldIndex + 1, 0, newBlock)
|
||||
this.form.properties = newFields
|
||||
this.$store.commit('open/working_form/openSettingsForField', this.selectedFieldIndex + 1)
|
||||
this.workingFormStore.openSettingsForField(this.selectedFieldIndex + 1)
|
||||
}
|
||||
this.reset()
|
||||
},
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../../../stores/working_form'
|
||||
import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
|
||||
import ProTag from '../../../../common/ProTag.vue'
|
||||
import VTransition from '../../../../common/transitions/VTransition.vue'
|
||||
|
@ -136,6 +137,12 @@ import VTransition from '../../../../common/transitions/VTransition.vue'
|
|||
export default {
|
||||
components: {EditorOptionsPanel, ProTag, VTransition},
|
||||
props: {},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
submissionOptions: {}
|
||||
|
@ -145,11 +152,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
|
|
@ -38,11 +38,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../../../stores/working_form'
|
||||
import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
|
||||
|
||||
export default {
|
||||
components: { EditorOptionsPanel },
|
||||
props: {},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
|
@ -50,11 +57,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -17,12 +17,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../../../stores/working_form'
|
||||
import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
|
||||
import CodeInput from '../../../../forms/CodeInput.vue'
|
||||
|
||||
export default {
|
||||
components: { EditorOptionsPanel, CodeInput },
|
||||
props: {
|
||||
props: {},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
@ -32,11 +38,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -23,11 +23,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../../../stores/working_form'
|
||||
import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
|
||||
|
||||
export default {
|
||||
components: { EditorOptionsPanel },
|
||||
props: {},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
|
@ -35,11 +42,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
/>
|
||||
<toggle-switch-input name="confetti_on_submission" :form="form" class="mt-4"
|
||||
label="Confetti on successful submisison"
|
||||
@input="onChangeConfettiOnSubmission"
|
||||
@update:model-value="onChangeConfettiOnSubmission"
|
||||
/>
|
||||
<toggle-switch-input name="auto_save" :form="form"
|
||||
label="Auto save form response"
|
||||
|
@ -81,6 +81,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../../../stores/working_form'
|
||||
import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
|
||||
import ProTag from '../../../../common/ProTag.vue'
|
||||
|
||||
|
@ -88,6 +89,12 @@ export default {
|
|||
components: { EditorOptionsPanel, ProTag },
|
||||
props: {
|
||||
},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isMounted: false
|
||||
|
@ -97,11 +104,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -59,12 +59,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../../../stores/working_form'
|
||||
import VSwitch from '../../../../forms/components/VSwitch.vue'
|
||||
import OpenCompleteForm from '../../OpenCompleteForm.vue'
|
||||
|
||||
export default {
|
||||
components: { OpenCompleteForm, VSwitch },
|
||||
props: {
|
||||
props: {},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
@ -75,11 +81,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
creating () { // returns true if we are creating a form
|
||||
|
|
|
@ -66,14 +66,27 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from 'vue'
|
||||
import clonedeep from 'clone-deep'
|
||||
import { useFormsStore } from '../../../../../stores/forms'
|
||||
import { useWorkingFormStore } from '../../../../../stores/working_form'
|
||||
import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
|
||||
import SelectInput from '../../../../forms/SelectInput.vue'
|
||||
import { mapState } from 'vuex'
|
||||
import clonedeep from 'clone-deep'
|
||||
|
||||
export default {
|
||||
components: { SelectInput, EditorOptionsPanel },
|
||||
props: {},
|
||||
|
||||
setup () {
|
||||
const formsStore = useFormsStore()
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
formsStore,
|
||||
workingFormStore,
|
||||
forms : computed(() => formsStore.content)
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
showCopyFormSettingsModal: false,
|
||||
|
@ -106,20 +119,17 @@ export default {
|
|||
}
|
||||
})
|
||||
},
|
||||
...mapState({
|
||||
forms: state => state['open/forms'].content
|
||||
}),
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
allTagsOptions () {
|
||||
return this.$store.getters['open/forms/getAllTags'].map((tagname) => {
|
||||
return this.formsStore.getAllTags.map((tagname) => {
|
||||
return {
|
||||
name: tagname,
|
||||
value: tagname
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../../../stores/working_form'
|
||||
import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
|
||||
import FormNotificationsOption from './components/FormNotificationsOption.vue'
|
||||
import FormNotificationsSlack from './components/FormNotificationsSlack.vue'
|
||||
|
@ -40,7 +41,12 @@ import FormNotificationsWebhook from './components/FormNotificationsWebhook.vue'
|
|||
|
||||
export default {
|
||||
components: { FormNotificationsSubmissionConfirmation, FormNotificationsSlack, FormNotificationsDiscord, FormNotificationsOption, EditorOptionsPanel, FormNotificationsWebhook },
|
||||
props: {
|
||||
props: {},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
@ -50,11 +56,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
zapierUrl: () => window.config.links.zapier_integration
|
||||
|
|
|
@ -17,11 +17,17 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../../../stores/working_form'
|
||||
import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
|
||||
|
||||
export default {
|
||||
components: { EditorOptionsPanel },
|
||||
props: {
|
||||
props: {},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
@ -30,11 +36,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -11,12 +11,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../../../stores/working_form'
|
||||
import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
|
||||
import FormFieldsEditor from '../FormFieldsEditor.vue'
|
||||
|
||||
export default {
|
||||
components: { EditorOptionsPanel, FormFieldsEditor },
|
||||
props: {
|
||||
props: {},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
@ -26,11 +32,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,12 +46,19 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../../../../stores/working_form'
|
||||
import ProTag from '../../../../../common/ProTag.vue'
|
||||
import FormNotificationsMessageActions from './FormNotificationsMessageActions.vue'
|
||||
|
||||
export default {
|
||||
components: { ProTag, FormNotificationsMessageActions },
|
||||
props: {},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showModal: false
|
||||
|
@ -61,11 +68,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -50,11 +50,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../../../../stores/working_form'
|
||||
import ProTag from '../../../../../common/ProTag.vue'
|
||||
|
||||
export default {
|
||||
components: { ProTag },
|
||||
props: {},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showModal: false
|
||||
|
@ -64,11 +71,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
replayToEmailField () {
|
||||
|
|
|
@ -47,12 +47,19 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../../../../stores/working_form'
|
||||
import ProTag from '../../../../../common/ProTag.vue'
|
||||
import FormNotificationsMessageActions from './FormNotificationsMessageActions.vue'
|
||||
|
||||
export default {
|
||||
components: { ProTag, FormNotificationsMessageActions },
|
||||
props: {},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showModal: false
|
||||
|
@ -62,11 +69,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -62,11 +62,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../../../../stores/working_form'
|
||||
import ProTag from '../../../../../common/ProTag.vue'
|
||||
|
||||
export default {
|
||||
components: { ProTag },
|
||||
props: {},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showModal: false
|
||||
|
@ -76,11 +83,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
emailSubmissionConfirmationField () {
|
||||
|
|
|
@ -43,11 +43,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../../../../stores/working_form'
|
||||
import ProTag from '../../../../../common/ProTag.vue'
|
||||
|
||||
export default {
|
||||
components: { ProTag },
|
||||
props: {},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showModal: false
|
||||
|
@ -57,11 +64,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
:multiple="true" class="mt-1" placeholder="Actions..."
|
||||
help="Action(s) triggerred when above conditions are true"
|
||||
:options="actionOptions"
|
||||
@input="onActionInput"
|
||||
@update:model-value="onActionInput"
|
||||
/>
|
||||
|
||||
<modal :show="showCopyFormModal" @close="showCopyFormModal = false">
|
||||
|
|
|
@ -72,10 +72,11 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Form from 'vform'
|
||||
import store from '~/store'
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import axios from 'axios'
|
||||
import Form from 'vform'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../../../../stores/auth'
|
||||
import { useTemplatesStore } from '../../../../../stores/templates'
|
||||
import QuestionsEditor from './QuestionsEditor.vue'
|
||||
|
||||
export default {
|
||||
|
@ -87,6 +88,18 @@ export default {
|
|||
template: { type: Object, required: false, default: () => {} }
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const templatesStore = useTemplatesStore()
|
||||
return {
|
||||
templatesStore,
|
||||
user : computed(() => authStore.user),
|
||||
templates : computed(() => templatesStore.content),
|
||||
industries : computed(() => templatesStore.industries),
|
||||
types : computed(() => templatesStore.types)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
templateForm: null
|
||||
}),
|
||||
|
@ -104,18 +117,10 @@ export default {
|
|||
related_templates: null,
|
||||
questions: []
|
||||
})
|
||||
store.dispatch('open/templates/loadIfEmpty')
|
||||
this.templatesStore.loadIfEmpty()
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState({
|
||||
templates: state => state['open/templates'].content,
|
||||
industries: state => state['open/templates'].industries,
|
||||
types: state => state['open/templates'].types
|
||||
}),
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
}),
|
||||
typesOptions () {
|
||||
return Object.values(this.types).map((type) => {
|
||||
return {
|
||||
|
@ -156,7 +161,7 @@ export default {
|
|||
if (response.data.message) {
|
||||
this.alertSuccess(response.data.message)
|
||||
}
|
||||
this.$store.commit('open/templates/addOrUpdate', response.data.data)
|
||||
this.templatesStore.addOrUpdate(response.data.data)
|
||||
this.$emit('close')
|
||||
})
|
||||
},
|
||||
|
@ -166,7 +171,7 @@ export default {
|
|||
if (response.data.message) {
|
||||
this.alertSuccess(response.data.message)
|
||||
}
|
||||
this.$store.commit('open/templates/addOrUpdate', response.data.data)
|
||||
this.templatesStore.addOrUpdate(response.data.data)
|
||||
this.$emit('close')
|
||||
})
|
||||
},
|
||||
|
@ -177,7 +182,7 @@ export default {
|
|||
this.alertSuccess(response.data.message)
|
||||
}
|
||||
this.$router.push({ name: 'templates' })
|
||||
this.$store.commit('open/templates/remove', this.template)
|
||||
this.templatesStore.remove(this.template)
|
||||
this.$emit('close')
|
||||
})
|
||||
}
|
||||
|
|
|
@ -70,8 +70,9 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import clonedeep from 'clone-deep'
|
||||
import { useWorkingFormStore } from '../../../../stores/working_form'
|
||||
import ChangeFieldType from './components/ChangeFieldType.vue'
|
||||
import FieldOptions from './components/FieldOptions.vue'
|
||||
import BlockOptions from './components/BlockOptions.vue'
|
||||
|
@ -80,6 +81,14 @@ export default {
|
|||
name: 'FormFieldEditSidebar',
|
||||
components: { ChangeFieldType, FieldOptions, BlockOptions },
|
||||
props: {},
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore,
|
||||
selectedFieldIndex : computed(() => workingFormStore.selectedFieldIndex),
|
||||
showEditFieldSidebar : computed(() => workingFormStore.showEditFieldSidebar)
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
|
@ -87,17 +96,13 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapState({
|
||||
selectedFieldIndex: state => state['open/working_form'].selectedFieldIndex,
|
||||
showEditFieldSidebar: state => state['open/working_form'].showEditFieldSidebar
|
||||
}),
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
field () {
|
||||
|
@ -145,7 +150,7 @@ export default {
|
|||
this.closeSidebar()
|
||||
},
|
||||
closeSidebar () {
|
||||
this.$store.commit('open/working_form/closeEditFieldSidebar')
|
||||
this.workingFormStore.closeEditFieldSidebar()
|
||||
},
|
||||
generateUUID () {
|
||||
let d = new Date().getTime()// Timestamp
|
||||
|
|
|
@ -186,7 +186,7 @@
|
|||
<text-area-input v-model="optionsText" :name="field.id+'_options_text'" class="mt-3"
|
||||
label="Set selection options"
|
||||
help="Add one option per line"
|
||||
@input="onFieldOptionsChange"
|
||||
@update:model-value="onFieldOptionsChange"
|
||||
/>
|
||||
<v-checkbox v-model="field.allow_creation"
|
||||
name="allow_creation" help="" @update:model-value="onFieldAllowCreationChange"
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { useWorkingFormStore } from '../../../stores/working_form'
|
||||
import OpenText from './components/OpenText.vue'
|
||||
import OpenUrl from './components/OpenUrl.vue'
|
||||
import OpenSelect from './components/OpenSelect.vue'
|
||||
|
@ -119,6 +120,13 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
setup () {
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
return {
|
||||
workingFormStore
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
tableHash: null,
|
||||
|
@ -129,10 +137,11 @@ export default {
|
|||
computed: {
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
hasActions () {
|
||||
|
|
|
@ -31,18 +31,23 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
|
||||
export default {
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
user : computed(() => authStore.user)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
appName: window.config.appName,
|
||||
currYear: new Date().getFullYear(),
|
||||
}),
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
}),
|
||||
helpUrl: () => window.config.links.help_url,
|
||||
githubUrl: () => window.config.links.github_url,
|
||||
forumUrl: () => window.config.links.github_forum_url,
|
||||
|
|
|
@ -24,28 +24,34 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth';
|
||||
import { useWorkspacesStore } from '../../stores/workspaces';
|
||||
|
||||
export default {
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
return {
|
||||
authStore,
|
||||
workspacesStore,
|
||||
isImpersonating : computed(() => authStore.isImpersonating),
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
loading: false
|
||||
}),
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
isImpersonating: 'auth/isImpersonating'
|
||||
})
|
||||
},
|
||||
computed: {},
|
||||
|
||||
mounted () {
|
||||
},
|
||||
mounted () {},
|
||||
|
||||
methods: {
|
||||
reverseImpersonation () {
|
||||
this.loading = true
|
||||
this.$store.dispatch('auth/stopImpersonating')
|
||||
.then(() => {
|
||||
this.$store.commit('open/workspaces/set', [])
|
||||
this.authStore.stopImpersonating().then(() => {
|
||||
this.workspacesStore.set([])
|
||||
this.$router.push({ name: 'settings.admin' })
|
||||
this.loading = false
|
||||
})
|
||||
|
|
|
@ -62,14 +62,22 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from 'vue'
|
||||
import axios from 'axios'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { useAuthStore } from '../../../stores/auth';
|
||||
import VTransition from '../../common/transitions/VTransition.vue'
|
||||
|
||||
export default {
|
||||
components: { VTransition },
|
||||
props: {},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
user : computed(() => authStore.user)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
changelogEntries: [],
|
||||
showNewFeatures: false
|
||||
|
@ -80,9 +88,6 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
}),
|
||||
requestFeatureLink () {
|
||||
return window.config.links.feature_requests
|
||||
},
|
||||
|
|
|
@ -122,8 +122,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from 'vue'
|
||||
import axios from 'axios'
|
||||
import {mapGetters, mapState} from 'vuex'
|
||||
import { useAuthStore } from '../../../../stores/auth'
|
||||
import { useFormsStore } from '../../../../stores/forms'
|
||||
import Dropdown from '../../../common/Dropdown.vue'
|
||||
import FormTemplateModal from '../../../open/forms/components/templates/FormTemplateModal.vue'
|
||||
|
||||
|
@ -135,6 +137,15 @@ export default {
|
|||
isMainPage: { type: Boolean, required: false, default: false }
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const formsStore = useFormsStore()
|
||||
return {
|
||||
formsStore,
|
||||
user : computed(() => authStore.user)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
loadingDuplicate: false,
|
||||
loadingDelete: false,
|
||||
|
@ -143,9 +154,6 @@ export default {
|
|||
}),
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
}),
|
||||
formEndpoint: () => '/api/open/forms/{id}',
|
||||
},
|
||||
|
||||
|
@ -163,7 +171,7 @@ export default {
|
|||
if (this.loadingDuplicate) return
|
||||
this.loadingDuplicate = true
|
||||
axios.post(this.formEndpoint.replace('{id}', this.form.id) + '/duplicate').then((response) => {
|
||||
this.$store.commit('open/forms/addOrUpdate', response.data.new_form)
|
||||
this.formsStore.addOrUpdate(response.data.new_form)
|
||||
this.$router.push({name: 'forms.show', params: {slug: response.data.new_form.slug}})
|
||||
this.alertSuccess('Form was successfully duplicated.')
|
||||
this.loadingDuplicate = false
|
||||
|
@ -173,7 +181,7 @@ export default {
|
|||
if (this.loadingDelete) return
|
||||
this.loadingDelete = true
|
||||
axios.delete(this.formEndpoint.replace('{id}', this.form.id)).then(() => {
|
||||
this.$store.commit('open/forms/remove', this.form)
|
||||
this.formsStore.remove(this.form)
|
||||
this.$router.push({name: 'home'})
|
||||
this.alertSuccess('Form was deleted.')
|
||||
this.loadingDelete = false
|
||||
|
|
|
@ -72,7 +72,9 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from 'vue'
|
||||
import axios from 'axios'
|
||||
import { useFormsStore } from '../../../../stores/forms'
|
||||
|
||||
export default {
|
||||
name: 'RegenerateFormLink',
|
||||
|
@ -81,6 +83,13 @@ export default {
|
|||
form: { type: Object, required: true }
|
||||
},
|
||||
|
||||
setup () {
|
||||
const formsStore = useFormsStore()
|
||||
return {
|
||||
formsStore
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
loadingNewLink: false,
|
||||
showGenerateFormLinkModal: false,
|
||||
|
@ -95,7 +104,7 @@ export default {
|
|||
if (this.loadingNewLink) return
|
||||
this.loadingNewLink = true
|
||||
axios.put(this.formEndpoint.replace('{id}', this.form.id) + '/regenerate-link/' + option).then((response) => {
|
||||
this.$store.commit('open/forms/addOrUpdate', response.data.form)
|
||||
this.formsStore.addOrUpdate(response.data.form)
|
||||
this.$router.push({name: 'forms.show', params: {slug: response.data.form.slug}})
|
||||
this.alertSuccess(response.data.message)
|
||||
this.loadingNewLink = false
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import TextInput from '../../forms/TextInput.vue'
|
||||
import Form from 'vform'
|
||||
import VButton from '../../common/Button.vue'
|
||||
import { computed } from 'vue'
|
||||
import axios from 'axios'
|
||||
import Form from 'vform'
|
||||
import { useAuthStore } from '../../../stores/auth'
|
||||
import TextInput from '../../forms/TextInput.vue'
|
||||
import VButton from '../../common/Button.vue'
|
||||
|
||||
export default {
|
||||
|
||||
components: { VButton, TextInput },
|
||||
props: {
|
||||
show: {
|
||||
|
@ -34,6 +34,14 @@ export default {
|
|||
default: true
|
||||
}
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
user : computed(() => authStore.user)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
form: new Form({
|
||||
name: '',
|
||||
|
@ -88,10 +96,6 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
})
|
||||
}
|
||||
computed: {}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -107,7 +107,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../../stores/auth'
|
||||
import axios from 'axios'
|
||||
import MonthlyYearlySelector from './MonthlyYearlySelector.vue'
|
||||
import CheckoutDetailsModal from './CheckoutDetailsModal.vue'
|
||||
|
@ -127,6 +128,13 @@ export default {
|
|||
default: false
|
||||
}
|
||||
},
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
authenticated : computed(() => authStore.check),
|
||||
user : computed(() => authStore.user)
|
||||
}
|
||||
},
|
||||
data: () => ({
|
||||
isYearly: true,
|
||||
selectedPlan: 'pro',
|
||||
|
@ -160,11 +168,6 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
authenticated: 'auth/check',
|
||||
user: 'auth/user'
|
||||
})
|
||||
}
|
||||
computed: {}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -39,7 +39,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import store from '~/store'
|
||||
import { computed } from 'vue'
|
||||
import { useTemplatesStore } from '../../../stores/templates'
|
||||
import TemplateTags from './TemplateTags.vue'
|
||||
|
||||
export default {
|
||||
|
@ -52,22 +53,29 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
setup () {
|
||||
const templatesStore = useTemplatesStore()
|
||||
return {
|
||||
templatesStore
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({}),
|
||||
|
||||
computed: {
|
||||
template () {
|
||||
return this.$store.getters['open/templates/getBySlug'](this.slug)
|
||||
return this.templatesStore.getBySlug(this.slug)
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
slug () {
|
||||
store.dispatch('open/templates/loadTemplate', this.slug)
|
||||
this.templatesStore.loadTemplate(this.slug)
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
store.dispatch('open/templates/loadTemplate', this.slug)
|
||||
this.templatesStore.loadTemplate(this.slug)
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
|
@ -41,6 +41,9 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from 'vue'
|
||||
import { useTemplatesStore } from '../../../stores/templates'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
slug: {
|
||||
|
@ -53,19 +56,26 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
setup () {
|
||||
const templatesStore = useTemplatesStore()
|
||||
return {
|
||||
templatesStore
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({}),
|
||||
|
||||
computed: {
|
||||
template () {
|
||||
return this.$store.getters['open/templates/getBySlug'](this.slug)
|
||||
return this.templatesStore.getBySlug(this.slug)
|
||||
},
|
||||
types () {
|
||||
if (!this.template) return null
|
||||
return this.$store.getters['open/templates/getTemplateTypes'](this.template.types)
|
||||
return this.templatesStore.getTemplateTypes(this.template.types)
|
||||
},
|
||||
industries () {
|
||||
if (!this.template) return null
|
||||
return this.$store.getters['open/templates/getTemplateIndustries'](this.template.industries)
|
||||
return this.templatesStore.getTemplateIndustries(this.template.industries)
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -79,24 +79,25 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import store from '~/store'
|
||||
import { mapGetters, mapState } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../../stores/auth'
|
||||
import { useTemplatesStore } from '../../../stores/templates'
|
||||
import Form from 'vform'
|
||||
import Fuse from 'fuse.js'
|
||||
import SingleTemplate from './SingleTemplate.vue'
|
||||
|
||||
const loadTemplates = function (onlyMy) {
|
||||
const templatesStore = useTemplatesStore()
|
||||
if(onlyMy){
|
||||
store.dispatch('open/templates/loadAll', {'onlymy':true})
|
||||
templatesStore.loadAll({'onlymy':true})
|
||||
} else {
|
||||
store.dispatch('open/templates/loadIfEmpty')
|
||||
templatesStore.loadIfEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'TemplatesList',
|
||||
components: { SingleTemplate },
|
||||
|
||||
props: {
|
||||
onlyMy: {
|
||||
type: Boolean,
|
||||
|
@ -104,6 +105,18 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const templatesStore = useTemplatesStore()
|
||||
return {
|
||||
user : computed(() => authStore.user),
|
||||
templates : computed(() => templatesStore.content),
|
||||
templatesLoading : computed(() => templatesStore.loading),
|
||||
industries : computed(() => templatesStore.industries),
|
||||
types : computed(() => templatesStore.types)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
selectedType: 'all',
|
||||
selectedIndustry: 'all',
|
||||
|
@ -119,15 +132,6 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapState({
|
||||
templates: state => state['open/templates'].content,
|
||||
templatesLoading: state => state['open/templates'].loading,
|
||||
industries: state => state['open/templates'].industries,
|
||||
types: state => state['open/templates'].types
|
||||
}),
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
}),
|
||||
industriesOptions () {
|
||||
return [{ name: 'All Industries', value: 'all' }].concat(Object.values(this.industries).map((industry) => {
|
||||
return {
|
||||
|
|
|
@ -87,16 +87,19 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters} from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../../stores/auth'
|
||||
|
||||
export default {
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
authenticated : computed(() => authStore.check)
|
||||
}
|
||||
},
|
||||
props: {},
|
||||
data: () => ({}),
|
||||
computed: {
|
||||
...mapGetters({
|
||||
authenticated: 'auth/check'
|
||||
}),
|
||||
},
|
||||
computed: {},
|
||||
methods: {}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -36,19 +36,23 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import store from '~/store'
|
||||
import { mapGetters, mapState } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useTemplatesStore } from '../../../stores/templates'
|
||||
import SingleTemplate from '../templates/SingleTemplate.vue'
|
||||
|
||||
export default {
|
||||
components: { SingleTemplate },
|
||||
props: { },
|
||||
setup () {
|
||||
const templatesStore = useTemplatesStore()
|
||||
return {
|
||||
templatesStore,
|
||||
templates : computed(() => templatesStore.content)
|
||||
}
|
||||
},
|
||||
data: () => ({}),
|
||||
|
||||
computed: {
|
||||
...mapState({
|
||||
templates: state => state['open/templates'].content
|
||||
}),
|
||||
sliderTemplates () {
|
||||
return this.templates.slice(0, 20)
|
||||
}
|
||||
|
@ -66,7 +70,7 @@ export default {
|
|||
},
|
||||
|
||||
mounted() {
|
||||
store.dispatch('open/templates/loadAll', { limit: 20 })
|
||||
this.templatesStore.loadAll({ limit: 20 })
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
<template />
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
|
||||
export default {
|
||||
|
||||
name: 'Amplitude',
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
authStore,
|
||||
authenticated : computed(() => authStore.check),
|
||||
user : computed(() => authStore.user)
|
||||
}
|
||||
},
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
loaded: false,
|
||||
|
@ -14,12 +23,7 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
authenticated: 'auth/check',
|
||||
user: 'auth/user'
|
||||
})
|
||||
},
|
||||
computed: {},
|
||||
|
||||
watch: {
|
||||
$route () {
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
<template />
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
|
||||
export default {
|
||||
|
||||
name: 'Hotjar',
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
authenticated : computed(() => authStore.check),
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
authenticated () {
|
||||
if (this.authenticated) {
|
||||
|
@ -38,9 +45,6 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
authenticated: 'auth/check'
|
||||
}),
|
||||
isIframe () {
|
||||
return window.location !== window.parent.location || window.frameElement
|
||||
}
|
||||
|
|
|
@ -21,23 +21,27 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../../stores/auth'
|
||||
import VButton from '../../common/Button.vue'
|
||||
|
||||
export default {
|
||||
|
||||
name: 'AppSumoBilling',
|
||||
components: { VButton },
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
user : computed(() => authStore.user),
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
}),
|
||||
licenseTier () {
|
||||
return this.user?.active_license?.meta?.tier
|
||||
},
|
||||
|
@ -67,10 +71,9 @@ export default {
|
|||
|
||||
mounted () {},
|
||||
|
||||
created () {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
created () {},
|
||||
|
||||
destroyed () {},
|
||||
|
||||
methods: {}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import store from '~/store'
|
||||
import { useAuthStore } from '../stores/auth';
|
||||
|
||||
export default (to, from, next) => {
|
||||
if (!store.getters['auth/user'].admin) {
|
||||
const authStore = useAuthStore()
|
||||
if (!authStore.user?.admin) {
|
||||
next({ name: 'home' })
|
||||
} else {
|
||||
next()
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import store from '~/store'
|
||||
import { useAuthStore } from '../stores/auth';
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
export default async (to, from, next) => {
|
||||
if (!store.getters['auth/check']) {
|
||||
const authStore = useAuthStore()
|
||||
if (!authStore.check) {
|
||||
Cookies.set('intended_url', to.path)
|
||||
|
||||
next({ name: 'login' })
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import store from '~/store'
|
||||
import { useAuthStore } from '../stores/auth';
|
||||
import * as Sentry from '@sentry/vue'
|
||||
|
||||
export function initCrisp (user) {
|
||||
|
@ -36,12 +36,13 @@ export function initSentry (user) {
|
|||
}
|
||||
|
||||
export default async (to, from, next) => {
|
||||
if (!store.getters['auth/check'] &&
|
||||
store.getters['auth/token'] !== null &&
|
||||
store.getters['auth/token'] !== undefined
|
||||
const authStore = useAuthStore()
|
||||
if (!authStore.check &&
|
||||
authStore.token !== null &&
|
||||
authStore.token !== undefined
|
||||
) {
|
||||
try {
|
||||
store.dispatch('auth/fetchUser').then((user) => {
|
||||
authStore.fetchUser().then((user) => {
|
||||
initCrisp(user)
|
||||
initSentry(user)
|
||||
})
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import store from '~/store'
|
||||
import { useAuthStore } from '../stores/auth';
|
||||
|
||||
export default (to, from, next) => {
|
||||
if (store.getters['auth/check']) {
|
||||
const authStore = useAuthStore()
|
||||
if (authStore.check) {
|
||||
next({ name: 'home' })
|
||||
} else {
|
||||
next()
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import store from '~/store'
|
||||
import { useAuthStore } from '../stores/auth';
|
||||
|
||||
export default async (to, from, next) => {
|
||||
if (store.getters['auth/check'] && store.getters['auth/user'].workspaces_count === 0) {
|
||||
const authStore = useAuthStore()
|
||||
if (authStore.check && authStore.user?.workspaces_count === 0) {
|
||||
if ([
|
||||
'forms.create',
|
||||
'forms.show',
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import store from '~/store'
|
||||
import { useAuthStore } from '../stores/auth';
|
||||
|
||||
/**
|
||||
* This is middleware to check the current user role.
|
||||
|
@ -7,14 +7,13 @@ import store from '~/store'
|
|||
*/
|
||||
|
||||
export default (to, from, next, roles) => {
|
||||
// Grab the user
|
||||
const user = store.getters['auth/user']
|
||||
const authStore = useAuthStore()
|
||||
|
||||
// Split roles into an array
|
||||
roles = roles.split(',')
|
||||
|
||||
// Check if the user has one of the required roles...
|
||||
if (!roles.includes(user.role)) {
|
||||
if (!roles.includes(authStore.user?.role)) {
|
||||
next('/unauthorized')
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import store from '~/store'
|
||||
import { useAuthStore } from '../stores/auth';
|
||||
|
||||
export default (to, from, next) => {
|
||||
if (!store.getters['auth/user'].is_subscribed) {
|
||||
const authStore = useAuthStore()
|
||||
if (!authStore.user?.is_subscribed) {
|
||||
next({ name: 'pricing' })
|
||||
} else {
|
||||
next()
|
||||
|
|
|
@ -476,7 +476,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters} from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
import OpenFormFooter from '../components/pages/OpenFormFooter.vue'
|
||||
import SeoMeta from '../mixins/seo-meta.js'
|
||||
|
||||
|
@ -484,6 +485,14 @@ export default {
|
|||
components: {OpenFormFooter},
|
||||
layout: 'default',
|
||||
mixins: [SeoMeta],
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
authenticated : computed(() => authStore.check),
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
title: window.config.appName,
|
||||
metaTitle: 'AI form builder for free',
|
||||
|
@ -494,9 +503,6 @@ export default {
|
|||
methods: {},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
authenticated: 'auth/check'
|
||||
}),
|
||||
configLinks: () => window.config.links
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,8 +41,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from 'vue'
|
||||
import Form from 'vform'
|
||||
import Cookies from 'js-cookie'
|
||||
import { useAuthStore } from '../../../stores/auth'
|
||||
import OpenFormFooter from '../../../components/pages/OpenFormFooter.vue'
|
||||
import Testimonials from '../../../components/pages/welcome/Testimonials.vue'
|
||||
import ForgotPasswordModal from '../ForgotPasswordModal.vue'
|
||||
|
@ -62,6 +64,13 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
authStore
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
form: new Form({
|
||||
email: '',
|
||||
|
@ -77,13 +86,10 @@ export default {
|
|||
const { data } = await this.form.post('/api/login')
|
||||
|
||||
// Save the token.
|
||||
this.$store.dispatch('auth/saveToken', {
|
||||
token: data.token,
|
||||
remember: this.remember
|
||||
})
|
||||
this.authStore.saveToken(data.token, this.remember)
|
||||
|
||||
// Fetch the user.
|
||||
await this.$store.dispatch('auth/fetchUser')
|
||||
await this.authStore.fetchUser()
|
||||
|
||||
// Redirect home.
|
||||
this.redirect()
|
||||
|
|
|
@ -48,7 +48,9 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from 'vue'
|
||||
import Form from 'vform'
|
||||
import { useAuthStore } from '../../../stores/auth'
|
||||
import { initCrisp } from '../../../middleware/check-auth.js'
|
||||
|
||||
export default {
|
||||
|
@ -62,6 +64,13 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
authStore
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
form: new Form({
|
||||
name: '',
|
||||
|
@ -112,10 +121,10 @@ export default {
|
|||
const { data: { token } } = await this.form.post('/api/login')
|
||||
|
||||
// Save the token.
|
||||
this.$store.dispatch('auth/saveToken', { token })
|
||||
this.authStore.saveToken(token)
|
||||
|
||||
// Update the user.
|
||||
await this.$store.dispatch('auth/updateUser', { user: data })
|
||||
await this.authStore.updateUser(data)
|
||||
|
||||
// Track event
|
||||
this.$logEvent('register', { source: this.form.hear_about_us })
|
||||
|
|
|
@ -24,18 +24,21 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import store from '~/store'
|
||||
import { computed } from 'vue'
|
||||
import Form from 'vform'
|
||||
import { mapState, mapActions } from 'vuex'
|
||||
import { useTemplatesStore } from '../../stores/templates'
|
||||
import { useWorkingFormStore } from '../../stores/working_form'
|
||||
import { useWorkspacesStore } from '../../stores/workspaces'
|
||||
import QuickRegister from '../auth/components/QuickRegister.vue'
|
||||
import initForm from '../../mixins/form_editor/initForm.js'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
import CreateFormBaseModal from '../../components/pages/forms/create/CreateFormBaseModal.vue'
|
||||
|
||||
const loadTemplates = function () {
|
||||
store.commit('open/templates/startLoading')
|
||||
store.dispatch('open/templates/loadIfEmpty').then(() => {
|
||||
store.commit('open/templates/stopLoading')
|
||||
const templatesStore = useTemplatesStore()
|
||||
templatesStore.startLoading()
|
||||
templatesStore.loadIfEmpty().then(() => {
|
||||
templatesStore.stopLoading()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -45,13 +48,25 @@ export default {
|
|||
QuickRegister, CreateFormBaseModal
|
||||
},
|
||||
mixins: [initForm, SeoMeta],
|
||||
middleware: 'guest',
|
||||
|
||||
beforeRouteEnter (to, from, next) {
|
||||
loadTemplates()
|
||||
next()
|
||||
},
|
||||
|
||||
middleware: 'guest',
|
||||
setup () {
|
||||
const templatesStore = useTemplatesStore()
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
return {
|
||||
templatesStore,
|
||||
workingFormStore,
|
||||
workspacesStore,
|
||||
workspaces : computed(() => workspacesStore.content),
|
||||
workspacesLoading : computed(() => workspacesStore.loading)
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
|
@ -66,21 +81,17 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapState({
|
||||
workspaces: state => state['open/workspaces'].content,
|
||||
workspacesLoading: state => state['open/workspaces'].loading
|
||||
}),
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
workspace () {
|
||||
return this.$store.getters['open/workspaces/getCurrent']()
|
||||
return this.workspacesStore.getCurrent()
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -100,12 +111,12 @@ export default {
|
|||
is_enterprise: false,
|
||||
is_pro: false
|
||||
}
|
||||
this.$store.commit('open/workspaces/set', [guestWorkspace])
|
||||
this.$store.commit('open/workspaces/setCurrentId', guestWorkspace.id)
|
||||
this.workspacesStore.set([guestWorkspace])
|
||||
this.workspacesStore.setCurrentId(guestWorkspace.id)
|
||||
|
||||
this.initForm()
|
||||
if (this.$route.query.template !== undefined && this.$route.query.template) {
|
||||
const template = this.$store.getters['open/templates/getBySlug'](this.$route.query.template)
|
||||
const template = this.templatesStore.getBySlug(this.$route.query.template)
|
||||
if (template && template.structure) {
|
||||
this.form = new Form({ ...this.form.data(), ...template.structure })
|
||||
}
|
||||
|
@ -121,16 +132,13 @@ export default {
|
|||
unmounted () {},
|
||||
|
||||
methods: {
|
||||
...mapActions({
|
||||
loadWorkspaces: 'open/workspaces/load'
|
||||
}),
|
||||
openRegister () {
|
||||
this.registerModal = true
|
||||
},
|
||||
afterLogin () {
|
||||
this.registerModal = false
|
||||
this.isGuest = false
|
||||
this.loadWorkspaces()
|
||||
this.workspacesStore.load()
|
||||
setTimeout(() => {
|
||||
if (this.$refs.editor) {
|
||||
this.$refs.editor.saveFormCreate()
|
||||
|
|
|
@ -19,17 +19,21 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import store from '~/store'
|
||||
import Form from 'vform'
|
||||
import { mapState, mapActions } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
import { useTemplatesStore } from '../../stores/templates'
|
||||
import { useWorkingFormStore } from '../../stores/working_form'
|
||||
import { useWorkspacesStore } from '../../stores/workspaces'
|
||||
import initForm from '../../mixins/form_editor/initForm.js'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
import CreateFormBaseModal from '../../components/pages/forms/create/CreateFormBaseModal.vue'
|
||||
|
||||
const loadTemplates = function () {
|
||||
store.commit('open/templates/startLoading')
|
||||
store.dispatch('open/templates/loadIfEmpty').then(() => {
|
||||
store.commit('open/templates/stopLoading')
|
||||
const templatesStore = useTemplatesStore()
|
||||
templatesStore.startLoading()
|
||||
templatesStore.loadIfEmpty().then(() => {
|
||||
templatesStore.stopLoading()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -38,6 +42,7 @@ export default {
|
|||
components: { CreateFormBaseModal },
|
||||
|
||||
mixins: [initForm, SeoMeta],
|
||||
middleware: 'auth',
|
||||
|
||||
beforeRouteEnter (to, from, next) {
|
||||
loadTemplates()
|
||||
|
@ -54,7 +59,20 @@ export default {
|
|||
next()
|
||||
},
|
||||
|
||||
middleware: 'auth',
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const templatesStore = useTemplatesStore()
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
return {
|
||||
templatesStore,
|
||||
workingFormStore,
|
||||
workspacesStore,
|
||||
user: computed(() => authStore.user),
|
||||
workspaces : computed(() => workspacesStore.content),
|
||||
workspacesLoading : computed(() => workspacesStore.loading)
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
|
@ -68,22 +86,17 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapState({
|
||||
workspaces: state => state['open/workspaces'].content,
|
||||
workspacesLoading: state => state['open/workspaces'].loading,
|
||||
user: state => state.auth.user
|
||||
}),
|
||||
form: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
workspace () {
|
||||
return this.$store.getters['open/workspaces/getCurrent']()
|
||||
return this.workspacesStore.getCurrent()
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -108,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.$store.getters['open/templates/getBySlug'](this.$route.query.template)
|
||||
const template = this.templatesStore.getBySlug(this.$route.query.template)
|
||||
if (template && template.structure) {
|
||||
this.form = new Form({ ...this.form.data(), ...template.structure })
|
||||
}
|
||||
|
@ -117,7 +130,7 @@ export default {
|
|||
this.showInitialFormModal = true
|
||||
}
|
||||
this.closeAlert()
|
||||
this.loadWorkspaces()
|
||||
this.workspacesStore.loadIfEmpty()
|
||||
|
||||
this.stateReady = this.user !== null
|
||||
},
|
||||
|
@ -126,9 +139,6 @@ export default {
|
|||
unmounted () {},
|
||||
|
||||
methods: {
|
||||
...mapActions({
|
||||
loadWorkspaces: 'open/workspaces/loadIfEmpty'
|
||||
}),
|
||||
formGenerated (form) {
|
||||
this.form = new Form({ ...this.form.data(), ...form })
|
||||
},
|
||||
|
|
|
@ -14,17 +14,20 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import store from '~/store'
|
||||
import Breadcrumb from '../../components/common/Breadcrumb.vue'
|
||||
import { computed } from 'vue'
|
||||
import Form from 'vform'
|
||||
import { mapState } from 'vuex'
|
||||
import { useFormsStore } from '../../stores/forms'
|
||||
import { useWorkingFormStore } from '../../stores/working_form'
|
||||
import { useWorkspacesStore } from '../../stores/workspaces'
|
||||
import Breadcrumb from '../../components/common/Breadcrumb.vue'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
|
||||
const loadForms = function () {
|
||||
store.commit('open/forms/startLoading')
|
||||
store.dispatch('open/workspaces/loadIfEmpty').then(() => {
|
||||
store.dispatch('open/forms/load', store.state['open/workspaces'].currentId)
|
||||
const formsStore = useFormsStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
formsStore.startLoading()
|
||||
workspacesStore.loadIfEmpty().then(() => {
|
||||
formsStore.load(workspacesStore.currentId)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -32,12 +35,15 @@ export default {
|
|||
name: 'EditForm',
|
||||
components: { Breadcrumb },
|
||||
mixins: [SeoMeta],
|
||||
middleware: 'auth',
|
||||
|
||||
beforeRouteEnter (to, from, next) {
|
||||
if (!store.getters['open/forms/getBySlug'](to.params.slug)) {
|
||||
const formsStore = useFormsStore()
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
if (!formsStore.getBySlug(to.params.slug)) {
|
||||
loadForms()
|
||||
}
|
||||
store.commit('open/working_form/set', null) // Reset old working form
|
||||
workingFormStore.set(null) // Reset old working form
|
||||
next()
|
||||
},
|
||||
|
||||
|
@ -51,7 +57,17 @@ export default {
|
|||
next()
|
||||
},
|
||||
|
||||
middleware: 'auth',
|
||||
setup () {
|
||||
const formsStore = useFormsStore()
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
return {
|
||||
formsStore,
|
||||
workingFormStore,
|
||||
workspacesStore,
|
||||
formsLoading : computed(() => formsStore.loading)
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
|
@ -62,20 +78,17 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapState({
|
||||
formsLoading: state => state['open/forms'].loading
|
||||
}),
|
||||
updatedForm: {
|
||||
get () {
|
||||
return this.$store.state['open/working_form'].content
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
form () {
|
||||
return this.$store.getters['open/forms/getBySlug'](this.$route.params.slug)
|
||||
return this.formsStore.getBySlug(this.$route.params.slug)
|
||||
},
|
||||
pageLoaded () {
|
||||
return !this.loading && this.updatedForm !== null
|
||||
|
|
|
@ -50,8 +50,9 @@
|
|||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import store from '~/store'
|
||||
import { mapState } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useFormsStore } from '../../stores/forms'
|
||||
import { useRecordsStore } from '../../stores/records'
|
||||
import OpenCompleteForm from '../../components/open/forms/OpenCompleteForm.vue'
|
||||
import Cookies from 'js-cookie'
|
||||
import sha256 from 'js-sha256'
|
||||
|
@ -93,11 +94,12 @@ function handleTransparentMode (form) {
|
|||
}
|
||||
|
||||
function loadForm (slug) {
|
||||
if (store.state['open/forms'].loading) return
|
||||
store.commit('open/forms/startLoading')
|
||||
const formsStore = useFormsStore()
|
||||
if (formsStore.loading) return
|
||||
formsStore.startLoading()
|
||||
return axios.get('/api/forms/' + slug).then((response) => {
|
||||
const form = response.data
|
||||
store.commit('open/forms/set', [response.data])
|
||||
formsStore.set([response.data])
|
||||
|
||||
// Custom code injection
|
||||
if (form.custom_code) {
|
||||
|
@ -108,9 +110,9 @@ function loadForm (slug) {
|
|||
handleDarkMode(form)
|
||||
handleTransparentMode(form)
|
||||
|
||||
store.commit('open/forms/stopLoading')
|
||||
formsStore.stopLoading()
|
||||
}).catch(() => {
|
||||
store.commit('open/forms/stopLoading')
|
||||
formsStore.stopLoading()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -132,6 +134,17 @@ export default {
|
|||
next()
|
||||
},
|
||||
|
||||
setup () {
|
||||
const formsStore = useFormsStore()
|
||||
const recordsStore = useRecordsStore()
|
||||
return {
|
||||
formsStore,
|
||||
forms : computed(() => formsStore.content),
|
||||
formLoading : computed(() => formsStore.loading),
|
||||
recordLoading : computed(() => recordsStore.loading)
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
submitted: false
|
||||
|
@ -166,16 +179,11 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapState({
|
||||
forms: state => state['open/forms'].content,
|
||||
formLoading: state => state['open/forms'].loading,
|
||||
recordLoading: state => state['open/records'].loading
|
||||
}),
|
||||
formSlug () {
|
||||
return this.$route.params.slug
|
||||
},
|
||||
form () {
|
||||
return this.$store.getters['open/forms/getBySlug'](this.formSlug)
|
||||
return this.formsStore.getBySlug(this.formSlug)
|
||||
},
|
||||
isIframe () {
|
||||
return window.location !== window.parent.location || window.frameElement
|
||||
|
|
|
@ -116,10 +116,12 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import store from '~/store'
|
||||
import { computed } from 'vue'
|
||||
import Form from 'vform'
|
||||
import {mapGetters, mapState} from 'vuex'
|
||||
import { useAuthStore } from '../../../stores/auth'
|
||||
import { useFormsStore } from '../../../stores/forms'
|
||||
import { useWorkingFormStore } from '../../../stores/working_form'
|
||||
import { useWorkspacesStore } from '../../../stores/workspaces'
|
||||
import ProTag from '../../../components/common/ProTag.vue'
|
||||
import VButton from "../../../components/common/Button.vue";
|
||||
import ExtraMenu from '../../../components/pages/forms/show/ExtraMenu.vue'
|
||||
|
@ -127,9 +129,11 @@ import SeoMeta from '../../../mixins/seo-meta.js'
|
|||
import FormCleanings from '../../../components/pages/forms/show/FormCleanings.vue'
|
||||
|
||||
const loadForms = function () {
|
||||
store.commit('open/forms/startLoading')
|
||||
store.dispatch('open/workspaces/loadIfEmpty').then(() => {
|
||||
store.dispatch('open/forms/loadIfEmpty', store.state['open/workspaces'].currentId)
|
||||
const formsStore = useFormsStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
formsStore.startLoading()
|
||||
workspacesStore.loadIfEmpty().then(() => {
|
||||
formsStore.loadIfEmpty(workspacesStore.currentId)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -154,6 +158,21 @@ export default {
|
|||
},
|
||||
middleware: 'auth',
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const formsStore = useFormsStore()
|
||||
const workingFormStore = useWorkingFormStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
return {
|
||||
formsStore,
|
||||
workingFormStore,
|
||||
workspacesStore,
|
||||
user : computed(() => authStore.user),
|
||||
formsLoading : computed(() => formsStore.loading),
|
||||
workspacesLoading : computed(() => workspacesStore.loading)
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
metaTitle: 'Home',
|
||||
|
@ -175,27 +194,21 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
}),
|
||||
...mapState({
|
||||
formsLoading: state => state['open/forms'].loading,
|
||||
workspacesLoading: state => state['open/workspaces'].loading
|
||||
}),
|
||||
workingForm: {
|
||||
get() {
|
||||
return this.$store.state['open/working_form'].content
|
||||
get () {
|
||||
return this.workingFormStore.content
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('open/working_form/set', value)
|
||||
/* We add a setter */
|
||||
set (value) {
|
||||
this.workingFormStore.set(value)
|
||||
}
|
||||
},
|
||||
workspace() {
|
||||
if (!this.form) return null
|
||||
return this.$store.getters['open/workspaces/getById'](this.form.workspace_id)
|
||||
return this.workspacesStore.getById(this.form.workspace_id)
|
||||
},
|
||||
form() {
|
||||
return this.$store.getters['open/forms/getBySlug'](this.$route.params.slug)
|
||||
return this.formsStore.getBySlug(this.$route.params.slug)
|
||||
},
|
||||
formEndpoint: () => '/api/open/forms/{id}',
|
||||
loading() {
|
||||
|
|
|
@ -104,8 +104,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import store from '~/store'
|
||||
import { mapGetters, mapState } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../stores/auth';
|
||||
import { useFormsStore } from '../stores/forms';
|
||||
import { useWorkspacesStore } from '../stores/workspaces';
|
||||
import Fuse from 'fuse.js'
|
||||
import Form from 'vform'
|
||||
import TextInput from '../components/forms/TextInput.vue'
|
||||
|
@ -113,9 +115,11 @@ import OpenFormFooter from '../components/pages/OpenFormFooter.vue'
|
|||
import ExtraMenu from '../components/pages/forms/show/ExtraMenu.vue'
|
||||
|
||||
const loadForms = function () {
|
||||
store.commit('open/forms/startLoading')
|
||||
store.dispatch('open/workspaces/loadIfEmpty').then(() => {
|
||||
store.dispatch('open/forms/loadIfEmpty', store.state['open/workspaces'].currentId)
|
||||
const formsStore = useFormsStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
formsStore.startLoading()
|
||||
workspacesStore.loadIfEmpty().then(() => {
|
||||
formsStore.loadIfEmpty(workspacesStore.currentId)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -133,6 +137,19 @@ export default {
|
|||
metaDescription: { type: String, default: 'All of your OpnForm are here. Create new forms, or update your existing one!' }
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const formsStore = useFormsStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
return {
|
||||
formsStore,
|
||||
workspacesStore,
|
||||
user : computed(() => authStore.user),
|
||||
forms : computed(() => formsStore.content),
|
||||
formsLoading : computed(() => formsStore.loading)
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
showEditFormModal: false,
|
||||
|
@ -165,19 +182,12 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
}),
|
||||
...mapState({
|
||||
forms: state => state['open/forms'].content,
|
||||
formsLoading: state => state['open/forms'].loading
|
||||
}),
|
||||
isFilteringForms () {
|
||||
return (this.searchForm.search !== '' && this.searchForm.search !== null) || this.selectedTags.length > 0
|
||||
},
|
||||
enrichedForms () {
|
||||
let enrichedForms = this.forms.map((form) => {
|
||||
form.workspace = this.$store.getters['open/workspaces/getById'](form.workspace_id)
|
||||
form.workspace = this.workspacesStore.getById(form.workspace_id)
|
||||
return form
|
||||
})
|
||||
|
||||
|
@ -206,7 +216,7 @@ export default {
|
|||
})
|
||||
},
|
||||
allTags () {
|
||||
return this.$store.getters['open/forms/getAllTags']
|
||||
return this.formsStore.getAllTags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -236,14 +236,14 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters} from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../stores/auth';
|
||||
import OpenFormFooter from '../components/pages/OpenFormFooter.vue'
|
||||
import PricingTable from '../components/pages/pricing/PricingTable.vue'
|
||||
import SeoMeta from '../mixins/seo-meta.js'
|
||||
|
||||
export default {
|
||||
components: {OpenFormFooter, PricingTable},
|
||||
|
||||
mixins: [SeoMeta],
|
||||
layout: 'default',
|
||||
|
||||
|
@ -257,20 +257,23 @@ export default {
|
|||
next()
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
user : computed(() => authStore.user),
|
||||
authenticated : computed(() => authStore.check)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
metaTitle: 'Pricing',
|
||||
metaDescription: 'All of our core features are free, and there is no quantity limit. You can also created more advanced and customized forms with OpnForms Pro.',
|
||||
}),
|
||||
|
||||
mounted() {
|
||||
},
|
||||
mounted() {},
|
||||
|
||||
computed: {},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
authenticated: 'auth/check',
|
||||
user: 'auth/user'
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
contactUs() {
|
||||
window.$crisp.push(['do', 'chat:show'])
|
||||
|
|
|
@ -18,12 +18,20 @@
|
|||
<script>
|
||||
import Form from 'vform'
|
||||
import axios from 'axios'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
|
||||
export default {
|
||||
scrollToTop: false,
|
||||
mixins: [SeoMeta],
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
authStore
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
metaTitle: 'Account',
|
||||
form: new Form({
|
||||
|
@ -39,7 +47,7 @@ export default {
|
|||
this.loading = false
|
||||
this.alertSuccess(response.data.message)
|
||||
// Log out the user.
|
||||
await this.$store.dispatch('auth/logout')
|
||||
await this.authStore.logout()
|
||||
|
||||
// Redirect to login.
|
||||
this.$router.push({ name: 'login' })
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
<script>
|
||||
import Form from 'vform'
|
||||
import axios from 'axios'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
import { useWorkspacesStore } from '../../stores/workspaces'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
|
||||
export default {
|
||||
|
@ -45,6 +47,15 @@ export default {
|
|||
scrollToTop: false,
|
||||
mixins: [SeoMeta],
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
return {
|
||||
authStore,
|
||||
workspacesStore
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
metaTitle: 'Admin',
|
||||
form: new Form({
|
||||
|
@ -56,21 +67,18 @@ export default {
|
|||
methods: {
|
||||
async impersonate () {
|
||||
this.loading = true
|
||||
this.$store.commit('auth/startImpersonating')
|
||||
this.authStore.startImpersonating()
|
||||
axios.get('/api/admin/impersonate/' + encodeURI(this.form.identifier)).then(async (response) => {
|
||||
this.loading = false
|
||||
|
||||
// Save the token.
|
||||
this.$store.dispatch('auth/saveToken', {
|
||||
token: response.data.token,
|
||||
remember: false
|
||||
})
|
||||
this.authStore.saveToken(response.data.token, false)
|
||||
|
||||
// Fetch the user.
|
||||
await this.$store.dispatch('auth/fetchUser')
|
||||
await this.authStore.fetchUser()
|
||||
|
||||
// Redirect to the dashboard.
|
||||
this.$store.commit('open/workspaces/set', [])
|
||||
this.workspacesStore.set([])
|
||||
this.$router.push({ name: 'home' })
|
||||
}).catch((error) => {
|
||||
this.alertError(error.response.data.message)
|
||||
|
|
|
@ -21,9 +21,10 @@
|
|||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
import VButton from '../../components/common/Button.vue'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
import { mapGetters } from 'vuex'
|
||||
import AppSumoBilling from '../../components/vendor/appsumo/AppSumoBilling.vue'
|
||||
|
||||
export default {
|
||||
|
@ -31,6 +32,13 @@ export default {
|
|||
mixins: [SeoMeta],
|
||||
scrollToTop: false,
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
user : computed(() => authStore.user)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
metaTitle: 'Billing',
|
||||
billingLoading: false
|
||||
|
@ -50,10 +58,6 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
})
|
||||
}
|
||||
computed: {}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -38,20 +38,25 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
|
||||
export default {
|
||||
middleware: 'auth',
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
user : computed(() => authStore.user)
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
user: 'auth/user'
|
||||
}),
|
||||
tabsList () {
|
||||
const tabs = [
|
||||
{
|
||||
|
|
|
@ -24,13 +24,22 @@
|
|||
|
||||
<script>
|
||||
import Form from 'vform'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
|
||||
export default {
|
||||
mixins: [SeoMeta],
|
||||
scrollToTop: false,
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
authStore,
|
||||
user : computed(() => authStore.user)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
metaTitle: 'Profile',
|
||||
form: new Form({
|
||||
|
@ -39,10 +48,6 @@ export default {
|
|||
})
|
||||
}),
|
||||
|
||||
computed: mapGetters({
|
||||
user: 'auth/user'
|
||||
}),
|
||||
|
||||
created () {
|
||||
// Fill the form with user data.
|
||||
this.form.keys().forEach(key => {
|
||||
|
@ -54,7 +59,7 @@ export default {
|
|||
async update () {
|
||||
const { data } = await this.form.patch('/api/settings/profile')
|
||||
|
||||
this.$store.dispatch('auth/updateUser', { user: data })
|
||||
this.authStore.updateUser(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,8 +73,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from 'vue'
|
||||
import Form from 'vform'
|
||||
import {mapActions, mapState} from 'vuex'
|
||||
import { useFormsStore } from '../../stores/forms'
|
||||
import { useWorkspacesStore } from '../../stores/workspaces'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
|
||||
export default {
|
||||
|
@ -82,6 +84,17 @@ export default {
|
|||
scrollToTop: false,
|
||||
mixins: [SeoMeta],
|
||||
|
||||
setup () {
|
||||
const formsStore = useFormsStore()
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
return {
|
||||
formsStore,
|
||||
workspacesStore,
|
||||
workspaces: computed(() => workspacesStore.content),
|
||||
loading: computed(() => workspacesStore.loading)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
metaTitle: 'Workspaces',
|
||||
form: new Form({
|
||||
|
@ -92,28 +105,20 @@ export default {
|
|||
}),
|
||||
|
||||
mounted() {
|
||||
this.loadWorkspaces()
|
||||
this.workspacesStore.loadIfEmpty()
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState({
|
||||
workspaces: state => state['open/workspaces'].content,
|
||||
loading: state => state['open/workspaces'].loading
|
||||
})
|
||||
},
|
||||
computed: {},
|
||||
|
||||
methods: {
|
||||
...mapActions({
|
||||
loadWorkspaces: 'open/workspaces/loadIfEmpty'
|
||||
}),
|
||||
switchWorkspace(workspace) {
|
||||
this.$store.commit('open/workspaces/setCurrentId', workspace.id)
|
||||
this.workspacesStore.setCurrentId(workspace.id)
|
||||
this.$router.push({name: 'home'})
|
||||
this.$store.dispatch('open/forms/load', workspace.id)
|
||||
this.formsStore.load(workspace.id)
|
||||
},
|
||||
deleteWorkspace(workspace) {
|
||||
this.alertConfirm('Do you really want to delete this workspace? All forms created in this workspace will be removed.', () => {
|
||||
this.$store.dispatch('open/workspaces/delete', workspace.id).then(() => {
|
||||
this.workspacesStore.delete(workspace.id).then(() => {
|
||||
this.alertSuccess('Workspace successfully removed.')
|
||||
})
|
||||
})
|
||||
|
@ -129,7 +134,7 @@ export default {
|
|||
},
|
||||
async createWorkspace() {
|
||||
const {data} = await this.form.post('/api/open/workspaces/create')
|
||||
this.$store.dispatch('open/workspaces/load')
|
||||
this.workspacesStore.load()
|
||||
this.workspaceModal = false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<template />
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
|
||||
export default {
|
||||
|
@ -10,6 +11,13 @@ export default {
|
|||
middleware: 'auth',
|
||||
mixins: [SeoMeta],
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
authenticated : computed(() => authStore.check),
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
metaTitle: 'Error',
|
||||
}),
|
||||
|
@ -19,10 +27,6 @@ export default {
|
|||
this.alertError('Unfortunately we could not confirm your subscription. Please try again and contact us if the issue persists.')
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
authenticated: 'auth/check'
|
||||
})
|
||||
}
|
||||
computed: {}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
import OpenFormFooter from '../../components/pages/OpenFormFooter.vue'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
|
||||
|
@ -26,6 +27,15 @@ export default {
|
|||
layout: 'default',
|
||||
middleware: 'auth',
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
authStore,
|
||||
authenticated : computed(() => authStore.check),
|
||||
user : computed(() => authStore.user)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
metaTitle: 'Subscription Success',
|
||||
interval: null
|
||||
|
@ -43,7 +53,7 @@ export default {
|
|||
methods: {
|
||||
async checkSubscription () {
|
||||
// Fetch the user.
|
||||
await this.$store.dispatch('auth/fetchUser')
|
||||
await this.authStore.fetchUser()
|
||||
this.redirectIfSubscribed()
|
||||
},
|
||||
redirectIfSubscribed () {
|
||||
|
@ -63,11 +73,6 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
authenticated: 'auth/check',
|
||||
user: 'auth/user'
|
||||
})
|
||||
}
|
||||
computed: {}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -93,19 +93,21 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import store from '~/store'
|
||||
import Form from 'vform'
|
||||
import Fuse from 'fuse.js'
|
||||
import { mapGetters, mapState } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
import { useTemplatesStore } from '../../stores/templates'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
import OpenFormFooter from '../../components/pages/OpenFormFooter.vue'
|
||||
import Breadcrumb from '../../components/common/Breadcrumb.vue'
|
||||
import SingleTemplate from '../../components/pages/templates/SingleTemplate.vue'
|
||||
|
||||
const loadTemplates = function () {
|
||||
store.commit('open/templates/startLoading')
|
||||
store.dispatch('open/templates/loadIfEmpty').then(() => {
|
||||
store.commit('open/templates/stopLoading')
|
||||
const templatesStore = useTemplatesStore()
|
||||
templatesStore.startLoading()
|
||||
templatesStore.loadIfEmpty().then(() => {
|
||||
templatesStore.stopLoading()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -118,6 +120,20 @@ export default {
|
|||
next()
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const templatesStore = useTemplatesStore()
|
||||
return {
|
||||
authStore,
|
||||
authenticated : computed(() => authStore.check),
|
||||
user : computed(() => authStore.user),
|
||||
templates : computed(() => templatesStore.content),
|
||||
templatesLoading : computed(() => templatesStore.loading),
|
||||
industries : computed(() => templatesStore.industries),
|
||||
types : computed(() => templatesStore.types)
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
selectedType: 'all',
|
||||
|
@ -130,16 +146,6 @@ export default {
|
|||
mounted () {},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
authenticated: 'auth/check',
|
||||
user: 'auth/user'
|
||||
}),
|
||||
...mapState({
|
||||
templates: state => state['open/templates'].content,
|
||||
templatesLoading: state => state['open/templates'].loading,
|
||||
industries: state => state['open/templates'].industries,
|
||||
types: state => state['open/templates'].types
|
||||
}),
|
||||
breadcrumbs () {
|
||||
if (!this.industry) {
|
||||
return [{ route: { name: 'templates' }, label: 'Templates' }]
|
||||
|
|
|
@ -196,9 +196,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import store from '~/store'
|
||||
import Form from 'vform'
|
||||
import { mapGetters, mapState } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
import { useTemplatesStore } from '../../stores/templates'
|
||||
import OpenFormFooter from '../../components/pages/OpenFormFooter.vue'
|
||||
import OpenCompleteForm from '../../components/open/forms/OpenCompleteForm.vue'
|
||||
import Breadcrumb from '../../components/common/Breadcrumb.vue'
|
||||
|
@ -213,21 +214,32 @@ export default {
|
|||
mixins: [SeoMeta],
|
||||
|
||||
beforeRouteEnter (to, from, next) {
|
||||
const templatesStore = useTemplatesStore()
|
||||
if (to.params?.slug) {
|
||||
store.dispatch('open/templates/loadTemplate', to.params?.slug)
|
||||
store.dispatch('open/templates/loadTypesAndIndustries')
|
||||
templatesStore.loadTemplate(to.params?.slug)
|
||||
templatesStore.loadTypesAndIndustries()
|
||||
}
|
||||
next()
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const templatesStore = useTemplatesStore()
|
||||
return {
|
||||
templatesStore,
|
||||
authenticated : computed(() => authStore.check),
|
||||
user : computed(() => authStore.user),
|
||||
templatesLoading : computed(() => templatesStore.loading)
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
showFormTemplateModal: false
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
},
|
||||
mounted () {},
|
||||
|
||||
methods: {
|
||||
cleanQuotes (str) {
|
||||
|
@ -247,13 +259,6 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
authenticated: 'auth/check',
|
||||
user: 'auth/user'
|
||||
}),
|
||||
...mapState({
|
||||
templatesLoading: state => state['open/templates'].loading
|
||||
}),
|
||||
breadcrumbs () {
|
||||
if (!this.template) {
|
||||
return [{ route: { name: 'templates' }, label: 'Templates' }]
|
||||
|
@ -261,7 +266,7 @@ export default {
|
|||
return [{ route: { name: 'templates' }, label: 'Templates' }, { label: this.template.name }]
|
||||
},
|
||||
template () {
|
||||
return this.$store.getters['open/templates/getBySlug'](this.$route.params.slug)
|
||||
return this.templatesStore.getBySlug(this.$route.params.slug)
|
||||
},
|
||||
form () {
|
||||
return this.template ? new Form(this.template.structure) : null
|
||||
|
|
|
@ -93,19 +93,21 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import store from '~/store'
|
||||
import Form from 'vform'
|
||||
import Fuse from 'fuse.js'
|
||||
import { mapGetters, mapState } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../../stores/auth'
|
||||
import { useTemplatesStore } from '../../stores/templates'
|
||||
import SeoMeta from '../../mixins/seo-meta.js'
|
||||
import OpenFormFooter from '../../components/pages/OpenFormFooter.vue'
|
||||
import Breadcrumb from '../../components/common/Breadcrumb.vue'
|
||||
import SingleTemplate from '../../components/pages/templates/SingleTemplate.vue'
|
||||
|
||||
const loadTemplates = function () {
|
||||
store.commit('open/templates/startLoading')
|
||||
store.dispatch('open/templates/loadIfEmpty').then(() => {
|
||||
store.commit('open/templates/stopLoading')
|
||||
const templatesStore = useTemplatesStore()
|
||||
templatesStore.startLoading()
|
||||
templatesStore.loadIfEmpty().then(() => {
|
||||
templatesStore.stopLoading()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -118,6 +120,19 @@ export default {
|
|||
next()
|
||||
},
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
const templatesStore = useTemplatesStore()
|
||||
return {
|
||||
authenticated : computed(() => authStore.check),
|
||||
user : computed(() => authStore.user),
|
||||
templates : computed(() => templatesStore.content),
|
||||
templatesLoading : computed(() => templatesStore.loading),
|
||||
industries : computed(() => templatesStore.industries),
|
||||
types : computed(() => templatesStore.types)
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
selectedIndustry: 'all',
|
||||
|
@ -130,16 +145,6 @@ export default {
|
|||
mounted () {},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
authenticated: 'auth/check',
|
||||
user: 'auth/user'
|
||||
}),
|
||||
...mapState({
|
||||
templates: state => state['open/templates'].content,
|
||||
templatesLoading: state => state['open/templates'].loading,
|
||||
industries: state => state['open/templates'].industries,
|
||||
types: state => state['open/templates'].types
|
||||
}),
|
||||
breadcrumbs () {
|
||||
if (!this.type) {
|
||||
return [{ route: { name: 'templates' }, label: 'Templates' }]
|
||||
|
|
|
@ -181,7 +181,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
import Features from '~/components/pages/welcome/Features.vue'
|
||||
import MoreFeatures from '~/components/pages/welcome/MoreFeatures.vue'
|
||||
import PricingTable from '../components/pages/pricing/PricingTable.vue'
|
||||
|
@ -193,11 +194,16 @@ import SeoMeta from '../mixins/seo-meta.js'
|
|||
|
||||
export default {
|
||||
components: { Testimonials, OpenFormFooter, Features, MoreFeatures, PricingTable, AiFeature, TemplatesSlider },
|
||||
|
||||
mixins: [SeoMeta],
|
||||
|
||||
layout: 'default',
|
||||
|
||||
setup () {
|
||||
const authStore = useAuthStore()
|
||||
return {
|
||||
authenticated : computed(() => authStore.check)
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
title: window.config.appName,
|
||||
metaTitle: 'Create beautiful & open-source forms for free'
|
||||
|
@ -215,9 +221,6 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
authenticated: 'auth/check'
|
||||
}),
|
||||
configLinks: () => window.config.links,
|
||||
paidPlansEnabled () {
|
||||
return window.config.paid_plans_enabled
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import axios from 'axios'
|
||||
import store from '~/store'
|
||||
import { useAuthStore } from '../stores/auth';
|
||||
import router from '~/router'
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
|
@ -17,16 +17,13 @@ function addPasswordToFormRequest (request) {
|
|||
|
||||
// Request interceptor
|
||||
axios.interceptors.request.use(request => {
|
||||
const token = store.getters['auth/token']
|
||||
const authStore = useAuthStore()
|
||||
const token = authStore.token
|
||||
if (token) {
|
||||
request.headers.common.Authorization = `Bearer ${token}`
|
||||
}
|
||||
|
||||
const locale = store.getters['lang/locale']
|
||||
if (locale) {
|
||||
request.headers.common['Accept-Language'] = locale
|
||||
}
|
||||
|
||||
request.headers.common['Accept-Language'] = 'en-US'
|
||||
// request.headers['X-Socket-Id'] = Echo.socketId()
|
||||
|
||||
request = addPasswordToFormRequest(request)
|
||||
|
@ -36,14 +33,14 @@ axios.interceptors.request.use(request => {
|
|||
|
||||
// Response interceptor
|
||||
axios.interceptors.response.use(response => response, error => {
|
||||
const authStore = useAuthStore()
|
||||
const { status } = error.response
|
||||
if (status >= 500) {
|
||||
console.log(status)
|
||||
}
|
||||
|
||||
if (status === 401 && store.getters['auth/check']) {
|
||||
store.commit('auth/LOGOUT')
|
||||
|
||||
if (status === 401 && authStore.check) {
|
||||
authStore.logout()
|
||||
router.push({ name: 'login' })
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import routes from './routes'
|
||||
import { createWebHistory, createRouter } from 'vue-router'
|
||||
import * as Sentry from '@sentry/vue'
|
||||
import store from '../store'
|
||||
import { useAppStore } from '../stores/app'
|
||||
import { defineComponent, nextTick } from 'vue'
|
||||
|
||||
// The middleware for every page of the application.
|
||||
|
@ -45,6 +45,8 @@ async function getMatchedComponents (to) {
|
|||
* @param {Function} next
|
||||
*/
|
||||
async function beforeEach (to, from, next) {
|
||||
const appStore = useAppStore()
|
||||
|
||||
// Sentry tracking
|
||||
if (window.config.sentry_dsn) {
|
||||
Sentry.configureScope((scope) => scope.setTransactionName(to?.name || 'Unknown route name'))
|
||||
|
@ -75,7 +77,7 @@ async function beforeEach (to, from, next) {
|
|||
|
||||
// Start the loading bar.
|
||||
if (components[components.length - 1].loading !== false) {
|
||||
nextTick(() => store.commit('app/loaderStart'))
|
||||
nextTick(() => appStore.loaderStart())
|
||||
}
|
||||
|
||||
// Get the middleware for all the matched components.
|
||||
|
@ -86,11 +88,11 @@ async function beforeEach (to, from, next) {
|
|||
// Set the application layout only if "next()" was called with no args.
|
||||
if (args.length === 0) {
|
||||
if (components[0].layout) {
|
||||
store.commit('app/setLayout', components[0].layout)
|
||||
appStore.setLayout(components[0].layout)
|
||||
} else if (components[0].default && components[0].default.layout) {
|
||||
store.commit('app/setLayout', components[0].default.layout)
|
||||
appStore.setLayout(components[0].default.layout)
|
||||
} else {
|
||||
store.commit('app/setLayout', null)
|
||||
appStore.setLayout(null)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +108,8 @@ async function beforeEach (to, from, next) {
|
|||
* @param {Function} next
|
||||
*/
|
||||
async function afterEach (to, from, next) {
|
||||
nextTick(() => store.commit('app/loaderFinish'))
|
||||
const appStore = useAppStore()
|
||||
nextTick(() => appStore.loaderFinish())
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,13 +121,14 @@ async function afterEach (to, from, next) {
|
|||
* @param {Function} next
|
||||
*/
|
||||
function callMiddleware (middleware, to, from, next) {
|
||||
const appStore = useAppStore()
|
||||
const stack = middleware.reverse()
|
||||
|
||||
const _next = (...args) => {
|
||||
// Stop if "_next" was called with an argument or the stack is empty.
|
||||
if (args.length > 0 || stack.length === 0) {
|
||||
if (args.length > 0) {
|
||||
store.commit('app/loaderFinish')
|
||||
appStore.loaderFinish()
|
||||
}
|
||||
|
||||
return next(...args)
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
// Load store modules dynamically.
|
||||
const requireContext = import.meta.glob('./modules/**/*.js', {eager: true})
|
||||
const modules = Object.keys(requireContext)
|
||||
|
||||
.map(file =>
|
||||
[file.replace(/(^.\/)|(\.js$)/g, '').replace('modules/',''), requireContext[file]]
|
||||
)
|
||||
.reduce((modules, [name, module]) => {
|
||||
if (module.namespaced === undefined) {
|
||||
module = {...module, namespaced: true}
|
||||
}
|
||||
|
||||
return { ...modules, [name]: module }
|
||||
}, {})
|
||||
export default new Vuex.Store({
|
||||
modules
|
||||
})
|
|
@ -1,73 +0,0 @@
|
|||
import { nextTick } from 'vue'
|
||||
|
||||
export const state = {
|
||||
layout: 'default',
|
||||
|
||||
// App Loader
|
||||
loader: {
|
||||
percent: 0,
|
||||
show: false,
|
||||
canSuccess: true,
|
||||
duration: 3000,
|
||||
_timer: null,
|
||||
_cut: null
|
||||
}
|
||||
}
|
||||
|
||||
export const mutations = {
|
||||
setLayout (state, layout) {
|
||||
state.layout = layout ?? 'default'
|
||||
},
|
||||
loaderStart (state) {
|
||||
state.loader.show = true
|
||||
state.loader.canSuccess = true
|
||||
if (state.loader._timer) {
|
||||
clearInterval(state.loader._timer)
|
||||
state.loader.percent = 0
|
||||
}
|
||||
state.loader._cut = 10000 / Math.floor(state.loader.duration)
|
||||
},
|
||||
loaderIncrease (state, num) {
|
||||
state.loader.percent = state.loader.percent + Math.floor(num)
|
||||
},
|
||||
loaderDecrease (state, num) {
|
||||
state.loader.percent = state.loader.percent - Math.floor(num)
|
||||
},
|
||||
loaderFinish (state) {
|
||||
state.loader.percent = 100
|
||||
mutations.loaderHide(state)
|
||||
},
|
||||
loaderSetTimer (state, timerVal) {
|
||||
state._timer = timerVal
|
||||
},
|
||||
loaderPause (state) {
|
||||
clearInterval(state.loader._timer)
|
||||
},
|
||||
loaderHide (state) {
|
||||
clearInterval(state.loader._timer)
|
||||
state.loader._timer = null
|
||||
setTimeout(() => {
|
||||
state.loader.show = false
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
state.loader.percent = 0
|
||||
}, 200)
|
||||
})
|
||||
}, 500)
|
||||
},
|
||||
loaderFail () {
|
||||
state.loader.canSuccess = false
|
||||
}
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
loaderStart ({ commit, dispatch }) {
|
||||
mutations.loaderStart()
|
||||
mutations.loaderSetTimer(setInterval(() => {
|
||||
mutations.loaderIncrease(state.loader._cut * Math.random())
|
||||
if (state.loader.percent > 95) {
|
||||
mutations.loaderFinish()
|
||||
}
|
||||
}, 100))
|
||||
}
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
import axios from 'axios'
|
||||
import Cookies from 'js-cookie'
|
||||
import * as types from '../mutation-types'
|
||||
|
||||
// state
|
||||
export const state = {
|
||||
user: null,
|
||||
token: Cookies.get('token'),
|
||||
|
||||
// For admin impersonation
|
||||
admin_token: Cookies.get('admin_token') ?? null
|
||||
}
|
||||
|
||||
// getters
|
||||
export const getters = {
|
||||
user: state => state.user,
|
||||
token: state => state.token,
|
||||
check: state => state.user !== null,
|
||||
isImpersonating: state => state.admin_token !== null
|
||||
}
|
||||
|
||||
// mutations
|
||||
export const mutations = {
|
||||
[types.SAVE_TOKEN] (state, { token, remember }) {
|
||||
state.token = token
|
||||
Cookies.set('token', token, { expires: remember ? 365 : null })
|
||||
},
|
||||
|
||||
[types.FETCH_USER_SUCCESS] (state, { user }) {
|
||||
state.user = user
|
||||
},
|
||||
|
||||
[types.FETCH_USER_FAILURE] (state) {
|
||||
state.token = null
|
||||
Cookies.remove('token')
|
||||
},
|
||||
|
||||
[types.LOGOUT] (state) {
|
||||
state.user = null
|
||||
state.token = null
|
||||
|
||||
Cookies.remove('token')
|
||||
},
|
||||
|
||||
[types.UPDATE_USER] (state, { user }) {
|
||||
state.user = user
|
||||
},
|
||||
|
||||
// Stores admin token temporarily for impersonation
|
||||
startImpersonating (state) {
|
||||
state.admin_token = state.token
|
||||
Cookies.set('admin_token', state.token, { expires: 365 })
|
||||
},
|
||||
|
||||
// Stores admin token temporarily for impersonation
|
||||
stopImpersonating (state) {
|
||||
state.token = state.admin_token
|
||||
state.admin_token = null
|
||||
Cookies.set('token', state.token, { expires: 365 })
|
||||
Cookies.remove('admin_token')
|
||||
}
|
||||
}
|
||||
|
||||
// actions
|
||||
export const actions = {
|
||||
saveToken ({ commit, dispatch }, payload) {
|
||||
commit(types.SAVE_TOKEN, payload)
|
||||
},
|
||||
|
||||
async fetchUser ({ commit }) {
|
||||
try {
|
||||
const { data } = await axios.get('/api/user')
|
||||
|
||||
commit(types.FETCH_USER_SUCCESS, { user: data })
|
||||
return data
|
||||
} catch (e) {
|
||||
commit(types.FETCH_USER_FAILURE)
|
||||
}
|
||||
},
|
||||
|
||||
updateUser ({ commit }, payload) {
|
||||
commit(types.UPDATE_USER, payload)
|
||||
},
|
||||
|
||||
async logout ({ commit }) {
|
||||
try {
|
||||
await axios.post('/api/logout')
|
||||
} catch (e) { }
|
||||
|
||||
commit(types.LOGOUT)
|
||||
},
|
||||
|
||||
async fetchOauthUrl (ctx, { provider }) {
|
||||
const { data } = await axios.post(`/api/oauth/${provider}`)
|
||||
|
||||
return data.url
|
||||
},
|
||||
|
||||
// Reverse admin impersonation
|
||||
stopImpersonating ({ commit, dispatch }, payload) {
|
||||
commit('stopImpersonating')
|
||||
return dispatch('fetchUser')
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
import Vue from 'vue'
|
||||
|
||||
export const namespaced = true
|
||||
|
||||
// state
|
||||
export const state = {
|
||||
content: []
|
||||
}
|
||||
|
||||
// getters
|
||||
export const getters = {
|
||||
getById: (state) => (id) => {
|
||||
if (state.content.length === 0) return null
|
||||
return state.content.find(item => item.id === id)
|
||||
}
|
||||
}
|
||||
|
||||
// mutations
|
||||
export const mutations = {
|
||||
set (state, items) {
|
||||
state.content = items
|
||||
},
|
||||
addOrUpdate (state, item) {
|
||||
state.content = state.content.filter((val) => val.id !== item.id)
|
||||
state.content.push(item)
|
||||
},
|
||||
remove (state, item) {
|
||||
state.content = state.content.filter((val) => val.id !== item.id)
|
||||
}
|
||||
}
|
||||
|
||||
// actions
|
||||
export const actions = {
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
import Vue from 'vue'
|
||||
|
||||
export const namespaced = true
|
||||
|
||||
// state
|
||||
export const state = {
|
||||
content: null
|
||||
}
|
||||
|
||||
// getters
|
||||
export const getters = {
|
||||
}
|
||||
|
||||
// mutations
|
||||
export const mutations = {
|
||||
set (state, error) {
|
||||
state.content = error
|
||||
},
|
||||
clear (state) {
|
||||
state.content = null
|
||||
}
|
||||
}
|
||||
|
||||
// actions
|
||||
export const actions = {
|
||||
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
import axios from 'axios'
|
||||
|
||||
export const formsEndpoint = '/api/open/workspaces/{workspaceId}/forms'
|
||||
export const namespaced = true
|
||||
export let currentPage = 1
|
||||
|
||||
// state
|
||||
export const state = {
|
||||
content: [],
|
||||
loading: false
|
||||
}
|
||||
|
||||
// getters
|
||||
export const getters = {
|
||||
getById: (state) => (id) => {
|
||||
if (state.content.length === 0) return null
|
||||
return state.content.find(item => item.id === id)
|
||||
},
|
||||
getBySlug: (state) => (slug) => {
|
||||
if (state.content.length === 0) return null
|
||||
return state.content.find(item => item.slug === slug)
|
||||
},
|
||||
getAllTags: (state) => {
|
||||
if (state.content.length === 0) return []
|
||||
let allTags = []
|
||||
state.content.forEach(form => {
|
||||
if(form.tags && form.tags.length > 0){
|
||||
allTags = allTags.concat(form.tags)
|
||||
}
|
||||
})
|
||||
return allTags.filter((item, i, ar) => ar.indexOf(item) === i)
|
||||
}
|
||||
}
|
||||
|
||||
// mutations
|
||||
export const mutations = {
|
||||
set (state, items) {
|
||||
state.content = items
|
||||
},
|
||||
append (state, items) {
|
||||
state.content = state.content.concat(items)
|
||||
},
|
||||
addOrUpdate (state, item) {
|
||||
state.content = state.content.filter((val) => val.id !== item.id)
|
||||
state.content.push(item)
|
||||
},
|
||||
remove (state, item) {
|
||||
state.content = state.content.filter((val) => val.id !== item.id)
|
||||
},
|
||||
startLoading (state) {
|
||||
state.loading = true
|
||||
},
|
||||
stopLoading (state) {
|
||||
state.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
// actions
|
||||
export const actions = {
|
||||
resetState (context) {
|
||||
context.commit('set', [])
|
||||
context.commit('stopLoading')
|
||||
currentPage = 1
|
||||
},
|
||||
load (context, workspaceId) {
|
||||
context.commit('startLoading')
|
||||
return axios.get(formsEndpoint.replace('{workspaceId}', workspaceId)+'?page='+currentPage).then((response) => {
|
||||
context.commit((currentPage == 1) ? 'set' : 'append', response.data.data)
|
||||
if (currentPage < response.data.meta.last_page) {
|
||||
currentPage += 1
|
||||
context.dispatch('load', workspaceId)
|
||||
} else {
|
||||
context.commit('stopLoading')
|
||||
currentPage = 1
|
||||
}
|
||||
})
|
||||
},
|
||||
loadIfEmpty (context, workspaceId) {
|
||||
if (context.state.content.length === 0) {
|
||||
return context.dispatch('load', workspaceId)
|
||||
}
|
||||
context.commit('stopLoading')
|
||||
return Promise.resolve()
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
import axios from 'axios'
|
||||
|
||||
export const namespaced = true
|
||||
export const workspaceEndpoint = '/api/open/records/'
|
||||
|
||||
/**
|
||||
* Loads records from database
|
||||
*/
|
||||
|
||||
// state
|
||||
export const state = {
|
||||
content: [],
|
||||
loading: false
|
||||
}
|
||||
|
||||
// getters
|
||||
export const getters = {
|
||||
getById: (state) => (id) => {
|
||||
if (state.content.length === 0) return null
|
||||
return state.content.find(item => item.submission_id === id)
|
||||
}
|
||||
}
|
||||
|
||||
// mutations
|
||||
export const mutations = {
|
||||
set (state, items) {
|
||||
state.content = items
|
||||
},
|
||||
addOrUpdate (state, item) {
|
||||
state.content = state.content.filter((val) => val.id !== item.id)
|
||||
state.content.push(item)
|
||||
},
|
||||
remove (state, itemId) {
|
||||
state.content = state.content.filter((val) => val.id !== itemId)
|
||||
},
|
||||
startLoading () {
|
||||
state.loading = true
|
||||
},
|
||||
stopLoading () {
|
||||
state.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
// actions
|
||||
export const actions = {
|
||||
resetState (context) {
|
||||
context.commit('set', [])
|
||||
context.commit('stopLoading')
|
||||
},
|
||||
loadRecord (context, request) {
|
||||
context.commit('set', [])
|
||||
context.commit('startLoading')
|
||||
return request.then((data) => {
|
||||
context.commit('addOrUpdate', data)
|
||||
context.commit('stopLoading')
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
import axios from 'axios'
|
||||
|
||||
export const templatesEndpoint = '/api/templates'
|
||||
export const namespaced = true
|
||||
|
||||
// state
|
||||
export const state = {
|
||||
content: [],
|
||||
industries: {},
|
||||
types: {},
|
||||
allLoaded: false,
|
||||
loading: false
|
||||
}
|
||||
|
||||
// getters
|
||||
export const 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 })
|
||||
}
|
||||
}
|
||||
|
||||
// mutations
|
||||
export const mutations = {
|
||||
set (state, items) {
|
||||
state.content = items
|
||||
state.allLoaded = true
|
||||
},
|
||||
append (state, items) {
|
||||
const ids = items.map((item) => { return item.id })
|
||||
state.content = state.content.filter((val) => !ids.includes(val.id))
|
||||
state.content = state.content.concat(items)
|
||||
},
|
||||
addOrUpdate (state, item) {
|
||||
state.content = state.content.filter((val) => val.id !== item.id)
|
||||
state.content.push(item)
|
||||
},
|
||||
remove (state, item) {
|
||||
state.content = state.content.filter((val) => val.id !== item.id)
|
||||
},
|
||||
startLoading (state) {
|
||||
state.loading = true
|
||||
},
|
||||
stopLoading (state) {
|
||||
state.loading = false
|
||||
},
|
||||
setAllLoaded (state, val) {
|
||||
state.allLoaded = val
|
||||
}
|
||||
}
|
||||
|
||||
// actions
|
||||
export const actions = {
|
||||
resetState (context) {
|
||||
context.commit('set', [])
|
||||
context.commit('stopLoading')
|
||||
},
|
||||
loadTypesAndIndustries (context) {
|
||||
if (Object.keys(context.state.industries).length === 0) {
|
||||
import('@/data/forms/templates/industries.json').then((module) => {
|
||||
context.state.industries = module.default
|
||||
})
|
||||
}
|
||||
if (Object.keys(context.state.types).length === 0) {
|
||||
import('@/data/forms/templates/types.json').then((module) => {
|
||||
context.state.types = module.default
|
||||
})
|
||||
}
|
||||
},
|
||||
loadTemplate (context, slug) {
|
||||
context.commit('startLoading')
|
||||
context.dispatch('loadTypesAndIndustries')
|
||||
|
||||
if (context.getters.getBySlug(slug)) {
|
||||
context.commit('stopLoading')
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
return axios.get(templatesEndpoint + '/' + slug).then((response) => {
|
||||
context.commit('addOrUpdate', response.data)
|
||||
context.commit('stopLoading')
|
||||
}).catch((error) => {
|
||||
context.commit('stopLoading')
|
||||
})
|
||||
},
|
||||
loadAll (context, options=null) {
|
||||
context.commit('startLoading')
|
||||
context.dispatch('loadTypesAndIndustries')
|
||||
|
||||
// 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 axios.get((queryStr) ? templatesEndpoint + '?' + queryStr : templatesEndpoint).then((response) => {
|
||||
if(options !== null){
|
||||
context.commit('set', response.data)
|
||||
context.commit('setAllLoaded', false)
|
||||
} else {
|
||||
context.commit('append', response.data)
|
||||
context.commit('setAllLoaded', true)
|
||||
}
|
||||
context.commit('stopLoading')
|
||||
}).catch((error) => {
|
||||
context.commit('stopLoading')
|
||||
})
|
||||
},
|
||||
loadIfEmpty (context) {
|
||||
if (!context.state.allLoaded) {
|
||||
return context.dispatch('loadAll')
|
||||
}
|
||||
context.commit('stopLoading')
|
||||
return Promise.resolve()
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
export const namespaced = true
|
||||
|
||||
// state
|
||||
export const state = {
|
||||
content: null,
|
||||
|
||||
// Field being edited
|
||||
selectedFieldIndex: null,
|
||||
showEditFieldSidebar: null,
|
||||
showAddFieldSidebar: null
|
||||
}
|
||||
|
||||
// mutations
|
||||
export const mutations = {
|
||||
set (state, form) {
|
||||
state.content = form
|
||||
},
|
||||
setProperties (state, properties) {
|
||||
state.content.properties = properties
|
||||
},
|
||||
openSettingsForField (state, index) {
|
||||
// If field is passed, compute index
|
||||
if (typeof index === 'object') {
|
||||
index = state.content.properties.findIndex(prop => prop.id === index.id)
|
||||
}
|
||||
state.selectedFieldIndex = index
|
||||
state.showEditFieldSidebar = true
|
||||
state.showAddFieldSidebar = false
|
||||
},
|
||||
closeEditFieldSidebar (state) {
|
||||
state.selectedFieldIndex = null
|
||||
state.showEditFieldSidebar = false
|
||||
state.showAddFieldSidebar = false
|
||||
},
|
||||
openAddFieldSidebar (state, index) {
|
||||
// If field is passed, compute index
|
||||
if (index !== null && typeof index === 'object') {
|
||||
index = state.content.properties.findIndex(prop => prop.id === index.id)
|
||||
}
|
||||
state.selectedFieldIndex = index
|
||||
state.showAddFieldSidebar = true
|
||||
state.showEditFieldSidebar = false
|
||||
},
|
||||
closeAddFieldSidebar (state) {
|
||||
state.selectedFieldIndex = null
|
||||
state.showAddFieldSidebar = false
|
||||
state.showEditFieldSidebar = false
|
||||
},
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
import Vue from 'vue'
|
||||
import axios from 'axios'
|
||||
|
||||
export const namespaced = true
|
||||
export const workspaceEndpoint = '/api/open/workspaces/'
|
||||
|
||||
const localStorageCurrentWorkspaceKey = 'currentWorkspace'
|
||||
|
||||
// state
|
||||
export const state = {
|
||||
content: [],
|
||||
currentId: null,
|
||||
loading: false
|
||||
}
|
||||
|
||||
// getters
|
||||
export const getters = {
|
||||
getById: (state) => (id) => {
|
||||
if (state.content.length === 0) return null
|
||||
return state.content.find(item => item.id === id)
|
||||
},
|
||||
getCurrent: (state) => () => {
|
||||
if (state.content.length === 0 || state.currentId === null) return null
|
||||
return state.content.find(item => item.id === state.currentId)
|
||||
}
|
||||
}
|
||||
|
||||
// mutations
|
||||
export const mutations = {
|
||||
set (state, items) {
|
||||
state.content = items
|
||||
if (state.currentId == null && state.content.length > 0) {
|
||||
// If one only, set it
|
||||
if (state.content.length === 1) {
|
||||
state.currentId = items[0].id
|
||||
localStorage.setItem(localStorageCurrentWorkspaceKey, state.currentId)
|
||||
} else if (localStorage.getItem(localStorageCurrentWorkspaceKey) && state.content.find(item => item.id === parseInt(localStorage.getItem(localStorageCurrentWorkspaceKey)))) {
|
||||
// Check local storage for current workspace, or take first
|
||||
state.currentId = parseInt(localStorage.getItem(localStorageCurrentWorkspaceKey))
|
||||
localStorage.setItem(localStorageCurrentWorkspaceKey, state.currentId)
|
||||
} else {
|
||||
// Else, take first
|
||||
state.currentId = items[0].id
|
||||
localStorage.setItem(localStorageCurrentWorkspaceKey, state.currentId)
|
||||
}
|
||||
} else {
|
||||
localStorage.removeItem(localStorageCurrentWorkspaceKey)
|
||||
}
|
||||
},
|
||||
setCurrentId (state, id) {
|
||||
state.currentId = id
|
||||
localStorage.setItem(localStorageCurrentWorkspaceKey, id)
|
||||
},
|
||||
addOrUpdate (state, item) {
|
||||
state.content = state.content.filter((val) => val.id !== item.id)
|
||||
state.content.push(item)
|
||||
if (state.currentId == null) {
|
||||
state.currentId = item.id
|
||||
localStorage.setItem(localStorageCurrentWorkspaceKey, state.currentId)
|
||||
}
|
||||
},
|
||||
remove (state, itemId) {
|
||||
state.content = state.content.filter((val) => val.id !== itemId)
|
||||
},
|
||||
startLoading () {
|
||||
state.loading = true
|
||||
},
|
||||
stopLoading () {
|
||||
state.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
// actions
|
||||
export const actions = {
|
||||
resetState (context) {
|
||||
context.commit('set', [])
|
||||
context.commit('stopLoading')
|
||||
},
|
||||
load (context) {
|
||||
context.commit('set', [])
|
||||
context.commit('startLoading')
|
||||
return axios.get(workspaceEndpoint).then((response) => {
|
||||
context.commit('set', response.data)
|
||||
context.commit('stopLoading')
|
||||
})
|
||||
},
|
||||
loadIfEmpty ({ context, dispatch, state }) {
|
||||
if (state.content.length === 0) {
|
||||
return dispatch('load')
|
||||
}
|
||||
return Promise.resolve()
|
||||
},
|
||||
delete ({ commit, dispatch, state }, id) {
|
||||
commit('startLoading')
|
||||
return axios.delete(workspaceEndpoint + id).then((response) => {
|
||||
commit('remove', response.data.workspace_id)
|
||||
commit('stopLoading')
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
// auth.js
|
||||
export const LOGOUT = 'LOGOUT'
|
||||
export const SAVE_TOKEN = 'SAVE_TOKEN'
|
||||
export const FETCH_USER = 'FETCH_USER'
|
||||
export const FETCH_USER_SUCCESS = 'FETCH_USER_SUCCESS'
|
||||
export const FETCH_USER_FAILURE = 'FETCH_USER_FAILURE'
|
||||
export const UPDATE_USER = 'UPDATE_USER'
|
||||
|
||||
// lang.js
|
||||
export const SET_LOCALE = 'SET_LOCALE'
|
|
@ -0,0 +1,71 @@
|
|||
|
||||
import { defineStore } from 'pinia'
|
||||
import { nextTick } from 'vue'
|
||||
|
||||
export const useAppStore = defineStore('app', {
|
||||
state: () => ({
|
||||
layout: 'default',
|
||||
|
||||
// App Loader
|
||||
loader: {
|
||||
percent: 0,
|
||||
show: false,
|
||||
canSuccess: true,
|
||||
duration: 3000,
|
||||
_timer: null,
|
||||
_cut: null
|
||||
}
|
||||
}),
|
||||
actions: {
|
||||
setLayout (layout) {
|
||||
this.layout = layout ?? 'default'
|
||||
},
|
||||
loaderIncrease (num) {
|
||||
this.loader.percent = this.loader.percent + Math.floor(num)
|
||||
},
|
||||
loaderDecrease (num) {
|
||||
this.loader.percent = this.loader.percent - Math.floor(num)
|
||||
},
|
||||
loaderFinish () {
|
||||
this.loader.percent = 100
|
||||
this.loaderHide()
|
||||
},
|
||||
loaderSetTimer (timerVal) {
|
||||
this._timer = timerVal
|
||||
},
|
||||
loaderPause () {
|
||||
clearInterval(this.loader._timer)
|
||||
},
|
||||
loaderHide () {
|
||||
clearInterval(this.loader._timer)
|
||||
this.loader._timer = null
|
||||
setTimeout(() => {
|
||||
this.loader.show = false
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.loader.percent = 0
|
||||
}, 200)
|
||||
})
|
||||
}, 500)
|
||||
},
|
||||
loaderFail () {
|
||||
this.loader.canSuccess = false
|
||||
},
|
||||
loaderStart () {
|
||||
this.loader.show = true
|
||||
this.loader.canSuccess = true
|
||||
if (this.loader._timer) {
|
||||
clearInterval(this.loader._timer)
|
||||
this.loader.percent = 0
|
||||
}
|
||||
this.loader._cut = 10000 / Math.floor(this.loader.duration)
|
||||
|
||||
this.loaderSetTimer(setInterval(() => {
|
||||
this.loaderIncrease(this.loader._cut * Math.random())
|
||||
if (this.loader.percent > 95) {
|
||||
this.loaderFinish()
|
||||
}
|
||||
}, 100))
|
||||
}
|
||||
}
|
||||
})
|
|
@ -0,0 +1,67 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import axios from 'axios'
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
export const useAuthStore = defineStore('auth', {
|
||||
state: () => ({
|
||||
user: null,
|
||||
token: Cookies.get('token'),
|
||||
|
||||
// For admin impersonation
|
||||
admin_token: Cookies.get('admin_token') ?? null
|
||||
}),
|
||||
getters: {
|
||||
check: (state) => (state.user !== null && state.user !== undefined),
|
||||
isImpersonating: (state) => (state.admin_token !== null && state.admin_token !== undefined)
|
||||
},
|
||||
actions: {
|
||||
// Stores admin token temporarily for impersonation
|
||||
startImpersonating () {
|
||||
this.admin_token = this.token
|
||||
Cookies.set('admin_token', this.token, { expires: 365 })
|
||||
},
|
||||
// Stop admin impersonation
|
||||
stopImpersonating () {
|
||||
this.token = this.admin_token
|
||||
this.admin_token = null
|
||||
Cookies.set('token', this.token, { expires: 365 })
|
||||
Cookies.remove('admin_token')
|
||||
this.fetchUser()
|
||||
},
|
||||
|
||||
saveToken (token, remember) {
|
||||
this.token = token
|
||||
Cookies.set('token', token, { expires: remember ? 365 : null })
|
||||
},
|
||||
|
||||
async fetchUser () {
|
||||
try {
|
||||
const { data } = await axios.get('/api/user')
|
||||
this.user = data
|
||||
return data
|
||||
} catch (e) {
|
||||
this.token = null
|
||||
Cookies.remove('token')
|
||||
}
|
||||
},
|
||||
|
||||
updateUser (payload) {
|
||||
this.user = payload
|
||||
},
|
||||
|
||||
async logout () {
|
||||
try {
|
||||
await axios.post('/api/logout')
|
||||
} catch (e) { }
|
||||
|
||||
this.user = null
|
||||
this.token = null
|
||||
Cookies.remove('token')
|
||||
},
|
||||
|
||||
async fetchOauthUrl (provider) {
|
||||
const { data } = await axios.post(`/api/oauth/${provider}`)
|
||||
return data.url
|
||||
}
|
||||
}
|
||||
})
|
|
@ -0,0 +1,17 @@
|
|||
import { defineStore } from 'pinia'
|
||||
|
||||
export const namespaced = true
|
||||
|
||||
export const useErrorsStore = defineStore('errors', {
|
||||
state: () => ({
|
||||
content: null
|
||||
}),
|
||||
actions: {
|
||||
set (error) {
|
||||
this.content = error
|
||||
},
|
||||
clear () {
|
||||
this.content = null
|
||||
}
|
||||
}
|
||||
})
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue