From 5ffc33fe0c07910f005f7e76134bf30077a1e251 Mon Sep 17 00:00:00 2001 From: Juanfran Date: Tue, 19 May 2015 09:02:32 +0200 Subject: [PATCH] currentUserService + refactor --- app/coffee/app.coffee | 6 +- app/coffee/modules/auth.coffee | 13 +- app/coffee/modules/base/http.coffee | 12 +- app/coffee/modules/common/loader.coffee | 2 +- app/modules/home/home-page.jade | 1 - app/modules/home/home.directive.coffee | 37 --- app/modules/home/home.directive.spec.coffee | 91 ------- app/modules/home/home.jade | 13 +- app/modules/home/home.service.coffee | 144 +++++------ app/modules/home/home.service.spec.coffee | 243 ++++++++---------- .../home-project-list-directive.spec.coffee | 40 +-- .../home-project-list.directive.coffee | 9 +- .../working-on/working-on.controller.coffee | 29 +++ .../working-on.controller.spec.coffee | 59 +++++ .../working-on/working-on.directive.coffee | 20 ++ app/modules/home/working-on/working-on.jade | 12 + .../dropdown-project-list.directive.coffee | 5 +- ...ropdown-project-list.directive.spec.coffee | 54 ++-- .../navigation-bar.directive.coffee | 6 +- .../navigation-bar.directive.spec.coffee | 32 +-- .../projects-listing.controller.coffee | 7 +- .../projects-listing.controller.spec.coffee | 29 ++- app/modules/projects/projects.service.coffee | 37 +-- .../projects/projects.service.spec.coffee | 108 +++----- .../services/current-user.service.coffee | 45 ++++ .../services/current-user.service.spec.coffee | 77 ++++++ bower.json | 3 +- gulpfile.js | 1 + karma.conf.js | 2 +- package.json | 1 - 30 files changed, 579 insertions(+), 559 deletions(-) delete mode 100644 app/modules/home/home-page.jade delete mode 100644 app/modules/home/home.directive.coffee delete mode 100644 app/modules/home/home.directive.spec.coffee create mode 100644 app/modules/home/working-on/working-on.controller.coffee create mode 100644 app/modules/home/working-on/working-on.controller.spec.coffee create mode 100644 app/modules/home/working-on/working-on.directive.coffee create mode 100644 app/modules/home/working-on/working-on.jade create mode 100644 app/modules/services/current-user.service.coffee create mode 100644 app/modules/services/current-user.service.spec.coffee diff --git a/app/coffee/app.coffee b/app/coffee/app.coffee index 201e2bf5..8b3b7f84 100644 --- a/app/coffee/app.coffee +++ b/app/coffee/app.coffee @@ -40,7 +40,7 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven $compileProvider, $translateProvider) -> $routeProvider.when("/", { - templateUrl: "home/home-page.html", + templateUrl: "home/home.html", access: { requiresLogin: true }, @@ -365,6 +365,10 @@ init = ($log, $rootscope, $auth, $events, $analytics, $translate, $location, $na lang = ctx.language i18nInit(lang, $translate) + # bluebird + Promise.setScheduler (cb) -> + $rootscope.$evalAsync(cb) + # Load user if $auth.isAuthenticated() $events.setupConnection() diff --git a/app/coffee/modules/auth.coffee b/app/coffee/modules/auth.coffee index 4e9e884b..a675ca65 100644 --- a/app/coffee/modules/auth.coffee +++ b/app/coffee/modules/auth.coffee @@ -36,15 +36,21 @@ class AuthService extends taiga.Service "$tgHttp", "$tgUrls", "$tgConfig", - "$translate"] + "$translate", + "tgCurrentUserService"] - constructor: (@rootscope, @storage, @model, @rs, @http, @urls, @config, @translate) -> + constructor: (@rootscope, @storage, @model, @rs, @http, @urls, @config, @translate, @currentUserService) -> super() userModel = @.getUser() @.setUserdata(userModel) setUserdata: (userModel) -> - @.userData = Immutable.fromJS(userModel.getAttrs()) + if userModel + @.userData = Immutable.fromJS(userModel.getAttrs()) + @currentUserService.setUser(@.userData) + else + @.userData = null + _setLocales: -> lang = @rootscope.user.lang || @config.get("defaultLanguage") || "en" @@ -67,6 +73,7 @@ class AuthService extends taiga.Service @rootscope.auth = user @storage.set("userInfo", user.getAttrs()) @rootscope.user = user + @.setUserdata(user) @._setLocales() diff --git a/app/coffee/modules/base/http.coffee b/app/coffee/modules/base/http.coffee index ddf2c7a9..e8847601 100644 --- a/app/coffee/modules/base/http.coffee +++ b/app/coffee/modules/base/http.coffee @@ -22,11 +22,12 @@ taiga = @.taiga class HttpService extends taiga.Service - @.$inject = ["$http", "$q", "$tgStorage", "$rootScope"] + @.$inject = ["$http", "$q", "$tgStorage", "$rootScope", "$cacheFactory"] - constructor: (@http, @q, @storage, @rootScope) -> + constructor: (@http, @q, @storage, @rootScope, @cacheFactory) -> super() + @.cache = @cacheFactory("httpget"); headers: -> headers = {} @@ -52,7 +53,12 @@ class HttpService extends taiga.Service get: (url, params, options) -> options = _.merge({method: "GET", url: url}, options) options.params = params if params - return @.request(options) + + # prevent duplicated http request + options.cache = @.cache + + return @.request(options).finally (data) => + @.cache.removeAll() post: (url, data, params, options) -> options = _.merge({method: "POST", url: url}, options) diff --git a/app/coffee/modules/common/loader.coffee b/app/coffee/modules/common/loader.coffee index 01e48791..d6886971 100644 --- a/app/coffee/modules/common/loader.coffee +++ b/app/coffee/modules/common/loader.coffee @@ -105,7 +105,7 @@ Loader = () -> clearInterval(intervalAuto) clearTimeout(timeoutAuto) - ), 200 + ), 50 start = () -> startLoadTime = new Date().getTime() diff --git a/app/modules/home/home-page.jade b/app/modules/home/home-page.jade deleted file mode 100644 index 9e2a5c4a..00000000 --- a/app/modules/home/home-page.jade +++ /dev/null @@ -1 +0,0 @@ -div(tg-home) diff --git a/app/modules/home/home.directive.coffee b/app/modules/home/home.directive.coffee deleted file mode 100644 index 47d8f99c..00000000 --- a/app/modules/home/home.directive.coffee +++ /dev/null @@ -1,37 +0,0 @@ -HomeDirective = ($q, homeService, projectsService) -> - link = (scope, el, attrs, ctrl) -> - scope.vm = {} - - projectsPromise = projectsService.getCurrentUserProjects() - workInProgresPromise = homeService.getWorkInProgress() - - $q.all([projectsPromise, workInProgresPromise]).then -> - homeService.attachProjectInfoToWorkInProgress(projectsService.currentUserProjectsById) - - taiga.defineImmutableProperty(scope.vm, "projects", () -> projectsService.currentUserProjects) - taiga.defineImmutableProperty(scope.vm, "workInProgress", () -> homeService.workInProgress) - - if scope.vm.workInProgress.size > 0 - userStories = scope.vm.workInProgress.get("assignedTo").get("userStories") - tasks = scope.vm.workInProgress.get("assignedTo").get("tasks") - issues = scope.vm.workInProgress.get("assignedTo").get("issues") - scope.vm.assignedTo = userStories.concat(tasks).concat(issues) - - userStories = scope.vm.workInProgress.get("watching").get("userStories") - tasks = scope.vm.workInProgress.get("watching").get("tasks") - issues = scope.vm.workInProgress.get("watching").get("issues") - scope.vm.watching = userStories.concat(tasks).concat(issues) - - return { - templateUrl: "home/home.html" - scope: {} - link: link - } - -HomeDirective.$inject = [ - "$q", - "tgHomeService", - "tgProjectsService" -] - -angular.module("taigaHome").directive("tgHome", HomeDirective) diff --git a/app/modules/home/home.directive.spec.coffee b/app/modules/home/home.directive.spec.coffee deleted file mode 100644 index e91aa9cb..00000000 --- a/app/modules/home/home.directive.spec.coffee +++ /dev/null @@ -1,91 +0,0 @@ -describe "homeDirective", () -> - scope = compile = provide = timeout = null - mockTgHomeService = mockTgProjectsService = null - thenStubGetCurrentUserProjectsById = thenStubGetWorkInProgress = null - template = "
" - - createDirective = () -> - elm = compile(template)(scope) - return elm - - _mockTgHomeService = () -> - thenStubGetWorkInProgress = sinon.stub() - - mockTgHomeService = { - getWorkInProgress: sinon.stub() - workInProgress: Immutable.fromJS({ - assignedTo: { - userStories: [{"id": 1}] - tasks: [{"id": 2}] - issues: [{"id": 3}] - } - watching: { - userStories: [{"id": 4}] - tasks: [{"id": 5}] - issues: [{"id": 6}] - } - }) - attachProjectInfoToWorkInProgress: sinon.stub() - } - - mockTgHomeService.getWorkInProgress.returns({ - then: thenStubGetWorkInProgress - }) - provide.value "tgHomeService", mockTgHomeService - - _mockTranslateFilter = () -> - mockTranslateFilter = (value) -> - return value - provide.value "translateFilter", mockTranslateFilter - - _mockTgDuty = () -> - provide.factory 'tgDutyDirective', () -> {} - - _mockHomeProjectList = () -> - provide.factory 'tgHomeProjectListDirective', () -> {} - - _mockTgProjectsService = () -> - thenStubGetCurrentUserProjectsById = sinon.stub() - mockTgProjectsService = { - getCurrentUserProjects: sinon.stub() - currentUserProjectsById: { - get: sinon.stub() - } - } - - mockTgProjectsService.getCurrentUserProjects.returns({ - then: thenStubGetCurrentUserProjectsById - }) - provide.value "tgProjectsService", mockTgProjectsService - - _mocks = () -> - module ($provide) -> - provide = $provide - _mockTgDuty() - _mockHomeProjectList() - _mockTgHomeService() - _mockTranslateFilter() - _mockTgProjectsService() - return null - - beforeEach -> - module "templates" - module "taigaHome" - - _mocks() - - inject ($rootScope, $compile, $timeout) -> - scope = $rootScope.$new() - compile = $compile - timeout = $timeout - - it "home directive content", () -> - elm = createDirective() - scope.$apply() - - thenStubGetCurrentUserProjectsById.callArg(0) - thenStubGetWorkInProgress.callArg(0) - timeout.flush() - - expect(elm.isolateScope().vm.assignedTo.size).to.be.equal(3) - expect(elm.isolateScope().vm.watching.size).to.be.equal(3) diff --git a/app/modules/home/home.jade b/app/modules/home/home.jade index c73a751b..eb815985 100644 --- a/app/modules/home/home.jade +++ b/app/modules/home/home.jade @@ -3,17 +3,6 @@ doctype html include ../../partials/includes/components/beta div.home-wrapper.centered div.duty-summary - div.title-bar.working-on-title(ng-show="vm.assignedTo.size", translate="HOME.WORKING_ON_SECTION") - section.working-on(ng-show="vm.assignedTo.size") - div.duty-single(tg-duty="duty", tg-repeat="duty in vm.assignedTo", ng-class="{blocked: duty.is_blocked}") - - div.title-bar.watching-title(translate="HOME.WATCHING_SECTION") - - section.watching-empty(ng-show="!vm.watching.size") - include ../../svg/hide.svg - p(translate="HOME.EMPTY_WATCHING") - - section.watching(ng-show="vm.watching.size") - div.duty-single(tg-duty="duty", tg-repeat="duty in vm.watching", ng-class="{blocked: duty.is_blocked}") + div(tg-working-on) aside.project-list(tg-home-project-list) diff --git a/app/modules/home/home.service.coffee b/app/modules/home/home.service.coffee index 36207c45..08cc5e03 100644 --- a/app/modules/home/home.service.coffee +++ b/app/modules/home/home.service.coffee @@ -1,18 +1,18 @@ +groupBy = @.taiga.groupBy + class HomeService extends taiga.Service - @.$inject = ["$q", "$tgNavUrls", "tgResources", "$rootScope", "$projectUrl", "$tgAuth"] + @.$inject = [ + "$tgNavUrls", + "tgResources", + "tgProjectsService" + ] - constructor: (@q, @navurls, @rs, @rootScope, @projectUrl, @auth) -> - @._workInProgress = Immutable.Map() - @._projectPromise = null - @._inProgress = false + constructor: (@navurls, @rs, @projectsService) -> - taiga.defineImmutableProperty @, "workInProgress", () => return @._workInProgress - - @.fetchWorkInProgress() - - attachProjectInfoToWorkInProgress: (projectsById) -> + _attachProjectInfoToWorkInProgress: (workInProgress, projectsById) -> _attachProjectInfoToDuty = (duty, objType) => project = projectsById.get(String(duty.get('project'))) + ctx = { project: project.get('slug') ref: duty.get('ref') @@ -26,105 +26,105 @@ class HomeService extends taiga.Service return duty - assignedTo = Immutable.Map() + assignedTo = workInProgress.get("assignedTo") - if @.assignedToUserStories - _duties = @.assignedToUserStories.map (duty) -> + if assignedTo.get("userStories") + _duties = assignedTo.get("userStories").map (duty) -> return _attachProjectInfoToDuty(duty, "userstories") assignedTo = assignedTo.set("userStories", _duties) - if @.assignedToTasks - _duties = @.assignedToTasks.map (duty) -> + if assignedTo.get("tasks") + _duties = assignedTo.get("tasks").map (duty) -> return _attachProjectInfoToDuty(duty, "tasks") assignedTo = assignedTo.set("tasks", _duties) - if @.assignedToIssues - _duties = @.assignedToIssues.map (duty) -> + if assignedTo.get("issues") + _duties = assignedTo.get("issues").map (duty) -> return _attachProjectInfoToDuty(duty, "issues") assignedTo = assignedTo.set("issues", _duties) - watching = Immutable.Map() + watching = workInProgress.get("watching") - if @.watchingUserStories - _duties = @.watchingUserStories.map (duty) -> + if watching.get("userStories") + _duties = watching.get("userStories").map (duty) -> return _attachProjectInfoToDuty(duty, "userstories") watching = watching.set("userStories", _duties) - if @.watchingTasks - _duties = @.watchingTasks.map (duty) -> + if watching.get("tasks") + _duties = watching.get("tasks").map (duty) -> return _attachProjectInfoToDuty(duty, "tasks") watching = watching.set("tasks", _duties) - if @.watchingIssues - _duties = @.watchingIssues.map (duty) -> + if watching.get("issues") + _duties = watching.get("issues").map (duty) -> return _attachProjectInfoToDuty(duty, "issues") watching = watching.set("issues", _duties) - @._workInProgress = Immutable.Map({ - assignedTo: assignedTo, - watching: watching - }) - getWorkInProgress: () -> - return @._projectPromise + workInProgress = workInProgress.set("assignedTo", assignedTo) + workInProgress = workInProgress.set("watching", watching) - fetchWorkInProgress: () -> - userId = @auth.getUser().id - if not @._inProgress - @._inProgress = true - params = { - status__is_closed: false - assigned_to: userId - } - assignedUserStoriesPromise = @rs.userstories.listInAllProjects(params).then (userstories) => - @.assignedToUserStories = userstories + getWorkInProgress: (userId) -> + projectsById = Immutable.Map() - assignedTasksPromise = @rs.tasks.listInAllProjects(params).then (tasks) => - @.assignedToTasks = tasks + projectsPromise = @projectsService.getProjectsByUserId(userId).then (projects) -> + projectsById = Immutable.fromJS(groupBy(projects.toJS(), (p) -> p.id)) - assignedIssuesPromise = @rs.issues.listInAllProjects(params).then (issues) => - @.assignedToIssues = issues + assignedTo = Immutable.Map() - params = { - status__is_closed: false - watchers: userId - } - watchingUserStoriesPromise = @rs.userstories.listInAllProjects(params).then (userstories) => - @.watchingUserStories = userstories + params = { + status__is_closed: false + assigned_to: userId + } - watchingTasksPromise = @rs.tasks.listInAllProjects(params).then (tasks) => - @.watchingTasks = tasks + assignedUserStoriesPromise = @rs.userstories.listInAllProjects(params).then (userstories) -> + assignedTo = assignedTo.set("userStories", userstories) - watchingIssuesPromise = @rs.issues.listInAllProjects(params).then (issues) => - @.watchingIssues = issues + assignedTasksPromise = @rs.tasks.listInAllProjects(params).then (tasks) -> + assignedTo = assignedTo.set("tasks", tasks) - @._projectPromise = @q.all([assignedUserStoriesPromise, assignedTasksPromise, - assignedIssuesPromise, watchingUserStoriesPromise, - watchingUserStoriesPromise, watchingIssuesPromise]) + assignedIssuesPromise = @rs.issues.listInAllProjects(params).then (issues) -> + assignedTo = assignedTo.set("issues", issues) - @._projectPromise.then => - @._workInProgress = Immutable.fromJS({ - assignedTo: { - userStories: @.assignedToUserStories - tasks: @.assignedToTasks - issues: @.assignedToIssues - } - watching: { - userStories: @.watchingUserStories - tasks: @.watchingTasks - issues: @.watchingIssues - } - }) + params = { + status__is_closed: false + watchers: userId + } - @._inProgress = false + watching = Immutable.Map() - return @._projectPromise + watchingUserStoriesPromise = @rs.userstories.listInAllProjects(params).then (userstories) -> + watching = watching.set("userStories", userstories) + + watchingTasksPromise = @rs.tasks.listInAllProjects(params).then (tasks) -> + watching = watching.set("tasks", tasks) + + watchingIssuesPromise = @rs.issues.listInAllProjects(params).then (issues) -> + watching = watching.set("issues", issues) + + workInProgress = Immutable.Map() + + Promise.all([ + projectsPromise + assignedUserStoriesPromise, + assignedTasksPromise, + assignedIssuesPromise, + watchingUserStoriesPromise, + watchingTasksPromise, + watchingIssuesPromise + ]).then => + workInProgress = workInProgress.set("assignedTo", assignedTo) + workInProgress = workInProgress.set("watching", watching) + + workInProgress = @._attachProjectInfoToWorkInProgress(workInProgress, projectsById) + + return workInProgress angular.module("taigaHome").service("tgHomeService", HomeService) diff --git a/app/modules/home/home.service.spec.coffee b/app/modules/home/home.service.spec.coffee index 167c5a61..e174608f 100644 --- a/app/modules/home/home.service.spec.coffee +++ b/app/modules/home/home.service.spec.coffee @@ -1,90 +1,36 @@ describe "tgHome", -> - homeService = provide = timeout = null + homeService = provide = null mocks = {} _mockResources = () -> mocks.resources = {} - mocks.resources.userstories = { - listInAllProjects: sinon.stub() - } + mocks.resources.userstories = {} + mocks.resources.tasks = {} + mocks.resources.issues = {} - mocks.resources.tasks = { - listInAllProjects: sinon.stub() - } - - mocks.resources.issues = { - listInAllProjects: sinon.stub() - } - - paramsAssignedTo = { - status__is_closed: false - assigned_to: 1 - } - - paramsWatching = { - status__is_closed: false - watchers: 1 - } - - mocks.thenStubAssignedToUserstories = sinon.stub() - mocks.resources.userstories.listInAllProjects.withArgs(paramsAssignedTo).returns({ - then: mocks.thenStubAssignedToUserstories - }) - - mocks.thenStubAssignedToTasks = sinon.stub() - mocks.resources.tasks.listInAllProjects.withArgs(paramsAssignedTo).returns({ - then: mocks.thenStubAssignedToTasks - }) - - mocks.thenStubAssignedToIssues = sinon.stub() - mocks.resources.issues.listInAllProjects.withArgs(paramsAssignedTo).returns({ - then: mocks.thenStubAssignedToIssues - }) - - - mocks.thenStubWatchingUserstories = sinon.stub() - mocks.resources.userstories.listInAllProjects.withArgs(paramsWatching).returns({ - then: mocks.thenStubWatchingUserstories - }) - - mocks.thenStubWatchingTasks = sinon.stub() - mocks.resources.tasks.listInAllProjects.withArgs(paramsWatching).returns({ - then: mocks.thenStubWatchingTasks - }) - - mocks.thenStubWatchingIssues = sinon.stub() - mocks.resources.issues.listInAllProjects.withArgs(paramsWatching).returns({ - then: mocks.thenStubWatchingIssues - }) + mocks.resources.userstories.listInAllProjects = sinon.stub().promise() + mocks.resources.tasks.listInAllProjects = sinon.stub().promise() + mocks.resources.issues.listInAllProjects = sinon.stub().promise() provide.value "tgResources", mocks.resources - _mockProjectUrl = () -> - mocks.projectUrl = {get: sinon.stub()} - mocks.projectUrl.get = (project) -> - return "url-" + project.id - - provide.value "$projectUrl", mocks.projectUrl - - _mockAuth = () -> - mocks.auth = { - getUser: sinon.stub() - } - - mocks.auth.getUser.returns(id: 1) - - provide.value "$tgAuth", mocks.auth - _mockTgNavUrls = () -> mocks.tgNavUrls = { resolve: sinon.stub() } + provide.value "$tgNavUrls", mocks.tgNavUrls + _mockProjectsService = () -> + mocks.projectsService = { + getProjectsByUserId: sinon.stub().promise() + } + + provide.value "tgProjectsService", mocks.projectsService + _inject = (callback) -> - inject (_$timeout_, _tgHomeService_) -> - timeout = _$timeout_ + inject (_tgHomeService_) -> homeService = _tgHomeService_ callback() if callback @@ -92,9 +38,9 @@ describe "tgHome", -> module ($provide) -> provide = $provide _mockResources() - _mockProjectUrl() - _mockAuth() _mockTgNavUrls() + _mockProjectsService() + return null _setup = -> @@ -105,80 +51,93 @@ describe "tgHome", -> _setup() _inject() - describe "fetch items", -> - it "work in progress filled", () -> - mocks.thenStubAssignedToUserstories.callArg(0, Immutable.fromJS([{"id": 1}])) - mocks.thenStubAssignedToTasks.callArg(0, Immutable.fromJS([{"id": 2}])) - mocks.thenStubAssignedToIssues.callArg(0, Immutable.fromJS([{"id": 3}])) - mocks.thenStubWatchingUserstories.callArg(0, Immutable.fromJS([{"id": 4}])) - mocks.thenStubWatchingTasks.callArg(0, Immutable.fromJS([{"id": 5}])) - mocks.thenStubWatchingIssues.callArg(0, Immutable.fromJS([{"id": 6}])) + it "get work in progress by user", (done) -> + userId = 3 - timeout.flush() - expect(homeService.workInProgress.toJS()).to.be.eql({ - assignedTo: { - userStories: [{"id": 1}] - tasks: [{"id": 2}] - issues: [{"id": 3}] - } - watching: { - userStories: [{"id": 4}] - tasks: [{"id": 5}] - issues: [{"id": 6}] - } - }) + mocks.projectsService.getProjectsByUserId + .withArgs(userId) + .resolve(Immutable.fromJS([ + {id: 1, name: "fake1", slug: "project-1"}, + {id: 2, name: "fake2", slug: "project-2"} + ])) - it "_inProgress change to false when tgResources end", () -> - expect(homeService._inProgress).to.be.true - timeout.flush() - expect(homeService._inProgress).to.be.false + mocks.resources.userstories.listInAllProjects + .resolve(Immutable.fromJS([{id: 1, ref: 1, project: "1"}])) - it "project info filled", () -> - duty = { - id: 66 - ref: 123 - project: 1 - } + mocks.resources.tasks.listInAllProjects + .resolve(Immutable.fromJS([{id: 2, ref: 2, project: "1"}])) - mocks.thenStubAssignedToUserstories.callArg(0, Immutable.fromJS([duty])) - mocks.thenStubAssignedToTasks.callArg(0, Immutable.fromJS([])) - mocks.thenStubAssignedToIssues.callArg(0, Immutable.fromJS([])) - mocks.thenStubWatchingUserstories.callArg(0, Immutable.fromJS([])) - mocks.thenStubWatchingTasks.callArg(0, Immutable.fromJS([])) - mocks.thenStubWatchingIssues.callArg(0, Immutable.fromJS([])) - timeout.flush() + mocks.resources.issues.listInAllProjects + .resolve(Immutable.fromJS([{id: 3, ref: 3, project: "1"}])) - projectsById = { - get: () -> Immutable.fromJS({ - name: "Testing project" - slug: "testing-project" + # mock urls + mocks.tgNavUrls.resolve + .withArgs("project-userstories-detail", {project: "project-1", ref: 1}) + .returns("/testing-project/us/1") + + mocks.tgNavUrls.resolve + .withArgs("project-tasks-detail", {project: "project-1", ref: 2}) + .returns("/testing-project/tasks/1") + + mocks.tgNavUrls.resolve + .withArgs("project-issues-detail", {project: "project-1", ref: 3}) + .returns("/testing-project/issues/1") + + homeService.getWorkInProgress(userId) + .then (workInProgress) -> + expect(workInProgress.toJS()).to.be.eql({ + assignedTo: { + userStories: [{ + id: 1, + ref: 1, + project: '1', + url: '/testing-project/us/1', + projectName: 'fake1', + _name: 'userstories' + }] + tasks: [{ + id: 2, + ref: 2, + project: '1', + url: '/testing-project/tasks/1', + projectName: 'fake1', + _name: 'tasks' + }] + issues: [{ + id: 3, + ref: 3, + project: '1', + url: '/testing-project/issues/1', + projectName: 'fake1', + _name: 'issues' + }] + } + watching: { + userStories: [{ + id: 1, + ref: 1, + project: '1', + url: '/testing-project/us/1', + projectName: 'fake1', + _name: 'userstories' + }] + tasks: [{ + id: 2, + ref: 2, + project: '1', + url: '/testing-project/tasks/1', + projectName: 'fake1', + _name: 'tasks' + }] + issues: [{ + id: 3, + ref: 3, + project: '1', + url: '/testing-project/issues/1', + projectName: 'fake1', + _name: 'issues' + }] + } }) - } - mocks.tgNavUrls.resolve - .withArgs("project-userstories-detail", {project: "testing-project", ref: 123}) - .returns("/testing-project/us/123") - - homeService.attachProjectInfoToWorkInProgress(projectsById) - - expect(homeService.workInProgress.toJS()).to.be.eql({ - assignedTo: { - userStories: [ - { - id: 66 - _name: "userstories" - ref: 123 - project: 1 - url: "/testing-project/us/123" - projectName: "Testing project" - } - ] - tasks: [] - issues: [] - } - watching: { - userStories: [] - tasks: [] - issues: [] - } - }) + done() diff --git a/app/modules/home/projects/home-project-list-directive.spec.coffee b/app/modules/home/projects/home-project-list-directive.spec.coffee index 2ad8b7b6..eccd78ec 100644 --- a/app/modules/home/projects/home-project-list-directive.spec.coffee +++ b/app/modules/home/projects/home-project-list-directive.spec.coffee @@ -1,21 +1,31 @@ describe "homeProjectListDirective", () -> scope = compile = provide = null - mockTgProjectsService = null + mocks = {} template = "
" - recents = [] + projects = Immutable.fromJS({ + recents: [ + {id: 1}, + {id: 2}, + {id: 3} + ] + }) createDirective = () -> elm = compile(template)(scope) return elm - _mockTgProjectsService = () -> - mockTgProjectsService = { - newProject: sinon.stub() - currentUserProjects: { - get: sinon.stub() - } + _mockTgCurrentUserService = () -> + mocks.currentUserService = { + projects: projects } - provide.value "tgProjectsService", mockTgProjectsService + + provide.value "tgCurrentUserService", mocks.currentUserService + + _mockTgProjectsService = () -> + mocks.projectsService = { + newProject: sinon.stub() + } + provide.value "tgProjectsService", mocks.projectsService _mockTranslateFilter = () -> mockTranslateFilter = (value) -> @@ -25,6 +35,7 @@ describe "homeProjectListDirective", () -> _mocks = () -> module ($provide) -> provide = $provide + _mockTgCurrentUserService() _mockTgProjectsService() _mockTranslateFilter() return null @@ -49,17 +60,14 @@ describe "homeProjectListDirective", () -> ]) it "home project list directive scope content", () -> - mockTgProjectsService.currentUserProjects.get - .withArgs("recents") - .returns(recents) - elm = createDirective() scope.$apply() - expect(elm.isolateScope().vm.projects.size).to.be.equal(2) + expect(elm.isolateScope().vm.projects.size).to.be.equal(3) it "home project list directive newProject", () -> elm = createDirective() scope.$apply() - expect(mockTgProjectsService.newProject.callCount).to.be.equal(0) + + expect(mocks.projectsService.newProject.callCount).to.be.equal(0) elm.isolateScope().vm.newProject() - expect(mockTgProjectsService.newProject.callCount).to.be.equal(1) + expect(mocks.projectsService.newProject.callCount).to.be.equal(1) diff --git a/app/modules/home/projects/home-project-list.directive.coffee b/app/modules/home/projects/home-project-list.directive.coffee index 17947490..4af582e0 100644 --- a/app/modules/home/projects/home-project-list.directive.coffee +++ b/app/modules/home/projects/home-project-list.directive.coffee @@ -1,8 +1,8 @@ -HomeProjectListDirective = (projectsService) -> +HomeProjectListDirective = (currentUserService, projectsService) -> link = (scope, el, attrs, ctrl) -> scope.vm = {} - taiga.defineImmutableProperty(scope.vm, "projects", () -> projectsService.currentUserProjects.get("recents")) + taiga.defineImmutableProperty(scope.vm, "projects", () -> currentUserService.projects.get("recents")) scope.vm.newProject = -> projectsService.newProject() @@ -15,6 +15,9 @@ HomeProjectListDirective = (projectsService) -> return directive -HomeProjectListDirective.$inject = ["tgProjectsService"] +HomeProjectListDirective.$inject = [ + "tgCurrentUserService", + "tgProjectsService" +] angular.module("taigaHome").directive("tgHomeProjectList", HomeProjectListDirective) diff --git a/app/modules/home/working-on/working-on.controller.coffee b/app/modules/home/working-on/working-on.controller.coffee new file mode 100644 index 00000000..9d101bcf --- /dev/null +++ b/app/modules/home/working-on/working-on.controller.coffee @@ -0,0 +1,29 @@ +class WorkingOnController + @.$inject = [ + "tgHomeService" + ] + + constructor: (@homeService) -> + @.assignedTo = Immutable.Map() + @.watching = Immutable.Map() + + _setAssignedTo: (workInProgress) -> + userStories = workInProgress.get("assignedTo").get("userStories") + tasks = workInProgress.get("assignedTo").get("tasks") + issues = workInProgress.get("assignedTo").get("issues") + + @.assignedTo = userStories.concat(tasks).concat(issues) + + _setWatching: (workInProgress) -> + userStories = workInProgress.get("watching").get("userStories") + tasks = workInProgress.get("watching").get("tasks") + issues = workInProgress.get("watching").get("issues") + + @.watching = userStories.concat(tasks).concat(issues) + + getWorkInProgress: (userId) -> + return @homeService.getWorkInProgress(userId).then (workInProgress) => + @._setAssignedTo(workInProgress) + @._setWatching(workInProgress) + +angular.module("taigaHome").controller("WorkingOn", WorkingOnController) diff --git a/app/modules/home/working-on/working-on.controller.spec.coffee b/app/modules/home/working-on/working-on.controller.spec.coffee new file mode 100644 index 00000000..9a77d8b2 --- /dev/null +++ b/app/modules/home/working-on/working-on.controller.spec.coffee @@ -0,0 +1,59 @@ +describe "WorkingOn", -> + $controller = null + $provide = null + mocks = {} + + _mockHomeService = () -> + mocks.homeService = { + getWorkInProgress: sinon.stub().promise() + } + + $provide.value("tgHomeService", mocks.homeService) + + _mocks = () -> + module (_$provide_) -> + $provide = _$provide_ + + _mockHomeService() + + return null + + _inject = () -> + inject (_$controller_) -> + $controller = _$controller_ + + beforeEach -> + module "taigaHome" + _mocks() + _inject() + + it "get work in progress items", (done) -> + userId = 3 + + workInProgress = Immutable.fromJS({ + assignedTo: { + userStories: [{id: 1}, {id: 2}], + tasks: [{id: 3}, {id: 4}], + issues: [{id: 5}, {id: 6}] + }, + watching: { + userStories: [{id: 7}, {id: 8}], + tasks: [{id: 9}, {id: 10}], + issues: [{id: 11}, {id: 12}] + } + }) + + mocks.homeService.getWorkInProgress.withArgs(userId).resolve(workInProgress) + + ctrl = $controller("WorkingOn") + + ctrl.getWorkInProgress(userId).then () -> + expect(ctrl.assignedTo.toJS()).to.be.eql([ + {id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6} + ]) + + expect(ctrl.watching.toJS()).to.be.eql([ + {id: 7}, {id: 8}, {id: 9}, {id: 10}, {id: 11}, {id: 12} + ]) + + done() diff --git a/app/modules/home/working-on/working-on.directive.coffee b/app/modules/home/working-on/working-on.directive.coffee new file mode 100644 index 00000000..2a806655 --- /dev/null +++ b/app/modules/home/working-on/working-on.directive.coffee @@ -0,0 +1,20 @@ +WorkingOnDirective = (homeService, currentUserService) -> + link = (scope, el, attrs, ctrl) -> + userId = currentUserService.getUser().get("id") + + ctrl.getWorkInProgress(userId) + + return { + controller: "WorkingOn", + controllerAs: "vm", + templateUrl: "home/working-on/working-on.html", + scope: {}, + link: link + } + +WorkingOnDirective.$inject = [ + "tgHomeService", + "tgCurrentUserService" +] + +angular.module("taigaHome").directive("tgWorkingOn", WorkingOnDirective) diff --git a/app/modules/home/working-on/working-on.jade b/app/modules/home/working-on/working-on.jade new file mode 100644 index 00000000..34e287ef --- /dev/null +++ b/app/modules/home/working-on/working-on.jade @@ -0,0 +1,12 @@ +div.title-bar.working-on-title(ng-show="vm.assignedTo.size", translate="HOME.WORKING_ON_SECTION") +section.working-on(ng-show="vm.assignedTo.size") + div.duty-single(tg-duty="duty", tg-repeat="duty in vm.assignedTo", ng-class="{blocked: duty.is_blocked}") + +div.title-bar.watching-title(translate="HOME.WATCHING_SECTION") + +section.watching-empty(ng-show="!vm.watching.size") + include ../../../svg/hide.svg + p(translate="HOME.EMPTY_WATCHING") + +section.watching(ng-show="vm.watching.size") + div.duty-single(tg-duty="duty", tg-repeat="duty in vm.watching", ng-class="{blocked: duty.is_blocked}") \ No newline at end of file diff --git a/app/modules/navigation-bar/dropdown-project-list/dropdown-project-list.directive.coffee b/app/modules/navigation-bar/dropdown-project-list/dropdown-project-list.directive.coffee index be019c11..b125c86c 100644 --- a/app/modules/navigation-bar/dropdown-project-list/dropdown-project-list.directive.coffee +++ b/app/modules/navigation-bar/dropdown-project-list/dropdown-project-list.directive.coffee @@ -1,8 +1,8 @@ -DropdownProjectListDirective = (projectsService) -> +DropdownProjectListDirective = (currentUserService, projectsService) -> link = (scope, el, attrs, ctrl) -> scope.vm = {} - taiga.defineImmutableProperty(scope.vm, "projects", () -> projectsService.currentUserProjects.get("recents")) + taiga.defineImmutableProperty(scope.vm, "projects", () -> currentUserService.projects.get("recents")) scope.vm.newProject = -> projectsService.newProject() @@ -16,6 +16,7 @@ DropdownProjectListDirective = (projectsService) -> return directive DropdownProjectListDirective.$inject = [ + "tgCurrentUserService", "tgProjectsService" ] diff --git a/app/modules/navigation-bar/dropdown-project-list/dropdown-project-list.directive.spec.coffee b/app/modules/navigation-bar/dropdown-project-list/dropdown-project-list.directive.spec.coffee index 46fe9b75..4f144067 100644 --- a/app/modules/navigation-bar/dropdown-project-list/dropdown-project-list.directive.spec.coffee +++ b/app/modules/navigation-bar/dropdown-project-list/dropdown-project-list.directive.spec.coffee @@ -1,32 +1,45 @@ describe "dropdownProjectListDirective", () -> scope = compile = provide = null - mockTgProjectsService = null + mocks = {} template = "
" recents = [] - createDirective = () -> - elm = compile(template)(scope) - return elm - - _mockTgProjectsService = () -> - mockTgProjectsService = { - newProject: sinon.stub() - currentUserProjects: { - get: sinon.stub() - } - } - provide.value "tgProjectsService", mockTgProjectsService + projects = Immutable.fromJS({ + recents: [ + {id: 1}, + {id: 2}, + {id: 3} + ] + }) _mockTranslateFilter = () -> mockTranslateFilter = (value) -> return value provide.value "translateFilter", mockTranslateFilter + createDirective = () -> + elm = compile(template)(scope) + return elm + + _mockTgProjectsService = () -> + mocks.projectsService = { + newProject: sinon.stub() + } + provide.value "tgProjectsService", mocks.projectsService + + _mockTgCurrentUserService = () -> + mocks.currentUserService = { + projects: projects + } + provide.value "tgCurrentUserService", mocks.currentUserService + _mocks = () -> module ($provide) -> provide = $provide _mockTgProjectsService() + _mockTgCurrentUserService() _mockTranslateFilter() + return null beforeEach -> @@ -39,20 +52,7 @@ describe "dropdownProjectListDirective", () -> scope = $rootScope.$new() compile = $compile - recents = Immutable.fromJS([ - { - id:1 - }, - { - id: 2 - } - ]) - it "dropdown project list directive scope content", () -> - mockTgProjectsService.currentUserProjects.get - .withArgs("recents") - .returns(recents) - elm = createDirective() scope.$apply() - expect(elm.isolateScope().vm.projects.size).to.be.equal(2) + expect(elm.isolateScope().vm.projects.size).to.be.equal(3) diff --git a/app/modules/navigation-bar/navigation-bar.directive.coffee b/app/modules/navigation-bar/navigation-bar.directive.coffee index cdda7d28..ba8e0fe6 100644 --- a/app/modules/navigation-bar/navigation-bar.directive.coffee +++ b/app/modules/navigation-bar/navigation-bar.directive.coffee @@ -1,8 +1,8 @@ -NavigationBarDirective = (projectsService) -> +NavigationBarDirective = (currentUserService) -> link = (scope, el, attrs, ctrl) -> scope.vm = {} - taiga.defineImmutableProperty(scope.vm, "projects", () -> projectsService.currentUserProjects.get("recents")) + taiga.defineImmutableProperty(scope.vm, "projects", () -> currentUserService.projects.get("recents")) directive = { templateUrl: "navigation-bar/navigation-bar.html" @@ -13,7 +13,7 @@ NavigationBarDirective = (projectsService) -> return directive NavigationBarDirective.$inject = [ - "tgProjectsService" + "tgCurrentUserService" ] angular.module("taigaNavigationBar").directive("tgNavigationBar", NavigationBarDirective) diff --git a/app/modules/navigation-bar/navigation-bar.directive.spec.coffee b/app/modules/navigation-bar/navigation-bar.directive.spec.coffee index 31f2b13e..62d9aa42 100644 --- a/app/modules/navigation-bar/navigation-bar.directive.spec.coffee +++ b/app/modules/navigation-bar/navigation-bar.directive.spec.coffee @@ -1,21 +1,26 @@ describe "navigationBarDirective", () -> scope = compile = provide = null - mockTgProjectsService = null + mocks = {} template = "
" - recents = [] + projects = Immutable.fromJS({ + recents: [ + {id: 1}, + {id: 2}, + {id: 3} + ] + }) createDirective = () -> elm = compile(template)(scope) return elm - _mockTgProjectsService = () -> - mockTgProjectsService = { - newProject: sinon.stub() - currentUserProjects: { - get: sinon.stub() - } + _mocksCurrentUserService = () -> + mocks.currentUserService = { + projects: projects } - provide.value "tgProjectsService", mockTgProjectsService + + provide.value "tgCurrentUserService", mocks.currentUserService + _mockTranslateFilter = () -> mockTranslateFilter = (value) -> @@ -31,7 +36,8 @@ describe "navigationBarDirective", () -> _mocks = () -> module ($provide) -> provide = $provide - _mockTgProjectsService() + + _mocksCurrentUserService() _mockTranslateFilter() _mockTgDropdownProjectListDirective() _mockTgDropdownUserDirective() @@ -57,10 +63,6 @@ describe "navigationBarDirective", () -> ]) it "navigation bar directive scope content", () -> - mockTgProjectsService.currentUserProjects.get - .withArgs("recents") - .returns(recents) - elm = createDirective() scope.$apply() - expect(elm.isolateScope().vm.projects.size).to.be.equal(2) + expect(elm.isolateScope().vm.projects.size).to.be.equal(3) diff --git a/app/modules/projects/listing/projects-listing.controller.coffee b/app/modules/projects/listing/projects-listing.controller.coffee index 3206782c..d815fa5c 100644 --- a/app/modules/projects/listing/projects-listing.controller.coffee +++ b/app/modules/projects/listing/projects-listing.controller.coffee @@ -1,10 +1,11 @@ class ProjectsListingController @.$inject = [ - "tgProjectsService" + "tgCurrentUserService", + "tgProjectsService", ] - constructor: (@projectsService) -> - taiga.defineImmutableProperty(@, "projects", () => @projectsService.currentUserProjects.get("all")) + constructor: (@currentUserService, @projectsService) -> + taiga.defineImmutableProperty(@, "projects", () => @currentUserService.projects.get("all")) newProject: -> @projectsService.newProject() diff --git a/app/modules/projects/listing/projects-listing.controller.spec.coffee b/app/modules/projects/listing/projects-listing.controller.spec.coffee index a976da33..58b61c79 100644 --- a/app/modules/projects/listing/projects-listing.controller.spec.coffee +++ b/app/modules/projects/listing/projects-listing.controller.spec.coffee @@ -4,30 +4,37 @@ describe "ProjectsListingController", -> controller = null mocks = {} - projects = Immutable.fromJS([ - {id: 1}, - {id: 2}, - {id: 3} - ]) + projects = Immutable.fromJS({ + all: [ + {id: 1}, + {id: 2}, + {id: 3} + ] + }) + + _mockCurrentUserService = () -> + stub = sinon.stub() + + mocks.currentUserService = { + projects: projects + } + + provide.value "tgCurrentUserService", mocks.currentUserService _mockProjectsService = () -> stub = sinon.stub() mocks.projectsService = { - currentUserProjects: { - get: stub - }, newProject: sinon.stub() } - stub.withArgs("all").returns(projects) - provide.value "tgProjectsService", mocks.projectsService _mocks = () -> module ($provide) -> provide = $provide _mockProjectsService() + _mockCurrentUserService() return null @@ -43,7 +50,7 @@ describe "ProjectsListingController", -> pageCtrl = controller "ProjectsListing", $scope: {} - expect(pageCtrl.projects).to.be.equal(projects) + expect(pageCtrl.projects).to.be.equal(projects.get('all')) it "new project", () -> pageCtrl = controller "ProjectsListing", diff --git a/app/modules/projects/projects.service.coffee b/app/modules/projects/projects.service.coffee index 996944dd..22cd4cc2 100644 --- a/app/modules/projects/projects.service.coffee +++ b/app/modules/projects/projects.service.coffee @@ -2,21 +2,9 @@ taiga = @.taiga groupBy = @.taiga.groupBy class ProjectsService extends taiga.Service - @.$inject = ["tgResources", "$tgAuth", "$projectUrl", "tgLightboxFactory"] + @.$inject = ["tgResources", "$projectUrl", "tgLightboxFactory"] - constructor: (@rs, @auth, @projectUrl, @lightboxFactory) -> - @._currentUserProjects = Immutable.Map() - @._currentUserProjectsById = Immutable.Map() - @._inProgress = false - @._currentUserProjectsPromise = null - - taiga.defineImmutableProperty @, "currentUserProjects", () => return @._currentUserProjects - taiga.defineImmutableProperty @, "currentUserProjectsById", () => return @._currentUserProjectsById - - @.fetchProjects() - - getCurrentUserProjects: -> - return @._currentUserProjectsPromise + constructor: (@rs, @projectUrl, @lightboxFactory) -> getProjectBySlug: (projectSlug) -> return @rs.projects.getProjectBySlug(projectSlug) @@ -47,24 +35,6 @@ class ProjectsService extends taiga.Service return project - fetchProjects: -> - if not @._inProgress - @._inProgress = true - - @._currentUserProjectsPromise = @.getProjectsByUserId(@auth.userData.get("id")) - @._currentUserProjectsPromise.then (projects) => - @._currentUserProjects = @._currentUserProjects.set("all", projects) - @._currentUserProjects = @._currentUserProjects.set("recents", projects.slice(0, 10)) - - @._currentUserProjectsById = Immutable.fromJS(groupBy(projects.toJS(), (p) -> p.id)) - - return @.projects - - @._currentUserProjectsPromise.finally => - @._inProgress = false - - return @._currentUserProjectsPromise - newProject: -> @lightboxFactory.create("tg-lb-create-project", { "class": "wizard-create-project" @@ -74,5 +44,4 @@ class ProjectsService extends taiga.Service @rs.projects.bulkUpdateOrder(sortData).then => @.fetchProjects() -angular.module("taigaProjects").service("tgProjectsService -", ProjectsService) +angular.module("taigaProjects").service("tgProjectsService", ProjectsService) diff --git a/app/modules/projects/projects.service.spec.coffee b/app/modules/projects/projects.service.spec.coffee index e57fc68b..e861574a 100644 --- a/app/modules/projects/projects.service.spec.coffee +++ b/app/modules/projects/projects.service.spec.coffee @@ -35,13 +35,9 @@ describe "tgProjects", -> provide.value "tgLightboxFactory", mocks.lightboxFactory _inject = (callback) -> - inject (_$q_, _$rootScope_) -> + inject (_$q_, _$rootScope_, _tgProjectsService_) -> $q = _$q_ $rootScope = _$rootScope_ - callback() if callback - - _injectService = (callback) -> - inject (_tgProjectsService_) -> projectsService = _tgProjectsService_ callback() if callback @@ -60,75 +56,7 @@ describe "tgProjects", -> _mocks() _inject() - describe "fetch items", -> - projects = [] - - beforeEach -> - projects = [ - {"id": 1, url: 'url-1', tags: ['xx', 'yy', 'aa'], tags_colors: {xx: "red", yy: "blue", aa: "white"}, colorized_tags: [{name: 'aa', color: 'white'}, {name: 'xx', color: 'red'}, {name: 'yy', color: 'blue'}]}, - {"id": 2, url: 'url-2'}, - {"id": 3, url: 'url-3'}, - {"id": 4, url: 'url-4'}, - {"id": 5, url: 'url-5'}, - {"id": 6, url: 'url-6'}, - {"id": 7, url: 'url-7'}, - {"id": 8, url: 'url-8'}, - {"id": 9, url: 'url-9'}, - {"id": 10, url: 'url-10'}, - {"id": 11, url: 'url-11'}, - {"id": 12, url: 'url-12'} - ] - - mocks.resources.projects.getProjectsByUserId = () -> - return $q (resolve) -> - resolve(Immutable.fromJS(projects)) - - _injectService() - - it "all & recents filled", () -> - projectsService.fetchProjects() - $rootScope.$digest() - - expect(projectsService.currentUserProjects.get("all").toJS()).to.be.eql(projects) - expect(projectsService.currentUserProjects.get("recents").toJS()).to.be.eql(projects.slice(0, 10)) - - it "_inProgress change to false when tgResources end", () -> - expect(projectsService._inProgress).to.be.true - - $rootScope.$digest() - - expect(projectsService._inProgress).to.be.false - - it "group projects by id", () -> - $rootScope.$digest() - - expect(projectsService.currentUserProjectsById.size).to.be.equal(12) - expect(projectsService.currentUserProjectsById.toJS()[1].id).to.be.equal(projects[0].id) - - it "add urls in the project object", () -> - $rootScope.$digest() - - expect(projectsService.currentUserProjectsById.toJS()[1].url).to.be.equal("url-1") - expect(projectsService.currentUserProjects.get("all").toJS()[0].url).to.be.equal("url-1") - expect(projectsService.currentUserProjects.get("recents").toJS()[0].url).to.be.equal("url-1") - - it "add sorted colorized_tags project object", () -> - $rootScope.$digest() - - tags = [ - {name: "aa", color: "white"}, - {name: "xx", color: "red"}, - {name: "yy", color: "blue"} - ]; - - - colorized_tags = projectsService.currentUserProjects.get("all").toJS()[0].colorized_tags - - expect(colorized_tags).to.be.eql(tags) - it "newProject, create the wizard lightbox", () -> - _injectService() - projectsService.newProject() expect(mocks.lightboxFactory.create).to.have.been.calledWith("tg-lb-create-project", { @@ -136,8 +64,6 @@ describe "tgProjects", -> }) it "bulkUpdateProjectsOrder and then fetch projects again", () -> - _injectService() - projects_order = [ {"id": 8}, {"id": 2}, @@ -170,8 +96,6 @@ describe "tgProjects", -> expect(projectsService.fetchProjects).to.have.been.calledOnce it "getProjectBySlug", () -> - _injectService() - projectSlug = "project-slug" mocks.resources.projects = {} @@ -181,8 +105,6 @@ describe "tgProjects", -> expect(projectsService.getProjectBySlug(projectSlug)).to.be.true it "getProjectStats", () -> - _injectService() - projectId = 3 mocks.resources.projects = {} @@ -190,3 +112,31 @@ describe "tgProjects", -> mocks.resources.projects.getProjectStats.withArgs(projectId).returns(true) expect(projectsService.getProjectStats(projectId)).to.be.true + + it "getProjectsByUserId", (done) -> + projectId = 3 + + projects = Immutable.fromJS([ + {id: 1, url: 'url-1'}, + {id: 2, url: 'url-2', tags: ['xx', 'yy', 'aa'], tags_colors: {xx: "red", yy: "blue", aa: "white"}} + ]) + + mocks.resources.projects = {} + mocks.resources.projects.getProjectsByUserId = sinon.stub().promise() + mocks.resources.projects.getProjectsByUserId.withArgs(projectId).resolve(projects) + + projectsService.getProjectsByUserId(projectId).then (projects) -> + expect(projects.toJS()).to.be.eql([{ + id: 1, + url: 'url-1' + }, + { + id: 2, + url: 'url-2', + tags: ['xx', 'yy', 'aa'], + tags_colors: {xx: "red", yy: "blue", aa: "white"}, + colorized_tags: [{name: 'aa', color: 'white'}, {name: 'xx', color: 'red'}, {name: 'yy', color: 'blue'}] + } + ]) + + done() diff --git a/app/modules/services/current-user.service.coffee b/app/modules/services/current-user.service.coffee new file mode 100644 index 00000000..a25110db --- /dev/null +++ b/app/modules/services/current-user.service.coffee @@ -0,0 +1,45 @@ +taiga = @.taiga + +groupBy = @.taiga.groupBy + +class CurrentUserService + @.$inject = [ + "tgProjectsService", + "$tgStorage" + ] + + constructor: (@projectsService, @storageService) -> + @._user = Immutable.Map() + @._projects = Immutable.Map() + @._projectsById = Immutable.Map() + + taiga.defineImmutableProperty @, "projects", () => return @._projects + taiga.defineImmutableProperty @, "projectsById", () => return @._projectsById + + getUser: () -> + if !@._user.size + userData = @storageService.get("userInfo") + userData = Immutable.fromJS(userData) + @.setUser(userData) if userData + + return @._user + + setUser: (user) -> + @._user = user + + return @._loadUserInfo() + + _loadProjects: () -> + return @projectsService.getProjectsByUserId(@._user.get("id")) + .then (projects) => + @._projects = @._projects.set("all", projects) + @._projects = @._projects.set("recents", projects.slice(0, 10)) + + @._projectsById = Immutable.fromJS(groupBy(projects.toJS(), (p) -> p.id)) + + return @.projects + + _loadUserInfo: () -> + return @._loadProjects() + +angular.module("taigaCommon").service("tgCurrentUserService", CurrentUserService) diff --git a/app/modules/services/current-user.service.spec.coffee b/app/modules/services/current-user.service.spec.coffee new file mode 100644 index 00000000..a5fb23b4 --- /dev/null +++ b/app/modules/services/current-user.service.spec.coffee @@ -0,0 +1,77 @@ +describe "tgCurrentUserService", -> + currentUserService = provide = null + mocks = {} + + _mockTgStorage = () -> + mocks.storageService = { + get: sinon.stub() + } + + provide.value "$tgStorage", mocks.storageService + + _mockProjectsService = () -> + mocks.projectsService = { + getProjectsByUserId: sinon.stub().promise() + } + + provide.value "tgProjectsService", mocks.projectsService + + _inject = (callback) -> + inject (_tgCurrentUserService_) -> + currentUserService = _tgCurrentUserService_ + callback() if callback + + _mocks = () -> + module ($provide) -> + provide = $provide + _mockTgStorage() + _mockProjectsService() + + return null + + _setup = -> + _mocks() + + beforeEach -> + module "taigaCommon" + _setup() + _inject() + + describe "get user", () -> + it "return the user if it is defined", () -> + currentUserService._user = 123 + + expect(currentUserService.getUser()).to.be.equal(123) + + it "get user form storage if it is not defined", () -> + user = {id: 1, name: "fake1"} + + currentUserService.setUser = sinon.spy() + mocks.storageService.get.withArgs("userInfo").returns(user) + + _user = currentUserService.getUser() + + expect(currentUserService.setUser).to.be.calledOnce + + it "set user and load user info", (done) -> + user = Immutable.fromJS({id: 1, name: "fake1"}) + + projects = Immutable.fromJS([ + {id: 1, name: "fake1"}, + {id: 2, name: "fake2"}, + {id: 3, name: "fake3"}, + {id: 4, name: "fake4"}, + {id: 5, name: "fake5"} + ]) + + mocks.projectsService.getProjectsByUserId = sinon.stub().promise() + mocks.projectsService.getProjectsByUserId.withArgs(user.get("id")).resolve(projects) + + currentUserService.setUser(user).then () -> + expect(currentUserService._user).to.be.equal(user) + expect(currentUserService.projects.get("all").size).to.be.equal(5) + expect(currentUserService.projects.get("recents").size).to.be.equal(5) + expect(currentUserService.projectsById.size).to.be.equal(5) + expect(currentUserService.projectsById.get("3").get("name")).to.be.equal("fake3") + + done() diff --git a/bower.json b/bower.json index 7989c254..c16cfedc 100644 --- a/bower.json +++ b/bower.json @@ -79,7 +79,8 @@ "angular-translate-interpolation-messageformat": "~2.6.1", "ngInfiniteScroll": "1.0.0", "eventemitter2": "~0.4.14", - "immutable": "~3.7.2" + "immutable": "~3.7.2", + "bluebird": "~2.9.25" }, "resolutions": { "lodash": "~2.4.1", diff --git a/gulpfile.js b/gulpfile.js index b1017fb8..bb22d5d7 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -116,6 +116,7 @@ paths.coffee_order = [ ]; paths.libs = [ + paths.vendor + "bluebird/js/browser/bluebird.js", paths.vendor + "jquery/dist/jquery.js", paths.vendor + "lodash/dist/lodash.js", paths.vendor + "emoticons/lib/emoticons.js", diff --git a/karma.conf.js b/karma.conf.js index ae7b045e..209da9ec 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -18,7 +18,7 @@ module.exports = function(config) { 'karma.app.conf.js', 'dist/js/libs.js', 'node_modules/angular-mocks/angular-mocks.js', - 'node_modules/bluebird/js/browser/bluebird.js', + 'vendor/bluebird/js/browser/bluebird.js', 'test-utils.js', 'dist/js/app.js', 'dist/js/templates.js', diff --git a/package.json b/package.json index 46b73b46..ad9f67d3 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,6 @@ }, "devDependencies": { "angular-mocks": "^1.3.15", - "bluebird": "^2.9.21", "chai": "^2.2.0", "cli-color": "^0.3.3", "coffee-script": "^1.9.1",