@oat-sa/tao-core-ui 3.23.0 → 3.24.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/dist/figure/FigureStateActive.js +64 -32
- package/dist/image/ImgStateActive/initHelper.js +64 -32
- package/dist/image/ImgStateActive.js +64 -32
- package/dist/previewer.js +1 -1
- package/dist/resourcemgr/assetSearch.js +793 -0
- package/dist/resourcemgr/assetSearchContract.js +477 -0
- package/dist/resourcemgr/css/resourcemgr.css +1137 -97
- package/dist/resourcemgr/css/resourcemgr.css.map +1 -1
- package/dist/resourcemgr/fileBrowser.js +456 -79
- package/dist/resourcemgr/filePreview.js +40 -4
- package/dist/resourcemgr/fileSelector.js +362 -92
- package/dist/resourcemgr.js +309 -57
- package/dist/searchModal/advancedSearch.js +233 -31
- package/package.json +15 -6
- package/src/image/ImgStateActive/initHelper.js +69 -31
- package/src/previewer.js +1 -1
- package/src/resourcemgr/assetSearch.js +847 -0
- package/src/resourcemgr/assetSearchContract.js +489 -0
- package/src/resourcemgr/css/resourcemgr.css +1137 -97
- package/src/resourcemgr/css/resourcemgr.css.map +1 -1
- package/src/resourcemgr/fileBrowser.js +470 -91
- package/src/resourcemgr/filePreview.js +46 -4
- package/src/resourcemgr/fileSelector.js +338 -46
- package/src/resourcemgr/scss/resourcemgr.scss +1351 -88
- package/src/resourcemgr/tpl/advanced-search.tpl +10 -0
- package/src/resourcemgr/tpl/fileSelect.tpl +25 -28
- package/src/resourcemgr/tpl/folder.tpl +4 -1
- package/src/resourcemgr/tpl/layout.tpl +113 -54
- package/src/resourcemgr/tpl/rootFolder.tpl +3 -1
- package/src/resourcemgr.js +289 -47
- package/src/searchModal/advancedSearch.js +242 -31
package/src/resourcemgr.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import $ from 'jquery';
|
|
2
2
|
import _ from 'lodash';
|
|
3
3
|
import Pluginifier from 'core/pluginifier';
|
|
4
|
+
import assetSearch from 'ui/resourcemgr/assetSearch';
|
|
4
5
|
import fileBrowser from 'ui/resourcemgr/fileBrowser';
|
|
5
6
|
import filePreview from 'ui/resourcemgr/filePreview';
|
|
6
7
|
import fileSelector from 'ui/resourcemgr/fileSelector';
|
|
8
|
+
import feedback from 'ui/feedback';
|
|
7
9
|
import layout from 'ui/resourcemgr/tpl/layout';
|
|
10
|
+
import urlUtil from 'util/url';
|
|
11
|
+
import __ from 'i18n';
|
|
8
12
|
import 'ui/modal';
|
|
9
13
|
import 'ui/resourcemgr/css/resourcemgr.css';
|
|
10
14
|
|
|
@@ -15,7 +19,13 @@ var defaults = {
|
|
|
15
19
|
mediaSources: [{ root: 'local', path: '/' }],
|
|
16
20
|
open: true,
|
|
17
21
|
appendContainer: '.tao-scope:first',
|
|
18
|
-
title: ''
|
|
22
|
+
title: '',
|
|
23
|
+
pathParam: 'path',
|
|
24
|
+
// Advanced Search metadata filters (same endpoints as ui/searchModal)
|
|
25
|
+
rootClassUri: 'http://www.tao.lu/Ontologies/TAOMedia.rdf#Media',
|
|
26
|
+
classMappingUrl: urlUtil.route('getWithMapping', 'ClassMetadata', 'tao'),
|
|
27
|
+
statusUrl: urlUtil.route('status', 'AdvancedSearch', 'tao'),
|
|
28
|
+
maxListSize: 5
|
|
19
29
|
};
|
|
20
30
|
|
|
21
31
|
/**
|
|
@@ -34,7 +44,18 @@ var resourceMgr = {
|
|
|
34
44
|
* @constructor
|
|
35
45
|
* @param {Object} options - the plugin options
|
|
36
46
|
* @param {Sring|Boolean} [options.bindEvent = 'click'] - the event that trigger the toggling
|
|
37
|
-
* @param {String} options.
|
|
47
|
+
* @param {String} [options.browseUrl] - folder browse endpoint (legacy alias: options.url)
|
|
48
|
+
* @param {String} [options.url] - legacy alias for browseUrl
|
|
49
|
+
* @param {String} [options.searchUrl] - scoped asset-search endpoint; omit for browse-only
|
|
50
|
+
* @param {Boolean} [options.browseSearchFallback=false] - client filter when searchUrl returns browse-shaped `{ children }`
|
|
51
|
+
* @param {String} [options.initialPath] - folder to open on start (within the media source tree)
|
|
52
|
+
* @param {String} [options.initialSelection] - asset URI to preselect when present in results
|
|
53
|
+
* @param {String} [options.currentAsset] - asset URI/path to resolve to parent folder + selection
|
|
54
|
+
* @param {String} [options.pathParam='path'] - query parameter name for folder/asset path
|
|
55
|
+
* @param {String} [options.rootClassUri=TAOMedia#Media] - Assets class URI for Advanced Search criteria (metadata filters)
|
|
56
|
+
* @param {String} [options.classMappingUrl] - ClassMetadata mapping endpoint for criteria list
|
|
57
|
+
* @param {String} [options.statusUrl] - Advanced Search status endpoint
|
|
58
|
+
* @param {Number} [options.maxListSize=5] - max list values per criterion in filters UI
|
|
38
59
|
* @fires ResourceMgr#create.resourcemgr
|
|
39
60
|
* @returns {jQueryElement} for chaining
|
|
40
61
|
*/
|
|
@@ -43,6 +64,9 @@ var resourceMgr = {
|
|
|
43
64
|
|
|
44
65
|
//get options using default
|
|
45
66
|
options = _.defaults(options, defaults);
|
|
67
|
+
if (!options.browseUrl && options.url) {
|
|
68
|
+
options.browseUrl = options.url;
|
|
69
|
+
}
|
|
46
70
|
|
|
47
71
|
return this.each(function() {
|
|
48
72
|
var $elt = $(this);
|
|
@@ -55,7 +79,10 @@ var resourceMgr = {
|
|
|
55
79
|
//auto bind events configured in options
|
|
56
80
|
_.functions(options).forEach(function(eventName) {
|
|
57
81
|
$elt.on(eventName + '.' + ns, function() {
|
|
58
|
-
|
|
82
|
+
const live = $elt.data(dataNs);
|
|
83
|
+
if (live && typeof live[eventName] === 'function') {
|
|
84
|
+
live[eventName].apply($elt, arguments);
|
|
85
|
+
}
|
|
59
86
|
});
|
|
60
87
|
});
|
|
61
88
|
|
|
@@ -74,56 +101,269 @@ var resourceMgr = {
|
|
|
74
101
|
$target.on('closed.modal', function() {
|
|
75
102
|
$elt.trigger('close.' + ns);
|
|
76
103
|
});
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
|
|
105
|
+
options.contextToken = 1;
|
|
106
|
+
const initToken = options.contextToken;
|
|
107
|
+
$elt.data(dataNs, options);
|
|
108
|
+
|
|
109
|
+
that._resolveCurrentAssetContext(options, initToken).always(function(resolvedOptions) {
|
|
110
|
+
const current = $elt.data(dataNs);
|
|
111
|
+
if (!current) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const ownsOpen = current.contextToken === initToken;
|
|
115
|
+
if (!ownsOpen) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
$elt.data(dataNs, resolvedOptions);
|
|
119
|
+
|
|
120
|
+
that._ensureBrowsersStarted($elt, resolvedOptions).always(function() {
|
|
121
|
+
const latest = $elt.data(dataNs) || resolvedOptions;
|
|
122
|
+
if (!latest._createEventEmitted) {
|
|
123
|
+
latest._createEventEmitted = true;
|
|
124
|
+
$elt.data(dataNs, latest);
|
|
125
|
+
/**
|
|
126
|
+
* The plugin have been created.
|
|
127
|
+
* @event ResourceMgr#create.resourcemgr
|
|
128
|
+
*/
|
|
129
|
+
$elt.trigger('create.' + ns, [latest.$target[0]]);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (ownsOpen && latest.open) {
|
|
133
|
+
that._open($elt);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
} else {
|
|
138
|
+
// Reopen: consumer may pass a new currentAsset (edit/change after create).
|
|
139
|
+
that._reopenWithContext($elt, options);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Merge reopen options, re-resolve currentAsset, re-apply folder/selection, then open.
|
|
146
|
+
* @param {jQuery} $elt
|
|
147
|
+
* @param {Object} incoming - options from the latest .resourcemgr(…) call
|
|
148
|
+
*/
|
|
149
|
+
_reopenWithContext: function($elt, incoming) {
|
|
150
|
+
const that = resourceMgr;
|
|
151
|
+
const stored = $elt.data(dataNs);
|
|
152
|
+
if (!stored) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (Object.prototype.hasOwnProperty.call(incoming, 'currentAsset')) {
|
|
157
|
+
stored.currentAsset = incoming.currentAsset;
|
|
158
|
+
stored.initialPath = null;
|
|
159
|
+
stored.initialSelection = null;
|
|
160
|
+
stored.currentAssetItem = null;
|
|
161
|
+
}
|
|
162
|
+
if (incoming.params && typeof incoming.params === 'object') {
|
|
163
|
+
stored.params = Object.assign({}, stored.params || {}, incoming.params);
|
|
164
|
+
}
|
|
165
|
+
['select', 'open', 'close'].forEach(function(key) {
|
|
166
|
+
if (typeof incoming[key] === 'function') {
|
|
167
|
+
stored[key] = incoming[key];
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
stored.contextToken = (stored.contextToken || 0) + 1;
|
|
172
|
+
const token = stored.contextToken;
|
|
173
|
+
$elt.data(dataNs, stored);
|
|
174
|
+
|
|
175
|
+
that._resolveCurrentAssetContext(stored, token).always(function(resolved) {
|
|
176
|
+
const current = $elt.data(dataNs);
|
|
177
|
+
if (!current || current.contextToken !== token) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
$elt.data(dataNs, resolved);
|
|
181
|
+
that._ensureBrowsersStarted($elt, resolved).always(function() {
|
|
182
|
+
that._applyResolvedContext($elt, resolved);
|
|
183
|
+
that._open($elt);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Notify mounted browser/selector to open parent folder and (re)preselect.
|
|
190
|
+
* @param {jQuery} $elt
|
|
191
|
+
* @param {Object} options
|
|
192
|
+
*/
|
|
193
|
+
_applyResolvedContext: function($elt, options) {
|
|
194
|
+
if (!options || !options.$target) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
options.$target.trigger('applycontext.' + ns, [
|
|
198
|
+
{
|
|
199
|
+
path: options.initialPath || options.path || '/',
|
|
200
|
+
selection: options.initialSelection || null,
|
|
201
|
+
currentAssetItem: options.currentAssetItem || null
|
|
202
|
+
}
|
|
203
|
+
]);
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Resolve currentAsset via browse/search endpoint into initialPath/initialSelection.
|
|
208
|
+
* @param {Object} options
|
|
209
|
+
* @param {number} [expectedToken] - contextToken that must still match before mutating options
|
|
210
|
+
* @returns {Promise}
|
|
211
|
+
*/
|
|
212
|
+
_resolveCurrentAssetContext: function(options, expectedToken) {
|
|
213
|
+
const deferred = $.Deferred();
|
|
214
|
+
const isStale = function() {
|
|
215
|
+
return typeof expectedToken !== 'undefined' && expectedToken !== null && options.contextToken !== expectedToken;
|
|
216
|
+
};
|
|
217
|
+
if (!options.currentAsset || (!options.browseUrl && !options.searchUrl)) {
|
|
218
|
+
deferred.resolve(options);
|
|
219
|
+
return deferred.promise();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const endpoint = options.browseUrl || options.searchUrl;
|
|
223
|
+
const pathParam = options.pathParam || 'path';
|
|
224
|
+
const params = Object.assign({}, options.params || {}, {
|
|
225
|
+
currentAsset: options.currentAsset
|
|
226
|
+
});
|
|
227
|
+
params[pathParam] = options.path || '/';
|
|
228
|
+
|
|
229
|
+
$.ajax({
|
|
230
|
+
url: endpoint,
|
|
231
|
+
method: 'GET',
|
|
232
|
+
dataType: 'json',
|
|
233
|
+
timeout: Number(options.ajaxTimeoutMs) > 0 ? Number(options.ajaxTimeoutMs) : 10000,
|
|
234
|
+
data: params
|
|
235
|
+
})
|
|
236
|
+
.done(function(response) {
|
|
237
|
+
if (isStale()) {
|
|
238
|
+
deferred.resolve(options);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const payload = response && response.data ? response.data : response;
|
|
242
|
+
if (payload && payload.parentPath) {
|
|
243
|
+
options.initialPath = payload.parentPath;
|
|
105
244
|
}
|
|
245
|
+
if (payload && payload.currentAsset && payload.currentAsset.uri) {
|
|
246
|
+
options.initialSelection = payload.currentAsset.uri;
|
|
247
|
+
options.currentAssetItem = payload.currentAsset;
|
|
248
|
+
} else {
|
|
249
|
+
options.initialSelection = null;
|
|
250
|
+
options.currentAssetItem = null;
|
|
251
|
+
}
|
|
252
|
+
deferred.resolve(options);
|
|
253
|
+
})
|
|
254
|
+
.fail(function() {
|
|
255
|
+
if (isStale()) {
|
|
256
|
+
deferred.resolve(options);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
// AC6: keep RM usable without selection; surface recoverable feedback.
|
|
260
|
+
options.initialSelection = null;
|
|
261
|
+
options.currentAssetItem = null;
|
|
262
|
+
if (options.$target && options.$target.length) {
|
|
263
|
+
feedback(options.$target).warning(
|
|
264
|
+
__('Unable to resolve the current asset. You can still browse and select another file.')
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
deferred.resolve(options);
|
|
268
|
+
});
|
|
106
269
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
filePreview(options);
|
|
270
|
+
return deferred.promise();
|
|
271
|
+
},
|
|
110
272
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
273
|
+
/**
|
|
274
|
+
* Start browsers once and resolve when the tree wrapper is mounted.
|
|
275
|
+
* @param {jQuery} $elt
|
|
276
|
+
* @param {Object} options
|
|
277
|
+
* @returns {Promise}
|
|
278
|
+
*/
|
|
279
|
+
_ensureBrowsersStarted: function($elt, options) {
|
|
280
|
+
const stored = $elt.data(dataNs) || options;
|
|
281
|
+
if (stored._browsersStartPromise) {
|
|
282
|
+
return stored._browsersStartPromise;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
stored._browsersStartPromise = this._startBrowsers($elt, stored);
|
|
286
|
+
$elt.data(dataNs, stored);
|
|
287
|
+
return stored._browsersStartPromise;
|
|
288
|
+
},
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Mount file browser / selector / search after options are ready.
|
|
292
|
+
* @param {jQuery} $elt
|
|
293
|
+
* @param {Object} options
|
|
294
|
+
*/
|
|
295
|
+
_startBrowsers: function($elt, options) {
|
|
296
|
+
const $fileBrowser = $('.file-browser .file-browser-wrapper', options.$target);
|
|
297
|
+
|
|
298
|
+
const waitForTreeWrapper = function() {
|
|
299
|
+
const deferred = $.Deferred();
|
|
300
|
+
const isMounted = function() {
|
|
301
|
+
return $fileBrowser.children().length > 0;
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
if (isMounted()) {
|
|
305
|
+
deferred.resolve();
|
|
306
|
+
return deferred.promise();
|
|
307
|
+
}
|
|
116
308
|
|
|
117
|
-
|
|
118
|
-
|
|
309
|
+
let attempts = 200;
|
|
310
|
+
const poll = function() {
|
|
311
|
+
if (isMounted()) {
|
|
312
|
+
deferred.resolve();
|
|
313
|
+
return;
|
|
119
314
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
315
|
+
attempts -= 1;
|
|
316
|
+
if (attempts <= 0) {
|
|
317
|
+
deferred.reject();
|
|
318
|
+
return;
|
|
124
319
|
}
|
|
320
|
+
window.setTimeout(poll, 50);
|
|
321
|
+
};
|
|
322
|
+
poll();
|
|
323
|
+
return deferred.promise();
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
const finishMount = function() {
|
|
327
|
+
$fileBrowser.find('li.root:last').addClass('active');
|
|
328
|
+
fileSelector(options);
|
|
329
|
+
filePreview(options);
|
|
330
|
+
assetSearch(options);
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
const mountFromSources = function(mediaSources) {
|
|
334
|
+
const sources = mediaSources || defaults.mediaSources;
|
|
335
|
+
for (let i = 0; i < sources.length; i++) {
|
|
336
|
+
options.root = sources[i].root;
|
|
337
|
+
options.path = sources[i].path;
|
|
338
|
+
$fileBrowser.append('<div class="' + options.root + '"><ul class="folders"></ul></div>');
|
|
339
|
+
fileBrowser(options);
|
|
125
340
|
}
|
|
126
|
-
}
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
const afterComponentsMounted = function() {
|
|
344
|
+
finishMount();
|
|
345
|
+
return waitForTreeWrapper();
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
if (options.mediaSourcesUrl) {
|
|
349
|
+
return $.getJSON(options.mediaSourcesUrl).then(
|
|
350
|
+
function(data) {
|
|
351
|
+
mountFromSources(data || defaults.mediaSources);
|
|
352
|
+
return afterComponentsMounted();
|
|
353
|
+
},
|
|
354
|
+
function() {
|
|
355
|
+
mountFromSources(defaults.mediaSources);
|
|
356
|
+
return afterComponentsMounted();
|
|
357
|
+
}
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (options.path && options.root) {
|
|
362
|
+
$fileBrowser.append('<div class="' + options.root + '"><ul class="folders"></ul></div>');
|
|
363
|
+
fileBrowser(options);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return afterComponentsMounted();
|
|
127
367
|
},
|
|
128
368
|
|
|
129
369
|
_createTarget: function($elt) {
|
|
@@ -136,7 +376,9 @@ var resourceMgr = {
|
|
|
136
376
|
options.$target = $(
|
|
137
377
|
layout({
|
|
138
378
|
title: options.title || '',
|
|
139
|
-
className: options.className || ''
|
|
379
|
+
className: options.className || '',
|
|
380
|
+
assetSearchInputId: options.targetId + '-asset-search',
|
|
381
|
+
assetSearchBodyId: options.targetId + '-asset-search-body'
|
|
140
382
|
})
|
|
141
383
|
);
|
|
142
384
|
|