зеркало из https://github.com/nextcloud/news.git
add undo for feed and folder deletion, fix #56
This commit is contained in:
Родитель
ac5c8f5f4f
Коммит
b9099435cb
|
@ -19,6 +19,39 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#undo-container {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
z-index: 101;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
#undo {
|
||||
z-index:101;
|
||||
background-color:#fc4;
|
||||
border:0;
|
||||
padding:0 .7em .3em;
|
||||
display:none;
|
||||
position: relative;
|
||||
top:0;
|
||||
-moz-border-radius-bottomleft:1em;
|
||||
-webkit-border-bottom-left-radius:1em;
|
||||
border-bottom-left-radius:1em;
|
||||
-moz-border-radius-bottomright:1em;
|
||||
-webkit-border-bottom-right-radius:1em;
|
||||
border-bottom-right-radius:1em;
|
||||
}
|
||||
|
||||
#undo a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#undo a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
.starred-icon {
|
||||
background-image: url('%appswebroot%/news/img/starred.png');
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
###
|
||||
|
||||
ownCloud - News
|
||||
|
||||
@author Bernhard Posselt
|
||||
@copyright 2012 Bernhard Posselt nukeawhale@gmail.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/>.
|
||||
|
||||
###
|
||||
|
||||
angular.module('News').directive 'undoNotification', ['$rootScope',
|
||||
($rootScope) ->
|
||||
|
||||
return (scope, elm, attr) ->
|
||||
|
||||
elm.click ->
|
||||
$(@).fadeOut()
|
||||
|
||||
scope.$on 'notUndone', ->
|
||||
$(elm).fadeOut()
|
||||
|
||||
undo = ->
|
||||
caption = ''
|
||||
|
||||
link = $(elm).find('a')
|
||||
link.click ->
|
||||
undo()
|
||||
$rootScope.$apply()
|
||||
elm.fadeOut()
|
||||
|
||||
scope.getCaption = ->
|
||||
return caption
|
||||
|
||||
scope.$on 'undoMessage', (scope, data) ->
|
||||
undo = data.undoCallback
|
||||
caption = data.caption
|
||||
elm.fadeIn().css("display","inline")
|
||||
|
||||
|
||||
]
|
|
@ -23,14 +23,16 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
angular.module('News').factory 'FeedBusinessLayer',
|
||||
['_BusinessLayer', 'ShowAll', 'Persistence', 'ActiveFeed', 'FeedType',
|
||||
'ItemModel', 'FeedModel', 'NewLoading', '_ExistsError', 'Utils',
|
||||
'ItemModel', 'FeedModel', 'NewLoading', '_ExistsError', 'Utils', '$rootScope',
|
||||
'UndoQueue',
|
||||
(_BusinessLayer, ShowAll, Persistence, ActiveFeed, FeedType, ItemModel,
|
||||
FeedModel, NewLoading, _ExistsError, Utils) ->
|
||||
FeedModel, NewLoading, _ExistsError, Utils, $rootScope, UndoQueue) ->
|
||||
|
||||
class FeedBusinessLayer extends _BusinessLayer
|
||||
|
||||
constructor: (@_showAll, @_feedModel, persistence, activeFeed, feedType,
|
||||
itemModel, @_newLoading, @_utils) ->
|
||||
itemModel, @_newLoading, @_utils, @_$rootScope,
|
||||
@_undoQueue) ->
|
||||
super(activeFeed, persistence, itemModel, feedType.Feed)
|
||||
@_feedType = feedType
|
||||
|
||||
|
@ -52,8 +54,14 @@ FeedModel, NewLoading, _ExistsError, Utils) ->
|
|||
|
||||
|
||||
delete: (feedId) ->
|
||||
@_feedModel.removeById(feedId)
|
||||
@_persistence.deleteFeed(feedId)
|
||||
feed = @_feedModel.removeById(feedId)
|
||||
callback = =>
|
||||
@_persistence.deleteFeed(feedId)
|
||||
|
||||
undoCallback = =>
|
||||
@_feedModel.add(feed)
|
||||
|
||||
@_undoQueue.add(feed.title, callback, 10*1000, undoCallback)
|
||||
|
||||
|
||||
markFeedRead: (feedId) ->
|
||||
|
@ -185,6 +193,7 @@ FeedModel, NewLoading, _ExistsError, Utils) ->
|
|||
|
||||
|
||||
return new FeedBusinessLayer(ShowAll, FeedModel, Persistence, ActiveFeed,
|
||||
FeedType, ItemModel, NewLoading, Utils)
|
||||
FeedType, ItemModel, NewLoading, Utils,
|
||||
$rootScope, UndoQueue)
|
||||
|
||||
]
|
|
@ -24,22 +24,31 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
angular.module('News').factory 'FolderBusinessLayer',
|
||||
['_BusinessLayer', 'FolderModel', 'FeedBusinessLayer', 'Persistence',
|
||||
'FeedType', 'ActiveFeed', 'ItemModel', 'ShowAll', '_ExistsError', 'OPMLParser',
|
||||
'UndoQueue',
|
||||
(_BusinessLayer, FolderModel, FeedBusinessLayer, Persistence, FeedType,
|
||||
ActiveFeed, ItemModel, ShowAll, _ExistsError, OPMLParser) ->
|
||||
ActiveFeed, ItemModel, ShowAll, _ExistsError, OPMLParser, UndoQueue) ->
|
||||
|
||||
class FolderBusinessLayer extends _BusinessLayer
|
||||
|
||||
constructor: (@_folderModel, @_feedBusinessLayer, @_showAll, activeFeed,
|
||||
persistence, @_feedType, itemModel, @_opmlParser) ->
|
||||
persistence, @_feedType, itemModel, @_opmlParser,
|
||||
@_undoQueue) ->
|
||||
super(activeFeed, persistence, itemModel, @_feedType.Folder)
|
||||
|
||||
|
||||
getById: (folderId) ->
|
||||
return @_folderModel.getById(folderId)
|
||||
|
||||
|
||||
delete: (folderId) ->
|
||||
@_folderModel.removeById(folderId)
|
||||
@_persistence.deleteFolder(folderId)
|
||||
folder = @_folderModel.removeById(folderId)
|
||||
callback = =>
|
||||
@_persistence.deleteFolder(folderId)
|
||||
|
||||
undoCallback = =>
|
||||
@_folderModel.add(folder)
|
||||
|
||||
@_undoQueue.add(folder.name, callback, 10*1000, undoCallback)
|
||||
|
||||
|
||||
hasFeeds: (folderId) ->
|
||||
|
@ -155,6 +164,6 @@ ActiveFeed, ItemModel, ShowAll, _ExistsError, OPMLParser) ->
|
|||
|
||||
return new FolderBusinessLayer(FolderModel, FeedBusinessLayer, ShowAll,
|
||||
ActiveFeed, Persistence, FeedType, ItemModel,
|
||||
OPMLParser)
|
||||
OPMLParser, UndoQueue)
|
||||
|
||||
]
|
|
@ -40,7 +40,8 @@ angular.module('News').factory 'FeedModel',
|
|||
if data.faviconLink == null
|
||||
data.faviconLink = 'url(' +
|
||||
@_utils.imagePath('news', 'rss.svg') + ')'
|
||||
else if angular.isDefined(data.faviconLink)
|
||||
else if angular.isDefined(data.faviconLink) and
|
||||
data.faviconLink.indexOf('url(') != 0
|
||||
data.faviconLink = 'url(' + data.faviconLink + ')'
|
||||
###
|
||||
We want to add a feed on the client side before
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
###
|
||||
|
||||
ownCloud - App Framework
|
||||
|
||||
@author Bernhard Posselt
|
||||
@copyright 2012 Bernhard Posselt nukeawhale@gmail.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/>.
|
||||
|
||||
###
|
||||
|
||||
# A class which follows the command pattern
|
||||
# Can be used for actions that need need to be able to undo like folder deletion
|
||||
angular.module('News').factory 'UndoQueue',
|
||||
['$timeout', '$rootScope',
|
||||
($timeout, $rootScope) ->
|
||||
|
||||
class UndoQueue
|
||||
|
||||
constructor: (@_$timeout, @_$rootScope) ->
|
||||
@_queue = []
|
||||
|
||||
|
||||
add: (@_caption, @_callback, @_timeout=0, @_undoCallback=null) ->
|
||||
###
|
||||
@_caption the caption which indentifies the item
|
||||
@_callback function the callback which should be executed when it was
|
||||
not undone, this will usually be a request to the server to finally
|
||||
delete something
|
||||
@_timeout int the timeout after the callback should be executed
|
||||
defaults to 0
|
||||
@_undoCallback function the function which should be executed when
|
||||
an command has been canceled. Usually this will add back a deleted
|
||||
object back to the interface, defaults to an empty function
|
||||
###
|
||||
@_executeAll()
|
||||
|
||||
command =
|
||||
_undoCallback: @_undoCallback or= ->
|
||||
_callback: @_callback
|
||||
execute: =>
|
||||
command._callback()
|
||||
undo: =>
|
||||
command._undoCallback()
|
||||
@_$timeout.cancel(command.promise)
|
||||
@_queue = []
|
||||
promise: @_$timeout =>
|
||||
command.execute()
|
||||
@_$rootScope.$broadcast('notUndone')
|
||||
, @_timeout
|
||||
|
||||
data =
|
||||
undoCallback: command.undo
|
||||
caption: @_caption
|
||||
|
||||
@_$rootScope.$broadcast 'undoMessage', data
|
||||
|
||||
@_queue.push(command)
|
||||
|
||||
|
||||
_executeAll: ->
|
||||
###
|
||||
Executes the callback before the timeout has run out
|
||||
This is useful to execute all remaining commands if a new command is
|
||||
added
|
||||
###
|
||||
for command in @_queue
|
||||
@_$timeout.cancel(command.promise)
|
||||
command.execute()
|
||||
@_queue = []
|
||||
|
||||
|
||||
return new UndoQueue($timeout, $rootScope)
|
||||
|
||||
]
|
207
js/public/app.js
207
js/public/app.js
|
@ -312,6 +312,63 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
|
||||
(function() {
|
||||
angular.module('News').directive('undoNotification', [
|
||||
'$rootScope', function($rootScope) {
|
||||
return function(scope, elm, attr) {
|
||||
var caption, link, undo;
|
||||
|
||||
elm.click(function() {
|
||||
return $(this).fadeOut();
|
||||
});
|
||||
scope.$on('notUndone', function() {
|
||||
return $(elm).fadeOut();
|
||||
});
|
||||
undo = function() {};
|
||||
caption = '';
|
||||
link = $(elm).find('a');
|
||||
link.click(function() {
|
||||
undo();
|
||||
$rootScope.$apply();
|
||||
return elm.fadeOut();
|
||||
});
|
||||
scope.getCaption = function() {
|
||||
return caption;
|
||||
};
|
||||
return scope.$on('undoMessage', function(scope, data) {
|
||||
undo = data.undoCallback;
|
||||
caption = data.caption;
|
||||
return elm.fadeIn().css("display", "inline");
|
||||
});
|
||||
};
|
||||
}
|
||||
]);
|
||||
|
||||
}).call(this);
|
||||
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
/*
|
||||
|
||||
ownCloud - News
|
||||
|
||||
@author Bernhard Posselt
|
||||
@copyright 2012 Bernhard Posselt nukeawhale@gmail.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/>.
|
||||
*/
|
||||
|
||||
|
||||
(function() {
|
||||
angular.module('News').controller('FeedController', [
|
||||
'$scope', '_ExistsError', 'Persistence', 'FolderBusinessLayer', 'FeedBusinessLayer', 'SubscriptionsBusinessLayer', 'StarredBusinessLayer', 'unreadCountFormatter', 'ActiveFeed', 'FeedType', '$window', function($scope, _ExistsError, Persistence, FolderBusinessLayer, FeedBusinessLayer, SubscriptionsBusinessLayer, StarredBusinessLayer, unreadCountFormatter, ActiveFeed, FeedType, $window) {
|
||||
|
@ -711,17 +768,19 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
angular.module('News').factory('FeedBusinessLayer', [
|
||||
'_BusinessLayer', 'ShowAll', 'Persistence', 'ActiveFeed', 'FeedType', 'ItemModel', 'FeedModel', 'NewLoading', '_ExistsError', 'Utils', function(_BusinessLayer, ShowAll, Persistence, ActiveFeed, FeedType, ItemModel, FeedModel, NewLoading, _ExistsError, Utils) {
|
||||
'_BusinessLayer', 'ShowAll', 'Persistence', 'ActiveFeed', 'FeedType', 'ItemModel', 'FeedModel', 'NewLoading', '_ExistsError', 'Utils', '$rootScope', 'UndoQueue', function(_BusinessLayer, ShowAll, Persistence, ActiveFeed, FeedType, ItemModel, FeedModel, NewLoading, _ExistsError, Utils, $rootScope, UndoQueue) {
|
||||
var FeedBusinessLayer;
|
||||
|
||||
FeedBusinessLayer = (function(_super) {
|
||||
__extends(FeedBusinessLayer, _super);
|
||||
|
||||
function FeedBusinessLayer(_showAll, _feedModel, persistence, activeFeed, feedType, itemModel, _newLoading, _utils) {
|
||||
function FeedBusinessLayer(_showAll, _feedModel, persistence, activeFeed, feedType, itemModel, _newLoading, _utils, _$rootScope, _undoQueue) {
|
||||
this._showAll = _showAll;
|
||||
this._feedModel = _feedModel;
|
||||
this._newLoading = _newLoading;
|
||||
this._utils = _utils;
|
||||
this._$rootScope = _$rootScope;
|
||||
this._undoQueue = _undoQueue;
|
||||
FeedBusinessLayer.__super__.constructor.call(this, activeFeed, persistence, itemModel, feedType.Feed);
|
||||
this._feedType = feedType;
|
||||
}
|
||||
|
@ -743,8 +802,17 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
};
|
||||
|
||||
FeedBusinessLayer.prototype["delete"] = function(feedId) {
|
||||
this._feedModel.removeById(feedId);
|
||||
return this._persistence.deleteFeed(feedId);
|
||||
var callback, feed, undoCallback,
|
||||
_this = this;
|
||||
|
||||
feed = this._feedModel.removeById(feedId);
|
||||
callback = function() {
|
||||
return _this._persistence.deleteFeed(feedId);
|
||||
};
|
||||
undoCallback = function() {
|
||||
return _this._feedModel.add(feed);
|
||||
};
|
||||
return this._undoQueue.add(feed.title, callback, 10 * 1000, undoCallback);
|
||||
};
|
||||
|
||||
FeedBusinessLayer.prototype.markFeedRead = function(feedId) {
|
||||
|
@ -912,7 +980,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
return FeedBusinessLayer;
|
||||
|
||||
})(_BusinessLayer);
|
||||
return new FeedBusinessLayer(ShowAll, FeedModel, Persistence, ActiveFeed, FeedType, ItemModel, NewLoading, Utils);
|
||||
return new FeedBusinessLayer(ShowAll, FeedModel, Persistence, ActiveFeed, FeedType, ItemModel, NewLoading, Utils, $rootScope, UndoQueue);
|
||||
}
|
||||
]);
|
||||
|
||||
|
@ -946,18 +1014,19 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
angular.module('News').factory('FolderBusinessLayer', [
|
||||
'_BusinessLayer', 'FolderModel', 'FeedBusinessLayer', 'Persistence', 'FeedType', 'ActiveFeed', 'ItemModel', 'ShowAll', '_ExistsError', 'OPMLParser', function(_BusinessLayer, FolderModel, FeedBusinessLayer, Persistence, FeedType, ActiveFeed, ItemModel, ShowAll, _ExistsError, OPMLParser) {
|
||||
'_BusinessLayer', 'FolderModel', 'FeedBusinessLayer', 'Persistence', 'FeedType', 'ActiveFeed', 'ItemModel', 'ShowAll', '_ExistsError', 'OPMLParser', 'UndoQueue', function(_BusinessLayer, FolderModel, FeedBusinessLayer, Persistence, FeedType, ActiveFeed, ItemModel, ShowAll, _ExistsError, OPMLParser, UndoQueue) {
|
||||
var FolderBusinessLayer;
|
||||
|
||||
FolderBusinessLayer = (function(_super) {
|
||||
__extends(FolderBusinessLayer, _super);
|
||||
|
||||
function FolderBusinessLayer(_folderModel, _feedBusinessLayer, _showAll, activeFeed, persistence, _feedType, itemModel, _opmlParser) {
|
||||
function FolderBusinessLayer(_folderModel, _feedBusinessLayer, _showAll, activeFeed, persistence, _feedType, itemModel, _opmlParser, _undoQueue) {
|
||||
this._folderModel = _folderModel;
|
||||
this._feedBusinessLayer = _feedBusinessLayer;
|
||||
this._showAll = _showAll;
|
||||
this._feedType = _feedType;
|
||||
this._opmlParser = _opmlParser;
|
||||
this._undoQueue = _undoQueue;
|
||||
FolderBusinessLayer.__super__.constructor.call(this, activeFeed, persistence, itemModel, this._feedType.Folder);
|
||||
}
|
||||
|
||||
|
@ -966,8 +1035,17 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
};
|
||||
|
||||
FolderBusinessLayer.prototype["delete"] = function(folderId) {
|
||||
this._folderModel.removeById(folderId);
|
||||
return this._persistence.deleteFolder(folderId);
|
||||
var callback, folder, undoCallback,
|
||||
_this = this;
|
||||
|
||||
folder = this._folderModel.removeById(folderId);
|
||||
callback = function() {
|
||||
return _this._persistence.deleteFolder(folderId);
|
||||
};
|
||||
undoCallback = function() {
|
||||
return _this._folderModel.add(folder);
|
||||
};
|
||||
return this._undoQueue.add(folder.name, callback, 10 * 1000, undoCallback);
|
||||
};
|
||||
|
||||
FolderBusinessLayer.prototype.hasFeeds = function(folderId) {
|
||||
|
@ -1136,7 +1214,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
return FolderBusinessLayer;
|
||||
|
||||
})(_BusinessLayer);
|
||||
return new FolderBusinessLayer(FolderModel, FeedBusinessLayer, ShowAll, ActiveFeed, Persistence, FeedType, ItemModel, OPMLParser);
|
||||
return new FolderBusinessLayer(FolderModel, FeedBusinessLayer, ShowAll, ActiveFeed, Persistence, FeedType, ItemModel, OPMLParser, UndoQueue);
|
||||
}
|
||||
]);
|
||||
|
||||
|
@ -1626,7 +1704,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
}
|
||||
if (data.faviconLink === null) {
|
||||
data.faviconLink = 'url(' + this._utils.imagePath('news', 'rss.svg') + ')';
|
||||
} else if (angular.isDefined(data.faviconLink)) {
|
||||
} else if (angular.isDefined(data.faviconLink) && data.faviconLink.indexOf('url(') !== 0) {
|
||||
data.faviconLink = 'url(' + data.faviconLink + ')';
|
||||
}
|
||||
/*
|
||||
|
@ -2977,6 +3055,113 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
// Generated by CoffeeScript 1.6.2
|
||||
/*
|
||||
|
||||
ownCloud - App Framework
|
||||
|
||||
@author Bernhard Posselt
|
||||
@copyright 2012 Bernhard Posselt nukeawhale@gmail.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/>.
|
||||
*/
|
||||
|
||||
|
||||
(function() {
|
||||
angular.module('News').factory('UndoQueue', [
|
||||
'$timeout', '$rootScope', function($timeout, $rootScope) {
|
||||
var UndoQueue;
|
||||
|
||||
UndoQueue = (function() {
|
||||
function UndoQueue(_$timeout, _$rootScope) {
|
||||
this._$timeout = _$timeout;
|
||||
this._$rootScope = _$rootScope;
|
||||
this._queue = [];
|
||||
}
|
||||
|
||||
UndoQueue.prototype.add = function(_caption, _callback, _timeout, _undoCallback) {
|
||||
var command, data,
|
||||
_this = this;
|
||||
|
||||
this._caption = _caption;
|
||||
this._callback = _callback;
|
||||
this._timeout = _timeout != null ? _timeout : 0;
|
||||
this._undoCallback = _undoCallback != null ? _undoCallback : null;
|
||||
/*
|
||||
@_caption the caption which indentifies the item
|
||||
@_callback function the callback which should be executed when it was
|
||||
not undone, this will usually be a request to the server to finally
|
||||
delete something
|
||||
@_timeout int the timeout after the callback should be executed
|
||||
defaults to 0
|
||||
@_undoCallback function the function which should be executed when
|
||||
an command has been canceled. Usually this will add back a deleted
|
||||
object back to the interface, defaults to an empty function
|
||||
*/
|
||||
|
||||
this._executeAll();
|
||||
command = {
|
||||
_undoCallback: this._undoCallback || (this._undoCallback = function() {}),
|
||||
_callback: this._callback,
|
||||
execute: function() {
|
||||
return command._callback();
|
||||
},
|
||||
undo: function() {
|
||||
command._undoCallback();
|
||||
_this._$timeout.cancel(command.promise);
|
||||
return _this._queue = [];
|
||||
},
|
||||
promise: this._$timeout(function() {
|
||||
command.execute();
|
||||
return _this._$rootScope.$broadcast('notUndone');
|
||||
}, this._timeout)
|
||||
};
|
||||
data = {
|
||||
undoCallback: command.undo,
|
||||
caption: this._caption
|
||||
};
|
||||
this._$rootScope.$broadcast('undoMessage', data);
|
||||
return this._queue.push(command);
|
||||
};
|
||||
|
||||
UndoQueue.prototype._executeAll = function() {
|
||||
/*
|
||||
Executes the callback before the timeout has run out
|
||||
This is useful to execute all remaining commands if a new command is
|
||||
added
|
||||
*/
|
||||
|
||||
var command, _i, _len, _ref;
|
||||
|
||||
_ref = this._queue;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
command = _ref[_i];
|
||||
this._$timeout.cancel(command.promise);
|
||||
command.execute();
|
||||
}
|
||||
return this._queue = [];
|
||||
};
|
||||
|
||||
return UndoQueue;
|
||||
|
||||
})();
|
||||
return new UndoQueue($timeout, $rootScope);
|
||||
}
|
||||
]);
|
||||
|
||||
}).call(this);
|
||||
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
/*
|
||||
|
||||
ownCloud - News
|
||||
|
||||
@author Bernhard Posselt
|
||||
|
|
|
@ -44,16 +44,20 @@ describe 'FeedBusinessLayer', ->
|
|||
|
||||
|
||||
beforeEach inject (@FeedBusinessLayer, @FeedModel, @ItemModel, @FeedType,
|
||||
@ShowAll, @ActiveFeed, @_ExistsError) =>
|
||||
@ShowAll, @ActiveFeed, @_ExistsError, @$timeout) =>
|
||||
@ShowAll.setShowAll(false)
|
||||
@ActiveFeed.handle({type: @FeedType.Folder, id:0})
|
||||
|
||||
it 'should delete feeds', =>
|
||||
@FeedModel.removeById = jasmine.createSpy('remove')
|
||||
@FeedModel.removeById = jasmine.createSpy('remove').andCallFake ->
|
||||
return {id: 3, title: 'test'}
|
||||
@persistence.deleteFeed = jasmine.createSpy('deletequery')
|
||||
@FeedBusinessLayer.delete(3)
|
||||
|
||||
expect(@FeedModel.removeById).toHaveBeenCalledWith(3)
|
||||
|
||||
@$timeout.flush()
|
||||
|
||||
expect(@persistence.deleteFeed).toHaveBeenCalledWith(3)
|
||||
|
||||
|
||||
|
|
|
@ -39,15 +39,17 @@ describe 'FolderBusinessLayer', ->
|
|||
|
||||
|
||||
beforeEach inject (@FolderBusinessLayer, @FolderModel, @FeedModel, @ShowAll,
|
||||
@ActiveFeed, @FeedType, @_ExistsError) =>
|
||||
@ActiveFeed, @FeedType, @_ExistsError, @$timeout) =>
|
||||
@ShowAll.setShowAll(false)
|
||||
@ActiveFeed.handle({type: @FeedType.Feed, id:0})
|
||||
|
||||
|
||||
it 'should delete folders', =>
|
||||
@FolderModel.removeById = jasmine.createSpy('remove')
|
||||
@FolderModel.removeById = jasmine.createSpy('remove').andCallFake ->
|
||||
return {id: 3, name: 'test'}
|
||||
@persistence.deleteFolder = jasmine.createSpy('deletequery')
|
||||
@FolderBusinessLayer.delete(3)
|
||||
@$timeout.flush()
|
||||
|
||||
expect(@FolderModel.removeById).toHaveBeenCalledWith(3)
|
||||
expect(@persistence.deleteFolder).toHaveBeenCalledWith(3)
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
###
|
||||
|
||||
ownCloud - App Framework
|
||||
|
||||
@author Bernhard Posselt
|
||||
@copyright 2012 Bernhard Posselt nukeawhale@gmail.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 'UndoQueue', ->
|
||||
|
||||
beforeEach module 'News'
|
||||
|
||||
|
||||
beforeEach inject (@UndoQueue, @$timeout, @$rootScope) =>
|
||||
@queue = @UndoQueue
|
||||
|
||||
|
||||
it 'should execute a callback', =>
|
||||
executed = false
|
||||
callback = ->
|
||||
executed = true
|
||||
|
||||
@queue.add('hi', callback, 3000)
|
||||
|
||||
@$timeout.flush()
|
||||
|
||||
expect(executed).toBe(true)
|
||||
|
||||
|
||||
it 'should execute a task when a new one is added', =>
|
||||
executed = 0
|
||||
undone = 0
|
||||
callback = ->
|
||||
executed += 1
|
||||
|
||||
undoCallback = ->
|
||||
undone += 1
|
||||
|
||||
@queue.add('hi', callback, 3000, undoCallback)
|
||||
@queue.add('hi', callback, 3000, undoCallback)
|
||||
|
||||
expect(executed).toBe(1)
|
||||
expect(undone).toBe(0)
|
||||
|
||||
|
|
@ -22,6 +22,12 @@
|
|||
?>
|
||||
|
||||
<div id="app" ng-app="News">
|
||||
<div id="undo-container">
|
||||
<div undo-notification id="undo">
|
||||
<a href="#"><?php p($l->t('Undo deletion of ')); ?>{{ getCaption() }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="app-navigation" ng-controller="FeedController">
|
||||
|
||||
<ul class="with-icon" data-id="0" droppable>
|
||||
|
|
Загрузка…
Ссылка в новой задаче