@webitel/ui-sdk 24.10.42 → 24.10.43

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": "24.10.42",
3
+ "version": "24.10.43",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "dev": "vite",
@@ -0,0 +1,97 @@
1
+ import {
2
+ getDefaultGetListResponse,
3
+ getDefaultGetParams,
4
+ getDefaultInstance,
5
+ } from '../../defaults/index.js';
6
+ import applyTransform, {
7
+ camelToSnake,
8
+ generateUrl,
9
+ merge,
10
+ mergeEach,
11
+ notify,
12
+ sanitize,
13
+ snakeToCamel,
14
+ starToSearch,
15
+ } from '../../transformers/index.js';
16
+
17
+ const permissionsUrl = '/acl';
18
+
19
+ const handlePermissionsList = (items) => {
20
+ return items.map((item) => ({
21
+ ...item,
22
+ access: {
23
+ x: {
24
+ id: (item.granted.match(/x/g) || []).length + 1,
25
+ rule: 'x'.repeat((item.granted.match(/x/g) || []).length),
26
+ },
27
+ r: {
28
+ id: (item.granted.match(/r/g) || []).length + 1,
29
+ rule: 'r'.repeat((item.granted.match(/r/g) || []).length),
30
+ },
31
+ w: {
32
+ id: (item.granted.match(/w/g) || []).length + 1,
33
+ rule: 'w'.repeat((item.granted.match(/w/g) || []).length),
34
+ },
35
+ d: {
36
+ id: (item.granted.match(/d/g) || []).length + 1,
37
+ rule: 'd'.repeat((item.granted.match(/d/g) || []).length),
38
+ },
39
+ },
40
+ }));
41
+ };
42
+
43
+ export const generatePermissionsApi = (baseUrl) => {
44
+ const instance = getDefaultInstance();
45
+
46
+ const getList = async ({ parentId, ...params }) => {
47
+ const fieldsToSend = ['page', 'size', 'q', 'sort', 'fields', 'id'];
48
+
49
+ const defaultObject = {
50
+ user: false,
51
+ };
52
+
53
+ const url = applyTransform(params, [
54
+ merge(getDefaultGetParams()),
55
+ starToSearch('search'),
56
+ (params) => ({
57
+ ...params,
58
+ q: params.search,
59
+ }),
60
+ sanitize(fieldsToSend),
61
+ camelToSnake(),
62
+ generateUrl(`${baseUrl}/${parentId}/${permissionsUrl}`),
63
+ ]);
64
+ try {
65
+ const response = await instance.get(url);
66
+ const { items, next } = applyTransform(response.data, [
67
+ snakeToCamel(),
68
+ merge(getDefaultGetListResponse()),
69
+ ]);
70
+ return {
71
+ items: applyTransform(items, [
72
+ mergeEach(defaultObject),
73
+ handlePermissionsList,
74
+ ]),
75
+ next,
76
+ };
77
+ } catch (err) {
78
+ throw applyTransform(err, [notify]);
79
+ }
80
+ };
81
+
82
+ const patch = async ({ changes, id }) => {
83
+ const body = applyTransform(changes, [camelToSnake()]);
84
+ const url = `${baseUrl}/${id}/${permissionsUrl}`;
85
+ try {
86
+ const response = await instance.patch(url, body);
87
+ return applyTransform(response.data, [snakeToCamel()]);
88
+ } catch (err) {
89
+ throw applyTransform(err, [notify]);
90
+ }
91
+ };
92
+
93
+ return {
94
+ getPermissionsList: getList,
95
+ patchPermissions: patch,
96
+ };
97
+ };
@@ -11,6 +11,7 @@ import media from './media/media.js';
11
11
  import queues from './queues/queues.js';
12
12
  import roles from './roles/roles.js';
13
13
  import users from './users/users.js';
14
+ import { contacts, contactChatMessagesHistory } from './сontacts/index.js';
14
15
 
