Commit f344fa1d authored by Mark Florian's avatar Mark Florian

Merge branch 'papa-translations' into 'master'

Build papaparse alert component and translate errors

See merge request gitlab-org/gitlab!66683
parents 89dec6ec 91fd2b5d
<script>
import { GlAlert, GlLoadingIcon, GlTable } from '@gitlab/ui';
import { GlLoadingIcon, GlTable } from '@gitlab/ui';
import Papa from 'papaparse';
import PapaParseAlert from '~/vue_shared/components/papa_parse_alert.vue';
export default {
components: {
PapaParseAlert,
GlTable,
GlAlert,
GlLoadingIcon,
},
props: {
......@@ -17,7 +18,7 @@ export default {
data() {
return {
items: [],
errorMessage: null,
papaParseErrors: [],
loading: true,
};
},
......@@ -26,7 +27,7 @@ export default {
this.items = parsed.data;
if (parsed.errors.length) {
this.errorMessage = parsed.errors.map((e) => e.message).join('. ');
this.papaParseErrors = parsed.errors;
}
this.loading = false;
......@@ -40,9 +41,7 @@ export default {
<gl-loading-icon class="gl-mt-5" size="lg" />
</div>
<div v-else>
<gl-alert v-if="errorMessage" variant="danger" :dismissible="false">
{{ errorMessage }}
</gl-alert>
<papa-parse-alert v-if="papaParseErrors.length" :papa-parse-errors="papaParseErrors" />
<gl-table
:empty-text="__('No CSV data to display.')"
:items="items"
......
<script>
import { GlAlert } from '@gitlab/ui';
import { s__ } from '~/locale';
export default {
components: {
GlAlert,
},
i18n: {
genericErrorMessage: s__('CsvParser|Failed to render the CSV file for the following reasons:'),
MissingQuotes: s__('CsvParser|Quoted field unterminated'),
InvalidQuotes: s__('CsvParser|Trailing quote on quoted field is malformed'),
UndetectableDelimiter: s__('CsvParser|Unable to auto-detect delimiter; defaulted to ","'),
TooManyFields: s__('CsvParser|Too many fields'),
TooFewFields: s__('CsvParser|Too few fields'),
},
props: {
papaParseErrors: {
type: Array,
required: false,
default: () => [],
},
},
computed: {
errorMessages() {
const errorMessages = this.papaParseErrors.map(
(error) => this.$options.i18n[error.code] ?? error.message,
);
return new Set(errorMessages);
},
},
};
</script>
<template>
<gl-alert variant="danger" :dismissible="false">
{{ $options.i18n.genericErrorMessage }}
<ul class="gl-mb-0!">
<li v-for="error in errorMessages" :key="error">
{{ error }}
</li>
</ul>
</gl-alert>
</template>
......@@ -9642,6 +9642,24 @@ msgstr ""
msgid "Crowd"
msgstr ""
msgid "CsvParser|Failed to render the CSV file for the following reasons:"
msgstr ""
msgid "CsvParser|Quoted field unterminated"
msgstr ""
msgid "CsvParser|Too few fields"
msgstr ""
msgid "CsvParser|Too many fields"
msgstr ""
msgid "CsvParser|Trailing quote on quoted field is malformed"
msgstr ""
msgid "CsvParser|Unable to auto-detect delimiter; defaulted to \",\""
msgstr ""
msgid "Current"
msgstr ""
......
import { GlAlert, GlLoadingIcon, GlTable } from '@gitlab/ui';
import { GlLoadingIcon, GlTable } from '@gitlab/ui';
import { getAllByRole } from '@testing-library/dom';
import { shallowMount, mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import CSVViewer from '~/blob/csv/csv_viewer.vue';
import CsvViewer from '~/blob/csv/csv_viewer.vue';
import PapaParseAlert from '~/vue_shared/components/papa_parse_alert.vue';
const validCsv = 'one,two,three';
const brokenCsv = '{\n "json": 1,\n "key": [1, 2, 3]\n}';
......@@ -11,7 +12,7 @@ describe('app/assets/javascripts/blob/csv/csv_viewer.vue', () => {
let wrapper;
const createComponent = ({ csv = validCsv, mountFunction = shallowMount } = {}) => {
wrapper = mountFunction(CSVViewer, {
wrapper = mountFunction(CsvViewer, {
propsData: {
csv,
},
......@@ -20,7 +21,7 @@ describe('app/assets/javascripts/blob/csv/csv_viewer.vue', () => {
const findCsvTable = () => wrapper.findComponent(GlTable);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findAlert = () => wrapper.findComponent(GlAlert);
const findAlert = () => wrapper.findComponent(PapaParseAlert);
afterEach(() => {
wrapper.destroy();
......@@ -35,12 +36,12 @@ describe('app/assets/javascripts/blob/csv/csv_viewer.vue', () => {
});
describe('when the CSV contains errors', () => {
it('should render alert', async () => {
it('should render alert with correct props', async () => {
createComponent({ csv: brokenCsv });
await nextTick;
expect(findAlert().props()).toMatchObject({
variant: 'danger',
papaParseErrors: [{ code: 'UndetectableDelimiter' }],
});
});
});
......
import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import PapaParseAlert from '~/vue_shared/components/papa_parse_alert.vue';
describe('app/assets/javascripts/vue_shared/components/papa_parse_alert.vue', () => {
let wrapper;
const createComponent = ({ errorMessages } = {}) => {
wrapper = shallowMount(PapaParseAlert, {
propsData: {
papaParseErrors: errorMessages,
},
});
};
const findAlert = () => wrapper.findComponent(GlAlert);
afterEach(() => {
wrapper.destroy();
});
it('should render alert with correct props', async () => {
createComponent({ errorMessages: [{ code: 'MissingQuotes' }] });
await nextTick;
expect(findAlert().props()).toMatchObject({
variant: 'danger',
});
expect(findAlert().text()).toContain(
'Failed to render the CSV file for the following reasons:',
);
expect(findAlert().text()).toContain('Quoted field unterminated');
});
it('should render original message if no translation available', async () => {
createComponent({
errorMessages: [{ code: 'NotDefined', message: 'Error code is undefined' }],
});
await nextTick;
expect(findAlert().text()).toContain('Error code is undefined');
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment