diff --git a/app/javascript/dashboard/routes/dashboard/settings/sla/AddSLA.vue b/app/javascript/dashboard/routes/dashboard/settings/sla/AddSLA.vue new file mode 100644 index 000000000..b7c86151e --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/sla/AddSLA.vue @@ -0,0 +1,122 @@ + + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/sla/EditSLA.vue b/app/javascript/dashboard/routes/dashboard/settings/sla/EditSLA.vue new file mode 100644 index 000000000..a8f88bdbd --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/sla/EditSLA.vue @@ -0,0 +1,125 @@ + + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/sla/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/sla/Index.vue new file mode 100644 index 000000000..2d01d4ba5 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/sla/Index.vue @@ -0,0 +1,202 @@ + + + + diff --git a/app/javascript/dashboard/routes/dashboard/settings/sla/sla.routes.js b/app/javascript/dashboard/routes/dashboard/settings/sla/sla.routes.js new file mode 100644 index 000000000..27fdc161a --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/sla/sla.routes.js @@ -0,0 +1,32 @@ +import { frontendURL } from '../../../../helper/URLHelper'; + +const SettingsContent = () => import('../Wrapper.vue'); +const Index = () => import('./Index.vue'); + +export default { + routes: [ + { + path: frontendURL('accounts/:accountId/settings/sla'), + component: SettingsContent, + props: { + headerTitle: 'SLA_MGMT.HEADER', + icon: 'tag', + showNewButton: false, + }, + children: [ + { + path: '', + name: 'sla_wrapper', + roles: ['administrator'], + redirect: 'list', + }, + { + path: 'list', + name: 'sla_list', + roles: ['administrator'], + component: Index, + }, + ], + }, + ], +}; diff --git a/app/javascript/dashboard/routes/dashboard/settings/sla/specs/validationMixin.spec.js b/app/javascript/dashboard/routes/dashboard/settings/sla/specs/validationMixin.spec.js new file mode 100644 index 000000000..8e1628bdb --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/sla/specs/validationMixin.spec.js @@ -0,0 +1,72 @@ +import { shallowMount, createLocalVue } from '@vue/test-utils'; +import VueI18n from 'vue-i18n'; +import Vuelidate from 'vuelidate'; + +import validationMixin from '../validationMixin'; +import validations from '../validations'; +import i18n from 'dashboard/i18n'; +const localVue = createLocalVue(); + +localVue.use(VueI18n); +localVue.use(Vuelidate); +const i18nConfig = new VueI18n({ + locale: 'en', + messages: i18n, +}); +const Component = { + render() {}, + title: 'TestComponent', + mixins: [validationMixin], + validations, +}; + +describe('validationMixin', () => { + it('it should return empty error message if valid label name passed', async () => { + const wrapper = shallowMount(Component, { + i18n: i18nConfig, + localVue, + data() { + return { title: 'sales' }; + }, + }); + wrapper.vm.$v.$touch(); + expect(wrapper.vm.getLabelTitleErrorMessage).toBe(''); + }); + it('it should return label required error message if empty name is passed', async () => { + const wrapper = shallowMount(Component, { + i18n: i18nConfig, + localVue, + data() { + return { title: '' }; + }, + }); + wrapper.vm.$v.$touch(); + expect(wrapper.vm.getLabelTitleErrorMessage).toBe('Label name is required'); + }); + it('it should return label minimum length error message if one charceter label name is passed', async () => { + const wrapper = shallowMount(Component, { + i18n: i18nConfig, + localVue, + data() { + return { title: 's' }; + }, + }); + wrapper.vm.$v.$touch(); + expect(wrapper.vm.getLabelTitleErrorMessage).toBe( + 'Minimum length 2 is required' + ); + }); + it('it should return invalid character error message if invalid lable name passed', async () => { + const wrapper = shallowMount(Component, { + i18n: i18nConfig, + localVue, + data() { + return { title: 'sales enquiry' }; + }, + }); + wrapper.vm.$v.$touch(); + expect(wrapper.vm.getLabelTitleErrorMessage).toBe( + 'Only Alphabets, Numbers, Hyphen and Underscore are allowed' + ); + }); +}); diff --git a/app/javascript/dashboard/routes/dashboard/settings/sla/specs/validations.spec.js b/app/javascript/dashboard/routes/dashboard/settings/sla/specs/validations.spec.js new file mode 100644 index 000000000..47c8c21df --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/sla/specs/validations.spec.js @@ -0,0 +1,10 @@ +import { validLabelCharacters } from '../validations'; + +describe('#validLabelCharacters', () => { + it('validates the label', () => { + expect(validLabelCharacters('')).toEqual(false); + expect(validLabelCharacters('str str')).toEqual(false); + expect(validLabelCharacters('str_str')).toEqual(true); + expect(validLabelCharacters('str-str')).toEqual(true); + }); +}); diff --git a/app/javascript/dashboard/routes/dashboard/settings/sla/validationMixin.js b/app/javascript/dashboard/routes/dashboard/settings/sla/validationMixin.js new file mode 100644 index 000000000..74c2a2fbf --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/sla/validationMixin.js @@ -0,0 +1,17 @@ +export default { + computed: { + getLabelTitleErrorMessage() { + let errorMessage = ''; + if (!this.$v.title.$error) { + errorMessage = ''; + } else if (!this.$v.title.required) { + errorMessage = this.$t('SLA_MGMT.FORM.NAME.REQUIRED_ERROR'); + } else if (!this.$v.title.minLength) { + errorMessage = this.$t('SLA_MGMT.FORM.NAME.MINIMUM_LENGTH_ERROR'); + } else if (!this.$v.title.validLabelCharacters) { + errorMessage = this.$t('SLA_MGMT.FORM.NAME.VALID_ERROR'); + } + return errorMessage; + }, + }, +}; diff --git a/app/javascript/dashboard/routes/dashboard/settings/sla/validations.js b/app/javascript/dashboard/routes/dashboard/settings/sla/validations.js new file mode 100644 index 000000000..0a2373a06 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/sla/validations.js @@ -0,0 +1,16 @@ +import { required, minLength } from 'vuelidate/lib/validators'; + +export const validLabelCharacters = (str = '') => !!str && !str.includes(' '); + +export default { + title: { + required, + minLength: minLength(2), + validLabelCharacters, + }, + description: {}, + color: { + required, + }, + showOnSidebar: {}, +};