@girder/core 3.2.8 → 5.0.0-a7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -0
- package/package.json +79 -31
- package/assets/Girder_Mark.png +0 -0
- package/auth.js +0 -152
- package/collections/ApiKeyCollection.js +0 -9
- package/collections/AssetstoreCollection.js +0 -9
- package/collections/Collection.js +0 -295
- package/collections/CollectionCollection.js +0 -9
- package/collections/FileCollection.js +0 -11
- package/collections/FolderCollection.js +0 -11
- package/collections/GroupCollection.js +0 -9
- package/collections/ItemCollection.js +0 -11
- package/collections/UserCollection.js +0 -24
- package/collections/index.js +0 -21
- package/constants.js +0 -33
- package/dialog.js +0 -128
- package/events.js +0 -6
- package/index.js +0 -31
- package/main.js +0 -21
- package/misc.js +0 -260
- package/models/AccessControlledModel.js +0 -76
- package/models/ApiKeyModel.js +0 -31
- package/models/AssetstoreModel.js +0 -43
- package/models/CollectionCreationPolicyModel.js +0 -20
- package/models/CollectionModel.js +0 -12
- package/models/FileModel.js +0 -310
- package/models/FolderModel.js +0 -33
- package/models/GroupModel.js +0 -197
- package/models/ItemModel.js +0 -72
- package/models/MetadataMixin.js +0 -88
- package/models/Model.js +0 -187
- package/models/UserModel.js +0 -189
- package/models/index.js +0 -25
- package/pluginUtils.js +0 -11
- package/rest.js +0 -216
- package/router.js +0 -58
- package/routes.js +0 -231
- package/stylesheets/apidocs/apidocs.styl +0 -50
- package/stylesheets/body/adminConsole.styl +0 -21
- package/stylesheets/body/assetstores.styl +0 -46
- package/stylesheets/body/collectionList.styl +0 -39
- package/stylesheets/body/collectionPage.styl +0 -6
- package/stylesheets/body/frontPage.styl +0 -48
- package/stylesheets/body/groupList.styl +0 -43
- package/stylesheets/body/groupPage.styl +0 -116
- package/stylesheets/body/itemPage.styl +0 -81
- package/stylesheets/body/plugins.styl +0 -61
- package/stylesheets/body/searchResultsList.styl +0 -51
- package/stylesheets/body/systemConfig.styl +0 -56
- package/stylesheets/body/userAccount.styl +0 -57
- package/stylesheets/body/userList.styl +0 -79
- package/stylesheets/body/userPage.styl +0 -6
- package/stylesheets/layout/footer.styl +0 -19
- package/stylesheets/layout/global.styl +0 -154
- package/stylesheets/layout/globalNav.styl +0 -89
- package/stylesheets/layout/header.styl +0 -29
- package/stylesheets/layout/headerUser.styl +0 -33
- package/stylesheets/layout/layout.styl +0 -75
- package/stylesheets/layout/layoutVars.styl +0 -9
- package/stylesheets/layout/loading.styl +0 -37
- package/stylesheets/layout/progressArea.styl +0 -17
- package/stylesheets/widgets/accessWidget.styl +0 -106
- package/stylesheets/widgets/browserWidget.styl +0 -9
- package/stylesheets/widgets/hierarchyWidget.styl +0 -188
- package/stylesheets/widgets/markdownWidget.styl +0 -92
- package/stylesheets/widgets/metadataWidget.styl +0 -92
- package/stylesheets/widgets/searchFieldWidget.styl +0 -70
- package/stylesheets/widgets/taskProgress.styl +0 -41
- package/stylesheets/widgets/timelineWidget.styl +0 -41
- package/stylesheets/widgets/uploadWidget.styl +0 -43
- package/stylesheets/widgets/userOtpManagementWidget.styl +0 -159
- package/templates/body/adminConsole.pug +0 -13
- package/templates/body/assetstores.pug +0 -98
- package/templates/body/collectionList.pug +0 -40
- package/templates/body/collectionPage.pug +0 -36
- package/templates/body/filesystemImport.pug +0 -41
- package/templates/body/frontPage.pug +0 -83
- package/templates/body/groupList.pug +0 -30
- package/templates/body/groupPage.pug +0 -116
- package/templates/body/itemPage.pug +0 -61
- package/templates/body/plugins.pug +0 -20
- package/templates/body/s3Import.pug +0 -35
- package/templates/body/searchResults.pug +0 -15
- package/templates/body/searchResultsType.pug +0 -13
- package/templates/body/systemConfiguration.pug +0 -221
- package/templates/body/userAccount.pug +0 -83
- package/templates/body/userList.pug +0 -43
- package/templates/body/userPage.pug +0 -40
- package/templates/layout/alert.pug +0 -5
- package/templates/layout/layout.pug +0 -12
- package/templates/layout/layoutFooter.pug +0 -11
- package/templates/layout/layoutGlobalNav.pug +0 -7
- package/templates/layout/layoutHeader.pug +0 -8
- package/templates/layout/layoutHeaderUser.pug +0 -26
- package/templates/layout/layoutProgressArea.pug +0 -1
- package/templates/layout/loginDialog.pug +0 -30
- package/templates/layout/registerDialog.pug +0 -35
- package/templates/layout/resetPasswordDialog.pug +0 -25
- package/templates/widgets/accessEditor.pug +0 -23
- package/templates/widgets/accessEditorMixins.pug +0 -57
- package/templates/widgets/accessEditorNonModal.pug +0 -11
- package/templates/widgets/accessEntry.pug +0 -32
- package/templates/widgets/apiKeyList.pug +0 -50
- package/templates/widgets/browserWidget.pug +0 -32
- package/templates/widgets/checkedActionsMenu.pug +0 -46
- package/templates/widgets/collectionInfoDialog.pug +0 -37
- package/templates/widgets/confirmDialog.pug +0 -14
- package/templates/widgets/dateTimeRangeWidget.pug +0 -20
- package/templates/widgets/dateTimeWidget.pug +0 -8
- package/templates/widgets/editApiKeyWidget.pug +0 -43
- package/templates/widgets/editAssetstoreWidget.pug +0 -78
- package/templates/widgets/editCollectionWidget.pug +0 -27
- package/templates/widgets/editFileWidget.pug +0 -21
- package/templates/widgets/editFolderWidget.pug +0 -27
- package/templates/widgets/editGroupWidget.pug +0 -54
- package/templates/widgets/editItemWidget.pug +0 -27
- package/templates/widgets/fileInfoDialog.pug +0 -33
- package/templates/widgets/fileList.pug +0 -33
- package/templates/widgets/folderInfoDialog.pug +0 -42
- package/templates/widgets/folderList.pug +0 -21
- package/templates/widgets/groupAdminList.pug +0 -33
- package/templates/widgets/groupInviteDialog.pug +0 -76
- package/templates/widgets/groupInviteList.pug +0 -14
- package/templates/widgets/groupMemberList.pug +0 -39
- package/templates/widgets/groupModList.pug +0 -23
- package/templates/widgets/hierarchyBreadcrumb.pug +0 -37
- package/templates/widgets/hierarchyPaginated.pug +0 -19
- package/templates/widgets/hierarchyWidget.pug +0 -96
- package/templates/widgets/itemBreadcrumb.pug +0 -16
- package/templates/widgets/itemList.pug +0 -27
- package/templates/widgets/jsonMetadatumEditWidget.pug +0 -13
- package/templates/widgets/jsonMetadatumView.pug +0 -6
- package/templates/widgets/loadingAnimation.pug +0 -4
- package/templates/widgets/markdownWidget.pug +0 -34
- package/templates/widgets/metadataWidget.pug +0 -16
- package/templates/widgets/metadatumEditWidget.pug +0 -15
- package/templates/widgets/metadatumView.pug +0 -5
- package/templates/widgets/newAssetstore.pug +0 -118
- package/templates/widgets/paginateWidget.pug +0 -7
- package/templates/widgets/pluginConfigBreadcrumb.pug +0 -13
- package/templates/widgets/rootSelectorWidget.pug +0 -13
- package/templates/widgets/searchField.pug +0 -10
- package/templates/widgets/searchHelp.pug +0 -12
- package/templates/widgets/searchModeSelect.pug +0 -9
- package/templates/widgets/searchResults.pug +0 -14
- package/templates/widgets/sortCollectionWidget.pug +0 -14
- package/templates/widgets/taskProgress.pug +0 -16
- package/templates/widgets/timeline.pug +0 -15
- package/templates/widgets/uploadWidget.pug +0 -15
- package/templates/widgets/uploadWidgetMixins.pug +0 -31
- package/templates/widgets/uploadWidgetNonModal.pug +0 -10
- package/templates/widgets/userOtpBegin.pug +0 -4
- package/templates/widgets/userOtpDisable.pug +0 -6
- package/templates/widgets/userOtpEnable.pug +0 -44
- package/utilities/EventStream.js +0 -177
- package/utilities/PluginUtils.js +0 -36
- package/utilities/S3UploadHandler.js +0 -303
- package/utilities/index.js +0 -9
- package/utilities/jquery/girderEnable.js +0 -19
- package/utilities/jquery/girderModal.js +0 -48
- package/version.js +0 -10
- package/views/App.js +0 -359
- package/views/View.js +0 -78
- package/views/body/AdminView.js +0 -29
- package/views/body/AssetstoresView.js +0 -235
- package/views/body/CollectionView.js +0 -188
- package/views/body/CollectionsView.js +0 -120
- package/views/body/FilesystemImportView.js +0 -83
- package/views/body/FolderView.js +0 -54
- package/views/body/FrontPageView.js +0 -47
- package/views/body/GroupView.js +0 -336
- package/views/body/GroupsView.js +0 -106
- package/views/body/ItemView.js +0 -177
- package/views/body/PluginsView.js +0 -73
- package/views/body/S3ImportView.js +0 -80
- package/views/body/SearchResultsView.js +0 -162
- package/views/body/SystemConfigurationView.js +0 -196
- package/views/body/UserAccountView.js +0 -179
- package/views/body/UserView.js +0 -165
- package/views/body/UsersView.js +0 -124
- package/views/body/index.js +0 -37
- package/views/index.js +0 -13
- package/views/layout/FooterView.js +0 -29
- package/views/layout/GlobalNavView.js +0 -103
- package/views/layout/HeaderUserView.js +0 -45
- package/views/layout/HeaderView.js +0 -83
- package/views/layout/LoginView.js +0 -100
- package/views/layout/ProgressListView.js +0 -70
- package/views/layout/RegisterView.js +0 -101
- package/views/layout/ResetPasswordView.js +0 -70
- package/views/layout/index.js +0 -19
- package/views/widgets/AccessWidget.js +0 -427
- package/views/widgets/ApiKeyListWidget.js +0 -140
- package/views/widgets/BrowserWidget.js +0 -317
- package/views/widgets/CheckedMenuWidget.js +0 -68
- package/views/widgets/CollectionInfoWidget.js +0 -40
- package/views/widgets/DateTimeRangeWidget.js +0 -179
- package/views/widgets/DateTimeWidget.js +0 -109
- package/views/widgets/EditApiKeyWidget.js +0 -122
- package/views/widgets/EditAssetstoreWidget.js +0 -148
- package/views/widgets/EditCollectionWidget.js +0 -93
- package/views/widgets/EditFileWidget.js +0 -56
- package/views/widgets/EditFolderWidget.js +0 -116
- package/views/widgets/EditGroupWidget.js +0 -125
- package/views/widgets/EditItemWidget.js +0 -110
- package/views/widgets/FileInfoWidget.js +0 -26
- package/views/widgets/FileListWidget.js +0 -151
- package/views/widgets/FolderInfoWidget.js +0 -39
- package/views/widgets/FolderListWidget.js +0 -106
- package/views/widgets/GroupAdminsWidget.js +0 -88
- package/views/widgets/GroupInvitesWidget.js +0 -56
- package/views/widgets/GroupMembersWidget.js +0 -185
- package/views/widgets/GroupModsWidget.js +0 -77
- package/views/widgets/HierarchyWidget.js +0 -1097
- package/views/widgets/ItemBreadcrumbWidget.js +0 -38
- package/views/widgets/ItemListWidget.js +0 -345
- package/views/widgets/LoadingAnimation.js +0 -17
- package/views/widgets/MarkdownWidget.js +0 -217
- package/views/widgets/MetadataWidget.js +0 -504
- package/views/widgets/NewAssetstoreWidget.js +0 -81
- package/views/widgets/PaginateWidget.js +0 -37
- package/views/widgets/PluginConfigBreadcrumbWidget.js +0 -33
- package/views/widgets/RootSelectorWidget.js +0 -192
- package/views/widgets/SearchFieldWidget.js +0 -365
- package/views/widgets/SearchPaginateWidget.js +0 -149
- package/views/widgets/SortCollectionWidget.js +0 -53
- package/views/widgets/TaskProgressWidget.js +0 -91
- package/views/widgets/TimelineWidget.js +0 -155
- package/views/widgets/UploadWidget.js +0 -340
- package/views/widgets/UserOtpManagementWidget.js +0 -105
- package/views/widgets/index.js +0 -75
|
@@ -1,1097 +0,0 @@
|
|
|
1
|
-
import $ from 'jquery';
|
|
2
|
-
import _ from 'underscore';
|
|
3
|
-
|
|
4
|
-
import * as allModels from '@girder/core/models';
|
|
5
|
-
import AccessWidget from '@girder/core/views/widgets/AccessWidget';
|
|
6
|
-
import CheckedMenuWidget from '@girder/core/views/widgets/CheckedMenuWidget';
|
|
7
|
-
import CollectionInfoWidget from '@girder/core/views/widgets/CollectionInfoWidget';
|
|
8
|
-
import EditCollectionWidget from '@girder/core/views/widgets/EditCollectionWidget';
|
|
9
|
-
import EditFolderWidget from '@girder/core/views/widgets/EditFolderWidget';
|
|
10
|
-
import EditItemWidget from '@girder/core/views/widgets/EditItemWidget';
|
|
11
|
-
import FolderInfoWidget from '@girder/core/views/widgets/FolderInfoWidget';
|
|
12
|
-
import FolderListWidget from '@girder/core/views/widgets/FolderListWidget';
|
|
13
|
-
import ItemListWidget from '@girder/core/views/widgets/ItemListWidget';
|
|
14
|
-
import ItemModel from '@girder/core/models/ItemModel';
|
|
15
|
-
import MetadataWidget from '@girder/core/views/widgets/MetadataWidget';
|
|
16
|
-
import router from '@girder/core/router';
|
|
17
|
-
import UploadWidget from '@girder/core/views/widgets/UploadWidget';
|
|
18
|
-
import View from '@girder/core/views/View';
|
|
19
|
-
import { AccessType } from '@girder/core/constants';
|
|
20
|
-
import { confirm, handleClose } from '@girder/core/dialog';
|
|
21
|
-
import events from '@girder/core/events';
|
|
22
|
-
import { getModelClassByName, renderMarkdown, formatCount, capitalize, formatSize } from '@girder/core/misc';
|
|
23
|
-
import { restRequest, getApiRoot } from '@girder/core/rest';
|
|
24
|
-
|
|
25
|
-
import HierarchyBreadcrumbTemplate from '@girder/core/templates/widgets/hierarchyBreadcrumb.pug';
|
|
26
|
-
import HierarchyPaginatedTemplate from '@girder/core/templates/widgets/hierarchyPaginated.pug';
|
|
27
|
-
import HierarchyWidgetTemplate from '@girder/core/templates/widgets/hierarchyWidget.pug';
|
|
28
|
-
|
|
29
|
-
import '@girder/core/stylesheets/widgets/hierarchyWidget.styl';
|
|
30
|
-
|
|
31
|
-
import 'bootstrap/js/dropdown';
|
|
32
|
-
|
|
33
|
-
var pickedResources = null;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Renders the breadcrumb list in the hierarchy widget.
|
|
37
|
-
*/
|
|
38
|
-
var HierarchyBreadcrumbView = View.extend({
|
|
39
|
-
events: {
|
|
40
|
-
'click a.g-breadcrumb-link': function (event) {
|
|
41
|
-
var link = $(event.currentTarget);
|
|
42
|
-
this.trigger('g:breadcrumbClicked', parseInt(link.attr('g-index'), 10));
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
initialize: function (settings) {
|
|
47
|
-
this.objects = settings.objects;
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
render: function () {
|
|
51
|
-
// Clone the array so we don't alter the instance's copy
|
|
52
|
-
var objects = this.objects.slice(0);
|
|
53
|
-
|
|
54
|
-
// Pop off the last object, it refers to the currently viewed
|
|
55
|
-
// object and should be the "active" class, and not a link.
|
|
56
|
-
var active = objects.pop();
|
|
57
|
-
|
|
58
|
-
var descriptionText = $(renderMarkdown(
|
|
59
|
-
active.get('description') || '')).text();
|
|
60
|
-
|
|
61
|
-
this.$el.html(HierarchyBreadcrumbTemplate({
|
|
62
|
-
links: objects,
|
|
63
|
-
current: active,
|
|
64
|
-
descriptionText: descriptionText
|
|
65
|
-
}));
|
|
66
|
-
|
|
67
|
-
return this;
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
var HierarchyPaginatedView = View.extend({
|
|
72
|
-
events: {
|
|
73
|
-
'change #g-page-selection-input': function (event) {
|
|
74
|
-
const num = Number(event.target.value);
|
|
75
|
-
if (this.itemListWidget && num <= this.itemListWidget.getNumPages() && num > 0) {
|
|
76
|
-
this.disabled = true;
|
|
77
|
-
this.itemListWidget.setPage(num).done(() => {
|
|
78
|
-
this.disabled = false;
|
|
79
|
-
this.render();
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
this.render();
|
|
83
|
-
},
|
|
84
|
-
'click li.g-page-next:not(.disabled) a#g-next-paginated': function () {
|
|
85
|
-
this.disabled = true;
|
|
86
|
-
this.itemListWidget.setPage(Number(this.$('#g-page-selection-input').val()) + 1).done(() => {
|
|
87
|
-
this.disabled = false;
|
|
88
|
-
this.render();
|
|
89
|
-
});
|
|
90
|
-
this.render();
|
|
91
|
-
},
|
|
92
|
-
'click li.g-page-prev:not(.disabled) a#g-previous-paginated': function () {
|
|
93
|
-
this.disabled = true;
|
|
94
|
-
this.itemListWidget.setPage(Number(this.$('#g-page-selection-input').val()) - 1).done(() => {
|
|
95
|
-
this.disabled = false;
|
|
96
|
-
this.render();
|
|
97
|
-
});
|
|
98
|
-
this.render();
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
initialize: function (settings) {
|
|
102
|
-
this.itemListWidget = settings.itemListWidget;
|
|
103
|
-
this.disabled = false;
|
|
104
|
-
},
|
|
105
|
-
render: function () {
|
|
106
|
-
this.$el.html(HierarchyPaginatedTemplate({
|
|
107
|
-
totalPages: this.itemListWidget && this.itemListWidget.getNumPages(),
|
|
108
|
-
currentPage: this.itemListWidget && this.itemListWidget.getCurrentPage(),
|
|
109
|
-
disabled: this.disabled
|
|
110
|
-
}));
|
|
111
|
-
|
|
112
|
-
return this;
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* This widget is used to navigate the data hierarchy of folders and items.
|
|
118
|
-
*/
|
|
119
|
-
var HierarchyWidget = View.extend({
|
|
120
|
-
events: {
|
|
121
|
-
'click a.g-create-subfolder': 'createFolderDialog',
|
|
122
|
-
'click a.g-edit-folder': 'editFolderDialog',
|
|
123
|
-
'click button.g-select-folder': 'selectFolder',
|
|
124
|
-
'click a.g-delete-folder': 'deleteFolderDialog',
|
|
125
|
-
'click .g-folder-info-button': 'showInfoDialog',
|
|
126
|
-
'click .g-collection-info-button': 'showInfoDialog',
|
|
127
|
-
'click .g-description-preview': 'showInfoDialog',
|
|
128
|
-
'click a.g-create-item': 'createItemDialog',
|
|
129
|
-
'click .g-upload-here-button': 'uploadDialog',
|
|
130
|
-
'click .g-edit-access': 'editAccess',
|
|
131
|
-
'click .g-hierarchy-level-up': 'upOneLevel',
|
|
132
|
-
'click a.g-download-checked': 'downloadChecked',
|
|
133
|
-
'click a.g-pick-checked': 'pickChecked',
|
|
134
|
-
'click a.g-move-picked': 'movePickedResources',
|
|
135
|
-
'click a.g-copy-picked': 'copyPickedResources',
|
|
136
|
-
'click a.g-clear-picked': 'clearPickedResources',
|
|
137
|
-
'click a.g-delete-checked': 'deleteCheckedDialog',
|
|
138
|
-
'click .g-list-checkbox': 'checkboxListener',
|
|
139
|
-
'change .g-select-all': function (e) {
|
|
140
|
-
this.folderListView.checkAll(e.currentTarget.checked);
|
|
141
|
-
|
|
142
|
-
if (this.itemListView) {
|
|
143
|
-
this.itemListView.checkAll(e.currentTarget.checked);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
},
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* This should be instantiated with the following settings:
|
|
150
|
-
* parentModel: The model representing the root node. Must be a User,
|
|
151
|
-
* Collection, or Folder model.
|
|
152
|
-
* [showActions=true]: Whether to show the action bar.
|
|
153
|
-
* [showItems=true]: Whether to show items in the list (or just folders).
|
|
154
|
-
* [checkboxes=true]: Whether to show checkboxes next to each resource.
|
|
155
|
-
* [routing=true]: Whether the route should be updated by this widget.
|
|
156
|
-
* [appendPages=false]: Whether new pages should be appended instead of
|
|
157
|
-
* replaced.
|
|
158
|
-
* [onItemClick]: A function that will be called when an item is clicked,
|
|
159
|
-
* passed the Item model as its first argument and the
|
|
160
|
-
* event as its second.
|
|
161
|
-
* [defaultSelectedResource] : default selected Resource item , will open up to this resource
|
|
162
|
-
* [highlightItem=false] : sets the item to be styled as selected and will scroll to it in the list
|
|
163
|
-
* [paginated=false] : sets the itemlist view to be paginated, will set appendPages to false
|
|
164
|
-
*/
|
|
165
|
-
initialize: function (settings) {
|
|
166
|
-
this.parentModel = settings.parentModel;
|
|
167
|
-
this.upload = settings.upload;
|
|
168
|
-
|
|
169
|
-
this._showActions = _.has(settings, 'showActions') ? settings.showActions : true;
|
|
170
|
-
this._showItems = _.has(settings, 'showItems') ? settings.showItems : true;
|
|
171
|
-
|
|
172
|
-
this._itemFilter = settings.itemFilter;
|
|
173
|
-
|
|
174
|
-
this._checkboxes = _.has(settings, 'checkboxes') ? settings.checkboxes : true;
|
|
175
|
-
this._downloadLinks = _.has(settings, 'downloadLinks') ? settings.downloadLinks : true;
|
|
176
|
-
this._viewLinks = _.has(settings, 'viewLinks') ? settings.viewLinks : true;
|
|
177
|
-
this._showSizes = _.has(settings, 'showSizes') ? settings.showSizes : true;
|
|
178
|
-
this._showMetadata = _.has(settings, 'showMetadata') ? settings.showMetadata : true;
|
|
179
|
-
this._routing = _.has(settings, 'routing') ? settings.routing : true;
|
|
180
|
-
this._appendPages = _.has(settings, 'appendPages') ? settings.appendPages : false;
|
|
181
|
-
this._onItemClick = settings.onItemClick || function (item) {
|
|
182
|
-
router.navigate('item/' + item.get('_id'), { trigger: true });
|
|
183
|
-
};
|
|
184
|
-
this._defaultSelectedResource = settings.defaultSelectedResource;
|
|
185
|
-
this._highlightItem = _.has(settings, 'highlightItem') ? settings.highlightItem : false;
|
|
186
|
-
this._paginated = _.has(settings, 'paginated') ? settings.paginated : false;
|
|
187
|
-
this._onFolderSelect = settings.onFolderSelect;
|
|
188
|
-
|
|
189
|
-
this.folderAccess = settings.folderAccess;
|
|
190
|
-
this.folderCreate = settings.folderCreate;
|
|
191
|
-
this.folderEdit = settings.folderEdit;
|
|
192
|
-
this.itemCreate = settings.itemCreate;
|
|
193
|
-
this.breadcrumbs = [this.parentModel];
|
|
194
|
-
|
|
195
|
-
// Initialize the breadcrumb bar state
|
|
196
|
-
this.breadcrumbView = new HierarchyBreadcrumbView({
|
|
197
|
-
objects: this.breadcrumbs,
|
|
198
|
-
parentView: this
|
|
199
|
-
});
|
|
200
|
-
this.breadcrumbView.on('g:breadcrumbClicked', function (idx) {
|
|
201
|
-
this.breadcrumbs = this.breadcrumbs.slice(0, idx + 1);
|
|
202
|
-
this.setCurrentModel(this.breadcrumbs[idx]);
|
|
203
|
-
this._setRoute();
|
|
204
|
-
}, this);
|
|
205
|
-
|
|
206
|
-
this.checkedMenuWidget = new CheckedMenuWidget({
|
|
207
|
-
pickedCount: this.getPickedCount(),
|
|
208
|
-
pickedCopyAllowed: this.getPickedCopyAllowed(),
|
|
209
|
-
pickedMoveAllowed: this.getPickedMoveAllowed(),
|
|
210
|
-
pickedDesc: this.getPickedDescription(),
|
|
211
|
-
parentView: this
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
this.folderListView = new FolderListWidget({
|
|
215
|
-
folderFilter: this._itemFilter,
|
|
216
|
-
parentType: this.parentModel.resourceName,
|
|
217
|
-
parentId: this.parentModel.get('_id'),
|
|
218
|
-
checkboxes: this._checkboxes,
|
|
219
|
-
parentView: this
|
|
220
|
-
});
|
|
221
|
-
this.folderListView.on('g:folderClicked', function (folder) {
|
|
222
|
-
this.descend(folder);
|
|
223
|
-
|
|
224
|
-
if (this.uploadWidget) {
|
|
225
|
-
this.uploadWidget.folder = folder;
|
|
226
|
-
}
|
|
227
|
-
}, this).off('g:checkboxesChanged')
|
|
228
|
-
.on('g:checkboxesChanged', this.updateChecked, this)
|
|
229
|
-
.off('g:changed').on('g:changed', function () {
|
|
230
|
-
this.folderCount = this.folderListView.collection.length;
|
|
231
|
-
this._childCountCheck();
|
|
232
|
-
}, this);
|
|
233
|
-
|
|
234
|
-
if (this.parentModel.resourceName === 'folder') {
|
|
235
|
-
this._fetchToRoot(this.parentModel);
|
|
236
|
-
} else {
|
|
237
|
-
this.itemCount = 0;
|
|
238
|
-
this.render();
|
|
239
|
-
}
|
|
240
|
-
events.on('g:login', () => {
|
|
241
|
-
this.constructor.resetPickedResources();
|
|
242
|
-
}, this);
|
|
243
|
-
},
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* If both the child folders and child items have been fetched, and
|
|
247
|
-
* there are neither of either type in this parent container, we should
|
|
248
|
-
* show the "empty container" message.
|
|
249
|
-
*/
|
|
250
|
-
_childCountCheck: function () {
|
|
251
|
-
var container = this.$('.g-empty-parent-message').addClass('hide');
|
|
252
|
-
if (this.folderCount === 0 && this.itemCount === 0) {
|
|
253
|
-
container.removeClass('hide');
|
|
254
|
-
}
|
|
255
|
-
},
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Initializes the subwidgets that are only shown when the parent resource
|
|
259
|
-
* is a folder type.
|
|
260
|
-
*/
|
|
261
|
-
_initFolderViewSubwidgets: function () {
|
|
262
|
-
if (!this.itemListView) {
|
|
263
|
-
this.itemListView = new ItemListWidget({
|
|
264
|
-
itemFilter: this._itemFilter,
|
|
265
|
-
folderId: this.parentModel.id,
|
|
266
|
-
public: this.parentModel.get('public'),
|
|
267
|
-
accessLevel: this.parentModel.getAccessLevel(),
|
|
268
|
-
checkboxes: this._checkboxes,
|
|
269
|
-
downloadLinks: this._downloadLinks,
|
|
270
|
-
viewLinks: this._viewLinks,
|
|
271
|
-
showSizes: this._showSizes,
|
|
272
|
-
selectedItem: this._defaultSelectedResource,
|
|
273
|
-
highlightItem: this._highlightItem,
|
|
274
|
-
paginated: this._paginated,
|
|
275
|
-
parentView: this
|
|
276
|
-
});
|
|
277
|
-
this.listenTo(this.itemListView, 'g:itemClicked', this._onItemClick);
|
|
278
|
-
this.listenTo(this.itemListView, 'g:checkboxesChanged', this.updateChecked);
|
|
279
|
-
|
|
280
|
-
this.listenTo(this.itemListView, 'g:changed', () => {
|
|
281
|
-
this.itemCount = this.itemListView.collection.length;
|
|
282
|
-
this._childCountCheck();
|
|
283
|
-
if (this._paginated && this.hierarchyPaginated && this.itemListView.getNumPages() > 1) {
|
|
284
|
-
if (this.parentModel.resourceName !== 'collection') {
|
|
285
|
-
this.hierarchyPaginated.setElement(this.$('.g-hierarachy-paginated-bar')).render();
|
|
286
|
-
}
|
|
287
|
-
this.$('.g-hierarchy-breadcrumb-bar').addClass('g-hierarchy-sticky');
|
|
288
|
-
this.$('.g-hierarachy-paginated-bar').addClass('g-hierarchy-sticky');
|
|
289
|
-
this.$('.g-hierarchy-breadcrumb-bar').css({ top: 0 });
|
|
290
|
-
this.$('.g-hierarachy-paginated-bar').css({ bottom: 0 });
|
|
291
|
-
this.$('.g-hierarachy-paginated-bar').removeClass('hidden');
|
|
292
|
-
} else {
|
|
293
|
-
// We remove the bar if the current folder doesn't have more than one page, keep the sticky breadcrumb though
|
|
294
|
-
this.$('.g-hierarachy-paginated-bar').addClass('hidden');
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
|
-
// Only emitted when there is more than one page of data
|
|
298
|
-
this.listenTo(this.itemListView, 'g:paginated', () => {
|
|
299
|
-
if (this._paginated && !this.hierarchyPaginated) {
|
|
300
|
-
this.hierarchyPaginated = new HierarchyPaginatedView({
|
|
301
|
-
parentView: this,
|
|
302
|
-
itemListWidget: this.itemListView
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
if (!this.metadataWidget) {
|
|
309
|
-
this.metadataWidget = new MetadataWidget({
|
|
310
|
-
item: this.parentModel,
|
|
311
|
-
parentView: this,
|
|
312
|
-
accessLevel: this.parentModel.getAccessLevel()
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
},
|
|
316
|
-
|
|
317
|
-
_setRoute: function () {
|
|
318
|
-
if (this._routing) {
|
|
319
|
-
var route = this.breadcrumbs[0].resourceName + '/' +
|
|
320
|
-
this.breadcrumbs[0].get('_id');
|
|
321
|
-
if (this.parentModel.resourceName === 'folder') {
|
|
322
|
-
route += '/folder/' + this.parentModel.get('_id');
|
|
323
|
-
}
|
|
324
|
-
router.navigate(route);
|
|
325
|
-
events.trigger('g:hierarchy.route', { route: route });
|
|
326
|
-
}
|
|
327
|
-
},
|
|
328
|
-
|
|
329
|
-
_fetchToRoot: function (folder) {
|
|
330
|
-
folder.getRootPath().done((path) => {
|
|
331
|
-
const breadcrumbs = path.map((r) => new allModels[getModelClassByName(r.type)](r.object));
|
|
332
|
-
this.breadcrumbs.unshift(...breadcrumbs);
|
|
333
|
-
this.render();
|
|
334
|
-
});
|
|
335
|
-
},
|
|
336
|
-
|
|
337
|
-
render: function () {
|
|
338
|
-
this.folderCount = null;
|
|
339
|
-
this.itemCount = null;
|
|
340
|
-
|
|
341
|
-
this.$el.html(HierarchyWidgetTemplate({
|
|
342
|
-
type: this.parentModel.resourceName,
|
|
343
|
-
model: this.parentModel,
|
|
344
|
-
level: this.parentModel.getAccessLevel(),
|
|
345
|
-
AccessType: AccessType,
|
|
346
|
-
onFolderSelect: this._onFolderSelect,
|
|
347
|
-
showActions: this._showActions,
|
|
348
|
-
showMetadata: this._showMetadata,
|
|
349
|
-
checkboxes: this._checkboxes,
|
|
350
|
-
capitalize: capitalize,
|
|
351
|
-
itemFilter: this._itemFilter
|
|
352
|
-
}));
|
|
353
|
-
|
|
354
|
-
if (this.$('.g-folder-actions-menu>li>a').length === 0) {
|
|
355
|
-
// Disable the actions button if actions list is empty
|
|
356
|
-
this.$('.g-folder-actions-button').girderEnable(false);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
this.breadcrumbView.setElement(this.$('.g-hierarchy-breadcrumb-bar>ol')).render();
|
|
360
|
-
this.checkedMenuWidget.dropdownToggle = this.$('.g-checked-actions-button');
|
|
361
|
-
this.checkedMenuWidget.setElement(this.$('.g-checked-actions-menu')).render();
|
|
362
|
-
this.folderListView.setElement(this.$('.g-folder-list-container')).render();
|
|
363
|
-
if (this.hierarchyPaginated && this.parentModel.resourceName !== 'collection') {
|
|
364
|
-
this.hierarchyPaginated.setElement(this.$('.g-hierarachy-paginated-bar')).render();
|
|
365
|
-
}
|
|
366
|
-
if (this.parentModel.resourceName === 'folder' && this._showItems) {
|
|
367
|
-
this._initFolderViewSubwidgets();
|
|
368
|
-
this.itemListView.setElement(this.$('.g-item-list-container')).render();
|
|
369
|
-
this.metadataWidget.setItem(this.parentModel);
|
|
370
|
-
this.metadataWidget.accessLevel = this.parentModel.getAccessLevel();
|
|
371
|
-
if (this._showMetadata) {
|
|
372
|
-
this.metadataWidget.setElement(this.$('.g-folder-metadata')).render();
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
if (this.parentModel.resourceName === 'collection' && this._showMetadata) {
|
|
377
|
-
if (!this.metadataWidget) {
|
|
378
|
-
this.metadataWidget = new MetadataWidget({
|
|
379
|
-
item: this.parentModel,
|
|
380
|
-
parentView: this,
|
|
381
|
-
accessLevel: this.parentModel.getAccessLevel()
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
|
-
this.metadataWidget.setItem(this.parentModel);
|
|
385
|
-
this.metadataWidget.accessLevel = this.parentModel.getAccessLevel();
|
|
386
|
-
this.metadataWidget.setElement(this.$('.g-folder-metadata')).render();
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
if (this.upload) {
|
|
390
|
-
this.uploadDialog();
|
|
391
|
-
} else if (this.folderAccess) {
|
|
392
|
-
this.editAccess();
|
|
393
|
-
} else if (this.folderCreate) {
|
|
394
|
-
this.createFolderDialog();
|
|
395
|
-
} else if (this.folderEdit) {
|
|
396
|
-
this.editFolderDialog();
|
|
397
|
-
} else if (this.itemCreate) {
|
|
398
|
-
this.createItemDialog();
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
this.fetchAndShowChildCount();
|
|
402
|
-
|
|
403
|
-
return this;
|
|
404
|
-
},
|
|
405
|
-
|
|
406
|
-
/**
|
|
407
|
-
* Descend into the given folder.
|
|
408
|
-
*/
|
|
409
|
-
descend: function (folder) {
|
|
410
|
-
this.breadcrumbs.push(folder);
|
|
411
|
-
this.setCurrentModel(folder);
|
|
412
|
-
},
|
|
413
|
-
|
|
414
|
-
/**
|
|
415
|
-
* Go to the parent of the current folder
|
|
416
|
-
*/
|
|
417
|
-
upOneLevel: function () {
|
|
418
|
-
this.breadcrumbs.pop();
|
|
419
|
-
this.setCurrentModel(this.breadcrumbs[this.breadcrumbs.length - 1]);
|
|
420
|
-
},
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Called when the "select this folder" link is clicked.
|
|
424
|
-
*/
|
|
425
|
-
selectFolder: function () {
|
|
426
|
-
if (_.isFunction(this._onFolderSelect)) {
|
|
427
|
-
this._onFolderSelect(this.parentModel);
|
|
428
|
-
}
|
|
429
|
-
},
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Prompt the user to create a new subfolder in the current folder.
|
|
433
|
-
*/
|
|
434
|
-
createFolderDialog: function () {
|
|
435
|
-
new EditFolderWidget({
|
|
436
|
-
el: $('#g-dialog-container'),
|
|
437
|
-
parentModel: this.parentModel,
|
|
438
|
-
parentView: this
|
|
439
|
-
}).on('g:saved', function (folder) {
|
|
440
|
-
this.folderListView.insertFolder(folder);
|
|
441
|
-
if (this.parentModel.has('nFolders')) {
|
|
442
|
-
this.parentModel.increment('nFolders');
|
|
443
|
-
}
|
|
444
|
-
this.updateChecked();
|
|
445
|
-
}, this).render();
|
|
446
|
-
},
|
|
447
|
-
|
|
448
|
-
/**
|
|
449
|
-
* Prompt the user to create a new item in the current folder
|
|
450
|
-
*/
|
|
451
|
-
createItemDialog: function () {
|
|
452
|
-
new EditItemWidget({
|
|
453
|
-
el: $('#g-dialog-container'),
|
|
454
|
-
parentModel: this.parentModel,
|
|
455
|
-
parentView: this
|
|
456
|
-
}).on('g:saved', function (item) {
|
|
457
|
-
this.itemListView.insertItem(item);
|
|
458
|
-
if (this.parentModel.has('nItems')) {
|
|
459
|
-
this.parentModel.increment('nItems');
|
|
460
|
-
}
|
|
461
|
-
this.updateChecked();
|
|
462
|
-
}, this).render();
|
|
463
|
-
},
|
|
464
|
-
|
|
465
|
-
/**
|
|
466
|
-
* Prompt user to edit the current folder or collection.
|
|
467
|
-
*/
|
|
468
|
-
editFolderDialog: function () {
|
|
469
|
-
if (this.parentModel.resourceName === 'folder') {
|
|
470
|
-
new EditFolderWidget({
|
|
471
|
-
el: $('#g-dialog-container'),
|
|
472
|
-
parentModel: this.parentModel,
|
|
473
|
-
folder: this.parentModel,
|
|
474
|
-
parentView: this
|
|
475
|
-
}).on('g:saved', function () {
|
|
476
|
-
events.trigger('g:alert', {
|
|
477
|
-
icon: 'ok',
|
|
478
|
-
text: 'Folder info updated.',
|
|
479
|
-
type: 'success',
|
|
480
|
-
timeout: 4000
|
|
481
|
-
});
|
|
482
|
-
this.breadcrumbView.render();
|
|
483
|
-
}, this).on('g:fileUploaded', function (args) {
|
|
484
|
-
var item = new ItemModel({
|
|
485
|
-
_id: args.model.get('itemId')
|
|
486
|
-
});
|
|
487
|
-
|
|
488
|
-
item.once('g:fetched', function () {
|
|
489
|
-
this.itemListView.insertItem(item);
|
|
490
|
-
if (this.parentModel.has('nItems')) {
|
|
491
|
-
this.parentModel.increment('nItems');
|
|
492
|
-
}
|
|
493
|
-
this.updateChecked();
|
|
494
|
-
}, this).fetch();
|
|
495
|
-
}, this).render();
|
|
496
|
-
} else if (this.parentModel.resourceName === 'collection') {
|
|
497
|
-
new EditCollectionWidget({
|
|
498
|
-
el: $('#g-dialog-container'),
|
|
499
|
-
model: this.parentModel,
|
|
500
|
-
parentView: this
|
|
501
|
-
}).on('g:saved', function () {
|
|
502
|
-
this.breadcrumbView.render();
|
|
503
|
-
this.trigger('g:collectionChanged');
|
|
504
|
-
}, this).render();
|
|
505
|
-
}
|
|
506
|
-
},
|
|
507
|
-
|
|
508
|
-
/**
|
|
509
|
-
* Prompt the user to delete the currently viewed folder or collection.
|
|
510
|
-
*/
|
|
511
|
-
deleteFolderDialog: function () {
|
|
512
|
-
var type = this.parentModel.resourceName;
|
|
513
|
-
var params = {
|
|
514
|
-
text: 'Are you sure you want to delete the ' + type + ' <b>' +
|
|
515
|
-
this.parentModel.escape('name') + '</b>?',
|
|
516
|
-
escapedHtml: true,
|
|
517
|
-
yesText: 'Delete',
|
|
518
|
-
confirmCallback: () => {
|
|
519
|
-
this.parentModel.on('g:deleted', function () {
|
|
520
|
-
if (type === 'collection') {
|
|
521
|
-
router.navigate('collections', { trigger: true });
|
|
522
|
-
} else if (type === 'folder') {
|
|
523
|
-
this.breadcrumbs.pop();
|
|
524
|
-
this.setCurrentModel(this.breadcrumbs.slice(-1)[0]);
|
|
525
|
-
}
|
|
526
|
-
}, this).destroy({
|
|
527
|
-
throwError: true,
|
|
528
|
-
progress: true
|
|
529
|
-
});
|
|
530
|
-
}
|
|
531
|
-
};
|
|
532
|
-
if (type === 'collection' &&
|
|
533
|
-
(this.parentModel.get('nFolders') !== 0 || this.parentModel.get('size') !== 0)) {
|
|
534
|
-
params = _.extend({
|
|
535
|
-
name: this.parentModel.escape('name'),
|
|
536
|
-
additionalText: '<b>' + this.parentModel.escape('name') + '</b>' +
|
|
537
|
-
' contains <b>' + this.parentModel.escape('nFolders') +
|
|
538
|
-
' folders</b> taking up <b>' +
|
|
539
|
-
formatSize(parseInt(this.parentModel.get('size'), 10)) + '</b>',
|
|
540
|
-
msgConfirmation: true
|
|
541
|
-
}, params);
|
|
542
|
-
}
|
|
543
|
-
confirm(params);
|
|
544
|
-
},
|
|
545
|
-
|
|
546
|
-
showInfoDialog: function () {
|
|
547
|
-
var opts = {
|
|
548
|
-
el: $('#g-dialog-container'),
|
|
549
|
-
model: this.parentModel,
|
|
550
|
-
parentView: this
|
|
551
|
-
};
|
|
552
|
-
|
|
553
|
-
if (this.parentModel.resourceName === 'collection') {
|
|
554
|
-
new CollectionInfoWidget(opts).render();
|
|
555
|
-
} else if (this.parentModel.resourceName === 'folder') {
|
|
556
|
-
new FolderInfoWidget(opts).render();
|
|
557
|
-
}
|
|
558
|
-
},
|
|
559
|
-
|
|
560
|
-
fetchAndShowChildCount: function () {
|
|
561
|
-
this.$('.g-child-count-container').addClass('hide');
|
|
562
|
-
|
|
563
|
-
var showCounts = () => {
|
|
564
|
-
const folderCount = formatCount(this.parentModel.get('nFolders'));
|
|
565
|
-
this.$('.g-child-count-container').removeClass('hide');
|
|
566
|
-
this.$('.g-subfolder-count').text(folderCount);
|
|
567
|
-
const folderTooltip = folderCount === 1 ? `${folderCount} total folder` : `${folderCount} total folders`;
|
|
568
|
-
this.$('.g-subfolder-count-container').attr('title', folderTooltip);
|
|
569
|
-
if (this.parentModel.has('nItems')) {
|
|
570
|
-
const itemCount = formatCount(this.parentModel.get('nItems'));
|
|
571
|
-
this.$('.g-item-count').text(itemCount);
|
|
572
|
-
const itemTooltip = itemCount === 1 ? `${itemCount} total item` : `${itemCount} total items`;
|
|
573
|
-
this.$('.g-item-count-container').attr('title', itemTooltip);
|
|
574
|
-
}
|
|
575
|
-
};
|
|
576
|
-
|
|
577
|
-
if (this.parentModel.has('nFolders')) {
|
|
578
|
-
showCounts();
|
|
579
|
-
} else {
|
|
580
|
-
this.parentModel.set('nFolders', 0); // prevents fetching details twice
|
|
581
|
-
this.parentModel.once('g:fetched.details', function () {
|
|
582
|
-
showCounts();
|
|
583
|
-
}, this).fetch({ extraPath: 'details' });
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
this.parentModel.off('change:nItems', showCounts, this)
|
|
587
|
-
.on('change:nItems', showCounts, this)
|
|
588
|
-
.off('change:nFolders', showCounts, this)
|
|
589
|
-
.on('change:nFolders', showCounts, this);
|
|
590
|
-
|
|
591
|
-
return this;
|
|
592
|
-
},
|
|
593
|
-
|
|
594
|
-
/**
|
|
595
|
-
* Change the current parent model, i.e. the resource being shown currently.
|
|
596
|
-
*
|
|
597
|
-
* @param parent The parent model to change to.
|
|
598
|
-
*/
|
|
599
|
-
setCurrentModel: function (parent, opts) {
|
|
600
|
-
opts = opts || {};
|
|
601
|
-
this.parentModel = parent;
|
|
602
|
-
|
|
603
|
-
this.breadcrumbView.objects = this.breadcrumbs;
|
|
604
|
-
|
|
605
|
-
this.folderListView.initialize({
|
|
606
|
-
parentType: parent.resourceName,
|
|
607
|
-
parentId: parent.get('_id'),
|
|
608
|
-
checkboxes: this._checkboxes,
|
|
609
|
-
folderFilter: this._itemFilter
|
|
610
|
-
});
|
|
611
|
-
|
|
612
|
-
this.updateChecked();
|
|
613
|
-
|
|
614
|
-
if (parent.resourceName === 'folder') {
|
|
615
|
-
if (this.itemListView) {
|
|
616
|
-
this.itemListView.initialize({
|
|
617
|
-
folderId: parent.get('_id'),
|
|
618
|
-
checkboxes: this._checkboxes,
|
|
619
|
-
downloadLinks: this._downloadLinks,
|
|
620
|
-
viewLinks: this._viewLinks,
|
|
621
|
-
itemFilter: this._itemFilter,
|
|
622
|
-
showSizes: this._showSizes,
|
|
623
|
-
paginated: this._paginated,
|
|
624
|
-
public: this.parentModel.get('public'),
|
|
625
|
-
accessLevel: this.parentModel.getAccessLevel()
|
|
626
|
-
});
|
|
627
|
-
}
|
|
628
|
-
this._initFolderViewSubwidgets();
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
this.render();
|
|
632
|
-
if (!_.has(opts, 'setRoute') || opts.setRoute) {
|
|
633
|
-
this._setRoute();
|
|
634
|
-
}
|
|
635
|
-
this.trigger('g:setCurrentModel');
|
|
636
|
-
},
|
|
637
|
-
|
|
638
|
-
/**
|
|
639
|
-
* Based on a resource collection with either has model references or
|
|
640
|
-
* checkbox references, return a string that describes the collection.
|
|
641
|
-
* :param resources: a hash with different resources.
|
|
642
|
-
* :returns: description of the resources.
|
|
643
|
-
*/
|
|
644
|
-
_describeResources: function (resources) {
|
|
645
|
-
/* If the resources aren't English words or don't have simple plurals,
|
|
646
|
-
* this will need to be refactored. */
|
|
647
|
-
var kinds = ['folder', 'item'];
|
|
648
|
-
|
|
649
|
-
var desc = [];
|
|
650
|
-
for (var i = 0; i < kinds.length; i += 1) {
|
|
651
|
-
var kind = kinds[i];
|
|
652
|
-
if (resources[kind] && resources[kind].length) {
|
|
653
|
-
desc.push(resources[kind].length + ' ' + kind +
|
|
654
|
-
(resources[kind].length !== 1 ? 's' : ''));
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
switch (desc.length) {
|
|
658
|
-
case 0:
|
|
659
|
-
return 'nothing';
|
|
660
|
-
case 1:
|
|
661
|
-
return desc[0];
|
|
662
|
-
case 2:
|
|
663
|
-
return desc[0] + ' and ' + desc[1];
|
|
664
|
-
/* If we add a third model type, enable this:
|
|
665
|
-
default:
|
|
666
|
-
desc[desc.length-1] = 'and ' + desc[desc.length-1];
|
|
667
|
-
return ', '.join(desc);
|
|
668
|
-
*/
|
|
669
|
-
}
|
|
670
|
-
},
|
|
671
|
-
|
|
672
|
-
/**
|
|
673
|
-
* Prompt the user to delete the currently checked items.
|
|
674
|
-
*/
|
|
675
|
-
deleteCheckedDialog: function () {
|
|
676
|
-
var folders = this.folderListView.checked;
|
|
677
|
-
var items;
|
|
678
|
-
if (this.itemListView && this.itemListView.checked.length) {
|
|
679
|
-
items = this.itemListView.checked;
|
|
680
|
-
}
|
|
681
|
-
var desc = this._describeResources({ folder: folders, item: items });
|
|
682
|
-
|
|
683
|
-
var params = {
|
|
684
|
-
text: 'Are you sure you want to delete the checked resources (' +
|
|
685
|
-
desc + ')?',
|
|
686
|
-
|
|
687
|
-
yesText: 'Delete',
|
|
688
|
-
confirmCallback: () => {
|
|
689
|
-
var resources = this._getCheckedResourceParam();
|
|
690
|
-
var resourceSize = this._getCheckedResourceSize();
|
|
691
|
-
/* Content on DELETE requests is somewhat oddly supported (I
|
|
692
|
-
* can't get it to work under jasmine/phantom), so override the
|
|
693
|
-
* method. */
|
|
694
|
-
restRequest({
|
|
695
|
-
url: 'resource',
|
|
696
|
-
method: 'POST',
|
|
697
|
-
data: { resources: resources, progress: true },
|
|
698
|
-
headers: { 'X-HTTP-Method-Override': 'DELETE' }
|
|
699
|
-
}).done(() => {
|
|
700
|
-
if (items && items.length && this.parentModel.has('nItems')) {
|
|
701
|
-
this.parentModel.increment('nItems', -items.length);
|
|
702
|
-
}
|
|
703
|
-
if (folders.length && this.parentModel.has('nFolders')) {
|
|
704
|
-
this.parentModel.increment('nFolders', -folders.length);
|
|
705
|
-
}
|
|
706
|
-
if (this.parentModel.has('size') && resourceSize.items) {
|
|
707
|
-
this.parentModel.increment('size', -resourceSize.items);
|
|
708
|
-
}
|
|
709
|
-
this.setCurrentModel(this.parentModel, { setRoute: false });
|
|
710
|
-
});
|
|
711
|
-
}
|
|
712
|
-
};
|
|
713
|
-
confirm(params);
|
|
714
|
-
},
|
|
715
|
-
|
|
716
|
-
/**
|
|
717
|
-
* Show and handle the upload dialog
|
|
718
|
-
*/
|
|
719
|
-
uploadDialog: function () {
|
|
720
|
-
var container = $('#g-dialog-container');
|
|
721
|
-
|
|
722
|
-
new UploadWidget({
|
|
723
|
-
el: container,
|
|
724
|
-
parent: this.parentModel,
|
|
725
|
-
parentType: this.parentType,
|
|
726
|
-
parentView: this
|
|
727
|
-
}).on('g:uploadFinished', function (info) {
|
|
728
|
-
handleClose('upload');
|
|
729
|
-
this.upload = false;
|
|
730
|
-
if (this.parentModel.has('nItems')) {
|
|
731
|
-
this.parentModel.increment('nItems', info.files.length);
|
|
732
|
-
}
|
|
733
|
-
if (this.parentModel.has('size')) {
|
|
734
|
-
this.parentModel.increment('size', info.totalSize);
|
|
735
|
-
}
|
|
736
|
-
this.setCurrentModel(this.parentModel, { setRoute: false });
|
|
737
|
-
}, this).render();
|
|
738
|
-
},
|
|
739
|
-
|
|
740
|
-
/**
|
|
741
|
-
* When any of the checkboxes is changed, this will be called to update
|
|
742
|
-
* the checked menu state.
|
|
743
|
-
*/
|
|
744
|
-
updateChecked: function () {
|
|
745
|
-
var folders = this.folderListView.checked,
|
|
746
|
-
items = [];
|
|
747
|
-
|
|
748
|
-
// Only show actions corresponding to the minimum access level over
|
|
749
|
-
// the whole set of checked resources.
|
|
750
|
-
var minFolderLevel = AccessType.ADMIN;
|
|
751
|
-
_.every(folders, function (cid) {
|
|
752
|
-
var folder = this.folderListView.collection.get(cid);
|
|
753
|
-
minFolderLevel = Math.min(minFolderLevel, folder.getAccessLevel());
|
|
754
|
-
return minFolderLevel > AccessType.READ; // acts as 'break'
|
|
755
|
-
}, this);
|
|
756
|
-
|
|
757
|
-
var minItemLevel = AccessType.ADMIN;
|
|
758
|
-
if (this.itemListView) {
|
|
759
|
-
items = this.itemListView.checked;
|
|
760
|
-
if (items.length) {
|
|
761
|
-
minItemLevel = Math.min(minItemLevel, this.parentModel.getAccessLevel());
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
// Disable folder actions if checkboxes are checked
|
|
766
|
-
const anyChecked = folders.length + items.length > 0;
|
|
767
|
-
this.$('.g-folder-actions-button').girderEnable(!anyChecked);
|
|
768
|
-
|
|
769
|
-
this.checkedMenuWidget.update({
|
|
770
|
-
minFolderLevel: minFolderLevel,
|
|
771
|
-
minItemLevel: minItemLevel,
|
|
772
|
-
folderCount: folders.length,
|
|
773
|
-
itemCount: items.length,
|
|
774
|
-
pickedCount: this.getPickedCount(),
|
|
775
|
-
pickedCopyAllowed: this.getPickedCopyAllowed(),
|
|
776
|
-
pickedMoveAllowed: this.getPickedMoveAllowed(),
|
|
777
|
-
pickedDesc: this.getPickedDescription()
|
|
778
|
-
});
|
|
779
|
-
},
|
|
780
|
-
|
|
781
|
-
getPickedCount: function () {
|
|
782
|
-
var pickedCount = 0;
|
|
783
|
-
if (pickedResources && pickedResources.resources) {
|
|
784
|
-
_.each(pickedResources.resources, function (list) {
|
|
785
|
-
pickedCount += list.length;
|
|
786
|
-
});
|
|
787
|
-
}
|
|
788
|
-
return pickedCount;
|
|
789
|
-
},
|
|
790
|
-
|
|
791
|
-
getPickedCopyAllowed: function () {
|
|
792
|
-
/* We must have something picked */
|
|
793
|
-
if (!pickedResources) {
|
|
794
|
-
return false;
|
|
795
|
-
}
|
|
796
|
-
/* If we have an item picked but this page isn't a folder's list, then
|
|
797
|
-
* you can't move or copy them here. */
|
|
798
|
-
if (this.parentModel.resourceName !== 'folder') {
|
|
799
|
-
if (pickedResources.resources.item &&
|
|
800
|
-
pickedResources.resources.item.length) {
|
|
801
|
-
return false;
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
/* We must have permission to write to this folder to be allowed to
|
|
805
|
-
* copy. */
|
|
806
|
-
if (this.parentModel.getAccessLevel() < AccessType.WRITE) {
|
|
807
|
-
return false;
|
|
808
|
-
}
|
|
809
|
-
return true;
|
|
810
|
-
},
|
|
811
|
-
|
|
812
|
-
getPickedMoveAllowed: function () {
|
|
813
|
-
/* All of the restrictions for copy are the same */
|
|
814
|
-
if (!this.getPickedCopyAllowed()) {
|
|
815
|
-
return false;
|
|
816
|
-
}
|
|
817
|
-
/* We also can't move an item or folder if we don't have permission to
|
|
818
|
-
* delete that item or folder (since a move deletes it from the
|
|
819
|
-
* original spot). */
|
|
820
|
-
if (pickedResources.minFolderLevel < AccessType.ADMIN) {
|
|
821
|
-
return false;
|
|
822
|
-
}
|
|
823
|
-
if (pickedResources.minItemLevel < AccessType.WRITE) {
|
|
824
|
-
return false;
|
|
825
|
-
}
|
|
826
|
-
return true;
|
|
827
|
-
},
|
|
828
|
-
|
|
829
|
-
getPickedDescription: function () {
|
|
830
|
-
if (!pickedResources || !pickedResources.resources) {
|
|
831
|
-
return '';
|
|
832
|
-
}
|
|
833
|
-
return this._describeResources(pickedResources.resources);
|
|
834
|
-
},
|
|
835
|
-
|
|
836
|
-
/**
|
|
837
|
-
* Get a parameter that can be added to a url for the checked resources.
|
|
838
|
-
*/
|
|
839
|
-
_getCheckedResourceParam: function (asObject) {
|
|
840
|
-
var resources = { folder: [], item: [] };
|
|
841
|
-
var folders = this.folderListView.checked;
|
|
842
|
-
_.each(folders, function (cid) {
|
|
843
|
-
var folder = this.folderListView.collection.get(cid);
|
|
844
|
-
resources.folder.push(folder.id);
|
|
845
|
-
}, this);
|
|
846
|
-
if (this.itemListView) {
|
|
847
|
-
var items = this.itemListView.checked;
|
|
848
|
-
_.each(items, function (cid) {
|
|
849
|
-
var item = this.itemListView.collection.get(cid);
|
|
850
|
-
resources.item.push(item.id);
|
|
851
|
-
}, this);
|
|
852
|
-
}
|
|
853
|
-
_.each(resources, function (list, key) {
|
|
854
|
-
if (!list.length) {
|
|
855
|
-
delete resources[key];
|
|
856
|
-
}
|
|
857
|
-
});
|
|
858
|
-
if (asObject) {
|
|
859
|
-
return resources;
|
|
860
|
-
}
|
|
861
|
-
return JSON.stringify(resources);
|
|
862
|
-
},
|
|
863
|
-
|
|
864
|
-
/**
|
|
865
|
-
* Get the sum of the sizes of checked resources.
|
|
866
|
-
*/
|
|
867
|
-
_getCheckedResourceSize: function () {
|
|
868
|
-
var totalSize = { items: 0, folders: 0 };
|
|
869
|
-
var folders = this.folderListView.checked;
|
|
870
|
-
_.each(folders, function (cid) {
|
|
871
|
-
var folder = this.folderListView.collection.get(cid);
|
|
872
|
-
totalSize.folders += (folder.get('size') || 0);
|
|
873
|
-
}, this);
|
|
874
|
-
if (this.itemListView) {
|
|
875
|
-
var items = this.itemListView.checked;
|
|
876
|
-
_.each(items, function (cid) {
|
|
877
|
-
var item = this.itemListView.collection.get(cid);
|
|
878
|
-
totalSize.items += (item.get('size') || 0);
|
|
879
|
-
}, this);
|
|
880
|
-
}
|
|
881
|
-
return totalSize;
|
|
882
|
-
},
|
|
883
|
-
|
|
884
|
-
downloadChecked: function () {
|
|
885
|
-
var url = getApiRoot() + '/resource/download';
|
|
886
|
-
var resources = this._getCheckedResourceParam();
|
|
887
|
-
var data = { resources: resources };
|
|
888
|
-
|
|
889
|
-
this.redirectViaForm('POST', url, data);
|
|
890
|
-
},
|
|
891
|
-
|
|
892
|
-
pickChecked: function () {
|
|
893
|
-
if (!pickedResources) {
|
|
894
|
-
pickedResources = {
|
|
895
|
-
resources: {},
|
|
896
|
-
minItemLevel: AccessType.ADMIN,
|
|
897
|
-
minFolderLevel: AccessType.ADMIN
|
|
898
|
-
};
|
|
899
|
-
}
|
|
900
|
-
/* Maintain our minimum permissions. It is expensive to compute them
|
|
901
|
-
* arbitrarily later. */
|
|
902
|
-
var folders = this.folderListView.checked;
|
|
903
|
-
_.every(folders, function (cid) {
|
|
904
|
-
var folder = this.folderListView.collection.get(cid);
|
|
905
|
-
pickedResources.minFolderLevel = Math.min(
|
|
906
|
-
pickedResources.minFolderLevel,
|
|
907
|
-
folder.getAccessLevel());
|
|
908
|
-
return (pickedResources.minFolderLevel >
|
|
909
|
-
AccessType.READ); // acts as 'break'
|
|
910
|
-
}, this);
|
|
911
|
-
if (this.itemListView) {
|
|
912
|
-
var items = this.itemListView.checked;
|
|
913
|
-
if (items.length) {
|
|
914
|
-
pickedResources.minItemLevel = Math.min(
|
|
915
|
-
pickedResources.minItemLevel,
|
|
916
|
-
this.parentModel.getAccessLevel());
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
var resources = this._getCheckedResourceParam(true);
|
|
920
|
-
var pickDesc = this._describeResources(resources);
|
|
921
|
-
/* Merge these resources with any that are already picked */
|
|
922
|
-
var existing = pickedResources.resources;
|
|
923
|
-
_.each(existing, function (list, resource) {
|
|
924
|
-
if (!resources[resource]) {
|
|
925
|
-
resources[resource] = list;
|
|
926
|
-
} else {
|
|
927
|
-
resources[resource] = _.union(list, resources[resource]);
|
|
928
|
-
}
|
|
929
|
-
});
|
|
930
|
-
pickedResources.resources = resources;
|
|
931
|
-
this.updateChecked();
|
|
932
|
-
var totalPickDesc = this.getPickedDescription();
|
|
933
|
-
var desc = totalPickDesc + ' picked.';
|
|
934
|
-
if (pickDesc !== totalPickDesc) {
|
|
935
|
-
desc = pickDesc + ' added to picked resources. Now ' + desc;
|
|
936
|
-
}
|
|
937
|
-
events.trigger('g:alert', {
|
|
938
|
-
icon: 'ok',
|
|
939
|
-
text: desc,
|
|
940
|
-
type: 'info',
|
|
941
|
-
timeout: 4000
|
|
942
|
-
});
|
|
943
|
-
},
|
|
944
|
-
|
|
945
|
-
_incrementCounts: function (nFolders, nItems) {
|
|
946
|
-
if (this.parentModel.has('nItems')) {
|
|
947
|
-
this.parentModel.increment('nItems', nItems);
|
|
948
|
-
}
|
|
949
|
-
if (this.parentModel.has('nFolders')) {
|
|
950
|
-
this.parentModel.increment('nFolders', nFolders);
|
|
951
|
-
}
|
|
952
|
-
},
|
|
953
|
-
|
|
954
|
-
movePickedResources: function () {
|
|
955
|
-
if (!this.getPickedMoveAllowed()) {
|
|
956
|
-
return;
|
|
957
|
-
}
|
|
958
|
-
var resources = JSON.stringify(pickedResources.resources);
|
|
959
|
-
var nFolders = (pickedResources.resources.folder || []).length;
|
|
960
|
-
var nItems = (pickedResources.resources.item || []).length;
|
|
961
|
-
restRequest({
|
|
962
|
-
url: 'resource/move',
|
|
963
|
-
method: 'PUT',
|
|
964
|
-
data: {
|
|
965
|
-
resources: resources,
|
|
966
|
-
parentType: this.parentModel.resourceName,
|
|
967
|
-
parentId: this.parentModel.get('_id'),
|
|
968
|
-
progress: true
|
|
969
|
-
}
|
|
970
|
-
}).done(() => {
|
|
971
|
-
this._incrementCounts(nFolders, nItems);
|
|
972
|
-
this.setCurrentModel(this.parentModel, { setRoute: false });
|
|
973
|
-
});
|
|
974
|
-
this.clearPickedResources();
|
|
975
|
-
},
|
|
976
|
-
|
|
977
|
-
copyPickedResources: function () {
|
|
978
|
-
if (!this.getPickedCopyAllowed()) {
|
|
979
|
-
return;
|
|
980
|
-
}
|
|
981
|
-
var resources = JSON.stringify(pickedResources.resources);
|
|
982
|
-
var nFolders = (pickedResources.resources.folder || []).length;
|
|
983
|
-
var nItems = (pickedResources.resources.item || []).length;
|
|
984
|
-
restRequest({
|
|
985
|
-
url: 'resource/copy',
|
|
986
|
-
method: 'POST',
|
|
987
|
-
data: {
|
|
988
|
-
resources: resources,
|
|
989
|
-
parentType: this.parentModel.resourceName,
|
|
990
|
-
parentId: this.parentModel.get('_id'),
|
|
991
|
-
progress: true
|
|
992
|
-
}
|
|
993
|
-
}).done(() => {
|
|
994
|
-
this._incrementCounts(nFolders, nItems);
|
|
995
|
-
this.setCurrentModel(this.parentModel, { setRoute: false });
|
|
996
|
-
});
|
|
997
|
-
this.clearPickedResources();
|
|
998
|
-
},
|
|
999
|
-
|
|
1000
|
-
clearPickedResources: function (event) {
|
|
1001
|
-
this.constructor.resetPickedResources();
|
|
1002
|
-
this.updateChecked();
|
|
1003
|
-
if (event) {
|
|
1004
|
-
events.trigger('g:alert', {
|
|
1005
|
-
icon: 'ok',
|
|
1006
|
-
text: 'Cleared picked resources',
|
|
1007
|
-
type: 'info',
|
|
1008
|
-
timeout: 4000
|
|
1009
|
-
});
|
|
1010
|
-
}
|
|
1011
|
-
},
|
|
1012
|
-
|
|
1013
|
-
redirectViaForm: function (method, url, data) {
|
|
1014
|
-
var form = $('<form/>').attr({ action: url, method: method });
|
|
1015
|
-
_.each(data, function (value, key) {
|
|
1016
|
-
form.append($('<input/>').attr({ type: 'text', name: key, value: value }));
|
|
1017
|
-
});
|
|
1018
|
-
// $(form).trigger('submit') will *not* work w/ Firefox (http://stackoverflow.com/q/7117084/250457)
|
|
1019
|
-
$(form).appendTo('body').trigger('submit').remove();
|
|
1020
|
-
},
|
|
1021
|
-
|
|
1022
|
-
editAccess: function () {
|
|
1023
|
-
new AccessWidget({
|
|
1024
|
-
el: $('#g-dialog-container'),
|
|
1025
|
-
modelType: this.parentModel.resourceName,
|
|
1026
|
-
model: this.parentModel,
|
|
1027
|
-
parentView: this
|
|
1028
|
-
}).on('g:accessListSaved', function (params) {
|
|
1029
|
-
if (params.recurse) {
|
|
1030
|
-
// Refresh list since the public flag may have changed on the children.
|
|
1031
|
-
this.refreshFolderList();
|
|
1032
|
-
}
|
|
1033
|
-
}, this);
|
|
1034
|
-
},
|
|
1035
|
-
|
|
1036
|
-
/**
|
|
1037
|
-
* Reloads the folder list view.
|
|
1038
|
-
*/
|
|
1039
|
-
refreshFolderList: function () {
|
|
1040
|
-
this.folderListView.collection.fetch(null, true);
|
|
1041
|
-
},
|
|
1042
|
-
|
|
1043
|
-
/**
|
|
1044
|
-
* Select (highlight) an item in the list.
|
|
1045
|
-
* @param item An ItemModel instance representing the item to select.
|
|
1046
|
-
*/
|
|
1047
|
-
selectItem: function (item) {
|
|
1048
|
-
this.itemListView.selectItem(item);
|
|
1049
|
-
},
|
|
1050
|
-
|
|
1051
|
-
/**
|
|
1052
|
-
* Return the currently selected item, or null if there is no selected item.
|
|
1053
|
-
*/
|
|
1054
|
-
getSelectedItem: function () {
|
|
1055
|
-
return this.itemListView.getSelectedItem();
|
|
1056
|
-
},
|
|
1057
|
-
|
|
1058
|
-
/**
|
|
1059
|
-
* In order to handle range selection, we must listen to checkbox changes
|
|
1060
|
-
* at this level, in case a range selection crosses the boundary between
|
|
1061
|
-
* folders and items.
|
|
1062
|
-
*/
|
|
1063
|
-
checkboxListener: function (e) {
|
|
1064
|
-
var checkbox = $(e.currentTarget);
|
|
1065
|
-
|
|
1066
|
-
if (this._lastCheckbox) {
|
|
1067
|
-
if (e.shiftKey) {
|
|
1068
|
-
var checkboxes = this.$el.find(':checkbox');
|
|
1069
|
-
var from = checkboxes.index(this._lastCheckbox);
|
|
1070
|
-
var to = checkboxes.index(checkbox);
|
|
1071
|
-
|
|
1072
|
-
checkboxes.slice(Math.min(from, to), Math.max(from, to) + 1)
|
|
1073
|
-
.prop('checked', checkbox.prop('checked'));
|
|
1074
|
-
|
|
1075
|
-
this.folderListView.recomputeChecked();
|
|
1076
|
-
|
|
1077
|
-
if (this.itemListView) {
|
|
1078
|
-
this.itemListView.recomputeChecked();
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
this.updateChecked();
|
|
1082
|
-
}
|
|
1083
|
-
}
|
|
1084
|
-
this._lastCheckbox = checkbox;
|
|
1085
|
-
}
|
|
1086
|
-
}, {
|
|
1087
|
-
/* Because we need to be able to clear picked resources when the current user
|
|
1088
|
-
* changes, this function is placed in the girder namespace. */
|
|
1089
|
-
resetPickedResources: function (val) {
|
|
1090
|
-
pickedResources = val || null;
|
|
1091
|
-
},
|
|
1092
|
-
getPickedResources: function () {
|
|
1093
|
-
return pickedResources;
|
|
1094
|
-
}
|
|
1095
|
-
});
|
|
1096
|
-
|
|
1097
|
-
export default HierarchyWidget;
|