@oat-sa/tao-core-ui 1.57.0 → 1.58.2
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/actionbar.js +386 -395
- package/dist/adder.js +21 -19
- package/dist/animable/absorbable/absorbable.js +204 -213
- package/dist/animable/absorbable/css/absorb.css +1 -0
- package/dist/animable/absorbable/css/absorb.css.map +1 -1
- package/dist/animable/pulsable/pulsable.js +168 -177
- package/dist/autocomplete/css/autocomplete.css +1 -0
- package/dist/autocomplete/css/autocomplete.css.map +1 -1
- package/dist/autocomplete.js +68 -66
- package/dist/badge/badge.js +188 -197
- package/dist/badge/css/badge.css +1 -0
- package/dist/badge/css/badge.css.map +1 -1
- package/dist/breadcrumbs.js +275 -284
- package/dist/btngrouper.js +5 -5
- package/dist/bulkActionPopup.js +490 -495
- package/dist/button.js +283 -291
- package/dist/cascadingComboBox.js +249 -258
- package/dist/ckeditor/ckConfigurator.js +42 -20
- package/dist/ckeditor/dtdHandler.js +11 -9
- package/dist/class/selector.js +441 -450
- package/dist/component/resizable.js +1 -1
- package/dist/component/windowed.js +285 -294
- package/dist/component.js +419 -428
- package/dist/contextualPopup.js +417 -426
- package/dist/dashboard.js +300 -309
- package/dist/datalist.js +753 -762
- package/dist/datatable/filterStrategy/multiple.js +1 -1
- package/dist/datatable/filterStrategy/single.js +1 -1
- package/dist/datatable.js +1527 -1550
- package/dist/dateRange/dateRange.js +393 -402
- package/dist/datetime/picker.js +665 -672
- package/dist/deleter.js +368 -377
- package/dist/destination/selector.js +286 -295
- package/dist/dialog/alert.js +3 -3
- package/dist/dialog/confirm.js +1 -1
- package/dist/dialog/confirmDelete.js +216 -225
- package/dist/dialog.js +650 -654
- package/dist/disabler.js +8 -8
- package/dist/documentViewer/providers/pdfViewer/fallback/viewer.js +166 -175
- package/dist/documentViewer/providers/pdfViewer/pdfjs/findBar.js +518 -527
- package/dist/documentViewer/providers/pdfViewer/pdfjs/pageView.js +380 -389
- package/dist/documentViewer/providers/pdfViewer/pdfjs/searchEngine.js +539 -548
- package/dist/documentViewer/providers/pdfViewer/pdfjs/viewer.js +369 -378
- package/dist/documentViewer/providers/pdfViewer.js +184 -193
- package/dist/documentViewer.js +292 -301
- package/dist/dropdown.js +383 -392
- package/dist/durationer.js +5 -5
- package/dist/dynamicComponent.js +597 -598
- package/dist/feedback.js +356 -362
- package/dist/figure/FigureStateActive.js +117 -108
- package/dist/filesender.js +2 -2
- package/dist/filter.js +230 -239
- package/dist/form/dropdownForm.js +355 -357
- package/dist/form/form.js +919 -690
- package/dist/form/simpleForm.js +1 -1
- package/dist/form/validator/renderer.js +233 -235
- package/dist/form/validator/validator.js +257 -189
- package/dist/form/widget/definitions.js +1 -1
- package/dist/form/widget/providers/checkBox.js +254 -259
- package/dist/form/widget/providers/comboBox.js +187 -192
- package/dist/form/widget/providers/default.js +8 -9
- package/dist/form/widget/providers/hidden.js +170 -179
- package/dist/form/widget/providers/hiddenBox.js +262 -267
- package/dist/form/widget/providers/radioBox.js +216 -225
- package/dist/form/widget/providers/textArea.js +187 -196
- package/dist/form/widget/providers/textBox.js +2 -3
- package/dist/form/widget/widget.js +473 -475
- package/dist/formValidator/formValidator.js +1 -1
- package/dist/formValidator/highlighters/message.js +1 -1
- package/dist/generis/form/form.js +314 -323
- package/dist/generis/validator/validator.js +209 -218
- package/dist/generis/widget/checkBox/checkBox.js +218 -227
- package/dist/generis/widget/comboBox/comboBox.js +179 -188
- package/dist/generis/widget/hiddenBox/hiddenBox.js +220 -229
- package/dist/generis/widget/textBox/textBox.js +169 -178
- package/dist/generis/widget/widget.js +246 -255
- package/dist/groupedComboBox.js +222 -231
- package/dist/groupvalidator.js +2 -2
- package/dist/highlighter.js +967 -958
- package/dist/image/ImgStateActive/helper.js +7 -5
- package/dist/image/ImgStateActive/initHelper.js +49 -43
- package/dist/image/ImgStateActive/initMediaEditor.js +24 -20
- package/dist/image/ImgStateActive/mediaSizer.js +14 -12
- package/dist/image/ImgStateActive.js +72 -70
- package/dist/incrementer.js +6 -6
- package/dist/inplacer.js +6 -6
- package/dist/itemButtonList/css/item-button-list.css +1 -0
- package/dist/itemButtonList/css/item-button-list.css.map +1 -1
- package/dist/itemButtonList.js +439 -435
- package/dist/keyNavigation/navigableDomElement.js +51 -38
- package/dist/keyNavigation/navigator.js +85 -70
- package/dist/listbox.js +460 -469
- package/dist/liststyler.js +8 -8
- package/dist/loadingButton/loadingButton.js +209 -218
- package/dist/lock.js +476 -485
- package/dist/login/login.js +475 -484
- package/dist/maths/calculator/basicCalculator.js +235 -244
- package/dist/maths/calculator/calculatorComponent.js +3 -3
- package/dist/maths/calculator/core/board.js +772 -781
- package/dist/maths/calculator/core/expression.js +476 -485
- package/dist/maths/calculator/core/labels.js +228 -237
- package/dist/maths/calculator/core/tokenizer.js +1 -1
- package/dist/maths/calculator/core/tokens.js +163 -170
- package/dist/maths/calculator/plugins/keyboard/templateKeyboard/templateKeyboard.js +244 -253
- package/dist/maths/calculator/plugins/screen/simpleScreen/simpleScreen.js +279 -288
- package/dist/maths/calculator/scientificCalculator.js +327 -336
- package/dist/mediaEditor/mediaEditorComponent.js +238 -245
- package/dist/mediaEditor/plugins/mediaAlignment/helper.js +7 -7
- package/dist/mediaEditor/plugins/mediaAlignment/mediaAlignmentComponent.js +229 -235
- package/dist/mediaEditor/plugins/mediaDimension/mediaDimensionComponent.js +580 -589
- package/dist/mediaplayer/players/html5.js +666 -675
- package/dist/mediaplayer/players/youtube.js +419 -424
- package/dist/mediaplayer/support.js +11 -10
- package/dist/mediaplayer/utils/reminder.js +14 -13
- package/dist/mediaplayer/utils/timeObserver.js +10 -11
- package/dist/mediaplayer/youtubeManager.js +164 -145
- package/dist/mediaplayer.js +1565 -1520
- package/dist/mediasizer.js +669 -678
- package/dist/modal.js +10 -17
- package/dist/pageSizeSelector.js +219 -228
- package/dist/pagination/providers/pages.js +280 -289
- package/dist/pagination/providers/simple.js +192 -201
- package/dist/previewer.js +30 -30
- package/dist/progressbar.js +4 -4
- package/dist/report.js +347 -356
- package/dist/resource/filters.js +271 -280
- package/dist/resource/list.js +1264 -1273
- package/dist/resource/selector.js +865 -874
- package/dist/resource/tree.js +1483 -1492
- package/dist/resourcemgr/fileBrowser.js +564 -569
- package/dist/resourcemgr/filePreview.js +16 -16
- package/dist/resourcemgr/fileSelector.js +515 -524
- package/dist/resourcemgr/util/updatePermissions.js +2 -2
- package/dist/resourcemgr.js +306 -315
- package/dist/searchModal/advancedSearch.js +796 -767
- package/dist/searchModal.js +597 -549
- package/dist/switch/switch.js +298 -307
- package/dist/tabs.js +598 -575
- package/dist/taskQueue/status.js +312 -321
- package/dist/taskQueue/table.js +375 -384
- package/dist/taskQueue/taskQueueModel.js +488 -472
- package/dist/taskQueueButton/taskable.js +264 -273
- package/dist/taskQueueButton/treeButton.js +189 -198
- package/dist/themeLoader.js +24 -23
- package/dist/themes.js +1 -1
- package/dist/toggler.js +3 -3
- package/dist/tooltip.js +295 -304
- package/dist/transformer.js +2 -2
- package/dist/tristateCheckboxGroup.js +311 -320
- package/dist/uploader.js +687 -696
- package/dist/validator/Report.js +1 -1
- package/dist/validator/Validator.js +3 -3
- package/dist/validator/validators.js +9 -9
- package/dist/validator.js +240 -230
- package/dist/waitForMedia.js +1 -1
- package/package.json +3 -3
- package/scss/ckeditor/skins/tao/scss/inc/_menu.scss +51 -27
- package/scss/ckeditor/skins/tao/scss/inc/_panel.scss +16 -5
- package/scss/ckeditor/skins/tao/scss/inc/_richcombo.scss +0 -2
- package/scss/ckeditor/skins/tao/scss/inc/_toolbar.scss +15 -3
- package/src/animable/absorbable/css/absorb.css +1 -0
- package/src/animable/absorbable/css/absorb.css.map +1 -1
- package/src/autocomplete/css/autocomplete.css +1 -0
- package/src/autocomplete/css/autocomplete.css.map +1 -1
- package/src/badge/css/badge.css +1 -0
- package/src/badge/css/badge.css.map +1 -1
- package/src/ckeditor/ckConfigurator.js +24 -1
- package/src/itemButtonList/css/item-button-list.css +1 -0
- package/src/itemButtonList/css/item-button-list.css.map +1 -1
- package/scss/.DS_Store +0 -0
- package/src/.DS_Store +0 -0
package/dist/searchModal.js
CHANGED
|
@@ -1,638 +1,686 @@
|
|
|
1
1
|
define(['jquery', 'lodash', 'i18n', 'context', 'handlebars', 'lib/dompurify/purify', 'css!ui/searchModal/css/searchModal.css', 'ui/component', 'ui/modal', 'ui/datatable', 'core/store', 'ui/resource/selector', 'ui/searchModal/advancedSearch', 'core/dataProvider/request', 'util/url', 'select2', 'util/shortcut/registry'], function ($$1, _, __, context, Handlebars, DOMPurify, searchModal_css, component, modal, datatable, store, resourceSelectorFactory, advancedSearchFactory, request, urlUtil, select2, shortcutRegistry) { 'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
$$1 = $$1 && Object.prototype.hasOwnProperty.call($$1, 'default') ? $$1['default'] : $$1;
|
|
4
|
+
_ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _;
|
|
5
|
+
__ = __ && Object.prototype.hasOwnProperty.call(__, 'default') ? __['default'] : __;
|
|
6
|
+
context = context && Object.prototype.hasOwnProperty.call(context, 'default') ? context['default'] : context;
|
|
7
|
+
Handlebars = Handlebars && Object.prototype.hasOwnProperty.call(Handlebars, 'default') ? Handlebars['default'] : Handlebars;
|
|
8
|
+
DOMPurify = DOMPurify && Object.prototype.hasOwnProperty.call(DOMPurify, 'default') ? DOMPurify['default'] : DOMPurify;
|
|
9
|
+
component = component && Object.prototype.hasOwnProperty.call(component, 'default') ? component['default'] : component;
|
|
10
|
+
store = store && Object.prototype.hasOwnProperty.call(store, 'default') ? store['default'] : store;
|
|
11
|
+
resourceSelectorFactory = resourceSelectorFactory && Object.prototype.hasOwnProperty.call(resourceSelectorFactory, 'default') ? resourceSelectorFactory['default'] : resourceSelectorFactory;
|
|
12
|
+
advancedSearchFactory = advancedSearchFactory && Object.prototype.hasOwnProperty.call(advancedSearchFactory, 'default') ? advancedSearchFactory['default'] : advancedSearchFactory;
|
|
13
|
+
request = request && Object.prototype.hasOwnProperty.call(request, 'default') ? request['default'] : request;
|
|
14
|
+
urlUtil = urlUtil && Object.prototype.hasOwnProperty.call(urlUtil, 'default') ? urlUtil['default'] : urlUtil;
|
|
15
|
+
shortcutRegistry = shortcutRegistry && Object.prototype.hasOwnProperty.call(shortcutRegistry, 'default') ? shortcutRegistry['default'] : shortcutRegistry;
|
|
16
|
+
|
|
17
|
+
function ownKeys(object, enumerableOnly) {
|
|
18
|
+
var keys = Object.keys(object);
|
|
19
|
+
|
|
20
|
+
if (Object.getOwnPropertySymbols) {
|
|
21
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
22
|
+
enumerableOnly && (symbols = symbols.filter(function (sym) {
|
|
23
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
24
|
+
})), keys.push.apply(keys, symbols);
|
|
25
|
+
}
|
|
16
26
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
* modify it under the terms of the GNU General Public License
|
|
20
|
-
* as published by the Free Software Foundation; under version 2
|
|
21
|
-
* of the License (non-upgradable).
|
|
22
|
-
*
|
|
23
|
-
* This program is distributed in the hope that it will be useful,
|
|
24
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
25
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
26
|
-
* GNU General Public License for more details.
|
|
27
|
-
*
|
|
28
|
-
* You should have received a copy of the GNU General Public License
|
|
29
|
-
* along with this program; if not, write to the Free Software
|
|
30
|
-
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
31
|
-
*
|
|
32
|
-
* Copyright (c) 2013-2019 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*/
|
|
36
|
-
function Helpers0 (hb) {
|
|
37
|
-
//register a i18n helper
|
|
38
|
-
hb.registerHelper('__', function (key) {
|
|
39
|
-
return __(key);
|
|
40
|
-
});
|
|
41
|
-
/**
|
|
42
|
-
* Register dompurify helper
|
|
43
|
-
*
|
|
44
|
-
* https://github.com/cure53/DOMPurify
|
|
45
|
-
* with config SAFE_FOR_TEMPLATES: true
|
|
46
|
-
* to make output safe for template systems
|
|
47
|
-
*/
|
|
27
|
+
return keys;
|
|
28
|
+
}
|
|
48
29
|
|
|
49
|
-
|
|
50
|
-
|
|
30
|
+
function _objectSpread2(target) {
|
|
31
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
32
|
+
var source = null != arguments[i] ? arguments[i] : {};
|
|
33
|
+
i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
|
|
34
|
+
_defineProperty(target, key, source[key]);
|
|
35
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
|
|
36
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
51
37
|
});
|
|
52
|
-
|
|
53
|
-
* Register join helper
|
|
54
|
-
*
|
|
55
|
-
* Example :
|
|
56
|
-
* var values = {a:v1, b:v2, c:v3};
|
|
57
|
-
* Using {{{join attributes '=' ' ' '"'}}} will return : a="v1" b="v2" c="v3"
|
|
58
|
-
* Using {{{join values null ' or ' '*'}}} will return : *v1* or *v2* or *v3*
|
|
59
|
-
*/
|
|
38
|
+
}
|
|
60
39
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
40
|
+
return target;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function _typeof(obj) {
|
|
44
|
+
"@babel/helpers - typeof";
|
|
45
|
+
|
|
46
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
|
|
47
|
+
return typeof obj;
|
|
48
|
+
} : function (obj) {
|
|
49
|
+
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
|
50
|
+
}, _typeof(obj);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function _defineProperty(obj, key, value) {
|
|
54
|
+
if (key in obj) {
|
|
55
|
+
Object.defineProperty(obj, key, {
|
|
56
|
+
value: value,
|
|
57
|
+
enumerable: true,
|
|
58
|
+
configurable: true,
|
|
59
|
+
writable: true
|
|
60
|
+
});
|
|
61
|
+
} else {
|
|
62
|
+
obj[key] = value;
|
|
63
|
+
}
|
|
66
64
|
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
return obj;
|
|
66
|
+
}
|
|
69
67
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
68
|
+
function Helpers0 (hb) {
|
|
69
|
+
//register a i18n helper
|
|
70
|
+
hb.registerHelper('__', function (key) {
|
|
71
|
+
return __(key);
|
|
72
|
+
});
|
|
73
|
+
/**
|
|
74
|
+
* Register dompurify helper
|
|
75
|
+
*
|
|
76
|
+
* https://github.com/cure53/DOMPurify
|
|
77
|
+
* with config SAFE_FOR_TEMPLATES: true
|
|
78
|
+
* to make output safe for template systems
|
|
79
|
+
*/
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
hb.registerHelper('dompurify', function (context) {
|
|
82
|
+
return DOMPurify.sanitize(context);
|
|
83
|
+
});
|
|
84
|
+
/**
|
|
85
|
+
* Register join helper
|
|
86
|
+
*
|
|
87
|
+
* Example :
|
|
88
|
+
* var values = {a:v1, b:v2, c:v3};
|
|
89
|
+
* Using {{{join attributes '=' ' ' '"'}}} will return : a="v1" b="v2" c="v3"
|
|
90
|
+
* Using {{{join values null ' or ' '*'}}} will return : *v1* or *v2* or *v3*
|
|
91
|
+
*/
|
|
83
92
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
93
|
+
hb.registerHelper('join', function (arr, keyValueGlue, fragmentGlue, wrapper) {
|
|
94
|
+
var fragments = [];
|
|
95
|
+
keyValueGlue = typeof keyValueGlue === 'string' ? keyValueGlue : undefined;
|
|
96
|
+
fragmentGlue = typeof fragmentGlue === 'string' ? fragmentGlue : ' ';
|
|
97
|
+
wrapper = typeof wrapper === 'string' ? wrapper : '"';
|
|
87
98
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
//it also adds a local variable "i" as the index in each iteration loop
|
|
99
|
+
_.forIn(arr, function (value, key) {
|
|
100
|
+
var fragment = '';
|
|
91
101
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
102
|
+
if (value !== null || value !== undefined) {
|
|
103
|
+
if (typeof value === 'boolean') {
|
|
104
|
+
value = value ? 'true' : 'false';
|
|
105
|
+
} else if (_typeof(value) === 'object') {
|
|
106
|
+
value = _.values(value).join(' ');
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
value = '';
|
|
110
|
+
}
|
|
97
111
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
i: i
|
|
101
|
-
}));
|
|
112
|
+
if (keyValueGlue !== undefined) {
|
|
113
|
+
fragment += key + keyValueGlue;
|
|
102
114
|
}
|
|
103
115
|
|
|
104
|
-
|
|
116
|
+
fragment += wrapper + value + wrapper;
|
|
117
|
+
fragments.push(fragment);
|
|
105
118
|
});
|
|
106
|
-
hb.registerHelper('equal', function (var1, var2, options) {
|
|
107
|
-
if (var1 == var2) {
|
|
108
|
-
return options.fn(this);
|
|
109
|
-
} else {
|
|
110
|
-
return options.inverse(this);
|
|
111
|
-
}
|
|
112
|
-
}); // register a "get property" helper
|
|
113
|
-
// it gets the named property from the provided context
|
|
114
119
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// it checks if value is in array
|
|
120
|
+
return fragments.join(fragmentGlue);
|
|
121
|
+
}); //register a classic "for loop" helper
|
|
122
|
+
//it also adds a local variable "i" as the index in each iteration loop
|
|
119
123
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
124
|
+
hb.registerHelper('for', function (startIndex, stopIndex, increment, options) {
|
|
125
|
+
var ret = '';
|
|
126
|
+
startIndex = parseInt(startIndex);
|
|
127
|
+
stopIndex = parseInt(stopIndex);
|
|
128
|
+
increment = parseInt(increment);
|
|
126
129
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
this.compilerInfo = [4,'>= 1.0.0'];
|
|
133
|
-
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
|
|
134
|
-
var buffer = "", stack1, helper, options, functionType="function", escapeExpression=this.escapeExpression, helperMissing=helpers.helperMissing;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
buffer += "<div class=\"search-modal section-container\">\n <div class=\"clear content-wrapper content-panel\">\n <div class=\"ui-container\">\n <div class=\"filters-container\">\n <div class=\"basic-search-container\">\n <div class=\"filter-container\">\n <span class=\"icon-find\"></span>\n <input class=\"generic-search-input\" type=\"text\" placeholder=\"";
|
|
138
|
-
if (helper = helpers.placeholder) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
139
|
-
else { helper = (depth0 && depth0.placeholder); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
140
|
-
buffer += escapeExpression(stack1)
|
|
141
|
-
+ "\">\n </div>\n <div class=\"filter-container class-filter-container\">\n <span class=\"icon-folder\"></span>\n <span class=\"icon-down\"></span>\n <textarea class=\"class-filter\" cols=\"40\" rows=\"1\" readonly></textarea>\n <div class=\"class-tree\"></div>\n </div>\n </div>\n </div>\n <div class=\"buttons-container\">\n <button class=\"btn-clear btn-transparent small\">"
|
|
142
|
-
+ escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Clear", options) : helperMissing.call(depth0, "__", "Clear", options)))
|
|
143
|
-
+ "</button>\n <button class=\"btn-search btn-info small\">"
|
|
144
|
-
+ escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Search", options) : helperMissing.call(depth0, "__", "Search", options)))
|
|
145
|
-
+ "</button>\n </div>\n </div>\n <div class=\"content-container\" style=\"padding:40px 20px\">\n </div>\n </div>\n</div>";
|
|
146
|
-
return buffer;
|
|
147
|
-
});
|
|
148
|
-
function layoutTpl(data, options, asString) {
|
|
149
|
-
var html = Template(data, options);
|
|
150
|
-
return (asString || true) ? html : $(html);
|
|
151
|
-
}
|
|
130
|
+
for (var i = startIndex; i < stopIndex; i += increment) {
|
|
131
|
+
ret += options.fn(_.extend({}, this, {
|
|
132
|
+
i: i
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
152
135
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
buffer += "<div class='no-datatable-container'>\n <span class=\"no-datatable-icon ";
|
|
164
|
-
if (helper = helpers.icon) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
165
|
-
else { helper = (depth0 && depth0.icon); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
166
|
-
buffer += escapeExpression(stack1)
|
|
167
|
-
+ "\"></span>\n <p class=\"no-datatable-message\">";
|
|
168
|
-
if (helper = helpers.message) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
169
|
-
else { helper = (depth0 && depth0.message); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
170
|
-
buffer += escapeExpression(stack1)
|
|
171
|
-
+ "</p>\n</div>";
|
|
172
|
-
return buffer;
|
|
173
|
-
});
|
|
174
|
-
function infoMessageTpl(data, options, asString) {
|
|
175
|
-
var html = Template$1(data, options);
|
|
176
|
-
return (asString || true) ? html : $(html);
|
|
177
|
-
}
|
|
136
|
+
return ret;
|
|
137
|
+
});
|
|
138
|
+
hb.registerHelper('equal', function (var1, var2, options) {
|
|
139
|
+
if (var1 == var2) {
|
|
140
|
+
return options.fn(this);
|
|
141
|
+
} else {
|
|
142
|
+
return options.inverse(this);
|
|
143
|
+
}
|
|
144
|
+
}); // register a "get property" helper
|
|
145
|
+
// it gets the named property from the provided context
|
|
178
146
|
|
|
147
|
+
hb.registerHelper('property', function (name, context) {
|
|
148
|
+
return context[name] || '';
|
|
149
|
+
}); // register an 'includes' helper
|
|
150
|
+
// it checks if value is in array
|
|
151
|
+
|
|
152
|
+
hb.registerHelper('includes', function (haystack, needle, options) {
|
|
153
|
+
if (_.contains(haystack, needle)) {
|
|
154
|
+
return options.fn(this);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (!Helpers0.__initialized) {
|
|
160
|
+
Helpers0(Handlebars);
|
|
161
|
+
Helpers0.__initialized = true;
|
|
162
|
+
}
|
|
163
|
+
var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
|
|
164
|
+
this.compilerInfo = [4,'>= 1.0.0'];
|
|
165
|
+
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
|
|
166
|
+
var buffer = "", stack1, helper, options, functionType="function", escapeExpression=this.escapeExpression, helperMissing=helpers.helperMissing;
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
buffer += "<div class=\"search-modal section-container\">\n <div class=\"clear content-wrapper content-panel\">\n <div class=\"ui-container\">\n <div class=\"filters-container\">\n <div class=\"basic-search-container\">\n <div class=\"filter-container\">\n <span class=\"icon-find\"></span>\n <input class=\"generic-search-input\" type=\"text\" placeholder=\"";
|
|
170
|
+
if (helper = helpers.placeholder) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
171
|
+
else { helper = (depth0 && depth0.placeholder); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
172
|
+
buffer += escapeExpression(stack1)
|
|
173
|
+
+ "\">\n </div>\n <div class=\"filter-container class-filter-container\">\n <span class=\"icon-folder\"></span>\n <span class=\"icon-down\"></span>\n <textarea class=\"class-filter\" cols=\"40\" rows=\"1\" readonly></textarea>\n <div class=\"class-tree\"></div>\n </div>\n </div>\n </div>\n <div class=\"buttons-container\">\n <button class=\"btn-clear btn-transparent small\">"
|
|
174
|
+
+ escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Clear", options) : helperMissing.call(depth0, "__", "Clear", options)))
|
|
175
|
+
+ "</button>\n <button class=\"btn-search btn-info small\">"
|
|
176
|
+
+ escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Search", options) : helperMissing.call(depth0, "__", "Search", options)))
|
|
177
|
+
+ "</button>\n </div>\n </div>\n <div class=\"content-container\" style=\"padding:40px 20px\">\n </div>\n </div>\n</div>";
|
|
178
|
+
return buffer;
|
|
179
|
+
});
|
|
180
|
+
function layoutTpl(data, options, asString) {
|
|
181
|
+
var html = Template(data, options);
|
|
182
|
+
return (asString || true) ? html : $(html);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (!Helpers0.__initialized) {
|
|
186
|
+
Helpers0(Handlebars);
|
|
187
|
+
Helpers0.__initialized = true;
|
|
188
|
+
}
|
|
189
|
+
var Template$1 = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
|
|
190
|
+
this.compilerInfo = [4,'>= 1.0.0'];
|
|
191
|
+
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
|
|
192
|
+
var buffer = "", stack1, helper, functionType="function", escapeExpression=this.escapeExpression;
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
buffer += "<div class='no-datatable-container'>\n <span class=\"no-datatable-icon ";
|
|
196
|
+
if (helper = helpers.icon) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
197
|
+
else { helper = (depth0 && depth0.icon); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
198
|
+
buffer += escapeExpression(stack1)
|
|
199
|
+
+ "\"></span>\n <p class=\"no-datatable-message\">";
|
|
200
|
+
if (helper = helpers.message) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
201
|
+
else { helper = (depth0 && depth0.message); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
202
|
+
buffer += escapeExpression(stack1)
|
|
203
|
+
+ "</p>\n</div>";
|
|
204
|
+
return buffer;
|
|
205
|
+
});
|
|
206
|
+
function infoMessageTpl(data, options, asString) {
|
|
207
|
+
var html = Template$1(data, options);
|
|
208
|
+
return (asString || true) ? html : $(html);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Creates a searchModal instance
|
|
213
|
+
*
|
|
214
|
+
* @param {object} config
|
|
215
|
+
* @param {object} config.renderTo - DOM element where component will be rendered to
|
|
216
|
+
* @param {string} config.criterias - Search criteria to be set on component creation
|
|
217
|
+
* @param {boolean} config.searchOnInit - if init search must be triggered or not (stored results are used instead)
|
|
218
|
+
* @param {string} config.url - search endpoint to be set on datatable
|
|
219
|
+
* @param {string} config.rootClassUri - Uri for the root class of current context, required to init the class filter
|
|
220
|
+
* @param {bool} config.hideResourceSelector - if resourceSelector must be hidden
|
|
221
|
+
* @param {string} config.placeholder - placeholder for input in template
|
|
222
|
+
* @returns {searchModal}
|
|
223
|
+
*/
|
|
224
|
+
|
|
225
|
+
function searchModalFactory(config) {
|
|
226
|
+
var defaults = {
|
|
227
|
+
renderTo: 'body',
|
|
228
|
+
criterias: {},
|
|
229
|
+
searchOnInit: true,
|
|
230
|
+
maxListSize: 5
|
|
231
|
+
}; // Private properties to be easily accessible by instance methods
|
|
232
|
+
|
|
233
|
+
var $container = null;
|
|
234
|
+
var $searchInput = null;
|
|
235
|
+
var $searchButton = null;
|
|
236
|
+
var $clearButton = null;
|
|
237
|
+
var running = false;
|
|
238
|
+
var searchStore = null;
|
|
239
|
+
var resourceSelector = null;
|
|
240
|
+
var $classFilterContainer = null;
|
|
241
|
+
var $classFilterInput = null;
|
|
242
|
+
var $classTreeContainer = null;
|
|
243
|
+
var advancedSearch = null; // resorce selector
|
|
244
|
+
|
|
245
|
+
var isResourceSelector = !config.hideResourceSelector;
|
|
246
|
+
var rootClassUri = config.rootClassUri;
|
|
179
247
|
/**
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
* as published by the Free Software Foundation; under version 2
|
|
183
|
-
* of the License (non-upgradable).
|
|
184
|
-
*
|
|
185
|
-
* This program is distributed in the hope that it will be useful,
|
|
186
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
187
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
188
|
-
* GNU General Public License for more details.
|
|
189
|
-
*
|
|
190
|
-
* You should have received a copy of the GNU General Public License
|
|
191
|
-
* along with this program; if not, write to the Free Software
|
|
192
|
-
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
193
|
-
*
|
|
194
|
-
* Copyright (c) 2021 (original work) Open Assessment Technologies SA ;
|
|
248
|
+
* Creates search modal, inits template selectors, inits search store, and once is created triggers initial search
|
|
249
|
+
* rootClassUri is sent to advancedSearch factory for disabling in whitelisted sections
|
|
195
250
|
*/
|
|
251
|
+
|
|
252
|
+
function renderModal() {
|
|
253
|
+
var promises = [];
|
|
254
|
+
initModal();
|
|
255
|
+
initUiSelectors();
|
|
256
|
+
advancedSearch = advancedSearchFactory({
|
|
257
|
+
renderTo: $$1('.filters-container', $container),
|
|
258
|
+
advancedCriteria: instance.config.criterias.advancedCriteria,
|
|
259
|
+
rootClassUri: rootClassUri
|
|
260
|
+
});
|
|
261
|
+
promises.push(initClassFilter());
|
|
262
|
+
promises.push(initSearchStore());
|
|
263
|
+
Promise.all(promises).then(function () {
|
|
264
|
+
instance.trigger('ready');
|
|
265
|
+
$searchButton.trigger('click');
|
|
266
|
+
}).catch(function (e) {
|
|
267
|
+
return instance.trigger('error', e);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
196
270
|
/**
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
* @param {object} config
|
|
200
|
-
* @param {object} config.renderTo - DOM element where component will be rendered to
|
|
201
|
-
* @param {string} config.criterias - Search criteria to be set on component creation
|
|
202
|
-
* @param {boolean} config.searchOnInit - if init search must be triggered or not (stored results are used instead)
|
|
203
|
-
* @param {string} config.url - search endpoint to be set on datatable
|
|
204
|
-
* @param {string} config.rootClassUri - Uri for the root class of current context, required to init the class filter
|
|
205
|
-
* @param {bool} config.hideResourceSelector - if resourceSelector must be hidden
|
|
206
|
-
* @param {string} config.placeholder - placeholder for input in template
|
|
207
|
-
* @returns {searchModal}
|
|
271
|
+
* Removes search modal
|
|
208
272
|
*/
|
|
209
273
|
|
|
210
|
-
function searchModalFactory(config) {
|
|
211
|
-
const defaults = {
|
|
212
|
-
renderTo: 'body',
|
|
213
|
-
criterias: {},
|
|
214
|
-
searchOnInit: true,
|
|
215
|
-
maxListSize: 5
|
|
216
|
-
}; // Private properties to be easily accessible by instance methods
|
|
217
|
-
|
|
218
|
-
let $container = null;
|
|
219
|
-
let $searchInput = null;
|
|
220
|
-
let $searchButton = null;
|
|
221
|
-
let $clearButton = null;
|
|
222
|
-
let running = false;
|
|
223
|
-
let searchStore = null;
|
|
224
|
-
let resourceSelector = null;
|
|
225
|
-
let $classFilterContainer = null;
|
|
226
|
-
let $classFilterInput = null;
|
|
227
|
-
let $classTreeContainer = null;
|
|
228
|
-
let advancedSearch = null; // resorce selector
|
|
229
|
-
|
|
230
|
-
const isResourceSelector = !config.hideResourceSelector;
|
|
231
|
-
const rootClassUri = config.rootClassUri;
|
|
232
|
-
/**
|
|
233
|
-
* Creates search modal, inits template selectors, inits search store, and once is created triggers initial search
|
|
234
|
-
* rootClassUri is sent to advancedSearch factory for disabling in whitelisted sections
|
|
235
|
-
*/
|
|
236
274
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
advancedSearch = advancedSearchFactory({
|
|
242
|
-
renderTo: $$1('.filters-container', $container),
|
|
243
|
-
advancedCriteria: instance.config.criterias.advancedCriteria,
|
|
244
|
-
rootClassUri: rootClassUri
|
|
245
|
-
});
|
|
246
|
-
promises.push(initClassFilter());
|
|
247
|
-
promises.push(initSearchStore());
|
|
248
|
-
Promise.all(promises).then(() => {
|
|
249
|
-
instance.trigger('ready');
|
|
250
|
-
$searchButton.trigger('click');
|
|
251
|
-
}).catch(e => instance.trigger('error', e));
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* Removes search modal
|
|
255
|
-
*/
|
|
275
|
+
function destroyModal() {
|
|
276
|
+
$container.removeClass('modal').modal('destroy');
|
|
277
|
+
$$1('.modal-bg').remove();
|
|
278
|
+
} // Creates new component
|
|
256
279
|
|
|
257
280
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const instance = component({}, defaults).setTemplate(layoutTpl).on('render', renderModal).on('destroy', destroyModal);
|
|
265
|
-
/**
|
|
266
|
-
* Creates search modal
|
|
267
|
-
*/
|
|
281
|
+
var instance = component({}, defaults).setTemplate(layoutTpl).on('render', renderModal).on('destroy', destroyModal);
|
|
282
|
+
/**
|
|
283
|
+
* Creates search modal
|
|
284
|
+
*/
|
|
268
285
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
286
|
+
function initModal() {
|
|
287
|
+
$container = instance.getElement();
|
|
288
|
+
$container.addClass('modal').on('closed.modal', function () {
|
|
289
|
+
return instance.destroy();
|
|
290
|
+
}).modal({
|
|
291
|
+
disableEscape: false,
|
|
292
|
+
width: $$1(window).width(),
|
|
293
|
+
modalCloseClass: 'modal-close-left'
|
|
294
|
+
}).focus();
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Inits class filter selector
|
|
298
|
+
*/
|
|
280
299
|
|
|
281
300
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
301
|
+
function initClassFilter() {
|
|
302
|
+
return new Promise(function (resolve) {
|
|
303
|
+
if (!isResourceSelector) {
|
|
304
|
+
$classFilterContainer.hide();
|
|
305
|
+
return resolve();
|
|
306
|
+
}
|
|
288
307
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
};
|
|
303
|
-
const route = urlUtil.route('getAll', 'RestResource', 'tao');
|
|
304
|
-
request(route, classOnlyParams).then(response => {
|
|
305
|
-
if (response.permissions && response.permissions.data && response.permissions.supportedRights && response.permissions.supportedRights.length > 0) {
|
|
306
|
-
manageClassTreePermissions(response);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
resourceSelector.update(response.resources, classOnlyParams);
|
|
310
|
-
}).catch(e => instance.trigger('error', e));
|
|
308
|
+
var initialClassUri = instance.config.criterias && instance.config.criterias.class ? instance.config.criterias.class : rootClassUri;
|
|
309
|
+
resourceSelector = resourceSelectorFactory($$1('.class-tree', $container), {
|
|
310
|
+
//set up the inner resource selector
|
|
311
|
+
selectionMode: 'single',
|
|
312
|
+
selectClass: true,
|
|
313
|
+
classUri: rootClassUri,
|
|
314
|
+
showContext: false,
|
|
315
|
+
showSelection: false
|
|
316
|
+
}); // when a class query is triggered, update selector options with received resources
|
|
317
|
+
|
|
318
|
+
resourceSelector.on('query', function (params) {
|
|
319
|
+
var classOnlyParams = _objectSpread2(_objectSpread2({}, params), {}, {
|
|
320
|
+
classOnly: true
|
|
311
321
|
});
|
|
312
|
-
/*
|
|
313
|
-
* the first time selector opions are updated the root class is selected. Promise is
|
|
314
|
-
* resolved so init process continues only when class input value has been set
|
|
315
|
-
*/
|
|
316
322
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}); // then new class is selected, set its label into class filter input and hide filter container, then request class properties
|
|
322
|
-
|
|
323
|
-
resourceSelector.on('change', selectedValue => {
|
|
324
|
-
/*
|
|
325
|
-
* on searchModal init we set manually the selector to the provided config.rootClassUri. When a selector
|
|
326
|
-
* is set manually Selector component execs @clearSelection which triggers a change event
|
|
327
|
-
* with an empty object as param. We catch this undesired behaviour here
|
|
328
|
-
*/
|
|
329
|
-
if (_.isEmpty(selectedValue)) {
|
|
330
|
-
return;
|
|
323
|
+
var route = urlUtil.route('getAll', 'RestResource', 'tao');
|
|
324
|
+
request(route, classOnlyParams).then(function (response) {
|
|
325
|
+
if (response.permissions && response.permissions.data && response.permissions.supportedRights && response.permissions.supportedRights.length > 0) {
|
|
326
|
+
manageClassTreePermissions(response);
|
|
331
327
|
}
|
|
332
328
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
const uri = _.map(selectedValue, 'uri')[0];
|
|
338
|
-
|
|
339
|
-
const route = urlUtil.route('getWithMapping', 'ClassMetadata', 'tao', {
|
|
340
|
-
classUri,
|
|
341
|
-
maxListSize: instance.config.maxListSize
|
|
342
|
-
});
|
|
343
|
-
$classFilterInput.html(label);
|
|
344
|
-
$classFilterInput.data('uri', uri);
|
|
345
|
-
$classTreeContainer.hide();
|
|
346
|
-
advancedSearch.updateCriteria(route).then(() => instance.trigger('criteriaListUpdated')).catch(e => instance.trigger('error', e));
|
|
329
|
+
resourceSelector.update(response.resources, classOnlyParams);
|
|
330
|
+
}).catch(function (e) {
|
|
331
|
+
return instance.trigger('error', e);
|
|
347
332
|
});
|
|
348
|
-
setResourceSelectorUIBehaviour();
|
|
349
333
|
});
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
* @param {object} classTree - class tree received by server, containing resources (classes) and permissions
|
|
355
|
-
*/
|
|
334
|
+
/*
|
|
335
|
+
* the first time selector opions are updated the root class is selected. Promise is
|
|
336
|
+
* resolved so init process continues only when class input value has been set
|
|
337
|
+
*/
|
|
356
338
|
|
|
339
|
+
resourceSelector.on('update', function () {
|
|
340
|
+
resourceSelector.off('update');
|
|
341
|
+
resourceSelector.select(initialClassUri);
|
|
342
|
+
resolve();
|
|
343
|
+
}); // then new class is selected, set its label into class filter input and hide filter container, then request class properties
|
|
357
344
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
}
|
|
368
|
-
});
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
disableBlockedClasses(classTree.resources);
|
|
372
|
-
}
|
|
373
|
-
/**
|
|
374
|
-
* Inits template selectors, buttons behaviour, scroll animation,
|
|
375
|
-
* and sets initial search query on search input
|
|
376
|
-
*/
|
|
345
|
+
resourceSelector.on('change', function (selectedValue) {
|
|
346
|
+
/*
|
|
347
|
+
* on searchModal init we set manually the selector to the provided config.rootClassUri. When a selector
|
|
348
|
+
* is set manually Selector component execs @clearSelection which triggers a change event
|
|
349
|
+
* with an empty object as param. We catch this undesired behaviour here
|
|
350
|
+
*/
|
|
351
|
+
if (_.isEmpty(selectedValue)) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
377
354
|
|
|
355
|
+
var classUri = _.map(selectedValue, 'classUri')[0];
|
|
378
356
|
|
|
379
|
-
|
|
380
|
-
$searchButton = $$1('.btn-search', $container);
|
|
381
|
-
$clearButton = $$1('.btn-clear', $container);
|
|
382
|
-
$searchInput = $$1('.generic-search-input', $container);
|
|
383
|
-
$classFilterInput = $$1('.class-filter', $container);
|
|
384
|
-
$classTreeContainer = $$1('.class-tree', $container);
|
|
385
|
-
$classFilterContainer = $$1('.class-filter-container', $container);
|
|
386
|
-
$searchButton.on('click', search);
|
|
387
|
-
$clearButton.on('click', clear);
|
|
388
|
-
const shortcuts = shortcutRegistry($searchInput);
|
|
389
|
-
shortcuts.clear().add('enter', search);
|
|
390
|
-
$searchInput.val(instance.config.criterias && instance.config.criterias.search ? instance.config.criterias.search : '');
|
|
391
|
-
}
|
|
392
|
-
/**
|
|
393
|
-
* Sets required listeners to properly manage resourceSelector visualization
|
|
394
|
-
*/
|
|
357
|
+
var label = _.map(selectedValue, 'label')[0];
|
|
395
358
|
|
|
359
|
+
var uri = _.map(selectedValue, 'uri')[0];
|
|
396
360
|
|
|
397
|
-
|
|
398
|
-
|
|
361
|
+
var route = urlUtil.route('getWithMapping', 'ClassMetadata', 'tao', {
|
|
362
|
+
classUri: classUri,
|
|
363
|
+
maxListSize: instance.config.maxListSize
|
|
364
|
+
});
|
|
365
|
+
$classFilterInput.html(label);
|
|
366
|
+
$classFilterInput.data('uri', uri);
|
|
399
367
|
$classTreeContainer.hide();
|
|
368
|
+
advancedSearch.updateCriteria(route).then(function () {
|
|
369
|
+
return instance.trigger('criteriaListUpdated');
|
|
370
|
+
}).catch(function (e) {
|
|
371
|
+
return instance.trigger('error', e);
|
|
372
|
+
});
|
|
400
373
|
});
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
374
|
+
setResourceSelectorUIBehaviour();
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Loops through each class in received class tree and sets access mode to 'denied' on private classes
|
|
379
|
+
* so are disabled on class tree
|
|
380
|
+
* @param {object} classTree - class tree received by server, containing resources (classes) and permissions
|
|
381
|
+
*/
|
|
405
382
|
|
|
406
|
-
const shortcuts = shortcutRegistry($classFilterInput);
|
|
407
|
-
shortcuts.add('enter', () => $classTreeContainer.show());
|
|
408
|
-
shortcuts.add('space', () => $classTreeContainer.show());
|
|
409
|
-
shortcuts.add('backspace', () => $classTreeContainer.hide());
|
|
410
|
-
shortcuts.add('escape', () => $classTreeContainer.hide(), {
|
|
411
|
-
propagate: false
|
|
412
|
-
});
|
|
413
|
-
/**
|
|
414
|
-
* clicking on class filter container will toggle resource selector
|
|
415
|
-
*/
|
|
416
383
|
|
|
417
|
-
|
|
418
|
-
|
|
384
|
+
function manageClassTreePermissions(classTree) {
|
|
385
|
+
var disableBlockedClasses = function disableBlockedClasses(resources) {
|
|
386
|
+
_.forEach(resources, function (resource, index, array) {
|
|
387
|
+
if (classTree.permissions.data[resource.uri] && classTree.permissions.data[resource.uri].find(function (permission) {
|
|
388
|
+
return permission === 'READ';
|
|
389
|
+
})) {
|
|
390
|
+
if (resource.children) {
|
|
391
|
+
disableBlockedClasses(resource.children);
|
|
392
|
+
}
|
|
393
|
+
} else {
|
|
394
|
+
array[index].accessMode = 'denied';
|
|
395
|
+
}
|
|
419
396
|
});
|
|
420
|
-
|
|
421
|
-
* clicking on class filter container will
|
|
422
|
-
* stopPropagation to prevent be closed
|
|
423
|
-
* by searchModal.mouseDown listener
|
|
424
|
-
*/
|
|
397
|
+
};
|
|
425
398
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
399
|
+
disableBlockedClasses(classTree.resources);
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Inits template selectors, buttons behaviour, scroll animation,
|
|
403
|
+
* and sets initial search query on search input
|
|
404
|
+
*/
|
|
429
405
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
406
|
+
|
|
407
|
+
function initUiSelectors() {
|
|
408
|
+
$searchButton = $$1('.btn-search', $container);
|
|
409
|
+
$clearButton = $$1('.btn-clear', $container);
|
|
410
|
+
$searchInput = $$1('.generic-search-input', $container);
|
|
411
|
+
$classFilterInput = $$1('.class-filter', $container);
|
|
412
|
+
$classTreeContainer = $$1('.class-tree', $container);
|
|
413
|
+
$classFilterContainer = $$1('.class-filter-container', $container);
|
|
414
|
+
$searchButton.on('click', search);
|
|
415
|
+
$clearButton.on('click', clear);
|
|
416
|
+
var shortcuts = shortcutRegistry($searchInput);
|
|
417
|
+
shortcuts.clear().add('enter', search);
|
|
418
|
+
$searchInput.val(instance.config.criterias && instance.config.criterias.search ? instance.config.criterias.search : '');
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Sets required listeners to properly manage resourceSelector visualization
|
|
422
|
+
*/
|
|
438
423
|
|
|
439
424
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
}
|
|
425
|
+
function setResourceSelectorUIBehaviour() {
|
|
426
|
+
$container.on('mousedown', function () {
|
|
427
|
+
$classTreeContainer.hide();
|
|
428
|
+
});
|
|
445
429
|
/**
|
|
446
|
-
*
|
|
430
|
+
* Pressing space, enter, esc, backspace
|
|
431
|
+
* on class filter input will toggle resource selector
|
|
447
432
|
*/
|
|
448
433
|
|
|
434
|
+
var shortcuts = shortcutRegistry($classFilterInput);
|
|
435
|
+
shortcuts.add('enter', function () {
|
|
436
|
+
return $classTreeContainer.show();
|
|
437
|
+
});
|
|
438
|
+
shortcuts.add('space', function () {
|
|
439
|
+
return $classTreeContainer.show();
|
|
440
|
+
});
|
|
441
|
+
shortcuts.add('backspace', function () {
|
|
442
|
+
return $classTreeContainer.hide();
|
|
443
|
+
});
|
|
444
|
+
shortcuts.add('escape', function () {
|
|
445
|
+
return $classTreeContainer.hide();
|
|
446
|
+
}, {
|
|
447
|
+
propagate: false
|
|
448
|
+
});
|
|
449
|
+
/**
|
|
450
|
+
* clicking on class filter container will toggle resource selector
|
|
451
|
+
*/
|
|
449
452
|
|
|
450
|
-
function
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
const searchHandler = _.throttle(query => {
|
|
455
|
-
if (running === false) {
|
|
456
|
-
running = true;
|
|
457
|
-
$$1.ajax({
|
|
458
|
-
url: instance.config.url,
|
|
459
|
-
type: 'POST',
|
|
460
|
-
data: {
|
|
461
|
-
query: query,
|
|
462
|
-
parentNode: classFilterUri,
|
|
463
|
-
structure: context.shownStructure
|
|
464
|
-
},
|
|
465
|
-
dataType: 'json'
|
|
466
|
-
}).done(data => {
|
|
467
|
-
appendDefaultDatasetToDatatable(data.data).then(() => buildSearchResultsDatatable(data.data)).catch(e => instance.trigger('error', e));
|
|
468
|
-
}).always(() => running = false);
|
|
469
|
-
}
|
|
470
|
-
}, 100);
|
|
471
|
-
|
|
472
|
-
searchHandler(query);
|
|
473
|
-
}
|
|
453
|
+
$classFilterContainer.on('click', function (e) {
|
|
454
|
+
$classTreeContainer.toggle();
|
|
455
|
+
});
|
|
474
456
|
/**
|
|
475
|
-
*
|
|
457
|
+
* clicking on class filter container will
|
|
458
|
+
* stopPropagation to prevent be closed
|
|
459
|
+
* by searchModal.mouseDown listener
|
|
476
460
|
*/
|
|
477
461
|
|
|
462
|
+
$classFilterContainer.on('mousedown', function (e) {
|
|
463
|
+
e.stopPropagation();
|
|
464
|
+
}); // clicking on resource selector will stopPropagation to prevent be closed by searchModal.mouseDown listener
|
|
478
465
|
|
|
479
|
-
function
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
466
|
+
$classTreeContainer.on('mousedown', function (e) {
|
|
467
|
+
e.stopPropagation();
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Loads search store so it is accessible in the component
|
|
472
|
+
* @returns {Promise}
|
|
473
|
+
*/
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
function initSearchStore() {
|
|
477
|
+
return store('search').then(function (store) {
|
|
478
|
+
searchStore = store;
|
|
479
|
+
}).catch(function (e) {
|
|
480
|
+
return instance.trigger('error', e);
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Request search results and manages its results
|
|
485
|
+
*/
|
|
490
486
|
|
|
491
487
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
488
|
+
function search() {
|
|
489
|
+
var query = buildComplexQuery();
|
|
490
|
+
var classFilterUri = isResourceSelector ? $classFilterInput.data('uri').trim() : rootClassUri; //throttle and control to prevent sending too many requests
|
|
491
|
+
|
|
492
|
+
var searchHandler = _.throttle(function (query) {
|
|
493
|
+
if (running === false) {
|
|
494
|
+
running = true;
|
|
495
|
+
$$1.ajax({
|
|
496
|
+
url: instance.config.url,
|
|
497
|
+
type: 'POST',
|
|
498
|
+
data: {
|
|
499
|
+
query: query,
|
|
500
|
+
parentNode: classFilterUri,
|
|
501
|
+
structure: context.shownStructure
|
|
502
|
+
},
|
|
503
|
+
dataType: 'json'
|
|
504
|
+
}).done(function (data) {
|
|
505
|
+
appendDefaultDatasetToDatatable(data.data).then(function () {
|
|
506
|
+
return buildSearchResultsDatatable(data.data);
|
|
507
|
+
}).catch(function (e) {
|
|
508
|
+
return instance.trigger('error', e);
|
|
503
509
|
});
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
/**
|
|
510
|
-
* Creates a datatable with search results
|
|
511
|
-
* @param {object} data - search configuration including model and endpoint for datatable
|
|
512
|
-
*/
|
|
510
|
+
}).always(function () {
|
|
511
|
+
return running = false;
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
}, 100);
|
|
513
515
|
|
|
516
|
+
searchHandler(query);
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* build final complex query appending every filter
|
|
520
|
+
*/
|
|
514
521
|
|
|
515
|
-
function buildSearchResultsDatatable(data) {
|
|
516
|
-
//update the section container
|
|
517
|
-
const $tableContainer = $$1('<div class="flex-container-full"></div>');
|
|
518
|
-
const section = $$1('.content-container', $container);
|
|
519
|
-
section.empty();
|
|
520
|
-
section.append($tableContainer);
|
|
521
|
-
$tableContainer.on('load.datatable', searchResultsLoaded); //create datatable
|
|
522
|
-
|
|
523
|
-
$tableContainer.datatable({
|
|
524
|
-
url: data.url,
|
|
525
|
-
model: _.values(data.model),
|
|
526
|
-
labels: {
|
|
527
|
-
actions: ''
|
|
528
|
-
},
|
|
529
|
-
actions: [{
|
|
530
|
-
id: 'go-to-item',
|
|
531
|
-
label: __('View'),
|
|
532
|
-
action: function openResource(uri, data) {
|
|
533
|
-
instance.trigger('refresh', uri, data);
|
|
534
|
-
instance.destroy();
|
|
535
|
-
}
|
|
536
|
-
}],
|
|
537
|
-
params: {
|
|
538
|
-
params: data.params,
|
|
539
|
-
filters: data.filters,
|
|
540
|
-
rows: 20
|
|
541
|
-
}
|
|
542
|
-
}, data.storedSearchResults);
|
|
543
|
-
}
|
|
544
|
-
/**
|
|
545
|
-
* Triggered on load.datatable event, it updates searchStore and manages possible exceptions
|
|
546
|
-
* @param {object} e - load.datatable event
|
|
547
|
-
* @param {object} dataset - datatable dataset
|
|
548
|
-
*/
|
|
549
522
|
|
|
523
|
+
function buildComplexQuery() {
|
|
524
|
+
var $searchInputValue = $searchInput.val().trim();
|
|
525
|
+
var query = $searchInputValue;
|
|
526
|
+
query += advancedSearch.getAdvancedCriteriaQuery(query !== '');
|
|
527
|
+
return query;
|
|
528
|
+
}
|
|
529
|
+
/*
|
|
530
|
+
* If search on init is not required, extends data with stored dataset
|
|
531
|
+
* @param {object} data - search configuration including model and endpoint for datatable
|
|
532
|
+
* @returns {Promise}
|
|
533
|
+
*/
|
|
550
534
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
535
|
+
|
|
536
|
+
function appendDefaultDatasetToDatatable(data) {
|
|
537
|
+
return new Promise(function (resolve, reject) {
|
|
538
|
+
// If no search on init, get dataset from searchStore
|
|
539
|
+
if (instance.config.searchOnInit === false) {
|
|
540
|
+
searchStore.getItem('results').then(function (storedSearchResults) {
|
|
541
|
+
instance.config.searchOnInit = true;
|
|
542
|
+
data.storedSearchResults = storedSearchResults;
|
|
543
|
+
resolve();
|
|
544
|
+
}).catch(function (e) {
|
|
545
|
+
instance.trigger('error', e);
|
|
546
|
+
reject(new Error('Error appending default dataset from searchStore to datatable'));
|
|
547
|
+
});
|
|
548
|
+
} else {
|
|
549
|
+
resolve();
|
|
554
550
|
}
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Creates a datatable with search results
|
|
555
|
+
* @param {object} data - search configuration including model and endpoint for datatable
|
|
556
|
+
*/
|
|
555
557
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
558
|
+
|
|
559
|
+
function buildSearchResultsDatatable(data) {
|
|
560
|
+
//update the section container
|
|
561
|
+
var $tableContainer = $$1('<div class="flex-container-full"></div>');
|
|
562
|
+
var section = $$1('.content-container', $container);
|
|
563
|
+
section.empty();
|
|
564
|
+
section.append($tableContainer);
|
|
565
|
+
$tableContainer.on('load.datatable', searchResultsLoaded); //create datatable
|
|
566
|
+
|
|
567
|
+
$tableContainer.datatable({
|
|
568
|
+
url: data.url,
|
|
569
|
+
model: _.values(data.model),
|
|
570
|
+
labels: {
|
|
571
|
+
actions: ''
|
|
572
|
+
},
|
|
573
|
+
actions: [{
|
|
574
|
+
id: 'go-to-item',
|
|
575
|
+
label: __('View'),
|
|
576
|
+
action: function openResource(uri, data) {
|
|
577
|
+
instance.trigger('refresh', uri, data);
|
|
578
|
+
instance.destroy();
|
|
565
579
|
}
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
580
|
+
}],
|
|
581
|
+
params: {
|
|
582
|
+
params: data.params,
|
|
583
|
+
filters: data.filters,
|
|
584
|
+
rows: 20
|
|
585
|
+
}
|
|
586
|
+
}, data.storedSearchResults);
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Triggered on load.datatable event, it updates searchStore and manages possible exceptions
|
|
590
|
+
* @param {object} e - load.datatable event
|
|
591
|
+
* @param {object} dataset - datatable dataset
|
|
592
|
+
*/
|
|
574
593
|
|
|
575
594
|
|
|
576
|
-
|
|
577
|
-
|
|
595
|
+
function searchResultsLoaded(e, dataset) {
|
|
596
|
+
if (dataset.records === 0) {
|
|
597
|
+
replaceSearchResultsDatatableWithMessage('no-matches');
|
|
598
|
+
}
|
|
578
599
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
600
|
+
instance.trigger("datatable-loaded");
|
|
601
|
+
updateSearchStore({
|
|
602
|
+
action: 'update',
|
|
603
|
+
dataset: dataset,
|
|
604
|
+
context: context.shownStructure,
|
|
605
|
+
criterias: {
|
|
606
|
+
search: $searchInput.val(),
|
|
607
|
+
class: isResourceSelector ? _.map(resourceSelector.getSelection(), 'uri')[0] : rootClassUri,
|
|
608
|
+
advancedCriteria: advancedSearch.getState()
|
|
585
609
|
}
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Updates searchStore. If action is 'clear', searchStore is claread. If not, received
|
|
614
|
+
* data is assigned to searchStore. Once all actions have been done,
|
|
615
|
+
* store-updated event is triggered
|
|
616
|
+
* @param {object} data - data to store
|
|
617
|
+
*/
|
|
586
618
|
|
|
587
|
-
Promise.all(promises).then(() => instance.trigger(`store-updated`)).catch(e => instance.trigger('error', e));
|
|
588
|
-
}
|
|
589
|
-
/**
|
|
590
|
-
* Clear search input, criteria and results from both, view and store.
|
|
591
|
-
* Also sets every criterion on criteriaState to unredered and
|
|
592
|
-
* undefined value
|
|
593
|
-
*/
|
|
594
619
|
|
|
620
|
+
function updateSearchStore(data) {
|
|
621
|
+
var promises = [];
|
|
595
622
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
action: 'clear'
|
|
603
|
-
});
|
|
623
|
+
if (data.action === 'clear') {
|
|
624
|
+
promises.push(searchStore.clear());
|
|
625
|
+
} else if (data.action === 'update') {
|
|
626
|
+
promises.push(searchStore.setItem('criterias', data.criterias));
|
|
627
|
+
promises.push(searchStore.setItem('context', data.context));
|
|
628
|
+
promises.push(data.dataset.records === 0 ? searchStore.removeItem('results') : searchStore.setItem('results', data.dataset));
|
|
604
629
|
}
|
|
605
|
-
/**
|
|
606
|
-
* Removes datatable container and displays a message instead
|
|
607
|
-
* @param {string} reason - reason why datatable is not rendered, to display appropiate message
|
|
608
|
-
*/
|
|
609
630
|
|
|
631
|
+
Promise.all(promises).then(function () {
|
|
632
|
+
return instance.trigger("store-updated");
|
|
633
|
+
}).catch(function (e) {
|
|
634
|
+
return instance.trigger('error', e);
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Clear search input, criteria and results from both, view and store.
|
|
639
|
+
* Also sets every criterion on criteriaState to unredered and
|
|
640
|
+
* undefined value
|
|
641
|
+
*/
|
|
610
642
|
|
|
611
|
-
function replaceSearchResultsDatatableWithMessage(reason) {
|
|
612
|
-
const section = $$1('.content-container', $container);
|
|
613
|
-
section.empty();
|
|
614
|
-
let message = '';
|
|
615
|
-
let icon = '';
|
|
616
643
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
644
|
+
function clear() {
|
|
645
|
+
$searchInput.val('');
|
|
646
|
+
advancedSearch.clear();
|
|
647
|
+
isResourceSelector && resourceSelector.select(rootClassUri);
|
|
648
|
+
replaceSearchResultsDatatableWithMessage('no-query');
|
|
649
|
+
updateSearchStore({
|
|
650
|
+
action: 'clear'
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Removes datatable container and displays a message instead
|
|
655
|
+
* @param {string} reason - reason why datatable is not rendered, to display appropiate message
|
|
656
|
+
*/
|
|
624
657
|
|
|
625
|
-
const infoMessage = infoMessageTpl({
|
|
626
|
-
message,
|
|
627
|
-
icon
|
|
628
|
-
});
|
|
629
|
-
section.append(infoMessage);
|
|
630
|
-
} // return initialized instance of searchModal
|
|
631
658
|
|
|
659
|
+
function replaceSearchResultsDatatableWithMessage(reason) {
|
|
660
|
+
var section = $$1('.content-container', $container);
|
|
661
|
+
section.empty();
|
|
662
|
+
var message = '';
|
|
663
|
+
var icon = '';
|
|
632
664
|
|
|
633
|
-
|
|
634
|
-
|
|
665
|
+
if (reason === 'no-query') {
|
|
666
|
+
message = __('Please define your search in the search panel.');
|
|
667
|
+
icon = 'icon-find';
|
|
668
|
+
} else if (reason === 'no-matches') {
|
|
669
|
+
message = __('No item found. Please try other search criteria.');
|
|
670
|
+
icon = 'icon-info';
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
var infoMessage = infoMessageTpl({
|
|
674
|
+
message: message,
|
|
675
|
+
icon: icon
|
|
676
|
+
});
|
|
677
|
+
section.append(infoMessage);
|
|
678
|
+
} // return initialized instance of searchModal
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
return instance.init(config);
|
|
682
|
+
}
|
|
635
683
|
|
|
636
|
-
|
|
684
|
+
return searchModalFactory;
|
|
637
685
|
|
|
638
686
|
});
|