3
0

Adjust error reporting in compose blocks

This commit is contained in:
Jože Fortun 2024-11-27 15:35:51 +01:00
parent ac06c00805
commit 3172415575
12 changed files with 252 additions and 105 deletions

View File

@ -16,6 +16,14 @@ export default {
this.toast(message, { title, variant: 'warning' }) this.toast(message, { title, variant: 'warning' })
}, },
toastInfo (message, title = undefined) {
if (title === undefined) {
title = this.$t('notification:general.info')
}
this.toast(message, { title, variant: 'info' })
},
toastDanger (message, title = undefined) { toastDanger (message, title = undefined) {
if (title === undefined) { if (title === undefined) {
title = this.$t('notification:general.error') title = this.$t('notification:general.error')
@ -28,6 +36,14 @@ export default {
this.$root.$bvToast.toast(msg, opt) this.$root.$bvToast.toast(msg, opt)
}, },
getToastMessage (err) {
if (err.message && err.message.startsWith('notification')) {
return this.$t(`notification:${err.message.substring('notification.'.length)}`)
}
return err.message
},
toastErrorHandler (opt) { toastErrorHandler (opt) {
if (typeof opt === 'string') { if (typeof opt === 'string') {
opt = { prefix: opt } opt = { prefix: opt }
@ -36,13 +52,13 @@ export default {
const { prefix, title } = opt const { prefix, title } = opt
return (err = {}) => { return (err = {}) => {
// only messages starting with 'notification:' or 'notification.' should be translated err.message = this.getToastMessage(err)
if (err.message && err.message.startsWith('notification')) {
err.message = this.$t(`notification:${err.message.substring('notification.'.length)}`)
}
// all other messages should be shown as they are // all other messages should be shown as they are
const msg = err.message ? `${prefix}: ${err.message}` : prefix const msg = err.message ? `${prefix}: ${err.message}` : prefix
this.toastDanger(msg, title) this.toastDanger(msg, title)
return err.message
} }
}, },
}, },

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="d-flex flex-column align-items-center justify-content-center h-100 position-relative"> <div class="d-flex h-100 w-100 position-relative">
<div <div
v-if="processing" v-if="processing"
class="d-flex flex-column align-items-center justify-content-center flex-fill" class="d-flex flex-column align-items-center justify-content-center flex-fill"
@ -7,8 +7,15 @@
<b-spinner /> <b-spinner />
</div> </div>
<label
v-else-if="error"
class="text-primary p-3"
>
{{ error }}
</label>
<c-chart <c-chart
v-if="renderer" v-else-if="renderer"
:chart="renderer" :chart="renderer"
class="flex-fill p-1" class="flex-fill p-1"
@click="drillDown" @click="drillDown"
@ -50,6 +57,7 @@ export default {
data () { data () {
return { return {
error: undefined,
processing: false, processing: false,
valueMap: new Map(), valueMap: new Map(),
@ -87,6 +95,7 @@ export default {
}), }),
async updateChart () { async updateChart () {
this.error = undefined
this.renderer = undefined this.renderer = undefined
const [report = {}] = this.chart.config.reports const [report = {}] = this.chart.config.reports
@ -203,8 +212,8 @@ export default {
this.renderer = chart.makeOptions(data) this.renderer = chart.makeOptions(data)
} catch (e) { } catch (e) {
this.error = this.toastErrorHandler(this.$t('chart.optionsBuildFailed'))(e)
this.processing = false this.processing = false
this.toastErrorHandler(this.$t('chart.optionsBuildFailed'))(e)
} }
setTimeout(() => { setTimeout(() => {
@ -245,11 +254,6 @@ export default {
} }
}, },
error (msg) {
/* eslint-disable no-console */
console.error(msg)
},
setDefaultValues () { setDefaultValues () {
this.processing = false this.processing = false
this.renderer = undefined this.renderer = undefined

View File

@ -3,8 +3,16 @@
v-bind="$props" v-bind="$props"
v-on="$listeners" v-on="$listeners"
> >
<label
v-if="error"
class="text-primary p-3"
>
{{ error }}
</label>
<div <div
class="rt-content px-3 py-2" v-else
class="rt-content p-3"
> >
<p <p
:style="{ 'white-space': 'pre-wrap' }" :style="{ 'white-space': 'pre-wrap' }"
@ -21,17 +29,39 @@ import { NoID } from '@cortezaproject/corteza-js'
export default { export default {
extends: base, extends: base,
computed: { data () {
contentBody () { return {
const { body = '' } = this.options error: null,
contentBody: '',
}
},
return evaluatePrefilter(body, { watch: {
record: this.record, 'options.body': {
user: this.$auth.user || {}, immediate: true,
recordID: (this.record || {}).recordID || NoID, handler () {
ownerID: (this.record || {}).ownedBy || NoID, this.makeContentBody()
userID: (this.$auth.user || {}).userID || NoID, },
}) },
},
methods: {
makeContentBody () {
this.error = null
try {
const { body = '' } = this.options
this.contentBody = evaluatePrefilter(body, {
record: this.record,
user: this.$auth.user || {},
recordID: (this.record || {}).recordID || NoID,
ownerID: (this.record || {}).ownedBy || NoID,
userID: (this.$auth.user || {}).userID || NoID,
})
} catch (e) {
this.error = this.getToastMessage(e)
}
}, },
}, },
} }

View File

@ -11,6 +11,13 @@
<b-spinner /> <b-spinner />
</div> </div>
<label
v-else-if="error"
class="text-primary p-3"
>
{{ error }}
</label>
<template v-else> <template v-else>
<div <div
v-for="(m, mi) in options.metrics" v-for="(m, mi) in options.metrics"
@ -66,6 +73,8 @@ export default {
data () { data () {
return { return {
processing: false, processing: false,
error: undefined,
reports: [], reports: [],
abortableRequests: [], abortableRequests: [],
@ -148,6 +157,7 @@ export default {
* Pulls fresh data from the API * Pulls fresh data from the API
*/ */
async refresh () { async refresh () {
this.error = undefined
this.processing = true this.processing = true
try { try {
@ -196,7 +206,9 @@ export default {
setTimeout(() => { setTimeout(() => {
this.processing = false this.processing = false
}, 300) }, 300)
} catch { } catch (e) {
this.error = this.getToastMessage(e)
setTimeout(() => { setTimeout(() => {
this.processing = false this.processing = false
}, 300) }, 300)

View File

@ -4,13 +4,29 @@
v-on="$listeners" v-on="$listeners"
@refreshBlock="refresh" @refreshBlock="refresh"
> >
<template
v-if="canAddRecord"
#toolbar
>
<div class="p-3 border-bottom">
<b-button
variant="primary"
size="lg"
@click.prevent="createNewRecord"
>
{{ $t('recordOrganizer.addNewRecord') }}
</b-button>
</div>
</template>
<template #default> <template #default>
<div <label
v-if="!isConfigured" v-if="!isConfigured"
class="d-flex align-items-center justify-content-center h-100 p-3" class="text-primary p-3"
> >
{{ $t('recordOrganizer.notConfigured') }} {{ $t('recordOrganizer.notConfigured') }}
</div> </label>
<div <div
v-else v-else
class="h-100" class="h-100"
@ -30,7 +46,7 @@
#header #header
> >
<div <div
class="small p-3 text-secondary" class="small text-secondary"
> >
{{ $t('recordOrganizer.noRecords') }} {{ $t('recordOrganizer.noRecords') }}
</div> </div>
@ -40,7 +56,7 @@
v-for="record in records" v-for="record in records"
:key="`${record.recordID}`" :key="`${record.recordID}`"
body-class="rounded p-3" body-class="rounded p-3"
class="record-item border border-light mb-3 grab" class="record-item border border-light mb-3 grab shadow-sm"
@click="handleRecordClick(record)" @click="handleRecordClick(record)"
> >
<h6 <h6
@ -88,22 +104,6 @@
</div> </div>
</div> </div>
</template> </template>
<template
v-if="canAddRecord"
#footer
>
<div
class="p-2"
>
<b-button
variant="outline-light"
class="d-flex align-items-center justify-content-center text-primary border-0"
@click.prevent="createNewRecord"
>
{{ $t('recordOrganizer.addNewRecord') }}
</b-button>
</div>
</template>
</wrap> </wrap>
</template> </template>
@ -172,6 +172,19 @@ export default {
return this.options.moduleID return this.options.moduleID
}, },
allFields () {
if (this.options.moduleID) {
return [
...this.roModule.fields,
...this.roModule.systemFields().map(sf => {
sf.label = this.$t(`field:system.${sf.name}`)
return sf
}),
]
}
return []
},
labelField () { labelField () {
const { labelField } = this.options const { labelField } = this.options
@ -179,7 +192,7 @@ export default {
return undefined return undefined
} }
return this.roModule.fields.find(f => f.name === labelField) || {} return this.allFields.find(f => f.name === labelField) || {}
}, },
descriptionField () { descriptionField () {
@ -189,7 +202,7 @@ export default {
return undefined return undefined
} }
return this.roModule.fields.find(f => f.name === descriptionField) || {} return this.allFields.find(f => f.name === descriptionField) || {}
}, },
positionField () { positionField () {
@ -199,7 +212,7 @@ export default {
return undefined return undefined
} }
return this.roModule.fields.find(f => f.name === positionField) || {} return this.allFields.find(f => f.name === positionField) || {}
}, },
groupField () { groupField () {
@ -209,7 +222,7 @@ export default {
return undefined return undefined
} }
return this.roModule.fields.find(f => f.name === groupField) || {} return this.allFields.find(f => f.name === groupField) || {}
}, },
canPull () { canPull () {
@ -554,6 +567,6 @@ export default {
} }
.record-item:hover { .record-item:hover {
box-shadow: 0 0.125rem 0.25rem rgb(0 0 0 / 8%) !important; background-color: var(--light) !important;
} }
</style> </style>

View File

@ -75,9 +75,9 @@
> >
<c-input-select <c-input-select
v-model="options.labelField" v-model="options.labelField"
:options="selectedModuleFields" :options="allFields"
:reduce="o => o.name" :reduce="o => o.name"
:get-option-label="fieldLabel" :get-option-label="getFieldLabel"
:placeholder="$t('general.label.none')" :placeholder="$t('general.label.none')"
/> />
<b-form-text>{{ $t('recordOrganizer.labelField.footnote') }}</b-form-text> <b-form-text>{{ $t('recordOrganizer.labelField.footnote') }}</b-form-text>
@ -94,9 +94,9 @@
> >
<c-input-select <c-input-select
v-model="options.descriptionField" v-model="options.descriptionField"
:options="selectedModuleFields" :options="allFields"
:reduce="o => o.name" :reduce="o => o.name"
:get-option-label="descriptionLabel" :get-option-label="getFieldLabel"
:placeholder="$t('general.label.none')" :placeholder="$t('general.label.none')"
/> />
@ -118,7 +118,7 @@
v-model="options.groupField" v-model="options.groupField"
:options="groupFields" :options="groupFields"
:reduce="o => o.name" :reduce="o => o.name"
:get-option-label="groupFieldLabel" :get-option-label="getFieldLabel"
:placeholder="$t('general.label.none')" :placeholder="$t('general.label.none')"
/> />
@ -271,7 +271,7 @@ export default {
}, },
groupFields () { groupFields () {
return this.selectedModuleFields.filter(({ isMulti }) => !isMulti) return this.allFields.filter(({ isMulti }) => !isMulti)
}, },
group () { group () {
@ -332,21 +332,13 @@ export default {
}, },
methods: { methods: {
getFieldLabel (option) {
return `${option.label || option.name} (${option.kind})`
},
setDefaultValues () { setDefaultValues () {
this.mock = [] this.mock = []
}, },
fieldLabel (option) {
return `${option.label || option.name} (${option.kind})`
},
descriptionLabel (option) {
return `${option.label || option.name} (${option.kind})`
},
groupFieldLabel (option) {
return `${option.label || option.name}`
},
}, },
} }
</script> </script>

View File

@ -36,6 +36,14 @@ export default {
this.$root.$bvToast.toast(msg, opt) this.$root.$bvToast.toast(msg, opt)
}, },
getToastMessage (err) {
if (err.message && err.message.startsWith('notification')) {
return this.$t(`notification:${err.message.substring('notification.'.length)}`)
}
return err.message
},
toastErrorHandler (opt) { toastErrorHandler (opt) {
if (typeof opt === 'string') { if (typeof opt === 'string') {
opt = { prefix: opt } opt = { prefix: opt }
@ -44,13 +52,13 @@ export default {
const { prefix, title } = opt const { prefix, title } = opt
return (err = {}) => { return (err = {}) => {
// only messages starting with 'notification:' or 'notification.' should be translated err.message = this.getToastMessage(err)
if (err.message && err.message.startsWith('notification')) {
err.message = this.$t(`notification:${err.message.substring('notification.'.length)}`)
}
// all other messages should be shown as they are // all other messages should be shown as they are
const msg = err.message ? `${prefix}: ${err.message}` : prefix const msg = err.message ? `${prefix}: ${err.message}` : prefix
this.toastDanger(msg, title) this.toastDanger(msg, title)
return err.message
} }
}, },
}, },

View File

@ -2,7 +2,7 @@ export default {
methods: { methods: {
toastSuccess (message, title = undefined) { toastSuccess (message, title = undefined) {
if (title === undefined) { if (title === undefined) {
title = this.$t('notification:general:success') title = this.$t('notification:general.success')
} }
this.toast(message, { title, variant: 'success' }) this.toast(message, { title, variant: 'success' })
@ -10,15 +10,23 @@ export default {
toastWarning (message, title = undefined) { toastWarning (message, title = undefined) {
if (title === undefined) { if (title === undefined) {
title = this.$t('notification:general:warning') title = this.$t('notification:general.warning')
} }
this.toast(message, { title, variant: 'warning' }) this.toast(message, { title, variant: 'warning' })
}, },
toastInfo (message, title = undefined) {
if (title === undefined) {
title = this.$t('notification:general.info')
}
this.toast(message, { title, variant: 'info' })
},
toastDanger (message, title = undefined) { toastDanger (message, title = undefined) {
if (title === undefined) { if (title === undefined) {
title = this.$t('notification:general:error') title = this.$t('notification:general.error')
} }
this.toast(message, { title, variant: 'danger' }) this.toast(message, { title, variant: 'danger' })
@ -28,6 +36,14 @@ export default {
this.$root.$bvToast.toast(msg, opt) this.$root.$bvToast.toast(msg, opt)
}, },
getToastMessage (err) {
if (err.message && err.message.startsWith('notification')) {
return this.$t(`notification:${err.message.substring('notification.'.length)}`)
}
return err.message
},
toastErrorHandler (opt) { toastErrorHandler (opt) {
if (typeof opt === 'string') { if (typeof opt === 'string') {
opt = { prefix: opt } opt = { prefix: opt }
@ -36,13 +52,13 @@ export default {
const { prefix, title } = opt const { prefix, title } = opt
return (err = {}) => { return (err = {}) => {
// only messages starting with 'notification:' or 'notification.' should be translated err.message = this.getToastMessage(err)
if (err.message && err.message.startsWith('notification')) {
err.message = this.$t(`notification:${err.message.substring('notification.'.length)}`)
}
// all other messages should be shown as they are // all other messages should be shown as they are
const msg = err.message ? `${prefix}: ${err.message}` : prefix const msg = err.message ? `${prefix}: ${err.message}` : prefix
this.toastDanger(msg, title) this.toastDanger(msg, title)
return err.message
} }
}, },
}, },

View File

@ -2,7 +2,7 @@ export default {
methods: { methods: {
toastSuccess (message, title = undefined) { toastSuccess (message, title = undefined) {
if (title === undefined) { if (title === undefined) {
title = this.$t('notification:general:success') title = this.$t('notification:general.success')
} }
this.toast(message, { title, variant: 'success' }) this.toast(message, { title, variant: 'success' })
@ -10,15 +10,23 @@ export default {
toastWarning (message, title = undefined) { toastWarning (message, title = undefined) {
if (title === undefined) { if (title === undefined) {
title = this.$t('notification:general:warning') title = this.$t('notification:general.warning')
} }
this.toast(message, { title, variant: 'warning' }) this.toast(message, { title, variant: 'warning' })
}, },
toastInfo (message, title = undefined) {
if (title === undefined) {
title = this.$t('notification:general.info')
}
this.toast(message, { title, variant: 'info' })
},
toastDanger (message, title = undefined) { toastDanger (message, title = undefined) {
if (title === undefined) { if (title === undefined) {
title = this.$t('notification:general:error') title = this.$t('notification:general.error')
} }
this.toast(message, { title, variant: 'danger' }) this.toast(message, { title, variant: 'danger' })
@ -28,6 +36,14 @@ export default {
this.$root.$bvToast.toast(msg, opt) this.$root.$bvToast.toast(msg, opt)
}, },
getToastMessage (err) {
if (err.message && err.message.startsWith('notification')) {
return this.$t(`notification:${err.message.substring('notification.'.length)}`)
}
return err.message
},
toastErrorHandler (opt) { toastErrorHandler (opt) {
if (typeof opt === 'string') { if (typeof opt === 'string') {
opt = { prefix: opt } opt = { prefix: opt }
@ -36,13 +52,13 @@ export default {
const { prefix, title } = opt const { prefix, title } = opt
return (err = {}) => { return (err = {}) => {
// only messages starting with 'notification:' or 'notification.' should be translated err.message = this.getToastMessage(err)
if (err.message && err.message.startsWith('notification')) {
err.message = this.$t(`notification:${err.message.substring('notification.'.length)}`)
}
// all other messages should be shown as they are // all other messages should be shown as they are
const msg = err.message ? `${prefix}: ${err.message}` : prefix const msg = err.message ? `${prefix}: ${err.message}` : prefix
this.toastDanger(msg, title) this.toastDanger(msg, title)
return err.message
} }
}, },
}, },

View File

@ -2,7 +2,7 @@ export default {
methods: { methods: {
toastSuccess (message, title = undefined) { toastSuccess (message, title = undefined) {
if (title === undefined) { if (title === undefined) {
title = this.$t('notification:general:success') title = this.$t('notification:general.success')
} }
this.toast(message, { title, variant: 'success' }) this.toast(message, { title, variant: 'success' })
@ -10,15 +10,23 @@ export default {
toastWarning (message, title = undefined) { toastWarning (message, title = undefined) {
if (title === undefined) { if (title === undefined) {
title = this.$t('notification:general:warning') title = this.$t('notification:general.warning')
} }
this.toast(message, { title, variant: 'warning' }) this.toast(message, { title, variant: 'warning' })
}, },
toastInfo (message, title = undefined) {
if (title === undefined) {
title = this.$t('notification:general.info')
}
this.toast(message, { title, variant: 'info' })
},
toastDanger (message, title = undefined) { toastDanger (message, title = undefined) {
if (title === undefined) { if (title === undefined) {
title = this.$t('notification:general:error') title = this.$t('notification:general.error')
} }
this.toast(message, { title, variant: 'danger' }) this.toast(message, { title, variant: 'danger' })
@ -28,6 +36,14 @@ export default {
this.$root.$bvToast.toast(msg, opt) this.$root.$bvToast.toast(msg, opt)
}, },
getToastMessage (err) {
if (err.message && err.message.startsWith('notification')) {
return this.$t(`notification:${err.message.substring('notification.'.length)}`)
}
return err.message
},
toastErrorHandler (opt) { toastErrorHandler (opt) {
if (typeof opt === 'string') { if (typeof opt === 'string') {
opt = { prefix: opt } opt = { prefix: opt }
@ -36,13 +52,13 @@ export default {
const { prefix, title } = opt const { prefix, title } = opt
return (err = {}) => { return (err = {}) => {
// only messages starting with 'notification:' or 'notification.' should be translated err.message = this.getToastMessage(err)
if (err.message && err.message.startsWith('notification')) {
err.message = this.$t(`notification:${err.message.substring('notification.'.length)}`)
}
// all other messages should be shown as they are // all other messages should be shown as they are
const msg = err.message ? `${prefix}: ${err.message}` : prefix const msg = err.message ? `${prefix}: ${err.message}` : prefix
this.toastDanger(msg, title) this.toastDanger(msg, title)
return err.message
} }
}, },
}, },

View File

@ -1,25 +1,49 @@
export default { export default {
methods: { methods: {
toastSuccess (message, title = this.$t('notification:general.success')) { toastSuccess (message, title = undefined) {
if (title === undefined) {
title = this.$t('notification:general.success')
}
this.toast(message, { title, variant: 'success' }) this.toast(message, { title, variant: 'success' })
}, },
toastWarning (message, title = this.$t('notification:general.warning')) { toastWarning (message, title = undefined) {
if (title === undefined) {
title = this.$t('notification:general.warning')
}
this.toast(message, { title, variant: 'warning' }) this.toast(message, { title, variant: 'warning' })
}, },
toastDanger (message, title = this.$t('notification:general.error')) { toastInfo (message, title = undefined) {
this.toast(message, { title, variant: 'danger' }) if (title === undefined) {
title = this.$t('notification:general.info')
}
this.toast(message, { title, variant: 'info' })
}, },
toastInfo (message, title = this.$t('notification:general.info')) { toastDanger (message, title = undefined) {
this.toast(message, { title, variant: 'info' }) if (title === undefined) {
title = this.$t('notification:general.error')
}
this.toast(message, { title, variant: 'danger' })
}, },
toast (msg, opt = { variant: 'success' }) { toast (msg, opt = { variant: 'success' }) {
this.$root.$bvToast.toast(msg, opt) this.$root.$bvToast.toast(msg, opt)
}, },
getToastMessage (err) {
if (err.message && err.message.startsWith('notification')) {
return this.$t(`notification:${err.message.substring('notification.'.length)}`)
}
return err.message
},
toastErrorHandler (opt) { toastErrorHandler (opt) {
if (typeof opt === 'string') { if (typeof opt === 'string') {
opt = { prefix: opt } opt = { prefix: opt }
@ -28,13 +52,13 @@ export default {
const { prefix, title } = opt const { prefix, title } = opt
return (err = {}) => { return (err = {}) => {
// only messages starting with 'notification:' or 'notification.' should be translated err.message = this.getToastMessage(err)
if (err.message && err.message.startsWith('notification')) {
err.message = this.$t(`notification:${err.message.substring('notification.'.length)}`)
}
// all other messages should be shown as they are // all other messages should be shown as they are
const msg = err.message ? `${prefix}: ${err.message}` : prefix const msg = err.message ? `${prefix}: ${err.message}` : prefix
this.toastDanger(msg, title) this.toastDanger(msg, title)
return err.message
} }
}, },
}, },

View File

@ -586,7 +586,7 @@ recordList:
deleted: Show deleted records deleted: Show deleted records
existing: Show existing records existing: Show existing records
recordOrganizer: recordOrganizer:
onRecordClick: On record click onRecordClick: Record display mode
openInSameTab: Open in the same tab openInSameTab: Open in the same tab
openInNewTab: Open in a new tab openInNewTab: Open in a new tab
openInModal: Open in a modal openInModal: Open in a modal
@ -614,7 +614,7 @@ recordOrganizer:
preview: preview:
label: 'Record Organizer block for module {{0}}. Label field {{1}}, Description field {{2}}. Value setting field: {{3}}, Sorted by position field: {{4}}.' label: 'Record Organizer block for module {{0}}. Label field {{1}}, Description field {{2}}. Value setting field: {{3}}, Sorted by position field: {{4}}.'
moduleNotSelected: Record Organizer module not selected moduleNotSelected: Record Organizer module not selected
addNewRecord: + Add new record addNewRecord: + Add
recordRevisions: recordRevisions:
label: Record revisions label: Record revisions