15
16
  export {
16
17
  agents,
@@ -26,4 +27,6 @@ export {
26
27
  roles,
27
28
  users,
28
29
  configurations,
30
+ contacts,
31
+ contactChatMessagesHistory,
29
32
  };
@@ -13,6 +13,7 @@ import applyTransform, {
13
13
  sanitize,
14
14
  snakeToCamel,
15
15
  } from '../../transformers/index.js';
16
+ import { generatePermissionsApi } from '../_shared/generatePermissionsApi.js';
16
17
 
17
18
  const instance = getDefaultInstance();
18
19
 
@@ -214,6 +215,8 @@ const UsersAPI = {
214
215
  getLookup: getUsersLookup,
215
216
  patchUserPresence,
216
217
  logoutUser,
218
+
219
+ ...generatePermissionsApi(baseUrl),
217
220
  };
218
221
 
219
222
  export default UsersAPI;
@@ -5,14 +5,21 @@ import {
5
5
  ChannelType,
6
6
  EngineRoutingSchemaType,
7
7
  } from 'webitel-sdk';
8
- import { notify } from '../../api/transformers/index.js';
9
- import ChatGatewayProvider from '../../enums/ChatGatewayProvider/ChatGatewayProvider.enum.js';
8
+ import ChatGatewayProvider
9
+ from '../../enums/ChatGatewayProvider/ChatGatewayProvider.enum.js';
10
10
  import QueueType from '../../enums/QueueType/QueueType.enum.js';
11
- import AdminSections from '../../enums/WebitelApplications/AdminSections.enum.js';
12
- import AuditorSections from '../../enums/WebitelApplications/AuditorSections.enum.js';
11
+ import AdminSections
12
+ from '../../enums/WebitelApplications/AdminSections.enum.js';
13
+ import AuditorSections
14
+ from '../../enums/WebitelApplications/AuditorSections.enum.js';
13
15
  import CrmSections from '../../enums/WebitelApplications/CrmSections.enum.js';
14
- import SupervisorSections from '../../enums/WebitelApplications/SupervisorSections.enum.js';
15
- import WebitelApplications from '../../enums/WebitelApplications/WebitelApplications.enum.js';
16
+ import SupervisorSections
17
+ from '../../enums/WebitelApplications/SupervisorSections.enum.js';
18
+ import WebitelApplications
19
+ from '../../enums/WebitelApplications/WebitelApplications.enum.js';
20
+ import {
21
+ AccessMode,
22
+ } from '../../modules/ObjectPermissions/_internals/enums/AccessMode.enum.js';
16
23
  import { snakeToCamel } from '../../scripts/caseConverters.js';
17
24
 
18
25
  export default {
@@ -109,6 +116,18 @@ export default {
109
116
  sec: 'Sec',
110
117
  timezone: 'Time zone | Time zones',
111
118
  },
119
+ // locales, related to user access, permissions, etc.
120
+ access: {
121
+ ObAC: 'Managed by operations',
122
+ RbAC: 'Managed by records',
123
+ operations: 'Operations',
124
+ rbacDefault: 'Default Record based Access',
125
+ accessMode: {
126
+ [AccessMode.FORBIDDEN]: 'Forbidden',
127
+ [AccessMode.ALLOW]: 'Allow',
128
+ [AccessMode.MANAGE]: 'Allow with delegation',
129
+ },
130
+ },
112
131
  // describes Webitel system entities
113
132
  objects: {
114
133
  team: 'Team | Teams',
@@ -117,6 +136,8 @@ export default {
117
136
  region: 'Region | Regions',
118
137
  communicationType: 'Communication type | Communication types',
119
138
  grantee: 'Grantee | Grantees',
139
+ grantor: 'Grantor | Grantors',
140
+ role: 'Role | Roles',
120
141
  user: 'User | Users',
121
142
  queue: {
122
143
  type: {
@@ -5,13 +5,21 @@ import {
5
5
  ChannelType,
6
6
  EngineRoutingSchemaType,
7
7
  } from 'webitel-sdk';
8
- import ChatGatewayProvider from '../../enums/ChatGatewayProvider/ChatGatewayProvider.enum.js';
8
+ import ChatGatewayProvider
9
+ from '../../enums/ChatGatewayProvider/ChatGatewayProvider.enum.js';
9
10
  import QueueType from '../../enums/QueueType/QueueType.enum.js';
10
- import AdminSections from '../../enums/WebitelApplications/AdminSections.enum.js';
11
- import AuditorSections from '../../enums/WebitelApplications/AuditorSections.enum.js';
11
+ import AdminSections
12
+ from '../../enums/WebitelApplications/AdminSections.enum.js';
13
+ import AuditorSections
14
+ from '../../enums/WebitelApplications/AuditorSections.enum.js';
12
15
  import CrmSections from '../../enums/WebitelApplications/CrmSections.enum.js';
13
- import SupervisorSections from '../../enums/WebitelApplications/SupervisorSections.enum.js';
14
- import WebitelApplications from '../../enums/WebitelApplications/WebitelApplications.enum.js';
16
+ import SupervisorSections
17
+ from '../../enums/WebitelApplications/SupervisorSections.enum.js';
18
+ import WebitelApplications
19
+ from '../../enums/WebitelApplications/WebitelApplications.enum.js';
20
+ import {
21
+ AccessMode,
22
+ } from '../../modules/ObjectPermissions/_internals/enums/AccessMode.enum.js';
15
23
  import { snakeToCamel } from '../../scripts/caseConverters.js';
16
24
 
17
25
  export default {
@@ -107,6 +115,18 @@ export default {
107
115
  sec: 'Сек',
108
116
  timezone: 'Часовая зона | Часовые зоны',
109
117
  },
118
+ // locales, related to user access, permissions, etc.
119
+ access: {
120
+ ObAC: 'Управление действиями',
121
+ RbAC: 'Управление записями',
122
+ operations: 'Действия',
123
+ rbacDefault: 'Права доступа по записям по умолчанию',
124
+ accessMode: {
125
+ [AccessMode.FORBIDDEN]: 'Запрещено',
126
+ [AccessMode.ALLOW]: 'Разрешено',
127
+ [AccessMode.MANAGE]: 'Управление',
128
+ },
129
+ },
110
130
  // describes Webitel system entities
111
131
  objects: {
112
132
  team: 'Команда | Команды',
@@ -115,7 +135,9 @@ export default {
115
135
  region: 'Регион | Регионы',
116
136
  communicationType: 'Тип связи | Типы связи',
117
137
  grantee: 'Получатель | Получатели',
138
+ grantor: 'Праводатель | Праводатели',
118
139
  user: 'Пользователь | Пользователи',
140
+ role: 'Роль | Роли',
119
141
  queue: {
120
142
  type: {
121
143
  [QueueType.INBOUND_QUEUE]: 'Входящая очередь',
@@ -5,13 +5,21 @@ import {
5
5
  ChannelType,
6
6
  EngineRoutingSchemaType,
7
7
  } from 'webitel-sdk';
8
- import ChatGatewayProvider from '../../enums/ChatGatewayProvider/ChatGatewayProvider.enum.js';
8
+ import ChatGatewayProvider
9
+ from '../../enums/ChatGatewayProvider/ChatGatewayProvider.enum.js';
9
10
  import QueueType from '../../enums/QueueType/QueueType.enum.js';
10
- import AdminSections from '../../enums/WebitelApplications/AdminSections.enum.js';
11
- import AuditorSections from '../../enums/WebitelApplications/AuditorSections.enum.js';
11
+ import AdminSections
12
+ from '../../enums/WebitelApplications/AdminSections.enum.js';
13
+ import AuditorSections
14
+ from '../../enums/WebitelApplications/AuditorSections.enum.js';
12
15
  import CrmSections from '../../enums/WebitelApplications/CrmSections.enum.js';
13
- import SupervisorSections from '../../enums/WebitelApplications/SupervisorSections.enum.js';
14
- import WebitelApplications from '../../enums/WebitelApplications/WebitelApplications.enum.js';
16
+ import SupervisorSections
17
+ from '../../enums/WebitelApplications/SupervisorSections.enum.js';
18
+ import WebitelApplications
19
+ from '../../enums/WebitelApplications/WebitelApplications.enum.js';
20
+ import {
21
+ AccessMode,
22
+ } from '../../modules/ObjectPermissions/_internals/enums/AccessMode.enum.js';
15
23
  import { snakeToCamel } from '../../scripts/caseConverters.js';
16
24
 
17
25
  export default {
@@ -107,6 +115,18 @@ export default {
107
115
  sec: 'Сек',
108
116
  timezone: 'Часова зона | Часові зони',
109
117
  },
118
+ // locales, related to user access, permissions, etc.
119
+ access: {
120
+ ObAC: 'Управління діями',
121
+ RbAC: 'Управління записами',
122
+ operations: 'Дії',
123
+ rbacDefault: 'Права доступу на записи за замовчуванням',
124
+ accessMode: {
125
+ [AccessMode.FORBIDDEN]: 'Заборонено',
126
+ [AccessMode.ALLOW]: 'Дозволено',
127
+ [AccessMode.MANAGE]: 'Управління',
128
+ },
129
+ },
110
130
  // describes Webitel system entities
111
131
  objects: {
112
132
  team: 'Команда | Команди',
@@ -115,7 +135,9 @@ export default {
115
135
  region: 'Регіон | Регіони',
116
136
  communicationType: "Тип зв'язку | Типи зв'язку",
117
137
  grantee: 'Отримувач | Отримувачі',
138
+ grantor: 'Надавач | Надавачі',
118
139
  user: 'Користувач | Користувачі',
140
+ role: 'Роль | Ролі',
119
141
  queue: {
120
142
  type: {
121
143
  [QueueType.INBOUND_QUEUE]: 'Вхідна черга',
@@ -0,0 +1,28 @@
1
+ <template>
2
+ <div class="permissions-role-row">
3
+ <wt-icon
4
+ :icon="role.user ? 'user' : 'role'"
5
+ />
6
+ <slot>
7
+ {{ role.name }}
8
+ </slot>
9
+ </div>
10
+ </template>
11
+
12
+ <script setup>
13
+ const props = defineProps({
14
+ role: {
15
+ type: Object,
16
+ required: true,
17
+ },
18
+ });
19
+ </script>
20
+
21
+ <style lang="scss" scoped>
22
+ .permissions-role-row {
23
+ display: grid;
24
+ align-items: center;
25
+ grid-template-columns: var(--icon-md-size) 1fr;
26
+ gap: var(--spacing-sm);
27
+ }
28
+ </style>
@@ -0,0 +1,30 @@
1
+ <template>
2
+ <wt-select
3
+ class="permissions-role-select"
4
+ option-label="name"
5
+ v-bind="attrs"
6
+ >
7
+ <template #singleLabel="{ option, optionLabel }">
8
+ <role-row :role="option.user">
9
+ {{ option[optionLabel] || option }}
10
+ </role-row>
11
+ </template>
12
+
13
+ <template #option="{ option, optionLabel }">
14
+ <role-row :role="option.user">
15
+ {{ option[optionLabel] || option }}
16
+ </role-row>
17
+ </template>
18
+ </wt-select>
19
+ </template>
20
+
21
+ <script setup>
22
+ import { useAttrs } from 'vue';
23
+ import RoleRow from './permissions-role-row.vue';
24
+
25
+ const attrs = useAttrs();
26
+ </script>
27
+
28
+ <style lang="scss" scoped>
29
+
30
+ </style>
@@ -0,0 +1,109 @@
1
+ <template>
2
+ <div class="permissions-tab-role-popup">
3
+ <wt-icon-btn
4
+ icon="plus"
5
+ @click="add"
6
+ />
7
+
8
+ <wt-popup
9
+ :shown="shown"
10
+ overflow
11
+ size="sm"
12
+ @close="close"
13
+ >
14
+ <template #title>
15
+ {{ `${t('reusable.new')} ${t('objects.grantee', 1).toLowerCase()}` }}
16
+ </template>
17
+ <template #main>
18
+ <permissions-role-select
19
+ v-model="grantee"
20
+ :clearable="false"
21
+ :placeholder="t('object.role', 1)"
22
+ :search-method="getAvailableGrantees"
23
+ />
24
+ </template>
25
+ <template #actions>
26
+ <wt-button @click="save">
27
+ {{ t('objects.add') }}
28
+ </wt-button>
29
+ <wt-button
30
+ color="secondary"
31
+ @click="close"
32
+ >
33
+ {{ t('objects.close') }}
34
+ </wt-button>
35
+ </template>
36
+ </wt-popup>
37
+ </div>
38
+ </template>
39
+
40
+ <script setup>
41
+ import { ref, useAttrs } from 'vue';
42
+ import { useI18n } from 'vue-i18n';
43
+ import { useRoute, useRouter } from 'vue-router';
44
+ import { useStore } from 'vuex';
45
+ import RolesAPI from '../../../../api/clients/roles/roles.js';
46
+ import getNamespacedState from '../../../../store/helpers/getNamespacedState.js';
47
+ import PermissionsRoleSelect from './permissions-role-select.vue';
48
+
49
+ const props = defineProps({
50
+ namespace: {
51
+ type: String,
52
+ required: true,
53
+ },
54
+ });
55
+
56
+ const attrs = useAttrs();
57
+ const store = useStore();
58
+ const { t } = useI18n();
59
+ const router = useRouter();
60
+ const route = useRoute();
61
+
62
+ const grantee = ref(null);
63
+
64
+ const existingGranteesList = computed(() => getNamespacedState(store.state, props.namespace).dataList);
65
+
66
+ const shown = computed(() => !!route.params.permissionId);
67
+
68
+ const add = () => router.push({
69
+ ...route,
70
+ params: { ...route.params, permissionId: 'new' },
71
+ });
72
+
73
+ const close = () => {
74
+ const { permissionId, ...params } = route.params;
75
+
76
+ return router.push({
77
+ ...route,
78
+ params,
79
+ });
80
+ };
81
+
82
+ const loadGrantees = (params) => {
83
+ const fields = ['name', 'id', 'user'];
84
+ return RolesAPI.getExtendedRoles({
85
+ ...params,
86
+ fields,
87
+ });
88
+ };
89
+
90
+ // filter already existing roles
91
+ const getAvailableGrantees = async (params) => {
92
+ const { items, ...rest } = await loadGrantees(params);
93
+ return {
94
+ items: items.filter(
95
+ (role) => !existingGranteesList.value.some((usedRoles) => role.id === usedRoles.grantee.id),
96
+ ),
97
+ ...rest,
98
+ };
99
+ };
100
+
101
+ const save = async (payload = grantee.value) => {
102
+ await store.dispatch(`${props.namespace}/ADD_ROLE_PERMISSIONS`, payload);
103
+ return close();
104
+ };
105
+
106
+ </script>
107
+
108
+ <style lang="scss" scoped>
109
+ </style>
@@ -0,0 +1,5 @@
1
+ export const AccessMode = Object.freeze({
2
+ FORBIDDEN: 1,
3
+ ALLOW: 2,
4
+ MANAGE: 3,
5
+ });
@@ -0,0 +1,25 @@
1
+ import deepCopy from 'deep-copy';
2
+ import FiltersStoreModule
3
+ from '../../../../../Filters/store/FiltersStoreModule';
4
+
5
+ const filtersList = [
6
+ {
7
+ name: 'page',
8
+ value: 1,
9
+ },
10
+ {
11
+ name: 'size',
12
+ value: 10,
13
+ },
14
+ { name: 'sort' },
15
+ ];
16
+
17
+ export default () => {
18
+ const filters = new FiltersStoreModule()
19
+ .addFilter(deepCopy(filtersList))
20
+ .getModule();
21
+
22
+ return {
23
+ filters,
24
+ };
25
+ };
@@ -0,0 +1,15 @@
1
+ import { createBaseStoreModule } from '../../../../../store/new/index.js';
2
+ import tableStoreModule
3
+ from '../../../../../store/new/modules/tableStoreModule/tableStoreModule.js';
4
+ import objectPermissionsStoreModule
5
+ from '../modules/objectPermissionsStoreModule.js';
6
+
7
+ export const createObjectPermissionsStoreModule = (modules = []) => {
8
+ const modulesArr = Array.isArray(modules) ? modules : [modules];
9
+
10
+ return createBaseStoreModule([
11
+ tableStoreModule(),
12
+ objectPermissionsStoreModule(),
13
+ ...modulesArr,
14
+ ]);
15
+ };
@@ -0,0 +1,68 @@
1
+ import { AccessMode } from '../../enums/AccessMode.enum.js';
2
+ import generateFilters from '../../modules/filters/store/filters.store.js';
3
+
4
+ const actions = {
5
+ CHANGE_ACCESS_MODE: async (context, { mode, ruleName, item }) => {
6
+ const have = item.access[ruleName];
7
+ let want;
8
+ /*
9
+ has | patch | got
10
+ -----+-------+-----
11
+ - | w | w
12
+ w | w | -
13
+ - | ww | ww
14
+ w | ww | ww
15
+ ww | ww | w
16
+ ww | w | -
17
+ */
18
+ switch (mode.id) {
19
+ case AccessMode.FORBIDDEN:
20
+ want = ruleName;
21
+ break;
22
+ case AccessMode.ALLOW:
23
+ want = have.rule || ruleName;
24
+ break;
25
+ case AccessMode.MANAGE:
26
+ want = `${ruleName}${ruleName}`;
27
+ break;
28
+ default:
29
+ return;
30
+ }
31
+ const changes = {
32
+ grantee: +item.grantee.id,
33
+ grants: want,
34
+ };
35
+ try {
36
+ await context.dispatch('PATCH_ACCESS_MODE', {
37
+ item,
38
+ changes,
39
+ });
40
+ } finally {
41
+ await context.dispatch('LOAD_DATA_LIST');
42
+ }
43
+ },
44
+ ADD_ROLE_PERMISSIONS: async (context, role) => {
45
+ const changes = {
46
+ grantee: +role.id,
47
+ grants: 'r',
48
+ };
49
+ try {
50
+ await context.dispatch('PATCH_ACCESS_MODE', {
51
+ changes,
52
+ });
53
+ } finally {
54
+ await context.dispatch('LOAD_DATA_LIST');
55
+ }
56
+ },
57
+ };
58
+
59
+ export default () => {
60
+ const filters = generateFilters();
61
+
62
+ return {
63
+ actions,
64
+ modules: {
65
+ filters,
66
+ },
67
+ };
68
+ };