Merge branch 'feat/CW-3059' into feat/CW-3067-snooze
This commit is contained in:
@@ -7,12 +7,13 @@ class NotificationsAPI extends ApiClient {
|
||||
}
|
||||
|
||||
get({ page, status, type, sortOrder }) {
|
||||
const includesFilter = [status, type].filter(value => !!value);
|
||||
|
||||
return axios.get(this.url, {
|
||||
params: {
|
||||
page,
|
||||
status,
|
||||
type,
|
||||
sort_order: sortOrder,
|
||||
includes: includesFilter,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -27,20 +27,36 @@ describe('#NotificationAPI', () => {
|
||||
window.axios = originalAxios;
|
||||
});
|
||||
|
||||
it('#get', () => {
|
||||
notificationsAPI.get({
|
||||
page: 1,
|
||||
status: 'read',
|
||||
type: 'Conversation',
|
||||
sortOrder: 'desc',
|
||||
});
|
||||
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/notifications', {
|
||||
params: {
|
||||
describe('#get', () => {
|
||||
it('generates the API call if both params are available', () => {
|
||||
notificationsAPI.get({
|
||||
page: 1,
|
||||
status: 'read',
|
||||
type: 'Conversation',
|
||||
sort_order: 'desc',
|
||||
},
|
||||
status: 'snoozed',
|
||||
type: 'read',
|
||||
sortOrder: 'desc',
|
||||
});
|
||||
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/notifications', {
|
||||
params: {
|
||||
page: 1,
|
||||
sort_order: 'desc',
|
||||
includes: ['snoozed', 'read'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('generates the API call if one of the params are available', () => {
|
||||
notificationsAPI.get({
|
||||
page: 1,
|
||||
type: 'read',
|
||||
sortOrder: 'desc',
|
||||
});
|
||||
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/notifications', {
|
||||
params: {
|
||||
page: 1,
|
||||
sort_order: 'desc',
|
||||
includes: ['read'],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { applyInboxPageFilters, sortComparator } from './helpers';
|
||||
import { sortComparator } from './helpers';
|
||||
|
||||
export const getters = {
|
||||
getNotifications($state) {
|
||||
@@ -6,11 +6,8 @@ export const getters = {
|
||||
},
|
||||
getFilteredNotifications: $state => filters => {
|
||||
const sortOrder = filters.sortOrder === 'desc' ? 'newest' : 'oldest';
|
||||
const filteredNotifications = Object.values($state.records).filter(
|
||||
notification => applyInboxPageFilters(notification, filters)
|
||||
);
|
||||
const sortedNotifications = filteredNotifications.sort((a, b) =>
|
||||
sortComparator(a, b, sortOrder)
|
||||
const sortedNotifications = Object.values($state.records).sort((n1, n2) =>
|
||||
sortComparator(n1, n2, sortOrder)
|
||||
);
|
||||
return sortedNotifications;
|
||||
},
|
||||
|
||||
@@ -1,31 +1,3 @@
|
||||
export const filterByStatus = (snoozedUntil, filterStatus) =>
|
||||
filterStatus === 'snoozed' ? !!snoozedUntil : !snoozedUntil;
|
||||
|
||||
export const filterByType = (readAt, filterType) =>
|
||||
filterType === 'read' ? !!readAt : !readAt;
|
||||
|
||||
export const filterByTypeAndStatus = (
|
||||
readAt,
|
||||
snoozedUntil,
|
||||
filterType,
|
||||
filterStatus
|
||||
) => {
|
||||
const shouldFilterByStatus = filterByStatus(snoozedUntil, filterStatus);
|
||||
const shouldFilterByType = filterByType(readAt, filterType);
|
||||
return shouldFilterByStatus && shouldFilterByType;
|
||||
};
|
||||
|
||||
export const applyInboxPageFilters = (notification, filters) => {
|
||||
const { status, type } = filters;
|
||||
const { read_at: readAt, snoozed_until: snoozedUntil } = notification;
|
||||
|
||||
if (status && type)
|
||||
return filterByTypeAndStatus(readAt, snoozedUntil, type, status);
|
||||
if (status && !type) return filterByStatus(snoozedUntil, status);
|
||||
if (!status && type) return filterByType(readAt, type);
|
||||
return true;
|
||||
};
|
||||
|
||||
const INBOX_SORT_OPTIONS = {
|
||||
newest: 'desc',
|
||||
oldest: 'asc',
|
||||
|
||||
@@ -34,6 +34,8 @@ describe('#getters', () => {
|
||||
sortOrder: 'desc',
|
||||
};
|
||||
expect(getters.getFilteredNotifications(state)(filters)).toEqual([
|
||||
{ id: 1, read_at: '2024-02-07T11:42:39.988Z', snoozed_until: null },
|
||||
{ id: 2, read_at: null, snoozed_until: null },
|
||||
{
|
||||
id: 3,
|
||||
read_at: '2024-02-07T11:42:39.988Z',
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
import {
|
||||
filterByStatus,
|
||||
filterByType,
|
||||
filterByTypeAndStatus,
|
||||
applyInboxPageFilters,
|
||||
sortComparator,
|
||||
} from '../../notifications/helpers';
|
||||
import { sortComparator } from '../../notifications/helpers';
|
||||
|
||||
const notifications = [
|
||||
{
|
||||
@@ -45,126 +39,6 @@ const notifications = [
|
||||
},
|
||||
];
|
||||
|
||||
describe('#filterByStatus', () => {
|
||||
it('returns the notifications with snoozed status', () => {
|
||||
const filters = { status: 'snoozed' };
|
||||
notifications.forEach(notification => {
|
||||
expect(
|
||||
filterByStatus(notification.snoozed_until, filters.status)
|
||||
).toEqual(notification.snoozed_until !== null);
|
||||
});
|
||||
});
|
||||
it('returns true if the notification is snoozed', () => {
|
||||
const filters = { status: 'snoozed' };
|
||||
expect(
|
||||
filterByStatus(notifications[3].snoozed_until, filters.status)
|
||||
).toEqual(true);
|
||||
});
|
||||
it('returns false if the notification is not snoozed', () => {
|
||||
const filters = { status: 'snoozed' };
|
||||
expect(
|
||||
filterByStatus(notifications[2].snoozed_until, filters.status)
|
||||
).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#filterByType', () => {
|
||||
it('returns the notifications with read status', () => {
|
||||
const filters = { type: 'read' };
|
||||
notifications.forEach(notification => {
|
||||
expect(filterByType(notification.read_at, filters.type)).toEqual(
|
||||
notification.read_at !== null
|
||||
);
|
||||
});
|
||||
});
|
||||
it('returns true if the notification is read', () => {
|
||||
const filters = { type: 'read' };
|
||||
expect(filterByType(notifications[0].read_at, filters.type)).toEqual(true);
|
||||
});
|
||||
it('returns false if the notification is not read', () => {
|
||||
const filters = { type: 'read' };
|
||||
expect(filterByType(notifications[1].read_at, filters.type)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#filterByTypeAndStatus', () => {
|
||||
it('returns the notifications with type and status', () => {
|
||||
const filters = { type: 'read', status: 'snoozed' };
|
||||
notifications.forEach(notification => {
|
||||
expect(
|
||||
filterByTypeAndStatus(
|
||||
notification.read_at,
|
||||
notification.snoozed_until,
|
||||
filters.type,
|
||||
filters.status
|
||||
)
|
||||
).toEqual(
|
||||
notification.read_at !== null && notification.snoozed_until !== null
|
||||
);
|
||||
});
|
||||
});
|
||||
it('returns true if the notification is read and snoozed', () => {
|
||||
const filters = { type: 'read', status: 'snoozed' };
|
||||
expect(
|
||||
filterByTypeAndStatus(
|
||||
notifications[4].read_at,
|
||||
notifications[4].snoozed_until,
|
||||
filters.type,
|
||||
filters.status
|
||||
)
|
||||
).toEqual(true);
|
||||
});
|
||||
it('returns false if the notification is not read and snoozed', () => {
|
||||
const filters = { type: 'read', status: 'snoozed' };
|
||||
expect(
|
||||
filterByTypeAndStatus(
|
||||
notifications[3].read_at,
|
||||
notifications[3].snoozed_until,
|
||||
filters.type,
|
||||
filters.status
|
||||
)
|
||||
).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#applyInboxPageFilters', () => {
|
||||
it('returns the notifications with type and status', () => {
|
||||
const filters = { type: 'read', status: 'snoozed' };
|
||||
notifications.forEach(notification => {
|
||||
expect(applyInboxPageFilters(notification, filters)).toEqual(
|
||||
filterByTypeAndStatus(
|
||||
notification.read_at,
|
||||
notification.snoozed_until,
|
||||
filters.type,
|
||||
filters.status
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
it('returns the notifications with type only', () => {
|
||||
const filters = { type: 'read', status: null };
|
||||
notifications.forEach(notification => {
|
||||
expect(applyInboxPageFilters(notification, filters)).toEqual(
|
||||
filterByType(notification.read_at, filters.type)
|
||||
);
|
||||
});
|
||||
});
|
||||
it('returns the notifications with status only', () => {
|
||||
const filters = { type: null, status: 'snoozed' };
|
||||
notifications.forEach(notification => {
|
||||
expect(applyInboxPageFilters(notification, filters)).toEqual(
|
||||
filterByStatus(notification.snoozed_until, filters.status)
|
||||
);
|
||||
});
|
||||
});
|
||||
it('returns true if there are no filters', () => {
|
||||
const filters = { type: null, status: null };
|
||||
notifications.forEach(notification => {
|
||||
expect(applyInboxPageFilters(notification, filters)).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#sortComparator', () => {
|
||||
it('returns the notifications sorted by newest', () => {
|
||||
const sortOrder = 'newest';
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<with-label
|
||||
:label="label"
|
||||
:name="name"
|
||||
:has-error="hasError"
|
||||
:error-message="errorMessage"
|
||||
>
|
||||
<textarea
|
||||
:id="name"
|
||||
:name="name"
|
||||
autocomplete="off"
|
||||
:required="required"
|
||||
:placeholder="placeholder"
|
||||
:data-testid="dataTestid"
|
||||
:value="value"
|
||||
:rows="rows"
|
||||
:class="{
|
||||
'focus:outline-red-600 outline-red-600': hasError,
|
||||
'dark:outline-slate-600 dark:focus:outline-woot-500 outline-slate-200 focus:outline-woot-500':
|
||||
!hasError,
|
||||
'resize-none': !allowResize,
|
||||
}"
|
||||
class="block w-full p-3 border-none rounded-xl shadow-sm appearance-none outline outline-1 focus:outline focus:outline-2 text-slate-900 dark:text-slate-100 placeholder:text-slate-400 bg-white dark:bg-slate-800"
|
||||
@input="onInput"
|
||||
@blur="$emit('blur')"
|
||||
/>
|
||||
</with-label>
|
||||
</template>
|
||||
<script>
|
||||
import WithLabel from './WithLabel.vue';
|
||||
export default {
|
||||
components: {
|
||||
WithLabel,
|
||||
},
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
required: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
value: {
|
||||
type: [String, Number],
|
||||
default: '',
|
||||
},
|
||||
rows: {
|
||||
type: Number,
|
||||
default: 3,
|
||||
},
|
||||
allowResize: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
hasError: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
errorMessage: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
dataTestid: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onInput(e) {
|
||||
this.$emit('input', e.target.value);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user