@girder/core 3.2.3 → 5.0.0-beta.1
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 -84
- 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,38 +0,0 @@
|
|
|
1
|
-
import $ from 'jquery';
|
|
2
|
-
|
|
3
|
-
import router from '@girder/core/router';
|
|
4
|
-
import View from '@girder/core/views/View';
|
|
5
|
-
|
|
6
|
-
import ItemBreadcrumbTemplate from '@girder/core/templates/widgets/itemBreadcrumb.pug';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Renders the a breadcrumb for the item page
|
|
10
|
-
*/
|
|
11
|
-
var ItemBreadcrumbWidget = View.extend({
|
|
12
|
-
events: {
|
|
13
|
-
'click a.g-item-breadcrumb-link': function (event) {
|
|
14
|
-
var link = $(event.currentTarget);
|
|
15
|
-
router.navigate(link.data('type') + '/' + link.data('id'),
|
|
16
|
-
{ trigger: true });
|
|
17
|
-
},
|
|
18
|
-
'click a.g-hierarchy-level-up': function () {
|
|
19
|
-
var folder = this.parentChain.pop().object;
|
|
20
|
-
router.navigate('folder/' + folder._id, { trigger: true });
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
initialize: function (settings) {
|
|
25
|
-
this.parentChain = settings.parentChain;
|
|
26
|
-
this.render();
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
render: function () {
|
|
30
|
-
this.$el.html(ItemBreadcrumbTemplate({
|
|
31
|
-
parentChain: this.parentChain
|
|
32
|
-
}));
|
|
33
|
-
|
|
34
|
-
return this;
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
export default ItemBreadcrumbWidget;
|
|
@@ -1,345 +0,0 @@
|
|
|
1
|
-
import $ from 'jquery';
|
|
2
|
-
import _ from 'underscore';
|
|
3
|
-
|
|
4
|
-
import ItemCollection from '@girder/core/collections/ItemCollection';
|
|
5
|
-
import LoadingAnimation from '@girder/core/views/widgets/LoadingAnimation';
|
|
6
|
-
import View from '@girder/core/views/View';
|
|
7
|
-
import { formatSize } from '@girder/core/misc';
|
|
8
|
-
import { restRequest } from '@girder/core/rest';
|
|
9
|
-
|
|
10
|
-
import ItemListTemplate from '@girder/core/templates/widgets/itemList.pug';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* This widget shows a list of items under a given folder.
|
|
14
|
-
*/
|
|
15
|
-
var ItemListWidget = View.extend({
|
|
16
|
-
events: {
|
|
17
|
-
'click a.g-item-list-link': function (event) {
|
|
18
|
-
event.preventDefault();
|
|
19
|
-
var cid = $(event.currentTarget).attr('g-item-cid');
|
|
20
|
-
this.trigger('g:itemClicked', this.collection.get(cid), event);
|
|
21
|
-
},
|
|
22
|
-
'click a.g-show-more-items': function () {
|
|
23
|
-
this.collection.fetchNextPage();
|
|
24
|
-
},
|
|
25
|
-
'change .g-list-checkbox': function (event) {
|
|
26
|
-
const target = $(event.currentTarget);
|
|
27
|
-
const cid = target.attr('g-item-cid');
|
|
28
|
-
if (target.prop('checked')) {
|
|
29
|
-
this.checked.push(cid);
|
|
30
|
-
} else {
|
|
31
|
-
const idx = this.checked.indexOf(cid);
|
|
32
|
-
if (idx !== -1) {
|
|
33
|
-
this.checked.splice(idx, 1);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
this.trigger('g:checkboxesChanged');
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
initialize: function (settings) {
|
|
41
|
-
this.checked = [];
|
|
42
|
-
this._checkboxes = settings.checkboxes;
|
|
43
|
-
this._downloadLinks = (
|
|
44
|
-
_.has(settings, 'downloadLinks') ? settings.downloadLinks : true);
|
|
45
|
-
this._viewLinks = (
|
|
46
|
-
_.has(settings, 'viewLinks') ? settings.viewLinks : true);
|
|
47
|
-
this._showSizes = (
|
|
48
|
-
_.has(settings, 'showSizes') ? settings.showSizes : true);
|
|
49
|
-
this._highlightItem = (
|
|
50
|
-
_.has(settings, 'highlightItem') ? settings.highlightItem : false);
|
|
51
|
-
this._paginated = (
|
|
52
|
-
_.has(settings, 'paginated') ? settings.paginated : false);
|
|
53
|
-
|
|
54
|
-
this.accessLevel = settings.accessLevel;
|
|
55
|
-
this.public = settings.public;
|
|
56
|
-
this._selectedItem = settings.selectedItem;
|
|
57
|
-
|
|
58
|
-
new LoadingAnimation({
|
|
59
|
-
el: this.$el,
|
|
60
|
-
parentView: this
|
|
61
|
-
}).render();
|
|
62
|
-
|
|
63
|
-
this.collection = new ItemCollection();
|
|
64
|
-
this.collection.append = true; // Append, don't replace pages
|
|
65
|
-
this.collection.filterFunc = settings.itemFilter;
|
|
66
|
-
this.currentPage = 1; // By default we want to be on the first page
|
|
67
|
-
|
|
68
|
-
if (this._paginated) {
|
|
69
|
-
if (this.collection.filterFunc) {
|
|
70
|
-
console.warn('Pagination cannot be used with a filter function');
|
|
71
|
-
this._paginated = false;
|
|
72
|
-
} else {
|
|
73
|
-
// Override the default to prevent appending new pages
|
|
74
|
-
this.collection.append = false;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
this.collection.fetch({ folderId: settings.folderId }).done(() => {
|
|
79
|
-
this._totalPages = Math.ceil(this.collection.getTotalCount() / this.collection.pageLimit);
|
|
80
|
-
if (this._paginated && this.collection.hasNextPage()) {
|
|
81
|
-
// Tells the parent container that the item is paginated so it can render the page selector
|
|
82
|
-
this.trigger('g:paginated');
|
|
83
|
-
// We need to get the position in the list for the selected item
|
|
84
|
-
if (this._selectedItem) {
|
|
85
|
-
restRequest({
|
|
86
|
-
url: `item/${this._selectedItem.get('_id')}/position`,
|
|
87
|
-
method: 'GET',
|
|
88
|
-
data: { folderId: this._selectedItem.get('folderId'), sort: 'name' }
|
|
89
|
-
}).done((val) => {
|
|
90
|
-
// Now we fetch the correct page for the position
|
|
91
|
-
val = Number(val);
|
|
92
|
-
if (val >= this.collection.pageLimit) {
|
|
93
|
-
const pageLimit = this.collection.pageLimit;
|
|
94
|
-
const calculatedPage = 1 + Math.ceil((val - (val % pageLimit)) / pageLimit);
|
|
95
|
-
return this.collection.fetchPage(calculatedPage - 1);
|
|
96
|
-
}
|
|
97
|
-
}).done(() => this.bindOnChanged());
|
|
98
|
-
} else {
|
|
99
|
-
this.bindOnChanged();
|
|
100
|
-
}
|
|
101
|
-
} else {
|
|
102
|
-
this.bindOnChanged();
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Binds the change function to the collection and calls it initially to update the render
|
|
109
|
-
*/
|
|
110
|
-
bindOnChanged: function () {
|
|
111
|
-
this.collection.on('g:changed', this.changedFunc, this);
|
|
112
|
-
this.changedFunc();
|
|
113
|
-
},
|
|
114
|
-
/**
|
|
115
|
-
* Function that causes a render each time the collection is changed
|
|
116
|
-
* Will also update the current page in a paginated system
|
|
117
|
-
*/
|
|
118
|
-
changedFunc: function () {
|
|
119
|
-
if (this.accessLevel !== undefined) {
|
|
120
|
-
this.collection.each((model) => {
|
|
121
|
-
model.set('_accessLevel', this.accessLevel);
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
if (this._paginated) {
|
|
125
|
-
this.currentPage = this.collection.pageNum() + 1;
|
|
126
|
-
}
|
|
127
|
-
this.render();
|
|
128
|
-
this.trigger('g:changed');
|
|
129
|
-
},
|
|
130
|
-
|
|
131
|
-
render: function () {
|
|
132
|
-
this.checked = [];
|
|
133
|
-
// If we set a selected item in the beginning we will center the selection while loading
|
|
134
|
-
if (this._selectedItem && this._highlightItem) {
|
|
135
|
-
this.scrollPositionObserver();
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
this.$el.html(ItemListTemplate({
|
|
139
|
-
items: this.collection.toArray(),
|
|
140
|
-
isParentPublic: this.public,
|
|
141
|
-
hasMore: this.collection.hasNextPage(),
|
|
142
|
-
formatSize: formatSize,
|
|
143
|
-
checkboxes: this._checkboxes,
|
|
144
|
-
downloadLinks: this._downloadLinks,
|
|
145
|
-
viewLinks: this._viewLinks,
|
|
146
|
-
showSizes: this._showSizes,
|
|
147
|
-
highlightItem: this._highlightItem,
|
|
148
|
-
selectedItemId: (this._selectedItem || {}).id,
|
|
149
|
-
paginated: this._paginated
|
|
150
|
-
|
|
151
|
-
}));
|
|
152
|
-
|
|
153
|
-
return this;
|
|
154
|
-
},
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* @returns {number} the number of pages in the itemList for use in a paginated view
|
|
158
|
-
*/
|
|
159
|
-
getNumPages() {
|
|
160
|
-
return this._totalPages || 1;
|
|
161
|
-
},
|
|
162
|
-
/**
|
|
163
|
-
* @returns {number} the current page for paginated lists, defaults to 1 if none is provided
|
|
164
|
-
*/
|
|
165
|
-
getCurrentPage() {
|
|
166
|
-
return this.currentPage || 1;
|
|
167
|
-
},
|
|
168
|
-
/**
|
|
169
|
-
* Externally facing function to allow hierarchyWidget and others to set the current page if the item is paginated
|
|
170
|
-
* @param {Number} page 1 index integer specifying the page to fetch
|
|
171
|
-
*/
|
|
172
|
-
setPage(page) {
|
|
173
|
-
if (this._paginated && this.collection && this.collection.fetchPage) {
|
|
174
|
-
this.currentPage = page;
|
|
175
|
-
return this.collection.fetchPage(page - 1).then(() =>
|
|
176
|
-
this.$el.parents('.g-hierarchy-widget-container').scrollTop(0));
|
|
177
|
-
}
|
|
178
|
-
},
|
|
179
|
-
/**
|
|
180
|
-
* Insert an item into the collection and re-render it.
|
|
181
|
-
*/
|
|
182
|
-
insertItem: function (item) {
|
|
183
|
-
if (this.accessLevel !== undefined) {
|
|
184
|
-
item.set('_accessLevel', this.accessLevel);
|
|
185
|
-
}
|
|
186
|
-
this.collection.add(item);
|
|
187
|
-
this.trigger('g:changed');
|
|
188
|
-
this.render();
|
|
189
|
-
},
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Set all item checkboxes to a certain checked state. The event
|
|
193
|
-
* g:checkboxesChanged is triggered once after checking/unchecking everything.
|
|
194
|
-
* @param {bool} checked The checked state.
|
|
195
|
-
*/
|
|
196
|
-
checkAll: function (checked) {
|
|
197
|
-
this.$('.g-list-checkbox').prop('checked', checked);
|
|
198
|
-
|
|
199
|
-
this.checked = [];
|
|
200
|
-
if (checked) {
|
|
201
|
-
this.collection.each(function (model) {
|
|
202
|
-
this.checked.push(model.cid);
|
|
203
|
-
}, this);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
this.trigger('g:checkboxesChanged');
|
|
207
|
-
},
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Select (highlight) an item in the list.
|
|
211
|
-
* @param item An ItemModel instance representing the item to select.
|
|
212
|
-
*/
|
|
213
|
-
selectItem: function (item) {
|
|
214
|
-
this.$('li.g-item-list-entry').removeClass('g-selected');
|
|
215
|
-
this.$('a.g-item-list-link[g-item-cid=' + item.cid + ']')
|
|
216
|
-
.parents('li.g-item-list-entry').addClass('g-selected');
|
|
217
|
-
},
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Return the currently selected item, or null if there is no selected item.
|
|
221
|
-
*/
|
|
222
|
-
getSelectedItem: function () {
|
|
223
|
-
var el = this.$('li.g-item-list-entry.g-selected');
|
|
224
|
-
if (!el.length) {
|
|
225
|
-
return null;
|
|
226
|
-
}
|
|
227
|
-
var cid = $('.g-item-list-link', $(el[0])).attr('g-item-cid');
|
|
228
|
-
return this.collection.get(cid);
|
|
229
|
-
},
|
|
230
|
-
|
|
231
|
-
recomputeChecked: function () {
|
|
232
|
-
this.checked = _.map(this.$('.g-list-checkbox:checked'), function (checkbox) {
|
|
233
|
-
return $(checkbox).attr('g-item-cid');
|
|
234
|
-
}, this);
|
|
235
|
-
},
|
|
236
|
-
|
|
237
|
-
centerSelected: function () {
|
|
238
|
-
const widgetcontainer = this.$el.parents('.g-hierarchy-widget-container');
|
|
239
|
-
const selected = this.$('li.g-item-list-entry.g-selected');
|
|
240
|
-
if (widgetcontainer.length > 0 && selected.length > 0) {
|
|
241
|
-
// These items will effect the scroll position if they exists
|
|
242
|
-
const folderHeight = $('.g-folder-list').length ? $('.g-folder-list').height() : 0;
|
|
243
|
-
const breadcrumbHeight = $('.g-hierarchy-breadcrumb-bar').length ? $('.g-hierarchy-breadcrumb-bar').height() : 0;
|
|
244
|
-
const selectedTop = selected.position().top;
|
|
245
|
-
// The selectedTop position needs to account for the breadcrumbHeight and the folderHeight
|
|
246
|
-
const scrollingPos = selectedTop + folderHeight + breadcrumbHeight;
|
|
247
|
-
const centerPos = (widgetcontainer.height() / 2.0) - (folderHeight / 2.0) - (breadcrumbHeight / 2.0) - (selected.outerHeight() / 2.0);
|
|
248
|
-
|
|
249
|
-
const scrollPos = scrollingPos - centerPos;
|
|
250
|
-
if (this.tempScrollPos === undefined) {
|
|
251
|
-
this.tempScrollPos = scrollPos;
|
|
252
|
-
}
|
|
253
|
-
// Call a custom scroll event to prevent thinking the user initiated it
|
|
254
|
-
const e = new CustomEvent('scroll', { detail: 'selected_item_scroll' });
|
|
255
|
-
widgetcontainer[0].scrollTop = scrollPos;
|
|
256
|
-
widgetcontainer[0].dispatchEvent(e);
|
|
257
|
-
}
|
|
258
|
-
},
|
|
259
|
-
/**
|
|
260
|
-
* This will look at the position of the selected item and update it as images load and
|
|
261
|
-
* the DOM reflows
|
|
262
|
-
*/
|
|
263
|
-
scrollPositionObserver: function () {
|
|
264
|
-
// Set the default selected height for the selected item
|
|
265
|
-
const target = this.$('.g-item-list');
|
|
266
|
-
if (window.MutationObserver && target.length > 0) {
|
|
267
|
-
// Default items to monitor for the scroll position
|
|
268
|
-
const widgetcontainer = this.$el.parents('.g-hierarchy-widget-container');
|
|
269
|
-
// If the observer already exists disconnect it so it can be recreated
|
|
270
|
-
if (this.observer && this.observer.disconnect) {
|
|
271
|
-
this.observer.disconnect();
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Event handler for loading images declared once
|
|
275
|
-
const onLoadImage = (event) => {
|
|
276
|
-
if (this.observer) {
|
|
277
|
-
this.centerSelected();
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
this.observer = new MutationObserver((mutations) => {
|
|
282
|
-
// for every mutation
|
|
283
|
-
_.each(mutations, (mutation) => {
|
|
284
|
-
// If no nodes are added we can return
|
|
285
|
-
if (!mutation.addedNodes) {
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// for every added node
|
|
290
|
-
_.each(mutation.addedNodes, (node) => {
|
|
291
|
-
if (node.className && node.className.indexOf('g-item-list') !== -1) {
|
|
292
|
-
// We want to do a onetime scroll to position if the screen is idle
|
|
293
|
-
if (window.requestIdleCallback) {
|
|
294
|
-
// Processing time is 2 seconds, but should finish much faster
|
|
295
|
-
requestIdleCallback(() => {
|
|
296
|
-
this.centerSelected();
|
|
297
|
-
}, { timeout: 2000 });
|
|
298
|
-
} else {
|
|
299
|
-
this.centerSelected();
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// For any images added we wait until loaded and rescroll to the selected
|
|
304
|
-
if (_.isFunction(node.getElementsByTagName)) {
|
|
305
|
-
this.$('img', node).on('load', onLoadImage);
|
|
306
|
-
}
|
|
307
|
-
});
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
// bind mutation observer to a specific element (probably a div somewhere)
|
|
312
|
-
this.observer.observe(target.parent()[0], { childList: true, subtree: true });
|
|
313
|
-
|
|
314
|
-
// Remove event listeners and disconnect observer
|
|
315
|
-
const unbindDisconnect = () => {
|
|
316
|
-
if (this.observer) {
|
|
317
|
-
widgetcontainer.unbind('scroll.observerscroll');
|
|
318
|
-
widgetcontainer.unbind('wheel.observerscroll');
|
|
319
|
-
widgetcontainer.unbind('click.observerscroll');
|
|
320
|
-
this.observer.disconnect();
|
|
321
|
-
this.observer = null;
|
|
322
|
-
this.tempScrollPos = undefined;
|
|
323
|
-
// Prevents scrolling when user clicks 'show more...'
|
|
324
|
-
this._highlightItem = false;
|
|
325
|
-
}
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
// Add in scroll event to monitor the scrollPos to prevent uncessary updates and also kill observer when user scrolls
|
|
329
|
-
widgetcontainer.bind('scroll.observerscroll', (evt) => {
|
|
330
|
-
if (this.tempScrollPos !== undefined && this.tempScrollPos !== widgetcontainer[0].scrollTop) {
|
|
331
|
-
this.tempScrollPos = widgetcontainer[0].scrollTop;
|
|
332
|
-
// If the event detail is not 'selected_item_scroll' the scroll should be a user initiated scroll
|
|
333
|
-
if (evt.detail !== 'selected_item_scroll') {
|
|
334
|
-
unbindDisconnect();
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
});
|
|
338
|
-
// Backup function to kill observer if user clicks an item, moves scrollwheel, or touchpad equivalent
|
|
339
|
-
widgetcontainer.bind('wheel.selectionobserver', unbindDisconnect);
|
|
340
|
-
widgetcontainer.bind('click.selectionobserver', unbindDisconnect);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
export default ItemListWidget;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import View from '@girder/core/views/View';
|
|
2
|
-
|
|
3
|
-
import LoadingAnimationTemplate from '@girder/core/templates/widgets/loadingAnimation.pug';
|
|
4
|
-
|
|
5
|
-
import '@girder/core/stylesheets/layout/loading.styl';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* This widget can be used to display a small loading animation.
|
|
9
|
-
*/
|
|
10
|
-
var LoadingAnimation = View.extend({
|
|
11
|
-
render: function () {
|
|
12
|
-
this.$el.html(LoadingAnimationTemplate());
|
|
13
|
-
return this;
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
export default LoadingAnimation;
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import _ from 'underscore';
|
|
2
|
-
|
|
3
|
-
import FileModel from '@girder/core/models/FileModel';
|
|
4
|
-
import View from '@girder/core/views/View';
|
|
5
|
-
import events from '@girder/core/events';
|
|
6
|
-
import { renderMarkdown, formatSize } from '@girder/core/misc';
|
|
7
|
-
|
|
8
|
-
import MarkdownWidgetTemplate from '@girder/core/templates/widgets/markdownWidget.pug';
|
|
9
|
-
|
|
10
|
-
import '@girder/core/stylesheets/widgets/markdownWidget.styl';
|
|
11
|
-
|
|
12
|
-
import '@girder/core/utilities/jquery/girderEnable';
|
|
13
|
-
|
|
14
|
-
import 'bootstrap/js/tab';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* A simple widget for editing markdown text with a preview tab.
|
|
18
|
-
*/
|
|
19
|
-
var MarkdownWidget = View.extend({
|
|
20
|
-
events: {
|
|
21
|
-
'show.bs.tab .g-preview-link': function () {
|
|
22
|
-
renderMarkdown(this.val().trim() || 'Nothing to show',
|
|
23
|
-
this.$('.g-markdown-preview'));
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
'shown.bs.tab .g-write-link': function () {
|
|
27
|
-
this.$('.g-markdown-text').trigger('focus');
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
'click .g-browse': function () {
|
|
31
|
-
this.$('.g-file-input').trigger('click');
|
|
32
|
-
},
|
|
33
|
-
|
|
34
|
-
'change .g-file-input': function (e) {
|
|
35
|
-
var files = e.target.files;
|
|
36
|
-
|
|
37
|
-
if (files.length) {
|
|
38
|
-
this.files = files;
|
|
39
|
-
this.filesAdded();
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
'dragenter .g-markdown-drop-zone': function (e) {
|
|
44
|
-
e.stopPropagation();
|
|
45
|
-
e.preventDefault();
|
|
46
|
-
e.originalEvent.dataTransfer.dropEffect = 'copy';
|
|
47
|
-
this.$('.g-markdown-text,.g-upload-footer').addClass('dragover');
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
'dragleave .g-markdown-drop-zone': function (e) {
|
|
51
|
-
e.stopPropagation();
|
|
52
|
-
e.preventDefault();
|
|
53
|
-
this.$('.g-markdown-text,.g-upload-footer').removeClass('dragover');
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
'dragover .g-markdown-drop-zone': function (e) {
|
|
57
|
-
e.originalEvent.dataTransfer.dropEffect = 'copy';
|
|
58
|
-
this.$('.g-markdown-text,.g-upload-footer').addClass('dragover');
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
'drop .g-markdown-drop-zone': function (e) {
|
|
62
|
-
e.stopPropagation();
|
|
63
|
-
e.preventDefault();
|
|
64
|
-
this.$('.g-markdown-text,.g-upload-footer').removeClass('dragover');
|
|
65
|
-
this.files = e.originalEvent.dataTransfer.files;
|
|
66
|
-
this.filesAdded();
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* @param [settings.text=''] Initial markdown text.
|
|
72
|
-
* @param [settings.placeholder=''] Text area placeholder.
|
|
73
|
-
* @param [settings.prefix='markdown'] Prefix for element IDs in case
|
|
74
|
-
* multiple of these widgets are rendered simultaneously.
|
|
75
|
-
* @param [settings.enableUploads=false] Whether to allow uploading files
|
|
76
|
-
* inline into the markdown.
|
|
77
|
-
* @param [settings.maxUploadSize=10 MB] Max upload size in bytes.
|
|
78
|
-
* @param [settings.parent] If enableUploads is true, set this to the object
|
|
79
|
-
* into which files should be uploaded.
|
|
80
|
-
* @param [settings.allowedExtensions=null] If you want to restrict to
|
|
81
|
-
* certain file extensions, set this to a list of (lowercase) extensions,
|
|
82
|
-
* not including periods. E.g.: ["png", "jpg", "jpeg"]
|
|
83
|
-
*/
|
|
84
|
-
initialize: function (settings) {
|
|
85
|
-
this.text = settings.text || '';
|
|
86
|
-
this.placeholder = settings.placeholder || '';
|
|
87
|
-
this.prefix = settings.prefix || 'markdown';
|
|
88
|
-
this.enableUploads = settings.enableUploads || false;
|
|
89
|
-
this.parent = settings.parent || null;
|
|
90
|
-
this.maxUploadSize = settings.maxUploadSize || 1024 * 1024 * 10;
|
|
91
|
-
this.allowedExtensions = settings.allowedExtensions || null;
|
|
92
|
-
this.files = [];
|
|
93
|
-
},
|
|
94
|
-
|
|
95
|
-
filesAdded: function () {
|
|
96
|
-
try {
|
|
97
|
-
this.validateFiles();
|
|
98
|
-
} catch (err) {
|
|
99
|
-
events.trigger('g:alert', {
|
|
100
|
-
type: 'danger',
|
|
101
|
-
text: err.message,
|
|
102
|
-
icon: 'cancel',
|
|
103
|
-
timeout: 5000
|
|
104
|
-
});
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
var file = this.files[0];
|
|
109
|
-
var fileModel = new FileModel();
|
|
110
|
-
|
|
111
|
-
fileModel.on('g:upload.complete', function () {
|
|
112
|
-
var val = this.$('.g-markdown-text').val();
|
|
113
|
-
val += ' + ')\n';
|
|
114
|
-
|
|
115
|
-
this.$('.g-upload-overlay').addClass('hide');
|
|
116
|
-
this.$('.g-markdown-text').girderEnable(true).val(val);
|
|
117
|
-
|
|
118
|
-
this.trigger('g:fileUploaded', {
|
|
119
|
-
file: file,
|
|
120
|
-
model: fileModel
|
|
121
|
-
});
|
|
122
|
-
}, this).on('g:upload.progress', function (info) {
|
|
123
|
-
var currentProgress = info.startByte + info.loaded;
|
|
124
|
-
this.$('.g-markdown-upload-progress>.progress-bar').css('width',
|
|
125
|
-
Math.ceil(100 * currentProgress / info.total) + '%');
|
|
126
|
-
this.$('.g-markdown-upload-progress-message').text(
|
|
127
|
-
'Uploading ' + info.file.name + ' - ' +
|
|
128
|
-
formatSize(currentProgress) + ' / ' +
|
|
129
|
-
formatSize(info.total)
|
|
130
|
-
);
|
|
131
|
-
}, this).on('g:upload.error', function (info) {
|
|
132
|
-
events.trigger('g:alert', {
|
|
133
|
-
type: 'danger',
|
|
134
|
-
text: info.message,
|
|
135
|
-
icon: 'cancel',
|
|
136
|
-
timeout: 5000
|
|
137
|
-
});
|
|
138
|
-
this.$('.g-upload-overlay').addClass('hide');
|
|
139
|
-
this.$('.g-markdown-text').girderEnable(true);
|
|
140
|
-
}, this).on('g:upload.errorStarting', function (info) {
|
|
141
|
-
events.trigger('g:alert', {
|
|
142
|
-
type: 'danger',
|
|
143
|
-
text: info.message,
|
|
144
|
-
icon: 'cancel',
|
|
145
|
-
timeout: 5000
|
|
146
|
-
});
|
|
147
|
-
this.$('.g-upload-overlay').addClass('hide');
|
|
148
|
-
this.$('.g-markdown-text').girderEnable(true);
|
|
149
|
-
}, this).upload(this.parent, file);
|
|
150
|
-
|
|
151
|
-
this.$('.g-upload-overlay').removeClass('hide');
|
|
152
|
-
this.$('.g-markdown-text').girderEnable(false);
|
|
153
|
-
},
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Validate a selection of files. If invalid, throws an object containing
|
|
157
|
-
* a "message" field.
|
|
158
|
-
*/
|
|
159
|
-
validateFiles: function (files) {
|
|
160
|
-
files = files || this.files;
|
|
161
|
-
|
|
162
|
-
if (this.files.length !== 1) {
|
|
163
|
-
throw new Error('Please add only one file at a time.');
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
var file = files[0],
|
|
167
|
-
ext = file.name.split('.').pop().toLowerCase();
|
|
168
|
-
|
|
169
|
-
if (this.maxUploadSize && file.size > this.maxUploadSize) {
|
|
170
|
-
throw new Error(
|
|
171
|
-
'That file is too large. You may only attach files ' +
|
|
172
|
-
'up to ' + formatSize(this.maxUploadSize) + '.'
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (this.allowedExtensions && !_.contains(this.allowedExtensions, ext)) {
|
|
177
|
-
throw new Error(
|
|
178
|
-
'Only files with the following extensions are allowed: ' +
|
|
179
|
-
this.allowedExtensions.join(', ') + '.'
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
},
|
|
183
|
-
|
|
184
|
-
render: function () {
|
|
185
|
-
this.$el.html(MarkdownWidgetTemplate({
|
|
186
|
-
text: this.text,
|
|
187
|
-
placeholder: this.placeholder,
|
|
188
|
-
prefix: this.prefix,
|
|
189
|
-
enableUploads: this.enableUploads
|
|
190
|
-
}));
|
|
191
|
-
|
|
192
|
-
return this;
|
|
193
|
-
},
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Get or set the current markdown text. Call with no arguments to return
|
|
197
|
-
* the current value, or call with one argument to set the value to that.
|
|
198
|
-
*/
|
|
199
|
-
val: function () {
|
|
200
|
-
if (arguments.length) {
|
|
201
|
-
return this.$('.g-markdown-text').val(arguments[0]);
|
|
202
|
-
} else {
|
|
203
|
-
return this.$('.g-markdown-text').val();
|
|
204
|
-
}
|
|
205
|
-
},
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Normally, calling render() on this widget will reset it to its initial text
|
|
209
|
-
* value. Call this to set the text value that should be shown on re-render
|
|
210
|
-
* to the current value of the text area.
|
|
211
|
-
*/
|
|
212
|
-
saveText: function () {
|
|
213
|
-
this.text = this.val();
|
|
214
|
-
}
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
export default MarkdownWidget;
|