diff options
-rw-r--r-- | apps/files/l10n/fi.php | 5 | ||||
-rw-r--r-- | apps/files/l10n/ka.php | 9 | ||||
-rw-r--r-- | apps/files_external/l10n/ka.php | 5 | ||||
-rw-r--r-- | apps/files_sharing/l10n/ka.php | 6 | ||||
-rw-r--r-- | apps/files_trashbin/l10n/ka.php | 6 | ||||
-rw-r--r-- | apps/user_ldap/l10n/ka.php | 8 | ||||
-rw-r--r-- | core/css/apps.css | 25 | ||||
-rw-r--r-- | core/l10n/fi.php | 6 | ||||
-rw-r--r-- | core/l10n/ka.php | 17 | ||||
-rw-r--r-- | core/templates/layout.guest.php | 17 | ||||
-rw-r--r-- | lib/base.php | 3 | ||||
-rw-r--r-- | lib/l10n/fi.php | 5 | ||||
-rw-r--r-- | lib/l10n/ka.php | 17 | ||||
-rw-r--r-- | lib/private/templatelayout.php | 1 | ||||
-rwxr-xr-x | lib/private/util.php | 12 | ||||
-rw-r--r-- | settings/js/users/deleteHandler.js | 47 | ||||
-rw-r--r-- | settings/l10n/ka.php | 5 | ||||
-rw-r--r-- | settings/tests/js/users/deleteHandlerSpec.js | 185 | ||||
-rw-r--r-- | tests/karma.config.js | 10 |
19 files changed, 258 insertions, 131 deletions
diff --git a/apps/files/l10n/fi.php b/apps/files/l10n/fi.php deleted file mode 100644 index 43770829397..00000000000 --- a/apps/files/l10n/fi.php +++ /dev/null @@ -1,5 +0,0 @@ -<?php -$TRANSLATIONS = array( -"Save" => "tallentaa" -); -$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/ka.php b/apps/files/l10n/ka.php deleted file mode 100644 index 544e8168c54..00000000000 --- a/apps/files/l10n/ka.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php -$TRANSLATIONS = array( -"Files" => "ფაილები", -"_%n folder_::_%n folders_" => array(""), -"_%n file_::_%n files_" => array(""), -"_Uploading %n file_::_Uploading %n files_" => array(""), -"Download" => "გადმოწერა" -); -$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_external/l10n/ka.php b/apps/files_external/l10n/ka.php deleted file mode 100644 index f6356d2cef8..00000000000 --- a/apps/files_external/l10n/ka.php +++ /dev/null @@ -1,5 +0,0 @@ -<?php -$TRANSLATIONS = array( -"Users" => "მომხმარებლები" -); -$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/l10n/ka.php b/apps/files_sharing/l10n/ka.php deleted file mode 100644 index a9b046e03b6..00000000000 --- a/apps/files_sharing/l10n/ka.php +++ /dev/null @@ -1,6 +0,0 @@ -<?php -$TRANSLATIONS = array( -"Password" => "პაროლი", -"Download" => "გადმოწერა" -); -$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_trashbin/l10n/ka.php b/apps/files_trashbin/l10n/ka.php deleted file mode 100644 index 70f10d7c0bf..00000000000 --- a/apps/files_trashbin/l10n/ka.php +++ /dev/null @@ -1,6 +0,0 @@ -<?php -$TRANSLATIONS = array( -"_%n folder_::_%n folders_" => array(""), -"_%n file_::_%n files_" => array("") -); -$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/user_ldap/l10n/ka.php b/apps/user_ldap/l10n/ka.php deleted file mode 100644 index 23b6c93df86..00000000000 --- a/apps/user_ldap/l10n/ka.php +++ /dev/null @@ -1,8 +0,0 @@ -<?php -$TRANSLATIONS = array( -"_%s group found_::_%s groups found_" => array(""), -"_%s user found_::_%s users found_" => array(""), -"Help" => "შველა", -"Password" => "პაროლი" -); -$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/core/css/apps.css b/core/css/apps.css index aa888e92399..b84bbaa8b42 100644 --- a/core/css/apps.css +++ b/core/css/apps.css @@ -57,7 +57,7 @@ #app-navigation li:hover > a, #app-navigation .selected, #app-navigation .selected a { - background-color: #ccc; + background-color: #ddd; } #app-navigation .with-icon a, @@ -140,7 +140,7 @@ } #app-navigation > ul .collapsible.open:hover { - box-shadow: inset 0 0 3px #ccc; + box-shadow: inset 0 0 3px #ddd; } #app-navigation > ul .collapsible.open ul { @@ -428,27 +428,6 @@ background-color: transparent; } -/* icons */ -.folder-icon, .delete-icon, .edit-icon, .progress-icon { - background-repeat: no-repeat; - background-position: center; -} -.folder-icon { background-image: url('../img/places/folder.svg'); } -.delete-icon { background-image: url('../img/actions/delete.svg'); } -.delete-icon:hover, .delete-icon:focus { - background-image: url('../img/actions/delete-hover.svg'); -} -.edit-icon { background-image: url('../img/actions/rename.svg'); } -.progress-icon { - background-image: url('../img/loading.gif'); - background-size: 16px; - /* force show the loading icon, not only on hover */ - -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; - filter:alpha(opacity=100); - opacity: 1 !important; - display: inline !important; -} - /* buttons */ button.loading { background-image: url('../img/loading.gif'); diff --git a/core/l10n/fi.php b/core/l10n/fi.php deleted file mode 100644 index 956ab312337..00000000000 --- a/core/l10n/fi.php +++ /dev/null @@ -1,6 +0,0 @@ -<?php -$TRANSLATIONS = array( -"Settings" => "asetukset", -"Username" => "Käyttäjätunnus" -); -$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/core/l10n/ka.php b/core/l10n/ka.php deleted file mode 100644 index 4805886c32c..00000000000 --- a/core/l10n/ka.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php -$TRANSLATIONS = array( -"seconds ago" => "წამის წინ", -"_%n minute ago_::_%n minutes ago_" => array(""), -"_%n hour ago_::_%n hours ago_" => array(""), -"today" => "დღეს", -"yesterday" => "გუშინ", -"_%n day ago_::_%n days ago_" => array(""), -"_%n month ago_::_%n months ago_" => array(""), -"_{count} file conflict_::_{count} file conflicts_" => array(""), -"Password" => "პაროლი", -"Personal" => "პერსონა", -"Users" => "მომხმარებლები", -"Admin" => "ადმინისტრატორი", -"Help" => "შველა" -); -$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/core/templates/layout.guest.php b/core/templates/layout.guest.php index dcf0553a4eb..da40fd83ad8 100644 --- a/core/templates/layout.guest.php +++ b/core/templates/layout.guest.php @@ -33,17 +33,20 @@ ?> <?php endforeach; ?> </head> - <body id="body-login"> + <body id="<?php p($_['bodyid']);?>"> <noscript><div id="nojavascript"><div><?php print_unescaped($l->t('This application requires JavaScript for correct operation. Please <a href="http://enable-javascript.com/" target="_blank">enable JavaScript</a> and reload the page.')); ?></div></div></noscript> <div class="wrapper"><!-- for sticky footer --> <div class="v-align"><!-- vertically centred box --> - <header><div id="header"> - <div class="logo svg"></div> - <div id="logo-claim" style="display:none;"><?php p($theme->getLogoClaim()); ?></div> - </div></header> - + <?php if ($_['bodyid'] === 'body-login' ): ?> + <header> + <div id="header"> + <div class="logo svg"></div> + <div id="logo-claim" style="display:none;"><?php p($theme->getLogoClaim()); ?></div> + </div> + </header> + <?php endif; ?> <?php print_unescaped($_['content']); ?> - <div class="push"></div><!-- for sticky footer --> + <div class="push"></div><!-- for sticky footer --> </div> </div> diff --git a/lib/base.php b/lib/base.php index c113ed3b506..e21d0124b32 100644 --- a/lib/base.php +++ b/lib/base.php @@ -496,6 +496,9 @@ class OC { require_once $vendorAutoLoad; } + // initialize intl fallback is necessary + \Patchwork\Utf8\Bootup::initIntl(); + if (!defined('PHPUNIT_RUN')) { OC\Log\ErrorHandler::setLogger(OC_Log::$object); if (defined('DEBUG') and DEBUG) { diff --git a/lib/l10n/fi.php b/lib/l10n/fi.php deleted file mode 100644 index ac1f80a8f73..00000000000 --- a/lib/l10n/fi.php +++ /dev/null @@ -1,5 +0,0 @@ -<?php -$TRANSLATIONS = array( -"Settings" => "asetukset" -); -$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/l10n/ka.php b/lib/l10n/ka.php deleted file mode 100644 index 04fefe8bdf1..00000000000 --- a/lib/l10n/ka.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php -$TRANSLATIONS = array( -"Help" => "შველა", -"Personal" => "პერსონა", -"Users" => "მომხმარებლები", -"Admin" => "ადმინისტრატორი", -"ZIP download is turned off." => "ZIP გადმოწერა გამორთულია", -"Files" => "ფაილები", -"seconds ago" => "წამის წინ", -"_%n minute ago_::_%n minutes ago_" => array(""), -"_%n hour ago_::_%n hours ago_" => array(""), -"today" => "დღეს", -"yesterday" => "გუშინ", -"_%n day go_::_%n days ago_" => array(""), -"_%n month ago_::_%n months ago_" => array("") -); -$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/lib/private/templatelayout.php b/lib/private/templatelayout.php index b9a97186945..1de47ded3b3 100644 --- a/lib/private/templatelayout.php +++ b/lib/private/templatelayout.php @@ -63,6 +63,7 @@ class OC_TemplateLayout extends OC_Template { parent::__construct('core', 'layout.guest', '', false); } else if ($renderas == 'guest') { parent::__construct('core', 'layout.guest'); + $this->assign('bodyid', 'body-login'); } else { parent::__construct('core', 'layout.base'); } diff --git a/lib/private/util.php b/lib/private/util.php index a130d997ca3..79f3eb7b48c 100755 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -1402,13 +1402,11 @@ class OC_Util { * @return bool|string */ public static function normalizeUnicode($value) { - if (class_exists('Patchwork\PHP\Shim\Normalizer')) { - $normalizedValue = \Patchwork\PHP\Shim\Normalizer::normalize($value); - if ($normalizedValue === false) { - \OC_Log::write('core', 'normalizing failed for "' . $value . '"', \OC_Log::WARN); - } else { - $value = $normalizedValue; - } + $normalizedValue = normalizer_normalize($value); + if ($normalizedValue === null || $normalizedValue === false) { + \OC_Log::write('core', 'normalizing failed for "' . $value . '"', \OC_Log::WARN); + } else { + $value = $normalizedValue; } return $value; diff --git a/settings/js/users/deleteHandler.js b/settings/js/users/deleteHandler.js index d4736d88701..c89a844044e 100644 --- a/settings/js/users/deleteHandler.js +++ b/settings/js/users/deleteHandler.js @@ -35,6 +35,16 @@ function DeleteHandler(endpoint, paramID, markCallback, removeCallback) { } /** + * Number of milliseconds after which the operation is performed. + */ +DeleteHandler.TIMEOUT_MS = 7000; + +/** + * Timer after which the action will be performed anyway. + */ +DeleteHandler.prototype._timeout = null; + +/** * The function to be called after successfully marking the object for deletion * @callback markCallback * @param {string} oid the ID of the specific user or group @@ -72,7 +82,9 @@ DeleteHandler.prototype.setNotification = function(notifier, dataID, message, un var dh = this; - $('#notification').on('click', '.undo', function () { + $('#notification') + .off('click.deleteHandler_' + dataID) + .on('click.deleteHandler_' + dataID, '.undo', function () { if ($('#notification').data(dh.notificationDataID)) { var oid = dh.oidToDelete; dh.cancel(); @@ -116,18 +128,36 @@ DeleteHandler.prototype.hideNotification = function() { */ DeleteHandler.prototype.mark = function(oid) { if(this.oidToDelete !== false) { - this.deleteEntry(); + // passing true to avoid hiding the notification + // twice and causing the second notification + // to disappear immediately + this.deleteEntry(true); } this.oidToDelete = oid; this.canceled = false; this.markCallback(oid); this.showNotification(); + if (this._timeout) { + clearTimeout(this._timeout); + this._timeout = null; + } + if (DeleteHandler.TIMEOUT_MS > 0) { + this._timeout = window.setTimeout( + _.bind(this.deleteEntry, this), + DeleteHandler.TIMEOUT_MS + ); + } }; /** * cancels a delete operation */ DeleteHandler.prototype.cancel = function() { + if (this._timeout) { + clearTimeout(this._timeout); + this._timeout = null; + } + this.canceled = true; this.oidToDelete = false; }; @@ -137,22 +167,31 @@ DeleteHandler.prototype.cancel = function() { * initialized by mark(). On error, it will show a message via * OC.dialogs.alert. On success, a callback is fired so that the client can * update the web interface accordingly. + * + * @param {boolean} [keepNotification] true to keep the notification, false to hide + * it, defaults to false */ -DeleteHandler.prototype.deleteEntry = function() { +DeleteHandler.prototype.deleteEntry = function(keepNotification) { if(this.canceled || this.oidToDelete === false) { return false; } var dh = this; - if($('#notification').data(this.notificationDataID) === true) { + if(!keepNotification && $('#notification').data(this.notificationDataID) === true) { dh.hideNotification(); } + if (this._timeout) { + clearTimeout(this._timeout); + this._timeout = null; + } + var payload = {}; payload[dh.ajaxParamID] = dh.oidToDelete; $.ajax({ type: 'POST', url: OC.filePath('settings', 'ajax', dh.ajaxEndpoint), + // FIXME: do not use synchronous ajax calls as they block the browser ! async: false, data: payload, success: function (result) { diff --git a/settings/l10n/ka.php b/settings/l10n/ka.php deleted file mode 100644 index e9024a3c1c9..00000000000 --- a/settings/l10n/ka.php +++ /dev/null @@ -1,5 +0,0 @@ -<?php -$TRANSLATIONS = array( -"Password" => "პაროლი" -); -$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/settings/tests/js/users/deleteHandlerSpec.js b/settings/tests/js/users/deleteHandlerSpec.js new file mode 100644 index 00000000000..6b6328be801 --- /dev/null +++ b/settings/tests/js/users/deleteHandlerSpec.js @@ -0,0 +1,185 @@ +/** +* ownCloud +* +* @author Vincent Petry +* @copyright 2014 Vincent Petry <pvince81@owncloud.com> +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +* License as published by the Free Software Foundation; either +* version 3 of the License, or any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU AFFERO GENERAL PUBLIC LICENSE for more details. +* +* You should have received a copy of the GNU Affero General Public +* License along with this library. If not, see <http://www.gnu.org/licenses/>. +* +*/ + +describe('DeleteHandler tests', function() { + var showNotificationSpy; + var hideNotificationSpy; + var clock; + var removeCallback; + var markCallback; + var undoCallback; + + function init(markCallback, removeCallback, undoCallback) { + var handler = new DeleteHandler('dummyendpoint.php', 'paramid', markCallback, removeCallback); + handler.setNotification(OC.Notification, 'dataid', 'removed %oid entry', undoCallback); + return handler; + } + + beforeEach(function() { + showNotificationSpy = sinon.spy(OC.Notification, 'showHtml'); + hideNotificationSpy = sinon.spy(OC.Notification, 'hide'); + clock = sinon.useFakeTimers(); + removeCallback = sinon.stub(); + markCallback = sinon.stub(); + undoCallback = sinon.stub(); + + $('#testArea').append('<div id="notification"></div>'); + }); + afterEach(function() { + showNotificationSpy.restore(); + hideNotificationSpy.restore(); + clock.restore(); + }); + it('shows a notification when marking for delete', function() { + var handler = init(markCallback, removeCallback, undoCallback); + handler.mark('some_uid'); + + expect(showNotificationSpy.calledOnce).toEqual(true); + expect(showNotificationSpy.getCall(0).args[0]).toEqual('removed some_uid entry'); + + expect(markCallback.calledOnce).toEqual(true); + expect(markCallback.getCall(0).args[0]).toEqual('some_uid'); + expect(removeCallback.notCalled).toEqual(true); + expect(undoCallback.notCalled).toEqual(true); + + expect(fakeServer.requests.length).toEqual(0); + }); + it('deletes first entry and reshows notification on second delete', function() { + var handler = init(markCallback, removeCallback, undoCallback); + handler.mark('some_uid'); + + expect(showNotificationSpy.calledOnce).toEqual(true); + expect(showNotificationSpy.getCall(0).args[0]).toEqual('removed some_uid entry'); + showNotificationSpy.reset(); + + handler.mark('some_other_uid'); + + expect(hideNotificationSpy.calledOnce).toEqual(true); + expect(showNotificationSpy.calledOnce).toEqual(true); + expect(showNotificationSpy.getCall(0).args[0]).toEqual('removed some_other_uid entry'); + + expect(markCallback.calledTwice).toEqual(true); + expect(markCallback.getCall(0).args[0]).toEqual('some_uid'); + expect(markCallback.getCall(1).args[0]).toEqual('some_other_uid'); + expect(removeCallback.notCalled).toEqual(true); + expect(undoCallback.notCalled).toEqual(true); + + // previous one was delete + expect(fakeServer.requests.length).toEqual(1); + var request = fakeServer.requests[0]; + expect(request.url).toEqual(OC.webroot + '/index.php/settings/ajax/dummyendpoint.php'); + }); + it('automatically deletes after timeout', function() { + var handler = init(markCallback, removeCallback, undoCallback); + handler.mark('some_uid'); + + clock.tick(5000); + // nothing happens yet + expect(fakeServer.requests.length).toEqual(0); + + clock.tick(3000); + expect(fakeServer.requests.length).toEqual(1); + var request = fakeServer.requests[0]; + expect(request.url).toEqual(OC.webroot + '/index.php/settings/ajax/dummyendpoint.php'); + }); + it('deletes when deleteEntry is called', function() { + var handler = init(markCallback, removeCallback, undoCallback); + handler.mark('some_uid'); + + handler.deleteEntry(); + expect(fakeServer.requests.length).toEqual(1); + var request = fakeServer.requests[0]; + expect(request.url).toEqual(OC.webroot + '/index.php/settings/ajax/dummyendpoint.php'); + }); + it('cancels deletion when undo is clicked', function() { + var handler = init(markCallback, removeCallback, undoCallback); + handler.setNotification(OC.Notification, 'dataid', 'removed %oid entry <span class="undo">Undo</span>', undoCallback); + handler.mark('some_uid'); + $('#notification .undo').click(); + + expect(undoCallback.calledOnce).toEqual(true); + + // timer was cancelled + clock.tick(10000); + expect(fakeServer.requests.length).toEqual(0); + }); + it('cancels deletion when cancel method is called', function() { + var handler = init(markCallback, removeCallback, undoCallback); + handler.setNotification(OC.Notification, 'dataid', 'removed %oid entry <span class="undo">Undo</span>', undoCallback); + handler.mark('some_uid'); + handler.cancel(); + + // not sure why, seems to be by design + expect(undoCallback.notCalled).toEqual(true); + + // timer was cancelled + clock.tick(10000); + expect(fakeServer.requests.length).toEqual(0); + }); + it('calls removeCallback after successful server side deletion', function() { + fakeServer.respondWith(/\/index\.php\/settings\/ajax\/dummyendpoint.php/, [ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ]); + + var handler = init(markCallback, removeCallback, undoCallback); + handler.mark('some_uid'); + handler.deleteEntry(); + + expect(fakeServer.requests.length).toEqual(1); + var request = fakeServer.requests[0]; + var query = OC.parseQueryString(request.requestBody); + expect(query.paramid).toEqual('some_uid'); + + expect(removeCallback.calledOnce).toEqual(true); + expect(undoCallback.notCalled).toEqual(true); + expect(removeCallback.getCall(0).args[0]).toEqual('some_uid'); + }); + it('calls undoCallback and shows alert after failed server side deletion', function() { + // stub t to avoid extra calls + var tStub = sinon.stub(window, 't').returns('text'); + fakeServer.respondWith(/\/index\.php\/settings\/ajax\/dummyendpoint.php/, [ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'error', data: {message: 'test error'}}) + ]); + + var alertDialogStub = sinon.stub(OC.dialogs, 'alert'); + var handler = init(markCallback, removeCallback, undoCallback); + handler.mark('some_uid'); + handler.deleteEntry(); + + expect(fakeServer.requests.length).toEqual(1); + var request = fakeServer.requests[0]; + var query = OC.parseQueryString(request.requestBody); + expect(query.paramid).toEqual('some_uid'); + + expect(removeCallback.notCalled).toEqual(true); + expect(undoCallback.calledOnce).toEqual(true); + expect(undoCallback.getCall(0).args[0]).toEqual('some_uid'); + + expect(alertDialogStub.calledOnce); + + alertDialogStub.restore(); + tStub.restore(); + }); +}); diff --git a/tests/karma.config.js b/tests/karma.config.js index 14a0d7e8464..357fcf3f122 100644 --- a/tests/karma.config.js +++ b/tests/karma.config.js @@ -66,7 +66,15 @@ module.exports = function(config) { 'apps/files_external/js/mountsfilelist.js' ], testFiles: ['apps/files_external/tests/js/*.js'] - }]; + }, + { + name: 'settings', + srcFiles: [ + 'settings/js/users/deleteHandler.js' + ], + testFiles: ['settings/tests/js/users/deleteHandlerSpec.js'] + } + ]; } // respect NOCOVERAGE env variable |