Skip to content

Commit

Permalink
feat: timeline counters [WTEL-3534]
Browse files Browse the repository at this point in the history
  • Loading branch information
dlohvinov committed May 13, 2024
1 parent af99657 commit 59c0a05
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 31 deletions.
32 changes: 31 additions & 1 deletion src/modules/contacts/modules/timeline/api/TimelineAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,34 @@ const listHandler = (items) => {
}
};

export default { getList };
const getCounters = async (params) => {
const defaultObject = {
callsCount: 0,
chatsCount: 0,
dateFrom: Date.now(),
dateTo: Date.now(),
};

const {
parentId,
} = applyTransform(params, [
sanitize(['parentId']),
]);

try {
const response = await timeline.getTimelineCounter(parentId);
return applyTransform(response.data, [
snakeToCamel(),
merge(defaultObject),
]);
} catch (err) {
throw applyTransform(err, [
notify,
]);
}
};

export default {
getList,
getCounters,
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
:collapsed="collapsed"
:type="TimelinePinType.DAY"
:text="dayNumber"
:first="first"
:last="last && collapsed"
@click="toggle"
></timeline-pin>
Expand Down Expand Up @@ -67,6 +68,10 @@ const props = defineProps({
type: Array,
default: () => [],
},
first: {
type: Boolean,
default: false,
},
last: {
type: Boolean,
default: false,
Expand Down
29 changes: 24 additions & 5 deletions src/modules/contacts/modules/timeline/components/the-timeline.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,40 @@
<template #header>
<timeline-header
:list="dataList"
:contact-id="contactId"
/>
</template>

<template #content>
<wt-loader
<div
class="loader-wrapper"
v-if="isLoading"
/>
>
<wt-loader />
</div>

<wt-dummy
v-else-if="!dataList.length"
:src="darkMode ? dummyDark : dummyLight"
/>

<day-timeline-row
v-else
v-for="({ dayTimestamp, callsCount, chatsCount, items }, key) of dataList"
:key="dayTimestamp"
:timestamp="dayTimestamp"
:calls-count="callsCount"
:chats-count="chatsCount"
:tasks="items"
:first="!key"
:last="!next && key === dataList.length - 1"
/>
</template>

<template #after-content>
<timeline-intersection-observer
:next="next"
:loading="nextLoading"
@next="loadNext"
/>
</template>
Expand All @@ -38,7 +45,7 @@
</template>

<script setup>
import { computed, provide } from 'vue';
import { computed, provide, ref } from 'vue';
import { useStore } from 'vuex';
import getNamespacedState from '@webitel/ui-sdk/src/store/helpers/getNamespacedState';
import TimelineIntersectionObserver from './utils/timeline-intersection-observer.vue';
Expand All @@ -62,6 +69,7 @@ provide('namespace', timelineNamespace);
const store = useStore();
const darkMode = computed(() => store.getters['appearance/DARK_MODE']);
const contactId = computed(() => store.getters[`${timelineNamespace}/PARENT_ID`]);
const dataList = computed(() => getNamespacedState(store.state, timelineNamespace).dataList);
const isLoading = computed(() => getNamespacedState(store.state, timelineNamespace).isLoading);
Expand All @@ -71,8 +79,12 @@ function initializeList() {
return store.dispatch(`${timelineNamespace}/INITIALIZE_LIST`);
}
function loadNext() {
return store.dispatch(`${timelineNamespace}/LOAD_NEXT`);
const nextLoading = ref(false);
async function loadNext() {
nextLoading.value = true;
await store.dispatch(`${timelineNamespace}/LOAD_NEXT`);
nextLoading.value = false;
}
// TODO: uncomment me after fixing filters module
Expand All @@ -83,4 +95,11 @@ function loadNext() {
.wt-dummy {
height: 100%;
}
.loader-wrapper {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
<div class="timeline-header-actions">
<timeline-task-type-filter
:namespace="filtersNamespace"
:calls-count="taskCounters[WebitelContactsTimelineEventType.Call]"
:chats-count="taskCounters[WebitelContactsTimelineEventType.Chat]"
:calls-count="callsCount"
:chats-count="chatsCount"
/>
<button
class="timeline-header-collapse"
Expand All @@ -23,17 +23,17 @@

</template>
<script setup>
import { computed, inject } from 'vue';
import { computed, inject, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import capitalize from 'lodash/capitalize';
import { WebitelContactsTimelineEventType } from 'webitel-sdk';
import { useTableFilters } from '@webitel/ui-sdk/src/modules/Filters/composables/useTableFilters.js';
import TimelineAPI from '../api/TimelineAPI.js';
import TimelineTaskTypeFilter from '../modules/filters/components/timeline-task-type-filter.vue';
const props = defineProps({
list: {
type: Array,
default: () => [],
contactId: {
type: String,
required: true,
},
});
Expand All @@ -46,26 +46,19 @@ const { filtersNamespace } = useTableFilters(namespace);
const showHeader = computed(() => true);
const taskCounters = computed(() => {
return props.list.reduce((acc, { callsCount = 0, chatsCount = 0 }) => {
return {
[WebitelContactsTimelineEventType.Call]: acc[WebitelContactsTimelineEventType.Call] + +callsCount,
[WebitelContactsTimelineEventType.Chat]: acc[WebitelContactsTimelineEventType.Chat] + +chatsCount,
};
}, {
[WebitelContactsTimelineEventType.Call]: 0,
[WebitelContactsTimelineEventType.Chat]: 0,
})
});
const callsCount = ref(0);
const chatsCount = ref(0);
const dateFrom = ref(Date.now());
const dateTo = ref(Date.now());
const timelineInterval = computed(() => {
const formatDate = (date) => {
const fullDate = new Date(+date);
return capitalize(d(fullDate, 'timelineInterval', locale.value === 'ua' ? 'uk' : undefined));
}
const from = props.list.at(-1)?.dayTimestamp || (new Date().setMonth(new Date().getMonth() - 1));
const to = props.list.at(1)?.dayTimestamp || new Date().getTime();
const from = +dateFrom.value;
const to = +dateTo.value;
return `${formatDate(from)} - ${formatDate(to)}`;
})
Expand All @@ -74,6 +67,21 @@ function collapseAll () {
return eventBus.$emit('timeline/rows/collapse-all');
}
async function loadCounters() {
const {
dateFrom: sourceDateFrom,
dateTo: sourceDateTo,
callsCount: sourceCallsCount,
chatsCount: sourceChatsCount,
} = await TimelineAPI.getCounters({ parentId: props.contactId });
callsCount.value = sourceCallsCount;
chatsCount.value = sourceChatsCount;
dateFrom.value = sourceDateFrom;
dateTo.value = sourceDateTo;
}
loadCounters();
</script>

<style lang="scss" scoped>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<template>
<wt-loader
v-if="loading"
size="sm"
></wt-loader>
<div ref="intersectionTarget" />
</template>

Expand All @@ -11,6 +15,10 @@ const props = defineProps({
type: Function,
required: true,
},
loading: {
type: Boolean,
default: false,
},
});
const emit = defineEmits([
Expand All @@ -19,26 +27,30 @@ const emit = defineEmits([
const intersectionTarget = ref(null);
let stopIntersectionObserver;
let stopObs;
onMounted(() => {
/**
*
* Note, observer triggers at init, so it should be used also as init function
* however, current filters module version is initializing list by itself, so we need to refactor filters ASAP
*/
stopIntersectionObserver = useIntersectionObserver(intersectionTarget.value, ([{ isIntersecting }]) => {
if (isIntersecting && next.value) {
const { stop } = useIntersectionObserver(intersectionTarget.value, ([{ isIntersecting }]) => {
if (isIntersecting && props.next) {
emit('next');
}
});
stopObs = stop;
});
onUnmounted(() => {
stopIntersectionObserver();
stopObs();
});
</script>

<style scoped lang="scss">
.wt-loader {
margin: var(--spacing-lg) auto;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ const props = defineProps({
type: Boolean,
default: false,
},
first: {
type: Boolean,
default: false,
},
last: {
type: Boolean,
default: false,
Expand All @@ -49,6 +53,8 @@ const handleClick = () => {
emit('click');
};
if (props.first) handleClick();
const stateMap = {
[TimelinePinType.CLOSE]: {
component: TimelineRoundedAction,
Expand Down

0 comments on commit 59c0a05

Please sign in to comment.