diff --git a/packages/geoadmin-log/src/Message.ts b/packages/geoadmin-log/src/Message.ts index ad6e767c51..38310c33c6 100644 --- a/packages/geoadmin-log/src/Message.ts +++ b/packages/geoadmin-log/src/Message.ts @@ -3,22 +3,37 @@ export class Message { msg: string params: Record - + /** + * Flag telling that the user has seen the error and closed it, to avoid seeing again + */ + isAcknowledged: boolean + sourceId? : string /** * @param {string} msg Translation key message * @param {any} params Translation params to pass to i18n (used for message formatting) */ - constructor(msg: string, params: Record | null = null) { + constructor(msgParams: Record ) { + const { + msg = 'unknown_message', + params = {}, + isAcknowledged = false, + sourceId = undefined + } = msgParams this.msg = msg - this.params = params ?? {} + this.params = params + this.isAcknowledged = isAcknowledged + this.sourceId = sourceId } + // It is important that the Acknowledgement of the message is not part of the equality check. + // As this is used to stop new errors that have the same source to be dispatched. isEquals(object: Message) { return ( object instanceof Message && object.msg === this.msg && Object.keys(this.params).length === Object.keys(object.params).length && - Object.keys(this.params).every((key) => this.params[key] === object.params[key]) + Object.keys(this.params).every((key) => this.params[key] === object.params[key]) && + this.sourceId === object.sourceId ) } } diff --git a/packages/geoadmin-log/src/__test__/message.spec.js b/packages/geoadmin-log/src/__test__/message.spec.js new file mode 100644 index 0000000000..681b9658c3 --- /dev/null +++ b/packages/geoadmin-log/src/__test__/message.spec.js @@ -0,0 +1,91 @@ +import { expect } from 'chai' +import { ErrorMessage } from 'packages/geoadmin-log/src/Message' +import { describe, it } from 'vitest' + +describe('Unit Tests for messages', () => { + describe('checking equality between messages', () => { + it('Ensure that errors with no sources are considered equal too when the rest is equal', () => { + const msg1 = new ErrorMessage({ msg: 'test text', params: {} }) + const msg2 = new ErrorMessage({ msg: 'test text', params: {} }) + const msg3 = new ErrorMessage({ + msg: 'test text', + params: { key1: 'value1', key2: 'value2' }, + }) + const msg4 = new ErrorMessage({ + msg: 'test text', + params: { key1: 'value1', key2: 'value2' }, + }) + expect(msg1.isEquals(msg1)).to.equal(true) + expect(msg1.isEquals(msg2)).to.equal(true) + expect(msg3.isEquals(msg3)).to.equal(true) + expect(msg3.isEquals(msg4)).to.equal(true) + }) + it('detects equality and inequality between two messages', () => { + // messages without parameter + const simpleTextMsg1 = new ErrorMessage({ + msg: 'test text', + params: {}, + sourceId: 'test_source_12345', + }) + const copyOfimpleTextMsg1 = new ErrorMessage({ + msg: 'test text', + params: {}, + sourceId: 'test_source_12345', + }) + const simpleTextMsg1OtherSource = new ErrorMessage({ + msg: 'test text', + params: {}, + sourceId: 'test_source_02345', + }) + const simpleTextMsg2 = new ErrorMessage({ + msg: 'Another test text', + params: {}, + sourceId: 'test_source_12345', + }) + + expect(simpleTextMsg1.isEquals(simpleTextMsg1)).to.be.true + expect(simpleTextMsg1.isEquals(copyOfimpleTextMsg1)).to.be.true + expect(simpleTextMsg1.isEquals(simpleTextMsg1OtherSource)).to.be.false // different source + expect(simpleTextMsg1.isEquals(simpleTextMsg2)).to.be.false // different msg + + // messages with parameters + const paramMsg1 = new ErrorMessage({ + msg: 'test text', + params: { key1: 'value1', key2: 'value2' }, + sourceId: 'test_source_12345', + }) + const copyOfParamMsg1 = new ErrorMessage({ + msg: 'test text', + params: { key1: 'value1', key2: 'value2' }, + sourceId: 'test_source_12345', + }) + const paramMsg2 = new ErrorMessage({ + msg: 'test text', + params: { key1: 'value2', key2: 'value2' }, + sourceId: 'test_source_12345', + }) + + const paramMsg3 = new ErrorMessage({ + msg: 'test text', + params: { key2: 'value1', key3: 'value2' }, + sourceId: 'test_source_12345', + }) + const paramMsg4 = new ErrorMessage({ + msg: 'Another test text', + params: { key1: 'value1', key2: 'value2' }, + sourceId: 'test_source_12345', + }) + expect(simpleTextMsg1.isEquals(paramMsg1)).to.be.false // empty params vs params + expect(paramMsg1.isEquals(paramMsg1)).to.be.true + expect(paramMsg1.isEquals(copyOfParamMsg1)).to.be.true + expect(paramMsg1.isEquals(paramMsg4)).to.be.false // different text with params + expect(paramMsg1.isEquals(paramMsg2)).to.be.false // different values in params + expect(paramMsg1.isEquals(paramMsg3)).to.be.false // different keys in params + }) + it('ensure that acknowledement of a message does not change equality', () => { + const msg1 = new ErrorMessage({ msg: 'test', params: {}, isAcknowledged: false }) + const msg2 = new ErrorMessage({ msg: 'test', params: {}, isAcknowledged: true }) + expect(msg1.isEquals(msg2)).to.be.true + }) + }) +}) diff --git a/packages/mapviewer/src/App.vue b/packages/mapviewer/src/App.vue index b98c0792d9..49eac03f39 100644 --- a/packages/mapviewer/src/App.vue +++ b/packages/mapviewer/src/App.vue @@ -23,7 +23,7 @@ const dispatcher = { dispatcher: 'App.vue' } let debouncedOnResize const showFeedbackPopup = computed(() => { - return store.state.ui.errors.size + store.state.ui.warnings.size > 0 + return store.getters.getFirstError || store.getters.getFirstWarning }) const showDebugToolbar = computed(() => !IS_TESTING_WITH_CYPRESS && store.getters.hasDevSiteWarning) diff --git a/packages/mapviewer/src/api/errorQueues.api.js b/packages/mapviewer/src/api/errorQueues.api.js index 4f2017bf86..b558592110 100644 --- a/packages/mapviewer/src/api/errorQueues.api.js +++ b/packages/mapviewer/src/api/errorQueues.api.js @@ -1,9 +1,12 @@ import { ErrorMessage } from '@geoadmin/log/Message' export function getStandardErrorMessage(query, urlParamName) { - return new ErrorMessage('url_parameter_error', { - param: urlParamName, - value: query, + return new ErrorMessage({ + msg: 'url_parameter_error', + params: { + param: urlParamName, + value: query, + }, }) } diff --git a/packages/mapviewer/src/modules/drawing/DrawingModule.vue b/packages/mapviewer/src/modules/drawing/DrawingModule.vue index 3f3ad2d273..3acf457ed8 100644 --- a/packages/mapviewer/src/modules/drawing/DrawingModule.vue +++ b/packages/mapviewer/src/modules/drawing/DrawingModule.vue @@ -138,8 +138,11 @@ watch(availableIconSets, () => { const icon = getIcon(iconArgs, null /*iconStyle*/, availableIconSets.value, () => { store.dispatch('addWarnings', { warnings: [ - new WarningMessage('kml_icon_set_not_found', { - iconSetName: iconArgs.set, + new WarningMessage({ + msg: 'kml_icon_set_not_found', + params: { + iconSetName: iconArgs.set, + }, }), ], ...dispatcher, diff --git a/packages/mapviewer/src/modules/infobox/components/styling/FeatureStyleEdit.vue b/packages/mapviewer/src/modules/infobox/components/styling/FeatureStyleEdit.vue index 4ec98ea59a..ebdc5fe2d2 100644 --- a/packages/mapviewer/src/modules/infobox/components/styling/FeatureStyleEdit.vue +++ b/packages/mapviewer/src/modules/infobox/components/styling/FeatureStyleEdit.vue @@ -258,8 +258,8 @@ function mediaTypes() { {{ t('modify_description') }}