Fix sentry tracked issues

This commit is contained in:
Julien Nahum 2024-01-18 11:37:04 +01:00
parent ebdd06cbe6
commit c97be832d7
10 changed files with 136 additions and 131 deletions

View File

@ -130,7 +130,7 @@ export default {
}) ?? null }) ?? null
}, },
onInput (event) { onInput (event) {
this.inputVal = event.target.value.replace(/[^0-9]/g, '') this.inputVal = event?.target?.value.replace(/[^0-9]/g, '')
}, },
onChangeCountryCode () { onChangeCountryCode () {
if (!this.selectedCountryCode && this.countries.length > 0) { if (!this.selectedCountryCode && this.countries.length > 0) {

View File

@ -1,7 +1,8 @@
<template> <template>
<editor-options-panel name="Link Settings - SEO" :already-opened="false" :has-pro-tag="true"> <editor-options-panel name="Link Settings - SEO" :already-opened="false" :has-pro-tag="true">
<template #icon> <template #icon>
<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" <path stroke-linecap="round" stroke-linejoin="round"
d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z"
/> />
@ -10,7 +11,8 @@
<p class="mt-4 text-gray-500 text-sm"> <p class="mt-4 text-gray-500 text-sm">
Customize the link, images and text that appear when you share your form on other sites (Open Graph). Customize the link, images and text that appear when you share your form on other sites (Open Graph).
</p> </p>
<select-input v-if="customDomainAllowed" v-model="form.custom_domain" :disabled="customDomainOptions.length <= 0" :options="customDomainOptions" name="type" <select-input v-if="customDomainAllowed" v-model="form.custom_domain" :disabled="customDomainOptions.length <= 0"
:options="customDomainOptions" name="type"
class="mt-4" label="Form Domain" placeholder="yourdomain.com" class="mt-4" label="Form Domain" placeholder="yourdomain.com"
/> />
<text-input v-model="form.seo_meta.page_title" name="page_title" class="mt-4" <text-input v-model="form.seo_meta.page_title" name="page_title" class="mt-4"
@ -26,50 +28,49 @@
</template> </template>
<script> <script>
import { useWorkingFormStore } from '../../../../../stores/working_form' import {useWorkingFormStore} from '../../../../../stores/working_form'
import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue' import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
export default { export default {
components: { EditorOptionsPanel }, components: {EditorOptionsPanel},
props: {}, props: {},
setup () { setup() {
const workingFormStore = useWorkingFormStore() const workingFormStore = useWorkingFormStore()
return { return {
workspacesStore: useWorkspacesStore(), workspacesStore: useWorkspacesStore(),
workingFormStore workingFormStore
} }
}, },
data () { data() {
return { return {}
}
}, },
computed: { computed: {
form: { form: {
get () { get() {
return this.workingFormStore.content return this.workingFormStore.content
}, },
/* We add a setter */ /* We add a setter */
set (value) { set(value) {
this.workingFormStore.set(value) this.workingFormStore.set(value)
} }
}, },
workspace () { workspace() {
return this.workspacesStore.getCurrent return this.workspacesStore.getCurrent
}, },
customDomainOptions () { customDomainOptions() {
return this.workspace.custom_domains.map((domain) => { return this.workspace.custom_domains ? this.workspace.custom_domains.map((domain) => {
return { return {
name: domain, name: domain,
value: domain value: domain
} }
}) }) : []
}, },
customDomainAllowed () { customDomainAllowed() {
return useRuntimeConfig().public.customDomainsEnabled return useRuntimeConfig().public.customDomainsEnabled
} }
}, },
watch: {}, watch: {},
mounted () { mounted() {
['page_title', 'page_description', 'page_thumbnail'].forEach((keyname) => { ['page_title', 'page_description', 'page_thumbnail'].forEach((keyname) => {
if (this.form.seo_meta[keyname] === undefined) { if (this.form.seo_meta[keyname] === undefined) {
this.form.seo_meta[keyname] = null this.form.seo_meta[keyname] = null

View File

@ -38,14 +38,14 @@ export default {
computed: { computed: {
parsedFiles() { parsedFiles() {
return this.value.map((file) => { return this.value ? this.value.map((file) => {
return { return {
file_name: file.file_name, file_name: file.file_name,
file_url: file.file_url, file_url: file.file_url,
displayed_file_name: this.displayedFileName(file.file_name), displayed_file_name: this.displayedFileName(file.file_name),
is_image: !this.failedImages.includes(file.file_url) && this.isImage(file.file_name) is_image: !this.failedImages.includes(file.file_url) && this.isImage(file.file_name)
} }
}) }): []
} }
}, },

View File

@ -1,10 +1,10 @@
<template> <template>
<div> <div>
<forgot-password-modal :show="showForgotModal" @close="showForgotModal=false" /> <forgot-password-modal :show="showForgotModal" @close="showForgotModal=false"/>
<form class="mt-4" @submit.prevent="login" @keydown="form.onKeydown($event)"> <form class="mt-4" @submit.prevent="login" @keydown="form.onKeydown($event)">
<!-- Email --> <!-- Email -->
<text-input name="email" :form="form" label="Email" :required="true" placeholder="Your email address" /> <text-input name="email" :form="form" label="Email" :required="true" placeholder="Your email address"/>
<!-- Password --> <!-- Password -->
<text-input native-type="password" placeholder="Your password" <text-input native-type="password" placeholder="Your password"
@ -18,7 +18,8 @@
</v-checkbox> </v-checkbox>
<div class="w-full md:w-1/2 text-right"> <div class="w-full md:w-1/2 text-right">
<a href="#" class="text-xs hover:underline text-gray-500 sm:text-sm hover:text-gray-700" @click.prevent="showForgotModal=true"> <a href="#" class="text-xs hover:underline text-gray-500 sm:text-sm hover:text-gray-700"
@click.prevent="showForgotModal=true">
Forgot your password? Forgot your password?
</a> </a>
</div> </div>
@ -58,7 +59,7 @@ export default {
} }
}, },
setup () { setup() {
return { return {
authStore: useAuthStore(), authStore: useAuthStore(),
formsStore: useFormsStore(), formsStore: useFormsStore(),
@ -76,10 +77,9 @@ export default {
}), }),
methods: { methods: {
async login () { login() {
// Submit the form. // Submit the form.
const data = await this.form.post('login') this.form.post('login').then(async (data) => {
// Save the token. // Save the token.
this.authStore.setToken(data.token) this.authStore.setToken(data.token)
@ -94,9 +94,12 @@ export default {
// Redirect home. // Redirect home.
this.redirect() this.redirect()
}).catch(() => {
})
}, },
redirect () { redirect() {
if (this.isQuick) { if (this.isQuick) {
this.$emit('afterQuickLogin') this.$emit('afterQuickLogin')
return return
@ -106,10 +109,10 @@ export default {
const router = useRouter() const router = useRouter()
if (intendedUrlCookie.value) { if (intendedUrlCookie.value) {
router.push({ path: intendedUrlCookie.value }) router.push({path: intendedUrlCookie.value})
useCookie('intended_url').value = null useCookie('intended_url').value = null
} else { } else {
router.push({ name: 'home' }) router.push({name: 'home'})
} }
} }
} }

View File

@ -103,7 +103,7 @@ export default {
if (this.loadingNewLink) return if (this.loadingNewLink) return
this.loadingNewLink = true this.loadingNewLink = true
opnFetch(this.formEndpoint.replace('{id}', this.form.id) + '/regenerate-link/' + option, {method:'PUT'}).then((data) => { opnFetch(this.formEndpoint.replace('{id}', this.form.id) + '/regenerate-link/' + option, {method:'PUT'}).then((data) => {
this.formsStore.addOrUpdate(data.form) this.formsStore.save(data.form)
this.$router.push({name: 'forms-slug-show-share', params: {slug: data.form.slug}}) this.$router.push({name: 'forms-slug-show-share', params: {slug: data.form.slug}})
useAlert().success(data.message) useAlert().success(data.message)
this.loadingNewLink = false this.loadingNewLink = false

View File

@ -1,4 +1,5 @@
<template> <template>
<div>
<NuxtLayout> <NuxtLayout>
<div class="flex mt-6"> <div class="flex mt-6">
<div class="w-full md:w-2/3 md:mx-auto md:max-w-md"> <div class="w-full md:w-2/3 md:mx-auto md:max-w-md">
@ -16,6 +17,7 @@
</div> </div>
</div> </div>
</NuxtLayout> </NuxtLayout>
</div>
</template> </template>
<script setup> <script setup>

View File

@ -8,99 +8,90 @@
{{ error }} {{ error }}
</div> </div>
<div v-else class="text-center mt-4 py-6"> <div v-else class="text-center mt-4 py-6">
<Loader class="h-6 w-6 text-nt-blue mx-auto" /> <Loader class="h-6 w-6 text-nt-blue mx-auto"/>
</div> </div>
</div> </div>
</template> </template>
<script> <script setup>
import { computed } from 'vue' import {computed} from 'vue'
import Breadcrumb from '~/components/global/Breadcrumb.vue'
import FormEditor from "~/components/open/forms/components/FormEditor.vue"; import FormEditor from "~/components/open/forms/components/FormEditor.vue";
import {hash} from "~/lib/utils.js"; import {hash} from "~/lib/utils.js";
export default { const formsStore = useFormsStore()
name: 'EditForm', const workingFormStore = useWorkingFormStore()
components: { Breadcrumb, FormEditor }, const workspacesStore = useWorkspacesStore()
beforeRouteLeave (to, from, next) { if (!formsStore.allLoaded) {
if (this.isDirty()) { formsStore.startLoading()
}
const updatedForm = storeToRefs(workingFormStore).content
const form = computed(() => formsStore.getByKey(useRoute().params.slug))
const formsLoading = computed(() => formsStore.loading)
const error = ref(null)
const formInitialHash = ref(null)
function isDirty() {
return formInitialHash.value && updatedForm.value && formInitialHash.value !== hash(JSON.stringify(updatedForm.value.data() ?? null))
}
function initUpdatedForm() {
if (!form || !form.value) {
return
}
updatedForm.value = useForm(form.value)
if (!updatedForm.value) {
return
}
formInitialHash.value = hash(JSON.stringify(updatedForm.value.data()))
if (updatedForm.value && (!updatedForm.value.notification_settings || Array.isArray(updatedForm.value.notification_settings))) {
updatedForm.value.notification_settings = {}
}
}
// Create a form.id watcher that updates working form
watch(form, (form) => {
if (form.value) {
initUpdatedForm()
}
})
onBeforeRouteLeave((to, from, next) => {
if (isDirty()) {
return useAlert().confirm('Changes you made may not be saved. Are you sure want to leave?', () => { return useAlert().confirm('Changes you made may not be saved. Are you sure want to leave?', () => {
window.onbeforeunload = null window.onbeforeunload = null
next() next()
}, () => {}) }, () => {
})
} }
next() next()
}, })
setup () { onBeforeMount(() => {
const formsStore = useFormsStore() if (process.client) {
const workingFormStore = useWorkingFormStore()
const workspacesStore = useWorkspacesStore()
if (!formsStore.allLoaded) {
formsStore.startLoading()
}
const updatedForm = storeToRefs(workingFormStore).content
const form = computed(() => formsStore.getByKey(useRoute().params.slug))
// Create a form.id watcher that updates working form
watch(form, (form) => {
if (form) {
updatedForm.value = useForm(form)
}
})
useOpnSeoMeta({
title: 'Edit ' + ((form && form.value) ? form.value.title : 'Your Form')
})
definePageMeta({
middleware: "auth"
})
return {
formsStore,
workingFormStore,
workspacesStore,
updatedForm,
form,
formsLoading: computed(() => formsStore.loading),
}
},
data () {
return {
error: null,
formInitialHash: null
}
},
computed: {
},
async beforeMount() {
window.onbeforeunload = () => { window.onbeforeunload = () => {
if (this.isDirty()) { if (isDirty()) {
return false return false
} }
} }
if (!this.form && !this.formsStore.allLoaded) {
await this.formsStore.loadAll(this.workspacesStore.currentId)
} }
this.updatedForm = useForm(this.form) if (!form.value && !formsStore.allLoaded) {
this.formInitialHash = hash(JSON.stringify(this.updatedForm.data())) formsStore.loadAll(workspacesStore.currentId).then(()=>{
initUpdatedForm()
})
} else {
initUpdatedForm()
}
})
if (this.updatedForm && (!this.updatedForm.notification_settings || Array.isArray(this.updatedForm.notification_settings))) { useOpnSeoMeta({
this.updatedForm.notification_settings = {} title: 'Edit ' + ((form && form.value) ? form.value.title : 'Your Form')
} })
}, definePageMeta({
middleware: "auth"
methods: { })
isDirty () {
return this.formInitialHash && this.formInitialHash !== hash(JSON.stringify(this.updatedForm.data()))
}
}
}
</script> </script>

View File

@ -189,7 +189,7 @@ onMounted(() => {
watch(() => form?.value?.id, (id) => { watch(() => form?.value?.id, (id) => {
if (id) { if (id) {
workingFormStore.set(form) workingFormStore.set(form.value)
} }
}) })

View File

@ -160,7 +160,7 @@ const saveChanges = () => {
.map(domain => domain ? domain.trim() : null) .map(domain => domain ? domain.trim() : null)
.filter(domain => domain && domain.length > 0) .filter(domain => domain && domain.length > 0)
}).then((data) => { }).then((data) => {
workspacesStore.addOrUpdate(data) workspacesStore.save(data)
useAlert().success('Custom domains saved.') useAlert().success('Custom domains saved.')
}).catch((error) => { }).catch((error) => {
useAlert().error('Failed to update custom domains: ' + error.response.data.message) useAlert().error('Failed to update custom domains: ' + error.response.data.message)

View File

@ -54,6 +54,14 @@ export default defineNuxtPlugin({
replaysOnErrorSampleRate: config.public.SENTRY_ERROR_REPLAY_SAMPLE_RATE, replaysOnErrorSampleRate: config.public.SENTRY_ERROR_REPLAY_SAMPLE_RATE,
beforeSend(event) { beforeSend(event) {
if (event.exception.values.length) {
// Don't send validation exceptions to Sentry
if (event.exception.values[0].type === 'FetchError' &&
event.exception.values[0].value.includes('422')
) {
return null
}
}
return event; return event;
}, },
}) })