@webitel/ui-sdk 2.0.7 → 2.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webitel/ui-sdk",
3
- "version": "2.0.7",
3
+ "version": "2.0.10",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve-lib": "vue-cli-service serve",
@@ -7,6 +7,7 @@
7
7
  :popper-class="[
8
8
  'wt-tooltip__popper',
9
9
  { 'wt-tooltip--contrast__popper': contrast },
10
+ popperClass,
10
11
  ]"
11
12
  :triggers="['hover', 'focus', 'touch']"
12
13
  class="wt-tooltip"
@@ -30,6 +31,10 @@ export default {
30
31
  type: String,
31
32
  default: 'auto',
32
33
  },
34
+ popperClass: {
35
+ type: String,
36
+ default: '',
37
+ },
33
38
  },
34
39
  };
35
40
  </script>
@@ -13,6 +13,8 @@
13
13
  // cause we need to set styles to element somewhere in the HTML, not inside .wt-tooltip scope
14
14
  .wt-tooltip__popper .v-popper__inner {
15
15
  @extend %typo-body-1;
16
+ max-width: 80vw;
17
+ max-height: 80vh;
16
18
  padding: var(--tooltip-padding);
17
19
  color: var(--tooltip-light-text-color);
18
20
  background: var(--tooltip-light-bg-color);
@@ -0,0 +1,184 @@
1
+ import { ChatActions, CallActions } from 'webitel-sdk';
2
+ import i18n from '../../../locale/i18n';
3
+ import BaseStoreModule from '../../../store/BaseStoreModules/BaseStoreModule';
4
+ import endChatSound from '../assets/audio/end-chat.wav';
5
+ import newChatSound from '../assets/audio/new-chat.wav';
6
+ import newMessageSound from '../assets/audio/new-message.wav';
7
+ import ringingSound from '../assets/audio/ringing.mp3';
8
+ import notificationIcon from '../assets/img/notification-icon.png';
9
+
10
+ const NOTIFICATION_VISIBLE_INTERVAL = 2000;
11
+
12
+ const getNotificationSound = (action) => {
13
+ switch (action) {
14
+ case ChatActions.UserInvite:
15
+ return new Audio(newChatSound);
16
+ case ChatActions.Message:
17
+ return new Audio(newMessageSound);
18
+ case ChatActions.Close:
19
+ return new Audio(endChatSound);
20
+ case CallActions.Ringing:
21
+ // eslint-disable-next-line no-case-declarations
22
+ const audio = new Audio(ringingSound);
23
+ audio.loop = true;
24
+ return audio;
25
+ default:
26
+ return false;
27
+ }
28
+ };
29
+
30
+ const getCurrentTabId = () => localStorage.getItem('currentTabId');
31
+
32
+ const setCurrentTabId = (value) => localStorage.setItem('currentTabId', value);
33
+
34
+ export default class NotificationsStoreModule extends BaseStoreModule {
35
+ state = {
36
+ thisTabId: null, // this tab
37
+ currentTabId: null, // current tab is localStorage
38
+ broadcastChannel: null, // in order to reset the tab title with unread number
39
+ unreadCount: 0,
40
+ currentlyPlaying: false,
41
+ };
42
+
43
+ getters = {
44
+ IS_MAIN_TAB: (state) => state.thisTabId === state.currentTabId,
45
+ IS_SOUND_ALLOWED: (state, getters) => getters.IS_MAIN_TAB && !state.currentlyPlaying,
46
+ };
47
+
48
+ actions = {
49
+ // private
50
+ _SUBSCRIBE_TAB_CLOSING: (context) => {
51
+ window.addEventListener('storage', () => {
52
+ if (!getCurrentTabId()) {
53
+ setCurrentTabId(context.state.thisTabId);
54
+ }
55
+ context.commit('SET_CURRENT_TAB_ID', getCurrentTabId());
56
+ });
57
+ },
58
+
59
+ _SETUP_THIS_TAB_ID: (context) => {
60
+ const thisTabId = Math.random().toString();
61
+ context.commit('SET_THIS_TAB_ID', thisTabId);
62
+ setCurrentTabId(thisTabId);
63
+ context.commit('SET_CURRENT_TAB_ID', thisTabId);
64
+ },
65
+
66
+ _SETUP_UNREAD_COUND_BROADCAST_LISTENING: (context) => {
67
+ const broadcastChannel = new BroadcastChannel('WtAppNotifications');
68
+ broadcastChannel.addEventListener('message', ({ data }) => {
69
+ context.dispatch('_SET_UNREAD_COUNT', data.count);
70
+ });
71
+
72
+ document.documentElement.addEventListener('click', () => {
73
+ context.dispatch('_RESET_UNREAD_COUNT');
74
+ });
75
+ context.commit('SET_BROADCAST_CHANNEL', broadcastChannel);
76
+ },
77
+
78
+ _SET_UNREAD_COUNT: (context, count) => {
79
+ context.commit('SET_UNREAD_COUNT', count);
80
+ context.dispatch('_SET_TAB_TITLE');
81
+ },
82
+
83
+ _RESET_UNREAD_COUNT: (context) => {
84
+ if (context.state.unreadCount === 0) return;
85
+ const count = 0;
86
+ context.dispatch('_SET_UNREAD_COUNT', count);
87
+ context.state.broadcastChannel.postMessage({ count });
88
+ },
89
+
90
+ _SET_TAB_TITLE: (context) => {
91
+ const count = context.state.unreadCount;
92
+ const titleText = document.title.replace(/\s*\(.*?\)\s*/g, '');
93
+ document.title = count ? `(${count}) ${titleText}` : titleText;
94
+ },
95
+
96
+ _REMOVE_CURRENT_TAB_ID: () => {
97
+ localStorage.removeItem('currentTabId');
98
+ },
99
+
100
+ // public
101
+ INITIALIZE: (context) => Promise
102
+ .allSettled([
103
+ context.dispatch('_SETUP_THIS_TAB_ID'),
104
+ context.dispatch('_SETUP_UNREAD_COUND_BROADCAST_LISTENING'),
105
+ context.dispatch('_SUBSCRIBE_TAB_CLOSING'),
106
+ ]),
107
+
108
+ DESTROY: (context) => Promise
109
+ .allSettled([
110
+ context.dispatch('STOP_SOUND'),
111
+ context.dispatch('_REMOVE_CURRENT_TAB_ID'),
112
+ ]),
113
+
114
+ PLAY_SOUND: (context, {
115
+ action,
116
+ sound = getNotificationSound(action),
117
+ }) => {
118
+ if (context.getters.IS_SOUND_ALLOWED
119
+ && !localStorage.getItem('wtIsPlaying')
120
+ ) {
121
+ const audio = sound instanceof Audio ? sound : new Audio(sound);
122
+ audio.addEventListener('ended', () => {
123
+ context.dispatch('STOP_SOUND');
124
+ }, { once: true });
125
+ audio.play();
126
+ localStorage.setItem('wtIsPlaying', 'true');
127
+ context.commit('SET_CURRENTLY_PLAYING', audio);
128
+ }
129
+ },
130
+
131
+ STOP_SOUND: (context) => {
132
+ const { currentlyPlaying } = context.state;
133
+ if (currentlyPlaying) currentlyPlaying.pause();
134
+ localStorage.removeItem('wtIsPlaying');
135
+ context.commit('RESET_CURRENTLY_PLAYING');
136
+ },
137
+
138
+ SEND_NOTIFICATION: (context, {
139
+ locale,
140
+ text = i18n.t(locale),
141
+ icon = notificationIcon,
142
+ interval = NOTIFICATION_VISIBLE_INTERVAL,
143
+ }) => {
144
+ const notification = new Notification(text, { icon });
145
+
146
+ notification.addEventListener('click', () => {
147
+ window.focus();
148
+ }, { once: true });
149
+
150
+ setTimeout(() => {
151
+ notification.close();
152
+ }, interval);
153
+ },
154
+
155
+ INCREMENT_UNREAD_COUNT: (context) => {
156
+ const count = context.state.unreadCount + 1;
157
+ context.dispatch('_SET_UNREAD_COUNT', count);
158
+ context.state.broadcastChannel.postMessage({ count });
159
+ },
160
+ };
161
+
162
+ mutations = {
163
+ SET_THIS_TAB_ID: (state, thisTabId) => {
164
+ state.thisTabId = thisTabId;
165
+ },
166
+
167
+ SET_CURRENT_TAB_ID: (state, currentTabId) => {
168
+ state.currentTabId = currentTabId;
169
+ },
170
+
171
+ SET_BROADCAST_CHANNEL: (state, channel) => {
172
+ state.broadcastChannel = channel;
173
+ },
174
+ SET_CURRENTLY_PLAYING: (state, sound) => {
175
+ state.currentlyPlaying = sound;
176
+ },
177
+ RESET_CURRENTLY_PLAYING: (state) => {
178
+ state.currentlyPlaying = false;
179
+ },
180
+ SET_UNREAD_COUNT: (state, count) => {
181
+ state.unreadCount = count;
182
+ },
183
+ };
184
+ }
@@ -0,0 +1,139 @@
1
+ import { ChatActions } from 'webitel-sdk';
2
+ import audio from '../../assets/audio/new-message.wav';
3
+ import NotificationsStoreModule from '../NotificationsStoreModule';
4
+ import '../../../../../tests/mocks/broadcastChannelMock';
5
+
6
+ const notificationsModule = new NotificationsStoreModule().getModule();
7
+
8
+ const state = {
9
+ thisTabId: null,
10
+ broadcastChannel: new BroadcastChannel('WtAppNotifications'),
11
+ unreadCount: 0,
12
+ currentlyPlaying: false,
13
+ wtIsPlaying: false,
14
+ };
15
+
16
+ const chat = { id: '1', messages: [{ member: { name: 'name' } }] };
17
+
18
+ describe('features/notifications store: actions', () => {
19
+ const context = {
20
+ dispatch: jest.fn(),
21
+ commit: jest.fn(),
22
+ getters: {
23
+ IS_MAIN_TAB: () => true,
24
+ IS_SOUND_ALLOWED: () => true,
25
+ },
26
+ rootGetters: {
27
+ 'workspace/TASK_ON_WORKSPACE': { channelId: 'id' },
28
+ },
29
+ };
30
+
31
+ beforeEach(() => {
32
+ context.state = { ...state };
33
+ context.dispatch.mockClear();
34
+ context.commit.mockClear();
35
+ });
36
+
37
+ it('INITIALIZE action dispatches _SETUP_THIS_TAB_ID action', () => {
38
+ notificationsModule.actions.INITIALIZE(context);
39
+ expect(context.dispatch.mock.calls[0][0]).toContain('_SETUP_THIS_TAB_ID');
40
+ });
41
+
42
+ it('INITIALIZE action dispatches _SETUP_UNREAD_COUND_BROADCAST_LISTENING action', () => {
43
+ notificationsModule.actions.INITIALIZE(context);
44
+ expect(context.dispatch.mock.calls[1][0]).toContain('_SETUP_UNREAD_COUND_BROADCAST_LISTENING');
45
+ });
46
+
47
+ it('INITIALIZE action commits _SETUP_THIS_TAB_ID action', () => {
48
+ notificationsModule.actions.INITIALIZE(context);
49
+ expect(context.dispatch).toHaveBeenCalledWith('_SETUP_THIS_TAB_ID');
50
+ });
51
+
52
+ it('INCREMENT_UNREAD_COUNT action dispatches _SET_UNREAD_COUNT and increases unreadCount', () => {
53
+ notificationsModule.actions.INCREMENT_UNREAD_COUNT(context);
54
+ expect(context.dispatch).toHaveBeenCalledWith('_SET_UNREAD_COUNT', context.state.unreadCount + 1);
55
+ });
56
+
57
+ it('_SETUP_UNREAD_COUND_BROADCAST_LISTENING action commits SET_BROADCAST_CHANNEL mutation', () => {
58
+ notificationsModule.actions._SETUP_UNREAD_COUND_BROADCAST_LISTENING(context);
59
+ expect(context.commit.mock.calls[0][0]).toContain('SET_BROADCAST_CHANNEL');
60
+ });
61
+
62
+ it('PLAY_SOUND action commits SET_CURRENTLY_PLAIYNG mutation with sound', async () => {
63
+ const sound = new Audio(audio);
64
+ await notificationsModule.actions.PLAY_SOUND(context, { sound });
65
+ expect(context.commit).toHaveBeenCalledWith('SET_CURRENTLY_PLAYING', sound);
66
+ });
67
+
68
+ it('_SET_UNREAD_COUNT dispatches _SET_TAB_TITLE action', () => {
69
+ const unreadCount = 5;
70
+ notificationsModule.actions._SET_UNREAD_COUNT(context, unreadCount);
71
+ expect(context.dispatch).toHaveBeenCalledWith('_SET_TAB_TITLE');
72
+ });
73
+
74
+ it('_SET_UNREAD_COUNT action commits _SET_UNREAD_COUNT mutation with count', () => {
75
+ const unreadCount = 5;
76
+ notificationsModule.actions._SET_UNREAD_COUNT(context, unreadCount);
77
+ expect(context.commit).toHaveBeenCalledWith('SET_UNREAD_COUNT', unreadCount);
78
+ });
79
+
80
+ it('_RESET_UNREAD_COUNT action does not dispatch if unread count is 0', () => {
81
+ notificationsModule.actions._RESET_UNREAD_COUNT(context);
82
+ expect(context.dispatch).not.toHaveBeenCalledWith('_SET_UNREAD_COUNT');
83
+ });
84
+
85
+ it('_RESET_UNREAD_COUNT action dispatches _SET_UNREAD_COUNT passing unread count equal to 0', () => {
86
+ context.state.unreadCount = 1;
87
+ notificationsModule.actions._RESET_UNREAD_COUNT(context);
88
+ expect(context.dispatch).toHaveBeenCalledWith('_SET_UNREAD_COUNT', 0);
89
+ });
90
+
91
+ it('PLAY_SOUND action sets localStorage wtIsPlaying to true', () => {
92
+ const sound = new Audio(audio);
93
+ notificationsModule.actions.PLAY_SOUND(context, { sound });
94
+ expect(localStorage.getItem('wtIsPlaying')).toBeTruthy();
95
+ });
96
+
97
+ it('STOP_SOUND action commits RESET_CURRENTLY_PLAYING mutation', () => {
98
+ notificationsModule.actions.STOP_SOUND(context);
99
+ expect(context.commit).toHaveBeenCalledWith('RESET_CURRENTLY_PLAYING');
100
+ });
101
+
102
+ it('STOP_SOUND action removes localStorage wtIsPlaying', () => {
103
+ localStorage.setItem('wtIsPlaying', 'true');
104
+ notificationsModule.actions.STOP_SOUND(context);
105
+ expect(localStorage.getItem('wtIsPlaying')).toBeFalsy();
106
+ });
107
+ });
108
+
109
+ describe('features/notifications store: mutations', () => {
110
+ it('SET_THIS_TAB_ID sets window id to state', () => {
111
+ const thisTabId = 'thisTabId';
112
+ notificationsModule.mutations.SET_THIS_TAB_ID(state, thisTabId);
113
+ expect(state.thisTabId).toBe(thisTabId);
114
+ });
115
+
116
+ it('SET_BROADCAST_CHANNEL sets broadcastChannel to state', () => {
117
+ const state = { broadcastChannel: null };
118
+ const channel = new BroadcastChannel('test channel');
119
+ notificationsModule.mutations.SET_BROADCAST_CHANNEL(state, channel);
120
+ expect(state.broadcastChannel).toEqual(channel);
121
+ });
122
+
123
+ it('SET_CURRENTLY_PLAIYNG mutation sets currentlyPlaying to state', () => {
124
+ const wtIsPlaying = true;
125
+ notificationsModule.mutations.SET_CURRENTLY_PLAYING(state, wtIsPlaying);
126
+ expect(state.currentlyPlaying).toBe(true);
127
+ });
128
+
129
+ it('RESET_CURRENTLY_PLAYING mutation sets currentlyPlaying to false in state', () => {
130
+ notificationsModule.mutations.RESET_CURRENTLY_PLAYING(state);
131
+ expect(state.currentlyPlaying).toBe(false);
132
+ });
133
+
134
+ it('_SET_UNREAD_COUNT mutation sets unreadCount to state', () => {
135
+ const unreadCount = 15;
136
+ notificationsModule.mutations.SET_UNREAD_COUNT(state, unreadCount);
137
+ expect(state.unreadCount).toEqual(unreadCount);
138
+ });
139
+ });