Multiple bug fixing

This commit is contained in:
Julien Nahum 2024-02-10 12:20:45 +01:00
parent f2916b9e31
commit 91911bc6e5
16 changed files with 51 additions and 51 deletions

View File

@ -4,7 +4,7 @@
ref="scrollContainer"
:class="[$style['scroll-container'],{'no-scrollbar':hideScrollbar}]"
:style="{ width: width?width:'auto', height }"
@scroll.passive="toggleShadow"
@scroll.passive="throttled.toggleShadow"
>
<slot />
<span :class="[$style['shadow-top'], shadow.top && $style['is-active']]" :style="{
@ -19,6 +19,7 @@
</template>
<script>
import throttle from 'lodash.throttle'
function newResizeObserver (callback) {
// Skip this feature for browsers which
// do not support ResizeObserver.
@ -50,28 +51,31 @@ export default {
bottom: false,
left: false
},
debounceTimeout: null,
scrollContainerObserver: null,
wrapObserver: null
wrapObserver: null,
throttled: {}
}
},
mounted () {
window.addEventListener('resize', this.calcDimensions)
this.throttled.toggleShadow = throttle(this.toggleShadow, 100);
this.throttled.calcDimensions = throttle(this.calcDimensions, 100);
window.addEventListener('resize', this.throttled.calcDimensions)
// Check if shadows are necessary after the element is resized.
const scrollContainerObserver = newResizeObserver(this.toggleShadow)
const scrollContainerObserver = newResizeObserver(this.throttled.toggleShadow)
if (scrollContainerObserver) {
scrollContainerObserver.observe(this.$refs.scrollContainer)
}
// Recalculate the container dimensions when the wrapper is resized.
this.wrapObserver = newResizeObserver(this.calcDimensions)
this.wrapObserver = newResizeObserver(this.throttled.calcDimensions)
if (this.wrapObserver) {
this.wrapObserver.observe(this.$el)
}
},
unmounted () {
window.removeEventListener('resize', this.calcDimensions)
window.removeEventListener('resize', this.throttled.calcDimensions)
// Cleanup when the component is unmounted.
this.wrapObserver.disconnect()
if (this.scrollContainerObserver) {

View File

@ -173,6 +173,7 @@ export default {
*/
currentFieldsPageBreak () {
// Last block from current group
if (!this.currentFields?.length) return null
const block = this.currentFields[this.currentFields.length - 1]
if (block && block.type === 'nf-page-break') return block
return null

View File

@ -97,6 +97,7 @@ import FormCustomSeo from './form-components/FormCustomSeo.vue'
import FormAccess from './form-components/FormAccess.vue'
import {validatePropertiesLogic} from "~/composables/forms/validatePropertiesLogic.js"
import opnformConfig from "~/opnform.config.js";
import {captureException} from "@sentry/vue";
export default {
name: 'FormEditor',
@ -255,9 +256,12 @@ export default {
this.amplitude.logEvent('form_saved', { form_id: this.form.id, form_slug: this.form.slug })
this.displayFormModificationAlert(data)
}).catch((error) => {
if (error.response.status === 422) {
if (error?.response.status === 422) {
this.validationErrorResponse = error.response.data
this.showValidationErrors()
} else {
useAlert().error('An error occurred while saving the form, please try again.')
captureException(error)
}
}).finally(() => {
this.updateFormLoading = false
@ -282,10 +286,12 @@ export default {
this.displayFormModificationAlert(response)
useRouter().push({ name: 'forms-slug-show-share', params: { slug: this.createdFormSlug, new_form: response.users_first_form } })
}).catch((error) => {
console.error(error)
if (error.response && error.response.status === 422) {
if (error?.response?.status === 422) {
this.validationErrorResponse = error.response
this.showValidationErrors()
} else {
useAlert().error('An error occurred while saving the form, please try again.')
captureException(error)
}
}).finally(() => {
this.updateFormLoading = false

View File

@ -17,11 +17,6 @@
]"
:form="form" label="Form Theme"
/>
<div class="-mt-3 mb-3 text-gray-400 dark:text-gray-500">
<small>
Need another theme? <a href="#" @click.prevent="crisp.openAndShowChat">Send us some suggestions!</a>
</small>
</div>
<select-input name="dark_mode" class="mt-4"
help="To see changes, save your form and open it"

View File

@ -468,6 +468,7 @@ export default {
return true
},
optionsText () {
if (this.field[this.field.type]) return []
return this.field[this.field.type].options.map(option => {
return option.name
}).join('\n')

View File

@ -53,8 +53,8 @@
<td v-if="hasActions" class="n-table-cell border-gray-100 dark:border-gray-900 text-sm p-2 border-b"
style="width: 100px"
>
<record-operations :form="form" :structure="columns" :submission="row"
@deleted="(submission)=>$emit('deleted',submission)"
<record-operations :form="form" :structure="columns" :submission="row"
@deleted="(submission)=>$emit('deleted',submission)"
@updated="(submission)=>$emit('updated', submission)"/>
</td>
</tr>
@ -91,7 +91,7 @@ import {hash} from "~/lib/utils.js";
export default {
components: {ResizableTh, RecordOperations},
emits: ["updated", "deleted"],
emits: ["updated", "deleted", "resize"],
props: {
columns: {
type: Array,

View File

@ -145,7 +145,9 @@ export default {
this.fetchGeneratedForm(generationId)
}
}).catch(error => {
this.useAlert.error(error.data.message)
if (error?.data?.message){
this.useAlert.error(error.data.message)
}
this.state = 'default'
this.loading = false
})

View File

@ -25,7 +25,6 @@ export const useCrisp = () => {
function openAndShowChat(message = null) {
if (!crisp) return
showChat()
openChat()
if (message) sendTextMessage(message)
}

View File

@ -65,7 +65,7 @@ function checkContains (condition, fieldValue) {
function checkListContains (condition, fieldValue) {
if (!fieldValue) return false
if (Array.isArray(condition.value)) {
return condition.value.every(r => fieldValue.includes(r))
} else {
@ -74,11 +74,11 @@ function checkListContains (condition, fieldValue) {
}
function checkStartsWith (condition, fieldValue) {
return fieldValue.startsWith(condition.value)
return fieldValue?.startsWith(condition.value)
}
function checkendsWith (condition, fieldValue) {
return fieldValue && fieldValue.endsWith(condition.value)
return fieldValue?.endsWith(condition.value)
}
function checkIsEmpty (condition, fieldValue) {

View File

@ -28,6 +28,7 @@
"fuse.js": "^6.4.6",
"js-sha256": "^0.10.0",
"libphonenumber-js": "^1.10.44",
"lodash.throttle": "^4.1.1",
"nuxt3-notifications": "^1.1.9",
"object-to-formdata": "^4.5.1",
"pinia": "^2.1.7",
@ -8517,6 +8518,11 @@
"lodash._reinterpolate": "^3.0.0"
}
},
"node_modules/lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
},
"node_modules/lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",

View File

@ -43,6 +43,7 @@
"fuse.js": "^6.4.6",
"js-sha256": "^0.10.0",
"libphonenumber-js": "^1.10.44",
"lodash.throttle": "^4.1.1",
"nuxt3-notifications": "^1.1.9",
"object-to-formdata": "^4.5.1",
"pinia": "^2.1.7",

View File

@ -33,7 +33,9 @@ const error = ref(null)
const formInitialHash = ref(null)
function isDirty() {
return formInitialHash.value && updatedForm.value && formInitialHash.value !== hash(JSON.stringify(updatedForm.value.data() ?? null))
return formInitialHash.value &&
updatedForm.value &&
formInitialHash.value !== hash(JSON.stringify(updatedForm?.value?.data() ?? null))
}
function initUpdatedForm() {

View File

@ -71,14 +71,14 @@
}
]
if (user.value.is_subscribed) {
if (user?.value?.is_subscribed) {
tabs.splice(1, 0, {
name: 'Billing',
route: 'settings-billing'
})
}
if (user.value.admin) {
if (user?.value?.admin) {
tabs.push({
name: 'Admin',
route: 'settings-admin'

View File

@ -1,16 +1,5 @@
import * as Sentry from "@sentry/vue";
async function lazyLoadSentryIntegrations() {
// don't load on server
if (!process.client) return;
const {Replay} = await import("@sentry/vue");
Sentry.addIntegration(new Replay({
maskAllText: false,
blockAllMedia: false,
}));
}
function getSentryIntegrations() {
// don't load on server
if (!process.client) return [];
@ -65,8 +54,5 @@ export default defineNuxtPlugin({
return event;
},
})
// Lazy-load the replay integration to reduce bundle size
lazyLoadSentryIntegrations()
}
});

17
client/stores/auth.js vendored
View File

@ -1,4 +1,5 @@
import {defineStore} from 'pinia'
import {setUser as sentrySetUser} from "@sentry/vue";
export const useAuthStore = defineStore('auth', {
state: () => {
@ -65,18 +66,16 @@ export const useAuthStore = defineStore('auth', {
useCrisp().setUser(this.user)
// Init sentry
// console.log(process)
// $sentry.configureScope((scope) => {
// scope.setUser({
// id: this.user.id,
// email: this.user.email,
// subscription: this.user?.is_subscribed
// })
// })
sentrySetUser({
id: this.user.id,
email: this.user.email,
subscription: this.user?.is_subscribed
})
},
logout() {
opnFetch('logout', {method: 'POST'}).catch((error) => {})
opnFetch('logout', {method: 'POST'}).catch((error) => {
})
this.user = null
this.setToken(null)

View File

@ -1,7 +1,5 @@
import { defineStore } from 'pinia'
export const useWorkingFormStore = defineStore('working_form', {
state: () => ({
content: null,