diff --git a/app/coffee/app.coffee b/app/coffee/app.coffee index 0d61fa61..463532fb 100644 --- a/app/coffee/app.coffee +++ b/app/coffee/app.coffee @@ -22,7 +22,9 @@ @taiga = taiga = {} configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $compileProvider, $gmUrlsProvider) -> - $routeProvider.when('/project/:pslug/backlog', {templateUrl: '/partials/backlog.html'}) + $routeProvider.when("/project/:pslug/backlog", {templateUrl: "/partials/backlog.html"}) + $routeProvider.when("/login", {templateUrl: "/partials/login.html"}) + $routeProvider.otherwise({redirectTo: '/login'}) $locationProvider.html5Mode(true); @@ -80,6 +82,3 @@ angular.module("taigaLocalConfig", []).value("localconfig", {}) module = angular.module("taiga", modules) module.config(configure) module.run(init) - - - diff --git a/app/coffee/modules/auth.coffee b/app/coffee/modules/auth.coffee index 64b3be9e..51cf0989 100644 --- a/app/coffee/modules/auth.coffee +++ b/app/coffee/modules/auth.coffee @@ -22,9 +22,9 @@ taiga = @.taiga class AuthService extends taiga.Service - @.$inject = ["$rootScope", "$tgStorage", "$tgModel", "$tgHttp"] + @.$inject = ["$rootScope", "$tgStorage", "$tgModel", "$tgHttp", "$tgUrls"] - constructor: (@rootscope, @storage, @model, @http) -> + constructor: (@rootscope, @storage, @model, @http, @urls) -> super() getUser: -> @@ -60,11 +60,12 @@ class AuthService extends taiga.Service data = { username: username password: password + type: "normal" } return @http.post(url, data).then (data, status) => - user = @model.make_model("users", data) - @.setToken(data["auth_token"]) + user = @model.make_model("users", data.data) + @.setToken(user.auth_token) @.setUser(user) return user @@ -73,5 +74,19 @@ class AuthService extends taiga.Service return true return false + +class AuthController extends taiga.Controller + @.$inject = ["$scope", "$tgAuth", "$location"] + + constructor: (@scope, @auth, @location) -> + @scope.form = {username: "", password: ""} + + submit: -> + @auth.login(@scope.form.username, @scope.form.password).then (user) => + #TODO: fix this + @location.path("/project/project-example-0/backlog") + + module = angular.module("taigaAuth", ["taigaResources"]) module.service("$tgAuth", AuthService) +module.controller("AuthController", AuthController) diff --git a/app/coffee/modules/backlog/main.coffee b/app/coffee/modules/backlog/main.coffee index a66313c2..c8896feb 100644 --- a/app/coffee/modules/backlog/main.coffee +++ b/app/coffee/modules/backlog/main.coffee @@ -31,6 +31,22 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin) @rootscope.$on("usform:bulk:success", @.loadUserstories) + initializeProjectStats: -> + @scope.stats = { + total_points: "--" + defined_points: "--" + assigned_points: "--" + closed_points: "--" + completedPercentage: "--%" + } + + loadProjectStats: -> + return @rs.projects.stats(@scope.projectId).then (stats) => + @scope.stats = stats + completedPercentage = Math.round(100 * stats.closed_points / stats.total_points) + @scope.stats.completedPercentage = "#{completedPercentage}%" + return stats + loadSprints: -> return @rs.sprints.list(@scope.projectId).then (sprints) => @scope.sprints = sprints @@ -46,6 +62,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin) loadBacklog: -> return @q.all([ + @.loadProjectStats(), @.loadSprints(), @.loadUserstories() ]) @@ -58,6 +75,9 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin) return project loadInitialData: -> + # Set stats initial values + @.initializeProjectStats() + # Resolve project slug promise = @repo.resolve({pslug: @params.pslug}).then (data) => @scope.projectId = data.project @@ -213,7 +233,12 @@ BacklogDirective = ($repo) -> ############################################################################# BacklogSprintDirective = ($repo) -> - link = ($scope, $el, $attrs) -> + + ######################### + ## Common parts + ######################### + + linkCommon = ($scope, $el, $attrs, $ctrl) -> $ctrl = $el.closest("div.wrapper").controller() sprint = $scope.$eval($attrs.tgBacklogSprint) @@ -223,15 +248,28 @@ BacklogSprintDirective = ($repo) -> if sprint.closed $el.addClass("sprint-closed") + if not $scope.$first and not sprint.closed + $el.addClass("sprint-old-open") + + # Atatch formatted dates + initialDate = moment(sprint.estimated_start).format("YYYY/MM/DD") + finishDate = moment(sprint.estimated_finish).format("YYYY/MM/DD") + dates = "#{initialDate}-#{finishDate}" + $el.find(".sprint-date").html(dates) + + # Update progress bars + progressPercentage = Math.round(100 * (sprint.closed_points / sprint.total_points)) + $el.find(".current-progress").css("width", "#{progressPercentage}%") + # Event Handlers $el.on "click", ".sprint-summary > a", (event) -> $el.find(".sprint-table").toggle() - $scope.$on "$destroy", -> - $el.off() - - # Drag & Drop + ######################### + ## Drag & Drop Link + ######################### + linkSortable = ($scope, $el, $attrs, $ctrl) -> resortAndSave = -> toSave = [] for item, i in $scope.sprint.user_stories @@ -292,6 +330,14 @@ BacklogSprintDirective = ($repo) -> onRemove: onRemoveItem, }) + link = ($scope, $el, $attrs) -> + $ctrl = $el.controller() + linkSortable($scope, $el, $attrs, $ctrl) + linkCommon($scope, $el, $attrs, $ctrl) + + $scope.$on "$destroy", -> + $el.off() + return {link: link} diff --git a/app/coffee/modules/resources/projects.coffee b/app/coffee/modules/resources/projects.coffee index fb536a9a..e09ff8e8 100644 --- a/app/coffee/modules/resources/projects.coffee +++ b/app/coffee/modules/resources/projects.coffee @@ -39,10 +39,12 @@ resourceProvider = ($repo) -> params = {"project": projectId} return $repo.queryMany("roles", params) + service.stats = (projectId) -> + return $repo.queryOneRaw("projects", "#{projectId}/stats") + return (instance) -> instance.projects = service module = angular.module("taigaResources") module.factory("$tgProjectsResourcesProvider", ["$tgRepo", resourceProvider]) - diff --git a/app/partials/issues.jade b/app/partials/issues.jade new file mode 100644 index 00000000..01cef0b4 --- /dev/null +++ b/app/partials/issues.jade @@ -0,0 +1,20 @@ +extends layout + +block head + title Taiga Project management web application with scrum in mind! + +block content + div.wrapper + sidebar.menu-secondary.sidebar + header + h1 Filters + + include views/modules/search-in + include views/modules/filter-tags + + section.main.issues-page + header + include views/components/mainTitle + + include views/modules/list-filters + include views/modules/issues-table \ No newline at end of file diff --git a/app/partials/kanban.jade b/app/partials/kanban.jade new file mode 100644 index 00000000..b146328c --- /dev/null +++ b/app/partials/kanban.jade @@ -0,0 +1,16 @@ +extends layout + +block head + title Taiga Project management web application with scrum in mind! + +block content + div.wrapper + section.main.kanban + h1 + span ProjectName + span.green Sprint Name + span.date 02/10/2014-15/10/2014 + include views/components/large-summary + include views/modules/burndown + include views/modules/list-filters-kanban + include views/modules/taskboard-table \ No newline at end of file diff --git a/app/partials/login.jade b/app/partials/login.jade new file mode 100644 index 00000000..201e3dda --- /dev/null +++ b/app/partials/login.jade @@ -0,0 +1,11 @@ +extends dummy-layout + +block head + title Taiga Project management web application with scrum in mind! + +block content + div.wrapper(ng-controller="AuthController as ctrl") + form(ng-submit="ctrl.submit()") + input(type="text", name="username", ng-model="form.username", placeholder="User name") + input(type="password", name="password", ng-model="form.password", placeholder="Password") + input(type="submit", value="Submit") diff --git a/app/partials/views/components/summary.jade b/app/partials/views/components/summary.jade index 50650191..aa77ed0d 100644 --- a/app/partials/views/components/summary.jade +++ b/app/partials/views/components/summary.jade @@ -2,18 +2,18 @@ div.summary(tg-backlog-summary) div.summary-progress-bar div.current-progress div.data - span.number 30% + span.number(ng-bind="stats.completedPercentage") span.description completed ul li - span.number 12 + span.number(ng-bind="stats.total_points") span.description project
points li - span.number 23 + span.number(ng-bind="stats.defined_points") span.description defined
points li - span.number 12 + span.number(ng-bind="stats.assigned_points") span.description assigned
points li - span.number 23 + span.number(ng-bind="stats.closed_points") span.description closed
points diff --git a/app/partials/views/modules/filter-tags.jade b/app/partials/views/modules/filter-tags.jade new file mode 100644 index 00000000..8f4ac66f --- /dev/null +++ b/app/partials/views/modules/filter-tags.jade @@ -0,0 +1,12 @@ +section.filter-tags + div.filter-tag.active(style="background-color: red") + div.tag-name Tagname + div.tag-count 4 + + div.filter-tag(style="background-color: blue") + div.tag-name Tagname + div.tag-count 4 + + div.filter-tag(style="background-color: green") + div.tag-name Tagname + div.tag-count 4 \ No newline at end of file diff --git a/app/partials/views/modules/issues-table.jade b/app/partials/views/modules/issues-table.jade new file mode 100644 index 00000000..3adf6568 --- /dev/null +++ b/app/partials/views/modules/issues-table.jade @@ -0,0 +1,21 @@ +section.issues-table + div.row.title + div.level-field.width-1 Severity + div.level-field.width-1 Priority + div.width-7.subject Subject + div.width-2 Status + div.width-2 Assigned to + - for (var x = 0; x < 50; x++) + div.row.table-main + div.level-field.width-1 + div.level + div.level-field.width-1 + div.level + div.width-7.subject + | #2 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis sit amet leo accumsan, commodo neque eu, iaculis nisl. Phasellus fermentum ipsum eget sapien suscipit pretium. + div.width-2 + In progress + div.width-2 + figure.avatar + img(src="http://thecodeplayer.com/u/uifaces/12.jpg", alt="username") + figcaption Pilar \ No newline at end of file diff --git a/app/partials/views/modules/list-filters-kanban.jade b/app/partials/views/modules/list-filters-kanban.jade new file mode 100644 index 00000000..03dda696 --- /dev/null +++ b/app/partials/views/modules/list-filters-kanban.jade @@ -0,0 +1,23 @@ +section.list-filters + ul + li + a(href="#").active + span.icon.icon-filter + | SHOW FILTERS + + li + a(href="#") + span.icon.icon-tag + | SHOW TAGS + + li + a(href="#") + span.icon.icon-graph + | HIDE CFD GRAPH + + div.new-issue + a.button-green(href="") + span.text + | + NEW TASK + a.button-bulk(href="") + span.icon.icon-bulk \ No newline at end of file diff --git a/app/partials/views/modules/list-filters.jade b/app/partials/views/modules/list-filters.jade new file mode 100644 index 00000000..f3bd8b8d --- /dev/null +++ b/app/partials/views/modules/list-filters.jade @@ -0,0 +1,18 @@ +section.list-filters + ul + li + a(href="#").active + span.icon.icon-issues + | SHOW LIST + + li + a(href="#") + span.icon.icon-graph + | SHOW GRAPH + + div.new-issue + a.button-green(href="") + span.text + | + NEW ISSUE + a.button-bulk(href="") + span.icon.icon-bulk \ No newline at end of file diff --git a/app/partials/views/modules/search-in.jade b/app/partials/views/modules/search-in.jade index 5caa8f5f..9510a12f 100644 --- a/app/partials/views/modules/search-in.jade +++ b/app/partials/views/modules/search-in.jade @@ -1,4 +1,4 @@ -section.search +section.search-in header form fieldset diff --git a/app/partials/views/modules/sprints.jade b/app/partials/views/modules/sprints.jade index 553045d2..c0aaaf8f 100644 --- a/app/partials/views/modules/sprints.jade +++ b/app/partials/views/modules/sprints.jade @@ -4,8 +4,8 @@ section.sprints div.summary ul li - span.number 12 - span.description project
points + span.number(tg-bo-html="stats.total_milestones") -- + span.description
sprints div.new-sprint a.button-green(href="", title="Add New US") span.text + New sprint @@ -15,13 +15,13 @@ section.sprints div.sprint-summary a.icon.icon-arrow-up(href="", title="compact Sprint") span.sprint-name current sprint - span.sprint-date 04/06/14-20/06/14 + span.sprint-date ul li - span.number 12 + span.number(tg-bo-html="sprint.closed_points") -- span.description closed
points li - span.number 24 + span.number(tg-bo-html="sprint.total_points") -- span.description total
points div.sprint-progress-bar div.current-progress @@ -35,74 +35,3 @@ section.sprints a.button.button-gray(href="", tg-nav="project-taskboard:project=projectId,sprint=sprint.id", title="Current Sprint Taskboard") span Sprint Taskboard - - // If is current sprint - // section.sprint.sprint-current - // header - // div.sprint-summary - // a.icon.icon-arrow-up(href="", title="compact Sprint") - // span.sprint-name current sprint - // span.sprint-date 04/06/14-20/06/14 - // ul - // li - // span.number 12 - // span.description closed
points - // li - // span.number 24 - // span.description total
points - // div.sprint-progress-bar - // div.current-progress - // div.sprint-table - // - for (var x = 0; x < 10; x++) - // div.row - // div.column-us.width-8 - // a.us-name(href="", title="") #125 Crear el perfil de usuario Senior en el admin - // div.column-points.width-1 45 - // a.button.button-gray(href="", title="Current Sprint Taksboard") - // span Sprint Taskboard - - // // If Sprint is open but date is old - // section.sprint.sprint-old-open - // header - // div.sprint-summary - // a.icon.icon-arrow-up(href="", title="compact Sprint") - // span.sprint-name old open sprint - // span.sprint-date 04/05/14-03/06/14 - // ul - // li - // span.number 20 - // span.description closed
points - // li - // span.number 24 - // span.description total
points - // div.sprint-progress-bar - // div.current-progress - // div.sprint-table - // - for (var x = 0; x < 10; x++) - // div.row - // div.column-us.width-8 - // a(href="", title="") #125 Crear el perfil de usuario Senior en el admin - // div.column-points.width-1 45 - - // // If Sprint is closed and date is old - // section.sprint.sprint-closed - // header - // div.sprint-summary - // a.icon.icon-arrow-up(href="", title="compact Sprint") - // span.sprint-name old sprint - // span.sprint-date 04/04/14-03/05/14 - // ul - // li - // span.number 24 - // span.description closed
points - // li - // span.number 24 - // span.description total
points - // div.sprint-progress-bar - // div.current-progress - // div.sprint-table - // - for (var x = 0; x < 10; x++) - // div.row - // div.column-us.width-8 - // a(href="", title="") #125 Crear el perfil de usuario Senior en el admin - // div.column-points.width-1 45 diff --git a/app/styles/dependencies/forms.scss b/app/styles/dependencies/forms.scss index 8f6eca64..9fa008eb 100644 --- a/app/styles/dependencies/forms.scss +++ b/app/styles/dependencies/forms.scss @@ -4,12 +4,6 @@ fieldset { padding: 0; position: relative; width: 100%; - // xavi pleeeeeease - // .icon { - // position: absolute; - // right: 10px; - // top: 6px; - // } } input[type="text"], diff --git a/app/styles/layout/admin-membership.scss b/app/styles/layout/admin-membership.scss new file mode 100644 index 00000000..5f93feb7 --- /dev/null +++ b/app/styles/layout/admin-membership.scss @@ -0,0 +1,13 @@ +.admin-membership { + header { + @include clearfix; + margin-bottom: 1rem; + h1 { + float: left; + margin-bottom: 0; + } + a { + float: right; + } + } +} diff --git a/app/styles/layout/kanban.scss b/app/styles/layout/kanban.scss new file mode 100644 index 00000000..d3fb9ed0 --- /dev/null +++ b/app/styles/layout/kanban.scss @@ -0,0 +1,8 @@ +.kanban { + .burndown-container { + display: none; + } + .list-filters { + margin-bottom: 1rem; + } +} diff --git a/app/styles/main.scss b/app/styles/main.scss index 918c0a85..3bbfc4e7 100755 --- a/app/styles/main.scss +++ b/app/styles/main.scss @@ -35,11 +35,15 @@ $prefix-for-spec: true; @import 'modules/taskboard-table'; @import 'modules/search-filter'; @import 'modules/search-result-table'; +@import 'modules/search-in'; +@import 'modules/issues-table'; +@import 'modules/list-filters'; +@import 'modules/filter-tags'; @import 'modules/admin-menu'; @import 'modules/admin-submenu'; -@import 'modules/admin-membership'; @import 'modules/admin-roles'; @import 'modules/admin-functionalities'; +@import 'modules/admin-membership-table'; @import 'modules/category-config'; @import 'modules/project-details'; @import 'modules/attachments'; @@ -56,3 +60,5 @@ $prefix-for-spec: true; @import 'layout/backlog'; @import 'layout/taskboard'; @import 'layout/us-detail'; +@import 'layout/admin-membership'; +@import 'layout/kanban'; diff --git a/app/styles/modules/admin-membership.scss b/app/styles/modules/admin-membership-table.scss similarity index 90% rename from app/styles/modules/admin-membership.scss rename to app/styles/modules/admin-membership-table.scss index 17b75dd3..ac27d849 100644 --- a/app/styles/modules/admin-membership.scss +++ b/app/styles/modules/admin-membership-table.scss @@ -1,17 +1,3 @@ -.admin-membership { - header { - @include clearfix; - margin-bottom: 1rem; - h1 { - float: left; - margin-bottom: 0; - } - a { - float: right; - } - } -} - .admin-membership-table { align-content: stretch; align-items: center; diff --git a/app/styles/modules/filter-tags.scss b/app/styles/modules/filter-tags.scss new file mode 100644 index 00000000..d640d9a7 --- /dev/null +++ b/app/styles/modules/filter-tags.scss @@ -0,0 +1,21 @@ +.filter-tags { + margin-top: 2rem; + .filter-tag { + color: $white; + cursor: pointer; + margin-bottom: 1rem; + opacity: .5; + padding: .5rem 1rem; + position: relative; + &.active { + opacity: 1; + } + } + .tag-count { + background: none repeat scroll 0 0 rgba(0, 0, 0, .3); + padding: .5rem 1rem; + position: absolute; + right: 0; + top: 0; + } +} diff --git a/app/styles/modules/issues-table.scss b/app/styles/modules/issues-table.scss new file mode 100644 index 00000000..7bef17dd --- /dev/null +++ b/app/styles/modules/issues-table.scss @@ -0,0 +1,70 @@ +.issues-table { + align-content: stretch; + align-items: center; + display: flex; + flex-direction: column; + flex-wrap: wrap; + justify-content: flex-start; + width: 100%; + .row { + align-content: stretch; + align-items: center; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: flex-start; + padding: 1rem 0; + text-align: left; + width: 100%; + @for $i from 1 through 8 { + .width-#{$i} { + flex-basis: 50px; + flex-grow: $i; + flex-shrink: 0; + } + } + &:hover { + background: lighten($green-taiga, 60%); + @include transition (background .2s ease-in); + } + } + .row-selected { + background: lighten($green-taiga, 60%); + @include transition (background .2s ease-in); + } + .title { + @extend %medium; + border-bottom: 1px solid $gray-light; + font-family: 'DroidSans-Bold'; + &:hover { + background: transparent; + } + } + .table-main { + @extend %small; + border-bottom: 1px solid $gray-light; + } + .avatar { + align-items: center; + display: flex; + img { + flex-basis: 35px; + } + figcaption { + margin-left: 1rem; + } + } + .level { + background-color: $gray-light; + border-radius: 9px; + height: 18px; + margin: 0 auto; + width: 18px; + } + .level-field { + text-align: center; + } + .subject { + padding-right: 1rem; + } +} diff --git a/app/styles/modules/list-filters.scss b/app/styles/modules/list-filters.scss new file mode 100644 index 00000000..c0913e1a --- /dev/null +++ b/app/styles/modules/list-filters.scss @@ -0,0 +1,29 @@ +.list-filters { + align-items: center; + background-color: $whitish; + display: flex; + justify-content: space-between; + padding: .5rem 1rem; + ul { + display: flex; + margin-bottom: 0; + } + li { + margin-right: 2rem; + a { + @extend %large; + font-family: 'ostrichSans'; + opacity: .4; + &.active, + &:hover { + @include transition (opacity .3s linear); + color: $blackish; + opacity: 1; + + } + } + .icon { + padding-right: .5rem; + } + } +} diff --git a/app/styles/modules/search-in.scss b/app/styles/modules/search-in.scss new file mode 100644 index 00000000..c035755a --- /dev/null +++ b/app/styles/modules/search-in.scss @@ -0,0 +1,7 @@ +.search-in { + .icon { + position: absolute; + right: 10px; + top: 6px; + } +} diff --git a/app/styles/modules/taskboard-table.scss b/app/styles/modules/taskboard-table.scss index e75994bf..1f1dcc42 100644 --- a/app/styles/modules/taskboard-table.scss +++ b/app/styles/modules/taskboard-table.scss @@ -18,6 +18,9 @@ margin: 0 .3rem; padding: .5rem 0; text-align: center; + &:first-child { + margin-left: 0; + } } } diff --git a/gulpfile.coffee b/gulpfile.coffee index c761bb0a..62cde8be 100644 --- a/gulpfile.coffee +++ b/gulpfile.coffee @@ -51,7 +51,8 @@ paths = { "app/vendor/angular-sanitize/angular-sanitize.js", "app/vendor/angular-animate/angular-animate.js", "app/vendor/i18next/i18next.js", - "app/js/Sortable.js" + "app/js/Sortable.js", + "app/vendor/moment/min/moment-with-langs.js" ] }