vgapp 1.5.7 → 1.5.8
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/app/langs/en/buttons.json +17 -17
- package/app/langs/en/messages.json +36 -36
- package/app/langs/ru/buttons.json +17 -17
- package/app/langs/ru/messages.json +1 -1
- package/app/modules/vgalert/js/vgalert.js +7 -7
- package/app/modules/vgalert/scss/_variables.scss +16 -16
- package/app/modules/vgcollapse/scss/_variables.scss +7 -7
- package/app/modules/vgcollapse/scss/vgcollapse.scss +5 -5
- package/app/modules/vgdropdown/scss/_variables.scss +14 -14
- package/app/modules/vgdropdown/scss/vgdropdown.scss +5 -5
- package/app/modules/vgfilepreview/js/i18n.js +56 -56
- package/app/modules/vgfilepreview/js/renderers/image-modal.js +145 -145
- package/app/modules/vgfilepreview/js/renderers/image.js +92 -92
- package/app/modules/vgfilepreview/js/renderers/index.js +19 -19
- package/app/modules/vgfilepreview/js/renderers/office-modal.js +168 -168
- package/app/modules/vgfilepreview/js/renderers/office.js +79 -79
- package/app/modules/vgfilepreview/js/renderers/pdf-modal.js +260 -260
- package/app/modules/vgfilepreview/js/renderers/pdf.js +76 -76
- package/app/modules/vgfilepreview/js/renderers/playlist.js +71 -71
- package/app/modules/vgfilepreview/js/renderers/text-modal.js +343 -343
- package/app/modules/vgfilepreview/js/renderers/text.js +83 -83
- package/app/modules/vgfilepreview/js/renderers/zip-modal.js +522 -522
- package/app/modules/vgfilepreview/js/renderers/zip.js +89 -89
- package/app/modules/vgfilepreview/readme.md +68 -68
- package/app/modules/vgfiles/js/base.js +198 -198
- package/app/modules/vgfiles/js/droppable.js +17 -17
- package/app/modules/vgfiles/js/render.js +153 -153
- package/app/modules/vgfiles/js/sortable.js +52 -52
- package/app/modules/vgfiles/js/vgfiles.js +43 -43
- package/app/modules/vgfiles/readme.md +123 -123
- package/app/modules/vgfiles/scss/_mixins.scss +13 -13
- package/app/modules/vgfiles/scss/_variables.scss +10 -10
- package/app/modules/vgfiles/scss/vgfiles.scss +28 -28
- package/app/modules/vgformsender/js/hideshowpass.js +22 -22
- package/app/modules/vgformsender/readme.md +1 -1
- package/app/modules/vgformsender/scss/_variables.scss +5 -5
- package/app/modules/vgformsender/scss/vgformsender.scss +42 -42
- package/app/modules/vglawcookie/js/vglawcookie.js +19 -19
- package/app/modules/vglawcookie/scss/_variables.scss +13 -13
- package/app/modules/vglawcookie/scss/vglawcookie.scss +5 -5
- package/app/modules/vgmodal/js/vgmodal.interaction.js +216 -216
- package/app/modules/vgmodal/js/vgmodal.js +9 -9
- package/app/modules/vgmodal/js/vgmodal.minimized.js +227 -227
- package/app/modules/vgmodal/scss/_variables.scss +17 -17
- package/app/modules/vgmodal/scss/vgmodal.scss +77 -77
- package/app/modules/vgnav/js/vgnav.js +62 -62
- package/app/modules/vgnav/scss/_breakpoints.scss +36 -36
- package/app/modules/vgnav/scss/_hamburger.scss +5 -5
- package/app/modules/vgnav/scss/_placement.scss +5 -5
- package/app/modules/vgnav/scss/_toggle.scss +5 -5
- package/app/modules/vgnav/scss/_variables.scss +26 -26
- package/app/modules/vgnav/scss/vgnav.scss +41 -41
- package/app/modules/vgnestable/README.md +39 -39
- package/app/modules/vgrangeslider/js/skins.js +8 -8
- package/app/modules/vgrangeslider/js/vgrangeslider.js +29 -29
- package/app/modules/vgrangeslider/scss/_variables.scss +55 -55
- package/app/modules/vgrangeslider/scss/vgrangeslider.scss +239 -239
- package/app/modules/vgrollup/js/vgrollup.js +15 -15
- package/app/modules/vgrollup/scss/_variables.scss +15 -15
- package/app/modules/vgrollup/scss/vgrollup.scss +6 -6
- package/app/modules/vgselect/js/handlers.js +6 -6
- package/app/modules/vgselect/js/vgselect.js +167 -123
- package/app/modules/vgselect/readme.md +11 -11
- package/app/modules/vgselect/scss/_variables.scss +51 -51
- package/app/modules/vgselect/scss/vgselect.scss +1 -1
- package/app/modules/vgsidebar/js/vgsidebar.js +21 -21
- package/app/modules/vgsidebar/scss/_variables.scss +10 -10
- package/app/modules/vgsidebar/scss/vgsidebar.scss +5 -5
- package/app/modules/vgspy/js/vgspy.js +43 -43
- package/app/modules/vgtable/js/_filters.js +10 -6
- package/app/modules/vgtable/js/_options.js +16 -16
- package/app/modules/vgtable/js/_pagination.js +118 -118
- package/app/modules/vgtable/js/_responsive.js +79 -79
- package/app/modules/vgtable/js/_sticky-header.js +349 -280
- package/app/modules/vgtable/js/vgtable.js +98 -98
- package/app/modules/vgtable/scss/_sorting.scss +6 -6
- package/app/modules/vgtable/scss/_sticky-header.scss +31 -31
- package/app/modules/vgtable/scss/_variables.scss +6 -4
- package/app/modules/vgtable/scss/vgtable.scss +8 -4
- package/app/modules/vgtabs/js/vgtabs.js +91 -91
- package/app/modules/vgtabs/scss/_variables.scss +23 -23
- package/app/modules/vgtabs/scss/vgtabs.scss +5 -5
- package/app/modules/vgtoast/js/vgtoast.js +4 -4
- package/app/modules/vgtoast/scss/_variables.scss +13 -13
- package/app/modules/vgtoast/scss/vgtoast.scss +5 -5
- package/app/modules/vgtooltip/js/vgtooltip.js +127 -127
- package/app/modules/vgtooltip/scss/_variables.scss +10 -10
- package/app/modules/vgtooltip/scss/vgtooltip.scss +5 -5
- package/app/utils/js/components/audio-metadata.js +240 -240
- package/app/utils/js/components/backdrop.js +116 -116
- package/app/utils/js/components/file-icon.js +7 -7
- package/app/utils/js/components/file-preview.js +304 -304
- package/app/utils/js/components/responsive.js +165 -165
- package/app/utils/js/components/sanitize.js +150 -150
- package/app/utils/js/components/video-metadata.js +140 -140
- package/app/utils/scss/_backdrop.scss +5 -5
- package/app/utils/scss/_theme-default.scss +12 -12
- package/app/utils/scss/_theme.scss +7 -7
- package/app/utils/scss/default.scss +9 -9
- package/app/utils/scss/functions.scss +21 -21
- package/app/utils/scss/index.scss +4 -4
- package/app/utils/scss/mixin.scss +16 -16
- package/app/utils/scss/variables.scss +147 -147
- package/build/vgapp.css +1 -1
- package/build/vgapp.css.map +1 -1
- package/build/vgapp.js +1 -1
- package/build/vgapp.js.map +1 -1
- package/index.js +7 -7
- package/package.json +1 -1
|
@@ -1,154 +1,154 @@
|
|
|
1
|
-
import { isElement, normalizeData } from "../../../utils/js/functions";
|
|
2
|
-
import Params from "../../../utils/js/components/params";
|
|
3
|
-
import Selectors from "../../../utils/js/dom/selectors";
|
|
4
|
-
import { Manipulator } from "../../../utils/js/dom/manipulator";
|
|
5
|
-
|
|
6
|
-
class VGFilesTemplateRender {
|
|
7
|
-
constructor(vgFilesInstance, element, params = {}) {
|
|
8
|
-
this.module = vgFilesInstance;
|
|
9
|
-
this.element = isElement(element) ? element : null;
|
|
10
|
-
|
|
11
|
-
if (!this.element) {
|
|
12
|
-
console.error('Invalid element provided:', element);
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
this._params = new Params(params, element).get();
|
|
17
|
-
this._nodes = {
|
|
18
|
-
info: this.module._nodes.info,
|
|
19
|
-
drop: this.module._nodes.drop
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
this.bufferTemplate = '';
|
|
23
|
-
this.parsedFiles = [];
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
init() {
|
|
27
|
-
const $targetNode = this._nodes.info || this._nodes.drop;
|
|
28
|
-
if (!$targetNode) return false;
|
|
29
|
-
|
|
30
|
-
const area = this._nodes.info ? 'info' : 'drop';
|
|
31
|
-
return this._nativeRenderFiles(area, $targetNode);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
_nativeRenderFiles(area, $node) {
|
|
35
|
-
const $list = Selectors.find(`.vg-files-${area}--list`, $node);
|
|
36
|
-
if (!$list) return false;
|
|
37
|
-
|
|
38
|
-
const $items = Array.from($list.children).filter(li => li.tagName === 'LI');
|
|
39
|
-
if ($items.length === 0) return false;
|
|
40
|
-
|
|
41
|
-
this._setTemplateInBuffer($items);
|
|
42
|
-
if (!this.bufferTemplate) return false;
|
|
43
|
-
|
|
44
|
-
this.parsedFiles = $items
|
|
45
|
-
.map(li => {
|
|
46
|
-
const rawData = Manipulator.get(li, 'data-file');
|
|
47
|
-
if (!rawData) return null;
|
|
48
|
-
|
|
49
|
-
return this._parseDataFile(rawData);
|
|
50
|
-
})
|
|
51
|
-
.filter(Boolean);
|
|
52
|
-
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
_parseDataFile(rawData) {
|
|
57
|
-
const dataFile = normalizeData(rawData);
|
|
58
|
-
if (!dataFile || typeof dataFile !== 'object' || Array.isArray(dataFile)) return null;
|
|
59
|
-
|
|
60
|
-
const binaryMeta = this._extractBinaryMeta(dataFile);
|
|
61
|
-
const name = this._toStringOrNull(dataFile.name);
|
|
62
|
-
const id = this._toStringOrNull(dataFile.id);
|
|
63
|
-
const src = this._toStringOrNull(dataFile.src);
|
|
64
|
-
const type = this._toStringOrNull(dataFile.type) || binaryMeta.type || 'application/octet-stream';
|
|
65
|
-
const size = this._toNumberOrNull(dataFile.size) ?? binaryMeta.size ?? 0;
|
|
66
|
-
const lastModified = this._toNumberOrNull(dataFile.lastModified ?? dataFile['last-modified']) ?? binaryMeta.lastModified ?? Date.now();
|
|
67
|
-
|
|
68
|
-
const result = {
|
|
69
|
-
id,
|
|
70
|
-
name,
|
|
71
|
-
size,
|
|
72
|
-
type,
|
|
73
|
-
src,
|
|
74
|
-
lastModified
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
if (dataFile.image !== undefined && dataFile.image !== null && dataFile.image !== '') {
|
|
78
|
-
result.image = dataFile.image;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const requiredKeys = ['id', 'name', 'size', 'type', 'src'];
|
|
82
|
-
const isValid = requiredKeys.every((key) => {
|
|
83
|
-
const value = result[key];
|
|
84
|
-
if (key === 'size') return Number.isFinite(value);
|
|
85
|
-
return value !== undefined && value !== null && value !== '';
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
if (!isValid) return null;
|
|
89
|
-
|
|
90
|
-
const customData = {};
|
|
91
|
-
const reserved = new Set(['id', 'name', 'size', 'type', 'src', 'image', 'lastModified', 'last-modified']);
|
|
92
|
-
|
|
93
|
-
Object.entries(dataFile).forEach(([key, value]) => {
|
|
94
|
-
if (reserved.has(key)) return;
|
|
95
|
-
if (value === undefined || value === null || value === '') return;
|
|
96
|
-
customData[key] = value;
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
if (Object.keys(customData).length) {
|
|
100
|
-
result.customData = customData;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return result;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
_extractBinaryMeta(dataFile) {
|
|
107
|
-
const binary = dataFile.file || dataFile.blob || dataFile.originFile || null;
|
|
108
|
-
if (!(binary instanceof Blob)) return {};
|
|
109
|
-
|
|
110
|
-
const size = this._toNumberOrNull(binary.size);
|
|
111
|
-
const type = this._toStringOrNull(binary.type);
|
|
112
|
-
const lastModified = (binary instanceof File)
|
|
113
|
-
? this._toNumberOrNull(binary.lastModified)
|
|
114
|
-
: null;
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
size: size ?? null,
|
|
118
|
-
type: type || null,
|
|
119
|
-
lastModified: lastModified ?? null
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
_toStringOrNull(value) {
|
|
124
|
-
if (value === undefined || value === null) return null;
|
|
125
|
-
const normalized = String(value).trim();
|
|
126
|
-
return normalized ? normalized : null;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
_toNumberOrNull(value) {
|
|
130
|
-
if (value === undefined || value === null || value === '') return null;
|
|
131
|
-
const normalized = Number(value);
|
|
132
|
-
return Number.isFinite(normalized) ? normalized : null;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
_setTemplateInBuffer($items) {
|
|
136
|
-
if (this.bufferTemplate || $items.length === 0) return;
|
|
137
|
-
|
|
138
|
-
const firstItem = $items[0];
|
|
139
|
-
|
|
140
|
-
if (!Manipulator.has(firstItem, 'data-file')) {
|
|
141
|
-
this.bufferTemplate = firstItem.outerHTML;
|
|
142
|
-
firstItem.remove();
|
|
143
|
-
} else {
|
|
144
|
-
this.bufferTemplate = firstItem.outerHTML;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
dispose() {
|
|
149
|
-
this.bufferTemplate = '';
|
|
150
|
-
this.parsedFiles = [];
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
1
|
+
import { isElement, normalizeData } from "../../../utils/js/functions";
|
|
2
|
+
import Params from "../../../utils/js/components/params";
|
|
3
|
+
import Selectors from "../../../utils/js/dom/selectors";
|
|
4
|
+
import { Manipulator } from "../../../utils/js/dom/manipulator";
|
|
5
|
+
|
|
6
|
+
class VGFilesTemplateRender {
|
|
7
|
+
constructor(vgFilesInstance, element, params = {}) {
|
|
8
|
+
this.module = vgFilesInstance;
|
|
9
|
+
this.element = isElement(element) ? element : null;
|
|
10
|
+
|
|
11
|
+
if (!this.element) {
|
|
12
|
+
console.error('Invalid element provided:', element);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
this._params = new Params(params, element).get();
|
|
17
|
+
this._nodes = {
|
|
18
|
+
info: this.module._nodes.info,
|
|
19
|
+
drop: this.module._nodes.drop
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
this.bufferTemplate = '';
|
|
23
|
+
this.parsedFiles = [];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
init() {
|
|
27
|
+
const $targetNode = this._nodes.info || this._nodes.drop;
|
|
28
|
+
if (!$targetNode) return false;
|
|
29
|
+
|
|
30
|
+
const area = this._nodes.info ? 'info' : 'drop';
|
|
31
|
+
return this._nativeRenderFiles(area, $targetNode);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
_nativeRenderFiles(area, $node) {
|
|
35
|
+
const $list = Selectors.find(`.vg-files-${area}--list`, $node);
|
|
36
|
+
if (!$list) return false;
|
|
37
|
+
|
|
38
|
+
const $items = Array.from($list.children).filter(li => li.tagName === 'LI');
|
|
39
|
+
if ($items.length === 0) return false;
|
|
40
|
+
|
|
41
|
+
this._setTemplateInBuffer($items);
|
|
42
|
+
if (!this.bufferTemplate) return false;
|
|
43
|
+
|
|
44
|
+
this.parsedFiles = $items
|
|
45
|
+
.map(li => {
|
|
46
|
+
const rawData = Manipulator.get(li, 'data-file');
|
|
47
|
+
if (!rawData) return null;
|
|
48
|
+
|
|
49
|
+
return this._parseDataFile(rawData);
|
|
50
|
+
})
|
|
51
|
+
.filter(Boolean);
|
|
52
|
+
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
_parseDataFile(rawData) {
|
|
57
|
+
const dataFile = normalizeData(rawData);
|
|
58
|
+
if (!dataFile || typeof dataFile !== 'object' || Array.isArray(dataFile)) return null;
|
|
59
|
+
|
|
60
|
+
const binaryMeta = this._extractBinaryMeta(dataFile);
|
|
61
|
+
const name = this._toStringOrNull(dataFile.name);
|
|
62
|
+
const id = this._toStringOrNull(dataFile.id);
|
|
63
|
+
const src = this._toStringOrNull(dataFile.src);
|
|
64
|
+
const type = this._toStringOrNull(dataFile.type) || binaryMeta.type || 'application/octet-stream';
|
|
65
|
+
const size = this._toNumberOrNull(dataFile.size) ?? binaryMeta.size ?? 0;
|
|
66
|
+
const lastModified = this._toNumberOrNull(dataFile.lastModified ?? dataFile['last-modified']) ?? binaryMeta.lastModified ?? Date.now();
|
|
67
|
+
|
|
68
|
+
const result = {
|
|
69
|
+
id,
|
|
70
|
+
name,
|
|
71
|
+
size,
|
|
72
|
+
type,
|
|
73
|
+
src,
|
|
74
|
+
lastModified
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
if (dataFile.image !== undefined && dataFile.image !== null && dataFile.image !== '') {
|
|
78
|
+
result.image = dataFile.image;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const requiredKeys = ['id', 'name', 'size', 'type', 'src'];
|
|
82
|
+
const isValid = requiredKeys.every((key) => {
|
|
83
|
+
const value = result[key];
|
|
84
|
+
if (key === 'size') return Number.isFinite(value);
|
|
85
|
+
return value !== undefined && value !== null && value !== '';
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (!isValid) return null;
|
|
89
|
+
|
|
90
|
+
const customData = {};
|
|
91
|
+
const reserved = new Set(['id', 'name', 'size', 'type', 'src', 'image', 'lastModified', 'last-modified']);
|
|
92
|
+
|
|
93
|
+
Object.entries(dataFile).forEach(([key, value]) => {
|
|
94
|
+
if (reserved.has(key)) return;
|
|
95
|
+
if (value === undefined || value === null || value === '') return;
|
|
96
|
+
customData[key] = value;
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
if (Object.keys(customData).length) {
|
|
100
|
+
result.customData = customData;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
_extractBinaryMeta(dataFile) {
|
|
107
|
+
const binary = dataFile.file || dataFile.blob || dataFile.originFile || null;
|
|
108
|
+
if (!(binary instanceof Blob)) return {};
|
|
109
|
+
|
|
110
|
+
const size = this._toNumberOrNull(binary.size);
|
|
111
|
+
const type = this._toStringOrNull(binary.type);
|
|
112
|
+
const lastModified = (binary instanceof File)
|
|
113
|
+
? this._toNumberOrNull(binary.lastModified)
|
|
114
|
+
: null;
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
size: size ?? null,
|
|
118
|
+
type: type || null,
|
|
119
|
+
lastModified: lastModified ?? null
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
_toStringOrNull(value) {
|
|
124
|
+
if (value === undefined || value === null) return null;
|
|
125
|
+
const normalized = String(value).trim();
|
|
126
|
+
return normalized ? normalized : null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
_toNumberOrNull(value) {
|
|
130
|
+
if (value === undefined || value === null || value === '') return null;
|
|
131
|
+
const normalized = Number(value);
|
|
132
|
+
return Number.isFinite(normalized) ? normalized : null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
_setTemplateInBuffer($items) {
|
|
136
|
+
if (this.bufferTemplate || $items.length === 0) return;
|
|
137
|
+
|
|
138
|
+
const firstItem = $items[0];
|
|
139
|
+
|
|
140
|
+
if (!Manipulator.has(firstItem, 'data-file')) {
|
|
141
|
+
this.bufferTemplate = firstItem.outerHTML;
|
|
142
|
+
firstItem.remove();
|
|
143
|
+
} else {
|
|
144
|
+
this.bufferTemplate = firstItem.outerHTML;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
dispose() {
|
|
149
|
+
this.bufferTemplate = '';
|
|
150
|
+
this.parsedFiles = [];
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
154
|
export default VGFilesTemplateRender;
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Описание: управляет сортировкой уже загруженных файлов VGFiles.
|
|
3
|
-
* Возможности: меняет порядок элементов, сохраняет ID на сервере и маркирует внутренний drag для защиты dropzone.
|
|
4
|
-
*/
|
|
5
|
-
import Selectors from "../../../utils/js/dom/selectors";
|
|
6
|
-
import {isElement, normalizeData} from "../../../utils/js/functions";
|
|
7
|
-
import Ajax from "../../../utils/js/components/ajax";
|
|
8
|
-
import VGToast from "../../vgtoast";
|
|
9
|
-
|
|
10
|
-
export const VG_FILES_SORTABLE_DATA_TYPE = 'application/x-vg-files-sortable';
|
|
11
|
-
|
|
12
|
-
let isSortableDragActive = false;
|
|
13
|
-
let sortableDragClearTimer = null;
|
|
14
|
-
|
|
15
|
-
export function isVGFilesSortableDragActive() {
|
|
16
|
-
return isSortableDragActive;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function markSortableDragActive() {
|
|
20
|
-
if (sortableDragClearTimer) {
|
|
21
|
-
clearTimeout(sortableDragClearTimer);
|
|
22
|
-
sortableDragClearTimer = null;
|
|
23
|
-
}
|
|
24
|
-
isSortableDragActive = true;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function scheduleSortableDragClear() {
|
|
28
|
-
if (sortableDragClearTimer) clearTimeout(sortableDragClearTimer);
|
|
29
|
-
sortableDragClearTimer = setTimeout(() => {
|
|
30
|
-
isSortableDragActive = false;
|
|
31
|
-
sortableDragClearTimer = null;
|
|
32
|
-
}, 0);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
class VGFilesSortable {
|
|
1
|
+
/**
|
|
2
|
+
* Описание: управляет сортировкой уже загруженных файлов VGFiles.
|
|
3
|
+
* Возможности: меняет порядок элементов, сохраняет ID на сервере и маркирует внутренний drag для защиты dropzone.
|
|
4
|
+
*/
|
|
5
|
+
import Selectors from "../../../utils/js/dom/selectors";
|
|
6
|
+
import {isElement, normalizeData} from "../../../utils/js/functions";
|
|
7
|
+
import Ajax from "../../../utils/js/components/ajax";
|
|
8
|
+
import VGToast from "../../vgtoast";
|
|
9
|
+
|
|
10
|
+
export const VG_FILES_SORTABLE_DATA_TYPE = 'application/x-vg-files-sortable';
|
|
11
|
+
|
|
12
|
+
let isSortableDragActive = false;
|
|
13
|
+
let sortableDragClearTimer = null;
|
|
14
|
+
|
|
15
|
+
export function isVGFilesSortableDragActive() {
|
|
16
|
+
return isSortableDragActive;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function markSortableDragActive() {
|
|
20
|
+
if (sortableDragClearTimer) {
|
|
21
|
+
clearTimeout(sortableDragClearTimer);
|
|
22
|
+
sortableDragClearTimer = null;
|
|
23
|
+
}
|
|
24
|
+
isSortableDragActive = true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function scheduleSortableDragClear() {
|
|
28
|
+
if (sortableDragClearTimer) clearTimeout(sortableDragClearTimer);
|
|
29
|
+
sortableDragClearTimer = setTimeout(() => {
|
|
30
|
+
isSortableDragActive = false;
|
|
31
|
+
sortableDragClearTimer = null;
|
|
32
|
+
}, 0);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
class VGFilesSortable {
|
|
36
36
|
constructor(vgFilesInstance, options = {}) {
|
|
37
37
|
this._vg = vgFilesInstance;
|
|
38
38
|
this._params = {
|
|
@@ -104,12 +104,12 @@ class VGFilesSortable {
|
|
|
104
104
|
const item = e.target.closest(this._params.itemSelector) || e.target.closest('li');
|
|
105
105
|
if (!item) return;
|
|
106
106
|
|
|
107
|
-
this._draggedItem = item;
|
|
108
|
-
markSortableDragActive();
|
|
109
|
-
|
|
110
|
-
e.dataTransfer.effectAllowed = 'move';
|
|
111
|
-
e.dataTransfer.setData(VG_FILES_SORTABLE_DATA_TYPE, '1');
|
|
112
|
-
e.dataTransfer.setData('text/plain', 'vgsortable');
|
|
107
|
+
this._draggedItem = item;
|
|
108
|
+
markSortableDragActive();
|
|
109
|
+
|
|
110
|
+
e.dataTransfer.effectAllowed = 'move';
|
|
111
|
+
e.dataTransfer.setData(VG_FILES_SORTABLE_DATA_TYPE, '1');
|
|
112
|
+
e.dataTransfer.setData('text/plain', 'vgsortable');
|
|
113
113
|
|
|
114
114
|
item.classList.add('dragging');
|
|
115
115
|
requestAnimationFrame(() => item.classList.add('dragging-transparent'));
|
|
@@ -118,11 +118,11 @@ class VGFilesSortable {
|
|
|
118
118
|
_onDragEnd(e) {
|
|
119
119
|
if (this._draggedItem) {
|
|
120
120
|
this._draggedItem.classList.remove('dragging', 'dragging-transparent');
|
|
121
|
-
this._draggedItem = null;
|
|
122
|
-
this._saveOrder();
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
scheduleSortableDragClear();
|
|
121
|
+
this._draggedItem = null;
|
|
122
|
+
this._saveOrder();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
scheduleSortableDragClear();
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
_onDragOver(e) {
|
|
@@ -175,15 +175,15 @@ class VGFilesSortable {
|
|
|
175
175
|
}).filter(id => id !== null);
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
destroy() {
|
|
178
|
+
destroy() {
|
|
179
179
|
this._list.removeEventListener('dragstart', this._boundOnDragStart);
|
|
180
180
|
this._list.removeEventListener('dragend', this._boundOnDragEnd);
|
|
181
181
|
this._list.removeEventListener('dragover', this._boundOnDragOver);
|
|
182
182
|
this._list.removeEventListener('drop', this._boundOnDrop);
|
|
183
183
|
|
|
184
|
-
this._draggedItem = null;
|
|
185
|
-
scheduleSortableDragClear();
|
|
186
|
-
}
|
|
187
|
-
}
|
|
184
|
+
this._draggedItem = null;
|
|
185
|
+
scheduleSortableDragClear();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
188
|
|
|
189
|
-
export default VGFilesSortable
|
|
189
|
+
export default VGFilesSortable
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Описание: основной класс выбора, отображения и AJAX-загрузки файлов VGFiles.
|
|
3
|
-
* Возможности: управляет списками и dropzone, прогрессом, кастомными действиями, удалением, повторной загрузкой и сортировкой.
|
|
3
|
+
* Возможности: управляет списками и dropzone, прогрессом, кастомными действиями, удалением, повторной загрузкой и сортировкой.
|
|
4
4
|
*/
|
|
5
5
|
import VGFilesBase from "./base";
|
|
6
6
|
import FileUploader from "./loader";
|
|
@@ -47,11 +47,11 @@ class VGFiles extends VGFilesBase {
|
|
|
47
47
|
prepend: true,
|
|
48
48
|
replace: true,
|
|
49
49
|
rename: false,
|
|
50
|
-
smartdrop: false,
|
|
51
|
-
customButtons: {
|
|
52
|
-
hideOnUploadState: true
|
|
53
|
-
},
|
|
54
|
-
uploads: {
|
|
50
|
+
smartdrop: false,
|
|
51
|
+
customButtons: {
|
|
52
|
+
hideOnUploadState: true
|
|
53
|
+
},
|
|
54
|
+
uploads: {
|
|
55
55
|
mode: 'sequential',
|
|
56
56
|
route: '',
|
|
57
57
|
maxParallel: 3,
|
|
@@ -273,11 +273,11 @@ class VGFiles extends VGFilesBase {
|
|
|
273
273
|
this._failingUploadedKeys.clear();
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
-
const notUploadedFiles = files.filter(f =>
|
|
277
|
-
this._isFileValid(f) && !this._uploadedKeys.has(this._getFileKey(f))
|
|
278
|
-
);
|
|
279
|
-
this._setStatItem('failing', this._getFailingCount());
|
|
280
|
-
if (!notUploadedFiles.length) return;
|
|
276
|
+
const notUploadedFiles = files.filter(f =>
|
|
277
|
+
this._isFileValid(f) && !this._uploadedKeys.has(this._getFileKey(f))
|
|
278
|
+
);
|
|
279
|
+
this._setStatItem('failing', this._getFailingCount());
|
|
280
|
+
if (!notUploadedFiles.length) return;
|
|
281
281
|
|
|
282
282
|
if (!this._uploader || this._uploader.isIdle()) {
|
|
283
283
|
this._uploader = new FileUploader({
|
|
@@ -484,7 +484,7 @@ class VGFiles extends VGFilesBase {
|
|
|
484
484
|
Classes.remove($item, CLASS_NAME_PENDING);
|
|
485
485
|
Classes.replace($item, CLASS_NAME_LOADING, CLASS_NAME_FAILING);
|
|
486
486
|
|
|
487
|
-
this._setStatItem('failing', this._getFailingCount());
|
|
487
|
+
this._setStatItem('failing', this._getFailingCount());
|
|
488
488
|
this._setStatItem('pending', this._pendingUploadedKeys.size);
|
|
489
489
|
|
|
490
490
|
const button = this._getButtonElement(file);
|
|
@@ -512,7 +512,7 @@ class VGFiles extends VGFilesBase {
|
|
|
512
512
|
this._triggerEvent('upload.allComplete');
|
|
513
513
|
this._updateStat(false);
|
|
514
514
|
|
|
515
|
-
if (!this._getFailingCount()) {
|
|
515
|
+
if (!this._getFailingCount()) {
|
|
516
516
|
if (this._params.sortable?.enabled && this._params.sortable.route) {
|
|
517
517
|
import('./sortable.js').then(module => {
|
|
518
518
|
if (this._sortable && typeof this._sortable.destroy === 'function') {
|
|
@@ -528,7 +528,7 @@ class VGFiles extends VGFilesBase {
|
|
|
528
528
|
|
|
529
529
|
const payload = {
|
|
530
530
|
uploaded: this._uploadedKeys.size,
|
|
531
|
-
failed: this._getFailingCount(),
|
|
531
|
+
failed: this._getFailingCount(),
|
|
532
532
|
total: this._files.length
|
|
533
533
|
};
|
|
534
534
|
|
|
@@ -696,13 +696,13 @@ class VGFiles extends VGFilesBase {
|
|
|
696
696
|
};
|
|
697
697
|
|
|
698
698
|
const fileToRemove = this._files.find(f => f.name === name && f.size === size);
|
|
699
|
-
if (fileToRemove) {
|
|
700
|
-
const key = this._getFileKey(fileToRemove);
|
|
701
|
-
this._uploadedKeys.delete(key);
|
|
702
|
-
this._pendingUploadedKeys.delete(key);
|
|
703
|
-
this._failingUploadedKeys.delete(key);
|
|
704
|
-
this._forgetFileValidation(fileToRemove);
|
|
705
|
-
}
|
|
699
|
+
if (fileToRemove) {
|
|
700
|
+
const key = this._getFileKey(fileToRemove);
|
|
701
|
+
this._uploadedKeys.delete(key);
|
|
702
|
+
this._pendingUploadedKeys.delete(key);
|
|
703
|
+
this._failingUploadedKeys.delete(key);
|
|
704
|
+
this._forgetFileValidation(fileToRemove);
|
|
705
|
+
}
|
|
706
706
|
|
|
707
707
|
this._getItemElement().forEach(el => {
|
|
708
708
|
const btn = Selectors.find('button', el);
|
|
@@ -795,7 +795,7 @@ class VGFiles extends VGFilesBase {
|
|
|
795
795
|
_updateStatsAfterRemove() {
|
|
796
796
|
this._setStatItem('completed', this._uploadedKeys.size);
|
|
797
797
|
this._setStatItem('pending', this._pendingUploadedKeys.size);
|
|
798
|
-
this._setStatItem('failing', this._getFailingCount());
|
|
798
|
+
this._setStatItem('failing', this._getFailingCount());
|
|
799
799
|
this._updateStat();
|
|
800
800
|
}
|
|
801
801
|
|
|
@@ -901,35 +901,35 @@ class VGFiles extends VGFilesBase {
|
|
|
901
901
|
if ($value) $value.innerHTML = count;
|
|
902
902
|
}
|
|
903
903
|
|
|
904
|
-
_renderUIStatusDropInfoAjax(files) {
|
|
905
|
-
if (!this._params.ajax) return;
|
|
906
|
-
|
|
907
|
-
files.forEach(file => {
|
|
904
|
+
_renderUIStatusDropInfoAjax(files) {
|
|
905
|
+
if (!this._params.ajax) return;
|
|
906
|
+
|
|
907
|
+
files.forEach(file => {
|
|
908
908
|
const $item = this._getItemElement(file);
|
|
909
909
|
if (!$item) return;
|
|
910
910
|
|
|
911
|
-
const key = this._getFileKey(file);
|
|
912
|
-
if (!this._isFileValid(file)) {
|
|
913
|
-
Classes.remove($item, CLASS_NAME_PENDING);
|
|
914
|
-
Classes.add($item, CLASS_NAME_FAILING);
|
|
915
|
-
} else if (this._uploadedKeys.has(key)) {
|
|
911
|
+
const key = this._getFileKey(file);
|
|
912
|
+
if (!this._isFileValid(file)) {
|
|
913
|
+
Classes.remove($item, CLASS_NAME_PENDING);
|
|
914
|
+
Classes.add($item, CLASS_NAME_FAILING);
|
|
915
|
+
} else if (this._uploadedKeys.has(key)) {
|
|
916
916
|
Classes.replace($item, CLASS_NAME_PENDING, CLASS_NAME_COMPLETED);
|
|
917
917
|
Classes.add($item, CLASS_NAME_LOADED);
|
|
918
918
|
} else if (this._failingUploadedKeys.has(key)) {
|
|
919
919
|
Classes.replace($item, CLASS_NAME_PENDING, CLASS_NAME_FAILING);
|
|
920
920
|
} else {
|
|
921
|
-
Classes.add($item, CLASS_NAME_PENDING);
|
|
922
|
-
}
|
|
923
|
-
});
|
|
924
|
-
|
|
925
|
-
this._setStatItem('failing', this._getFailingCount());
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
_getFailingCount() {
|
|
929
|
-
const keys = new Set(this._failingUploadedKeys);
|
|
930
|
-
this._validationErrorsByKey.forEach((errors, key) => keys.add(key));
|
|
931
|
-
return keys.size;
|
|
932
|
-
}
|
|
921
|
+
Classes.add($item, CLASS_NAME_PENDING);
|
|
922
|
+
}
|
|
923
|
+
});
|
|
924
|
+
|
|
925
|
+
this._setStatItem('failing', this._getFailingCount());
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
_getFailingCount() {
|
|
929
|
+
const keys = new Set(this._failingUploadedKeys);
|
|
930
|
+
this._validationErrorsByKey.forEach((errors, key) => keys.add(key));
|
|
931
|
+
return keys.size;
|
|
932
|
+
}
|
|
933
933
|
|
|
934
934
|
_triggerCallback(name, data) {
|
|
935
935
|
const cb = this._params.callbacks?.[name];
|