@formixru/b2b-ui 1.7.0 → 2.0.0
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/CHANGELOG.md +5 -0
- package/CONTRIBUTING.md +0 -2
- package/package.json +37 -44
- package/src/components/color-input/index.scss +2 -1
- package/src/components/dialog/index.js +8 -54
- package/src/components/form/index.js +27 -102
- package/src/components/form/index.scss +1 -1
- package/src/components/input/index.js +1 -1
- package/src/components/request/index.js +164 -0
- package/src/components/sidebar/index.js +17 -72
- package/src/helpers/request.js +126 -0
- package/vite.config.js +75 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
## v2.0.0
|
|
2
|
+
|
|
3
|
+
- Добавлен новый компонент - универсальный AJAX-контроллер `Request`, который используется внутри `Dialog`/`Form`/`Sidebar` и может использоваться как отдельный компонент
|
|
4
|
+
- Storybook обновлён до 9-й версии
|
|
5
|
+
|
|
1
6
|
## v1.7.0
|
|
2
7
|
|
|
3
8
|
- Добавлен новый вид для WarningMessage (`light-info`)
|
package/CONTRIBUTING.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formixru/b2b-ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"defaults",
|
|
12
12
|
"not OperaMini all"
|
|
13
13
|
],
|
|
14
|
-
"packageManager": "yarn@4.
|
|
14
|
+
"packageManager": "yarn@4.9.3",
|
|
15
15
|
"scripts": {
|
|
16
16
|
"_postinstall": "husky",
|
|
17
17
|
"prepack": "yarn pinst --disable",
|
|
@@ -26,58 +26,51 @@
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@advdominion/get-scrollbar-width": "^2.0.0",
|
|
28
28
|
"@advdominion/is": "^1.0.1",
|
|
29
|
-
"@advdominion/lightningcss-loader": "^1.0.0",
|
|
30
29
|
"@advdominion/pluralize": "^1.0.1",
|
|
31
|
-
"@advdominion/tooltip": "^3.0.
|
|
32
|
-
"@eslint/eslintrc": "^3.
|
|
33
|
-
"@eslint/js": "^9.
|
|
34
|
-
"@floating-ui/dom": "^1.
|
|
30
|
+
"@advdominion/tooltip": "^3.0.1",
|
|
31
|
+
"@eslint/eslintrc": "^3.3.1",
|
|
32
|
+
"@eslint/js": "^9.33.0",
|
|
33
|
+
"@floating-ui/dom": "^1.7.4",
|
|
35
34
|
"@popperjs/core": "^2.11.8",
|
|
36
|
-
"@prettier/plugin-php": "^0.
|
|
37
|
-
"@storybook/addon-designs": "^
|
|
38
|
-
"@storybook/addon-
|
|
39
|
-
"@storybook/addon-links": "^
|
|
40
|
-
"@storybook/
|
|
41
|
-
"@
|
|
42
|
-
"@storybook
|
|
43
|
-
"
|
|
44
|
-
"browserslist": "^4.24.4",
|
|
45
|
-
"color": "^4.2.3",
|
|
46
|
-
"css-loader": "^7.1.2",
|
|
35
|
+
"@prettier/plugin-php": "^0.24.0",
|
|
36
|
+
"@storybook/addon-designs": "^10.0.2",
|
|
37
|
+
"@storybook/addon-docs": "^9.1.3",
|
|
38
|
+
"@storybook/addon-links": "^9.1.3",
|
|
39
|
+
"@storybook/vue3-vite": "^9.1.3",
|
|
40
|
+
"@vitejs/plugin-vue": "^6.0.1",
|
|
41
|
+
"@vueless/storybook-dark-mode": "^9.0.7",
|
|
42
|
+
"color": "^5.0.0",
|
|
47
43
|
"dayjs": "^1.11.13",
|
|
48
|
-
"eslint": "^9.
|
|
49
|
-
"eslint-config-prettier": "^10.
|
|
44
|
+
"eslint": "^9.33.0",
|
|
45
|
+
"eslint-config-prettier": "^10.1.8",
|
|
50
46
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
51
|
-
"eslint-plugin-
|
|
52
|
-
"eslint-plugin-
|
|
53
|
-
"
|
|
47
|
+
"eslint-plugin-storybook": "9.1.3",
|
|
48
|
+
"eslint-plugin-unicorn": "^60.0.0",
|
|
49
|
+
"eslint-plugin-vue": "^10.4.0",
|
|
50
|
+
"globals": "^16.3.0",
|
|
54
51
|
"husky": "^9.1.7",
|
|
55
52
|
"imask": "^7.6.1",
|
|
56
|
-
"
|
|
57
|
-
"lint-staged": "^15.4.1",
|
|
53
|
+
"lint-staged": "^16.1.5",
|
|
58
54
|
"lodash-es": "^4.17.21",
|
|
59
|
-
"mime": "^4.0.
|
|
60
|
-
"msw": "^2.
|
|
61
|
-
"msw-storybook-addon": "^2.0.
|
|
55
|
+
"mime": "^4.0.7",
|
|
56
|
+
"msw": "^2.10.5",
|
|
57
|
+
"msw-storybook-addon": "^2.0.5",
|
|
62
58
|
"nouislider": "^15.8.1",
|
|
63
59
|
"pinst": "^3.0.0",
|
|
64
|
-
"prettier": "^3.
|
|
60
|
+
"prettier": "^3.6.2",
|
|
65
61
|
"reset-css": "^5.0.2",
|
|
66
|
-
"sass-embedded": "^1.
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"style-loader": "^4.0.0",
|
|
71
|
-
"stylelint": "^16.13.2",
|
|
72
|
-
"stylelint-config-standard-scss": "^14.0.0",
|
|
62
|
+
"sass-embedded": "^1.90.0",
|
|
63
|
+
"storybook": "^9.1.3",
|
|
64
|
+
"stylelint": "^16.23.1",
|
|
65
|
+
"stylelint-config-standard-scss": "^15.0.1",
|
|
73
66
|
"stylelint-config-standard-vue": "^1.0.0",
|
|
74
|
-
"stylelint-order": "^
|
|
75
|
-
"swiper": "^11.2.
|
|
76
|
-
"update-browserslist-db": "^1.1.2",
|
|
67
|
+
"stylelint-order": "^7.0.0",
|
|
68
|
+
"swiper": "^11.2.10",
|
|
77
69
|
"v-calendar": "3.0.1",
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
70
|
+
"vite": "^7.1.3",
|
|
71
|
+
"vue": "^3.5.19",
|
|
72
|
+
"vue-eslint-parser": "^10.2.0",
|
|
73
|
+
"yargs": "^18.0.0"
|
|
81
74
|
},
|
|
82
75
|
"msw": {
|
|
83
76
|
"workerDirectory": [
|
|
@@ -88,8 +81,8 @@
|
|
|
88
81
|
"@advdominion/get-scrollbar-width": "^2.0.0",
|
|
89
82
|
"@advdominion/is": "^1.0.0",
|
|
90
83
|
"@advdominion/pluralize": "^1.0.0",
|
|
91
|
-
"@advdominion/tooltip": "^
|
|
92
|
-
"color": "^
|
|
84
|
+
"@advdominion/tooltip": "^3.0.0",
|
|
85
|
+
"color": "^5.0.0",
|
|
93
86
|
"dayjs": "^1.0.0",
|
|
94
87
|
"imask": "^7.0.0",
|
|
95
88
|
"lodash-es": "^4.0.0",
|
|
@@ -40,7 +40,8 @@ $b: '.color-input';
|
|
|
40
40
|
width: 4px * 7;
|
|
41
41
|
|
|
42
42
|
&_transparent {
|
|
43
|
-
background-image:
|
|
43
|
+
background-image:
|
|
44
|
+
linear-gradient(45deg, $color-grey-80 25%, transparent 25%),
|
|
44
45
|
linear-gradient(-45deg, $color-grey-80 25%, transparent 25%),
|
|
45
46
|
linear-gradient(45deg, transparent 75%, $color-grey-80 75%),
|
|
46
47
|
linear-gradient(-45deg, transparent 75%, $color-grey-80 75%);
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
/* globals BX */
|
|
2
|
-
|
|
3
|
-
import { is } from '@advdominion/is';
|
|
4
1
|
import _throttle from 'lodash-es/throttle.js';
|
|
5
2
|
|
|
6
3
|
import { cssVar } from '../../helpers/css-var.js';
|
|
7
|
-
import { errorHandler } from '../../helpers/error-handler.js';
|
|
8
4
|
import { mm } from '../../helpers/mm.js';
|
|
9
|
-
import { clearLoaderTimeout, hide as hideLoader, show as showLoader } from '../loader/index.js';
|
|
10
5
|
import { disableScroll, enableScroll } from '../overlay/index.js';
|
|
6
|
+
import { request } from '../request/index.js';
|
|
11
7
|
|
|
12
8
|
const isDialogOverflow = ($b) => {
|
|
13
9
|
return $b.scrollHeight > $b.clientHeight;
|
|
@@ -16,7 +12,6 @@ const isDialogOverflow = ($b) => {
|
|
|
16
12
|
export const init = ($b) => {
|
|
17
13
|
// Перемещаем кнопку закрытия модального окна для моб. устройств
|
|
18
14
|
if (!mm('tablet-landscape-up')) {
|
|
19
|
-
// $b.find('.dialog__close').prependTo($b); ??
|
|
20
15
|
$b.prepend($b.querySelector('.dialog__close'));
|
|
21
16
|
}
|
|
22
17
|
// Отключаем скролл у body, если при загрузке на странице есть видимое диалоговое окно
|
|
@@ -109,52 +104,15 @@ export const initDialogContent = ($b) => {
|
|
|
109
104
|
|
|
110
105
|
export const get = async (id, url) => {
|
|
111
106
|
if (url && url !== '#') {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
'X-Requested-With': 'XMLHttpRequest',
|
|
118
|
-
'X-Session-Id': BX.message('bitrix_sessid'),
|
|
119
|
-
},
|
|
120
|
-
});
|
|
121
|
-
if (!response.ok) {
|
|
122
|
-
throw response;
|
|
123
|
-
}
|
|
124
|
-
let data = await response.text();
|
|
125
|
-
try {
|
|
126
|
-
data = JSON.parse(data);
|
|
127
|
-
if (is(data.redirect, 'String')) {
|
|
128
|
-
if (data.redirect) {
|
|
129
|
-
location.assign(data.redirect);
|
|
130
|
-
clearLoaderTimeout();
|
|
131
|
-
} else {
|
|
132
|
-
location.reload();
|
|
133
|
-
}
|
|
134
|
-
} else {
|
|
135
|
-
try {
|
|
136
|
-
await window.__FORMIX__DIALOG__INTERCEPT_DATA(data);
|
|
137
|
-
} catch {
|
|
138
|
-
console.warn('Функция __FORMIX__DIALOG__INTERCEPT_DATA не установлена');
|
|
139
|
-
}
|
|
140
|
-
data = data.content || '';
|
|
141
|
-
}
|
|
142
|
-
} catch {} // eslint-disable-line no-empty
|
|
143
|
-
if (data.length > 0) {
|
|
144
|
-
const $b = document.querySelector(id);
|
|
145
|
-
$b.querySelector('.dialog__container').innerHTML = data;
|
|
107
|
+
const { content } = await request({ url });
|
|
108
|
+
if (content) {
|
|
109
|
+
const $b = document.querySelector(id);
|
|
110
|
+
if ($b) {
|
|
111
|
+
$b.querySelector('.dialog__container').innerHTML = content;
|
|
146
112
|
await show($b);
|
|
147
|
-
hideLoader();
|
|
148
113
|
initDialogContent($b);
|
|
149
114
|
} else {
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
} catch (error) {
|
|
153
|
-
if (error.status === 401) {
|
|
154
|
-
location.reload();
|
|
155
|
-
} else {
|
|
156
|
-
hideLoader();
|
|
157
|
-
errorHandler(error);
|
|
115
|
+
console.error(`Диалоговое окно с id ${id} не найдено`);
|
|
158
116
|
}
|
|
159
117
|
}
|
|
160
118
|
} else {
|
|
@@ -193,11 +151,7 @@ document.body.addEventListener('click', (event) => {
|
|
|
193
151
|
if (target.closest('[data-dialog]')) {
|
|
194
152
|
event.preventDefault();
|
|
195
153
|
const $el = target.closest('[data-dialog]');
|
|
196
|
-
|
|
197
|
-
if (url) {
|
|
198
|
-
url = new URL(url, location.origin);
|
|
199
|
-
}
|
|
200
|
-
get($el.dataset.dialog, url);
|
|
154
|
+
get($el.dataset.dialog, $el.dataset.dialogFetch ?? $el.href);
|
|
201
155
|
} else if (target.closest('[data-dialog-close]')) {
|
|
202
156
|
hide(target.closest('[data-dialog-close]').closest('.dialog'));
|
|
203
157
|
} else if (target.matches('.dialog') && target === $pointerDownTarget) {
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
/* globals
|
|
1
|
+
/* globals SmartCaptcha, SMART_CAPTCHA_KEY */
|
|
2
2
|
|
|
3
|
-
import { is } from '@advdominion/is';
|
|
4
|
-
|
|
5
|
-
import { errorHandler } from '../../helpers/error-handler.js';
|
|
6
3
|
import { getSmartCaptcha } from '../../helpers/get-smart-captcha.js';
|
|
7
4
|
import { scrollTo } from '../../helpers/scroll-to.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
5
|
+
import { initDialogContent } from '../dialog/index.js';
|
|
6
|
+
import { request } from '../request/index.js';
|
|
10
7
|
|
|
11
8
|
const initFormContent = ($b) => {
|
|
12
9
|
try {
|
|
@@ -17,106 +14,34 @@ const initFormContent = ($b) => {
|
|
|
17
14
|
};
|
|
18
15
|
|
|
19
16
|
export const send = async ($b, url, method, data) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
if (method === 'GET') {
|
|
31
|
-
for (const [name, value] of data) {
|
|
32
|
-
url.searchParams.append(name, value);
|
|
33
|
-
}
|
|
34
|
-
} else {
|
|
35
|
-
options.body = data;
|
|
17
|
+
const { success, content } = await request({
|
|
18
|
+
$b,
|
|
19
|
+
url: url || $b.getAttribute('action'),
|
|
20
|
+
method: method || $b.getAttribute('method'),
|
|
21
|
+
data: data || new FormData($b),
|
|
22
|
+
});
|
|
23
|
+
if (success) {
|
|
24
|
+
$b.dispatchEvent(new CustomEvent('form-success', { bubbles: true }));
|
|
36
25
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return {};
|
|
46
|
-
});
|
|
47
|
-
if (is(data.redirect, 'String')) {
|
|
48
|
-
if (data.redirect) {
|
|
49
|
-
location.assign(data.redirect);
|
|
50
|
-
if (data.redirect.startsWith('tg:')) {
|
|
51
|
-
hideLoader();
|
|
52
|
-
} else {
|
|
53
|
-
clearLoaderTimeout();
|
|
54
|
-
}
|
|
55
|
-
} else {
|
|
56
|
-
location.reload();
|
|
57
|
-
}
|
|
26
|
+
if (content) {
|
|
27
|
+
const $dialog = $b.closest('.dialog');
|
|
28
|
+
if ($dialog) {
|
|
29
|
+
$dialog.querySelector('.dialog__container').innerHTML = content;
|
|
30
|
+
initDialogContent($dialog);
|
|
31
|
+
setTimeout(() => {
|
|
32
|
+
scrollToError($dialog);
|
|
33
|
+
});
|
|
58
34
|
} else {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (data.success) {
|
|
68
|
-
$b.dispatchEvent(new CustomEvent('form-success', { bubbles: true }));
|
|
69
|
-
}
|
|
70
|
-
if (data.dialog) {
|
|
71
|
-
const $dialog = document.querySelector(data.dialog.id);
|
|
72
|
-
$dialog.querySelector('.dialog__container').innerHTML = data.dialog.content;
|
|
73
|
-
showDialog($dialog);
|
|
74
|
-
}
|
|
75
|
-
if (data.reloadOnHideDialog) {
|
|
76
|
-
$b.closest('.dialog').addEventListener('dialog-hide', () => {
|
|
77
|
-
location.reload();
|
|
35
|
+
const $parent = $b.parentElement;
|
|
36
|
+
$b.outerHTML = content;
|
|
37
|
+
const $form = $parent.querySelector('.form');
|
|
38
|
+
if ($form) {
|
|
39
|
+
init($form);
|
|
40
|
+
initFormContent($form);
|
|
41
|
+
setTimeout(() => {
|
|
42
|
+
scrollToError($form);
|
|
78
43
|
});
|
|
79
44
|
}
|
|
80
|
-
if (data.hideDialog) {
|
|
81
|
-
hideDialog($b.closest('.dialog'));
|
|
82
|
-
}
|
|
83
|
-
if (data.trigger) {
|
|
84
|
-
const $trigger = document.querySelector(data.trigger);
|
|
85
|
-
if ($trigger) {
|
|
86
|
-
$trigger?.click();
|
|
87
|
-
console.error(`Элемент с селектором ${data.trigger} не найден`);
|
|
88
|
-
} else {
|
|
89
|
-
hideLoader();
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
if (data.content) {
|
|
93
|
-
const $dialog = $b.closest('.dialog');
|
|
94
|
-
if ($dialog) {
|
|
95
|
-
$dialog.querySelector('.dialog__container').innerHTML = data.content;
|
|
96
|
-
initDialogContent($dialog);
|
|
97
|
-
setTimeout(() => {
|
|
98
|
-
scrollToError($dialog);
|
|
99
|
-
});
|
|
100
|
-
} else {
|
|
101
|
-
const $parent = $b.parentElement;
|
|
102
|
-
$b.outerHTML = data.content;
|
|
103
|
-
const $form = $parent.querySelector('.form');
|
|
104
|
-
if ($form) {
|
|
105
|
-
init($form);
|
|
106
|
-
initFormContent($form);
|
|
107
|
-
setTimeout(() => {
|
|
108
|
-
scrollToError($form);
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
} catch (error) {
|
|
115
|
-
if (error.status === 401) {
|
|
116
|
-
location.reload();
|
|
117
|
-
} else {
|
|
118
|
-
hideLoader();
|
|
119
|
-
errorHandler(error);
|
|
120
45
|
}
|
|
121
46
|
}
|
|
122
47
|
};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/* globals BX */
|
|
2
|
+
|
|
3
|
+
import { is } from '@advdominion/is';
|
|
4
|
+
|
|
5
|
+
import { errorHandler } from '../../helpers/error-handler.js';
|
|
6
|
+
import { hide as hideDialog, initDialogContent, show as showDialog } from '../dialog/index.js';
|
|
7
|
+
import { clearLoaderTimeout, hide as hideLoader, show as showLoader } from '../loader/index.js';
|
|
8
|
+
import { initSidebarContent, show as showSidebar } from '../sidebar/index.js';
|
|
9
|
+
|
|
10
|
+
export const request = async ({ $b, url = '', method = 'GET', data = {}, loader = true, showLoaderDelay }) => {
|
|
11
|
+
url = new URL(url, location.origin);
|
|
12
|
+
const options = {
|
|
13
|
+
method,
|
|
14
|
+
headers: {
|
|
15
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
16
|
+
'X-Session-Id': BX.message('bitrix_sessid'),
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
if (method === 'GET') {
|
|
20
|
+
let entries;
|
|
21
|
+
if (data instanceof FormData) {
|
|
22
|
+
entries = data.entries();
|
|
23
|
+
} else if (is(data, 'String')) {
|
|
24
|
+
entries = Object.entries(JSON.parse(data));
|
|
25
|
+
} else {
|
|
26
|
+
entries = Object.entries(data);
|
|
27
|
+
}
|
|
28
|
+
for (const [name, value] of entries) {
|
|
29
|
+
url.searchParams.append(name, value);
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
if (data instanceof FormData || is(data, 'String')) {
|
|
33
|
+
options.body = data;
|
|
34
|
+
} else {
|
|
35
|
+
options.body = JSON.stringify(data);
|
|
36
|
+
options.headers['Content-Type'] = 'application/json';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (loader) {
|
|
40
|
+
showLoader(showLoaderDelay);
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const response = await fetch(url, options);
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
throw response;
|
|
46
|
+
}
|
|
47
|
+
const data = await response.json().catch(async () => {
|
|
48
|
+
console.warn('Ошибка при попытке преобразования ответа в JSON');
|
|
49
|
+
const content = await response.text();
|
|
50
|
+
return { content };
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (is(data.redirect, 'String')) {
|
|
54
|
+
if (data.redirect) {
|
|
55
|
+
location.assign(data.redirect);
|
|
56
|
+
if (data.redirect.startsWith('tg:')) {
|
|
57
|
+
if (loader) {
|
|
58
|
+
hideLoader();
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
clearLoaderTimeout();
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
location.reload();
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
try {
|
|
68
|
+
await window.__FORMIX__REQ__INTERCEPT_DATA(data);
|
|
69
|
+
} catch {
|
|
70
|
+
console.warn('Функция __FORMIX__REQUEST__INTERCEPT_DATA не установлена');
|
|
71
|
+
}
|
|
72
|
+
if (data.dialog) {
|
|
73
|
+
const $dialog = document.querySelector(data.dialog.id);
|
|
74
|
+
if ($dialog) {
|
|
75
|
+
$dialog.querySelector('.dialog__container').innerHTML = data.dialog.content;
|
|
76
|
+
await showDialog($dialog);
|
|
77
|
+
initDialogContent($dialog);
|
|
78
|
+
} else {
|
|
79
|
+
console.error(`Диалоговое окно с id ${data.trigger} не найдено`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (data.reloadOnHideDialog) {
|
|
83
|
+
if (data.dialog) {
|
|
84
|
+
const $dialog = document.querySelector(data.dialog.id);
|
|
85
|
+
$dialog?.addEventListener('dialog-hide', () => {
|
|
86
|
+
location.reload();
|
|
87
|
+
});
|
|
88
|
+
} else {
|
|
89
|
+
$b?.closest('.dialog').addEventListener('dialog-hide', () => {
|
|
90
|
+
location.reload();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (data.hideDialog) {
|
|
95
|
+
if (data.dialog) {
|
|
96
|
+
const $dialog = document.querySelector(data.dialog.id);
|
|
97
|
+
if ($dialog) {
|
|
98
|
+
hideDialog($dialog);
|
|
99
|
+
}
|
|
100
|
+
} else if ($b) {
|
|
101
|
+
hideDialog($b.closest('.dialog'));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (data.sidebar) {
|
|
105
|
+
const $sidebar = document.querySelector(data.sidebar.id);
|
|
106
|
+
if ($sidebar) {
|
|
107
|
+
$sidebar.innerHTML = data.sidebar.content;
|
|
108
|
+
await showSidebar($sidebar);
|
|
109
|
+
initSidebarContent($sidebar);
|
|
110
|
+
} else {
|
|
111
|
+
console.error(`Сайдбар с id ${data.trigger} не найден`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (data.trigger) {
|
|
115
|
+
const $trigger = document.querySelector(data.trigger);
|
|
116
|
+
if ($trigger) {
|
|
117
|
+
$trigger.click();
|
|
118
|
+
} else {
|
|
119
|
+
console.error(`Элемент с селектором ${data.trigger} не найден`);
|
|
120
|
+
if (loader) {
|
|
121
|
+
hideLoader();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (!(data.reloadOnHideDialog && data.hideDialog) && (!data.trigger || data.hideDialog) && loader) {
|
|
126
|
+
hideLoader();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return data;
|
|
131
|
+
} catch (error) {
|
|
132
|
+
if (error.status === 401) {
|
|
133
|
+
location.reload();
|
|
134
|
+
} else {
|
|
135
|
+
if (loader) {
|
|
136
|
+
hideLoader();
|
|
137
|
+
}
|
|
138
|
+
errorHandler(error);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
document.body.addEventListener('click', (event) => {
|
|
144
|
+
const { target } = event;
|
|
145
|
+
if (target.closest('[data-request]')) {
|
|
146
|
+
event.preventDefault();
|
|
147
|
+
const $el = target.closest('[data-request]');
|
|
148
|
+
const options = { $b: $el, url: $el.dataset.request ?? $el.href };
|
|
149
|
+
if ($el.dataset.requestMethod) {
|
|
150
|
+
options.method = $el.dataset.requestMethod;
|
|
151
|
+
}
|
|
152
|
+
if ($el.dataset.requestData) {
|
|
153
|
+
try {
|
|
154
|
+
options.method = JSON.parse($el.dataset.requestData);
|
|
155
|
+
} catch {
|
|
156
|
+
console.warn('Ошибка при попытке преобразования значения data-request-data в JSON');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if ($el.dataset.requestLoader === 'false') {
|
|
160
|
+
options.loader = false;
|
|
161
|
+
}
|
|
162
|
+
request(options);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
/* globals BX */
|
|
2
|
-
|
|
3
|
-
import { is } from '@advdominion/is';
|
|
4
|
-
|
|
5
1
|
import { cssVar } from '../../helpers/css-var.js';
|
|
6
|
-
import { errorHandler } from '../../helpers/error-handler.js';
|
|
7
2
|
import { mm } from '../../helpers/mm.js';
|
|
8
|
-
import { clearLoaderTimeout, hide as hideLoader, show as showLoader } from '../loader/index.js';
|
|
9
3
|
import { disableScroll, enableScroll, hide as hideOverlay, show as showOverlay } from '../overlay/index.js';
|
|
4
|
+
import { request } from '../request/index.js';
|
|
10
5
|
|
|
11
6
|
export const show = async ($b) => {
|
|
12
7
|
if ($b.id !== 'settings-generator') {
|
|
@@ -54,52 +49,15 @@ export const initSidebarContent = ($b) => {
|
|
|
54
49
|
|
|
55
50
|
export const get = async (id, url, showLoaderDelay) => {
|
|
56
51
|
if (url && url !== '#') {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
'X-Requested-With': 'XMLHttpRequest',
|
|
63
|
-
'X-Session-Id': BX.message('bitrix_sessid'),
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
if (!response.ok) {
|
|
67
|
-
throw response;
|
|
68
|
-
}
|
|
69
|
-
let data = await response.text();
|
|
70
|
-
try {
|
|
71
|
-
data = JSON.parse(data);
|
|
72
|
-
if (is(data.redirect, 'String')) {
|
|
73
|
-
if (data.redirect) {
|
|
74
|
-
location.assign(data.redirect);
|
|
75
|
-
clearLoaderTimeout();
|
|
76
|
-
} else {
|
|
77
|
-
location.reload();
|
|
78
|
-
}
|
|
79
|
-
} else {
|
|
80
|
-
try {
|
|
81
|
-
await window.__FORMIX__SIDEBAR__INTERCEPT_DATA(data);
|
|
82
|
-
} catch {
|
|
83
|
-
console.warn('Функция __FORMIX__SIDEBAR__INTERCEPT_DATA не установлена');
|
|
84
|
-
}
|
|
85
|
-
data = data.content || '';
|
|
86
|
-
}
|
|
87
|
-
} catch {} // eslint-disable-line no-empty
|
|
88
|
-
if (data.length > 0) {
|
|
89
|
-
const $b = document.querySelector(id);
|
|
90
|
-
$b.innerHTML = data;
|
|
52
|
+
const { content } = await request({ url, showLoaderDelay });
|
|
53
|
+
if (content) {
|
|
54
|
+
const $b = document.querySelector(id);
|
|
55
|
+
if ($b) {
|
|
56
|
+
$b.innerHTML = content;
|
|
91
57
|
await show($b);
|
|
92
|
-
hideLoader();
|
|
93
58
|
initSidebarContent($b);
|
|
94
59
|
} else {
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
} catch (error) {
|
|
98
|
-
if (error.status === 401) {
|
|
99
|
-
location.reload();
|
|
100
|
-
} else {
|
|
101
|
-
hideLoader();
|
|
102
|
-
errorHandler(error);
|
|
60
|
+
console.error(`Сайдбар с id ${id} не найден`);
|
|
103
61
|
}
|
|
104
62
|
}
|
|
105
63
|
} else {
|
|
@@ -119,29 +77,16 @@ for (const $el of $sidebars) {
|
|
|
119
77
|
}
|
|
120
78
|
}
|
|
121
79
|
|
|
122
|
-
document.body.addEventListener('click', (
|
|
123
|
-
const
|
|
124
|
-
if (
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
document.body.addEventListener('click', (e) => {
|
|
135
|
-
const $b = e.target.closest('[data-sidebar-close]')?.closest('.sidebar');
|
|
136
|
-
if ($b) {
|
|
137
|
-
hide($b);
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
document.body.addEventListener('click', (e) => {
|
|
142
|
-
if (e.target.classList.contains('overlay')) {
|
|
143
|
-
const $sidebars = document.querySelectorAll('.sidebar:not([hidden])');
|
|
144
|
-
for (const $el of $sidebars) {
|
|
80
|
+
document.body.addEventListener('click', (event) => {
|
|
81
|
+
const { target } = event;
|
|
82
|
+
if (target.closest('[data-sidebar]')) {
|
|
83
|
+
event.preventDefault();
|
|
84
|
+
const $el = target.closest('[data-sidebar]');
|
|
85
|
+
get($el.dataset.sidebar, $el.dataset.sidebarFetch ?? $el.href);
|
|
86
|
+
} else if (target.closest('[data-sidebar-close]')) {
|
|
87
|
+
hide(target.closest('[data-sidebar-close]').closest('.sidebar'));
|
|
88
|
+
} else if (target.classList.contains('overlay')) {
|
|
89
|
+
for (const $el of document.querySelectorAll('.sidebar:not([hidden])')) {
|
|
145
90
|
hide($el);
|
|
146
91
|
}
|
|
147
92
|
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/* globals BX */
|
|
2
|
+
|
|
3
|
+
import { is } from '@advdominion/is';
|
|
4
|
+
|
|
5
|
+
import { hide as hideDialog, initDialogContent, show as showDialog } from '../components/dialog/index.js';
|
|
6
|
+
import { clearLoaderTimeout, hide as hideLoader, show as showLoader } from '../components/loader.js';
|
|
7
|
+
import { initSidebarContent, show as showSidebar } from '../components/sidebar/index.js';
|
|
8
|
+
import { errorHandler } from './error-handler.js';
|
|
9
|
+
|
|
10
|
+
export const req = async ({ $b, url = '', method = 'GET', data = {}, loader = true, showLoaderDelay }) => {
|
|
11
|
+
url = new URL(url, location.origin);
|
|
12
|
+
const options = {
|
|
13
|
+
method,
|
|
14
|
+
headers: {
|
|
15
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
16
|
+
'X-Session-Id': BX.message('bitrix_sessid'),
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
if (method === 'GET') {
|
|
20
|
+
for (const [name, value] of data) {
|
|
21
|
+
url.searchParams.append(name, value);
|
|
22
|
+
}
|
|
23
|
+
} else {
|
|
24
|
+
options.body = data;
|
|
25
|
+
}
|
|
26
|
+
if (loader) {
|
|
27
|
+
showLoader(showLoaderDelay);
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const response = await fetch(url, options);
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw response;
|
|
33
|
+
}
|
|
34
|
+
const data = await response.json().catch(async () => {
|
|
35
|
+
console.warn('Ошибка при попытке преобразования ответа в JSON.');
|
|
36
|
+
const content = await response.text();
|
|
37
|
+
return { content };
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (is(data.redirect, 'String')) {
|
|
41
|
+
if (data.redirect) {
|
|
42
|
+
location.assign(data.redirect);
|
|
43
|
+
if (data.redirect.startsWith('tg:')) {
|
|
44
|
+
if (loader) {
|
|
45
|
+
hideLoader();
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
clearLoaderTimeout();
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
location.reload();
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
try {
|
|
55
|
+
await window.__FORMIX__REQ__INTERCEPT_DATA(data);
|
|
56
|
+
} catch {
|
|
57
|
+
console.warn('Функция __FORMIX__REQUEST__INTERCEPT_DATA не установлена');
|
|
58
|
+
}
|
|
59
|
+
if (data.dialog) {
|
|
60
|
+
const $dialog = document.querySelector(data.dialog.id);
|
|
61
|
+
if ($dialog) {
|
|
62
|
+
$dialog.querySelector('.dialog__container').innerHTML = data.dialog.content;
|
|
63
|
+
await showDialog($dialog);
|
|
64
|
+
initDialogContent($dialog);
|
|
65
|
+
} else {
|
|
66
|
+
console.error(`Диалоговое окно с id ${data.trigger} не найдено`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (data.reloadOnHideDialog) {
|
|
70
|
+
if (data.dialog) {
|
|
71
|
+
const $dialog = document.querySelector(data.dialog.id);
|
|
72
|
+
$dialog?.addEventListener('dialog-hide', () => {
|
|
73
|
+
location.reload();
|
|
74
|
+
});
|
|
75
|
+
} else {
|
|
76
|
+
$b?.closest('.dialog').addEventListener('dialog-hide', () => {
|
|
77
|
+
location.reload();
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (data.hideDialog) {
|
|
82
|
+
if (data.dialog) {
|
|
83
|
+
const $dialog = document.querySelector(data.dialog.id);
|
|
84
|
+
if ($dialog) {
|
|
85
|
+
hideDialog($dialog);
|
|
86
|
+
}
|
|
87
|
+
} else if ($b) {
|
|
88
|
+
hideDialog($b.closest('.dialog'));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (data.sidebar) {
|
|
92
|
+
const $sidebar = document.querySelector(data.sidebar.id);
|
|
93
|
+
if ($sidebar) {
|
|
94
|
+
$sidebar.innerHTML = data.sidebar.content;
|
|
95
|
+
await showSidebar($sidebar);
|
|
96
|
+
initSidebarContent($sidebar);
|
|
97
|
+
} else {
|
|
98
|
+
console.error(`Сайдбар с id ${data.trigger} не найден`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (data.trigger) {
|
|
102
|
+
const $trigger = document.querySelector(data.trigger);
|
|
103
|
+
if ($trigger) {
|
|
104
|
+
$trigger?.click();
|
|
105
|
+
console.error(`Элемент с селектором ${data.trigger} не найден`);
|
|
106
|
+
} else if (loader) {
|
|
107
|
+
hideLoader();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (!(data.reloadOnHideDialog && data.hideDialog) && (!data.trigger || data.hideDialog) && loader) {
|
|
111
|
+
hideLoader();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return data;
|
|
116
|
+
} catch (error) {
|
|
117
|
+
if (error.status === 401) {
|
|
118
|
+
location.reload();
|
|
119
|
+
} else {
|
|
120
|
+
if (loader) {
|
|
121
|
+
hideLoader();
|
|
122
|
+
}
|
|
123
|
+
errorHandler(error);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
};
|
package/vite.config.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
5
|
+
|
|
6
|
+
import vue from '@vitejs/plugin-vue';
|
|
7
|
+
import { defineConfig } from 'vite';
|
|
8
|
+
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
|
|
11
|
+
export default defineConfig({
|
|
12
|
+
plugins: [
|
|
13
|
+
vue({
|
|
14
|
+
template: {
|
|
15
|
+
transformAssetUrls: {
|
|
16
|
+
video: [],
|
|
17
|
+
source: [],
|
|
18
|
+
img: [],
|
|
19
|
+
image: [],
|
|
20
|
+
use: [],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
],
|
|
25
|
+
css: {
|
|
26
|
+
preprocessorOptions: {
|
|
27
|
+
scss: {
|
|
28
|
+
api: 'modern-compiler',
|
|
29
|
+
importers: [
|
|
30
|
+
{
|
|
31
|
+
canonicalize(url, context) {
|
|
32
|
+
if (url.startsWith('pkg:')) {
|
|
33
|
+
return pathToFileURL(require.resolve(url.replace('pkg:', '')));
|
|
34
|
+
}
|
|
35
|
+
// Обработка относительных путей внутри pkg:
|
|
36
|
+
if (context.containingUrl?.href.includes('node_modules')) {
|
|
37
|
+
const basePath = path.dirname(fileURLToPath(context.containingUrl));
|
|
38
|
+
const resolvedPath = path.resolve(basePath, url);
|
|
39
|
+
|
|
40
|
+
// Пробуем найти файл с нужным названием (проверка на пустую строку нужна для случаев, когда в URL уже стоит файл с расширением)
|
|
41
|
+
const extensions = ['', '.scss'];
|
|
42
|
+
for (const ext of extensions) {
|
|
43
|
+
const fullPath = resolvedPath + ext;
|
|
44
|
+
try {
|
|
45
|
+
if (readFileSync(fullPath)) {
|
|
46
|
+
return pathToFileURL(fullPath);
|
|
47
|
+
}
|
|
48
|
+
} catch {} // eslint-disable-line no-empty
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Если не нашли файл с нужным названием, пробуем найти index
|
|
52
|
+
for (const ext of ['.scss']) {
|
|
53
|
+
const indexPath = path.join(resolvedPath, `index${ext}`);
|
|
54
|
+
try {
|
|
55
|
+
if (readFileSync(indexPath)) {
|
|
56
|
+
return pathToFileURL(indexPath);
|
|
57
|
+
}
|
|
58
|
+
} catch {} // eslint-disable-line no-empty
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// eslint-disable-next-line unicorn/no-null
|
|
62
|
+
return null;
|
|
63
|
+
},
|
|
64
|
+
load(canonicalUrl) {
|
|
65
|
+
return {
|
|
66
|
+
contents: readFileSync(fileURLToPath(canonicalUrl), 'utf8'),
|
|
67
|
+
syntax: 'scss',
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
});
|