@webhandle/tree-file-browser 1.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/README.md +144 -0
- package/client-lib/base-image-name.mjs +41 -0
- package/client-lib/data-to-image.mjs +45 -0
- package/client-lib/dynamic-load.mjs +21 -0
- package/client-lib/file-select-dialog.mjs +70 -0
- package/client-lib/form-answer-dialog.mjs +65 -0
- package/client-lib/format-bytes.mjs +10 -0
- package/client-lib/get-extension-from-mime.mjs +17 -0
- package/client-lib/get-file-image-stats.mjs +17 -0
- package/client-lib/get-image-stats.mjs +11 -0
- package/client-lib/image-browser-view-methods/create-directory.mjs +23 -0
- package/client-lib/image-browser-view-methods/delete.mjs +100 -0
- package/client-lib/image-browser-view-methods/drag-and-drop.mjs +57 -0
- package/client-lib/image-browser-view-methods/file-obj-manipulation.mjs +190 -0
- package/client-lib/image-browser-view-methods/sink.mjs +20 -0
- package/client-lib/image-browser-view-methods/upload.mjs +159 -0
- package/client-lib/image-browser-view-methods/utils.mjs +108 -0
- package/client-lib/image-browser-view-methods/view-interactions.mjs +96 -0
- package/client-lib/image-browser-view.mjs +227 -0
- package/client-lib/image-resize.mjs +32 -0
- package/client-lib/info-dialog.mjs +36 -0
- package/client-lib/load-styles.mjs +14 -0
- package/client-lib/make-image-set.mjs +75 -0
- package/client-lib/name-parts.mjs +24 -0
- package/client-lib/styles-loaded.mjs +18 -0
- package/less/components.less +357 -0
- package/package.json +80 -0
- package/public/tree-file-browser/resources/css/tree-browser.css +394 -0
- package/public/tree-file-browser/resources/css/tree-browser.css.map +1 -0
- package/public/tree-file-browser/resources/js/tree-file-browser.js +2 -0
- package/public/tree-file-browser/resources/js/tree-file-browser.js.map +1 -0
- package/server-lib/initialize-tree-browser-resources.cjs +17 -0
- package/server-lib/initialize-tree-browser-resources.mjs +15 -0
- package/views/load-browser-views.js +13 -0
- package/views/webhandle-tree-image-browser/extension-pill.tri +1 -0
- package/views/webhandle-tree-image-browser/guilded-file-upload-form.tri +11 -0
- package/views/webhandle-tree-image-browser/guilded-image-upload-form.tri +33 -0
- package/views/webhandle-tree-image-browser/image-browser-frame.tri +122 -0
- package/views/webhandle-tree-image-browser/variant-choice-box.tri +25 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import condense from '@dankolz/webp-detection/lib/condense-image-variants.js'
|
|
2
|
+
|
|
3
|
+
export function createVariantValues(info) {
|
|
4
|
+
let variants = condense(info.children)
|
|
5
|
+
let variantValues = Object.values(variants)
|
|
6
|
+
|
|
7
|
+
let used = []
|
|
8
|
+
for (let variant of variantValues) {
|
|
9
|
+
used.push(...this._getAssociatedRealFiles(variant).map(variant => variant.name))
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let remainingChildren = info.children.filter(item => {
|
|
13
|
+
return !used.includes(item.name)
|
|
14
|
+
})
|
|
15
|
+
.filter(item => !item.directory)
|
|
16
|
+
|
|
17
|
+
// Add thumbnails
|
|
18
|
+
for (let child of variantValues) {
|
|
19
|
+
child.thumbnailIcon = 'image'
|
|
20
|
+
if (child.preview) {
|
|
21
|
+
child.thumbnail = this._createAccessUrl(child.preview.file)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!this.imagesOnly) {
|
|
26
|
+
for (let file of remainingChildren) {
|
|
27
|
+
let info = {
|
|
28
|
+
file: file
|
|
29
|
+
, thumbnailIcon: 'description'
|
|
30
|
+
}
|
|
31
|
+
let name = file.name
|
|
32
|
+
info.ext = name.substring(name.lastIndexOf('.') + 1)
|
|
33
|
+
info.baseName = name.substring(0, name.lastIndexOf('.'))
|
|
34
|
+
variantValues.push(info)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
// Determine extensions
|
|
40
|
+
for (let item of variantValues) {
|
|
41
|
+
item.extensions = this._determineExtensions(item)
|
|
42
|
+
item.sizes = this._determineSizes(item)
|
|
43
|
+
if (item.sizes[0] == item.sizes[1]) {
|
|
44
|
+
item.size = this._formatBytes(item.sizes[0])
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
item.size = this._formatBytes(item.sizes[0]) + ' - ' + this._formatBytes(item.sizes[1])
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
variantValues.sort(this._compareVariants)
|
|
52
|
+
return variantValues
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function _getFilesFromEvent(evt) {
|
|
56
|
+
let files = []
|
|
57
|
+
|
|
58
|
+
// items is the new interface we should use if that's available
|
|
59
|
+
if (evt.dataTransfer.items) {
|
|
60
|
+
let foundItems = [];
|
|
61
|
+
[...evt.dataTransfer.items].forEach((item, i) => {
|
|
62
|
+
foundItems.push(item)
|
|
63
|
+
})
|
|
64
|
+
for (let item of foundItems) {
|
|
65
|
+
if (item.kind === "file") {
|
|
66
|
+
if (item.webkitGetAsEntry) {
|
|
67
|
+
let entry = item.webkitGetAsEntry()
|
|
68
|
+
if (entry) {
|
|
69
|
+
// if there's no entry, it's probably not a file, so we'll just ignore
|
|
70
|
+
if (entry.isDirectory) {
|
|
71
|
+
continue
|
|
72
|
+
|
|
73
|
+
// Evenually we'll want to handle directories too, but for now we'll just go
|
|
74
|
+
// on with the other items
|
|
75
|
+
|
|
76
|
+
// var dirReader = entry.createReader()
|
|
77
|
+
// dirReader.readEntries(function (entries) {
|
|
78
|
+
// console.log(entries)
|
|
79
|
+
// })
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
files.push(item.getAsFile())
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
files.push(item.getAsFile())
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else if (item instanceof File) {
|
|
92
|
+
// Maybe from a file input element
|
|
93
|
+
files.push(item)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
[...evt.dataTransfer.files].forEach((file, i) => {
|
|
98
|
+
files.push(file)
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
return files
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function _getAssociatedRealFiles(variant) {
|
|
105
|
+
let files = []
|
|
106
|
+
if (variant.variants) {
|
|
107
|
+
files.push(...variant.variants.map(variant => variant.file))
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
files.push(variant.file)
|
|
111
|
+
}
|
|
112
|
+
if (variant.definitionFile) {
|
|
113
|
+
files.push(variant.definitionFile)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return files
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function _createAccessUrl(file) {
|
|
120
|
+
return file.accessUrl
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
export function getSelectedFiles() {
|
|
125
|
+
let result = {
|
|
126
|
+
boxes: []
|
|
127
|
+
, variants: []
|
|
128
|
+
, files: []
|
|
129
|
+
, names: []
|
|
130
|
+
}
|
|
131
|
+
let currentSelected = this.el.querySelectorAll('.choice-boxes .variant-choice-box.selected')
|
|
132
|
+
if (currentSelected.length > 0) {
|
|
133
|
+
for (let sel of currentSelected) {
|
|
134
|
+
result.boxes.push(sel)
|
|
135
|
+
result.variants.push(sel.variant)
|
|
136
|
+
result.files.push(...this._getAssociatedRealFiles(sel.variant))
|
|
137
|
+
}
|
|
138
|
+
let names = result.files.map(file => file.name)
|
|
139
|
+
result.names.push(...names)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return result
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function _transformRelativeUrlToPublic(url) {
|
|
146
|
+
if(url.startsWith('/') == false) {
|
|
147
|
+
url = '/' + url
|
|
148
|
+
}
|
|
149
|
+
return url
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export async function getSelectedUrl(selectedFiles) {
|
|
153
|
+
if(!selectedFiles) {
|
|
154
|
+
selectedFiles = this.getSelectedFiles()
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if(selectedFiles.variants.length == 0) {
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
let variant = selectedFiles.variants[0]
|
|
162
|
+
let chosen
|
|
163
|
+
if(variant.primary) {
|
|
164
|
+
chosen = variant.primary.file
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
chosen = variant.file
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
let base = this._transformRelativeUrlToPublic(chosen.relPath)
|
|
171
|
+
|
|
172
|
+
if(variant.definitionFile) {
|
|
173
|
+
let defData = await this.sink.read(variant.definitionFile.relPath)
|
|
174
|
+
try {
|
|
175
|
+
let data = JSON.parse(defData)
|
|
176
|
+
let sizes = data.displaySize.split('x')
|
|
177
|
+
base += `#format=webp2x&width=${sizes[0]}&height=${sizes[1]}`
|
|
178
|
+
|
|
179
|
+
if(data.altText) {
|
|
180
|
+
base += '&alt=' + encodeURIComponent(data.altText)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch(e) {
|
|
184
|
+
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return base
|
|
189
|
+
|
|
190
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
export async function _uploadData(name, data) {
|
|
3
|
+
let path = this.currentNode.file.relPath + '/' + this.sanitizeFileName(name)
|
|
4
|
+
await this.sink.write(path, data)
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export async function findDirectories() {
|
|
8
|
+
return new Promise((resolve, reject) => {
|
|
9
|
+
let results = []
|
|
10
|
+
let events = this.sink.find({
|
|
11
|
+
file: false
|
|
12
|
+
})
|
|
13
|
+
events.on('data', (item) => {
|
|
14
|
+
results.push(item)
|
|
15
|
+
})
|
|
16
|
+
events.on('done', () => {
|
|
17
|
+
resolve(results)
|
|
18
|
+
})
|
|
19
|
+
})
|
|
20
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { FormAnswerDialog } from '../form-answer-dialog.mjs'
|
|
2
|
+
import baseImageName from '../base-image-name.mjs'
|
|
3
|
+
import makeImageSet from '../make-image-set.mjs'
|
|
4
|
+
import nameParts from '../name-parts.mjs'
|
|
5
|
+
import getFileImageStats from '../get-file-image-stats.mjs'
|
|
6
|
+
import { guidedImageUploadForm, guidedFileUploadForm } from '../../views/load-browser-views.js'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export async function _uploadGuidedImageFile(file) {
|
|
10
|
+
let baseFileName = baseImageName(file)
|
|
11
|
+
let stats = await getFileImageStats(file)
|
|
12
|
+
|
|
13
|
+
let data = {
|
|
14
|
+
nativeName: file.name
|
|
15
|
+
, name: baseFileName
|
|
16
|
+
, outputFormat: file.type
|
|
17
|
+
, stats: stats
|
|
18
|
+
, width: Math.floor(stats.width / 2)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
let dialog = new FormAnswerDialog({
|
|
23
|
+
title: 'Upload File'
|
|
24
|
+
, body: guidedImageUploadForm(data)
|
|
25
|
+
, data: data
|
|
26
|
+
, dialogFrameClass: 'webhandle-file-tree-image-browser'
|
|
27
|
+
})
|
|
28
|
+
let prom = dialog.open()
|
|
29
|
+
let result = await prom
|
|
30
|
+
|
|
31
|
+
if (result) {
|
|
32
|
+
let makeImageData = {
|
|
33
|
+
baseFileName: result.name
|
|
34
|
+
, outputFormat: result.outputFormat
|
|
35
|
+
, singleDensityWidth: parseInt(result.width)
|
|
36
|
+
, altText: result.altText
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let note = this._addPending(file)
|
|
40
|
+
let files = await makeImageSet(file, makeImageData)
|
|
41
|
+
|
|
42
|
+
for (let fileName of Object.keys(files)) {
|
|
43
|
+
await this._uploadData(fileName, files[fileName])
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (note) {
|
|
47
|
+
note.remove()
|
|
48
|
+
}
|
|
49
|
+
return true
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function _uploadGuidedFile(file) {
|
|
54
|
+
let parts = nameParts(file)
|
|
55
|
+
|
|
56
|
+
let data = {
|
|
57
|
+
nativeName: file.name
|
|
58
|
+
, name: parts.join('.')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
let dialog = new FormAnswerDialog({
|
|
63
|
+
title: 'Upload File'
|
|
64
|
+
, body: guidedFileUploadForm(data)
|
|
65
|
+
, data: data
|
|
66
|
+
, dialogFrameClass: 'webhandle-file-tree-image-browser'
|
|
67
|
+
})
|
|
68
|
+
let prom = dialog.open()
|
|
69
|
+
let result = await prom
|
|
70
|
+
|
|
71
|
+
if (result) {
|
|
72
|
+
let note = this._addPending(file)
|
|
73
|
+
|
|
74
|
+
await this._uploadData(result.name, file)
|
|
75
|
+
|
|
76
|
+
if (note) {
|
|
77
|
+
note.remove()
|
|
78
|
+
}
|
|
79
|
+
return true
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function _uploadAutomaticImageFile(file) {
|
|
84
|
+
let note = this._addPending(file)
|
|
85
|
+
let parts = nameParts(file)
|
|
86
|
+
let baseFileName = parts[0]
|
|
87
|
+
|
|
88
|
+
let files = await makeImageSet(file, {
|
|
89
|
+
baseFileName: baseFileName,
|
|
90
|
+
outputFormat: file.type
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
for (let fileName of Object.keys(files)) {
|
|
94
|
+
await this._uploadData(fileName, files[fileName])
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (note) {
|
|
98
|
+
note.remove()
|
|
99
|
+
}
|
|
100
|
+
return true
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export async function uploadFiles(files, { uploadType } = {}) {
|
|
104
|
+
for (let file of files) {
|
|
105
|
+
|
|
106
|
+
let uploaded = false
|
|
107
|
+
if (uploadType === 'guided' && this._isImageFile(file)) {
|
|
108
|
+
uploaded = await this._uploadGuidedImageFile(file)
|
|
109
|
+
}
|
|
110
|
+
else if (uploadType === 'guided') {
|
|
111
|
+
uploaded = await this._uploadGuidedFile(file)
|
|
112
|
+
}
|
|
113
|
+
else if (uploadType === 'automatic' && this._isImageFile(file)) {
|
|
114
|
+
uploaded = await this._uploadAutomaticImageFile(file)
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
let note = this._addPending(file)
|
|
118
|
+
if (uploadType === 'automatic') {
|
|
119
|
+
let parts = nameParts(file)
|
|
120
|
+
await this._uploadData(parts.join('.'), file)
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
await this._uploadData(file.name, file)
|
|
124
|
+
}
|
|
125
|
+
if (note) {
|
|
126
|
+
note.remove()
|
|
127
|
+
}
|
|
128
|
+
uploaded = true
|
|
129
|
+
}
|
|
130
|
+
if (this.eventNotificationPanel && uploaded) {
|
|
131
|
+
this.eventNotificationPanel.addNotification({
|
|
132
|
+
model: {
|
|
133
|
+
status: 'success',
|
|
134
|
+
headline: `uploaded ${file.name}`
|
|
135
|
+
}
|
|
136
|
+
, ttl: 2000
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
this.setCurrentNode(this.currentNode)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
export function _uploadFileButton(evt, selected) {
|
|
145
|
+
this.el.querySelector(this.fileUploadSelector).click()
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export async function _uploadFile(evt, selected) {
|
|
149
|
+
evt.preventDefault()
|
|
150
|
+
let input = this.el.querySelector(this.fileUploadSelector)
|
|
151
|
+
evt.dataTransfer = {
|
|
152
|
+
files: input.files
|
|
153
|
+
}
|
|
154
|
+
let files = await this._getFilesFromEvent(evt)
|
|
155
|
+
if(files.length > 0) {
|
|
156
|
+
this.uploadFiles(files, { uploadType: 'guided' })
|
|
157
|
+
input.value = ''
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
|
|
2
|
+
export function _join(...parts) {
|
|
3
|
+
parts = parts.filter(part => !!part)
|
|
4
|
+
let path = parts.join('/')
|
|
5
|
+
return path
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function _determineParentPath(path) {
|
|
9
|
+
if(!path) {
|
|
10
|
+
return ''
|
|
11
|
+
}
|
|
12
|
+
let parts = path.split('/')
|
|
13
|
+
parts.pop()
|
|
14
|
+
return parts.join('/')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function _fileToKalpaNode(file) {
|
|
18
|
+
let node = {
|
|
19
|
+
id: this.idInd++
|
|
20
|
+
, label: file.name
|
|
21
|
+
, directory: file.directory
|
|
22
|
+
, file: file
|
|
23
|
+
, loaded: false
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let parent = this.nodes[this._determineParentPath(file.relPath)]
|
|
27
|
+
this.nodes[file.relPath] = node
|
|
28
|
+
|
|
29
|
+
if (parent) {
|
|
30
|
+
node.parentId = parent.id
|
|
31
|
+
node.path = file.relPath
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
file.path = node.path
|
|
35
|
+
return node
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function _determineExtensions(variant) {
|
|
39
|
+
let extensions = new Set()
|
|
40
|
+
if (variant.variants) {
|
|
41
|
+
for (let imgVariant of variant.variants) {
|
|
42
|
+
extensions.add(imgVariant.ext)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
extensions.add(variant.ext)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let result = Array.from(extensions).filter(item => !!item)
|
|
50
|
+
result.sort((a, b) => {
|
|
51
|
+
return a.toLowerCase().localeCompare(b.toLowerCase())
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
return result
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function _determineSizes(variant) {
|
|
58
|
+
let min = 2000000000
|
|
59
|
+
let max = 0
|
|
60
|
+
if (variant.variants) {
|
|
61
|
+
for (let imgVariant of variant.variants) {
|
|
62
|
+
let size = imgVariant.file.stat.size
|
|
63
|
+
if (size > max) {
|
|
64
|
+
max = size
|
|
65
|
+
}
|
|
66
|
+
if (size < min) {
|
|
67
|
+
min = size
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
let size = variant.file.stat.size
|
|
73
|
+
if (size > max) {
|
|
74
|
+
max = size
|
|
75
|
+
}
|
|
76
|
+
if (size < min) {
|
|
77
|
+
min = size
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return [min, max]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function _sortFiles(files) {
|
|
84
|
+
files.sort((one, two) => {
|
|
85
|
+
return one.relPath.toLowerCase().localeCompare(two.relPath.toLowerCase())
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
return files
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function _compareVariants(one, two) {
|
|
92
|
+
return one.baseName.toLowerCase().localeCompare(two.baseName.toLowerCase())
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function sanitizeFileName(name) {
|
|
96
|
+
return name.split('/').join('-').split('..').join('-')
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
export function _isImageFile(file) {
|
|
101
|
+
if (!file.type.startsWith('image')) {
|
|
102
|
+
return false
|
|
103
|
+
}
|
|
104
|
+
if (file.type.includes('jpeg') || file.type.includes('png') || file.type.includes('webp')) {
|
|
105
|
+
return true
|
|
106
|
+
}
|
|
107
|
+
return false
|
|
108
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { InfoDialog } from '../info-dialog.mjs'
|
|
2
|
+
|
|
3
|
+
export function changeFilesView(evt, selected) {
|
|
4
|
+
let choiceBoxes = this.el.querySelector('.choice-boxes')
|
|
5
|
+
let classes = [...selected.closest('.view-icons').querySelectorAll('button')].map(button => button.getAttribute('data-show-class'))
|
|
6
|
+
classes.forEach(item => {
|
|
7
|
+
choiceBoxes.classList.remove(item)
|
|
8
|
+
})
|
|
9
|
+
choiceBoxes.classList.add(selected.getAttribute('data-show-class'))
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function applyFilter(evt, selected) {
|
|
13
|
+
setTimeout(() => {
|
|
14
|
+
let value = this.el.querySelector('[name="filter"]').value
|
|
15
|
+
let allVariants = this.el.querySelectorAll('.choice-boxes .variant-choice-box')
|
|
16
|
+
for (let variant of allVariants) {
|
|
17
|
+
variant.classList.remove('hidden')
|
|
18
|
+
if (value) {
|
|
19
|
+
let searchString = variant.variant.baseName + variant.variant.extensions.join()
|
|
20
|
+
if (searchString.indexOf(value) < 0) {
|
|
21
|
+
variant.classList.add('hidden')
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function clearFilter(evt, selected) {
|
|
29
|
+
this.el.querySelector('[name="filter"]').value = ''
|
|
30
|
+
this.applyFilter()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function selectVariant(evt, selected) {
|
|
34
|
+
let currentSelected = this.el.querySelectorAll('.choice-boxes .variant-choice-box.selected')
|
|
35
|
+
if (!evt.ctrlKey && !evt.shiftKey) {
|
|
36
|
+
for (let sel of currentSelected) {
|
|
37
|
+
sel.classList.remove('selected')
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (evt.shiftKey) {
|
|
42
|
+
let cur = selected
|
|
43
|
+
do {
|
|
44
|
+
if (cur.classList.contains('selected')) {
|
|
45
|
+
break
|
|
46
|
+
}
|
|
47
|
+
cur.classList.add('selected')
|
|
48
|
+
cur = cur.previousElementSibling
|
|
49
|
+
}
|
|
50
|
+
while (cur);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
selected.classList.toggle('selected')
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
let sel = this.getSelectedFiles()
|
|
58
|
+
this.emitter.emit('select', {
|
|
59
|
+
type: 'select'
|
|
60
|
+
, selected: sel
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
export function showVariantDetails(evt, selected) {
|
|
67
|
+
let choiceBox = selected.closest('.variant-choice-box')
|
|
68
|
+
let variant = choiceBox.variant
|
|
69
|
+
|
|
70
|
+
let files = this._getAssociatedRealFiles(variant)
|
|
71
|
+
|
|
72
|
+
let content = '<ul>'
|
|
73
|
+
for (let file of files) {
|
|
74
|
+
content += '<li><a target="_blank" href="' + file.accessUrl + '">'
|
|
75
|
+
content += file.name + '</a> - ' + this._formatBytes(file.stat.size)
|
|
76
|
+
content += '</li>'
|
|
77
|
+
}
|
|
78
|
+
content += '</ul>'
|
|
79
|
+
|
|
80
|
+
let dialog = new InfoDialog({
|
|
81
|
+
title: 'File Details: ' + variant.baseName
|
|
82
|
+
, body: content
|
|
83
|
+
, buttons: [
|
|
84
|
+
{
|
|
85
|
+
classes: 'btn btn-primary btn-ok',
|
|
86
|
+
label: 'OK'
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
})
|
|
90
|
+
let prom = dialog.open()
|
|
91
|
+
prom.then(async data => {
|
|
92
|
+
if (data) {
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
}
|