@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.
Files changed (31) hide show
  1. package/dist/figure/FigureStateActive.js +64 -32
  2. package/dist/image/ImgStateActive/initHelper.js +64 -32
  3. package/dist/image/ImgStateActive.js +64 -32
  4. package/dist/previewer.js +1 -1
  5. package/dist/resourcemgr/assetSearch.js +793 -0
  6. package/dist/resourcemgr/assetSearchContract.js +477 -0
  7. package/dist/resourcemgr/css/resourcemgr.css +1137 -97
  8. package/dist/resourcemgr/css/resourcemgr.css.map +1 -1
  9. package/dist/resourcemgr/fileBrowser.js +456 -79
  10. package/dist/resourcemgr/filePreview.js +40 -4
  11. package/dist/resourcemgr/fileSelector.js +362 -92
  12. package/dist/resourcemgr.js +309 -57
  13. package/dist/searchModal/advancedSearch.js +233 -31
  14. package/package.json +15 -6
  15. package/src/image/ImgStateActive/initHelper.js +69 -31
  16. package/src/previewer.js +1 -1
  17. package/src/resourcemgr/assetSearch.js +847 -0
  18. package/src/resourcemgr/assetSearchContract.js +489 -0
  19. package/src/resourcemgr/css/resourcemgr.css +1137 -97
  20. package/src/resourcemgr/css/resourcemgr.css.map +1 -1
  21. package/src/resourcemgr/fileBrowser.js +470 -91
  22. package/src/resourcemgr/filePreview.js +46 -4
  23. package/src/resourcemgr/fileSelector.js +338 -46
  24. package/src/resourcemgr/scss/resourcemgr.scss +1351 -88
  25. package/src/resourcemgr/tpl/advanced-search.tpl +10 -0
  26. package/src/resourcemgr/tpl/fileSelect.tpl +25 -28
  27. package/src/resourcemgr/tpl/folder.tpl +4 -1
  28. package/src/resourcemgr/tpl/layout.tpl +113 -54
  29. package/src/resourcemgr/tpl/rootFolder.tpl +3 -1
  30. package/src/resourcemgr.js +289 -47
  31. package/src/searchModal/advancedSearch.js +242 -31
