new resources return immutable objects
parent
0b5d09ca0c
commit
042d73b771
|
@ -66,7 +66,17 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
|
||||||
)
|
)
|
||||||
|
|
||||||
$routeProvider.when("/project/:pslug/",
|
$routeProvider.when("/project/:pslug/",
|
||||||
{templateUrl: "project/project.html"})
|
{
|
||||||
|
templateUrl: "projects/project/project-page.html",
|
||||||
|
resolve: {
|
||||||
|
loader: tgLoaderProvider.add(true),
|
||||||
|
pageParams: -> {
|
||||||
|
"authRequired": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
controller: "Page"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
$routeProvider.when("/project/:pslug/search",
|
$routeProvider.when("/project/:pslug/search",
|
||||||
{templateUrl: "search/search.html", reloadOnSearch: false})
|
{templateUrl: "search/search.html", reloadOnSearch: false})
|
||||||
|
|
|
@ -13,6 +13,16 @@
|
||||||
if (immutable_collection.toJS) {
|
if (immutable_collection.toJS) {
|
||||||
collection = immutable_collection.toJS();
|
collection = immutable_collection.toJS();
|
||||||
}
|
}
|
||||||
|
$scope[aliasAs] = collection; -> $scope[aliasAs] = immutable_collection;
|
||||||
|
|
||||||
|
value = collection[key];
|
||||||
|
immutable_value = immutable_collection.get(key); #x2
|
||||||
|
|
||||||
|
|
||||||
|
updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
|
||||||
|
-> (x2)
|
||||||
|
updateScope(block.scope, index, valueIdentifier, immutable_value, keyIdentifier, key, collectionLength);
|
||||||
|
|
||||||
--copy from angular
|
--copy from angular
|
||||||
copy angular hashKey
|
copy angular hashKey
|
||||||
copy angular createMap
|
copy angular createMap
|
||||||
|
@ -205,7 +215,7 @@
|
||||||
nextBlockOrder,
|
nextBlockOrder,
|
||||||
elementsToRemove;
|
elementsToRemove;
|
||||||
if (aliasAs) {
|
if (aliasAs) {
|
||||||
$scope[aliasAs] = collection;
|
$scope[aliasAs] = immutable_collection;
|
||||||
}
|
}
|
||||||
if (isArrayLike(collection)) {
|
if (isArrayLike(collection)) {
|
||||||
collectionKeys = collection;
|
collectionKeys = collection;
|
||||||
|
@ -226,6 +236,7 @@
|
||||||
for (index = 0; index < collectionLength; index++) {
|
for (index = 0; index < collectionLength; index++) {
|
||||||
key = (collection === collectionKeys) ? index : collectionKeys[index];
|
key = (collection === collectionKeys) ? index : collectionKeys[index];
|
||||||
value = collection[key];
|
value = collection[key];
|
||||||
|
immutable_value = immutable_collection.get(key);
|
||||||
trackById = trackByIdFn(key, value, index);
|
trackById = trackByIdFn(key, value, index);
|
||||||
if (lastBlockMap[trackById]) {
|
if (lastBlockMap[trackById]) {
|
||||||
// found previously seen block
|
// found previously seen block
|
||||||
|
@ -265,6 +276,7 @@
|
||||||
for (index = 0; index < collectionLength; index++) {
|
for (index = 0; index < collectionLength; index++) {
|
||||||
key = (collection === collectionKeys) ? index : collectionKeys[index];
|
key = (collection === collectionKeys) ? index : collectionKeys[index];
|
||||||
value = collection[key];
|
value = collection[key];
|
||||||
|
immutable_value = immutable_collection.get(key);
|
||||||
block = nextBlockOrder[index];
|
block = nextBlockOrder[index];
|
||||||
if (block.scope) {
|
if (block.scope) {
|
||||||
// if we have already seen this object, then we need to reuse the
|
// if we have already seen this object, then we need to reuse the
|
||||||
|
@ -279,7 +291,7 @@
|
||||||
$animate.move(getBlockNodes(block.clone), null, jqLite(previousNode));
|
$animate.move(getBlockNodes(block.clone), null, jqLite(previousNode));
|
||||||
}
|
}
|
||||||
previousNode = getBlockEnd(block);
|
previousNode = getBlockEnd(block);
|
||||||
updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
|
updateScope(block.scope, index, valueIdentifier, immutable_value, keyIdentifier, key, collectionLength);
|
||||||
} else {
|
} else {
|
||||||
// new item which we don't know about
|
// new item which we don't know about
|
||||||
$transclude(function ngRepeatTransclude(clone, scope) {
|
$transclude(function ngRepeatTransclude(clone, scope) {
|
||||||
|
@ -295,7 +307,7 @@
|
||||||
// by a directive with templateUrl when its template arrives.
|
// by a directive with templateUrl when its template arrives.
|
||||||
block.clone = clone;
|
block.clone = clone;
|
||||||
nextBlockMap[block.id] = block;
|
nextBlockMap[block.id] = block;
|
||||||
updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
|
updateScope(block.scope, index, valueIdentifier, immutable_value, keyIdentifier, key, collectionLength);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
DutyDirective = (navurls, projectsService, $translate) ->
|
DutyDirective = (navurls, $translate) ->
|
||||||
link = (scope, el, attrs, ctrl) ->
|
link = (scope, el, attrs, ctrl) ->
|
||||||
scope.vm = {}
|
scope.vm = {}
|
||||||
scope.vm.duty = scope.duty
|
scope.vm.duty = scope.duty
|
||||||
|
|
||||||
scope.vm.getDutyType = () ->
|
scope.vm.getDutyType = () ->
|
||||||
if scope.vm.duty
|
if scope.vm.duty
|
||||||
if scope.vm.duty._name == "userstories"
|
if scope.vm.duty.get('_name') == "userstories"
|
||||||
return $translate.instant("COMMON.USER_STORY")
|
return $translate.instant("COMMON.USER_STORY")
|
||||||
if scope.vm.duty._name == "tasks"
|
if scope.vm.duty.get('_name') == "tasks"
|
||||||
return $translate.instant("COMMON.TASK")
|
return $translate.instant("COMMON.TASK")
|
||||||
if scope.vm.duty._name == "issues"
|
if scope.vm.duty.get('_name') == "issues"
|
||||||
return $translate.instant("COMMON.ISSUE")
|
return $translate.instant("COMMON.ISSUE")
|
||||||
|
|
||||||
directive = {
|
return {
|
||||||
templateUrl: "home/duties/duty.html"
|
templateUrl: "home/duties/duty.html"
|
||||||
scope: {
|
scope: {
|
||||||
"duty": "=tgDuty"
|
"duty": "=tgDuty"
|
||||||
|
@ -20,11 +20,8 @@ DutyDirective = (navurls, projectsService, $translate) ->
|
||||||
link: link
|
link: link
|
||||||
}
|
}
|
||||||
|
|
||||||
return directive
|
|
||||||
|
|
||||||
DutyDirective.$inject = [
|
DutyDirective.$inject = [
|
||||||
"$tgNavUrls",
|
"$tgNavUrls",
|
||||||
"tgProjectsService",
|
|
||||||
"$translate"
|
"$translate"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ describe "dutyDirective", () ->
|
||||||
compile = $compile
|
compile = $compile
|
||||||
|
|
||||||
it "duty directive scope content", () ->
|
it "duty directive scope content", () ->
|
||||||
scope.duty = {
|
scope.duty = Immutable.fromJS({
|
||||||
project: 1
|
project: 1
|
||||||
ref: 1
|
ref: 1
|
||||||
_name: "userstories"
|
_name: "userstories"
|
||||||
|
@ -56,7 +56,7 @@ describe "dutyDirective", () ->
|
||||||
photo: "http://jstesting.taiga.io/photo"
|
photo: "http://jstesting.taiga.io/photo"
|
||||||
full_name_display: "Taiga testing js"
|
full_name_display: "Taiga testing js"
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
mockTgProjectsService.projectsById.get
|
mockTgProjectsService.projectsById.get
|
||||||
.withArgs("1")
|
.withArgs("1")
|
||||||
|
@ -72,4 +72,5 @@ describe "dutyDirective", () ->
|
||||||
|
|
||||||
elm = createDirective()
|
elm = createDirective()
|
||||||
scope.$apply()
|
scope.$apply()
|
||||||
|
|
||||||
expect(elm.isolateScope().vm.getDutyType()).to.be.equal("User story translated")
|
expect(elm.isolateScope().vm.getDutyType()).to.be.equal("User story translated")
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
a(href="{{ ::vm.duty.url }}", title="{{ ::duty.subject }}")
|
a(href="{{ ::vm.duty.get('url') }}", title="{{ ::duty.get('subject') }}")
|
||||||
img.avatar(
|
img.avatar(
|
||||||
src="{{ ::vm.duty.assigned_to_extra_info.photo }}"
|
src="{{ ::vm.duty.get('assigned_to_extra_info').get('photo') }}"
|
||||||
title="{{ ::vm.duty.assigned_to_extra_info.full_name_display }}")
|
title="{{ ::vm.duty.get('assigned_to_extra_info').get('full_name_display') }}")
|
||||||
|
|
||||||
div.duty-data
|
div.duty-data
|
||||||
div
|
div
|
||||||
span.duty-type {{ ::vm.getDutyType() }}
|
span.duty-type {{ ::vm.getDutyType() }}
|
||||||
span.duty-status(ng-style="{'color': vm.duty.status_extra_info.color}") {{ ::vm.duty.status_extra_info.name }}
|
span.duty-status(ng-style="{'color': vm.duty.get('status_extra_info').get('color')}") {{ ::vm.duty.get('status_extra_info').get('name') }}
|
||||||
span.duty-title
|
span.duty-title
|
||||||
span.duty-id(tg-bo-ref="duty.ref")
|
span.duty-id(tg-bo-ref="duty.get('ref')")
|
||||||
span.duty-name {{ ::duty.subject }}
|
span.duty-name {{ ::duty.get('subject') }}
|
||||||
div.duty-project {{ ::vm.duty.projectName}}
|
div.duty-project {{ ::vm.duty.get('projectName')}}
|
||||||
|
|
|
@ -13,7 +13,7 @@ div.home-wrapper.centered
|
||||||
include ../../svg/hide.svg
|
include ../../svg/hide.svg
|
||||||
p(translate="HOME.EMPTY_WATCHING")
|
p(translate="HOME.EMPTY_WATCHING")
|
||||||
|
|
||||||
section.watching(ng-show="vm.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.duty-single(tg-duty="duty", tg-repeat="duty in vm.watching", ng-class="{blocked: duty.is_blocked}")
|
||||||
|
|
||||||
aside.project-list(tg-home-project-list)
|
aside.project-list(tg-home-project-list)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
class HomeService extends taiga.Service
|
class HomeService extends taiga.Service
|
||||||
@.$inject = ["$q", "$tgNavUrls", "$tgResources", "$rootScope", "$projectUrl", "$tgAuth"]
|
@.$inject = ["$q", "$tgNavUrls", "tgResources", "$rootScope", "$projectUrl", "$tgAuth"]
|
||||||
|
|
||||||
constructor: (@q, @navurls, @rs, @rootScope, @projectUrl, @auth) ->
|
constructor: (@q, @navurls, @rs, @rootScope, @projectUrl, @auth) ->
|
||||||
@._workInProgress = Immutable.Map()
|
@._workInProgress = Immutable.Map()
|
||||||
|
@ -11,27 +11,64 @@ class HomeService extends taiga.Service
|
||||||
@.fetchWorkInProgress()
|
@.fetchWorkInProgress()
|
||||||
|
|
||||||
attachProjectInfoToWorkInProgress: (projectsById) ->
|
attachProjectInfoToWorkInProgress: (projectsById) ->
|
||||||
_attachProjectInfoToDuty = (duty) =>
|
_attachProjectInfoToDuty = (duty, objType) =>
|
||||||
project = projectsById.get(String(duty.project))
|
project = projectsById.get(String(duty.get('project')))
|
||||||
ctx = {
|
ctx = {
|
||||||
project: project.slug
|
project: project.get('slug')
|
||||||
ref: duty.ref
|
ref: duty.get('ref')
|
||||||
}
|
}
|
||||||
duty.url = @navurls.resolve("project-#{duty._name}-detail", ctx)
|
|
||||||
duty.projectName = project.name
|
url = @navurls.resolve("project-#{objType}-detail", ctx)
|
||||||
|
|
||||||
|
duty = duty.set('url', url)
|
||||||
|
duty = duty.set('projectName', project.get('name'))
|
||||||
|
duty = duty.set("_name", objType)
|
||||||
|
|
||||||
return duty
|
return duty
|
||||||
|
|
||||||
@._workInProgress = Immutable.fromJS({
|
assignedTo = Immutable.Map()
|
||||||
assignedTo: {
|
|
||||||
userStories: _.map(_.clone(@.assignedToUserStories), _attachProjectInfoToDuty)
|
if @.assignedToUserStories
|
||||||
tasks: _.map(_.clone(@.assignedToTasks), _attachProjectInfoToDuty)
|
_duties = @.assignedToUserStories.map (duty) ->
|
||||||
issues: _.map(_.clone(@.assignedToIssues), _attachProjectInfoToDuty)
|
return _attachProjectInfoToDuty(duty, "userstories")
|
||||||
}
|
|
||||||
watching: {
|
assignedTo = assignedTo.set("userStories", _duties)
|
||||||
userStories: _.map(_.clone(@.watchingUserStories), _attachProjectInfoToDuty)
|
|
||||||
tasks: _.map(_.clone(@.watchingTasks), _attachProjectInfoToDuty)
|
if @.assignedToTasks
|
||||||
issues: _.map(_.clone(@.watchingIssues), _attachProjectInfoToDuty)
|
_duties = @.assignedToTasks.map (duty) ->
|
||||||
}
|
return _attachProjectInfoToDuty(duty, "tasks")
|
||||||
|
|
||||||
|
assignedTo = assignedTo.set("tasks", _duties)
|
||||||
|
|
||||||
|
if @.assignedToIssues
|
||||||
|
_duties = @.assignedToIssues.map (duty) ->
|
||||||
|
return _attachProjectInfoToDuty(duty, "issues")
|
||||||
|
|
||||||
|
assignedTo = assignedTo.set("issues", _duties)
|
||||||
|
|
||||||
|
watching = Immutable.Map()
|
||||||
|
|
||||||
|
if @.watchingUserStories
|
||||||
|
_duties = @.watchingUserStories.map (duty) ->
|
||||||
|
return _attachProjectInfoToDuty(duty, "userstories")
|
||||||
|
|
||||||
|
watching = watching.set("userStories", _duties)
|
||||||
|
|
||||||
|
if @.watchingTasks
|
||||||
|
_duties = @.watchingTasks.map (duty) ->
|
||||||
|
return _attachProjectInfoToDuty(duty, "tasks")
|
||||||
|
|
||||||
|
watching = watching.set("tasks", _duties)
|
||||||
|
|
||||||
|
if @.watchingIssues
|
||||||
|
_duties = @.watchingIssues.map (duty) ->
|
||||||
|
return _attachProjectInfoToDuty(duty, "issues")
|
||||||
|
|
||||||
|
watching = watching.set("issues", _duties)
|
||||||
|
|
||||||
|
@._workInProgress = Immutable.Map({
|
||||||
|
assignedTo: assignedTo,
|
||||||
|
watching: watching
|
||||||
})
|
})
|
||||||
|
|
||||||
getWorkInProgress: () ->
|
getWorkInProgress: () ->
|
||||||
|
|
|
@ -58,7 +58,7 @@ describe "tgHome", ->
|
||||||
then: mocks.thenStubWatchingIssues
|
then: mocks.thenStubWatchingIssues
|
||||||
})
|
})
|
||||||
|
|
||||||
provide.value "$tgResources", mocks.resources
|
provide.value "tgResources", mocks.resources
|
||||||
|
|
||||||
_mockProjectUrl = () ->
|
_mockProjectUrl = () ->
|
||||||
mocks.projectUrl = {get: sinon.stub()}
|
mocks.projectUrl = {get: sinon.stub()}
|
||||||
|
@ -83,7 +83,7 @@ describe "tgHome", ->
|
||||||
provide.value "$tgNavUrls", mocks.tgNavUrls
|
provide.value "$tgNavUrls", mocks.tgNavUrls
|
||||||
|
|
||||||
_inject = (callback) ->
|
_inject = (callback) ->
|
||||||
inject (_$q_, _$tgResources_, _$rootScope_, _$projectUrl_, _$timeout_, _tgHomeService_) ->
|
inject (_$timeout_, _tgHomeService_) ->
|
||||||
timeout = _$timeout_
|
timeout = _$timeout_
|
||||||
homeService = _tgHomeService_
|
homeService = _tgHomeService_
|
||||||
callback() if callback
|
callback() if callback
|
||||||
|
@ -107,12 +107,12 @@ describe "tgHome", ->
|
||||||
|
|
||||||
describe "fetch items", ->
|
describe "fetch items", ->
|
||||||
it "work in progress filled", () ->
|
it "work in progress filled", () ->
|
||||||
mocks.thenStubAssignedToUserstories.callArg(0, [{"id": 1}])
|
mocks.thenStubAssignedToUserstories.callArg(0, Immutable.fromJS([{"id": 1}]))
|
||||||
mocks.thenStubAssignedToTasks.callArg(0, [{"id": 2}])
|
mocks.thenStubAssignedToTasks.callArg(0, Immutable.fromJS([{"id": 2}]))
|
||||||
mocks.thenStubAssignedToIssues.callArg(0, [{"id": 3}])
|
mocks.thenStubAssignedToIssues.callArg(0, Immutable.fromJS([{"id": 3}]))
|
||||||
mocks.thenStubWatchingUserstories.callArg(0, [{"id": 4}])
|
mocks.thenStubWatchingUserstories.callArg(0, Immutable.fromJS([{"id": 4}]))
|
||||||
mocks.thenStubWatchingTasks.callArg(0, [{"id": 5}])
|
mocks.thenStubWatchingTasks.callArg(0, Immutable.fromJS([{"id": 5}]))
|
||||||
mocks.thenStubWatchingIssues.callArg(0, [{"id": 6}])
|
mocks.thenStubWatchingIssues.callArg(0, Immutable.fromJS([{"id": 6}]))
|
||||||
|
|
||||||
timeout.flush()
|
timeout.flush()
|
||||||
expect(homeService.workInProgress.toJS()).to.be.eql({
|
expect(homeService.workInProgress.toJS()).to.be.eql({
|
||||||
|
@ -136,23 +136,23 @@ describe "tgHome", ->
|
||||||
it "project info filled", () ->
|
it "project info filled", () ->
|
||||||
duty = {
|
duty = {
|
||||||
id: 66
|
id: 66
|
||||||
_name: "userstories"
|
|
||||||
ref: 123
|
ref: 123
|
||||||
project: 1
|
project: 1
|
||||||
}
|
}
|
||||||
mocks.thenStubAssignedToUserstories.callArg(0, [duty])
|
|
||||||
mocks.thenStubAssignedToTasks.callArg(0)
|
mocks.thenStubAssignedToUserstories.callArg(0, Immutable.fromJS([duty]))
|
||||||
mocks.thenStubAssignedToIssues.callArg(0)
|
mocks.thenStubAssignedToTasks.callArg(0, Immutable.fromJS([]))
|
||||||
mocks.thenStubWatchingUserstories.callArg(0)
|
mocks.thenStubAssignedToIssues.callArg(0, Immutable.fromJS([]))
|
||||||
mocks.thenStubWatchingTasks.callArg(0)
|
mocks.thenStubWatchingUserstories.callArg(0, Immutable.fromJS([]))
|
||||||
mocks.thenStubWatchingIssues.callArg(0)
|
mocks.thenStubWatchingTasks.callArg(0, Immutable.fromJS([]))
|
||||||
|
mocks.thenStubWatchingIssues.callArg(0, Immutable.fromJS([]))
|
||||||
timeout.flush()
|
timeout.flush()
|
||||||
|
|
||||||
projectsById = {
|
projectsById = {
|
||||||
get: () -> {
|
get: () -> Immutable.fromJS({
|
||||||
name: "Testing project"
|
name: "Testing project"
|
||||||
slug: "testing-project"
|
slug: "testing-project"
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
mocks.tgNavUrls.resolve
|
mocks.tgNavUrls.resolve
|
||||||
|
@ -160,6 +160,7 @@ describe "tgHome", ->
|
||||||
.returns("/testing-project/us/123")
|
.returns("/testing-project/us/123")
|
||||||
|
|
||||||
homeService.attachProjectInfoToWorkInProgress(projectsById)
|
homeService.attachProjectInfoToWorkInProgress(projectsById)
|
||||||
|
|
||||||
expect(homeService.workInProgress.toJS()).to.be.eql({
|
expect(homeService.workInProgress.toJS()).to.be.eql({
|
||||||
assignedTo: {
|
assignedTo: {
|
||||||
userStories: [
|
userStories: [
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
ul.home-project-list(ng-show="vm.projects.size")
|
ul.home-project-list(ng-show="vm.projects.size")
|
||||||
li.home-project-list-single(tg-bind-scope, tg-repeat="project in vm.projects")
|
li.home-project-list-single(tg-bind-scope, tg-repeat="project in vm.projects")
|
||||||
a(href="#", tg-nav="project:project=project.slug")
|
a(href="#", tg-nav="project:project=project.get('slug')")
|
||||||
h2.home-project-list-single-title
|
h2.home-project-list-single-title
|
||||||
span.project-name(ng-bind="::project.name", title="{{ ::project.name }}")
|
span.project-name(title="{{ ::project.get('name') }}") {{::project.get('name')}}
|
||||||
span.private(ng-if="project.is_private", title="{{'PROJECT.PRIVATE' | translate}}")
|
span.private(ng-if="project.get('is_private')", title="{{'PROJECT.PRIVATE' | translate}}")
|
||||||
include ../../../svg/lock.svg
|
include ../../../svg/lock.svg
|
||||||
p {{ ::project.description | limitTo:150 }}
|
p {{ ::project.get('description') | limitTo:150 }}
|
||||||
span(ng-if="::project.description.length > 150") ...
|
span(ng-if="::project.get('description').size > 150") ...
|
||||||
a.see-more-projects-btn.button-gray(ng-show="vm.projects.size", href="#", tg-nav="projects", title="{{'PROJECT.NAVIGATION.SEE_MORE_PROJECTS' | translate}}", translate="PROJECT.NAVIGATION.SEE_MORE_PROJECTS")
|
a.see-more-projects-btn.button-gray(ng-show="vm.projects.size", href="#", tg-nav="projects", title="{{'PROJECT.NAVIGATION.SEE_MORE_PROJECTS' | translate}}", translate="PROJECT.NAVIGATION.SEE_MORE_PROJECTS")
|
||||||
section.projects-empty(ng-hide="vm.projects.size")
|
section.projects-empty(ng-hide="vm.projects.size")
|
||||||
include ../../../svg/empty-project.svg
|
include ../../../svg/empty-project.svg
|
||||||
|
|
|
@ -5,8 +5,7 @@ div.navbar-dropdown.dropdown-project-list
|
||||||
ul
|
ul
|
||||||
a(href="#",
|
a(href="#",
|
||||||
tg-repeat="project in vm.projects",
|
tg-repeat="project in vm.projects",
|
||||||
ng-bind="::project.name"
|
tg-nav="project:project=project.get('slug')") {{::project.get("name")}}
|
||||||
tg-nav="project:project=project.slug")
|
|
||||||
|
|
||||||
a.see-more-projects-btn.button-gray(
|
a.see-more-projects-btn.button-gray(
|
||||||
href="#",
|
href="#",
|
||||||
|
|
|
@ -11,6 +11,6 @@ class ProfileBarController
|
||||||
|
|
||||||
loadStats: () ->
|
loadStats: () ->
|
||||||
return @userService.getStats(@.user.id).then (stats) =>
|
return @userService.getStats(@.user.id).then (stats) =>
|
||||||
@.stats = stats.toJS()
|
@.stats = stats
|
||||||
|
|
||||||
angular.module("taigaProfile").controller("ProfileBar", ProfileBarController)
|
angular.module("taigaProfile").controller("ProfileBar", ProfileBarController)
|
||||||
|
|
|
@ -58,4 +58,4 @@ describe "ProfileBar", ->
|
||||||
|
|
||||||
$rootScope.$apply()
|
$rootScope.$apply()
|
||||||
|
|
||||||
expect(ctrl.stats).to.be.eql(stats.toJS())
|
expect(ctrl.stats.toJS()).to.be.eql(stats.toJS())
|
||||||
|
|
|
@ -9,7 +9,7 @@ section.profile-bar
|
||||||
// span(translate="USER.PROFILE.FOLLOW")
|
// span(translate="USER.PROFILE.FOLLOW")
|
||||||
div.profile-data
|
div.profile-data
|
||||||
h1 {{::vm.user.full_name}}
|
h1 {{::vm.user.full_name}}
|
||||||
h2 {{::vm.stats.roles.join(", ")}}
|
h2 {{::vm.stats.get('roles').join(", ")}}
|
||||||
// div.location
|
// div.location
|
||||||
// include ../../../svg/location.svg
|
// include ../../../svg/location.svg
|
||||||
// span Madrid
|
// span Madrid
|
||||||
|
@ -19,13 +19,13 @@ section.profile-bar
|
||||||
// These values in profile stats are not defined yet in UX. Please ask
|
// These values in profile stats are not defined yet in UX. Please ask
|
||||||
div.profile-stats
|
div.profile-stats
|
||||||
div.stat
|
div.stat
|
||||||
span.stat-number {{::vm.stats.projects}}
|
span.stat-number {{::vm.stats.get('projects')}}
|
||||||
span.stat-name(translate="USER.PROFILE.PROJECTS")
|
span.stat-name(translate="USER.PROFILE.PROJECTS")
|
||||||
div.stat
|
div.stat
|
||||||
span.stat-number {{::vm.stats.closed_userstories}}
|
span.stat-number {{::vm.stats.get('closed_userstories')}}
|
||||||
span.stat-name(translate="USER.PROFILE.CLOSED_US")
|
span.stat-name(translate="USER.PROFILE.CLOSED_US")
|
||||||
div.stat
|
div.stat
|
||||||
span.stat-number {{::vm.stats.contacts}}
|
span.stat-number {{::vm.stats.get('contacts')}}
|
||||||
span.stat-name(translate="USER.PROFILE.CONTACTS")
|
span.stat-name(translate="USER.PROFILE.CONTACTS")
|
||||||
// TODO Hide until organizations come
|
// TODO Hide until organizations come
|
||||||
// div.profile-organizations
|
// div.profile-organizations
|
||||||
|
@ -36,5 +36,5 @@ section.profile-bar
|
||||||
// div.organization
|
// div.organization
|
||||||
// div.organization
|
// div.organization
|
||||||
|
|
||||||
div.profile-quote(ng-if="vm.user.bio")
|
div.profile-quote(ng-if="::vm.user.bio")
|
||||||
span {{::vm.user.bio}}
|
span {{::vm.user.bio}}
|
||||||
|
|
|
@ -7,19 +7,19 @@ section.profile-contacts
|
||||||
|
|
||||||
div.profile-contact-single(tg-repeat="contact in ::vm.contacts")
|
div.profile-contact-single(tg-repeat="contact in ::vm.contacts")
|
||||||
div.profile-contact-picture
|
div.profile-contact-picture
|
||||||
a(tg-nav="user-profile:username=contact.username", title="{{::contact.name }}")
|
a(tg-nav="user-profile:username=contact.get('username')", title="{{::contact.get('name') }}")
|
||||||
img(ng-src='{{::contact.photo}}', alt='{{::contact.full_name}}')
|
img(ng-src="{{::contact.get('photo')}}", alt="{{::contact.get('full_name')}}")
|
||||||
|
|
||||||
div.profile-contact-data
|
div.profile-contact-data
|
||||||
h1
|
h1
|
||||||
a(tg-nav="user-profile:username=contact.username", title="{{::contact.name }}")
|
a(tg-nav="user-profile:username=contact.get('username')", title="{{::contact.get('name') }}")
|
||||||
| {{::contact.full_name}}
|
| {{::contact.get('full_name')}}
|
||||||
// span.your-contact Your contact
|
// span.your-contact Your contact
|
||||||
|
|
||||||
p(ng-if="contact.bio") {{::contact.bio}}
|
p(ng-if="contact.bio") {{::contact.get('bio')}}
|
||||||
|
|
||||||
div.extra-info
|
div.extra-info
|
||||||
span.position {{::contact.roles.join(", ")}}
|
span.position {{::contact.get('roles').join(", ")}}
|
||||||
// span.location todo
|
// span.location todo
|
||||||
// div.profile-project-stats
|
// div.profile-project-stats
|
||||||
// div.stat-projects(title="2 projects")
|
// div.stat-projects(title="2 projects")
|
||||||
|
|
|
@ -4,16 +4,16 @@ section.profile-projects
|
||||||
|
|
||||||
div.project-list-single-title
|
div.project-list-single-title
|
||||||
h1
|
h1
|
||||||
a(href="#", tg-nav="project:project=project.slug", title="{{ ::project.name }}") {{::project.name}}
|
a(href="#", tg-nav="project:project=project.get('slug')", title="{{ ::project.get('name') }}") {{::project.get('name')}}
|
||||||
p {{ ::project.description | limitTo:300 }}
|
p {{ ::project.get('description') | limitTo:300 }}
|
||||||
|
|
||||||
div.project-list-single-tags.tags-container
|
div.project-list-single-tags.tags-container
|
||||||
span.tag(style='border-left: 5px solid {{::tag.color}};', ng-repeat="tag in ::project.colorized_tags")
|
span.tag(style='border-left: 5px solid {{::tag.get("color")}};', tg-repeat="tag in ::project.get('colorized_tags')")
|
||||||
span.tag-name {{::tag.name}}
|
span.tag-name {{::tag.get('name')}}
|
||||||
|
|
||||||
div.project-list-single-members
|
div.project-list-single-members
|
||||||
a(ng-repeat="contact in ::project.contacts", tg-nav="user-profile:username=contact.username", title="{{::contact.full_name}}")
|
a(tg-repeat="contact in ::project.get('contacts')", tg-nav="user-profile:username=contact.get('username')", title="{{::contact.get('full_name')}}")
|
||||||
img(ng-src="{{::contact.photo}}")
|
img(ng-src="{{::contact.get('photo')}}")
|
||||||
|
|
||||||
// div.project-list-single-right
|
// div.project-list-single-right
|
||||||
// div.project-list-single-stats
|
// div.project-list-single-stats
|
||||||
|
|
|
@ -6,7 +6,7 @@ class ProfileTimelineItemController
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@sce, @profileTimelineItemType, @profileTimelineItemTitle) ->
|
constructor: (@sce, @profileTimelineItemType, @profileTimelineItemTitle) ->
|
||||||
timeline = @.timeline
|
timeline = @.timeline.toJS()
|
||||||
event = @.parseEventType(timeline.event_type)
|
event = @.parseEventType(timeline.event_type)
|
||||||
type = @profileTimelineItemType.getType(timeline, event)
|
type = @profileTimelineItemType.getType(timeline, event)
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,9 @@ describe "ProfileTimelineItemController", ->
|
||||||
|
|
||||||
it "basic activity fields filled", () ->
|
it "basic activity fields filled", () ->
|
||||||
timeline = scope.vm.timeline
|
timeline = scope.vm.timeline
|
||||||
|
timeline_immutable = Immutable.fromJS(timeline)
|
||||||
|
|
||||||
myCtrl = controller("ProfileTimelineItem", {$scope: scope}, {timeline: timeline})
|
myCtrl = controller("ProfileTimelineItem", {$scope: scope}, {timeline: timeline_immutable})
|
||||||
|
|
||||||
expect(myCtrl.activity.user).to.be.equal(timeline.data.user)
|
expect(myCtrl.activity.user).to.be.equal(timeline.data.user)
|
||||||
expect(myCtrl.activity.project).to.be.equal(timeline.data.project)
|
expect(myCtrl.activity.project).to.be.equal(timeline.data.project)
|
||||||
|
@ -94,7 +95,9 @@ describe "ProfileTimelineItemController", ->
|
||||||
mockType.description.withArgs(timeline).returns(description)
|
mockType.description.withArgs(timeline).returns(description)
|
||||||
mockType.member.withArgs(timeline).returns(member)
|
mockType.member.withArgs(timeline).returns(member)
|
||||||
|
|
||||||
myCtrl = controller("ProfileTimelineItem", {$scope: scope}, {timeline: timeline})
|
timeline_immutable = Immutable.fromJS(timeline)
|
||||||
|
|
||||||
|
myCtrl = controller("ProfileTimelineItem", {$scope: scope}, {timeline: timeline_immutable})
|
||||||
|
|
||||||
expect(myCtrl.activity.description).to.be.an('object') # $sce.trustAsHtml
|
expect(myCtrl.activity.description).to.be.an('object') # $sce.trustAsHtml
|
||||||
expect(myCtrl.activity.member).to.be.equal(member)
|
expect(myCtrl.activity.member).to.be.equal(member)
|
||||||
|
|
|
@ -19,7 +19,7 @@ ProjectsListingDirective = (projectsService) ->
|
||||||
|
|
||||||
sorted_project_ids = _.map(scope.vm.projects.toArray(), (p) -> p.id)
|
sorted_project_ids = _.map(scope.vm.projects.toArray(), (p) -> p.id)
|
||||||
sorted_project_ids = _.without(sorted_project_ids, project.id)
|
sorted_project_ids = _.without(sorted_project_ids, project.id)
|
||||||
sorted_project_ids.splice(index, 0, project.id)
|
sorted_project_ids.splice(index, 0, project.get('id'))
|
||||||
sortData = []
|
sortData = []
|
||||||
for value, index in sorted_project_ids
|
for value, index in sorted_project_ids
|
||||||
sortData.push({"project_id": value, "order":index})
|
sortData.push({"project_id": value, "order":index})
|
||||||
|
|
|
@ -15,15 +15,15 @@ div.project-list-wrapper.centered
|
||||||
div.project-list-single-left
|
div.project-list-single-left
|
||||||
div.project-list-single-title
|
div.project-list-single-title
|
||||||
h1
|
h1
|
||||||
a(href="#", tg-nav="project:project=project.slug")
|
a(href="#", tg-nav="project:project=project.get('slug')")
|
||||||
h1.project-name(ng-bind="::project.name", title="{{ ::project.name }}")
|
h1.project-name(title="{{ ::project.get('name') }}") {{project.get('name')}}
|
||||||
span.private(ng-if="project.is_private", title="{{'PROJECT.PRIVATE' | translate}}")
|
span.private(ng-if="project.get('is_private')", title="{{'PROJECT.PRIVATE' | translate}}")
|
||||||
include ../../../svg/lock.svg
|
include ../../../svg/lock.svg
|
||||||
p {{ ::project.description | limitTo:300 }}
|
p {{ ::project.get('description') | limitTo:300 }}
|
||||||
span(ng-if="::project.description.length > 300") ...
|
span(ng-if="::project.get('description').length > 300") ...
|
||||||
|
|
||||||
div.project-list-single-tags.tags-container(ng-if="::project.tags")
|
div.project-list-single-tags.tags-container(ng-if="::project.get('tags').size")
|
||||||
div.tags-block(tg-colorize-tags="project.tags", tg-colorize-tags-type="backlog")
|
div.tags-block(tg-colorize-tags="project.get('tags')", tg-colorize-tags-type="backlog")
|
||||||
|
|
||||||
div.project-list-single-right
|
div.project-list-single-right
|
||||||
span.drag.icon.icon-drag-v
|
span.drag.icon.icon-drag-v
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
div(tg-project)
|
|
@ -0,0 +1,17 @@
|
||||||
|
class ProjectController
|
||||||
|
@.$inject = [
|
||||||
|
"tgProjectsService",
|
||||||
|
"$routeParams",
|
||||||
|
"$appTitle"
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@projectsService, @routeParams, @appTitle) ->
|
||||||
|
projectSlug = @routeParams.pslug
|
||||||
|
|
||||||
|
@projectsService.getProjectBySlug(projectSlug)
|
||||||
|
.then (project) =>
|
||||||
|
@appTitle.set(project.get("name"))
|
||||||
|
|
||||||
|
@.project = project
|
||||||
|
|
||||||
|
angular.module("taigaProjects").controller("Project", ProjectController)
|
|
@ -0,0 +1,84 @@
|
||||||
|
describe "ProfileBar", ->
|
||||||
|
$controller = null
|
||||||
|
$q = null
|
||||||
|
provide = null
|
||||||
|
$rootScope = null
|
||||||
|
mocks = {}
|
||||||
|
|
||||||
|
_mockProjectsService = () ->
|
||||||
|
mocks.projectService = {
|
||||||
|
getProjectBySlug: sinon.stub()
|
||||||
|
}
|
||||||
|
|
||||||
|
provide.value "tgProjectsService", mocks.projectService
|
||||||
|
|
||||||
|
_mockAppTitle = () ->
|
||||||
|
mocks.appTitle = {
|
||||||
|
set: sinon.stub()
|
||||||
|
}
|
||||||
|
|
||||||
|
provide.value "$appTitle", mocks.appTitle
|
||||||
|
|
||||||
|
_mockRouteParams = () ->
|
||||||
|
provide.value "$routeParams", {
|
||||||
|
pslug: "project-slug"
|
||||||
|
}
|
||||||
|
|
||||||
|
_mocks = () ->
|
||||||
|
module ($provide) ->
|
||||||
|
provide = $provide
|
||||||
|
_mockProjectsService()
|
||||||
|
_mockRouteParams()
|
||||||
|
_mockAppTitle()
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
_inject = (callback) ->
|
||||||
|
inject (_$controller_, _$q_, _$rootScope_) ->
|
||||||
|
$q = _$q_
|
||||||
|
$rootScope = _$rootScope_
|
||||||
|
$controller = _$controller_
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaProjects"
|
||||||
|
_mocks()
|
||||||
|
_inject()
|
||||||
|
|
||||||
|
it "set page title", () ->
|
||||||
|
project = Immutable.fromJS({
|
||||||
|
name: "projectName"
|
||||||
|
})
|
||||||
|
|
||||||
|
thenStub = sinon.stub()
|
||||||
|
|
||||||
|
mocks.projectService.getProjectBySlug.withArgs("project-slug").returns({
|
||||||
|
then: thenStub
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl = $controller("Project")
|
||||||
|
|
||||||
|
thenStub.callArg(0, project)
|
||||||
|
|
||||||
|
$rootScope.$apply()
|
||||||
|
|
||||||
|
expect(mocks.appTitle.set.withArgs("projectName")).to.be.calledOnce
|
||||||
|
|
||||||
|
|
||||||
|
it "set local project variable", () ->
|
||||||
|
project = Immutable.fromJS({
|
||||||
|
name: "projectName"
|
||||||
|
})
|
||||||
|
|
||||||
|
thenStub = sinon.stub()
|
||||||
|
|
||||||
|
mocks.projectService.getProjectBySlug.withArgs("project-slug").returns({
|
||||||
|
then: thenStub
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl = $controller("Project")
|
||||||
|
|
||||||
|
thenStub.callArg(0, project)
|
||||||
|
|
||||||
|
$rootScope.$apply()
|
||||||
|
|
||||||
|
expect(ctrl.project).to.be.equal(project)
|
|
@ -0,0 +1,8 @@
|
||||||
|
ProjectDirective = () ->
|
||||||
|
return {
|
||||||
|
templateUrl: "projects/project/project.html",
|
||||||
|
controllerAs: "vm",
|
||||||
|
controller: "Project"
|
||||||
|
}
|
||||||
|
|
||||||
|
angular.module("taigaProjects").directive("tgProject", ProjectDirective)
|
|
@ -0,0 +1,24 @@
|
||||||
|
div.wrapper
|
||||||
|
div.main.centered.single-project
|
||||||
|
section.single-project-intro
|
||||||
|
h1
|
||||||
|
span.green(class="project-name") {{::vm.project.get("name")}}
|
||||||
|
span.private(ng-if="::vm.project.get('is_private')", title="{{'PROJECT.PRIVATE' | translate}}")
|
||||||
|
include ../../../svg/lock.svg
|
||||||
|
p.description {{vm.project.get('description')}}
|
||||||
|
div.project-list-single-tags.tags-container(ng-if="::vm.project.get('tags').size")
|
||||||
|
div.tags-block(tg-colorize-tags="vm.project.get('tags')", tg-colorize-tags-type="backlog")
|
||||||
|
|
||||||
|
div.project-data
|
||||||
|
section.timeline
|
||||||
|
span TODO. Missing the amazing timeline around!!dfdfdf
|
||||||
|
section.involved-data
|
||||||
|
h2.title Team
|
||||||
|
ul.involved-team
|
||||||
|
a(href="", title="{{::member.get('full_name')}}", tg-repeat="member in ::vm.project.get('memberships')")
|
||||||
|
img(ng-src="{{::member.get('photo')}}", alt="{{::member.get('full_name')}}")
|
||||||
|
|
||||||
|
// h2.title Organizations
|
||||||
|
// div.involved-organization
|
||||||
|
// a(href="", title="User Name")
|
||||||
|
// img(src="https://s3.amazonaws.com/uifaces/faces/twitter/dan_higham/48.jpg", alt="{{member.full_name}}")
|
|
@ -2,7 +2,7 @@ taiga = @.taiga
|
||||||
groupBy = @.taiga.groupBy
|
groupBy = @.taiga.groupBy
|
||||||
|
|
||||||
class ProjectsService extends taiga.Service
|
class ProjectsService extends taiga.Service
|
||||||
@.$inject = ["$tgResources", "$rootScope", "$projectUrl", "tgLightboxFactory"]
|
@.$inject = ["tgResources", "$rootScope", "$projectUrl", "tgLightboxFactory"]
|
||||||
|
|
||||||
constructor: (@rs, @rootScope, @projectUrl, @lightboxFactory) ->
|
constructor: (@rs, @rootScope, @projectUrl, @lightboxFactory) ->
|
||||||
@._currentUserProjects = Immutable.Map()
|
@._currentUserProjects = Immutable.Map()
|
||||||
|
@ -18,30 +18,40 @@ class ProjectsService extends taiga.Service
|
||||||
getCurrentUserProjects: ->
|
getCurrentUserProjects: ->
|
||||||
return @._currentUserProjectsPromise
|
return @._currentUserProjectsPromise
|
||||||
|
|
||||||
|
getProjectBySlug: (projectSlug) ->
|
||||||
|
return @rs.projects.getProjectBySlug(projectSlug)
|
||||||
|
|
||||||
|
getProjectStats: (projectId) ->
|
||||||
|
return @rs.projects.getProjectStats(projectId)
|
||||||
|
|
||||||
fetchProjects: ->
|
fetchProjects: ->
|
||||||
if not @._inProgress
|
if not @._inProgress
|
||||||
@._inProgress = true
|
@._inProgress = true
|
||||||
|
|
||||||
@._currentUserProjectsPromise = @rs.projects.listByMember(@rootScope.user?.id)
|
@._currentUserProjectsPromise = @rs.users.getProjects(@rootScope.user?.id)
|
||||||
@._currentUserProjectsPromise.then (projects) =>
|
@._currentUserProjectsPromise.then (projects) =>
|
||||||
_.map projects, (project) =>
|
projects = projects.map (project) =>
|
||||||
project.url = @projectUrl.get(project)
|
url = @projectUrl.get(project.toJS())
|
||||||
|
|
||||||
project.colorized_tags = []
|
project = project.set("url", url)
|
||||||
|
colorized_tags = []
|
||||||
|
|
||||||
if project.tags
|
if project.get("tags")
|
||||||
tags = project.tags.sort()
|
tags = project.get("tags").sort()
|
||||||
|
|
||||||
project.colorized_tags = _.map tags, (tag) ->
|
colorized_tags = tags.map (tag) ->
|
||||||
color = project.tags_colors[tag]
|
color = project.get("tags_colors").get(tag)
|
||||||
return {name: tag, color: color}
|
return {name: tag, color: color}
|
||||||
|
|
||||||
@._currentUserProjects = Immutable.fromJS({
|
project = project.set("colorized_tags", colorized_tags)
|
||||||
all: projects,
|
|
||||||
recents: projects.slice(0, 10)
|
|
||||||
})
|
|
||||||
|
|
||||||
@._currentUserProjectsById = Immutable.fromJS(groupBy(projects, (p) -> p.id))
|
return project
|
||||||
|
|
||||||
|
|
||||||
|
@._currentUserProjects = @._currentUserProjects.set("all", projects)
|
||||||
|
@._currentUserProjects = @._currentUserProjects.set("recents", projects.slice(0, 10))
|
||||||
|
|
||||||
|
@._currentUserProjectsById = Immutable.fromJS(groupBy(projects.toJS(), (p) -> p.id))
|
||||||
|
|
||||||
return @.projects
|
return @.projects
|
||||||
|
|
||||||
|
|
|
@ -5,18 +5,19 @@ describe "tgProjects", ->
|
||||||
_mockResources = () ->
|
_mockResources = () ->
|
||||||
mocks.resources = {}
|
mocks.resources = {}
|
||||||
|
|
||||||
mocks.resources.projects = {
|
mocks.resources.users = {
|
||||||
listByMember: sinon.stub()
|
getProjects: sinon.stub()
|
||||||
}
|
}
|
||||||
|
|
||||||
mocks.thenStub = sinon.stub()
|
mocks.thenStub = sinon.stub()
|
||||||
mocks.finallyStub = sinon.stub()
|
mocks.finallyStub = sinon.stub()
|
||||||
mocks.resources.projects.listByMember.withArgs(10).returns({
|
|
||||||
|
mocks.resources.users.getProjects.withArgs(10).returns({
|
||||||
then: mocks.thenStub
|
then: mocks.thenStub
|
||||||
finally: mocks.finallyStub
|
finally: mocks.finallyStub
|
||||||
})
|
})
|
||||||
|
|
||||||
provide.value "$tgResources", mocks.resources
|
provide.value "tgResources", mocks.resources
|
||||||
|
|
||||||
_mockRootScope = () ->
|
_mockRootScope = () ->
|
||||||
provide.value "$rootScope", {user: {id: 10}}
|
provide.value "$rootScope", {user: {id: 10}}
|
||||||
|
@ -64,22 +65,22 @@ describe "tgProjects", ->
|
||||||
|
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
projects = [
|
projects = [
|
||||||
{"id": 1, tags: ['xx', 'yy', 'aa'], tags_colors: {xx: "red", yy: "blue", aa: "white"}},
|
{"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},
|
{"id": 2, url: 'url-2'},
|
||||||
{"id": 3},
|
{"id": 3, url: 'url-3'},
|
||||||
{"id": 4},
|
{"id": 4, url: 'url-4'},
|
||||||
{"id": 5},
|
{"id": 5, url: 'url-5'},
|
||||||
{"id": 6},
|
{"id": 6, url: 'url-6'},
|
||||||
{"id": 7},
|
{"id": 7, url: 'url-7'},
|
||||||
{"id": 8},
|
{"id": 8, url: 'url-8'},
|
||||||
{"id": 9},
|
{"id": 9, url: 'url-9'},
|
||||||
{"id": 10},
|
{"id": 10, url: 'url-10'},
|
||||||
{"id": 11},
|
{"id": 11, url: 'url-11'},
|
||||||
{"id": 12},
|
{"id": 12, url: 'url-12'}
|
||||||
]
|
]
|
||||||
|
|
||||||
it "all & recents filled", () ->
|
it "all & recents filled", () ->
|
||||||
mocks.thenStub.callArg(0, projects)
|
mocks.thenStub.callArg(0, Immutable.fromJS(projects))
|
||||||
|
|
||||||
expect(projectsService.currentUserProjects.get("all").toJS()).to.be.eql(projects)
|
expect(projectsService.currentUserProjects.get("all").toJS()).to.be.eql(projects)
|
||||||
expect(projectsService.currentUserProjects.get("recents").toJS()).to.be.eql(projects.slice(0, 10))
|
expect(projectsService.currentUserProjects.get("recents").toJS()).to.be.eql(projects.slice(0, 10))
|
||||||
|
@ -87,7 +88,7 @@ describe "tgProjects", ->
|
||||||
it "_inProgress change to false when tgResources end", () ->
|
it "_inProgress change to false when tgResources end", () ->
|
||||||
expect(projectsService._inProgress).to.be.true
|
expect(projectsService._inProgress).to.be.true
|
||||||
|
|
||||||
mocks.thenStub.callArg(0, projects)
|
mocks.thenStub.callArg(0, Immutable.fromJS(projects))
|
||||||
mocks.finallyStub.callArg(0)
|
mocks.finallyStub.callArg(0)
|
||||||
|
|
||||||
expect(projectsService._inProgress).to.be.false
|
expect(projectsService._inProgress).to.be.false
|
||||||
|
@ -96,25 +97,25 @@ describe "tgProjects", ->
|
||||||
projectsService.fetchProjects()
|
projectsService.fetchProjects()
|
||||||
projectsService.fetchProjects()
|
projectsService.fetchProjects()
|
||||||
|
|
||||||
mocks.thenStub.callArg(0, projects)
|
mocks.thenStub.callArg(0, Immutable.fromJS(projects))
|
||||||
|
|
||||||
expect(mocks.resources.projects.listByMember).have.been.calledOnce
|
expect(mocks.resources.users.getProjects).have.been.calledOnce
|
||||||
|
|
||||||
it "group projects by id", () ->
|
it "group projects by id", () ->
|
||||||
mocks.thenStub.callArg(0, projects)
|
mocks.thenStub.callArg(0, Immutable.fromJS(projects))
|
||||||
|
|
||||||
expect(projectsService.currentUserProjectsById.size).to.be.equal(12)
|
expect(projectsService.currentUserProjectsById.size).to.be.equal(12)
|
||||||
expect(projectsService.currentUserProjectsById.toJS()[1].id).to.be.equal(projects[0].id)
|
expect(projectsService.currentUserProjectsById.toJS()[1].id).to.be.equal(projects[0].id)
|
||||||
|
|
||||||
it "add urls in the project object", () ->
|
it "add urls in the project object", () ->
|
||||||
mocks.thenStub.callArg(0, projects)
|
mocks.thenStub.callArg(0, Immutable.fromJS(projects))
|
||||||
|
|
||||||
expect(projectsService.currentUserProjectsById.toJS()[1].url).to.be.equal("url-1")
|
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("all").toJS()[0].url).to.be.equal("url-1")
|
||||||
expect(projectsService.currentUserProjects.get("recents").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", () ->
|
it "add sorted colorized_tags project object", () ->
|
||||||
mocks.thenStub.callArg(0, projects)
|
mocks.thenStub.callArg(0, Immutable.fromJS(projects))
|
||||||
|
|
||||||
tags = [
|
tags = [
|
||||||
{name: "aa", color: "white"},
|
{name: "aa", color: "white"},
|
||||||
|
@ -152,6 +153,7 @@ describe "tgProjects", ->
|
||||||
|
|
||||||
thenStub = sinon.stub()
|
thenStub = sinon.stub()
|
||||||
|
|
||||||
|
mocks.resources.projects = {}
|
||||||
mocks.resources.projects.bulkUpdateOrder = sinon.stub()
|
mocks.resources.projects.bulkUpdateOrder = sinon.stub()
|
||||||
mocks.resources.projects.bulkUpdateOrder.withArgs(projects_order).returns({
|
mocks.resources.projects.bulkUpdateOrder.withArgs(projects_order).returns({
|
||||||
then: thenStub
|
then: thenStub
|
||||||
|
@ -164,3 +166,21 @@ describe "tgProjects", ->
|
||||||
thenStub.callArg(0)
|
thenStub.callArg(0)
|
||||||
|
|
||||||
expect(projectsService.fetchProjects).to.have.been.calledOnce
|
expect(projectsService.fetchProjects).to.have.been.calledOnce
|
||||||
|
|
||||||
|
it "getProjectBySlug", () ->
|
||||||
|
projectSlug = "project-slug"
|
||||||
|
|
||||||
|
mocks.resources.projects = {}
|
||||||
|
mocks.resources.projects.getProjectBySlug = sinon.stub()
|
||||||
|
mocks.resources.projects.getProjectBySlug.withArgs(projectSlug).returns(true)
|
||||||
|
|
||||||
|
expect(projectsService.getProjectBySlug(projectSlug)).to.be.true
|
||||||
|
|
||||||
|
it "getProjectStats", () ->
|
||||||
|
projectId = 3
|
||||||
|
|
||||||
|
mocks.resources.projects = {}
|
||||||
|
mocks.resources.projects.getProjectStats = sinon.stub()
|
||||||
|
mocks.resources.projects.getProjectStats.withArgs(projectId).returns(true)
|
||||||
|
|
||||||
|
expect(projectsService.getProjectStats(projectId)).to.be.true
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
Resource = (urlsService, http) ->
|
||||||
|
service = {}
|
||||||
|
|
||||||
|
service.listInAllProjects = (params) ->
|
||||||
|
url = urlsService.resolve("issues")
|
||||||
|
|
||||||
|
httpOptions = {
|
||||||
|
headers: {
|
||||||
|
"x-disable-pagination": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return http.get(url, params, httpOptions)
|
||||||
|
.then (result) ->
|
||||||
|
return Immutable.fromJS(result.data)
|
||||||
|
|
||||||
|
return () ->
|
||||||
|
return {"issues": service}
|
||||||
|
|
||||||
|
Resource.$inject = ["$tgUrls", "$tgHttp"]
|
||||||
|
|
||||||
|
module = angular.module("taigaResources2")
|
||||||
|
module.factory("tgIssuesResource", Resource)
|
|
@ -0,0 +1,31 @@
|
||||||
|
Resource = (urlsService, http) ->
|
||||||
|
service = {}
|
||||||
|
|
||||||
|
service.getProjectBySlug = (projectSlug) ->
|
||||||
|
url = urlsService.resolve("projects")
|
||||||
|
|
||||||
|
url = "#{url}/by_slug?slug=#{projectSlug}"
|
||||||
|
|
||||||
|
return http.get(url)
|
||||||
|
.then (result) ->
|
||||||
|
return Immutable.fromJS(result.data)
|
||||||
|
|
||||||
|
service.getProjectStats = (projectId) ->
|
||||||
|
url = urlsService.resolve("projects")
|
||||||
|
url = "#{url}/#{projectId}"
|
||||||
|
|
||||||
|
return http.get(url)
|
||||||
|
.then (result) ->
|
||||||
|
return Immutable.fromJS(result.data)
|
||||||
|
|
||||||
|
service.bulkUpdateOrder = (bulkData) ->
|
||||||
|
url = urlsService.resolve("bulk-update-projects-order")
|
||||||
|
return http.post(url, bulkData)
|
||||||
|
|
||||||
|
return () ->
|
||||||
|
return {"projects": service}
|
||||||
|
|
||||||
|
Resource.$inject = ["$tgUrls", "$tgHttp"]
|
||||||
|
|
||||||
|
module = angular.module("taigaResources2")
|
||||||
|
module.factory("tgProjectsResources", Resource)
|
|
@ -1,5 +1,9 @@
|
||||||
services = [
|
services = [
|
||||||
"tgProjectsResources"
|
"tgProjectsResources",
|
||||||
|
"tgUsersResources",
|
||||||
|
"tgUserstoriesResource",
|
||||||
|
"tgTasksResource",
|
||||||
|
"tgIssuesResource"
|
||||||
]
|
]
|
||||||
|
|
||||||
Resources = ($injector) ->
|
Resources = ($injector) ->
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
Resource = (urlsService, http) ->
|
||||||
|
service = {}
|
||||||
|
|
||||||
|
service.listInAllProjects = (params) ->
|
||||||
|
url = urlsService.resolve("tasks")
|
||||||
|
|
||||||
|
httpOptions = {
|
||||||
|
headers: {
|
||||||
|
"x-disable-pagination": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return http.get(url, params, httpOptions)
|
||||||
|
.then (result) ->
|
||||||
|
return Immutable.fromJS(result.data)
|
||||||
|
|
||||||
|
return () ->
|
||||||
|
return {"tasks": service}
|
||||||
|
|
||||||
|
Resource.$inject = ["$tgUrls", "$tgHttp"]
|
||||||
|
|
||||||
|
module = angular.module("taigaResources2")
|
||||||
|
module.factory("tgTasksResource", Resource)
|
|
@ -43,4 +43,4 @@ Resource = (urlsService, http) ->
|
||||||
Resource.$inject = ["$tgUrls", "$tgHttp"]
|
Resource.$inject = ["$tgUrls", "$tgHttp"]
|
||||||
|
|
||||||
module = angular.module("taigaResources2")
|
module = angular.module("taigaResources2")
|
||||||
module.factory("tgProjectsResources", Resource)
|
module.factory("tgUsersResources", Resource)
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
Resource = (urlsService, http) ->
|
||||||
|
service = {}
|
||||||
|
|
||||||
|
service.listInAllProjects = (params) ->
|
||||||
|
url = urlsService.resolve("userstories")
|
||||||
|
|
||||||
|
httpOptions = {
|
||||||
|
headers: {
|
||||||
|
"x-disable-pagination": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return http.get(url, params, httpOptions)
|
||||||
|
.then (result) ->
|
||||||
|
return Immutable.fromJS(result.data)
|
||||||
|
|
||||||
|
return () ->
|
||||||
|
return {"userstories": service}
|
||||||
|
|
||||||
|
Resource.$inject = ["$tgUrls", "$tgHttp"]
|
||||||
|
|
||||||
|
module = angular.module("taigaResources2")
|
||||||
|
module.factory("tgUserstoriesResource", Resource)
|
|
@ -32,7 +32,7 @@ module.exports = function(config) {
|
||||||
// preprocess matching files before serving them to the browser
|
// preprocess matching files before serving them to the browser
|
||||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||||
preprocessors: {
|
preprocessors: {
|
||||||
'**/*.coffee': ['coffee'],
|
'**/*.spec.coffee': ['coffee'],
|
||||||
'dist/js/app.js': ['sourcemap']
|
'dist/js/app.js': ['sourcemap']
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue