From 6dcfbaee7f7ddbc019b5a360ce1b8ca72fc19ac0 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 12 Nov 2013 11:09:30 +1100 Subject: [PATCH] Adds a new filter arg to remove tree cache - we will use this in order to clear specific items from tree cache (like when we are creating folders for media in the media picker) --- .../src/common/services/tree.service.js | 33 ++++++++- .../src/common/services/util.service.js | 31 +++++++++ .../unit/common/services/tree-service.spec.js | 67 ++++++++++++++++--- 3 files changed, 118 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js index 5b6bf1833c..7a310a5d3b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js @@ -9,7 +9,11 @@ */ function treeService($q, treeResource, iconHelper, notificationsService, $rootScope) { - //TODO: implement this in local storage + //SD: Have looked at putting this in sessionStorage (not localStorage since that means you wouldn't be able to work + // in multiple tabs) - however our tree structure is cyclical, meaning a node has a reference to it's parent and it's children + // which you cannot serialize to sessionStorage. There's really no benefit of session storage except that you could refresh + // a tab and have the trees where they used to be - supposed that is kind of nice but would mean we'd have to store the parent + // as a nodeid reference instead of a variable with a getParent() method. var treeCache = {}; var standardCssClass = 'icon umb-tree-icon sprTree'; @@ -108,7 +112,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, $rootSc return undefined; }, - /** clears the tree cache - with optional cacheKey and optional section */ + /** clears the tree cache - with optional cacheKey, optional section or optional filter */ clearCache: function (args) { //clear all if not specified if (!args) { @@ -122,6 +126,29 @@ function treeService($q, treeResource, iconHelper, notificationsService, $rootSc treeCache = _.omit(treeCache, cacheKey); } } + else if (args.filter && angular.isFunction(args.filter)) { + //if a filter is supplied a cacheKey must be supplied as well + if (!args.cacheKey) { + throw "args.cacheKey is required if args.filter is supplied"; + } + + //if a filter is supplied the function needs to return the data to keep + var byKey = treeCache[args.cacheKey]; + if (byKey) { + var result = args.filter(byKey); + + if (result) { + //set the result to the filtered data + treeCache[args.cacheKey] = result; + } + else { + //remove the cache + treeCache = _.omit(treeCache, args.cacheKey); + } + + } + + } else if (args.cacheKey) { //if only the cache key is specified, then clear all cache starting with that key var allKeys1 = _.keys(treeCache); @@ -137,7 +164,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, $rootSc return k.endsWith("_" + args.section); }); treeCache = _.omit(treeCache, toRemove2); - } + } } }, diff --git a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js index 839411a90b..7892726d80 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js @@ -1,5 +1,36 @@ /*Contains multiple services for various helper tasks */ +/** + * @ngdoc function + * @name umbraco.services.umbSessionStorage + * @function + * + * @description + * Used to get/set things in browser sessionStorage but always prefixes keys with "umb_" and converts json vals so there is no overlap + * with any sessionStorage created by a developer. + */ +function umbSessionStorage($window) { + + //gets the sessionStorage object if available, otherwise just uses a normal object + // - required for unit tests. + var storage = $window['sessionStorage'] ? $window['sessionStorage'] : {}; + + return { + + get: function (key) { + console.log(storage); + console.log(storage["umb_" + key]); + return angular.fromJson(storage["umb_" + key]); + }, + + set : function(key, value) { + storage["umb_" + key] = angular.toJson(value); + } + + }; +} +angular.module('umbraco.services').factory('umbSessionStorage', umbSessionStorage); + /** * @ngdoc function * @name umbraco.services.legacyJsLoader diff --git a/src/Umbraco.Web.UI.Client/test/unit/common/services/tree-service.spec.js b/src/Umbraco.Web.UI.Client/test/unit/common/services/tree-service.spec.js index cd79092385..499d8c1d6b 100644 --- a/src/Umbraco.Web.UI.Client/test/unit/common/services/tree-service.spec.js +++ b/src/Umbraco.Web.UI.Client/test/unit/common/services/tree-service.spec.js @@ -54,16 +54,6 @@ describe('tree service tests', function () { describe('tree cache', function () { - //it('tree with section but no cache key does not cache', function () { - // treeService.getTree().then(function (data) { - - // var cache = treeService._getTreeCache(); - // expect(cache).toBeDefined(); - // expect(cache["_content"]).toBeDefined(); - - // }); - //}); - it('does not cache with no args', function () { var cache; @@ -215,6 +205,63 @@ describe('tree service tests', function () { cache = treeService._getTreeCache(); expect(_.keys(cache).length).toBe(0); }); + + it('clears cache by key using a filter that returns null', function () { + + var cache; + + treeService.getTree({ section: "media", cacheKey: "_" }).then(function (d) { + treeService.getTree({ section: "content", cacheKey: "_" }).then(function (dd) { + cache = treeService._getTreeCache(); + }); + }); + + $rootScope.$digest(); + $httpBackend.flush(); + + expect(_.keys(cache).length).toBe(2); + + treeService.clearCache({ + cacheKey: "__content", + filter: function(currentCache) { + return null; + } + }); + + cache = treeService._getTreeCache(); + + expect(_.keys(cache).length).toBe(1); + }); + + it('removes cache by key using a filter', function () { + + var cache; + + treeService.getTree({ section: "media", cacheKey: "_" }).then(function (d) { + treeService.getTree({ section: "content", cacheKey: "_" }).then(function (dd) { + cache = treeService._getTreeCache(); + }); + }); + + $rootScope.$digest(); + $httpBackend.flush(); + + expect(_.keys(cache).length).toBe(2); + expect(cache.__content.root.children.length).toBe(4); + + treeService.clearCache({ + cacheKey: "__content", + filter: function (currentCache) { + var toRemove = treeService.getDescendantNode(currentCache.root, 1235); + toRemove.parent.children = _.without(toRemove.parent.children, toRemove); + return currentCache; + } + }); + + cache = treeService._getTreeCache(); + + expect(cache.__content.root.children.length).toBe(3); + }); });