diff options
Diffstat (limited to 'core/js')
-rw-r--r-- | core/js/js.js | 38 | ||||
-rw-r--r-- | core/js/shareconfigmodel.js | 3 | ||||
-rw-r--r-- | core/js/sharedialoglinkshareview.js | 39 | ||||
-rw-r--r-- | core/js/sharedialogresharerinfoview.js | 13 | ||||
-rw-r--r-- | core/js/sharedialogshareelistview.js | 28 | ||||
-rw-r--r-- | core/js/sharedialogview.js | 55 | ||||
-rw-r--r-- | core/js/shareitemmodel.js | 16 | ||||
-rw-r--r-- | core/js/tests/specs/coreSpec.js | 6 | ||||
-rw-r--r-- | core/js/tests/specs/sharedialogviewSpec.js | 23 |
9 files changed, 158 insertions, 63 deletions
diff --git a/core/js/js.js b/core/js/js.js index 68b6f82648b..5f5f540af63 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -780,8 +780,18 @@ var OCP = {}, // sometimes "beforeunload" happens later, so need to defer the reload a bit setTimeout(function() { if (!self._userIsNavigatingAway && !self._reloadCalled) { - OC.Notification.show(t('core', 'Problem loading page, reloading in 5 seconds')); - setTimeout(OC.reload, 5000); + var timer = 0; + var seconds = 5; + var interval = setInterval( function() { + OC.Notification.showUpdate(n('core', 'Problem loading page, reloading in %n second', 'Problem loading page, reloading in %n seconds', seconds - timer)); + if (timer >= seconds) { + clearInterval(interval); + OC.reload(); + } + timer++; + }, 1000 // 1 second interval + ); + // only call reload once self._reloadCalled = true; } @@ -1174,6 +1184,30 @@ OC.Notification={ }, /** + * Updates (replaces) a sanitized notification. + * + * @param {string} text Message to display + * @return {jQuery} JQuery element for notificaiton row + */ + showUpdate: function(text) { + var $notification = $('#notification'); + // sanitise + var $html = $('<div/>').text(text).html(); + + // new notification + if (text && $notification.find('.row').length == 0) { + return this.showHtml($html); + } + + var $row = $('<div class="row"></div>').prepend($html); + + // just update html in notification + $notification.html($row); + + return $row; + }, + + /** * Shows a notification that disappears after x seconds, default is * 7 seconds * diff --git a/core/js/shareconfigmodel.js b/core/js/shareconfigmodel.js index 7c92853f682..98388cbd508 100644 --- a/core/js/shareconfigmodel.js +++ b/core/js/shareconfigmodel.js @@ -33,9 +33,10 @@ /** * @returns {boolean} + * @deprecated here for legacy reasons - will always return true */ areAvatarsEnabled: function() { - return oc_config.enable_avatars === true; + return true; }, /** diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js index cb553947de6..84a3d18942f 100644 --- a/core/js/sharedialoglinkshareview.js +++ b/core/js/sharedialoglinkshareview.js @@ -43,6 +43,13 @@ '</div>' + ' {{/if}}' + ' {{/if}}' + + ' {{#if publicEditing}}' + + '<div id="allowPublicEditingWrapper">' + + ' <span class="icon-loading-small hidden"></span>' + + ' <input type="checkbox" value="1" name="allowPublicEditing" id="sharingDialogAllowPublicEditing-{{cid}}" class="checkbox publicEditingCheckbox" {{{publicEditingChecked}}} />' + + '<label for="sharingDialogAllowPublicEditing-{{cid}}">{{publicEditingLabel}}</label>' + + '</div>' + + ' {{/if}}' + ' {{#if showPasswordCheckBox}}' + '<input type="checkbox" name="showPassword" id="showPassword-{{cid}}" class="checkbox showPasswordCheckbox" {{#if isPasswordSet}}checked="checked"{{/if}} value="1" />' + '<label for="showPassword-{{cid}}">{{enablePasswordLabel}}</label>' + @@ -87,6 +94,7 @@ 'click .linkCheckbox': 'onLinkCheckBoxChange', 'click .linkText': 'onLinkTextClick', 'change .publicUploadCheckbox': 'onAllowPublicUploadChange', + 'change .publicEditingCheckbox': 'onAllowPublicEditingChange', 'change .hideFileListCheckbox': 'onHideFileListChange', 'click .showPasswordCheckbox': 'onShowPasswordClick' }, @@ -128,7 +136,8 @@ 'onLinkTextClick', 'onShowPasswordClick', 'onHideFileListChange', - 'onAllowPublicUploadChange' + 'onAllowPublicUploadChange', + 'onAllowPublicEditingChange' ); var clipboard = new Clipboard('.clipboardButton'); @@ -266,6 +275,20 @@ }); }, + onAllowPublicEditingChange: function() { + var $checkbox = this.$('.publicEditingCheckbox'); + $checkbox.siblings('.icon-loading-small').removeClass('hidden').addClass('inlineblock'); + + var permissions = OC.PERMISSION_READ; + if($checkbox.is(':checked')) { + permissions = OC.PERMISSION_UPDATE | OC.PERMISSION_READ; + } + + this.model.saveLinkShare({ + permissions: permissions + }); + }, + onHideFileListChange: function () { var $checkbox = this.$('.hideFileListCheckbox'); $checkbox.siblings('.icon-loading-small').removeClass('hidden').addClass('inlineblock'); @@ -307,6 +330,12 @@ publicUploadChecked = 'checked="checked"'; } + var publicEditingChecked = ''; + if(this.model.isPublicEditingAllowed()) { + publicEditingChecked = 'checked="checked"'; + } + + var hideFileList = publicUploadChecked; var hideFileListChecked = ''; @@ -320,6 +349,11 @@ && ( !this.configModel.get('enforcePasswordForPublicLink') || !this.model.get('linkShare').password); + var publicEditable = + !this.model.isFolder() + && isLinkShare + && this.model.updatePermissionPossible(); + this.$el.html(linkShareTemplate({ cid: this.cid, shareAllowed: true, @@ -337,6 +371,9 @@ publicUploadChecked: publicUploadChecked, hideFileListChecked: hideFileListChecked, publicUploadLabel: t('core', 'Allow upload and editing'), + publicEditing: publicEditable, + publicEditingChecked: publicEditingChecked, + publicEditingLabel: t('core', 'Allow editing'), hideFileListLabel: t('core', 'File drop (upload only)'), mailPrivatePlaceholder: t('core', 'Email link to person'), mailButtonText: t('core', 'Send') diff --git a/core/js/sharedialogresharerinfoview.js b/core/js/sharedialogresharerinfoview.js index 9a9d95cfb60..a82b495bdcc 100644 --- a/core/js/sharedialogresharerinfoview.js +++ b/core/js/sharedialogresharerinfoview.js @@ -17,9 +17,7 @@ var TEMPLATE = '<span class="reshare">' + - ' {{#if avatarEnabled}}' + ' <div class="avatar" data-userName="{{reshareOwner}}"></div>' + - ' {{/if}}' + ' {{sharedByText}}' + '</span><br/>' ; @@ -93,17 +91,14 @@ } this.$el.html(reshareTemplate({ - avatarEnabled: this.configModel.areAvatarsEnabled(), reshareOwner: this.model.getReshareOwner(), sharedByText: sharedByText })); - if(this.configModel.areAvatarsEnabled()) { - this.$el.find('.avatar').each(function() { - var $this = $(this); - $this.avatar($this.data('username'), 32); - }); - } + this.$el.find('.avatar').each(function() { + var $this = $(this); + $this.avatar($this.data('username'), 32); + }); return this; }, diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js index 4647dedd722..47dc62d14fe 100644 --- a/core/js/sharedialogshareelistview.js +++ b/core/js/sharedialogshareelistview.js @@ -21,9 +21,7 @@ '<ul id="shareWithList" class="shareWithList">' + '{{#each sharees}}' + '<li data-share-id="{{shareId}}" data-share-type="{{shareType}}" data-share-with="{{shareWith}}">' + - '{{#if avatarEnabled}}' + '<div class="avatar {{#if modSeed}}imageplaceholderseed{{/if}}" data-username="{{shareWith}}" data-displayname="{{shareWithDisplayName}}" {{#if modSeed}}data-seed="{{shareWith}} {{shareType}}"{{/if}}></div>' + - '{{/if}}' + '<span class="has-tooltip username" title="{{shareWithTitle}}">{{shareWithDisplayName}}</span>' + '<span class="sharingOptionsGroup">' + '{{#if editPermissionPossible}}' + @@ -41,9 +39,7 @@ '{{/each}}' + '{{#each linkReshares}}' + '<li data-share-id="{{shareId}}" data-share-type="{{shareType}}">' + - '{{#if avatarEnabled}}' + '<div class="avatar" data-username="{{shareInitiator}}"></div>' + - '{{/if}}' + '<span class="has-tooltip username" title="{{shareInitiator}}">' + t('core', '{{shareInitiatorDisplayName}} shared via link') + '</span>' + '<span class="sharingOptionsGroup">' + @@ -193,7 +189,6 @@ getShareProperties: function() { return { - avatarEnabled: this.configModel.areAvatarsEnabled(), unshareLabel: t('core', 'Unshare'), canShareLabel: t('core', 'can reshare'), canEditLabel: t('core', 'can edit'), @@ -247,7 +242,6 @@ getLinkReshares: function() { var universal = { unshareLabel: t('core', 'Unshare'), - avatarEnabled: this.configModel.areAvatarsEnabled(), }; if(!this.model.hasUserShares()) { @@ -281,18 +275,16 @@ linkReshares: this.getLinkReshares() })); - if (this.configModel.areAvatarsEnabled()) { - this.$('.avatar').each(function () { - var $this = $(this); - if ($this.hasClass('imageplaceholderseed')) { - $this.css({width: 32, height: 32}); - $this.imageplaceholder($this.data('seed')); - } else { - // user, size, ie8fix, hidedefault, callback, displayname - $this.avatar($this.data('username'), 32, undefined, undefined, undefined, $this.data('displayname')); - } - }); - } + this.$('.avatar').each(function () { + var $this = $(this); + if ($this.hasClass('imageplaceholderseed')) { + $this.css({width: 32, height: 32}); + $this.imageplaceholder($this.data('seed')); + } else { + // user, size, ie8fix, hidedefault, callback, displayname + $this.avatar($this.data('username'), 32, undefined, undefined, undefined, $this.data('displayname')); + } + }); this.$('.has-tooltip').tooltip({ placement: 'bottom' diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js index 60cd97fb572..a63960da2b8 100644 --- a/core/js/sharedialogview.js +++ b/core/js/sharedialogview.js @@ -130,18 +130,46 @@ }, autocompleteHandler: function (search, response) { - var view = this; - var $loading = this.$el.find('.shareWithLoading'); + var $shareWithField = $('.shareWithField'), + view = this, + $loading = this.$el.find('.shareWithLoading'), + $remoteShareInfo = this.$el.find('.shareWithRemoteInfo'); + + var count = oc_config['sharing.minSearchStringLength']; + if (search.term.trim().length < count) { + var title = n('core', + 'At least {count} character is needed for autocompletion', + 'At least {count} characters are needed for autocompletion', + count, + { count: count } + ); + $shareWithField.addClass('error') + .attr('data-original-title', title) + .tooltip('hide') + .tooltip({ + placement: 'bottom', + trigger: 'manual' + }) + .tooltip('fixTitle') + .tooltip('show'); + response(); + return; + } + $loading.removeClass('hidden'); $loading.addClass('inlineblock'); - var $remoteShareInfo = this.$el.find('.shareWithRemoteInfo'); $remoteShareInfo.addClass('hidden'); + + $shareWithField.removeClass('error') + .tooltip('hide'); + + var perPage = 200; $.get( OC.linkToOCS('apps/files_sharing/api/v1') + 'sharees', { format: 'json', search: search.term.trim(), - perPage: 200, + perPage: perPage, itemType: view.model.get('itemType') }, function (result) { @@ -232,16 +260,27 @@ var suggestions = users.concat(groups).concat(remotes).concat(emails).concat(lookup); if (suggestions.length > 0) { - $('.shareWithField').removeClass('error') - .tooltip('hide') + $shareWithField .autocomplete("option", "autoFocus", true); + response(suggestions); + + // show a notice that the list is truncated + // this is the case if one of the search results is at least as long as the max result config option + if(oc_config['sharing.maxAutocompleteResults'] > 0 && + Math.min(perPage, oc_config['sharing.maxAutocompleteResults']) + <= Math.max(users.length, groups.length, remotes.length, emails.length, lookup.length)) { + + var message = t('core', 'This list is maybe truncated - please refine your search term to see more results.'); + $('.ui-autocomplete').append('<li class="autocomplete-note">' + message + '</li>'); + } + } else { - var title = t('core', 'No users or groups found for {search}', {search: $('.shareWithField').val()}); + var title = t('core', 'No users or groups found for {search}', {search: $shareWithField.val()}); if (!view.configModel.get('allowGroupSharing')) { title = t('core', 'No users found for {search}', {search: $('.shareWithField').val()}); } - $('.shareWithField').addClass('error') + $shareWithField.addClass('error') .attr('data-original-title', title) .tooltip('hide') .tooltip({ diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js index 9b10f067afc..ae4c07e3f4e 100644 --- a/core/js/shareitemmodel.js +++ b/core/js/shareitemmodel.js @@ -272,6 +272,10 @@ return this.get('allowPublicUploadStatus'); }, + isPublicEditingAllowed: function() { + return this.get('allowPublicEditingStatus'); + }, + /** * @returns {boolean} */ @@ -679,6 +683,17 @@ }); } + var allowPublicEditingStatus = true; + if(!_.isUndefined(data.shares)) { + $.each(data.shares, function (key, value) { + if (value.share_type === OC.Share.SHARE_TYPE_LINK) { + allowPublicEditingStatus = (value.permissions & OC.PERMISSION_UPDATE) ? true : false; + return true; + } + }); + } + + var hideFileListStatus = false; if(!_.isUndefined(data.shares)) { $.each(data.shares, function (key, value) { @@ -762,6 +777,7 @@ linkShare: linkShare, permissions: permissions, allowPublicUploadStatus: allowPublicUploadStatus, + allowPublicEditingStatus: allowPublicEditingStatus, hideFileListStatus: hideFileListStatus }; }, diff --git a/core/js/tests/specs/coreSpec.js b/core/js/tests/specs/coreSpec.js index d83c0cd9a38..3380b6be420 100644 --- a/core/js/tests/specs/coreSpec.js +++ b/core/js/tests/specs/coreSpec.js @@ -1000,7 +1000,7 @@ describe('Core base tests', function() { describe('global ajax errors', function() { var reloadStub, ajaxErrorStub, clock; var notificationStub; - var waitTimeMs = 6000; + var waitTimeMs = 6500; var oldCurrentUser; beforeEach(function() { @@ -1075,10 +1075,12 @@ describe('Core base tests', function() { it('displays notification', function() { var xhr = { status: 401 }; + notificationUpdateStub = sinon.stub(OC.Notification, 'showUpdate'); + $(document).trigger(new $.Event('ajaxError'), xhr); clock.tick(waitTimeMs); - expect(notificationStub.calledOnce).toEqual(true); + expect(notificationUpdateStub.notCalled).toEqual(false); }); it('shows a temporary notification if the connection is lost', function() { var xhr = { status: 0 }; diff --git a/core/js/tests/specs/sharedialogviewSpec.js b/core/js/tests/specs/sharedialogviewSpec.js index cbb74714ff7..307adea85ff 100644 --- a/core/js/tests/specs/sharedialogviewSpec.js +++ b/core/js/tests/specs/sharedialogviewSpec.js @@ -24,7 +24,6 @@ describe('OC.Share.ShareDialogView', function() { var $container; var oldAppConfig; var autocompleteStub; - var oldEnableAvatars; var avatarStub; var placeholderStub; var oldCurrentUser; @@ -103,8 +102,6 @@ describe('OC.Share.ShareDialogView', function() { return $el; }); - oldEnableAvatars = oc_config.enable_avatars; - oc_config.enable_avatars = false; avatarStub = sinon.stub($.fn, 'avatar'); placeholderStub = sinon.stub($.fn, 'imageplaceholder'); @@ -123,7 +120,6 @@ describe('OC.Share.ShareDialogView', function() { autocompleteStub.restore(); avatarStub.restore(); placeholderStub.restore(); - oc_config.enable_avatars = oldEnableAvatars; }); describe('Share with link', function() { // TODO: test ajax calls @@ -440,18 +436,13 @@ describe('OC.Share.ShareDialogView', function() { describe('avatars enabled', function() { beforeEach(function() { - oc_config.enable_avatars = true; avatarStub.reset(); dialog.render(); }); - afterEach(function() { - oc_config.enable_avatars = false; - }); - it('test correct function calls', function() { expect(avatarStub.calledTwice).toEqual(true); - expect(placeholderStub.calledTwice).toEqual(true); + expect(placeholderStub.callCount).toEqual(4); expect(dialog.$('.shareWithList').children().length).toEqual(3); expect(dialog.$('.avatar').length).toEqual(4); }); @@ -481,18 +472,6 @@ describe('OC.Share.ShareDialogView', function() { expect(args[0]).toEqual('foo@bar.com/baz ' + OC.Share.SHARE_TYPE_REMOTE); }); }); - - describe('avatars disabled', function() { - beforeEach(function() { - dialog.render(); - }); - - it('no avatar classes', function() { - expect($('.avatar').length).toEqual(0); - expect(avatarStub.callCount).toEqual(0); - expect(placeholderStub.callCount).toEqual(0); - }); - }); }); describe('remote sharing', function() { it('shows remote share info when allowed', function() { |