Refactor markup and specs

This commit is contained in:
fayazara 2022-10-10 19:31:01 +05:30
parent 56bb2a9121
commit 47d8c9335d
11 changed files with 267 additions and 101 deletions

View file

@ -0,0 +1,71 @@
export const teams = [
{
id: 1,
name: '⚙️ sales team',
description: 'This is our internal sales team',
allow_auto_assign: true,
account_id: 1,
is_member: true,
},
{
id: 2,
name: '🤷‍♂️ fayaz',
description: 'Test',
allow_auto_assign: true,
account_id: 1,
is_member: true,
},
{
id: 3,
name: '🇮🇳 apac sales',
description: 'Sales team for France Territory',
allow_auto_assign: true,
account_id: 1,
is_member: true,
},
];
export const labels = [
{
id: 6,
title: 'sales',
description: 'sales team',
color: '#8EA20F',
show_on_sidebar: true,
},
{
id: 2,
title: 'billing',
description: 'billing',
color: '#4077DA',
show_on_sidebar: true,
},
{
id: 1,
title: 'snoozed',
description: 'Items marked for later',
color: '#D12F42',
show_on_sidebar: true,
},
{
id: 5,
title: 'mobile-app',
description: 'tech team',
color: '#2DB1CC',
show_on_sidebar: true,
},
{
id: 14,
title: 'human-resources-department-with-long-title',
description: 'Test',
color: '#FF6E09',
show_on_sidebar: true,
},
{
id: 22,
title: 'priority',
description: 'For important sales leads',
color: '#7E7CED',
show_on_sidebar: true,
},
];

View file

@ -0,0 +1,53 @@
import { MACRO_ACTION_TYPES } from '../../routes/dashboard/settings/macros/constants';
import { teams, labels } from './macrosFixtures';
import {
resolveActionName,
emptyMacro,
resolveLabels,
resolveTeamIds,
} from '../../routes/dashboard/settings/macros/macroHelper';
describe('#resolveActionName', () => {
it('resolve action name from key and return the correct label', () => {
expect(resolveActionName(MACRO_ACTION_TYPES[0].key)).toEqual(
MACRO_ACTION_TYPES[0].label
);
expect(resolveActionName(MACRO_ACTION_TYPES[1].key)).toEqual(
MACRO_ACTION_TYPES[1].label
);
expect(resolveActionName(MACRO_ACTION_TYPES[1].key)).not.toEqual(
MACRO_ACTION_TYPES[0].label
);
});
});
describe('#emptyMacro', () => {
const defaultMacro = {
name: '',
actions: [
{
action_name: 'assign_team',
action_params: [],
},
],
visibility: 'global',
};
it('returns the default macro', () => {
expect(emptyMacro).toEqual(defaultMacro);
});
});
describe('#resolveTeamIds', () => {
it('resolves team names from ids, and returns a joined string', () => {
const resolvedTeams = '⚙️ sales team, 🤷‍♂️ fayaz';
expect(resolveTeamIds(teams, [1, 2])).toEqual(resolvedTeams);
});
});
describe('#resolveLabels', () => {
it('resolves labels names from ids and returns a joined string', () => {
const resolvedLabels = 'sales, billing';
expect(resolveLabels(labels, ['sales', 'billing'])).toEqual(resolvedLabels);
});
});

View file

@ -88,12 +88,12 @@
"VISIBILITY": { "VISIBILITY": {
"LABEL": "Macro Visibility", "LABEL": "Macro Visibility",
"GLOBAL": { "GLOBAL": {
"LABEL": "Global", "LABEL": "Public",
"DESCRIPTION": "This macro is available globally for all agents in this account." "DESCRIPTION": "This macro is available publicly for all agents in this account."
}, },
"PERSONAL": { "PERSONAL": {
"LABEL": "Personal", "LABEL": "Private",
"DESCRIPTION": "This macro will be personal to you and not be available to others." "DESCRIPTION": "This macro will be private to you and not be available to others."
} }
} }
}, },

View file

