@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.
Files changed (231) hide show
  1. package/README.md +61 -0
  2. package/package.json +79 -31
  3. package/assets/Girder_Mark.png +0 -0
  4. package/auth.js +0 -152
  5. package/collections/ApiKeyCollection.js +0 -9
  6. package/collections/AssetstoreCollection.js +0 -9
  7. package/collections/Collection.js +0 -295
  8. package/collections/CollectionCollection.js +0 -9
  9. package/collections/FileCollection.js +0 -11
  10. package/collections/FolderCollection.js +0 -11
  11. package/collections/GroupCollection.js +0 -9
  12. package/collections/ItemCollection.js +0 -11
  13. package/collections/UserCollection.js +0 -24
  14. package/collections/index.js +0 -21
  15. package/constants.js +0 -33
  16. package/dialog.js +0 -128
  17. package/events.js +0 -6
  18. package/index.js +0 -31
  19. package/main.js +0 -21
  20. package/misc.js +0 -260
  21. package/models/AccessControlledModel.js +0 -76
  22. package/models/ApiKeyModel.js +0 -31
  23. package/models/AssetstoreModel.js +0 -43
  24. package/models/CollectionCreationPolicyModel.js +0 -20
  25. package/models/CollectionModel.js +0 -12
  26. package/models/FileModel.js +0 -310
  27. package/models/FolderModel.js +0 -33
  28. package/models/GroupModel.js +0 -197
  29. package/models/ItemModel.js +0 -72
  30. package/models/MetadataMixin.js +0 -88
  31. package/models/Model.js +0 -187
  32. package/models/UserModel.js +0 -189
  33. package/models/index.js +0 -25
  34. package/pluginUtils.js +0 -11
  35. package/rest.js +0 -216
  36. package/router.js +0 -58
  37. package/routes.js +0 -231
  38. package/stylesheets/apidocs/apidocs.styl +0 -50
  39. package/stylesheets/body/adminConsole.styl +0 -21
  40. package/stylesheets/body/assetstores.styl +0 -46
  41. package/stylesheets/body/collectionList.styl +0 -39
  42. package/stylesheets/body/collectionPage.styl +0 -6
  43. package/stylesheets/body/frontPage.styl +0 -48
  44. package/stylesheets/body/groupList.styl +0 -43
  45. package/stylesheets/body/groupPage.styl +0 -116
  46. package/stylesheets/body/itemPage.styl +0 -81
  47. package/stylesheets/body/plugins.styl +0 -61
  48. package/stylesheets/body/searchResultsList.styl +0 -51
  49. package/stylesheets/body/systemConfig.styl +0 -56
  50. package/stylesheets/body/userAccount.styl +0 -57
  51. package/stylesheets/body/userList.styl +0 -79
  52. package/stylesheets/body/userPage.styl +0 -6
  53. package/stylesheets/layout/footer.styl +0 -19
  54. package/stylesheets/layout/global.styl +0 -154
  55. package/stylesheets/layout/globalNav.styl +0 -89
  56. package/stylesheets/layout/header.styl +0 -29
  57. package/stylesheets/layout/headerUser.styl +0 -33
  58. package/stylesheets/layout/layout.styl +0 -75
  59. package/stylesheets/layout/layoutVars.styl +0 -9
  60. package/stylesheets/layout/loading.styl +0 -37
  61. package/stylesheets/layout/progressArea.styl +0 -17
  62. package/stylesheets/widgets/accessWidget.styl +0 -106
  63. package/stylesheets/widgets/browserWidget.styl +0 -9
  64. package/stylesheets/widgets/hierarchyWidget.styl +0 -188
  65. package/stylesheets/widgets/markdownWidget.styl +0 -92
  66. package/stylesheets/widgets/metadataWidget.styl +0 -92
  67. package/stylesheets/widgets/searchFieldWidget.styl +0 -70
  68. package/stylesheets/widgets/taskProgress.styl +0 -41
  69. package/stylesheets/widgets/timelineWidget.styl +0 -41
  70. package/stylesheets/widgets/uploadWidget.styl +0 -43
  71. package/stylesheets/widgets/userOtpManagementWidget.styl +0 -159
  72. package/templates/body/adminConsole.pug +0 -13
  73. package/templates/body/assetstores.pug +0 -98
  74. package/templates/body/collectionList.pug +0 -40
  75. package/templates/body/collectionPage.pug +0 -36
  76. package/templates/body/filesystemImport.pug +0 -41
  77. package/templates/body/frontPage.pug +0 -83
  78. package/templates/body/groupList.pug +0 -30
  79. package/templates/body/groupPage.pug +0 -116
  80. package/templates/body/itemPage.pug +0 -61
  81. package/templates/body/plugins.pug +0 -20
  82. package/templates/body/s3Import.pug +0 -35
  83. package/templates/body/searchResults.pug +0 -15
  84. package/templates/body/searchResultsType.pug +0 -13
  85. package/templates/body/systemConfiguration.pug +0 -221
  86. package/templates/body/userAccount.pug +0 -83
  87. package/templates/body/userList.pug +0 -43
  88. package/templates/body/userPage.pug +0 -40
  89. package/templates/layout/alert.pug +0 -5
  90. package/templates/layout/layout.pug +0 -12
  91. package/templates/layout/layoutFooter.pug +0 -11
  92. package/templates/layout/layoutGlobalNav.pug +0 -7
  93. package/templates/layout/layoutHeader.pug +0 -8
  94. package/templates/layout/layoutHeaderUser.pug +0 -26
  95. package/templates/layout/layoutProgressArea.pug +0 -1
  96. package/templates/layout/loginDialog.pug +0 -30
  97. package/templates/layout/registerDialog.pug +0 -35
  98. package/templates/layout/resetPasswordDialog.pug +0 -25
  99. package/templates/widgets/accessEditor.pug +0 -23
  100. package/templates/widgets/accessEditorMixins.pug +0 -57
  101. package/templates/widgets/accessEditorNonModal.pug +0 -11
  102. package/templates/widgets/accessEntry.pug +0 -32
  103. package/templates/widgets/apiKeyList.pug +0 -50
  104. package/templates/widgets/browserWidget.pug +0 -32
  105. package/templates/widgets/checkedActionsMenu.pug +0 -46
  106. package/templates/widgets/collectionInfoDialog.pug +0 -37
  107. package/templates/widgets/confirmDialog.pug +0 -14
  108. package/templates/widgets/dateTimeRangeWidget.pug +0 -20
  109. package/templates/widgets/dateTimeWidget.pug +0 -8
  110. package/templates/widgets/editApiKeyWidget.pug +0 -43
  111. package/templates/widgets/editAssetstoreWidget.pug +0 -78
  112. package/templates/widgets/editCollectionWidget.pug +0 -27
  113. package/templates/widgets/editFileWidget.pug +0 -21
  114. package/templates/widgets/editFolderWidget.pug +0 -27
  115. package/templates/widgets/editGroupWidget.pug +0 -54
  116. package/templates/widgets/editItemWidget.pug +0 -27
  117. package/templates/widgets/fileInfoDialog.pug +0 -33
  118. package/templates/widgets/fileList.pug +0 -33
  119. package/templates/widgets/folderInfoDialog.pug +0 -42
  120. package/templates/widgets/folderList.pug +0 -21
  121. package/templates/widgets/groupAdminList.pug +0 -33
  122. package/templates/widgets/groupInviteDialog.pug +0 -76
  123. package/templates/widgets/groupInviteList.pug +0 -14
  124. package/templates/widgets/groupMemberList.pug +0 -39
  125. package/templates/widgets/groupModList.pug +0 -23
  126. package/templates/widgets/hierarchyBreadcrumb.pug +0 -37
  127. package/templates/widgets/hierarchyPaginated.pug +0 -19
  128. package/templates/widgets/hierarchyWidget.pug +0 -96
  129. package/templates/widgets/itemBreadcrumb.pug +0 -16
  130. package/templates/widgets/itemList.pug +0 -27
  131. package/templates/widgets/jsonMetadatumEditWidget.pug +0 -13
  132. package/templates/widgets/jsonMetadatumView.pug +0 -6
  133. package/templates/widgets/loadingAnimation.pug +0 -4
  134. package/templates/widgets/markdownWidget.pug +0 -34
  135. package/templates/widgets/metadataWidget.pug +0 -16
  136. package/templates/widgets/metadatumEditWidget.pug +0 -15
  137. package/templates/widgets/metadatumView.pug +0 -5
  138. package/templates/widgets/newAssetstore.pug +0 -118
  139. package/templates/widgets/paginateWidget.pug +0 -7
  140. package/templates/widgets/pluginConfigBreadcrumb.pug +0 -13
  141. package/templates/widgets/rootSelectorWidget.pug +0 -13
  142. package/templates/widgets/searchField.pug +0 -10
  143. package/templates/widgets/searchHelp.pug +0 -12
  144. package/templates/widgets/searchModeSelect.pug +0 -9
  145. package/templates/widgets/searchResults.pug +0 -14
  146. package/templates/widgets/sortCollectionWidget.pug +0 -14
  147. package/templates/widgets/taskProgress.pug +0 -16
  148. package/templates/widgets/timeline.pug +0 -15
  149. package/templates/widgets/uploadWidget.pug +0 -15
  150. package/templates/widgets/uploadWidgetMixins.pug +0 -31
  151. package/templates/widgets/uploadWidgetNonModal.pug +0 -10
  152. package/templates/widgets/userOtpBegin.pug +0 -4
  153. package/templates/widgets/userOtpDisable.pug +0 -6
  154. package/templates/widgets/userOtpEnable.pug +0 -44
  155. package/utilities/EventStream.js +0 -177
  156. package/utilities/PluginUtils.js +0 -36
  157. package/utilities/S3UploadHandler.js +0 -303
  158. package/utilities/index.js +0 -9
  159. package/utilities/jquery/girderEnable.js +0 -19
  160. package/utilities/jquery/girderModal.js +0 -48
  161. package/version.js +0 -10
  162. package/views/App.js +0 -359
  163. package/views/View.js +0 -78
  164. package/views/body/AdminView.js +0 -29
  165. package/views/body/AssetstoresView.js +0 -235
  166. package/views/body/CollectionView.js +0 -188
  167. package/views/body/CollectionsView.js +0 -120
  168. package/views/body/FilesystemImportView.js +0 -83
  169. package/views/body/FolderView.js +0 -54
  170. package/views/body/FrontPageView.js +0 -47
  171. package/views/body/GroupView.js +0 -336
  172. package/views/body/GroupsView.js +0 -106
  173. package/views/body/ItemView.js +0 -177
  174. package/views/body/PluginsView.js +0 -73
  175. package/views/body/S3ImportView.js +0 -80
  176. package/views/body/SearchResultsView.js +0 -162
  177. package/views/body/SystemConfigurationView.js +0 -196
  178. package/views/body/UserAccountView.js +0 -179
  179. package/views/body/UserView.js +0 -165
  180. package/views/body/UsersView.js +0 -124
  181. package/views/body/index.js +0 -37
  182. package/views/index.js +0 -13
  183. package/views/layout/FooterView.js +0 -29
  184. package/views/layout/GlobalNavView.js +0 -103
  185. package/views/layout/HeaderUserView.js +0 -45
  186. package/views/layout/HeaderView.js +0 -83
  187. package/views/layout/LoginView.js +0 -100
  188. package/views/layout/ProgressListView.js +0 -70
  189. package/views/layout/RegisterView.js +0 -101
  190. package/views/layout/ResetPasswordView.js +0 -70
  191. package/views/layout/index.js +0 -19
  192. package/views/widgets/AccessWidget.js +0 -427
  193. package/views/widgets/ApiKeyListWidget.js +0 -140
  194. package/views/widgets/BrowserWidget.js +0 -317
  195. package/views/widgets/CheckedMenuWidget.js +0 -68
  196. package/views/widgets/CollectionInfoWidget.js +0 -40
  197. package/views/widgets/DateTimeRangeWidget.js +0 -179
  198. package/views/widgets/DateTimeWidget.js +0 -109
  199. package/views/widgets/EditApiKeyWidget.js +0 -122
  200. package/views/widgets/EditAssetstoreWidget.js +0 -148
  201. package/views/widgets/EditCollectionWidget.js +0 -93
  202. package/views/widgets/EditFileWidget.js +0 -56
  203. package/views/widgets/EditFolderWidget.js +0 -116
  204. package/views/widgets/EditGroupWidget.js +0 -125
  205. package/views/widgets/EditItemWidget.js +0 -110
  206. package/views/widgets/FileInfoWidget.js +0 -26
  207. package/views/widgets/FileListWidget.js +0 -151
  208. package/views/widgets/FolderInfoWidget.js +0 -39
  209. package/views/widgets/FolderListWidget.js +0 -106
  210. package/views/widgets/GroupAdminsWidget.js +0 -88
  211. package/views/widgets/GroupInvitesWidget.js +0 -56
  212. package/views/widgets/GroupMembersWidget.js +0 -185
  213. package/views/widgets/GroupModsWidget.js +0 -77
  214. package/views/widgets/HierarchyWidget.js +0 -1097
  215. package/views/widgets/ItemBreadcrumbWidget.js +0 -38
  216. package/views/widgets/ItemListWidget.js +0 -345
  217. package/views/widgets/LoadingAnimation.js +0 -17
  218. package/views/widgets/MarkdownWidget.js +0 -217
  219. package/views/widgets/MetadataWidget.js +0 -504
  220. package/views/widgets/NewAssetstoreWidget.js +0 -81
  221. package/views/widgets/PaginateWidget.js +0 -37
  222. package/views/widgets/PluginConfigBreadcrumbWidget.js +0 -33
  223. package/views/widgets/RootSelectorWidget.js +0 -192
  224. package/views/widgets/SearchFieldWidget.js +0 -365
  225. package/views/widgets/SearchPaginateWidget.js +0 -149
  226. package/views/widgets/SortCollectionWidget.js +0 -53
  227. package/views/widgets/TaskProgressWidget.js +0 -91
  228. package/views/widgets/TimelineWidget.js +0 -155
  229. package/views/widgets/UploadWidget.js +0 -340
  230. package/views/widgets/UserOtpManagementWidget.js +0 -105
  231. 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;