@girder/core 5.0.0-beta.1 → 5.0.0-beta.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-lib/Girder_Favicon.png +0 -0
- package/dist-lib/Girder_Mark.png +0 -0
- package/dist-lib/girder-core.js +48560 -0
- package/dist-lib/girder-core.js.map +1 -0
- package/dist-lib/girder-core.umd.cjs +630 -0
- package/dist-lib/girder-core.umd.cjs.map +1 -0
- package/dist-lib/index.d.ts +1 -0
- package/dist-lib/src/auth.js +112 -0
- package/dist-lib/src/collections/ApiKeyCollection.js +9 -0
- package/dist-lib/src/collections/AssetstoreCollection.js +9 -0
- package/dist-lib/src/collections/Collection.js +295 -0
- package/dist-lib/src/collections/CollectionCollection.js +9 -0
- package/dist-lib/src/collections/FileCollection.js +11 -0
- package/dist-lib/src/collections/FolderCollection.js +11 -0
- package/dist-lib/src/collections/GroupCollection.js +9 -0
- package/dist-lib/src/collections/ItemCollection.js +11 -0
- package/dist-lib/src/collections/UserCollection.js +24 -0
- package/dist-lib/src/collections/index.js +21 -0
- package/dist-lib/src/constants.js +32 -0
- package/dist-lib/src/dialog.js +128 -0
- package/dist-lib/src/events.js +6 -0
- package/dist-lib/src/index.d.ts +23 -0
- package/dist-lib/src/index.ts +80 -0
- package/dist-lib/src/main.ts +45 -0
- package/dist-lib/src/misc.js +260 -0
- package/dist-lib/src/models/AccessControlledModel.js +76 -0
- package/dist-lib/src/models/ApiKeyModel.js +31 -0
- package/dist-lib/src/models/AssetstoreModel.js +43 -0
- package/dist-lib/src/models/CollectionCreationPolicyModel.js +20 -0
- package/dist-lib/src/models/CollectionModel.js +12 -0
- package/dist-lib/src/models/FileModel.js +310 -0
- package/dist-lib/src/models/FolderModel.js +33 -0
- package/dist-lib/src/models/GroupModel.js +197 -0
- package/dist-lib/src/models/ItemModel.js +72 -0
- package/dist-lib/src/models/MetadataMixin.js +88 -0
- package/dist-lib/src/models/Model.js +187 -0
- package/dist-lib/src/models/UserModel.js +189 -0
- package/dist-lib/src/models/index.js +25 -0
- package/dist-lib/src/pluginUtils.js +11 -0
- package/dist-lib/src/rest.js +221 -0
- package/dist-lib/src/router.js +58 -0
- package/dist-lib/src/routes.js +229 -0
- package/dist-lib/src/stylesheets/apidocs/apidocs.styl +50 -0
- package/dist-lib/src/stylesheets/body/adminConsole.styl +21 -0
- package/dist-lib/src/stylesheets/body/assetstores.styl +46 -0
- package/dist-lib/src/stylesheets/body/collectionList.styl +39 -0
- package/dist-lib/src/stylesheets/body/collectionPage.styl +6 -0
- package/dist-lib/src/stylesheets/body/frontPage.styl +48 -0
- package/dist-lib/src/stylesheets/body/groupList.styl +43 -0
- package/dist-lib/src/stylesheets/body/groupPage.styl +116 -0
- package/dist-lib/src/stylesheets/body/itemPage.styl +81 -0
- package/dist-lib/src/stylesheets/body/plugins.styl +61 -0
- package/dist-lib/src/stylesheets/body/searchResultsList.styl +51 -0
- package/dist-lib/src/stylesheets/body/systemConfig.styl +56 -0
- package/dist-lib/src/stylesheets/body/userAccount.styl +57 -0
- package/dist-lib/src/stylesheets/body/userList.styl +79 -0
- package/dist-lib/src/stylesheets/body/userPage.styl +6 -0
- package/dist-lib/src/stylesheets/layout/footer.styl +19 -0
- package/dist-lib/src/stylesheets/layout/global.styl +154 -0
- package/dist-lib/src/stylesheets/layout/globalNav.styl +89 -0
- package/dist-lib/src/stylesheets/layout/header.styl +29 -0
- package/dist-lib/src/stylesheets/layout/headerUser.styl +33 -0
- package/dist-lib/src/stylesheets/layout/layout.styl +75 -0
- package/dist-lib/src/stylesheets/layout/layoutVars.styl +9 -0
- package/dist-lib/src/stylesheets/layout/loading.styl +37 -0
- package/dist-lib/src/stylesheets/layout/progressArea.styl +17 -0
- package/dist-lib/src/stylesheets/widgets/accessWidget.styl +106 -0
- package/dist-lib/src/stylesheets/widgets/browserWidget.styl +9 -0
- package/dist-lib/src/stylesheets/widgets/hierarchyWidget.styl +188 -0
- package/dist-lib/src/stylesheets/widgets/markdownWidget.styl +92 -0
- package/dist-lib/src/stylesheets/widgets/metadataWidget.styl +92 -0
- package/dist-lib/src/stylesheets/widgets/searchFieldWidget.styl +70 -0
- package/dist-lib/src/stylesheets/widgets/taskProgress.styl +41 -0
- package/dist-lib/src/stylesheets/widgets/timelineWidget.styl +41 -0
- package/dist-lib/src/stylesheets/widgets/uploadWidget.styl +43 -0
- package/dist-lib/src/stylesheets/widgets/userOtpManagementWidget.styl +159 -0
- package/dist-lib/src/templates/body/adminConsole.pug +13 -0
- package/dist-lib/src/templates/body/assetstores.pug +83 -0
- package/dist-lib/src/templates/body/collectionList.pug +40 -0
- package/dist-lib/src/templates/body/collectionPage.pug +36 -0
- package/dist-lib/src/templates/body/filesystemImport.pug +41 -0
- package/dist-lib/src/templates/body/frontPage.pug +84 -0
- package/dist-lib/src/templates/body/groupList.pug +30 -0
- package/dist-lib/src/templates/body/groupPage.pug +116 -0
- package/dist-lib/src/templates/body/itemPage.pug +61 -0
- package/dist-lib/src/templates/body/plugins.pug +20 -0
- package/dist-lib/src/templates/body/s3Import.pug +35 -0
- package/dist-lib/src/templates/body/searchResults.pug +15 -0
- package/dist-lib/src/templates/body/searchResultsType.pug +13 -0
- package/dist-lib/src/templates/body/systemConfiguration.pug +199 -0
- package/dist-lib/src/templates/body/userAccount.pug +83 -0
- package/dist-lib/src/templates/body/userList.pug +43 -0
- package/dist-lib/src/templates/body/userPage.pug +40 -0
- package/dist-lib/src/templates/layout/alert.pug +5 -0
- package/dist-lib/src/templates/layout/layout.pug +12 -0
- package/dist-lib/src/templates/layout/layoutFooter.pug +11 -0
- package/dist-lib/src/templates/layout/layoutGlobalNav.pug +7 -0
- package/dist-lib/src/templates/layout/layoutHeader.pug +8 -0
- package/dist-lib/src/templates/layout/layoutHeaderUser.pug +26 -0
- package/dist-lib/src/templates/layout/layoutProgressArea.pug +1 -0
- package/dist-lib/src/templates/layout/loginDialog.pug +30 -0
- package/dist-lib/src/templates/layout/registerDialog.pug +35 -0
- package/dist-lib/src/templates/layout/resetPasswordDialog.pug +25 -0
- package/dist-lib/src/templates/widgets/accessEditor.pug +23 -0
- package/dist-lib/src/templates/widgets/accessEditorMixins.pug +57 -0
- package/dist-lib/src/templates/widgets/accessEditorNonModal.pug +11 -0
- package/dist-lib/src/templates/widgets/accessEntry.pug +32 -0
- package/dist-lib/src/templates/widgets/apiKeyList.pug +50 -0
- package/dist-lib/src/templates/widgets/browserWidget.pug +32 -0
- package/dist-lib/src/templates/widgets/checkedActionsMenu.pug +46 -0
- package/dist-lib/src/templates/widgets/collectionInfoDialog.pug +37 -0
- package/dist-lib/src/templates/widgets/confirmDialog.pug +14 -0
- package/dist-lib/src/templates/widgets/dateTimeRangeWidget.pug +20 -0
- package/dist-lib/src/templates/widgets/dateTimeWidget.pug +8 -0
- package/dist-lib/src/templates/widgets/editApiKeyWidget.pug +43 -0
- package/dist-lib/src/templates/widgets/editAssetstoreWidget.pug +66 -0
- package/dist-lib/src/templates/widgets/editCollectionWidget.pug +27 -0
- package/dist-lib/src/templates/widgets/editFileWidget.pug +21 -0
- package/dist-lib/src/templates/widgets/editFolderWidget.pug +27 -0
- package/dist-lib/src/templates/widgets/editGroupWidget.pug +54 -0
- package/dist-lib/src/templates/widgets/editItemWidget.pug +27 -0
- package/dist-lib/src/templates/widgets/fileInfoDialog.pug +33 -0
- package/dist-lib/src/templates/widgets/fileList.pug +33 -0
- package/dist-lib/src/templates/widgets/folderInfoDialog.pug +42 -0
- package/dist-lib/src/templates/widgets/folderList.pug +21 -0
- package/dist-lib/src/templates/widgets/groupAdminList.pug +33 -0
- package/dist-lib/src/templates/widgets/groupInviteDialog.pug +76 -0
- package/dist-lib/src/templates/widgets/groupInviteList.pug +14 -0
- package/dist-lib/src/templates/widgets/groupMemberList.pug +39 -0
- package/dist-lib/src/templates/widgets/groupModList.pug +23 -0
- package/dist-lib/src/templates/widgets/hierarchyBreadcrumb.pug +37 -0
- package/dist-lib/src/templates/widgets/hierarchyPaginated.pug +19 -0
- package/dist-lib/src/templates/widgets/hierarchyWidget.pug +96 -0
- package/dist-lib/src/templates/widgets/itemBreadcrumb.pug +16 -0
- package/dist-lib/src/templates/widgets/itemList.pug +27 -0
- package/dist-lib/src/templates/widgets/jsonMetadatumEditWidget.pug +13 -0
- package/dist-lib/src/templates/widgets/jsonMetadatumView.pug +6 -0
- package/dist-lib/src/templates/widgets/loadingAnimation.pug +4 -0
- package/dist-lib/src/templates/widgets/markdownWidget.pug +34 -0
- package/dist-lib/src/templates/widgets/metadataWidget.pug +16 -0
- package/dist-lib/src/templates/widgets/metadatumEditWidget.pug +15 -0
- package/dist-lib/src/templates/widgets/metadatumView.pug +5 -0
- package/dist-lib/src/templates/widgets/newAssetstore.pug +83 -0
- package/dist-lib/src/templates/widgets/paginateWidget.pug +7 -0
- package/dist-lib/src/templates/widgets/pluginConfigBreadcrumb.pug +13 -0
- package/dist-lib/src/templates/widgets/rootSelectorWidget.pug +13 -0
- package/dist-lib/src/templates/widgets/searchField.pug +10 -0
- package/dist-lib/src/templates/widgets/searchHelp.pug +12 -0
- package/dist-lib/src/templates/widgets/searchModeSelect.pug +9 -0
- package/dist-lib/src/templates/widgets/searchResults.pug +14 -0
- package/dist-lib/src/templates/widgets/sortCollectionWidget.pug +14 -0
- package/dist-lib/src/templates/widgets/taskProgress.pug +16 -0
- package/dist-lib/src/templates/widgets/timeline.pug +15 -0
- package/dist-lib/src/templates/widgets/uploadWidget.pug +15 -0
- package/dist-lib/src/templates/widgets/uploadWidgetMixins.pug +31 -0
- package/dist-lib/src/templates/widgets/uploadWidgetNonModal.pug +10 -0
- package/dist-lib/src/templates/widgets/userOtpBegin.pug +4 -0
- package/dist-lib/src/templates/widgets/userOtpDisable.pug +6 -0
- package/dist-lib/src/templates/widgets/userOtpEnable.pug +44 -0
- package/dist-lib/src/utilities/EventStream.js +177 -0
- package/dist-lib/src/utilities/PluginUtils.js +36 -0
- package/dist-lib/src/utilities/S3UploadHandler.js +303 -0
- package/dist-lib/src/utilities/index.js +9 -0
- package/dist-lib/src/utilities/jquery/girderEnable.js +19 -0
- package/dist-lib/src/utilities/jquery/girderModal.js +48 -0
- package/dist-lib/src/version.js +6 -0
- package/dist-lib/src/views/App.js +359 -0
- package/dist-lib/src/views/View.js +79 -0
- package/dist-lib/src/views/body/AdminView.js +29 -0
- package/dist-lib/src/views/body/AssetstoresView.js +234 -0
- package/dist-lib/src/views/body/CollectionView.js +188 -0
- package/dist-lib/src/views/body/CollectionsView.js +120 -0
- package/dist-lib/src/views/body/FilesystemImportView.js +83 -0
- package/dist-lib/src/views/body/FolderView.js +54 -0
- package/dist-lib/src/views/body/FrontPageView.js +47 -0
- package/dist-lib/src/views/body/GroupView.js +336 -0
- package/dist-lib/src/views/body/GroupsView.js +106 -0
- package/dist-lib/src/views/body/ItemView.js +177 -0
- package/dist-lib/src/views/body/PluginsView.js +73 -0
- package/dist-lib/src/views/body/S3ImportView.js +80 -0
- package/dist-lib/src/views/body/SearchResultsView.js +162 -0
- package/dist-lib/src/views/body/SystemConfigurationView.js +182 -0
- package/dist-lib/src/views/body/UserAccountView.js +179 -0
- package/dist-lib/src/views/body/UserView.js +165 -0
- package/dist-lib/src/views/body/UsersView.js +124 -0
- package/dist-lib/src/views/body/index.js +37 -0
- package/dist-lib/src/views/index.js +13 -0
- package/dist-lib/src/views/layout/FooterView.js +29 -0
- package/dist-lib/src/views/layout/GlobalNavView.js +103 -0
- package/dist-lib/src/views/layout/HeaderUserView.js +45 -0
- package/dist-lib/src/views/layout/HeaderView.js +83 -0
- package/dist-lib/src/views/layout/LoginView.js +100 -0
- package/dist-lib/src/views/layout/ProgressListView.js +70 -0
- package/dist-lib/src/views/layout/RegisterView.js +101 -0
- package/dist-lib/src/views/layout/ResetPasswordView.js +70 -0
- package/dist-lib/src/views/layout/index.js +19 -0
- package/dist-lib/src/views/widgets/AccessWidget.js +427 -0
- package/dist-lib/src/views/widgets/ApiKeyListWidget.js +140 -0
- package/dist-lib/src/views/widgets/BrowserWidget.js +317 -0
- package/dist-lib/src/views/widgets/CheckedMenuWidget.js +68 -0
- package/dist-lib/src/views/widgets/CollectionInfoWidget.js +40 -0
- package/dist-lib/src/views/widgets/DateTimeRangeWidget.js +180 -0
- package/dist-lib/src/views/widgets/DateTimeWidget.js +110 -0
- package/dist-lib/src/views/widgets/EditApiKeyWidget.js +122 -0
- package/dist-lib/src/views/widgets/EditAssetstoreWidget.js +133 -0
- package/dist-lib/src/views/widgets/EditCollectionWidget.js +93 -0
- package/dist-lib/src/views/widgets/EditFileWidget.js +56 -0
- package/dist-lib/src/views/widgets/EditFolderWidget.js +116 -0
- package/dist-lib/src/views/widgets/EditGroupWidget.js +125 -0
- package/dist-lib/src/views/widgets/EditItemWidget.js +110 -0
- package/dist-lib/src/views/widgets/FileInfoWidget.js +26 -0
- package/dist-lib/src/views/widgets/FileListWidget.js +151 -0
- package/dist-lib/src/views/widgets/FolderInfoWidget.js +39 -0
- package/dist-lib/src/views/widgets/FolderListWidget.js +106 -0
- package/dist-lib/src/views/widgets/GroupAdminsWidget.js +88 -0
- package/dist-lib/src/views/widgets/GroupInvitesWidget.js +56 -0
- package/dist-lib/src/views/widgets/GroupMembersWidget.js +185 -0
- package/dist-lib/src/views/widgets/GroupModsWidget.js +77 -0
- package/dist-lib/src/views/widgets/HierarchyWidget.js +1097 -0
- package/dist-lib/src/views/widgets/ItemBreadcrumbWidget.js +38 -0
- package/dist-lib/src/views/widgets/ItemListWidget.js +345 -0
- package/dist-lib/src/views/widgets/LoadingAnimation.js +17 -0
- package/dist-lib/src/views/widgets/MarkdownWidget.js +217 -0
- package/dist-lib/src/views/widgets/MetadataWidget.js +508 -0
- package/dist-lib/src/views/widgets/NewAssetstoreWidget.js +71 -0
- package/dist-lib/src/views/widgets/PaginateWidget.js +37 -0
- package/dist-lib/src/views/widgets/PluginConfigBreadcrumbWidget.js +33 -0
- package/dist-lib/src/views/widgets/RootSelectorWidget.js +192 -0
- package/dist-lib/src/views/widgets/SearchFieldWidget.js +365 -0
- package/dist-lib/src/views/widgets/SearchPaginateWidget.js +149 -0
- package/dist-lib/src/views/widgets/SortCollectionWidget.js +53 -0
- package/dist-lib/src/views/widgets/TaskProgressWidget.js +91 -0
- package/dist-lib/src/views/widgets/TimelineWidget.js +155 -0
- package/dist-lib/src/views/widgets/UploadWidget.js +340 -0
- package/dist-lib/src/views/widgets/UserOtpManagementWidget.js +105 -0
- package/dist-lib/src/views/widgets/index.js +75 -0
- package/dist-lib/src/vite-env.d.ts +5 -0
- package/dist-lib/style.css +16 -0
- package/package.json +1 -1
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import _ from 'underscore';
|
|
2
|
+
|
|
3
|
+
import CollectionCollection from '@girder/core/collections/CollectionCollection';
|
|
4
|
+
import UserCollection from '@girder/core/collections/UserCollection';
|
|
5
|
+
import View from '@girder/core/views/View';
|
|
6
|
+
import events from '@girder/core/events';
|
|
7
|
+
import { getCurrentUser } from '@girder/core/auth';
|
|
8
|
+
|
|
9
|
+
import RootSelectorWidgetTemplate from '@girder/core/templates/widgets/rootSelectorWidget.pug';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* This widget creates a dropdown box allowing the user to select
|
|
13
|
+
* "root" paths for a hierarchy widget.
|
|
14
|
+
*
|
|
15
|
+
* @emits RootSelectorWidget#g:selected The selected element changed
|
|
16
|
+
* @type {object}
|
|
17
|
+
* @property {Model|null} root The selected root model
|
|
18
|
+
* @property {string|null} group The selection group
|
|
19
|
+
*
|
|
20
|
+
* @emits RootSelectorWidget#g:group A collection group was updated
|
|
21
|
+
* @type {object}
|
|
22
|
+
* @property {Collection} collection
|
|
23
|
+
*/
|
|
24
|
+
var RootSelectorWidget = View.extend({
|
|
25
|
+
events: {
|
|
26
|
+
'change #g-root-selector': '_selectRoot'
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Initialize the widget. The caller can configure the list of items
|
|
31
|
+
* that are present in the select box. If no values are given, then
|
|
32
|
+
* appropriate rest calls will be made to fetch models automatically.
|
|
33
|
+
*
|
|
34
|
+
* Additional categories of roots can be provided via an object mapping,
|
|
35
|
+
* for example:
|
|
36
|
+
*
|
|
37
|
+
* {
|
|
38
|
+
* friends: new UserCollection([...]),
|
|
39
|
+
* saved: new FolderCollection([...])
|
|
40
|
+
* }
|
|
41
|
+
*
|
|
42
|
+
* Only a single page of results are displayed for each collection provided.
|
|
43
|
+
* The default maximum number can be configured, but for more sophisticated
|
|
44
|
+
* behavior, the caller should act on the collection objects directly and
|
|
45
|
+
* rerender.
|
|
46
|
+
*
|
|
47
|
+
* @param {object} settings
|
|
48
|
+
* @param {UserModel} [settings.home=getCurrentUser()]
|
|
49
|
+
* @param {object} [settings.groups] Additional collection groups to add
|
|
50
|
+
* @param {number} [settings.pageLimit=25] The maximum number of models to fetch
|
|
51
|
+
* @param {Model} [settings.selected] The default/current selection
|
|
52
|
+
* @param {string[]} [settings.display=['Home', 'Collections', 'Users'] Display order
|
|
53
|
+
* @param {boolean} [settings.reset=true] Always fetch from offset 0
|
|
54
|
+
* @param {Model|string} [settings.selectByResource] use the baseParentId to
|
|
55
|
+
* set the default selected item, can use a model based like an object, or a specific string ParentId
|
|
56
|
+
*
|
|
57
|
+
*/
|
|
58
|
+
initialize: function (settings) {
|
|
59
|
+
settings = settings || {};
|
|
60
|
+
|
|
61
|
+
this.pageLimit = settings.pageLimit || 25;
|
|
62
|
+
|
|
63
|
+
// collections are provided for public access here
|
|
64
|
+
this.groups = {
|
|
65
|
+
Collections: new CollectionCollection(),
|
|
66
|
+
Users: new UserCollection()
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
this.groups.Collections.pageLimit = settings.pageLimit;
|
|
70
|
+
this.groups.Users.pageLimit = settings.pageLimit;
|
|
71
|
+
this.groups.Users.sortField = 'login';
|
|
72
|
+
|
|
73
|
+
// override default selection groups
|
|
74
|
+
_.extend(this.groups, settings.groups);
|
|
75
|
+
|
|
76
|
+
// attach collection change events
|
|
77
|
+
_.each(this.groups, (group) => {
|
|
78
|
+
this.listenTo(group, 'g:changed', () => {
|
|
79
|
+
this._updateGroup(group);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// possible values that determine rendered behavior for "Home":
|
|
84
|
+
// - model: show this model as Home
|
|
85
|
+
// - undefined|null: use getCurrentUser()
|
|
86
|
+
this.home = settings.home;
|
|
87
|
+
|
|
88
|
+
// we need to fetch the collections and rerender on login
|
|
89
|
+
this.listenTo(events, 'g:login', this.fetch);
|
|
90
|
+
|
|
91
|
+
this.selected = settings.selected;
|
|
92
|
+
this.selectByResource = settings.selectByResource;
|
|
93
|
+
this.display = settings.display || ['Home', 'Collections', 'Users'];
|
|
94
|
+
|
|
95
|
+
this.fetch();
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
render: function () {
|
|
99
|
+
this._home = this.home || getCurrentUser();
|
|
100
|
+
// Set the selected item if it is already defined and get it by resource if not
|
|
101
|
+
if (this.selectByResource) {
|
|
102
|
+
this.setRootByBaseParent(this.selectByResource);
|
|
103
|
+
}
|
|
104
|
+
this.$el.html(
|
|
105
|
+
RootSelectorWidgetTemplate({
|
|
106
|
+
home: this._home,
|
|
107
|
+
groups: this.groups,
|
|
108
|
+
display: this.display,
|
|
109
|
+
selected: this.selected,
|
|
110
|
+
format: this._formatName
|
|
111
|
+
})
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return this;
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
setRootByBaseParent: function (baseParentId) {
|
|
118
|
+
// Filter for an Id String from an object if given
|
|
119
|
+
if (_.isObject(baseParentId)) {
|
|
120
|
+
if ((baseParentId.attributes || {}).baseParentId !== undefined) {
|
|
121
|
+
baseParentId = baseParentId.attributes.baseParentId;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (_.isString(baseParentId)) {
|
|
126
|
+
_.each(this.groups, (group) => {
|
|
127
|
+
if (group.get(baseParentId) !== undefined) {
|
|
128
|
+
this.selected = group.get(baseParentId);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Called when the user selects a new item. Resolves the
|
|
136
|
+
* model object from the DOM and triggers the g:selected event.
|
|
137
|
+
*/
|
|
138
|
+
_selectRoot: function () {
|
|
139
|
+
var sel = this.$(':selected');
|
|
140
|
+
var id = sel.val();
|
|
141
|
+
var group = sel.data('group') || null;
|
|
142
|
+
this.selected = null;
|
|
143
|
+
if (_.has(this.groups, group)) {
|
|
144
|
+
this.selected = this.groups[group].get(id);
|
|
145
|
+
} else if (this._home && this._home.id === id) {
|
|
146
|
+
this.selected = this._home;
|
|
147
|
+
}
|
|
148
|
+
this.trigger('g:selected', {
|
|
149
|
+
root: this.selected,
|
|
150
|
+
group: group
|
|
151
|
+
});
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Called when a collection is modified... rerenders the view.
|
|
156
|
+
*/
|
|
157
|
+
_updateGroup: function (collection) {
|
|
158
|
+
this.trigger('g:group', {
|
|
159
|
+
collection: collection
|
|
160
|
+
});
|
|
161
|
+
this.render();
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Return a string to display for the given model.
|
|
166
|
+
*/
|
|
167
|
+
_formatName: function (model) {
|
|
168
|
+
var name = model.id;
|
|
169
|
+
switch (model.get('_modelType')) {
|
|
170
|
+
case 'user':
|
|
171
|
+
name = model.get('login');
|
|
172
|
+
break;
|
|
173
|
+
case 'folder':
|
|
174
|
+
case 'collection':
|
|
175
|
+
name = model.get('name');
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
return name;
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Fetch all collections from the server.
|
|
183
|
+
*/
|
|
184
|
+
fetch: function () {
|
|
185
|
+
var reset = this.reset;
|
|
186
|
+
_.each(this.groups, function (collection) {
|
|
187
|
+
collection.fetch(null, reset);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
export default RootSelectorWidget;
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import $ from 'jquery';
|
|
2
|
+
import _ from 'underscore';
|
|
3
|
+
// Bootstrap tooltip is required by popover
|
|
4
|
+
import 'bootstrap/js/tooltip';
|
|
5
|
+
import 'bootstrap/js/popover';
|
|
6
|
+
|
|
7
|
+
import View from '@girder/core/views/View';
|
|
8
|
+
import { restRequest } from '@girder/core/rest';
|
|
9
|
+
import router from '@girder/core/router';
|
|
10
|
+
|
|
11
|
+
import SearchFieldTemplate from '@girder/core/templates/widgets/searchField.pug';
|
|
12
|
+
import SearchHelpTemplate from '@girder/core/templates/widgets/searchHelp.pug';
|
|
13
|
+
import SearchModeSelectTemplate from '@girder/core/templates/widgets/searchModeSelect.pug';
|
|
14
|
+
import SearchResultsTemplate from '@girder/core/templates/widgets/searchResults.pug';
|
|
15
|
+
import '@girder/core/stylesheets/widgets/searchFieldWidget.styl';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* This widget provides a text field that will search any set of data types
|
|
19
|
+
* and show matching results as the user types. Results can be clicked,
|
|
20
|
+
* triggering a callback.
|
|
21
|
+
*/
|
|
22
|
+
var SearchFieldWidget = View.extend({
|
|
23
|
+
events: {
|
|
24
|
+
'input .g-search-field': 'search',
|
|
25
|
+
|
|
26
|
+
'click .g-search-mode-radio': function (e) {
|
|
27
|
+
this.currentMode = $(e.target).val();
|
|
28
|
+
this.hideResults().search();
|
|
29
|
+
|
|
30
|
+
window.setTimeout(() => {
|
|
31
|
+
this.$('.g-search-mode-choose').popover('hide');
|
|
32
|
+
}, 250);
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
'click .g-search-result>a': function (e) {
|
|
36
|
+
this._resultClicked($(e.currentTarget));
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
'keydown .g-search-field': function (e) {
|
|
40
|
+
var code = e.keyCode || e.which;
|
|
41
|
+
var list, pos;
|
|
42
|
+
if (code === 13 && this.noResourceSelected) { /* enter without resource seleted */
|
|
43
|
+
e.preventDefault();
|
|
44
|
+
if (this.$('.g-search-field').val() !== '' && !this.noResultsPage) {
|
|
45
|
+
this._goToResultPage(this.$('.g-search-field').val(), this.currentMode);
|
|
46
|
+
}
|
|
47
|
+
} else if (code === 40 || code === 38) {
|
|
48
|
+
this.noResourceSelected = false;
|
|
49
|
+
if (code === 40) { /* down arrow */
|
|
50
|
+
list = this.$('.g-search-result');
|
|
51
|
+
pos = list.index(list.filter('.g-search-selected')) + 1;
|
|
52
|
+
list.removeClass('g-search-selected');
|
|
53
|
+
if (pos < list.length) {
|
|
54
|
+
list.eq(pos).addClass('g-search-selected');
|
|
55
|
+
}
|
|
56
|
+
if (pos === list.length) {
|
|
57
|
+
this.noResourceSelected = true;
|
|
58
|
+
}
|
|
59
|
+
} else if (code === 38) { /* up arrow */
|
|
60
|
+
list = this.$('.g-search-result');
|
|
61
|
+
pos = list.index(list.filter('.g-search-selected')) - 1;
|
|
62
|
+
list.removeClass('g-search-selected');
|
|
63
|
+
if (pos === -1) {
|
|
64
|
+
this.noResourceSelected = true;
|
|
65
|
+
}
|
|
66
|
+
if (pos === -2) {
|
|
67
|
+
pos = list.length - 1;
|
|
68
|
+
}
|
|
69
|
+
if (pos >= 0) {
|
|
70
|
+
list.eq(pos).addClass('g-search-selected');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} else if (code === 13) { /* enter with resource selected */
|
|
74
|
+
e.preventDefault();
|
|
75
|
+
this.noResourceSelected = true;
|
|
76
|
+
var link = this.$('.g-search-result.g-search-selected>a');
|
|
77
|
+
if (link.length) {
|
|
78
|
+
this._resultClicked(link);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @param [settings.placeholder="Search..."] The placeholder text for the input field.
|
|
86
|
+
* @param [settings.getInfoCallback] For custom resource types, this callback can
|
|
87
|
+
* be passed in to resolve their title and icon. This callback should
|
|
88
|
+
* return an object with "icon" and "text" fields if it can resolve
|
|
89
|
+
* the result, or return falsy otherwise.
|
|
90
|
+
* @param [settings.modes=["text", "prefix"]] A string or list of strings
|
|
91
|
+
* representing the allowed search modes. Supported modes: "text", "prefix".
|
|
92
|
+
* If multiple are allowed, users are able to select which one to use
|
|
93
|
+
* via a dropdown.
|
|
94
|
+
* @param [settings.noResultsPage=false] If truthy, don't jump to a results
|
|
95
|
+
* page if enter is typed with a list of search results.
|
|
96
|
+
*/
|
|
97
|
+
initialize: function (settings) {
|
|
98
|
+
this.ajaxLock = false;
|
|
99
|
+
this.pending = null;
|
|
100
|
+
this.noResourceSelected = true;
|
|
101
|
+
this.placeholder = settings.placeholder || 'Search...';
|
|
102
|
+
this.noResultsPage = settings.noResultsPage || false;
|
|
103
|
+
this.getInfoCallback = settings.getInfoCallback || null;
|
|
104
|
+
/* The order of settings.types give the order of the display of the elements :
|
|
105
|
+
* ['collection', 'folder', 'item'] will be render like this
|
|
106
|
+
* [icon-collection] Collections..
|
|
107
|
+
* [icon-folder] Folders..
|
|
108
|
+
* [icon-item] Items..
|
|
109
|
+
*/
|
|
110
|
+
this.types = settings.types || [];
|
|
111
|
+
this.modes = settings.modes || SearchFieldWidget.getModes();
|
|
112
|
+
|
|
113
|
+
if (!_.isArray(this.modes)) {
|
|
114
|
+
this.modes = [this.modes];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
this.currentMode = this.modes[0];
|
|
118
|
+
|
|
119
|
+
// Do not change the icon for fast searches, to prevent jitter
|
|
120
|
+
this._animatePending = _.debounce(this._animatePending, 100);
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
search: function () {
|
|
124
|
+
var q = this.$('.g-search-field').val();
|
|
125
|
+
|
|
126
|
+
if (!q) {
|
|
127
|
+
this.hideResults();
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (this.ajaxLock) {
|
|
132
|
+
this.pending = q;
|
|
133
|
+
} else {
|
|
134
|
+
this._doSearch(q);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return this;
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
_goToResultPage: function (query, mode) {
|
|
141
|
+
this.resetState();
|
|
142
|
+
router.navigate(`#search/results?query=${query}&mode=${mode}`, { trigger: true });
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
_resultClicked: function (link) {
|
|
146
|
+
if (link.data('resourceType') === 'resultPage') {
|
|
147
|
+
this._goToResultPage(this.$('.g-search-field').val(), this.currentMode);
|
|
148
|
+
} else {
|
|
149
|
+
this.trigger('g:resultClicked', {
|
|
150
|
+
type: link.data('resourceType'),
|
|
151
|
+
id: link.data('resourceId'),
|
|
152
|
+
text: link.text().trim(),
|
|
153
|
+
icon: link.data('resourceIcon')
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
render: function () {
|
|
159
|
+
this.$el.html(SearchFieldTemplate({
|
|
160
|
+
placeholder: this.placeholder,
|
|
161
|
+
modes: this.modes,
|
|
162
|
+
currentMode: this.currentMode
|
|
163
|
+
}));
|
|
164
|
+
|
|
165
|
+
this.$('.g-search-options-button').popover({
|
|
166
|
+
trigger: 'manual',
|
|
167
|
+
viewport: {
|
|
168
|
+
selector: 'body',
|
|
169
|
+
padding: 10
|
|
170
|
+
},
|
|
171
|
+
content: () => {
|
|
172
|
+
return SearchHelpTemplate({
|
|
173
|
+
mode: this.currentMode,
|
|
174
|
+
modeHelp: SearchFieldWidget.getModeHelp(this.currentMode)
|
|
175
|
+
});
|
|
176
|
+
},
|
|
177
|
+
html: true,
|
|
178
|
+
sanitize: false
|
|
179
|
+
}).on('click', function () {
|
|
180
|
+
$(this).popover('toggle');
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
this.$('.g-search-mode-choose').popover({
|
|
184
|
+
trigger: 'manual',
|
|
185
|
+
viewport: {
|
|
186
|
+
selector: 'body',
|
|
187
|
+
padding: 10
|
|
188
|
+
},
|
|
189
|
+
content: () => {
|
|
190
|
+
return SearchModeSelectTemplate({
|
|
191
|
+
modes: this.modes,
|
|
192
|
+
currentMode: this.currentMode,
|
|
193
|
+
getModeDescription: SearchFieldWidget.getModeDescription
|
|
194
|
+
});
|
|
195
|
+
},
|
|
196
|
+
html: true,
|
|
197
|
+
sanitize: false
|
|
198
|
+
}).on('click', function () {
|
|
199
|
+
$(this).popover('toggle');
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
return this;
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Parent views should call this if they wish to hide the result list.
|
|
207
|
+
*/
|
|
208
|
+
hideResults: function () {
|
|
209
|
+
this.$('.dropdown').removeClass('open');
|
|
210
|
+
return this;
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Parent views should call this if they wish to clear the search text.
|
|
215
|
+
*/
|
|
216
|
+
clearText: function () {
|
|
217
|
+
this.$('.g-search-field').val('');
|
|
218
|
+
return this;
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Parent views should call this if they wish to reset the search widget,
|
|
223
|
+
* i.e. clear it and hide any results.
|
|
224
|
+
*/
|
|
225
|
+
resetState: function () {
|
|
226
|
+
return this.hideResults().clearText();
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
_animatePending: function () {
|
|
230
|
+
const isPending = this.ajaxLock;
|
|
231
|
+
this.$('.g-search-state')
|
|
232
|
+
.toggleClass('icon-search', !isPending)
|
|
233
|
+
.toggleClass('icon-spin4 animate-spin', isPending);
|
|
234
|
+
},
|
|
235
|
+
|
|
236
|
+
_doSearch: function (q) {
|
|
237
|
+
this.ajaxLock = true;
|
|
238
|
+
this.pending = null;
|
|
239
|
+
this._animatePending();
|
|
240
|
+
|
|
241
|
+
restRequest({
|
|
242
|
+
url: 'resource/search',
|
|
243
|
+
data: {
|
|
244
|
+
q: q,
|
|
245
|
+
mode: this.currentMode,
|
|
246
|
+
types: JSON.stringify(_.intersection(
|
|
247
|
+
this.types,
|
|
248
|
+
SearchFieldWidget.getModeTypes(this.currentMode))
|
|
249
|
+
)
|
|
250
|
+
}
|
|
251
|
+
}).done((results) => {
|
|
252
|
+
this.ajaxLock = false;
|
|
253
|
+
this._animatePending();
|
|
254
|
+
|
|
255
|
+
if (this.pending) {
|
|
256
|
+
this._doSearch(this.pending);
|
|
257
|
+
} else {
|
|
258
|
+
if (!this.$('.g-search-field').val()) {
|
|
259
|
+
// The search field is empty, so this widget probably had "this.resetState"
|
|
260
|
+
// called while the search was pending. So, don't render the (now obsolete)
|
|
261
|
+
// results.
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
var resources = [];
|
|
266
|
+
_.each(this.types, function (type) {
|
|
267
|
+
_.each(results[type] || [], function (result) {
|
|
268
|
+
var text, icon;
|
|
269
|
+
if (type === 'user') {
|
|
270
|
+
text = result.firstName + ' ' + result.lastName +
|
|
271
|
+
' (' + result.login + ')';
|
|
272
|
+
icon = 'user';
|
|
273
|
+
} else if (type === 'group') {
|
|
274
|
+
text = result.name;
|
|
275
|
+
icon = 'users';
|
|
276
|
+
} else if (type === 'collection') {
|
|
277
|
+
text = result.name;
|
|
278
|
+
icon = 'sitemap';
|
|
279
|
+
} else if (type === 'folder') {
|
|
280
|
+
text = result.name;
|
|
281
|
+
icon = 'folder';
|
|
282
|
+
} else if (type === 'item') {
|
|
283
|
+
text = result.name;
|
|
284
|
+
icon = 'doc-text-inv';
|
|
285
|
+
} else {
|
|
286
|
+
if (this.getInfoCallback) {
|
|
287
|
+
var res = this.getInfoCallback(type, result);
|
|
288
|
+
if (res) {
|
|
289
|
+
text = res.text;
|
|
290
|
+
icon = res.icon;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (!text || !icon) {
|
|
294
|
+
text = '[unknown type]';
|
|
295
|
+
icon = 'attention';
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
resources.push({
|
|
299
|
+
type: type,
|
|
300
|
+
id: result._id,
|
|
301
|
+
text: text,
|
|
302
|
+
icon: icon
|
|
303
|
+
});
|
|
304
|
+
}, this);
|
|
305
|
+
}, this);
|
|
306
|
+
this.$('.g-search-results>ul').html(SearchResultsTemplate({
|
|
307
|
+
results: resources.slice(0, 6)
|
|
308
|
+
}));
|
|
309
|
+
this.$('.dropdown').addClass('open');
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
}, {
|
|
314
|
+
_allowedSearchMode: {},
|
|
315
|
+
|
|
316
|
+
addMode: function (mode, types, description, help) {
|
|
317
|
+
if (_.has(SearchFieldWidget._allowedSearchMode, mode)) {
|
|
318
|
+
throw new Error(`The mode "${mode}" exist already. You can't change it`);
|
|
319
|
+
}
|
|
320
|
+
SearchFieldWidget._allowedSearchMode[mode] = {
|
|
321
|
+
types: types,
|
|
322
|
+
description: description,
|
|
323
|
+
help: help
|
|
324
|
+
};
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
getModes: function () {
|
|
328
|
+
return _.keys(SearchFieldWidget._allowedSearchMode);
|
|
329
|
+
},
|
|
330
|
+
|
|
331
|
+
getModeTypes: function (mode) {
|
|
332
|
+
return SearchFieldWidget._allowedSearchMode[mode].types;
|
|
333
|
+
},
|
|
334
|
+
|
|
335
|
+
getModeDescription: function (mode) {
|
|
336
|
+
return SearchFieldWidget._allowedSearchMode[mode].description;
|
|
337
|
+
},
|
|
338
|
+
|
|
339
|
+
getModeHelp: function (mode) {
|
|
340
|
+
return SearchFieldWidget._allowedSearchMode[mode].help;
|
|
341
|
+
},
|
|
342
|
+
|
|
343
|
+
removeMode: function (mode) {
|
|
344
|
+
delete SearchFieldWidget._allowedSearchMode[mode];
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
SearchFieldWidget.addMode(
|
|
349
|
+
'text',
|
|
350
|
+
['item', 'folder', 'group', 'collection', 'user'],
|
|
351
|
+
'Full text search',
|
|
352
|
+
`By default, search results will be returned if they contain
|
|
353
|
+
any of the terms of the search. If you wish to search for documents
|
|
354
|
+
containing all of the terms, place them in quotes.
|
|
355
|
+
Examples:`
|
|
356
|
+
);
|
|
357
|
+
SearchFieldWidget.addMode(
|
|
358
|
+
'prefix',
|
|
359
|
+
['item', 'folder', 'group', 'collection', 'user'],
|
|
360
|
+
'Search by prefix',
|
|
361
|
+
`You are searching by prefix.
|
|
362
|
+
Start typing the first letters of whatever you are searching for.`
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
export default SearchFieldWidget;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import _ from 'underscore';
|
|
2
|
+
|
|
3
|
+
import View from '@girder/core/views/View';
|
|
4
|
+
import { restRequest } from '@girder/core/rest';
|
|
5
|
+
|
|
6
|
+
import PaginateWidgetTemplate from '@girder/core/templates/widgets/paginateWidget.pug';
|
|
7
|
+
import SearchFieldWidget from '@girder/core/views/widgets/SearchFieldWidget';
|
|
8
|
+
/**
|
|
9
|
+
* This widget is used to provide a consistent widget for iterating amongst
|
|
10
|
+
* pages of a list of search results (using a search mode, a query, an unique type,
|
|
11
|
+
* and a limit).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
var SearchPaginateWidget = View.extend({
|
|
15
|
+
events: {
|
|
16
|
+
'click .g-page-next:not(.disabled)': function () {
|
|
17
|
+
this._updateHasNextPage(true);
|
|
18
|
+
},
|
|
19
|
+
'click .g-page-prev:not(.disabled)': function () {
|
|
20
|
+
this._updateHasPreviousPage(true);
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
initialize: function (settings) {
|
|
25
|
+
this._type = settings.type;
|
|
26
|
+
this._query = settings.query;
|
|
27
|
+
this._mode = settings.mode;
|
|
28
|
+
this._limit = settings.limit;
|
|
29
|
+
|
|
30
|
+
this._offset = 0;
|
|
31
|
+
this._currentPage = 0;
|
|
32
|
+
this._hasNextPage = false;
|
|
33
|
+
this._hasPreviousPage = false;
|
|
34
|
+
|
|
35
|
+
this.results = null;
|
|
36
|
+
|
|
37
|
+
this._updateHasNextPage();
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
render: function () {
|
|
41
|
+
this.$el.html(PaginateWidgetTemplate({
|
|
42
|
+
collection: this
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
this.$('.g-page-next').girderEnable(this._hasNextPage);
|
|
46
|
+
this.$('.g-page-prev').girderEnable(this._hasPreviousPage);
|
|
47
|
+
|
|
48
|
+
if (!this._hasNextPage && !this._hasPreviousPage) {
|
|
49
|
+
this.$el.hide();
|
|
50
|
+
} else {
|
|
51
|
+
this.$el.show();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return this;
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
pageNum: function () {
|
|
58
|
+
return this._currentPage;
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
_updateHasPreviousPage: function (update = false) {
|
|
62
|
+
if (this._currentPage) {
|
|
63
|
+
if (update) {
|
|
64
|
+
return this._fetchPreviousPage(update)
|
|
65
|
+
.done(() => {
|
|
66
|
+
return this._fetchPreviousPage();
|
|
67
|
+
});
|
|
68
|
+
} else {
|
|
69
|
+
return this._fetchPreviousPage();
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
return this._fetchPreviousPage();
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
_updateHasNextPage: function (update = false) {
|
|
77
|
+
if (update) {
|
|
78
|
+
return this._fetchNextPage(update)
|
|
79
|
+
.done(() => {
|
|
80
|
+
return this._fetchNextPage();
|
|
81
|
+
});
|
|
82
|
+
} else {
|
|
83
|
+
return this._fetchNextPage();
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
_fetchPreviousPage: function (update = false) {
|
|
88
|
+
var offset = this._limit * (this._currentPage - 1);
|
|
89
|
+
if (offset < 0) {
|
|
90
|
+
this._hasPreviousPage = false;
|
|
91
|
+
this.render();
|
|
92
|
+
} else {
|
|
93
|
+
return this._fetch(offset)
|
|
94
|
+
.done((results) => {
|
|
95
|
+
var result = results[this._type];
|
|
96
|
+
if (result.length) {
|
|
97
|
+
this._hasPreviousPage = true;
|
|
98
|
+
if (update) {
|
|
99
|
+
this.results = result;
|
|
100
|
+
this.trigger('g:changed');
|
|
101
|
+
this._currentPage--;
|
|
102
|
+
this._updateHasNextPage();
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
this._hasPreviousPage = false;
|
|
106
|
+
}
|
|
107
|
+
this.render();
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
_fetchNextPage: function (update = false) {
|
|
113
|
+
var offset = this._limit * (this._currentPage + 1);
|
|
114
|
+
return this._fetch(offset)
|
|
115
|
+
.done((results) => {
|
|
116
|
+
var result = results[this._type];
|
|
117
|
+
if (result.length) {
|
|
118
|
+
this._hasNextPage = true;
|
|
119
|
+
if (update) {
|
|
120
|
+
this.results = result;
|
|
121
|
+
this.trigger('g:changed');
|
|
122
|
+
this._currentPage++;
|
|
123
|
+
this._updateHasPreviousPage();
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
this._hasNextPage = false;
|
|
127
|
+
}
|
|
128
|
+
this.render();
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
_fetch: function (offset) {
|
|
133
|
+
return restRequest({
|
|
134
|
+
url: 'resource/search',
|
|
135
|
+
data: {
|
|
136
|
+
q: this._query,
|
|
137
|
+
mode: this._mode,
|
|
138
|
+
types: JSON.stringify(_.intersection(
|
|
139
|
+
[this._type],
|
|
140
|
+
SearchFieldWidget.getModeTypes(this._mode))
|
|
141
|
+
),
|
|
142
|
+
limit: this._limit,
|
|
143
|
+
offset: offset
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
export default SearchPaginateWidget;
|