@ -15,8 +15,8 @@ import {
resolveActionName, resolveActionName,
resolveTeamIds, resolveTeamIds,
resolveLabels, resolveLabels,
resolveSendEmailToTeam,
} from 'dashboard/routes/dashboard/settings/macros/macroHelper.js'; } from 'dashboard/routes/dashboard/settings/macros/macroHelper.js';
import { mapGetters } from 'vuex';
export default { export default {
props: { props: {
@ -37,23 +37,25 @@ export default {
}; };
}); });
}, },
...mapGetters({
labels: 'labels/getLabels',
teams: 'teams/getTeams',
}),
}, },
methods: { methods: {
getActionValue(key, params) { getActionValue(key, params) {
switch (key) { switch (key) {
case 'assign_team': case 'assign_team':
return resolveTeamIds(this.$store, params); return resolveTeamIds(this.teams, params);
case 'add_label': case 'add_label':
return resolveLabels(this.$store, params); return resolveLabels(this.labels, params);
case 'send_email_to_team':
case 'send_email_transcript':
return resolveSendEmailToTeam(params[0]);
case 'mute_conversation': case 'mute_conversation':
case 'snooze_conversation': case 'snooze_conversation':
case 'resolve_conversation': case 'resolve_conversation':
return null; return null;
case 'send_webhook_event': case 'send_webhook_event':
case 'send_message': case 'send_message':
case 'send_email_transcript':
return params[0]; return params[0];
default: default:
return ''; return '';

View file

@ -31,45 +31,12 @@
</th> </th>
</thead> </thead>
<tbody> <tbody>
<tr v-for="(macro, index) in records" :key="index"> <macros-table-row
<td>{{ macro.name }}</td> v-for="(macro, index) in records"
<td> :key="index"
<div class="avatar-container"> :macro="macro"
<thumbnail :username="macro.created_by.name" size="24px" /> @delete="openDeletePopup(macro, index)"
<span class="ml-2">{{ macro.created_by.name }}</span> />
</div>
</td>
<td>
<div class="avatar-container">
<thumbnail :username="macro.updated_by.name" size="24px" />
<span class="ml-2">{{ macro.updated_by.name }}</span>
</div>
</td>
<td class="macro-visibility">{{ macro.visibility }}</td>
<td class="button-wrapper">
<router-link
:to="addAccountScoping(`settings/macros/${macro.id}/edit`)"
>
<woot-button
v-tooltip.top="$t('MACROS.FORM.EDIT')"
variant="smooth"
size="tiny"
color-scheme="secondary"
class-names="grey-btn"
icon="edit"
/>
</router-link>
<woot-button
v-tooltip.top="$t('MACROS.FORM.DELETE')"
variant="smooth"
color-scheme="alert"
size="tiny"
icon="dismiss-circle"
class-names="grey-btn"
@click="openDeletePopup(macro, index)"
/>
</td>
</tr>
</tbody> </tbody>
</table> </table>
</div> </div>
@ -93,11 +60,11 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin'; import alertMixin from 'shared/mixins/alertMixin';
import Thumbnail from 'dashboard/components/widgets/Thumbnail';
import accountMixin from 'dashboard/mixins/account.js'; import accountMixin from 'dashboard/mixins/account.js';
import MacrosTableRow from './MacrosTableRow';
export default { export default {
components: { components: {
Thumbnail, MacrosTableRow,
}, },
mixins: [alertMixin, accountMixin], mixins: [alertMixin, accountMixin],
data() { data() {
@ -112,7 +79,6 @@ export default {
records: ['macros/getMacros'], records: ['macros/getMacros'],
uiFlags: 'macros/getUIFlags', uiFlags: 'macros/getUIFlags',
}), }),
// Delete Modal
deleteConfirmText() { deleteConfirmText() {
return `${this.$t('MACROS.DELETE.CONFIRM.YES')} ${ return `${this.$t('MACROS.DELETE.CONFIRM.YES')} ${
this.selectedResponse.name this.selectedResponse.name
@ -155,18 +121,3 @@ export default {
}, },
}; };
</script> </script>
<style scoped lang="scss">
.avatar-container {
display: flex;
align-items: center;
span {
margin-left: var(--space-one);
}
}
.macro-visibility {
text-transform: capitalize;
}
</style>

View file

@ -15,15 +15,16 @@
import MacroForm from './MacroForm'; import MacroForm from './MacroForm';
import { MACRO_ACTION_TYPES } from './constants'; import { MACRO_ACTION_TYPES } from './constants';
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import { getDropdownValues, emptyMacro } from './macroHelper'; import { emptyMacro } from './macroHelper';
import actionQueryGenerator from 'dashboard/helper/actionQueryGenerator.js'; import actionQueryGenerator from 'dashboard/helper/actionQueryGenerator.js';
import alertMixin from 'shared/mixins/alertMixin'; import alertMixin from 'shared/mixins/alertMixin';
import macrosMixin from './macrosMixin';
export default { export default {
components: { components: {
MacroForm, MacroForm,
}, },
mixins: [alertMixin], mixins: [alertMixin, macrosMixin],
provide() { provide() {
return { return {
macroActionTypes: this.macroActionTypes, macroActionTypes: this.macroActionTypes,
@ -39,6 +40,8 @@ export default {
computed: { computed: {
...mapGetters({ ...mapGetters({
uiFlags: 'macros/getUIFlags', uiFlags: 'macros/getUIFlags',
labels: 'labels/getLabels',
teams: 'teams/getTeams',
}), }),
macroId() { macroId() {
return this.$route.params.macroId; return this.$route.params.macroId;
@ -86,12 +89,12 @@ export default {
).inputType; ).inputType;
if (inputType === 'multi_select') { if (inputType === 'multi_select') {
actionParams = [ actionParams = [
...getDropdownValues(action.action_name, this.$store), ...this.getDropdownValues(action.action_name, this.$store),
].filter(item => [...action.action_params].includes(item.id)); ].filter(item => [...action.action_params].includes(item.id));
} else if (inputType === 'team_message') { } else if (inputType === 'team_message') {
actionParams = { actionParams = {
team_ids: [ team_ids: [
...getDropdownValues(action.action_name, this.$store), ...this.getDropdownValues(action.action_name, this.$store),
].filter(item => ].filter(item =>
[...action.action_params[0].team_ids].includes(item.id) [...action.action_params[0].team_ids].includes(item.id)
), ),

View file

@ -37,12 +37,15 @@
<script> <script>
import ActionInput from 'dashboard/components/widgets/AutomationActionInput'; import ActionInput from 'dashboard/components/widgets/AutomationActionInput';
import MacroActionButton from './ActionButton.vue'; import MacroActionButton from './ActionButton.vue';
import { getDropdownValues } from './macroHelper'; import macrosMixin from './macrosMixin';
import { mapGetters } from 'vuex';
export default { export default {
components: { components: {
ActionInput, ActionInput,
MacroActionButton, MacroActionButton,
}, },
mixins: [macrosMixin],
inject: ['macroActionTypes', '$v'], inject: ['macroActionTypes', '$v'],
props: { props: {
singleNode: { singleNode: {
@ -59,6 +62,10 @@ export default {
}, },
}, },
computed: { computed: {
...mapGetters({
labels: 'labels/getLabels',
teams: 'teams/getTeams',
}),
actionData: { actionData: {
get() { get() {
return this.value; return this.value;
@ -81,7 +88,7 @@ export default {
}, },
methods: { methods: {
dropdownValues() { dropdownValues() {
return getDropdownValues(this.value.action_name, this.$store); return this.getDropdownValues(this.value.action_name, this.$store);
}, },
hasError(v) { hasError(v) {
return !!(v.action_params.$dirty && v.action_params.$error); return !!(v.action_params.$dirty && v.action_params.$error);

View file

@ -134,6 +134,15 @@ export default {
color: var(--s-500); color: var(--s-500);
} }
.title {
display: block;
margin: 0;
font-size: var(--font-size-small);
font-weight: var(--font-weight-medium);
line-height: 1.8;
color: var(--color-body);
}
.visibility-check { .visibility-check {
position: absolute; position: absolute;
color: var(--w-500); color: var(--w-500);

View file

@ -0,0 +1,74 @@
<template>
<tr>
<td>{{ macro.name }}</td>
<td>
<div class="avatar-container">
<thumbnail :username="macro.created_by.name" size="24px" />
<span class="ml-2">{{ macro.created_by.name }}</span>
</div>
</td>
<td>
<div class="avatar-container">
<thumbnail :username="macro.updated_by.name" size="24px" />
<span class="ml-2">{{ macro.updated_by.name }}</span>
</div>
</td>
<td>{{ visibilityLabel }}</td>
<td class="button-wrapper">
<router-link :to="addAccountScoping(`settings/macros/${macro.id}/edit`)">
<woot-button
v-tooltip.top="$t('MACROS.FORM.EDIT')"
variant="smooth"
size="tiny"
color-scheme="secondary"
class-names="grey-btn"
icon="edit"
/>
</router-link>
<woot-button
v-tooltip.top="$t('MACROS.FORM.DELETE')"
variant="smooth"
color-scheme="alert"
size="tiny"
icon="dismiss-circle"
class-names="grey-btn"
@click="$emit('delete')"
/>
</td>
</tr>
</template>
<script>
import Thumbnail from 'dashboard/components/widgets/Thumbnail';
import accountMixin from 'dashboard/mixins/account.js';
export default {
components: {
Thumbnail,
},
mixins: [accountMixin],
props: {
macro: {
type: Object,
required: true,
},
},
computed: {
visibilityLabel() {
return this.macro.visibility === 'global'
? this.$t('MACROS.EDITOR.VISIBILITY.GLOBAL.LABEL')
: this.$t('MACROS.EDITOR.VISIBILITY.PERSONAL.LABEL');
},
},
};
</script>
<style scoped lang="scss">
.avatar-container {
display: flex;
align-items: center;
span {
margin-left: var(--space-one);
}
}
</style>

View file

@ -4,48 +4,24 @@ export const resolveActionName = key => {
return macroActionTypes.find(i => i.key === key).label; return macroActionTypes.find(i => i.key === key).label;
}; };
export const resolveTeamIds = (store, ids) => { export const resolveTeamIds = (teams, ids) => {
const allTeams = store.getters['teams/getTeams'];
return ids return ids
.map(id => { .map(id => {
const team = allTeams.find(i => i.id === id); const team = teams.find(i => i.id === id);
return team ? team.name : ''; return team ? team.name : '';
}) })
.join(', '); .join(', ');
}; };
export const resolveLabels = (store, ids) => { export const resolveLabels = (labels, ids) => {
const allLabels = store.getters['labels/getLabels'];
return ids return ids
.map(id => { .map(id => {
const label = allLabels.find(i => i.title === id); const label = labels.find(i => i.title === id);
return label ? label.title : ''; return label ? label.title : '';
}) })
.join(', '); .join(', ');
}; };
export const resolveSendEmailToTeam = obj => {
return ` ${obj.message} -
${resolveTeamIds(obj.team_ids)}`;
};
export const getDropdownValues = (type, store) => {
switch (type) {
case 'assign_team':
case 'send_email_to_team':
return store.getters['teams/getTeams'];
case 'add_label':
return store.getters['labels/getLabels'].map(i => {
return {
id: i.title,
name: i.title,
};
});
default:
return [];
}
};
export const emptyMacro = { export const emptyMacro = {
name: '', name: '',
actions: [ actions: [

View file

@ -0,0 +1,20 @@
export default {
methods: {
getDropdownValues(type) {
switch (type) {
case 'assign_team':
case 'send_email_to_team':
return this.teams;
case 'add_label':
return this.labels.map(i => {
return {
id: i.title,
name: i.title,
};
});
default:
return [];
}
},
},
};