vgapp 1.1.8 → 1.2.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 +30 -11
- package/app/modules/vgformsender/js/vgformsender.js +122 -32
- package/app/modules/vgtoast/js/vgtoast.js +48 -27
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,14 +1,29 @@
|
|
|
1
|
-
# VEGAS-APP 1.
|
|
2
|
-
## Новые фичи
|
|
3
|
-
* В
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
# VEGAS-APP 1.2.0 (Июнь, 16, 2026)
|
|
2
|
+
## Новые фичи
|
|
3
|
+
* В VGToast добавлен параметр `type` со встроенными SVG-иконками для типов `success`, `error`, `warning`, `info`.
|
|
4
|
+
* В VGFormSender добавлен новый режим алертов `alert.type = 'toast'` с интеграцией через `VGToast`.
|
|
5
|
+
|
|
6
|
+
## Изменения
|
|
7
|
+
* В VGToast добавлена мапа типов уведомлений на набор иконок `getSVG`, включая `error -> danger`.
|
|
8
|
+
* Вставка SVG-иконок в VGToast переведена на безопасную схему через `Sanitize.toSafeHtmlString()` и DOM fragment вместо прямого `innerHTML`.
|
|
9
|
+
* В VGFormSender выделена общая подготовка содержимого алертов в `_prepareAlertResponse()`, чтобы единообразно собирать `title/message` для modal, collapse и toast.
|
|
10
|
+
* В VGFormSender добавлена сборка toast-параметров из `alert.*` и `alert.toast`, включая проброс `theme`, `type`, `placement`, `autohide`, `delay`, `drag`, `resize`, `stack`, `animation`, `ajax`.
|
|
11
|
+
* В VGRollup исправлена инициализация локализованных текстов: язык и подписи кнопок теперь подставляются до слияния параметров, с учётом `data-lang` и `params.lang`.
|
|
12
|
+
* Обновлена версия пакета в `package.json`: `1.1.7` -> `1.2.0`.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# VEGAS-APP 1.1.7 (Апрель, 13, 2026)
|
|
17
|
+
## Новые фичи
|
|
18
|
+
* В VGFilePreview добавлена поддержка атрибута `data-name` для явной установки отображаемого имени файла (в приоритете над `data-vg-filepreview-display-name`).
|
|
19
|
+
|
|
20
|
+
## Изменения
|
|
21
|
+
* Обновлена версия пакета в `package.json`: `1.1.6` -> `1.1.7`.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# VEGAS-APP 1.1.6 (Апрель, 10, 2026)
|
|
26
|
+
## Новые фичи
|
|
12
27
|
* **VGToast**: добавлены встроенные модули VGToastDrag и VGToastResize с поддержкой параметров drag/resize (enable, threshold, edgeSize, minWidth/minHeight, debug).
|
|
13
28
|
|
|
14
29
|
## Изменения
|
|
@@ -298,3 +313,7 @@
|
|
|
298
313
|
---
|
|
299
314
|
|
|
300
315
|
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
import BaseModule from "../../base-module";
|
|
33
33
|
import VGModal from "../../vgmodal/js/vgmodal";
|
|
34
34
|
import VGCollapse from "../../vgcollapse/js/vgcollapse";
|
|
35
|
+
import VGToast from "../../vgtoast/js/vgtoast";
|
|
35
36
|
import VGHideShowPass from "./hideshowpass";
|
|
36
37
|
import {lang_titles, lang_messages} from "../../../utils/js/components/lang";
|
|
37
38
|
import Html from "../../../utils/js/components/templater";
|
|
@@ -133,7 +134,8 @@ class VGFormSender extends BaseModule {
|
|
|
133
134
|
enabled: true,
|
|
134
135
|
type: 'modal',
|
|
135
136
|
errors: true,
|
|
136
|
-
delay: 0
|
|
137
|
+
delay: 0,
|
|
138
|
+
toast: {}
|
|
137
139
|
},
|
|
138
140
|
ajax: {
|
|
139
141
|
route: '',
|
|
@@ -510,6 +512,10 @@ class VGFormSender extends BaseModule {
|
|
|
510
512
|
if (this._params.alert.type === 'collapse') {
|
|
511
513
|
this._alertCollapse(data, status)
|
|
512
514
|
}
|
|
515
|
+
|
|
516
|
+
if (this._params.alert.type === 'toast') {
|
|
517
|
+
this._alertToast(data, status)
|
|
518
|
+
}
|
|
513
519
|
}
|
|
514
520
|
|
|
515
521
|
/**
|
|
@@ -602,6 +608,65 @@ class VGFormSender extends BaseModule {
|
|
|
602
608
|
}
|
|
603
609
|
}
|
|
604
610
|
|
|
611
|
+
/**
|
|
612
|
+
* Показ алерта в виде toast
|
|
613
|
+
* @param {Object} data - Данные для отображения
|
|
614
|
+
* @param {string} status - Статус (success/error)
|
|
615
|
+
* @private
|
|
616
|
+
*/
|
|
617
|
+
_alertToast(data, status) {
|
|
618
|
+
const response = this._prepareAlertResponse(status, data);
|
|
619
|
+
const toastParams = this._getToastParams(status);
|
|
620
|
+
|
|
621
|
+
if (response.title) {
|
|
622
|
+
VGToast.run([response.title, response.message], toastParams);
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
VGToast.run(response.message, toastParams);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* Сборка параметров toast из alert.* и alert.toast
|
|
631
|
+
* @param {string} status - Статус алерта
|
|
632
|
+
* @returns {Object}
|
|
633
|
+
* @private
|
|
634
|
+
*/
|
|
635
|
+
_getToastParams(status) {
|
|
636
|
+
const theme = status === 'error' ? 'danger' : status;
|
|
637
|
+
const delay = this._params.alert.delay > 0 ? this._params.alert.delay : 3000;
|
|
638
|
+
const flatToastParams = {};
|
|
639
|
+
const allowedKeys = [
|
|
640
|
+
'static',
|
|
641
|
+
'placement',
|
|
642
|
+
'autohide',
|
|
643
|
+
'delay',
|
|
644
|
+
'enableClickToast',
|
|
645
|
+
'enableButtonClose',
|
|
646
|
+
'keyboard',
|
|
647
|
+
'theme',
|
|
648
|
+
'type',
|
|
649
|
+
'drag',
|
|
650
|
+
'resize',
|
|
651
|
+
'stack',
|
|
652
|
+
'animation',
|
|
653
|
+
'ajax'
|
|
654
|
+
];
|
|
655
|
+
|
|
656
|
+
allowedKeys.forEach((key) => {
|
|
657
|
+
if (key in this._params.alert) {
|
|
658
|
+
flatToastParams[key] = this._params.alert[key];
|
|
659
|
+
}
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
return mergeDeepObject({
|
|
663
|
+
theme: theme || 'dark',
|
|
664
|
+
enableButtonClose: true,
|
|
665
|
+
autohide: this._params.alert.delay > 0,
|
|
666
|
+
delay: delay
|
|
667
|
+
}, flatToastParams, this._params.alert.toast || {});
|
|
668
|
+
}
|
|
669
|
+
|
|
605
670
|
/**
|
|
606
671
|
* Формирование содержимого алерта (заголовок, текст, иконка)
|
|
607
672
|
* @param {HTMLElement} $element - Родительский элемент
|
|
@@ -611,15 +676,51 @@ class VGFormSender extends BaseModule {
|
|
|
611
676
|
* @returns {HTMLElement} - DOM-элемент с контентом
|
|
612
677
|
*/
|
|
613
678
|
setDataRelationStatus($element, status, data, type) {
|
|
614
|
-
let
|
|
615
|
-
|
|
679
|
+
let $alert = Selectors.find('.'+ CLASS_NAME_ALERT +'-content', $element);
|
|
680
|
+
const response = this._prepareAlertResponse(status, data);
|
|
681
|
+
const title = response.title
|
|
682
|
+
? Html('string').h4({class: CLASS_NAME_ALERT +'-content--title'}, response.title)
|
|
683
|
+
: '';
|
|
684
|
+
const content = title + response.message;
|
|
685
|
+
|
|
686
|
+
if (!$alert) {
|
|
687
|
+
const elm = Html('dom');
|
|
688
|
+
|
|
689
|
+
$alert = elm.div({
|
|
690
|
+
class: CLASS_NAME_ALERT + '-' + type
|
|
691
|
+
}, [
|
|
692
|
+
elm.div({class: CLASS_NAME_ALERT + '-content'}, [
|
|
693
|
+
elm.i({class: CLASS_NAME_ALERT + '-content--icon'}, getSVG(status), {isHTML: true}),
|
|
694
|
+
elm.div({class: CLASS_NAME_ALERT + '-content--text'}, content, {isHTML: true})
|
|
695
|
+
]),
|
|
696
|
+
]);
|
|
697
|
+
} else {
|
|
698
|
+
let text = Selectors.find('.vg-modal-body', $element);
|
|
699
|
+
text.innerHTML = content;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
return $alert;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* Подготовка содержимого алерта
|
|
707
|
+
* @param {string} status - Статус алерта
|
|
708
|
+
* @param {Object|string} data - Данные ответа
|
|
709
|
+
* @returns {{title: string, message: string}}
|
|
710
|
+
* @private
|
|
711
|
+
*/
|
|
712
|
+
_prepareAlertResponse(status, data) {
|
|
713
|
+
let response = normalizeData(data?.response) || data;
|
|
616
714
|
|
|
617
715
|
if (isObject(data)) {
|
|
618
|
-
|
|
716
|
+
if (isObject(data.response) && 'view' in data.response) {
|
|
717
|
+
return {
|
|
718
|
+
title: '',
|
|
719
|
+
message: data.response.view
|
|
720
|
+
};
|
|
721
|
+
}
|
|
619
722
|
|
|
620
|
-
if ('
|
|
621
|
-
response = data.response.view
|
|
622
|
-
} else if (typeof response !== 'string') {
|
|
723
|
+
if (typeof response !== 'string') {
|
|
623
724
|
if (status === 'danger') {
|
|
624
725
|
response.title = ('title' in response) ? response.title : lang_titles(this._params.lang, 'errors').title;
|
|
625
726
|
|
|
@@ -646,7 +747,7 @@ class VGFormSender extends BaseModule {
|
|
|
646
747
|
if (isObject(errors)) {
|
|
647
748
|
for (const error in errors) {
|
|
648
749
|
if (Array.isArray(errors[error])) {
|
|
649
|
-
errors[error].forEach((
|
|
750
|
+
errors[error].forEach((text) => response.message.push(text))
|
|
650
751
|
} else {
|
|
651
752
|
response.message.push(errors[error]);
|
|
652
753
|
}
|
|
@@ -656,42 +757,31 @@ class VGFormSender extends BaseModule {
|
|
|
656
757
|
}
|
|
657
758
|
|
|
658
759
|
const elm = Html('string');
|
|
659
|
-
|
|
660
|
-
view = elm.h4({class: CLASS_NAME_ALERT +'-content--title'}, response.title);
|
|
760
|
+
let message = '';
|
|
661
761
|
|
|
662
762
|
if (Array.isArray(response.message)) {
|
|
663
|
-
response.message.forEach(
|
|
664
|
-
|
|
763
|
+
response.message.forEach((text) => {
|
|
764
|
+
message += elm.div({
|
|
665
765
|
class: CLASS_NAME_ALERT +'-content--message'
|
|
666
|
-
},
|
|
766
|
+
}, text);
|
|
667
767
|
})
|
|
668
768
|
} else {
|
|
669
|
-
|
|
769
|
+
message = elm.div({
|
|
670
770
|
class: CLASS_NAME_ALERT +'-content--message'
|
|
671
771
|
}, response.message);
|
|
672
772
|
}
|
|
673
773
|
|
|
674
|
-
|
|
774
|
+
return {
|
|
775
|
+
title: response.title || '',
|
|
776
|
+
message: message
|
|
777
|
+
};
|
|
675
778
|
}
|
|
676
779
|
}
|
|
677
780
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
class: CLASS_NAME_ALERT + '-' + type
|
|
683
|
-
}, [
|
|
684
|
-
elm.div({class: CLASS_NAME_ALERT + '-content'}, [
|
|
685
|
-
elm.i({class: CLASS_NAME_ALERT + '-content--icon'}, getSVG(status), {isHTML: true}),
|
|
686
|
-
elm.div({class: CLASS_NAME_ALERT + '-content--text'}, response, {isHTML: true})
|
|
687
|
-
]),
|
|
688
|
-
]);
|
|
689
|
-
} else {
|
|
690
|
-
let text = Selectors.find('.vg-modal-body', $element);
|
|
691
|
-
text.innerHTML = response;
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
return $alert;
|
|
781
|
+
return {
|
|
782
|
+
title: '',
|
|
783
|
+
message: typeof response === 'string' ? response : ''
|
|
784
|
+
};
|
|
695
785
|
}
|
|
696
786
|
|
|
697
787
|
/**
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import BaseModule from "../../base-module";
|
|
2
|
-
import EventHandler from "../../../utils/js/dom/event";
|
|
3
|
-
import {dismissTrigger} from "../../module-fn";
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
2
|
+
import EventHandler from "../../../utils/js/dom/event";
|
|
3
|
+
import {dismissTrigger, getSVG} from "../../module-fn";
|
|
4
|
+
import Sanitize from "../../../utils/js/components/sanitize";
|
|
5
|
+
import {execute, isDisabled, makeRandomString, mergeDeepObject} from "../../../utils/js/functions";
|
|
6
|
+
import Selectors from "../../../utils/js/dom/selectors";
|
|
7
|
+
import VGToastDrag from "./vgtoast.drag";
|
|
8
|
+
import VGToastResize from "./vgtoast.resize";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* @constant {string} NAME - Имя модуля.
|
|
@@ -54,9 +55,15 @@ const EVENT_KEY_LOADED = `${NAME_KEY}.loaded`;
|
|
|
54
55
|
const EVENT_KEY_KEYDOWN_DISMISS = `keydown.dismiss.${NAME_KEY}`;
|
|
55
56
|
const EVENT_KEY_HIDE_PREVENTED = `hidePrevented.${NAME_KEY}`;
|
|
56
57
|
const EVENT_KEY_CLICK_DATA_API = `click.${NAME_KEY}.data.api`;
|
|
57
|
-
const EVENT_KEY_POINTERDOWN_INTERACTION = `pointerdown.interaction.${NAME_KEY}`;
|
|
58
|
-
const EVENT_KEY_POINTERUP_INTERACTION = `pointerup.interaction.${NAME_KEY}`;
|
|
59
|
-
const EVENT_KEY_POINTERCANCEL_INTERACTION = `pointercancel.interaction.${NAME_KEY}`;
|
|
58
|
+
const EVENT_KEY_POINTERDOWN_INTERACTION = `pointerdown.interaction.${NAME_KEY}`;
|
|
59
|
+
const EVENT_KEY_POINTERUP_INTERACTION = `pointerup.interaction.${NAME_KEY}`;
|
|
60
|
+
const EVENT_KEY_POINTERCANCEL_INTERACTION = `pointercancel.interaction.${NAME_KEY}`;
|
|
61
|
+
const TOAST_ICON_MAP = {
|
|
62
|
+
success: 'success',
|
|
63
|
+
error: 'danger',
|
|
64
|
+
warning: 'warning',
|
|
65
|
+
info: 'info',
|
|
66
|
+
};
|
|
60
67
|
|
|
61
68
|
/**
|
|
62
69
|
* @typedef {Object} ToastParams
|
|
@@ -65,12 +72,13 @@ const EVENT_KEY_POINTERCANCEL_INTERACTION = `pointercancel.interaction.${NAME_KE
|
|
|
65
72
|
* @property {boolean} autohide - Автоматически скрывать.
|
|
66
73
|
* @property {number} delay - Задержка перед авто-скрытием (мс).
|
|
67
74
|
* @property {boolean} enableClickToast - Закрывать по клику на тост.
|
|
68
|
-
* @property {boolean} enableButtonClose - Добавить кнопку закрытия.
|
|
69
|
-
* @property {boolean} keyboard - Закрывать по Esc.
|
|
70
|
-
* @property {string} theme - Тема: 'dark', 'light' и т.д.
|
|
71
|
-
* @property {
|
|
72
|
-
* @property {
|
|
73
|
-
* @property {
|
|
75
|
+
* @property {boolean} enableButtonClose - Добавить кнопку закрытия.
|
|
76
|
+
* @property {boolean} keyboard - Закрывать по Esc.
|
|
77
|
+
* @property {string} theme - Тема: 'dark', 'light' и т.д.
|
|
78
|
+
* @property {('success'|'error'|'warning'|'info'|null)} type - Тип уведомления для вывода иконки.
|
|
79
|
+
* @property {Object} stack - Настройки стека уведомлений.
|
|
80
|
+
* @property {boolean} stack.enable - Разрешить стек.
|
|
81
|
+
* @property {number} stack.max - Макс. количество тостов одновременно.
|
|
74
82
|
* @property {Object} animation - Анимация.
|
|
75
83
|
* @property {boolean} animation.enable - Включить анимацию.
|
|
76
84
|
* @property {string} animation.in - Анимация входа (Animate.css).
|
|
@@ -96,12 +104,13 @@ const defaultParams = {
|
|
|
96
104
|
autohide: false,
|
|
97
105
|
delay: 3000,
|
|
98
106
|
enableClickToast: true,
|
|
99
|
-
enableButtonClose: false,
|
|
100
|
-
keyboard: true,
|
|
101
|
-
theme: 'dark',
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
107
|
+
enableButtonClose: false,
|
|
108
|
+
keyboard: true,
|
|
109
|
+
theme: 'dark',
|
|
110
|
+
type: null,
|
|
111
|
+
stack: {
|
|
112
|
+
enable: true,
|
|
113
|
+
max: 5
|
|
105
114
|
},
|
|
106
115
|
drag: {
|
|
107
116
|
enable: false,
|
|
@@ -239,12 +248,24 @@ class VGToast extends BaseModule {
|
|
|
239
248
|
const wrapper = document.createElement('div');
|
|
240
249
|
wrapper.classList.add('vg-toast-wrapper');
|
|
241
250
|
|
|
242
|
-
// Иконка (если задан тип)
|
|
243
|
-
if (params.type) {
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
251
|
+
// Иконка (если задан тип)
|
|
252
|
+
if (params.type) {
|
|
253
|
+
const iconName = TOAST_ICON_MAP[params.type];
|
|
254
|
+
const iconSvg = iconName ? getSVG(iconName) : '';
|
|
255
|
+
|
|
256
|
+
if (iconSvg) {
|
|
257
|
+
const icon = document.createElement('div');
|
|
258
|
+
icon.classList.add('vg-toast-icon');
|
|
259
|
+
const safeIconSvg = Sanitize.toSafeHtmlString(iconSvg);
|
|
260
|
+
const fragment = document.createRange().createContextualFragment(safeIconSvg);
|
|
261
|
+
const svgElement = fragment.firstElementChild;
|
|
262
|
+
|
|
263
|
+
if (svgElement) {
|
|
264
|
+
icon.append(svgElement);
|
|
265
|
+
}
|
|
266
|
+
wrapper.append(icon);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
248
269
|
|
|
249
270
|
const content = document.createElement('div');
|
|
250
271
|
content.classList.add('vg-toast-content');
|