@@ -212,9 +212,9 @@ define(['jquery', 'nouislider', 'ui/resourcemgr', 'ui/tooltip', 'lodash', 'i18n'
212
212
  *
213
213
  * You should have received a copy of the GNU General Public License
214
214
  * along with this program; if not, write to the Free Software
215
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
215
+ * Foundation, Inc., 31 Milk St # 960789 Boston, MA 02196 USA.
216
216
  *
217
- * Copyright (c) 2021 (original work) Open Assessment Technologies SA ;
217
+ * Copyright (c) 2021-2026 (original work) Open Assessment Technologies SA ;
218
218
  *
219
219
  */
220
220
  const initAdvanced = function (widget) {
@@ -233,21 +233,45 @@ define(['jquery', 'nouislider', 'ui/resourcemgr', 'ui/tooltip', 'lodash', 'i18n'
233
233
  const $form = widget.$form;
234
234
  const options = widget.options;
235
235
  const {
236
- img
236
+ img,
237
+ $img
237
238
  } = getImage(widget);
238
239
  const $uploadTrigger = $form.find('[data-role="upload-trigger"]');
239
240
  const $src = $form.find('input[name=src]');
240
241
  const $alt = $form.find('input[name=alt]');
242
+ const commitSrc = function (srcValue) {
243
+ $src.val(srcValue);
244
+ // Keep QTI model + preview in sync immediately: the form src callback is
245
+ // throttled (1s), so a late trailing call must not leave a rejected pick.
246
+ if (img) {
247
+ img.attr('src', srcValue);
248
+ }
249
+ if ($img && $img.length) {
250
+ $img.attr('src', srcValue ? widget.getAssetManager().resolve(srcValue) : '');
251
+ $img.trigger('contentChange.qti-widget').change();
252
+ }
253
+ _.defer(function () {
254
+ if (img) {
255
+ img.attr('off-media-editor', 1);
256
+ }
257
+ $src.trigger('change');
258
+ });
259
+ };
241
260
  const _openResourceMgr = function () {
242
261
  $uploadTrigger.resourcemgr({
243
262
  title: __('Please select an image file from the resource manager. You can add files from your computer with the button "Add file(s)".'),
244
263
  appendContainer: options.mediaManager.appendContainer,
245
264
  mediaSourcesUrl: options.mediaManager.mediaSourcesUrl,
246
265
  browseUrl: options.mediaManager.browseUrl,
266
+ searchUrl: options.mediaManager.searchUrl,
247
267
  uploadUrl: options.mediaManager.uploadUrl,
248
268
  deleteUrl: options.mediaManager.deleteUrl,
249
269
  downloadUrl: options.mediaManager.downloadUrl,
250
270
  fileExistsUrl: options.mediaManager.fileExistsUrl,
271
+ rootClassUri: options.mediaManager.rootClassUri,
272
+ classMappingUrl: options.mediaManager.classMappingUrl,
273
+ statusUrl: options.mediaManager.statusUrl,
274
+ maxListSize: options.mediaManager.maxListSize,
251
275
  params: {
252
276
  uri: options.uri,
253
277
  lang: options.lang,
@@ -267,41 +291,49 @@ define(['jquery', 'nouislider', 'ui/resourcemgr', 'ui/tooltip', 'lodash', 'i18n'
267
291
  pathParam: 'path',
268
292
  path: options.mediaManager.path,
269
293
  root: options.mediaManager.root,
294
+ currentAsset: $src.val() || null,
270
295
  select: function (e, files) {
271
296
  let file, alt;
272
297
  let confirmBox, cancel, save;
273
- if (files && files.length) {
274
- file = files[0].file;
275
- alt = files[0].alt;
276
- $src.val(file);
277
- if ($$1.trim($alt.val()) === '') {
278
- if (alt === '') {
279
- alt = extractLabel(file);
280
- }
298
+ if (!(files && files.length)) {
299
+ return;
300
+ }
301
+ file = files[0].file;
302
+ alt = files[0].alt;
303
+
304
+ // Apply the new file immediately; alt confirm only decides alt text.
305
+ commitSrc(file);
306
+ if ($$1.trim($alt.val()) === '') {
307
+ if (alt === '') {
308
+ alt = extractLabel(file);
309
+ }
310
+ if (img) {
281
311
  img.attr('alt', alt);
282
- $alt.val(alt).trigger('change');
283
- } else {
284
- confirmBox = $$1('.change-alt-modal-feedback', $form);
285
- cancel = confirmBox.find('.cancel');
286
- save = confirmBox.find('.save');
287
- $$1('.alt-text', confirmBox).html(`"${$alt.val()}"<br>${__('with')}<br>"${alt}" ?`);
288
- confirmBox.modal({
289
- width: 500
290
- });
291
- save.off('click').on('click', function () {
292
- img.attr('alt', alt);
293
- $alt.val(alt).trigger('change');
294
- confirmBox.modal('close');
295
- });
296
- cancel.off('click').on('click', function () {
297
- confirmBox.modal('close');
298
- });
299
312
  }
300
- _.defer(function () {
301
- img.attr('off-media-editor', 1);
302
- $src.trigger('change');
303
- });
313
+ $alt.val(alt).trigger('change');
314
+ return;
304
315
  }
316
+
317
+ // Existing alt: confirm replace. Cancel / overlay / Esc keeps the new image;
318
+ // only alt text stays unchanged unless the user confirms.
319
+ confirmBox = $$1('.change-alt-modal-feedback', $form);
320
+ cancel = confirmBox.find('.cancel');
321
+ save = confirmBox.find('.save');
322
+ const $altText = $$1('.alt-text', confirmBox).empty();
323
+ $altText.append(document.createTextNode(`"${$alt.val()}"`)).append($$1('<br>')).append(document.createTextNode(__('with'))).append($$1('<br>')).append(document.createTextNode(`"${alt}" ?`));
324
+ confirmBox.modal({
325
+ width: 500
326
+ });
327
+ save.off('click').on('click', function () {
328
+ if (img) {
329
+ img.attr('alt', alt);
330
+ }
331
+ $alt.val(alt).trigger('change');
332
+ confirmBox.modal('close');
333
+ });
334
+ cancel.off('click').on('click', function () {
335
+ confirmBox.modal('close');
336
+ });
305
337
  },
306
338
  open: function () {
307
339
  // hide tooltip if displayed
@@ -210,9 +210,9 @@ define(['exports', 'jquery', 'lodash', 'i18n', 'core/mimetype', 'ui/mediaEditor/
210
210
  *
211
211
  * You should have received a copy of the GNU General Public License
212
212
  * along with this program; if not, write to the Free Software
213
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
213
+ * Foundation, Inc., 31 Milk St # 960789 Boston, MA 02196 USA.
214
214
  *
215
- * Copyright (c) 2021 (original work) Open Assessment Technologies SA ;
215
+ * Copyright (c) 2021-2026 (original work) Open Assessment Technologies SA ;
216
216
  *
217
217
  */
218
218
  const initAdvanced = function (widget) {
@@ -231,21 +231,45 @@ define(['exports', 'jquery', 'lodash', 'i18n', 'core/mimetype', 'ui/mediaEditor/
231
231
  const $form = widget.$form;
232
232
  const options = widget.options;
233
233
  const {
234
- img
234
+ img,
235
+ $img
235
236
  } = getImage(widget);
236
237
  const $uploadTrigger = $form.find('[data-role="upload-trigger"]');
237
238
  const $src = $form.find('input[name=src]');
238
239
  const $alt = $form.find('input[name=alt]');
240
+ const commitSrc = function (srcValue) {
241
+ $src.val(srcValue);
242
+ // Keep QTI model + preview in sync immediately: the form src callback is
243
+ // throttled (1s), so a late trailing call must not leave a rejected pick.
244
+ if (img) {
245
+ img.attr('src', srcValue);
246
+ }
247
+ if ($img && $img.length) {
248
+ $img.attr('src', srcValue ? widget.getAssetManager().resolve(srcValue) : '');
249
+ $img.trigger('contentChange.qti-widget').change();
250
+ }
251
+ _.defer(function () {
252
+ if (img) {
253
+ img.attr('off-media-editor', 1);
254
+ }
255
+ $src.trigger('change');
256
+ });
257
+ };
239
258
  const _openResourceMgr = function () {
240
259
  $uploadTrigger.resourcemgr({
241
260
  title: __('Please select an image file from the resource manager. You can add files from your computer with the button "Add file(s)".'),
242
261
  appendContainer: options.mediaManager.appendContainer,
243
262
  mediaSourcesUrl: options.mediaManager.mediaSourcesUrl,
244
263
  browseUrl: options.mediaManager.browseUrl,
264
+ searchUrl: options.mediaManager.searchUrl,
245
265
  uploadUrl: options.mediaManager.uploadUrl,
246
266
  deleteUrl: options.mediaManager.deleteUrl,
247
267
  downloadUrl: options.mediaManager.downloadUrl,
248
268
  fileExistsUrl: options.mediaManager.fileExistsUrl,
269
+ rootClassUri: options.mediaManager.rootClassUri,
270
+ classMappingUrl: options.mediaManager.classMappingUrl,
271
+ statusUrl: options.mediaManager.statusUrl,
272
+ maxListSize: options.mediaManager.maxListSize,
249
273
  params: {
250
274
  uri: options.uri,
251
275
  lang: options.lang,
@@ -265,41 +289,49 @@ define(['exports', 'jquery', 'lodash', 'i18n', 'core/mimetype', 'ui/mediaEditor/
265
289
  pathParam: 'path',
266
290
  path: options.mediaManager.path,
267
291
  root: options.mediaManager.root,
292
+ currentAsset: $src.val() || null,
268
293
  select: function (e, files) {
269
294
  let file, alt;
270
295
  let confirmBox, cancel, save;
271
- if (files && files.length) {
272
- file = files[0].file;
273
- alt = files[0].alt;
274
- $src.val(file);
275
- if ($.trim($alt.val()) === '') {
276
- if (alt === '') {
277
- alt = extractLabel(file);
278
- }
296
+ if (!(files && files.length)) {
297
+ return;
298
+ }
299
+ file = files[0].file;
300
+ alt = files[0].alt;
301
+
302
+ // Apply the new file immediately; alt confirm only decides alt text.
303
+ commitSrc(file);
304
+ if ($.trim($alt.val()) === '') {
305
+ if (alt === '') {
306
+ alt = extractLabel(file);
307
+ }
308
+ if (img) {
279
309
  img.attr('alt', alt);
280
- $alt.val(alt).trigger('change');
281
- } else {
282
- confirmBox = $('.change-alt-modal-feedback', $form);
283
- cancel = confirmBox.find('.cancel');
284
- save = confirmBox.find('.save');
285
- $('.alt-text', confirmBox).html(`"${$alt.val()}"<br>${__('with')}<br>"${alt}" ?`);
286
- confirmBox.modal({
287
- width: 500
288
- });
289
- save.off('click').on('click', function () {
290
- img.attr('alt', alt);
291
- $alt.val(alt).trigger('change');
292
- confirmBox.modal('close');
293
- });
294
- cancel.off('click').on('click', function () {
295
- confirmBox.modal('close');
296
- });
297
310
  }
298
- _.defer(function () {
299
- img.attr('off-media-editor', 1);
300
- $src.trigger('change');
301
- });
311
+ $alt.val(alt).trigger('change');
312
+ return;
302
313
  }
314
+
315
+ // Existing alt: confirm replace. Cancel / overlay / Esc keeps the new image;
316
+ // only alt text stays unchanged unless the user confirms.
317
+ confirmBox = $('.change-alt-modal-feedback', $form);
318
+ cancel = confirmBox.find('.cancel');
319
+ save = confirmBox.find('.save');
320
+ const $altText = $('.alt-text', confirmBox).empty();
321
+ $altText.append(document.createTextNode(`"${$alt.val()}"`)).append($('<br>')).append(document.createTextNode(__('with'))).append($('<br>')).append(document.createTextNode(`"${alt}" ?`));
322
+ confirmBox.modal({
323
+ width: 500
324
+ });
325
+ save.off('click').on('click', function () {
326
+ if (img) {
327
+ img.attr('alt', alt);
328
+ }
329
+ $alt.val(alt).trigger('change');
330
+ confirmBox.modal('close');
331
+ });
332
+ cancel.off('click').on('click', function () {
333
+ confirmBox.modal('close');
334
+ });
303
335
  },
304
336
  open: function () {
305
337
  // hide tooltip if displayed
@@ -210,9 +210,9 @@ define(['jquery', 'nouislider', 'ui/resourcemgr', 'ui/tooltip', 'lodash', 'i18n'
210
210
  *
211
211
  * You should have received a copy of the GNU General Public License
212
212
  * along with this program; if not, write to the Free Software
213
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
213
+ * Foundation, Inc., 31 Milk St # 960789 Boston, MA 02196 USA.
214
214
  *
215
- * Copyright (c) 2021 (original work) Open Assessment Technologies SA ;
215
+ * Copyright (c) 2021-2026 (original work) Open Assessment Technologies SA ;
216
216
  *
217
217
  */
218
218
  const initAdvanced = function (widget) {
@@ -231,21 +231,45 @@ define(['jquery', 'nouislider', 'ui/resourcemgr', 'ui/tooltip', 'lodash', 'i18n'
231
231
  const $form = widget.$form;
232
232
  const options = widget.options;
233
233
  const {
234
- img
234
+ img,
235
+ $img
235
236
  } = getImage(widget);
236
237
  const $uploadTrigger = $form.find('[data-role="upload-trigger"]');
237
238
  const $src = $form.find('input[name=src]');
238
239
  const $alt = $form.find('input[name=alt]');
240
+ const commitSrc = function (srcValue) {
241
+ $src.val(srcValue);
242
+ // Keep QTI model + preview in sync immediately: the form src callback is
243
+ // throttled (1s), so a late trailing call must not leave a rejected pick.
244
+ if (img) {
245
+ img.attr('src', srcValue);
246
+ }
247
+ if ($img && $img.length) {
248
+ $img.attr('src', srcValue ? widget.getAssetManager().resolve(srcValue) : '');
249
+ $img.trigger('contentChange.qti-widget').change();
250
+ }
251
+ _.defer(function () {
252
+ if (img) {
253
+ img.attr('off-media-editor', 1);
254
+ }
255
+ $src.trigger('change');
256
+ });
257
+ };
239
258
  const _openResourceMgr = function () {
240
259
  $uploadTrigger.resourcemgr({
241
260
  title: __('Please select an image file from the resource manager. You can add files from your computer with the button "Add file(s)".'),
242
261
  appendContainer: options.mediaManager.appendContainer,
243
262
  mediaSourcesUrl: options.mediaManager.mediaSourcesUrl,
244
263
  browseUrl: options.mediaManager.browseUrl,
264
+ searchUrl: options.mediaManager.searchUrl,
245
265
  uploadUrl: options.mediaManager.uploadUrl,
246
266
  deleteUrl: options.mediaManager.deleteUrl,
247
267
  downloadUrl: options.mediaManager.downloadUrl,
248
268
  fileExistsUrl: options.mediaManager.fileExistsUrl,
269
+ rootClassUri: options.mediaManager.rootClassUri,
270
+ classMappingUrl: options.mediaManager.classMappingUrl,
271
+ statusUrl: options.mediaManager.statusUrl,
272
+ maxListSize: options.mediaManager.maxListSize,
249
273
  params: {
250
274
  uri: options.uri,
251
275
  lang: options.lang,
@@ -265,41 +289,49 @@ define(['jquery', 'nouislider', 'ui/resourcemgr', 'ui/tooltip', 'lodash', 'i18n'
265
289
  pathParam: 'path',
266
290
  path: options.mediaManager.path,
267
291
  root: options.mediaManager.root,
292
+ currentAsset: $src.val() || null,
268
293
  select: function (e, files) {
269
294
  let file, alt;
270
295
  let confirmBox, cancel, save;
271
- if (files && files.length) {
272
- file = files[0].file;
273
- alt = files[0].alt;
274
- $src.val(file);
275
- if ($.trim($alt.val()) === '') {
276
- if (alt === '') {
277
- alt = extractLabel(file);
278
- }
296
+ if (!(files && files.length)) {
297
+ return;
298
+ }
299
+ file = files[0].file;
300
+ alt = files[0].alt;
301
+
302
+ // Apply the new file immediately; alt confirm only decides alt text.
303
+ commitSrc(file);
304
+ if ($.trim($alt.val()) === '') {
305
+ if (alt === '') {
306
+ alt = extractLabel(file);
307
+ }
308
+ if (img) {
279
309
  img.attr('alt', alt);
280
- $alt.val(alt).trigger('change');
281
- } else {
282
- confirmBox = $('.change-alt-modal-feedback', $form);
283
- cancel = confirmBox.find('.cancel');
284
- save = confirmBox.find('.save');
285
- $('.alt-text', confirmBox).html(`"${$alt.val()}"<br>${__('with')}<br>"${alt}" ?`);
286
- confirmBox.modal({
287
- width: 500
288
- });
289
- save.off('click').on('click', function () {
290
- img.attr('alt', alt);
291
- $alt.val(alt).trigger('change');
292
- confirmBox.modal('close');
293
- });
294
- cancel.off('click').on('click', function () {
295
- confirmBox.modal('close');
296
- });
297
310
  }
298
- _.defer(function () {
299
- img.attr('off-media-editor', 1);
300
- $src.trigger('change');
301
- });
311
+ $alt.val(alt).trigger('change');
312
+ return;
302
313
  }
314
+
315
+ // Existing alt: confirm replace. Cancel / overlay / Esc keeps the new image;
316
+ // only alt text stays unchanged unless the user confirms.
317
+ confirmBox = $('.change-alt-modal-feedback', $form);
318
+ cancel = confirmBox.find('.cancel');
319
+ save = confirmBox.find('.save');
320
+ const $altText = $('.alt-text', confirmBox).empty();
321
+ $altText.append(document.createTextNode(`"${$alt.val()}"`)).append($('<br>')).append(document.createTextNode(__('with'))).append($('<br>')).append(document.createTextNode(`"${alt}" ?`));
322
+ confirmBox.modal({
323
+ width: 500
324
+ });
325
+ save.off('click').on('click', function () {
326
+ if (img) {
327
+ img.attr('alt', alt);
328
+ }
329
+ $alt.val(alt).trigger('change');
330
+ confirmBox.modal('close');
331
+ });
332
+ cancel.off('click').on('click', function () {
333
+ confirmBox.modal('close');
334
+ });
303
335
  },
304
336
  open: function () {
305
337
  // hide tooltip if displayed
package/dist/previewer.js CHANGED
@@ -213,7 +213,7 @@ define(['jquery', 'lodash', 'core/mimetype', 'core/pluginifier', 'ui/mediaplayer
213
213
  // stop the video and free the socket on file select from the action icons
214
214
  // stop video, free the socket and remove player interface on video deletion
215
215
  // stop video and free the socket on all other cases when video is selected or temporary hidden or modal window is closed
216
- $controls = $('.actions a:nth-child(1), .actions a:nth-child(3), .icon-close, .upload-switcher, .select-action, .files li>span', '#mediaManager');
216
+ $controls = $('.actions a:nth-child(1), .actions a:nth-child(3), .icon-close, .upload-switcher, .select-action, .files-list tr, .files .desc', '#mediaManager');
217
217
  $controls.off('mousedown.mediaelement').on('mousedown.mediaelement', function (event) {
218
218
  event.stopPropagation();
219
219
  if (!$(this).closest('.mediaplayer').length) {