US #2127: Discover section [1]
parent
9566164031
commit
d19623b4d1
|
@ -0,0 +1,50 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover-home-order-by.controller.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
class DiscoverHomeOrderByController
|
||||||
|
@.$inject = [
|
||||||
|
'$translate'
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@translate) ->
|
||||||
|
@.is_open = false
|
||||||
|
|
||||||
|
@.texts = {
|
||||||
|
week: @translate.instant('DISCOVER.FILTERS.WEEK'),
|
||||||
|
month: @translate.instant('DISCOVER.FILTERS.MONTH'),
|
||||||
|
year: @translate.instant('DISCOVER.FILTERS.YEAR'),
|
||||||
|
all: @translate.instant('DISCOVER.FILTERS.ALL_TIME')
|
||||||
|
}
|
||||||
|
|
||||||
|
currentText: () ->
|
||||||
|
return @.texts[@.currentOrderBy]
|
||||||
|
|
||||||
|
open: () ->
|
||||||
|
@.is_open = true
|
||||||
|
|
||||||
|
close: () ->
|
||||||
|
@.is_open = false
|
||||||
|
|
||||||
|
orderBy: (type) ->
|
||||||
|
@.currentOrderBy = type
|
||||||
|
@.is_open = false
|
||||||
|
|
||||||
|
@.onChange({orderBy: @.currentOrderBy})
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").controller("DiscoverHomeOrderBy", DiscoverHomeOrderByController)
|
|
@ -0,0 +1,96 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover-home-order-by.controller.spec.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
describe "DiscoverHomeOrderBy", ->
|
||||||
|
$provide = null
|
||||||
|
$controller = null
|
||||||
|
mocks = {}
|
||||||
|
|
||||||
|
_mockTranslate = ->
|
||||||
|
mocks.translate = {
|
||||||
|
instant: sinon.stub()
|
||||||
|
}
|
||||||
|
|
||||||
|
$provide.value("$translate", mocks.translate)
|
||||||
|
|
||||||
|
_mocks = ->
|
||||||
|
module (_$provide_) ->
|
||||||
|
$provide = _$provide_
|
||||||
|
|
||||||
|
_mockTranslate()
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
_inject = ->
|
||||||
|
inject (_$controller_) ->
|
||||||
|
$controller = _$controller_
|
||||||
|
|
||||||
|
_setup = ->
|
||||||
|
_mocks()
|
||||||
|
_inject()
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaDiscover"
|
||||||
|
|
||||||
|
_setup()
|
||||||
|
|
||||||
|
it "get current search text", () ->
|
||||||
|
mocks.translate.instant.withArgs('DISCOVER.FILTERS.WEEK').returns('week')
|
||||||
|
mocks.translate.instant.withArgs('DISCOVER.FILTERS.MONTH').returns('month')
|
||||||
|
|
||||||
|
ctrl = $controller("DiscoverHomeOrderBy")
|
||||||
|
|
||||||
|
ctrl.currentOrderBy = 'week'
|
||||||
|
text = ctrl.currentText()
|
||||||
|
|
||||||
|
expect(text).to.be.equal('week')
|
||||||
|
|
||||||
|
ctrl.currentOrderBy = 'month'
|
||||||
|
text = ctrl.currentText()
|
||||||
|
|
||||||
|
expect(text).to.be.equal('month')
|
||||||
|
|
||||||
|
it "open", () ->
|
||||||
|
ctrl = $controller("DiscoverHomeOrderBy")
|
||||||
|
|
||||||
|
ctrl.is_open = false
|
||||||
|
|
||||||
|
ctrl.open()
|
||||||
|
|
||||||
|
expect(ctrl.is_open).to.be.true
|
||||||
|
|
||||||
|
it "close", () ->
|
||||||
|
ctrl = $controller("DiscoverHomeOrderBy")
|
||||||
|
|
||||||
|
ctrl.is_open = true
|
||||||
|
|
||||||
|
ctrl.close()
|
||||||
|
|
||||||
|
expect(ctrl.is_open).to.be.false
|
||||||
|
|
||||||
|
it "order by", () ->
|
||||||
|
ctrl = $controller("DiscoverHomeOrderBy")
|
||||||
|
ctrl.onChange = sinon.spy()
|
||||||
|
|
||||||
|
ctrl.orderBy('week')
|
||||||
|
|
||||||
|
|
||||||
|
expect(ctrl.currentOrderBy).to.be.equal('week')
|
||||||
|
expect(ctrl.is_open).to.be.false
|
||||||
|
expect(ctrl.onChange).to.have.been.calledWith({orderBy: 'week'})
|
|
@ -0,0 +1,37 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover-home-order-by.directive.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
DiscoverHomeOrderByDirective = () ->
|
||||||
|
link = (scope, el, attrs) ->
|
||||||
|
|
||||||
|
return {
|
||||||
|
controller: "DiscoverHomeOrderBy",
|
||||||
|
controllerAs: "vm",
|
||||||
|
bindToController: true,
|
||||||
|
templateUrl: "discover/components/discover-home-order-by/discover-home-order-by.html",
|
||||||
|
scope: {
|
||||||
|
currentOrderBy: "=orderBy",
|
||||||
|
onChange: "&"
|
||||||
|
},
|
||||||
|
link: link
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscoverHomeOrderByDirective.$inject = []
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").directive("tgDiscoverHomeOrderBy", DiscoverHomeOrderByDirective)
|
|
@ -0,0 +1,12 @@
|
||||||
|
.filter-highlighted(ng-mouseleave="vm.close()")
|
||||||
|
a.current-filter(
|
||||||
|
href="#"
|
||||||
|
ng-click="vm.open()"
|
||||||
|
) {{vm.currentText()}}
|
||||||
|
span.icon-arrow-bottom
|
||||||
|
|
||||||
|
ul.filter-list(ng-if="vm.is_open")
|
||||||
|
li(ng-click="vm.orderBy('week')") {{ 'DISCOVER.FILTERS.WEEK' | translate }}
|
||||||
|
li(ng-click="vm.orderBy('month')") {{ 'DISCOVER.FILTERS.MONTH' | translate }}
|
||||||
|
li(ng-click="vm.orderBy('year')") {{ 'DISCOVER.FILTERS.YEAR' | translate }}
|
||||||
|
li(ng-click="vm.orderBy('all')") {{ 'DISCOVER.FILTERS.ALL_TIME' | translate }}
|
|
@ -0,0 +1,36 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover-search-bar.controller.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
class DiscoverSearchBarController
|
||||||
|
@.$inject = [
|
||||||
|
'tgDiscoverProjectsService'
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@discoverProjectsService) ->
|
||||||
|
taiga.defineImmutableProperty @, 'projects', () => return @discoverProjectsService.projectsCount
|
||||||
|
|
||||||
|
@discoverProjectsService.fetchStats()
|
||||||
|
|
||||||
|
selectFilter: (filter) ->
|
||||||
|
@.onChange({filter: filter, q: @.q})
|
||||||
|
|
||||||
|
submitFilter: ->
|
||||||
|
@.onChange({filter: @.filter, q: @.q})
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").controller("DiscoverSearchBar", DiscoverSearchBarController)
|
|
@ -0,0 +1,72 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: doscover-search-bar.controller.spec.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
describe "DiscoverSearchBarController", ->
|
||||||
|
$provide = null
|
||||||
|
$controller = null
|
||||||
|
mocks = {}
|
||||||
|
|
||||||
|
_mockDiscoverProjectsService = ->
|
||||||
|
mocks.discoverProjectsService = {
|
||||||
|
fetchStats: sinon.spy()
|
||||||
|
}
|
||||||
|
|
||||||
|
$provide.value('tgDiscoverProjectsService', mocks.discoverProjectsService)
|
||||||
|
|
||||||
|
_inject = ->
|
||||||
|
inject (_$controller_) ->
|
||||||
|
$controller = _$controller_
|
||||||
|
|
||||||
|
_mocks = ->
|
||||||
|
module (_$provide_) ->
|
||||||
|
$provide = _$provide_
|
||||||
|
|
||||||
|
_mockDiscoverProjectsService()
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
_setup = ->
|
||||||
|
_inject()
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaDiscover"
|
||||||
|
|
||||||
|
_mocks()
|
||||||
|
_setup()
|
||||||
|
|
||||||
|
it "select filter", () ->
|
||||||
|
ctrl = $controller("DiscoverSearchBar")
|
||||||
|
ctrl.onChange = sinon.spy()
|
||||||
|
ctrl.q = 'query'
|
||||||
|
|
||||||
|
ctrl.selectFilter('text')
|
||||||
|
|
||||||
|
expect(mocks.discoverProjectsService.fetchStats).to.have.been.called;
|
||||||
|
expect(ctrl.onChange).to.have.been.calledWith(sinon.match({filter: 'text', q: 'query'}));
|
||||||
|
|
||||||
|
it "submit filter", () ->
|
||||||
|
ctrl = $controller("DiscoverSearchBar")
|
||||||
|
ctrl.filter = 'all'
|
||||||
|
ctrl.q = 'query'
|
||||||
|
ctrl.onChange = sinon.spy()
|
||||||
|
|
||||||
|
ctrl.submitFilter()
|
||||||
|
|
||||||
|
expect(mocks.discoverProjectsService.fetchStats).to.have.been.called;
|
||||||
|
expect(ctrl.onChange).to.have.been.calledWith(sinon.match({filter: 'all', q: 'query'}));
|
|
@ -0,0 +1,38 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover-search.directive.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
DiscoverSearchBarDirective = () ->
|
||||||
|
link = (scope, el, attrs, ctrl) ->
|
||||||
|
|
||||||
|
return {
|
||||||
|
controller: "DiscoverSearchBar",
|
||||||
|
controllerAs: "vm"
|
||||||
|
templateUrl: 'discover/components/discover-search-bar/discover-search-bar.html',
|
||||||
|
bindToController: true,
|
||||||
|
scope: {
|
||||||
|
q: "="
|
||||||
|
filter: "=",
|
||||||
|
onChange: "&"
|
||||||
|
},
|
||||||
|
link: link
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscoverSearchBarDirective.$inject = []
|
||||||
|
|
||||||
|
angular.module('taigaDiscover').directive('tgDiscoverSearchBar', DiscoverSearchBarDirective)
|
|
@ -0,0 +1,71 @@
|
||||||
|
div.discover-header
|
||||||
|
div.discover-header-inner
|
||||||
|
|
||||||
|
h1.title {{ 'DISCOVER.DISCOVER_TITLE' | translate }}
|
||||||
|
|
||||||
|
p.project-number(
|
||||||
|
ng-if="vm.projects",
|
||||||
|
translate="DISCOVER.DISCOVER_SUBTITLE",
|
||||||
|
translate-values="{ projects: '{{vm.projects}}'}"
|
||||||
|
translate-interpolation="messageformat"
|
||||||
|
)
|
||||||
|
|
||||||
|
form(ng-submit="vm.submitFilter()")
|
||||||
|
div.searchbox
|
||||||
|
input(
|
||||||
|
name="search"
|
||||||
|
type="text"
|
||||||
|
placeholder="{{ 'DISCOVER.SEARCH.INPUT_PLACEHOLDER' | translate }}"
|
||||||
|
ng-model="vm.q"
|
||||||
|
)
|
||||||
|
a.search-button(
|
||||||
|
ng-click="vm.submitFilter()"
|
||||||
|
href="#"
|
||||||
|
title="{{ 'DISCOVER.SEARCH.ACTION_TITLE' | translate }}"
|
||||||
|
)
|
||||||
|
include ../../../../svg/search.svg
|
||||||
|
|
||||||
|
fieldset.searchbox-filters(ng-if="vm.filter")
|
||||||
|
input(
|
||||||
|
type='radio'
|
||||||
|
id="filter-all"
|
||||||
|
name="filter-search"
|
||||||
|
)
|
||||||
|
label(
|
||||||
|
for="filter-all"
|
||||||
|
ng-click="vm.selectFilter('all')"
|
||||||
|
ng-class="{active: vm.filter == 'all'}",
|
||||||
|
) {{ 'DISCOVER.FILTERS.ALL' | translate }}
|
||||||
|
|
||||||
|
input(
|
||||||
|
type='radio'
|
||||||
|
id="filter-kanban"
|
||||||
|
name="filter-search"
|
||||||
|
)
|
||||||
|
label(
|
||||||
|
for="filter-kanban"
|
||||||
|
ng-class="{active: vm.filter == 'kanban'}",
|
||||||
|
ng-click="vm.selectFilter('kanban')"
|
||||||
|
) {{ 'DISCOVER.FILTERS.KANBAN' | translate }}
|
||||||
|
|
||||||
|
input(
|
||||||
|
type='radio'
|
||||||
|
id="filter-scrum"
|
||||||
|
name="filter-search"
|
||||||
|
)
|
||||||
|
label(
|
||||||
|
for="filter-scrum"
|
||||||
|
ng-class="{active: vm.filter == 'scrum'}",
|
||||||
|
ng-click="vm.selectFilter('scrum')"
|
||||||
|
) {{ 'DISCOVER.FILTERS.SCRUM' | translate }}
|
||||||
|
|
||||||
|
input(
|
||||||
|
type='radio'
|
||||||
|
id="filter-people"
|
||||||
|
name="filter-search"
|
||||||
|
)
|
||||||
|
label(
|
||||||
|
for="filter-people"
|
||||||
|
ng-class="{active: vm.filter == 'people'}",
|
||||||
|
ng-click="vm.selectFilter('people')"
|
||||||
|
) {{ 'DISCOVER.FILTERS.PEOPLE' | translate }}
|
|
@ -0,0 +1,54 @@
|
||||||
|
.discover-header {
|
||||||
|
background: url('../images/discover.png') repeat-x bottom left $whitish;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
padding: 1rem 1rem 2rem;
|
||||||
|
text-align: center;
|
||||||
|
.discover-header-inner {
|
||||||
|
@include centered;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
@extend %xxlarge;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.project-number {
|
||||||
|
@extend %light;
|
||||||
|
@extend %large;
|
||||||
|
color: $primary;
|
||||||
|
}
|
||||||
|
form {
|
||||||
|
margin: 0 30%;
|
||||||
|
position: relative;
|
||||||
|
@include breakpoint(tablet) {
|
||||||
|
margin: 0 .5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input[type="text"] {
|
||||||
|
background: $white;
|
||||||
|
border: 0;
|
||||||
|
padding: 1rem;
|
||||||
|
width: 100%;
|
||||||
|
&:focus {
|
||||||
|
outline-color: $primary-light;
|
||||||
|
}
|
||||||
|
&:-webkit-autofill {
|
||||||
|
background: rgba($primary-dark, .5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.search-button {
|
||||||
|
position: absolute;
|
||||||
|
right: 1rem;
|
||||||
|
top: 1rem;
|
||||||
|
&:hover {
|
||||||
|
svg {
|
||||||
|
fill: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
svg {
|
||||||
|
fill: $gray-light;
|
||||||
|
height: 1.5rem;
|
||||||
|
transition: all .2;
|
||||||
|
width: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover-search-list-header.controller.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
class DiscoverSearchListHeaderController
|
||||||
|
@.$inject = []
|
||||||
|
|
||||||
|
constructor: () ->
|
||||||
|
@.like_is_open = @.orderBy.indexOf('-total_fans') == 0
|
||||||
|
@.activity_is_open = @.orderBy.indexOf('-total_activity') == 0
|
||||||
|
|
||||||
|
openLike: () ->
|
||||||
|
@.like_is_open = true
|
||||||
|
@.activity_is_open = false
|
||||||
|
|
||||||
|
@.setOrderBy('-total_fans_last_week')
|
||||||
|
|
||||||
|
openActivity: () ->
|
||||||
|
@.activity_is_open = true
|
||||||
|
@.like_is_open = false
|
||||||
|
|
||||||
|
@.setOrderBy('-total_activity_last_week')
|
||||||
|
|
||||||
|
setOrderBy: (type = '') ->
|
||||||
|
if !type
|
||||||
|
@.like_is_open = false
|
||||||
|
@.activity_is_open = false
|
||||||
|
|
||||||
|
@.onChange({orderBy: type})
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").controller("DiscoverSearchListHeader", DiscoverSearchListHeaderController)
|
|
@ -0,0 +1,117 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover-search-list-header.controller.spec.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
describe "DiscoverSearchListHeader", ->
|
||||||
|
$provide = null
|
||||||
|
$controller = null
|
||||||
|
scope = null
|
||||||
|
|
||||||
|
_inject = ->
|
||||||
|
inject (_$controller_, $rootScope) ->
|
||||||
|
$controller = _$controller_
|
||||||
|
scope = $rootScope.$new()
|
||||||
|
|
||||||
|
_setup = ->
|
||||||
|
_inject()
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaDiscover"
|
||||||
|
|
||||||
|
_setup()
|
||||||
|
|
||||||
|
it "openLike", () ->
|
||||||
|
ctrl = $controller("DiscoverSearchListHeader", scope, {
|
||||||
|
orderBy: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl.like_is_open = false
|
||||||
|
ctrl.activity_is_open = true
|
||||||
|
ctrl.setOrderBy = sinon.spy()
|
||||||
|
|
||||||
|
ctrl.openLike()
|
||||||
|
|
||||||
|
expect(ctrl.like_is_open).to.be.true
|
||||||
|
expect(ctrl.activity_is_open).to.be.false
|
||||||
|
expect(ctrl.setOrderBy).have.been.calledWith('-total_fans_last_week')
|
||||||
|
|
||||||
|
it "openActivity", () ->
|
||||||
|
ctrl = $controller("DiscoverSearchListHeader", scope, {
|
||||||
|
orderBy: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl.activity_is_open = false
|
||||||
|
ctrl.like_is_open = true
|
||||||
|
ctrl.setOrderBy = sinon.spy()
|
||||||
|
|
||||||
|
ctrl.openActivity()
|
||||||
|
|
||||||
|
expect(ctrl.activity_is_open).to.be.true
|
||||||
|
expect(ctrl.like_is_open).to.be.false
|
||||||
|
expect(ctrl.setOrderBy).have.been.calledWith('-total_activity_last_week')
|
||||||
|
|
||||||
|
it "setOrderBy", () ->
|
||||||
|
ctrl = $controller("DiscoverSearchListHeader", scope, {
|
||||||
|
orderBy: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl.onChange = sinon.spy()
|
||||||
|
|
||||||
|
ctrl.setOrderBy("type1")
|
||||||
|
|
||||||
|
expect(ctrl.onChange).to.have.been.calledWith(sinon.match({orderBy: "type1"}))
|
||||||
|
|
||||||
|
it "setOrderBy falsy close the like or activity layer", () ->
|
||||||
|
ctrl = $controller("DiscoverSearchListHeader", scope, {
|
||||||
|
orderBy: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl.like_is_open = true
|
||||||
|
ctrl.activity_is_open = true
|
||||||
|
|
||||||
|
ctrl.onChange = sinon.spy()
|
||||||
|
|
||||||
|
ctrl.setOrderBy()
|
||||||
|
|
||||||
|
expect(ctrl.onChange).to.have.been.calledWith(sinon.match({orderBy: ''}))
|
||||||
|
expect(ctrl.like_is_open).to.be.false
|
||||||
|
expect(ctrl.activity_is_open).to.be.false
|
||||||
|
|
||||||
|
it "closed like & activity", () ->
|
||||||
|
ctrl = $controller("DiscoverSearchListHeader", scope, {
|
||||||
|
orderBy: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(ctrl.like_is_open).to.be.false
|
||||||
|
expect(ctrl.activity_is_open).to.be.false
|
||||||
|
|
||||||
|
it "open like", () ->
|
||||||
|
ctrl = $controller("DiscoverSearchListHeader", scope, {
|
||||||
|
orderBy: '-total_fans'
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(ctrl.like_is_open).to.be.true
|
||||||
|
expect(ctrl.activity_is_open).to.be.false
|
||||||
|
|
||||||
|
it "open activity", () ->
|
||||||
|
ctrl = $controller("DiscoverSearchListHeader", scope, {
|
||||||
|
orderBy: '-total_activity'
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(ctrl.like_is_open).to.be.false
|
||||||
|
expect(ctrl.activity_is_open).to.be.true
|
|
@ -0,0 +1,37 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover-search-list-header.directive.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
DiscoverSearchListHeaderDirective = () ->
|
||||||
|
link = (scope, el, attrs) ->
|
||||||
|
|
||||||
|
return {
|
||||||
|
controller: "DiscoverSearchListHeader",
|
||||||
|
controllerAs: "vm",
|
||||||
|
bindToController: true,
|
||||||
|
templateUrl: "discover/components/discover-search-list-header/discover-search-list-header.html",
|
||||||
|
scope: {
|
||||||
|
onChange: "&",
|
||||||
|
orderBy: "="
|
||||||
|
},
|
||||||
|
link: link
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscoverSearchListHeaderDirective.$inject = []
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").directive("tgDiscoverSearchListHeader", DiscoverSearchListHeaderDirective)
|
|
@ -0,0 +1,89 @@
|
||||||
|
.discover-results-header
|
||||||
|
.discover-results-header-inner
|
||||||
|
.title
|
||||||
|
include ../../../../svg/search.svg
|
||||||
|
h2 {{ 'DISCOVER.SEARCH.RESULTS' | translate }}
|
||||||
|
|
||||||
|
.filter-discover-search(ng-mouseleave="vm.toggleClose()")
|
||||||
|
a.discover-search-filter(
|
||||||
|
href="#"
|
||||||
|
ng-click="vm.openLike()"
|
||||||
|
ng-class="{active: vm.like_is_open}"
|
||||||
|
)
|
||||||
|
include ../../../../svg/like.svg
|
||||||
|
span {{ 'DISCOVER.MOST_LIKED' | translate }}
|
||||||
|
a.discover-search-filter(
|
||||||
|
href="#"
|
||||||
|
ng-click="vm.openActivity()"
|
||||||
|
ng-class="{active: vm.activity_is_open}"
|
||||||
|
)
|
||||||
|
include ../../../../svg/activity.svg
|
||||||
|
span {{ 'DISCOVER.MOST_ACTIVE' | translate }}
|
||||||
|
|
||||||
|
.discover-search-subfilter.most-liked-subfilter(ng-if="vm.like_is_open")
|
||||||
|
a.results(
|
||||||
|
ng-if="vm.orderBy"
|
||||||
|
title=""
|
||||||
|
href="#",
|
||||||
|
ng-click="vm.setOrderBy()"
|
||||||
|
) {{ 'DISCOVER.FILTERS.CLEAR' | translate }}
|
||||||
|
|
||||||
|
ul.filter-list
|
||||||
|
li
|
||||||
|
a(
|
||||||
|
ng-class="{active: vm.orderBy == '-total_fans_last_week'}",
|
||||||
|
href="#",
|
||||||
|
ng-click="vm.setOrderBy('-total_fans_last_week')"
|
||||||
|
) {{ 'DISCOVER.FILTERS.WEEK' | translate }}
|
||||||
|
li
|
||||||
|
a(
|
||||||
|
ng-class="{active: vm.orderBy == '-total_fans_last_month'}",
|
||||||
|
href="#",
|
||||||
|
ng-click="vm.setOrderBy('-total_fans_last_month')"
|
||||||
|
) {{ 'DISCOVER.FILTERS.MONTH' | translate }}
|
||||||
|
li
|
||||||
|
a(
|
||||||
|
ng-class="{active: vm.orderBy == '-total_fans_last_year'}",
|
||||||
|
href="#",
|
||||||
|
ng-click="vm.setOrderBy('-total_fans_last_year')"
|
||||||
|
) {{ 'DISCOVER.FILTERS.YEAR' | translate }}
|
||||||
|
li
|
||||||
|
a(
|
||||||
|
ng-class="{active: vm.orderBy == '-total_fans'}",
|
||||||
|
href="#",
|
||||||
|
ng-click="vm.setOrderBy('-total_fans')"
|
||||||
|
) {{ 'DISCOVER.FILTERS.ALL_TIME' | translate }}
|
||||||
|
|
||||||
|
.discover-search-subfilter.most-active-subfilter(ng-if="vm.activity_is_open")
|
||||||
|
a.results(
|
||||||
|
ng-if="vm.orderBy"
|
||||||
|
title=""
|
||||||
|
href="#",
|
||||||
|
ng-click="vm.setOrderBy()"
|
||||||
|
) {{ 'DISCOVER.FILTERS.CLEAR' | translate }}
|
||||||
|
|
||||||
|
ul.filter-list
|
||||||
|
li
|
||||||
|
a(
|
||||||
|
ng-class="{active: vm.orderBy == '-total_activity_last_week'}",
|
||||||
|
href="#",
|
||||||
|
ng-click="vm.setOrderBy('-total_activity_last_week')"
|
||||||
|
) {{ 'DISCOVER.FILTERS.WEEK' | translate }}
|
||||||
|
li
|
||||||
|
a(
|
||||||
|
ng-class="{active: vm.orderBy == '-total_activity_last_month'}",
|
||||||
|
href="#",
|
||||||
|
ng-click="vm.setOrderBy('-total_activity_last_month')"
|
||||||
|
) {{ 'DISCOVER.FILTERS.MONTH' | translate }}
|
||||||
|
li
|
||||||
|
a(
|
||||||
|
ng-class="{active: vm.orderBy == '-total_activity_last_year'}",
|
||||||
|
href="#",
|
||||||
|
ng-click="vm.setOrderBy('-total_activity_last_year')"
|
||||||
|
) {{ 'DISCOVER.FILTERS.YEAR' | translate }}
|
||||||
|
li
|
||||||
|
a(
|
||||||
|
ng-class="{active: vm.orderBy == '-total_activity'}",
|
||||||
|
href="#",
|
||||||
|
ng-click="vm.setOrderBy('-total_activity')"
|
||||||
|
) {{ 'DISCOVER.FILTERS.ALL_TIME' | translate }}
|
|
@ -0,0 +1,80 @@
|
||||||
|
.discover-results-header {
|
||||||
|
.discover-results-header-inner {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
svg {
|
||||||
|
@include svg-size(1.1rem);
|
||||||
|
fill: $gray-light;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
@extend %bold;
|
||||||
|
@extend %larger;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-discover-search {
|
||||||
|
.discover-search-filter {
|
||||||
|
margin-right: 1rem;
|
||||||
|
&.active {
|
||||||
|
color: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.discover-search-subfilter {
|
||||||
|
@include arrow('bottom', $whitish, $whitish, 1, 8);
|
||||||
|
align-items: center;
|
||||||
|
background: $whitish;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
position: relative;
|
||||||
|
&.most-liked-subfilter {
|
||||||
|
&::after,
|
||||||
|
&::before {
|
||||||
|
left: 85%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.most-active-subfilter {
|
||||||
|
&::after,
|
||||||
|
&::before {
|
||||||
|
left: 95%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.ng-enter {
|
||||||
|
animation: dropdownFade .2s;
|
||||||
|
}
|
||||||
|
.results {
|
||||||
|
@extend %small;
|
||||||
|
color: $red-light;
|
||||||
|
display: block;
|
||||||
|
padding: .5rem 1rem;
|
||||||
|
transition: all .2s;
|
||||||
|
&:hover {
|
||||||
|
color: $red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.filter-list {
|
||||||
|
display: flex;
|
||||||
|
margin: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
a {
|
||||||
|
display: block;
|
||||||
|
padding: .5rem 1rem;
|
||||||
|
transition: all .2s;
|
||||||
|
&:hover {
|
||||||
|
background: $gray-light;
|
||||||
|
color: currentColor;
|
||||||
|
}
|
||||||
|
&.active {
|
||||||
|
background: $primary-light;
|
||||||
|
color: $whitish;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: featured-projects.controller.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
class FeaturedProjectsController
|
||||||
|
@.$inject = [
|
||||||
|
"tgDiscoverProjectsService"
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@discoverProjectsService) ->
|
||||||
|
taiga.defineImmutableProperty @, "featured", () => return @discoverProjectsService.featured
|
||||||
|
|
||||||
|
@discoverProjectsService.fetchFeatured()
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").controller("FeaturedProjects", FeaturedProjectsController)
|
|
@ -0,0 +1,33 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: featured-projects.directive.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
FeaturedProjectsDirective = () ->
|
||||||
|
link = (scope, el, attrs) ->
|
||||||
|
|
||||||
|
return {
|
||||||
|
controller: "FeaturedProjects"
|
||||||
|
controllerAs: "vm",
|
||||||
|
templateUrl: "discover/components/featured-projects/featured-projects.html",
|
||||||
|
scope: {},
|
||||||
|
link: link
|
||||||
|
}
|
||||||
|
|
||||||
|
FeaturedProjectsDirective.$inject = []
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").directive("tgFeaturedProjects", FeaturedProjectsDirective)
|
|
@ -0,0 +1,52 @@
|
||||||
|
.featured-projects(ng-if="vm.featured.size")
|
||||||
|
h1.title {{ 'DISCOVER.FEATURED' | translate }}
|
||||||
|
|
||||||
|
.featured-projects-inner
|
||||||
|
.featured-project(tg-repeat="project in vm.featured track by project.get('id')")
|
||||||
|
.tags-container
|
||||||
|
.project-tag(
|
||||||
|
style="background: {{tag.get('color')}}"
|
||||||
|
title="{{tag.get('name')}}"
|
||||||
|
tg-repeat="tag in project.get('colorized_tags') track by tag.get('name')"
|
||||||
|
)
|
||||||
|
.project-card-inner
|
||||||
|
.project-card-header
|
||||||
|
a.project-card-logo(
|
||||||
|
href="#"
|
||||||
|
tg-nav="project:project=project.get('slug')"
|
||||||
|
title="{{::project.get('name')}}"
|
||||||
|
)
|
||||||
|
img(
|
||||||
|
tg-project-logo-src="::project"
|
||||||
|
alt="{{::project.get('name')}}"
|
||||||
|
)
|
||||||
|
h2.project-card-name
|
||||||
|
a(
|
||||||
|
href="#"
|
||||||
|
tg-nav="project:project=project.get('slug')"
|
||||||
|
title="{{::project.get('name')}}"
|
||||||
|
) {{::project.get('name')}}
|
||||||
|
span.look-for-people(
|
||||||
|
ng-if="project.get('is_looking_for_people')"
|
||||||
|
title="{{ ::project.get('looking_for_people_note') }}"
|
||||||
|
)
|
||||||
|
include ../../../../svg/recruit.svg
|
||||||
|
p.project-card-description {{ ::project.get('description') | limitTo:100 }}{{ ::project.get('description').length < 100 ? '' : '...'}}
|
||||||
|
.project-card-statistics
|
||||||
|
span.statistic(
|
||||||
|
ng-class="{'active': project.get('is_fan')}"
|
||||||
|
title="{{ 'PROJECT.FANS_COUNTER_TITLE'|translate:{total:project.get('total_fans')||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
include ../../../../svg/like.svg
|
||||||
|
span {{::project.get('total_fans')}}
|
||||||
|
span.statistic(
|
||||||
|
ng-class="{'active': project.get('is_watcher')}"
|
||||||
|
title="{{ 'PROJECT.WATCHERS_COUNTER_TITLE'|translate:{total:project.get('total_watchers')||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
include ../../../../svg/eye.svg
|
||||||
|
span {{::project.get('total_watchers')}}
|
||||||
|
span.statistic(
|
||||||
|
title="{{ 'PROJECT.MEMBERS_COUNTER_TITLE'|translate:{total:project.get('members').size||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
include ../../../../svg/team.svg
|
||||||
|
span.statistics-num {{ ::project.get('members').size }}
|
|
@ -0,0 +1,29 @@
|
||||||
|
@import '../../../../styles/dependencies/mixins/project-card';
|
||||||
|
|
||||||
|
.featured-projects {
|
||||||
|
@include centered;
|
||||||
|
.title {
|
||||||
|
@extend %bold;
|
||||||
|
@extend %larger;
|
||||||
|
color: $grayer;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.featured-projects-inner {
|
||||||
|
align-items: stretch;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.featured-project {
|
||||||
|
@include project-card;
|
||||||
|
display: flex;
|
||||||
|
flex-basis: 23%;
|
||||||
|
@include breakpoint(tablet) {
|
||||||
|
flex-basis: 45%;
|
||||||
|
}
|
||||||
|
@include breakpoint(mobile) {
|
||||||
|
flex-basis: 100%;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: highlighted.directive.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
HighlightedDirective = () ->
|
||||||
|
return {
|
||||||
|
templateUrl: "discover/components/highlighted/highlighted.html",
|
||||||
|
scope: {
|
||||||
|
loading: "=",
|
||||||
|
highlighted: "=",
|
||||||
|
orderBy: "="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HighlightedDirective.$inject = []
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").directive("tgHighlighted", HighlightedDirective)
|
|
@ -0,0 +1,57 @@
|
||||||
|
.highlighted-projects-container
|
||||||
|
.loading-container(
|
||||||
|
tg-loading="loading"
|
||||||
|
ng-show="loading"
|
||||||
|
)
|
||||||
|
.highlighted-project(
|
||||||
|
tg-repeat="project in highlighted track by project.get('id')"
|
||||||
|
ng-if="!loading"
|
||||||
|
)
|
||||||
|
a.project-logo(
|
||||||
|
href="#"
|
||||||
|
tg-nav="project:project=project.get('slug')"
|
||||||
|
title="{{::project.get('name')}}"
|
||||||
|
)
|
||||||
|
img(
|
||||||
|
tg-project-logo-src="::project"
|
||||||
|
alt="{{::project.get('name')}}"
|
||||||
|
)
|
||||||
|
.project-data-container
|
||||||
|
.single-project-header
|
||||||
|
h2.project-title
|
||||||
|
a(
|
||||||
|
href="#"
|
||||||
|
tg-nav="project:project=project.get('slug')"
|
||||||
|
title="{{::project.get('name')}}"
|
||||||
|
) {{::project.get('name')}}
|
||||||
|
span.look-for-people(
|
||||||
|
ng-if="project.get('is_looking_for_people')"
|
||||||
|
title="{{ ::project.get('looking_for_people_note') }}"
|
||||||
|
)
|
||||||
|
include ../../../../svg/recruit.svg
|
||||||
|
.project-statistics
|
||||||
|
span.statistic(
|
||||||
|
ng-class="{'active': project.get('is_fan')}"
|
||||||
|
title="{{ 'PROJECT.FANS_COUNTER_TITLE'|translate:{total:project.get('total_fans')||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
include ../../../../svg/like.svg
|
||||||
|
span {{::project.get('total_fans')}}
|
||||||
|
span.statistic(
|
||||||
|
ng-class="{'active': project.get('is_watcher')}"
|
||||||
|
title="{{ 'PROJECT.WATCHERS_COUNTER_TITLE'|translate:{total:project.get('total_watchers')||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
include ../../../../svg/eye.svg
|
||||||
|
span {{::project.get('total_watchers')}}
|
||||||
|
span.statistic(
|
||||||
|
title="{{ 'PROJECT.MEMBERS_COUNTER_TITLE'|translate:{total:project.get('members').size||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
include ../../../../svg/team.svg
|
||||||
|
span.statistics-num {{ ::project.get('members').size }}
|
||||||
|
p.project-description {{ ::project.get('description') | limitTo:150 }}{{ ::project.get('description').length < 150 ? '' : '...'}}
|
||||||
|
|
||||||
|
a.view-more-projects.button-green(
|
||||||
|
ng-if="highlighted"
|
||||||
|
tg-nav="discover-search"
|
||||||
|
tg-nav-get-params="{\"order_by\": \"{{orderBy}}\"}"
|
||||||
|
href="#"
|
||||||
|
) {{ 'DISCOVER.VIEW_MORE' | translate }}
|
|
@ -0,0 +1,205 @@
|
||||||
|
.highlighted {
|
||||||
|
@include centered;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
@include breakpoint(tablet) {
|
||||||
|
flex-direction: column;
|
||||||
|
tg-most-active {
|
||||||
|
margin-top: 4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tg-most-liked,
|
||||||
|
tg-most-active {
|
||||||
|
align-content: stretch;
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
tg-most-liked {
|
||||||
|
margin-right: 8%;
|
||||||
|
@include breakpoint(tablet) {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.most-active,
|
||||||
|
.most-liked {
|
||||||
|
align-content: stretch;
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
svg {
|
||||||
|
@include svg-size(1.5rem);
|
||||||
|
fill: $gray-light;
|
||||||
|
margin: .5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.title-wrapper {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
@extend %bold;
|
||||||
|
@extend %larger;
|
||||||
|
color: $grayer;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
tg-highlighted {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.highlighted-projects-container {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
.loading-container {
|
||||||
|
margin-top: calc(50% - 1rem);
|
||||||
|
}
|
||||||
|
.loading-spinner {
|
||||||
|
display: block;
|
||||||
|
margin: 2rem auto;
|
||||||
|
max-height: 3rem;
|
||||||
|
max-width: 3rem;
|
||||||
|
}
|
||||||
|
.view-more-projects {
|
||||||
|
margin-top: auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.empty-highlighted-project {
|
||||||
|
border: 2px dashed $whitish;
|
||||||
|
padding: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
svg {
|
||||||
|
@include svg-size(2rem);
|
||||||
|
display: block;
|
||||||
|
fill: $gray-light;
|
||||||
|
margin: 1rem auto;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
@extend %light;
|
||||||
|
color: $gray;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.filter-highlighted {
|
||||||
|
position: relative;
|
||||||
|
.current-filter {
|
||||||
|
padding: 1rem;
|
||||||
|
span {
|
||||||
|
margin-left: .2rem;
|
||||||
|
position: relative;
|
||||||
|
top: .2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.filter-list {
|
||||||
|
background: $black;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 1.5rem;
|
||||||
|
&.ng-enter {
|
||||||
|
animation: dropdownFade .2s ease-in;
|
||||||
|
}
|
||||||
|
&.ng-leave {
|
||||||
|
animation: dropdownFade .2s ease-in;
|
||||||
|
animation-direction: reverse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
@extend %small;
|
||||||
|
color: $white;
|
||||||
|
cursor: pointer;
|
||||||
|
min-width: 8rem;
|
||||||
|
padding: .25rem .5rem;
|
||||||
|
&:hover {
|
||||||
|
background: rgba($primary-light, .4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlighted-project {
|
||||||
|
align-items: flex-start;
|
||||||
|
border-bottom: 1px solid $whitish;
|
||||||
|
display: flex;
|
||||||
|
flex-basis: 9rem;
|
||||||
|
min-height: 9rem;
|
||||||
|
padding: 1.5rem 0;
|
||||||
|
&:nth-last-child(-n+2) {
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
.project-logo {
|
||||||
|
flex-basis: 3rem;
|
||||||
|
height: auto;
|
||||||
|
margin-right: 1rem;
|
||||||
|
width: 3rem;
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.project-data-container {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.single-project-header {
|
||||||
|
align-content: center;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.project-title {
|
||||||
|
@extend %large;
|
||||||
|
@extend %text;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
a {
|
||||||
|
color: $primary;
|
||||||
|
&:hover {
|
||||||
|
color: $primary-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.look-for-people {
|
||||||
|
svg {
|
||||||
|
@include svg-size();
|
||||||
|
fill: $gray-light;
|
||||||
|
margin-left: .5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.project-description {
|
||||||
|
@extend %small;
|
||||||
|
color: $gray;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.project-statistics {
|
||||||
|
display: flex;
|
||||||
|
flex-basis: 140px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
svg {
|
||||||
|
@include svg-size(.8rem);
|
||||||
|
fill: $gray-light;
|
||||||
|
}
|
||||||
|
.svg-eye-closed {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.statistic {
|
||||||
|
@extend %small;
|
||||||
|
color: $gray-light;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: .5rem;
|
||||||
|
&.active {
|
||||||
|
color: $primary;
|
||||||
|
svg {
|
||||||
|
fill: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: most-active.controller.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
class MostActiveController
|
||||||
|
@.$inject = [
|
||||||
|
"tgDiscoverProjectsService"
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@discoverProjectsService) ->
|
||||||
|
taiga.defineImmutableProperty @, "highlighted", () => return @discoverProjectsService.mostActive
|
||||||
|
|
||||||
|
@.currentOrderBy = 'week'
|
||||||
|
@.order_by = @.getOrderBy()
|
||||||
|
|
||||||
|
fetch: () ->
|
||||||
|
@.loading = true
|
||||||
|
@.order_by = @.getOrderBy()
|
||||||
|
|
||||||
|
return @discoverProjectsService.fetchMostActive({order_by: @.order_by}).then () =>
|
||||||
|
@.loading = false
|
||||||
|
|
||||||
|
orderBy: (type) ->
|
||||||
|
@.currentOrderBy = type
|
||||||
|
|
||||||
|
@.fetch()
|
||||||
|
|
||||||
|
getOrderBy: (type) ->
|
||||||
|
if @.currentOrderBy == 'all'
|
||||||
|
return '-total_activity'
|
||||||
|
else
|
||||||
|
return '-total_activity_last_' + @.currentOrderBy
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").controller("MostActive", MostActiveController)
|
|
@ -0,0 +1,79 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: most-active.controller.spec.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
describe "MostActive", ->
|
||||||
|
$provide = null
|
||||||
|
$controller = null
|
||||||
|
mocks = {}
|
||||||
|
|
||||||
|
_mockDiscoverProjectsService = ->
|
||||||
|
mocks.discoverProjectsService = {
|
||||||
|
fetchMostActive: sinon.stub()
|
||||||
|
}
|
||||||
|
|
||||||
|
$provide.value("tgDiscoverProjectsService", mocks.discoverProjectsService)
|
||||||
|
|
||||||
|
_mocks = ->
|
||||||
|
module (_$provide_) ->
|
||||||
|
$provide = _$provide_
|
||||||
|
|
||||||
|
_mockDiscoverProjectsService()
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
_inject = ->
|
||||||
|
inject (_$controller_) ->
|
||||||
|
$controller = _$controller_
|
||||||
|
|
||||||
|
_setup = ->
|
||||||
|
_mocks()
|
||||||
|
_inject()
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaDiscover"
|
||||||
|
|
||||||
|
_setup()
|
||||||
|
|
||||||
|
it "fetch", (done) ->
|
||||||
|
ctrl = $controller("MostActive")
|
||||||
|
|
||||||
|
ctrl.getOrderBy = sinon.stub().returns('week')
|
||||||
|
|
||||||
|
mockPromise = mocks.discoverProjectsService.fetchMostActive.withArgs(sinon.match({order_by: 'week'})).promise()
|
||||||
|
|
||||||
|
promise = ctrl.fetch()
|
||||||
|
|
||||||
|
expect(ctrl.loading).to.be.true
|
||||||
|
|
||||||
|
mockPromise.resolve()
|
||||||
|
|
||||||
|
promise.finally () ->
|
||||||
|
expect(ctrl.loading).to.be.false
|
||||||
|
done()
|
||||||
|
|
||||||
|
|
||||||
|
it "order by", () ->
|
||||||
|
ctrl = $controller("MostActive")
|
||||||
|
|
||||||
|
ctrl.fetch = sinon.spy()
|
||||||
|
|
||||||
|
ctrl.orderBy('month')
|
||||||
|
|
||||||
|
expect(ctrl.fetch).to.have.been.called
|
||||||
|
expect(ctrl.currentOrderBy).to.be.equal('month')
|
|
@ -0,0 +1,34 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: most-active.directive.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
MostActiveDirective = () ->
|
||||||
|
link = (scope, el, attrs, ctrl) ->
|
||||||
|
ctrl.fetch()
|
||||||
|
|
||||||
|
return {
|
||||||
|
controller: "MostActive"
|
||||||
|
controllerAs: "vm",
|
||||||
|
templateUrl: "discover/components/most-active/most-active.html",
|
||||||
|
scope: {},
|
||||||
|
link: link
|
||||||
|
}
|
||||||
|
|
||||||
|
MostActiveDirective.$inject = []
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").directive("tgMostActive", MostActiveDirective)
|
|
@ -0,0 +1,18 @@
|
||||||
|
.most-active(ng-if="vm.highlighted.size")
|
||||||
|
.header
|
||||||
|
.title-wrapper
|
||||||
|
include ../../../../svg/activity.svg
|
||||||
|
h1.title {{ 'DISCOVER.MOST_ACTIVE' | translate }}
|
||||||
|
tg-discover-home-order-by(on-change="vm.orderBy(orderBy)", order-by="vm.currentOrderBy")
|
||||||
|
|
||||||
|
tg-highlighted(
|
||||||
|
loading="vm.loading",
|
||||||
|
highlighted="vm.highlighted"
|
||||||
|
order-by="vm.order_by"
|
||||||
|
)
|
||||||
|
|
||||||
|
.empty-highlighted-project(
|
||||||
|
ng-if="!vm.highlighted.size"
|
||||||
|
)
|
||||||
|
include ../../../../svg/activity.svg
|
||||||
|
span {{ 'DISCOVER.MOST_ACTIVE_EMPTY' | translate }}
|
|
@ -0,0 +1,49 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: msot-liked.controller.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
class MostLikedController
|
||||||
|
@.$inject = [
|
||||||
|
"tgDiscoverProjectsService"
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@discoverProjectsService) ->
|
||||||
|
taiga.defineImmutableProperty @, "highlighted", () => return @discoverProjectsService.mostLiked
|
||||||
|
|
||||||
|
@.currentOrderBy = 'week'
|
||||||
|
@.order_by = @.getOrderBy()
|
||||||
|
|
||||||
|
fetch: () ->
|
||||||
|
@.loading = true
|
||||||
|
@.order_by = @.getOrderBy()
|
||||||
|
|
||||||
|
@discoverProjectsService.fetchMostLiked({order_by: @.order_by}).then () =>
|
||||||
|
@.loading = false
|
||||||
|
|
||||||
|
orderBy: (type) ->
|
||||||
|
@.currentOrderBy = type
|
||||||
|
|
||||||
|
@.fetch()
|
||||||
|
|
||||||
|
getOrderBy: () ->
|
||||||
|
if @.currentOrderBy == 'all'
|
||||||
|
return '-total_fans'
|
||||||
|
else
|
||||||
|
return '-total_fans_last_' + @.currentOrderBy
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").controller("MostLiked", MostLikedController)
|
|
@ -0,0 +1,79 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: most-liked.controller.spec.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
describe "MostLiked", ->
|
||||||
|
$provide = null
|
||||||
|
$controller = null
|
||||||
|
mocks = {}
|
||||||
|
|
||||||
|
_mockDiscoverProjectsService = ->
|
||||||
|
mocks.discoverProjectsService = {
|
||||||
|
fetchMostLiked: sinon.stub()
|
||||||
|
}
|
||||||
|
|
||||||
|
$provide.value("tgDiscoverProjectsService", mocks.discoverProjectsService)
|
||||||
|
|
||||||
|
_mocks = ->
|
||||||
|
module (_$provide_) ->
|
||||||
|
$provide = _$provide_
|
||||||
|
|
||||||
|
_mockDiscoverProjectsService()
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
_inject = ->
|
||||||
|
inject (_$controller_) ->
|
||||||
|
$controller = _$controller_
|
||||||
|
|
||||||
|
_setup = ->
|
||||||
|
_mocks()
|
||||||
|
_inject()
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaDiscover"
|
||||||
|
|
||||||
|
_setup()
|
||||||
|
|
||||||
|
it "fetch", (done) ->
|
||||||
|
ctrl = $controller("MostLiked")
|
||||||
|
|
||||||
|
ctrl.getOrderBy = sinon.stub().returns('week')
|
||||||
|
|
||||||
|
mockPromise = mocks.discoverProjectsService.fetchMostLiked.withArgs(sinon.match({order_by: 'week'})).promise()
|
||||||
|
|
||||||
|
promise = ctrl.fetch()
|
||||||
|
|
||||||
|
expect(ctrl.loading).to.be.true
|
||||||
|
|
||||||
|
mockPromise.resolve()
|
||||||
|
|
||||||
|
promise.finally () ->
|
||||||
|
expect(ctrl.loading).to.be.false
|
||||||
|
done()
|
||||||
|
|
||||||
|
|
||||||
|
it "order by", () ->
|
||||||
|
ctrl = $controller("MostLiked")
|
||||||
|
|
||||||
|
ctrl.fetch = sinon.spy()
|
||||||
|
|
||||||
|
ctrl.orderBy('month')
|
||||||
|
|
||||||
|
expect(ctrl.fetch).to.have.been.called
|
||||||
|
expect(ctrl.currentOrderBy).to.be.equal('month')
|
|
@ -0,0 +1,34 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: most-liked.directive.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
MostLikedDirective = () ->
|
||||||
|
link = (scope, el, attrs, ctrl) ->
|
||||||
|
ctrl.fetch()
|
||||||
|
|
||||||
|
return {
|
||||||
|
controller: "MostLiked"
|
||||||
|
controllerAs: "vm",
|
||||||
|
templateUrl: "discover/components/most-liked/most-liked.html",
|
||||||
|
scope: {},
|
||||||
|
link: link
|
||||||
|
}
|
||||||
|
|
||||||
|
MostLikedDirective.$inject = []
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").directive("tgMostLiked", MostLikedDirective)
|
|
@ -0,0 +1,17 @@
|
||||||
|
.most-liked(ng-if="vm.highlighted.size")
|
||||||
|
.header
|
||||||
|
.title-wrapper
|
||||||
|
include ../../../../svg/like.svg
|
||||||
|
h1.title {{ 'DISCOVER.MOST_LIKED' | translate }}
|
||||||
|
tg-discover-home-order-by(on-change="vm.orderBy(orderBy)", order-by="vm.currentOrderBy")
|
||||||
|
tg-highlighted(
|
||||||
|
loading="vm.loading",
|
||||||
|
highlighted="vm.highlighted"
|
||||||
|
order-by="vm.order_by"
|
||||||
|
)
|
||||||
|
|
||||||
|
.empty-highlighted-project(
|
||||||
|
ng-if="!vm.highlighted.size"
|
||||||
|
)
|
||||||
|
include ../../../../svg/like.svg
|
||||||
|
span {{ 'DISCOVER.MOST_LIKED_EMPTY' | translate }}
|
|
@ -0,0 +1,33 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover-home.controller.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
class DiscoverHomeController
|
||||||
|
@.$inject = [
|
||||||
|
'$tgLocation',
|
||||||
|
'$tgNavUrls'
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@location, @navUrls) ->
|
||||||
|
|
||||||
|
onSubmit: (q) ->
|
||||||
|
url = @navUrls.resolve('discover-search')
|
||||||
|
|
||||||
|
@location.search('text', q).path(url)
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").controller("DiscoverHome", DiscoverHomeController)
|
|
@ -0,0 +1,71 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: doscover-home.controller.spec.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
describe "DiscoverHomeController", ->
|
||||||
|
$provide = null
|
||||||
|
$controller = null
|
||||||
|
mocks = {}
|
||||||
|
|
||||||
|
_mockLocation = ->
|
||||||
|
mocks.location = {}
|
||||||
|
|
||||||
|
$provide.value('$tgLocation', mocks.location)
|
||||||
|
|
||||||
|
_mockNavUrls = ->
|
||||||
|
mocks.navUrls = {}
|
||||||
|
|
||||||
|
$provide.value('$tgNavUrls', mocks.navUrls)
|
||||||
|
|
||||||
|
_inject = ->
|
||||||
|
inject (_$controller_) ->
|
||||||
|
$controller = _$controller_
|
||||||
|
|
||||||
|
_mocks = ->
|
||||||
|
module (_$provide_) ->
|
||||||
|
$provide = _$provide_
|
||||||
|
|
||||||
|
_mockLocation()
|
||||||
|
_mockNavUrls()
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
_setup = ->
|
||||||
|
_inject()
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaDiscover"
|
||||||
|
|
||||||
|
_mocks()
|
||||||
|
_setup()
|
||||||
|
|
||||||
|
it "onSubmit redirect to discover search", () ->
|
||||||
|
mocks.navUrls.resolve = sinon.stub().withArgs('discover-search').returns('url')
|
||||||
|
|
||||||
|
pathSpy = sinon.spy()
|
||||||
|
searchStub = {
|
||||||
|
path: pathSpy
|
||||||
|
}
|
||||||
|
|
||||||
|
mocks.location.search = sinon.stub().withArgs('text', 'query').returns(searchStub)
|
||||||
|
|
||||||
|
ctrl = $controller("DiscoverHome")
|
||||||
|
|
||||||
|
ctrl.onSubmit('query')
|
||||||
|
|
||||||
|
expect(pathSpy).to.have.been.calledWith('url');
|
|
@ -0,0 +1,12 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
|
section.discover
|
||||||
|
header
|
||||||
|
tg-discover-search-bar(on-change="vm.onSubmit(q)")
|
||||||
|
|
||||||
|
section.highlighted
|
||||||
|
tg-most-liked
|
||||||
|
tg-most-active
|
||||||
|
|
||||||
|
section.featured-projects
|
||||||
|
tg-featured-projects
|
|
@ -0,0 +1,114 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover-search.controller.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
class DiscoverSearchController
|
||||||
|
@.$inject = [
|
||||||
|
'$routeParams',
|
||||||
|
'tgDiscoverProjectsService',
|
||||||
|
'$route'
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@routeParams, @discoverProjectsService, @route) ->
|
||||||
|
@.page = 1
|
||||||
|
|
||||||
|
taiga.defineImmutableProperty @, "searchResult", () => return @discoverProjectsService.searchResult
|
||||||
|
taiga.defineImmutableProperty @, "nextSearchPage", () => return @discoverProjectsService.nextSearchPage
|
||||||
|
|
||||||
|
@.q = @routeParams.text
|
||||||
|
@.filter = @routeParams.filter || 'all'
|
||||||
|
@.orderBy = @routeParams['order_by'] || ''
|
||||||
|
|
||||||
|
@.loadingGlobal = false
|
||||||
|
@.loadingList = false
|
||||||
|
@.loadingPagination = false
|
||||||
|
|
||||||
|
fetch: () ->
|
||||||
|
@.page = 1
|
||||||
|
|
||||||
|
@discoverProjectsService.resetSearchList()
|
||||||
|
|
||||||
|
return @.search()
|
||||||
|
|
||||||
|
fetchByGlobalSearch: () ->
|
||||||
|
return if @.loadingGlobal
|
||||||
|
|
||||||
|
@.loadingGlobal = true
|
||||||
|
|
||||||
|
@.fetch().then () => @.loadingGlobal = false
|
||||||
|
|
||||||
|
fetchByOrderBy: () ->
|
||||||
|
return if @.loadingList
|
||||||
|
|
||||||
|
@.loadingList = true
|
||||||
|
|
||||||
|
@.fetch().then () => @.loadingList = false
|
||||||
|
|
||||||
|
showMore: () ->
|
||||||
|
return if @.loadingPagination
|
||||||
|
|
||||||
|
@.loadingPagination = true
|
||||||
|
|
||||||
|
@.page++
|
||||||
|
|
||||||
|
return @.search().then () => @.loadingPagination = false
|
||||||
|
|
||||||
|
search: () ->
|
||||||
|
filter = @.getFilter()
|
||||||
|
|
||||||
|
params = {
|
||||||
|
page: @.page,
|
||||||
|
q: @.q,
|
||||||
|
order_by: @.orderBy
|
||||||
|
}
|
||||||
|
|
||||||
|
_.assign(params, filter)
|
||||||
|
|
||||||
|
return @discoverProjectsService.fetchSearch(params)
|
||||||
|
|
||||||
|
getFilter: () ->
|
||||||
|
if @.filter == 'people'
|
||||||
|
return {is_looking_for_people: true}
|
||||||
|
else if @.filter == 'scrum'
|
||||||
|
return {is_backlog_activated: true}
|
||||||
|
else if @.filter == 'kanban'
|
||||||
|
return {is_kanban_activated: true}
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
onChangeFilter: (filter, q) ->
|
||||||
|
@.filter = filter
|
||||||
|
@.q = q
|
||||||
|
|
||||||
|
@route.updateParams({
|
||||||
|
filter: @.filter,
|
||||||
|
text: @.q
|
||||||
|
})
|
||||||
|
|
||||||
|
@.fetchByGlobalSearch()
|
||||||
|
|
||||||
|
onChangeOrder: (orderBy) ->
|
||||||
|
@.orderBy = orderBy
|
||||||
|
|
||||||
|
@route.updateParams({
|
||||||
|
order_by: orderBy
|
||||||
|
})
|
||||||
|
|
||||||
|
@.fetchByOrderBy()
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").controller("DiscoverSearch", DiscoverSearchController)
|
|
@ -0,0 +1,199 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover-search.controller.spec.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
describe "DiscoverSearch", ->
|
||||||
|
$provide = null
|
||||||
|
$controller = null
|
||||||
|
mocks = {}
|
||||||
|
|
||||||
|
_mockRouteParams = ->
|
||||||
|
mocks.routeParams = {}
|
||||||
|
|
||||||
|
$provide.value("$routeParams", mocks.routeParams)
|
||||||
|
|
||||||
|
_mockRoute = ->
|
||||||
|
mocks.route = {}
|
||||||
|
|
||||||
|
$provide.value("$route", mocks.route)
|
||||||
|
|
||||||
|
_mockDiscoverProjects = ->
|
||||||
|
mocks.discoverProjects = {
|
||||||
|
resetSearchList: sinon.spy(),
|
||||||
|
fetchSearch: sinon.stub()
|
||||||
|
}
|
||||||
|
|
||||||
|
mocks.discoverProjects.fetchSearch.promise().resolve()
|
||||||
|
|
||||||
|
$provide.value("tgDiscoverProjectsService", mocks.discoverProjects)
|
||||||
|
|
||||||
|
_mocks = ->
|
||||||
|
module (_$provide_) ->
|
||||||
|
$provide = _$provide_
|
||||||
|
|
||||||
|
_mockRoute()
|
||||||
|
_mockRouteParams()
|
||||||
|
_mockDiscoverProjects()
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
_inject = ->
|
||||||
|
inject (_$controller_) ->
|
||||||
|
$controller = _$controller_
|
||||||
|
|
||||||
|
_setup = ->
|
||||||
|
_mocks()
|
||||||
|
_inject()
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaDiscover"
|
||||||
|
|
||||||
|
_setup()
|
||||||
|
|
||||||
|
it "initialize search params", () ->
|
||||||
|
mocks.routeParams.text = 'text'
|
||||||
|
mocks.routeParams.filter = 'filter'
|
||||||
|
mocks.routeParams.order_by = 'order'
|
||||||
|
|
||||||
|
ctrl = $controller('DiscoverSearch')
|
||||||
|
|
||||||
|
expect(ctrl.q).to.be.equal('text')
|
||||||
|
expect(ctrl.filter).to.be.equal('filter')
|
||||||
|
expect(ctrl.orderBy).to.be.equal('order')
|
||||||
|
|
||||||
|
it "fetch", () ->
|
||||||
|
ctrl = $controller('DiscoverSearch')
|
||||||
|
|
||||||
|
ctrl.search = sinon.spy()
|
||||||
|
|
||||||
|
ctrl.fetch()
|
||||||
|
|
||||||
|
expect(mocks.discoverProjects.resetSearchList).to.have.been.called
|
||||||
|
expect(ctrl.search).to.have.been.called
|
||||||
|
expect(ctrl.page).to.be.equal(1)
|
||||||
|
|
||||||
|
it "showMore", (done) ->
|
||||||
|
ctrl = $controller('DiscoverSearch')
|
||||||
|
|
||||||
|
ctrl.search = sinon.stub().promise()
|
||||||
|
|
||||||
|
ctrl.showMore().then () ->
|
||||||
|
expect(ctrl.loadingPagination).to.be.false
|
||||||
|
|
||||||
|
done()
|
||||||
|
|
||||||
|
expect(ctrl.loadingPagination).to.be.true
|
||||||
|
expect(ctrl.search).to.have.been.called
|
||||||
|
expect(ctrl.page).to.be.equal(2)
|
||||||
|
|
||||||
|
ctrl.search.resolve()
|
||||||
|
|
||||||
|
it "search", () ->
|
||||||
|
mocks.discoverProjects.fetchSearch = sinon.stub()
|
||||||
|
|
||||||
|
filter = {
|
||||||
|
filter: '123'
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrl = $controller('DiscoverSearch')
|
||||||
|
|
||||||
|
ctrl.page = 1
|
||||||
|
ctrl.q = 'text'
|
||||||
|
ctrl.orderBy = 1
|
||||||
|
|
||||||
|
ctrl.getFilter = () -> return filter
|
||||||
|
|
||||||
|
params = {
|
||||||
|
filter: '123',
|
||||||
|
page: 1,
|
||||||
|
q: 'text',
|
||||||
|
order_by: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrl.search()
|
||||||
|
|
||||||
|
expect(mocks.discoverProjects.fetchSearch).have.been.calledWith(sinon.match(params))
|
||||||
|
|
||||||
|
it "get filter", () ->
|
||||||
|
ctrl = $controller('DiscoverSearch')
|
||||||
|
|
||||||
|
ctrl.filter = 'people'
|
||||||
|
expect(ctrl.getFilter()).to.be.eql({is_looking_for_people: true})
|
||||||
|
|
||||||
|
ctrl.filter = 'scrum'
|
||||||
|
expect(ctrl.getFilter()).to.be.eql({is_backlog_activated: true})
|
||||||
|
|
||||||
|
ctrl.filter = 'kanban'
|
||||||
|
expect(ctrl.getFilter()).to.be.eql({is_kanban_activated: true})
|
||||||
|
|
||||||
|
it "onChangeFilter", () ->
|
||||||
|
ctrl = $controller('DiscoverSearch')
|
||||||
|
|
||||||
|
mocks.route.updateParams = sinon.stub()
|
||||||
|
|
||||||
|
ctrl.fetchByGlobalSearch = sinon.spy()
|
||||||
|
|
||||||
|
ctrl.onChangeFilter('filter', 'query')
|
||||||
|
|
||||||
|
expect(ctrl.filter).to.be.equal('filter')
|
||||||
|
expect(ctrl.q).to.be.equal('query')
|
||||||
|
expect(ctrl.fetchByGlobalSearch).to.have.been.called
|
||||||
|
expect(mocks.route.updateParams).to.have.been.calledWith(sinon.match({filter: 'filter', text: 'query'}))
|
||||||
|
|
||||||
|
it "onChangeOrder", () ->
|
||||||
|
ctrl = $controller('DiscoverSearch')
|
||||||
|
|
||||||
|
mocks.route.updateParams = sinon.stub()
|
||||||
|
|
||||||
|
ctrl.fetchByOrderBy = sinon.spy()
|
||||||
|
|
||||||
|
ctrl.onChangeOrder('order-by')
|
||||||
|
|
||||||
|
expect(ctrl.orderBy).to.be.equal('order-by')
|
||||||
|
expect(ctrl.fetchByOrderBy).to.have.been.called
|
||||||
|
expect(mocks.route.updateParams).to.have.been.calledWith(sinon.match({order_by: 'order-by'}))
|
||||||
|
|
||||||
|
it "fetchByGlobalSearch", (done) ->
|
||||||
|
ctrl = $controller('DiscoverSearch')
|
||||||
|
|
||||||
|
ctrl.fetch = sinon.stub().promise()
|
||||||
|
|
||||||
|
ctrl.fetchByGlobalSearch().then () ->
|
||||||
|
expect(ctrl.loadingGlobal).to.be.false
|
||||||
|
|
||||||
|
done()
|
||||||
|
|
||||||
|
expect(ctrl.loadingGlobal).to.be.true
|
||||||
|
expect(ctrl.fetch).to.have.been.called
|
||||||
|
|
||||||
|
ctrl.fetch.resolve()
|
||||||
|
|
||||||
|
it "fetchByOrderBy", (done) ->
|
||||||
|
ctrl = $controller('DiscoverSearch')
|
||||||
|
|
||||||
|
ctrl.fetch = sinon.stub().promise()
|
||||||
|
|
||||||
|
ctrl.fetchByOrderBy().then () ->
|
||||||
|
expect(ctrl.loadingList).to.be.false
|
||||||
|
|
||||||
|
done()
|
||||||
|
|
||||||
|
expect(ctrl.loadingList).to.be.true
|
||||||
|
expect(ctrl.fetch).to.have.been.called
|
||||||
|
|
||||||
|
ctrl.fetch.resolve()
|
|
@ -0,0 +1,32 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2016 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover-search.directive.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
DiscoverSearchDirective = () ->
|
||||||
|
link = (scope, element, attrs, ctrl) ->
|
||||||
|
ctrl.fetch()
|
||||||
|
|
||||||
|
return {
|
||||||
|
controller: "DiscoverSearch",
|
||||||
|
controllerAs: "vm"
|
||||||
|
link: link
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscoverSearchDirective.$inject = []
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").directive("tgDiscoverSearch", DiscoverSearchDirective)
|
|
@ -0,0 +1,77 @@
|
||||||
|
div(tg-discover-search)
|
||||||
|
.discover-search
|
||||||
|
tg-discover-search-bar(
|
||||||
|
filter="vm.filter",
|
||||||
|
q="vm.q",
|
||||||
|
on-change="vm.onChangeFilter(filter, q)"
|
||||||
|
)
|
||||||
|
|
||||||
|
.empty-discover-results(ng-if="!vm.searchResult.size && !vm.loadingGlobal && !vm.loadingList")
|
||||||
|
img(
|
||||||
|
src="/#{v}/images/issues-empty.png",
|
||||||
|
alt="{{ DISCOVER.EMPTY | translate }}"
|
||||||
|
)
|
||||||
|
p.title(translate="DISCOVER.EMPTY")
|
||||||
|
|
||||||
|
.discover-results(ng-if="vm.searchResult.size || vm.loadingGlobal || vm.loadingList")
|
||||||
|
.spin(tg-loading="vm.loadingGlobal")
|
||||||
|
|
||||||
|
.discover-results-inner(ng-if="!vm.loadingGlobal")
|
||||||
|
tg-discover-search-list-header(
|
||||||
|
on-change="vm.onChangeOrder(orderBy)",
|
||||||
|
order-by="vm.orderBy"
|
||||||
|
)
|
||||||
|
|
||||||
|
.spin(ng-show="vm.loadingList", tg-loading="vm.loadingList")
|
||||||
|
|
||||||
|
ul.project-list(ng-if="!vm.loadingList && vm.searchResult.size")
|
||||||
|
li.list-itemtype-project(tg-repeat="project in vm.searchResult track by project.get('id')")
|
||||||
|
.list-itemtype-project-left
|
||||||
|
a.list-itemtype-project-image(
|
||||||
|
href="#"
|
||||||
|
tg-nav="project:project=project.get('slug')"
|
||||||
|
title="{{ ::project.get('name') }}"
|
||||||
|
)
|
||||||
|
img(
|
||||||
|
tg-project-logo-src="::project"
|
||||||
|
alt="{{::project.get('name')}}"
|
||||||
|
)
|
||||||
|
.list-itemtype-project-data
|
||||||
|
h2
|
||||||
|
a(
|
||||||
|
href="#"
|
||||||
|
tg-nav="project:project=project.get('slug')"
|
||||||
|
title="{{ ::project.get('name') }}"
|
||||||
|
) {{project.get('name')}}
|
||||||
|
span.look-for-people(
|
||||||
|
ng-if="project.get('is_looking_for_people')"
|
||||||
|
title="{{ ::project.get('looking_for_people_note') }}"
|
||||||
|
)
|
||||||
|
include ../../../svg/recruit.svg
|
||||||
|
p {{ ::project.get('description') | limitTo:300 }}
|
||||||
|
span(ng-if="::project.get('description').length > 300") ...
|
||||||
|
.list-itemtype-project-right.project-statistics
|
||||||
|
span.statistic(
|
||||||
|
ng-class="{'active': project.get('is_fan')}"
|
||||||
|
title="{{ 'PROJECT.FANS_COUNTER_TITLE'|translate:{total:project.get('total_fans')||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
include ../../../svg/like.svg
|
||||||
|
span {{::project.get('total_fans')}}
|
||||||
|
span.statistic(
|
||||||
|
ng-class="{'active': project.get('is_watcher')}"
|
||||||
|
title="{{ 'PROJECT.WATCHERS_COUNTER_TITLE'|translate:{total:project.get('total_watchers')||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
include ../../../svg/eye.svg
|
||||||
|
span {{::project.get('total_watchers')}}
|
||||||
|
span.statistic(
|
||||||
|
title="{{ 'PROJECT.MEMBERS_COUNTER_TITLE'|translate:{total:project.get('members').size||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
include ../../../svg/team.svg
|
||||||
|
span.statistics-num {{ ::project.get('members').size }}
|
||||||
|
|
||||||
|
a.button-green.more-results(
|
||||||
|
tg-loading="vm.loadingPagination"
|
||||||
|
href="#"
|
||||||
|
ng-click="vm.showMore()"
|
||||||
|
ng-if="vm.nextSearchPage"
|
||||||
|
) {{ 'DISCOVER.VIEW_MORE' | translate }}
|
|
@ -0,0 +1,131 @@
|
||||||
|
.discover-search {
|
||||||
|
.discover-header {
|
||||||
|
form {
|
||||||
|
margin: 0 8rem;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button {
|
||||||
|
left: 1rem;
|
||||||
|
right: auto;
|
||||||
|
}
|
||||||
|
.searchbox {
|
||||||
|
input {
|
||||||
|
padding-left: 3.5rem;
|
||||||
|
padding-right: 23rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.searchbox-filters {
|
||||||
|
position: absolute;
|
||||||
|
right: 1rem;
|
||||||
|
top: .7rem;
|
||||||
|
width: auto;
|
||||||
|
input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
border-radius: 4px;
|
||||||
|
color: $gray-light;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
padding: .4rem .75rem;
|
||||||
|
transition: all .2s;
|
||||||
|
transition-delay: .2s;
|
||||||
|
&.active {
|
||||||
|
background: $primary-light;
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background: $whitish;
|
||||||
|
color: $gray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.discover-results {
|
||||||
|
@include centered;
|
||||||
|
.discover-results-inner {
|
||||||
|
.spin {
|
||||||
|
margin-top: 4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.list-itemtype-project {
|
||||||
|
border-bottom: 1px solid $gray-light;
|
||||||
|
display: flex;
|
||||||
|
padding: 1rem 0;
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.list-itemtype-project-left {
|
||||||
|
align-items: flex-start;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.list-itemtype-project-image {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
.list-itemtype-project-data {
|
||||||
|
flex: 1;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.look-for-people {
|
||||||
|
margin-left: .5rem;
|
||||||
|
svg {
|
||||||
|
@include svg-size(1rem);
|
||||||
|
fill: $gray-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.project-statistics {
|
||||||
|
display: flex;
|
||||||
|
flex-basis: 140px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
svg {
|
||||||
|
@include svg-size(.8rem);
|
||||||
|
fill: $gray-light;
|
||||||
|
}
|
||||||
|
.svg-eye-closed {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.statistic {
|
||||||
|
@extend %small;
|
||||||
|
color: $gray-light;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: .5rem;
|
||||||
|
&.active {
|
||||||
|
color: $primary;
|
||||||
|
svg {
|
||||||
|
fill: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.more-results {
|
||||||
|
display: block;
|
||||||
|
margin: 0 20rem;
|
||||||
|
transition: inherit;
|
||||||
|
}
|
||||||
|
div[tg-loading] {
|
||||||
|
img {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-discover-results {
|
||||||
|
@include centered;
|
||||||
|
margin-top: 4rem;
|
||||||
|
text-align: center;
|
||||||
|
img {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
@extend %large;
|
||||||
|
@extend %light;
|
||||||
|
margin: 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover.module.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
module = angular.module("taigaDiscover", [])
|
|
@ -0,0 +1,93 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover-projects.service.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
taiga = @.taiga
|
||||||
|
|
||||||
|
class DiscoverProjectsService extends taiga.Service
|
||||||
|
@.$inject = [
|
||||||
|
"tgResources",
|
||||||
|
"tgProjectsService"
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@rs, @projectsService) ->
|
||||||
|
@._mostLiked = Immutable.List()
|
||||||
|
@._mostActive = Immutable.List()
|
||||||
|
@._featured = Immutable.List()
|
||||||
|
@._searchResult = Immutable.List()
|
||||||
|
@._projectsCount = 0
|
||||||
|
|
||||||
|
@.decorate = @projectsService._decorate.bind(@projectsService)
|
||||||
|
|
||||||
|
taiga.defineImmutableProperty @, "mostLiked", () => return @._mostLiked
|
||||||
|
taiga.defineImmutableProperty @, "mostActive", () => return @._mostActive
|
||||||
|
taiga.defineImmutableProperty @, "featured", () => return @._featured
|
||||||
|
taiga.defineImmutableProperty @, "searchResult", () => return @._searchResult
|
||||||
|
taiga.defineImmutableProperty @, "nextSearchPage", () => return @._nextSearchPage
|
||||||
|
taiga.defineImmutableProperty @, "projectsCount", () => return @._projectsCount
|
||||||
|
|
||||||
|
fetchMostLiked: (params) ->
|
||||||
|
return @rs.projects.getProjects(params, false)
|
||||||
|
.then (result) =>
|
||||||
|
data = result.data.slice(0, 5)
|
||||||
|
|
||||||
|
projects = Immutable.fromJS(data)
|
||||||
|
projects = projects.map(@.decorate)
|
||||||
|
|
||||||
|
@._mostLiked = projects
|
||||||
|
|
||||||
|
fetchMostActive: (params) ->
|
||||||
|
return @rs.projects.getProjects(params, false)
|
||||||
|
.then (result) =>
|
||||||
|
data = result.data.slice(0, 5)
|
||||||
|
|
||||||
|
projects = Immutable.fromJS(data)
|
||||||
|
projects = projects.map(@.decorate)
|
||||||
|
|
||||||
|
@._mostActive = projects
|
||||||
|
|
||||||
|
fetchFeatured: () ->
|
||||||
|
params = {is_featured: true}
|
||||||
|
|
||||||
|
return @rs.projects.getProjects(params, false)
|
||||||
|
.then (result) =>
|
||||||
|
data = result.data.slice(0, 4)
|
||||||
|
|
||||||
|
projects = Immutable.fromJS(data)
|
||||||
|
projects = projects.map(@.decorate)
|
||||||
|
|
||||||
|
@._featured = projects
|
||||||
|
|
||||||
|
resetSearchList: () ->
|
||||||
|
@._searchResult = Immutable.List()
|
||||||
|
|
||||||
|
fetchStats: () ->
|
||||||
|
return @rs.stats.discover().then (discover) =>
|
||||||
|
@._projectsCount = discover.getIn(['projects', 'total'])
|
||||||
|
|
||||||
|
fetchSearch: (params) ->
|
||||||
|
return @rs.projects.getProjects(params)
|
||||||
|
.then (result) =>
|
||||||
|
@._nextSearchPage = !!result.headers('X-Pagination-Next')
|
||||||
|
|
||||||
|
projects = Immutable.fromJS(result.data)
|
||||||
|
projects = projects.map(@.decorate)
|
||||||
|
|
||||||
|
@._searchResult = @._searchResult.concat(projects)
|
||||||
|
|
||||||
|
angular.module("taigaDiscover").service("tgDiscoverProjectsService", DiscoverProjectsService)
|
|
@ -0,0 +1,178 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: discover-projects.service.spec.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
describe "tgDiscoverProjectsService", ->
|
||||||
|
discoverProjectsService = provide = null
|
||||||
|
mocks = {}
|
||||||
|
|
||||||
|
_mockResources = () ->
|
||||||
|
mocks.resources = {
|
||||||
|
projects: {
|
||||||
|
getProjects: sinon.stub()
|
||||||
|
},
|
||||||
|
stats: {
|
||||||
|
discover: sinon.stub()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
provide.value "tgResources", mocks.resources
|
||||||
|
|
||||||
|
_mockProjectsService = () ->
|
||||||
|
mocks.projectsService = {
|
||||||
|
_decorate: (content) ->
|
||||||
|
return content.set('decorate', true)
|
||||||
|
}
|
||||||
|
|
||||||
|
provide.value "tgProjectsService", mocks.projectsService
|
||||||
|
|
||||||
|
_inject = (callback) ->
|
||||||
|
inject (_tgDiscoverProjectsService_) ->
|
||||||
|
discoverProjectsService = _tgDiscoverProjectsService_
|
||||||
|
callback() if callback
|
||||||
|
|
||||||
|
_mocks = () ->
|
||||||
|
module ($provide) ->
|
||||||
|
provide = $provide
|
||||||
|
_mockResources()
|
||||||
|
_mockProjectsService()
|
||||||
|
return null
|
||||||
|
|
||||||
|
_setup = ->
|
||||||
|
_mocks()
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaDiscover"
|
||||||
|
_setup()
|
||||||
|
_inject()
|
||||||
|
|
||||||
|
it "fetch most liked", (done) ->
|
||||||
|
params = {test: 1}
|
||||||
|
|
||||||
|
mocks.resources.projects.getProjects.withArgs(sinon.match(params), false).promise().resolve({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3},
|
||||||
|
{id: 4},
|
||||||
|
{id: 5},
|
||||||
|
{id: 6},
|
||||||
|
{id: 7}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
discoverProjectsService.fetchMostLiked(params).then () ->
|
||||||
|
result = discoverProjectsService._mostLiked.toJS()
|
||||||
|
|
||||||
|
expect(result).to.have.length(5)
|
||||||
|
expect(result[0].decorate).to.be.ok;
|
||||||
|
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "fetch most active", (done) ->
|
||||||
|
params = {test: 1}
|
||||||
|
|
||||||
|
mocks.resources.projects.getProjects.withArgs(sinon.match(params), false).promise().resolve({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3},
|
||||||
|
{id: 4},
|
||||||
|
{id: 5},
|
||||||
|
{id: 6},
|
||||||
|
{id: 7}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
discoverProjectsService.fetchMostActive(params).then () ->
|
||||||
|
result = discoverProjectsService._mostActive.toJS()
|
||||||
|
|
||||||
|
expect(result).to.have.length(5)
|
||||||
|
expect(result[0].decorate).to.be.ok;
|
||||||
|
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "fetch featured", (done) ->
|
||||||
|
mocks.resources.projects.getProjects.withArgs(sinon.match({is_featured: true}), false).promise().resolve({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3},
|
||||||
|
{id: 4},
|
||||||
|
{id: 5},
|
||||||
|
{id: 6},
|
||||||
|
{id: 7}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
discoverProjectsService.fetchFeatured().then () ->
|
||||||
|
result = discoverProjectsService._featured.toJS()
|
||||||
|
|
||||||
|
expect(result).to.have.length(4)
|
||||||
|
expect(result[0].decorate).to.be.ok;
|
||||||
|
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "reset search list", () ->
|
||||||
|
discoverProjectsService._searchResult = 'xxx'
|
||||||
|
|
||||||
|
discoverProjectsService.resetSearchList()
|
||||||
|
|
||||||
|
expect(discoverProjectsService._searchResult.size).to.be.equal(0)
|
||||||
|
|
||||||
|
it "fetch stats", (done) ->
|
||||||
|
mocks.resources.stats.discover.promise().resolve(Immutable.fromJS({
|
||||||
|
projects: {
|
||||||
|
total: 3
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
discoverProjectsService.fetchStats().then () ->
|
||||||
|
expect(discoverProjectsService._projectsCount).to.be.equal(3)
|
||||||
|
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "fetch search", (done) ->
|
||||||
|
params = {test: 1}
|
||||||
|
|
||||||
|
result = {
|
||||||
|
headers: sinon.stub(),
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
result.headers.withArgs('X-Pagination-Next').returns('next')
|
||||||
|
|
||||||
|
mocks.resources.projects.getProjects.withArgs(sinon.match(params)).promise().resolve(result)
|
||||||
|
|
||||||
|
discoverProjectsService._searchResult = Immutable.fromJS([
|
||||||
|
{id: 4},
|
||||||
|
{id: 5}
|
||||||
|
])
|
||||||
|
|
||||||
|
discoverProjectsService.fetchSearch(params).then () ->
|
||||||
|
result = discoverProjectsService._searchResult.toJS()
|
||||||
|
|
||||||
|
expect(result).to.have.length(5)
|
||||||
|
|
||||||
|
expect(result[4].decorate).to.be.ok;
|
||||||
|
|
||||||
|
done()
|
|
@ -0,0 +1,78 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: home.controller.spec.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
describe "HomeController", ->
|
||||||
|
homeCtrl = null
|
||||||
|
provide = null
|
||||||
|
controller = null
|
||||||
|
mocks = {}
|
||||||
|
|
||||||
|
_mockCurrentUserService = () ->
|
||||||
|
mocks.currentUserService = {
|
||||||
|
getUser: sinon.stub()
|
||||||
|
}
|
||||||
|
|
||||||
|
provide.value "tgCurrentUserService", mocks.currentUserService
|
||||||
|
|
||||||
|
_mockLocation = () ->
|
||||||
|
mocks.location = {
|
||||||
|
path: sinon.stub()
|
||||||
|
}
|
||||||
|
provide.value "$location", mocks.location
|
||||||
|
|
||||||
|
_mockTgNavUrls = () ->
|
||||||
|
mocks.tgNavUrls = {
|
||||||
|
resolve: sinon.stub()
|
||||||
|
}
|
||||||
|
|
||||||
|
provide.value "$tgNavUrls", mocks.tgNavUrls
|
||||||
|
|
||||||
|
_mocks = () ->
|
||||||
|
module ($provide) ->
|
||||||
|
provide = $provide
|
||||||
|
_mockCurrentUserService()
|
||||||
|
_mockLocation()
|
||||||
|
_mockTgNavUrls()
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaHome"
|
||||||
|
|
||||||
|
_mocks()
|
||||||
|
|
||||||
|
inject ($controller) ->
|
||||||
|
controller = $controller
|
||||||
|
|
||||||
|
it "anonymous home", () ->
|
||||||
|
homeCtrl = controller "Home",
|
||||||
|
$scope: {}
|
||||||
|
|
||||||
|
expect(mocks.tgNavUrls.resolve).to.be.calledWith("discover")
|
||||||
|
expect(mocks.location.path).to.be.calledOnce
|
||||||
|
|
||||||
|
it "non anonymous home", () ->
|
||||||
|
mocks.currentUserService = {
|
||||||
|
getUser: Immutable.fromJS({
|
||||||
|
id: 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(mocks.tgNavUrls.resolve).to.be.notCalled
|
||||||
|
expect(mocks.location.path).to.be.notCalled
|
|
@ -0,0 +1,32 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: home.controller.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
class HomeController
|
||||||
|
@.$inject = [
|
||||||
|
"tgCurrentUserService",
|
||||||
|
"$location",
|
||||||
|
"$tgNavUrls"
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@currentUserService, @location, @navUrls) ->
|
||||||
|
if not @currentUserService.getUser()
|
||||||
|
@location.path(@navUrls.resolve("discover"))
|
||||||
|
|
||||||
|
|
||||||
|
angular.module("taigaHome").controller("Home", HomeController)
|
|
@ -11,7 +11,7 @@
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
.title-bar {
|
.title-bar {
|
||||||
@extend %title;
|
@extend %light;
|
||||||
@extend %larger;
|
@extend %larger;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
background: $whitish;
|
background: $whitish;
|
||||||
|
|
|
@ -1,13 +1,59 @@
|
||||||
section.home-project-list(ng-if="vm.projects.size")
|
section.home-project-list(ng-if="vm.projects.size")
|
||||||
ul
|
|
||||||
li.home-project-list-single(tg-bind-scope, tg-repeat="project in vm.projects")
|
.home-project(tg-bind-scope, tg-repeat="project in vm.projects")
|
||||||
a(href="#", tg-nav="project:project=project.get('slug')")
|
.tags-container
|
||||||
h2.home-project-list-single-title
|
.project-tag(
|
||||||
span.project-name(title="{{ ::project.get('name') }}") {{::project.get('name')}}
|
style="background: {{tag.get('color')}}"
|
||||||
span.private(ng-if="project.get('is_private')", title="{{'PROJECT.PRIVATE' | translate}}")
|
title="{{tag.get('name')}}"
|
||||||
|
tg-repeat="tag in project.get('colorized_tags') track by tag.get('name')"
|
||||||
|
)
|
||||||
|
.project-card-inner(href="#", tg-nav="project:project=project.get('slug')")
|
||||||
|
.project-card-header
|
||||||
|
a.project-card-logo(
|
||||||
|
href="#"
|
||||||
|
tg-nav="project:project=project.get('slug')"
|
||||||
|
title="{{::project.get('name')}}"
|
||||||
|
)
|
||||||
|
img(
|
||||||
|
tg-project-logo-src="::project"
|
||||||
|
alt="{{::project.get('name')}}"
|
||||||
|
)
|
||||||
|
h2.project-card-name
|
||||||
|
a(
|
||||||
|
href="#"
|
||||||
|
tg-nav="project:project=project.get('slug')"
|
||||||
|
title="{{::project.get('name')}}"
|
||||||
|
) {{::project.get('name')}}
|
||||||
|
span.look-for-people(
|
||||||
|
ng-if="project.get('is_looking_for_people')"
|
||||||
|
title="{{ ::project.get('looking_for_people_note') }}"
|
||||||
|
)
|
||||||
|
include ../../../svg/recruit.svg
|
||||||
|
p.project-card-description {{::project.get('description')| limitTo:100 }}
|
||||||
|
span(ng-if="::project.get('description').length > 100") ...
|
||||||
|
.project-card-statistics
|
||||||
|
span.statistic(
|
||||||
|
ng-class="{'active': project.get('is_fan')}"
|
||||||
|
title="{{ 'PROJECT.FANS_COUNTER_TITLE'|translate:{total:project.get('total_fans')||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
include ../../../svg/like.svg
|
||||||
|
span {{::project.get('total_fans')}}
|
||||||
|
span.statistic(
|
||||||
|
ng-class="{'active': project.get('is_watcher')}"
|
||||||
|
title="{{ 'PROJECT.WATCHERS_COUNTER_TITLE'|translate:{total:project.get('total_watchers')||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
include ../../../svg/eye.svg
|
||||||
|
span {{::project.get('total_watchers')}}
|
||||||
|
span.statistic(
|
||||||
|
title="{{ 'PROJECT.MEMBERS_COUNTER_TITLE'|translate:{total:project.get('members').size||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
include ../../../svg/team.svg
|
||||||
|
span.statistics-num {{ ::project.get('members').size }}
|
||||||
|
span.statistic(
|
||||||
|
ng-if="::project.get('is_private')"
|
||||||
|
title="{{ 'PROJECT.PRIVATE' | translate }}"
|
||||||
|
)
|
||||||
include ../../../svg/lock.svg
|
include ../../../svg/lock.svg
|
||||||
p {{ ::project.get('description') | limitTo:150 }}
|
|
||||||
span(ng-if="::project.get('description').size > 150") ...
|
|
||||||
|
|
||||||
a.see-more-projects-btn.button-gray(
|
a.see-more-projects-btn.button-gray(
|
||||||
href="#",
|
href="#",
|
||||||
|
|
|
@ -1,52 +1,13 @@
|
||||||
.home-project-list {
|
@import '../../../styles/dependencies/mixins/project-card';
|
||||||
li {
|
|
||||||
border: 1px solid lighten($gray-light, 15%);
|
.home-project {
|
||||||
border-radius: 3px;
|
@include project-card;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-bottom: .75rem;
|
margin-bottom: 1rem;
|
||||||
padding: 1rem;
|
transition: .2s;
|
||||||
text-overflow: ellipsis;
|
transition-delay: .1s;
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: $primary-light;
|
border: 1px solid $primary-light;
|
||||||
transition: all .3s linear;
|
|
||||||
p {
|
|
||||||
color: $gray;
|
|
||||||
transition: color .3s linear;
|
|
||||||
}
|
|
||||||
.private path {
|
|
||||||
fill: $gray;
|
|
||||||
transition: fill .3s linear;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
min-height: 5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
@extend %text;
|
|
||||||
color: $gray;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
line-height: 1.3;
|
|
||||||
margin-bottom: .5rem;
|
|
||||||
text-transform: none;
|
|
||||||
.project-name {
|
|
||||||
display: inline-block;
|
|
||||||
max-width: 90%;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
vertical-align: middle;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
@extend %text;
|
|
||||||
@extend %xsmall;
|
|
||||||
color: $gray-light;
|
|
||||||
line-height: 125%;
|
|
||||||
margin: 0;
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,20 @@ pagination = () ->
|
||||||
Resource = (urlsService, http, paginateResponseService) ->
|
Resource = (urlsService, http, paginateResponseService) ->
|
||||||
service = {}
|
service = {}
|
||||||
|
|
||||||
|
service.getProjects = (params = {}, pagination = true) ->
|
||||||
|
url = urlsService.resolve("projects")
|
||||||
|
|
||||||
|
httpOptions = {}
|
||||||
|
|
||||||
|
if !pagination
|
||||||
|
httpOptions = {
|
||||||
|
headers: {
|
||||||
|
"x-disable-pagination": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return http.get(url, params, httpOptions)
|
||||||
|
|
||||||
service.getProjectBySlug = (projectSlug) ->
|
service.getProjectBySlug = (projectSlug) ->
|
||||||
url = urlsService.resolve("projects")
|
url = urlsService.resolve("projects")
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,8 @@ services = [
|
||||||
"tgTasksResource",
|
"tgTasksResource",
|
||||||
"tgIssuesResource",
|
"tgIssuesResource",
|
||||||
"tgExternalAppsResource",
|
"tgExternalAppsResource",
|
||||||
"tgAttachmentsResource"
|
"tgAttachmentsResource",
|
||||||
|
"tgStatsResource"
|
||||||
]
|
]
|
||||||
|
|
||||||
Resources = ($injector) ->
|
Resources = ($injector) ->
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: stats-resource.service.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
Resource = (urlsService, http) ->
|
||||||
|
service = {}
|
||||||
|
|
||||||
|
service.discover = (applicationId, state) ->
|
||||||
|
url = urlsService.resolve("stats-discover")
|
||||||
|
return http.get(url).then (result) ->
|
||||||
|
Immutable.fromJS(result.data)
|
||||||
|
|
||||||
|
return () ->
|
||||||
|
return {"stats": service}
|
||||||
|
|
||||||
|
Resource.$inject = ["$tgUrls", "$tgHttp"]
|
||||||
|
|
||||||
|
module = angular.module("taigaResources2")
|
||||||
|
module.factory("tgStatsResource", Resource)
|
|
@ -40,7 +40,8 @@ exports.config = {
|
||||||
kanban: "e2e/suites/kanban.e2e.js",
|
kanban: "e2e/suites/kanban.e2e.js",
|
||||||
projectHome: "e2e/suites/project-home.e2e.js",
|
projectHome: "e2e/suites/project-home.e2e.js",
|
||||||
search: "e2e/suites/search.e2e.js",
|
search: "e2e/suites/search.e2e.js",
|
||||||
team: "e2e/suites/team.e2e.js"
|
team: "e2e/suites/team.e2e.js",
|
||||||
|
discover: "e2e/suites/discover/*.e2e.js"
|
||||||
},
|
},
|
||||||
onPrepare: function() {
|
onPrepare: function() {
|
||||||
// track mouse movements
|
// track mouse movements
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
var utils = require('../utils');
|
||||||
|
|
||||||
|
var helper = module.exports;
|
||||||
|
|
||||||
|
helper.liked = function() {
|
||||||
|
return $('tg-most-liked');
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.active = function() {
|
||||||
|
return $('tg-most-active');
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.featured = function() {
|
||||||
|
return $('tg-featured-projects');
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.likedProjects = function() {
|
||||||
|
return helper.liked().$$('.highlighted-project');
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.activeProjects = function() {
|
||||||
|
return helper.active().$$('.highlighted-project');
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.featuredProjects = function() {
|
||||||
|
return helper.featured().$$('.featured-project');
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.rearrangeLike = function(index) {
|
||||||
|
helper.liked().$('.current-filter').click();
|
||||||
|
|
||||||
|
helper.liked().$$('.filter-list li').get(index).click();
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.getLikeFilterText = function(index) {
|
||||||
|
return helper.liked().$('.current-filter').getText();
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.rearrangeActive = function(index) {
|
||||||
|
helper.active().$('.current-filter').click();
|
||||||
|
|
||||||
|
helper.active().$$('.filter-list li').get(index).click();
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.getActiveFilterText = function(index) {
|
||||||
|
return helper.active().$('.current-filter').getText();
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.searchFilter = function(index) {
|
||||||
|
return $$('.searchbox-filters label').get(index).click();
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.searchProjectsList = function() {
|
||||||
|
return $('.project-list');
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.searchProjects = function() {
|
||||||
|
return helper.searchProjectsList().$$('li');
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.searchInput = function() {
|
||||||
|
return $('.searchbox input');
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.sendSearch = function() {
|
||||||
|
return $('.search-button').click();
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.mostLiked = function() {
|
||||||
|
$$('.discover-search-filter').get(0).click();
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.mostActived = function() {
|
||||||
|
$$('.discover-search-filter').get(1).click();
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.searchOrder = function(index) {
|
||||||
|
$$('.filter-list a').get(index).click();
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.orderSelectorWrapper = function() {
|
||||||
|
return $('.discover-search-subfilter');
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.clearOrder = function() {
|
||||||
|
helper.orderSelectorWrapper().$('.results a').click();
|
||||||
|
};
|
|
@ -0,0 +1,27 @@
|
||||||
|
var utils = require('../utils');
|
||||||
|
|
||||||
|
var helper = module.exports;
|
||||||
|
|
||||||
|
helper.lookingForPeople = function() {
|
||||||
|
return $$('.looking-for-people input').get(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.lookingForPeopleReason = function() {
|
||||||
|
return $$('.looking-for-people-reason input').get(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.toggleIsLookingForPeople = function() {
|
||||||
|
helper.lookingForPeople().click();
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.editLogo = function() {
|
||||||
|
let inputFile = $('#logo-field');
|
||||||
|
|
||||||
|
var fileToUpload = utils.common.uploadImagePath();
|
||||||
|
|
||||||
|
return utils.common.uploadFile(inputFile, fileToUpload);
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.getLogoSrc = function() {
|
||||||
|
return $('.image-container .image');
|
||||||
|
};
|
|
@ -6,6 +6,8 @@ var chaiAsPromised = require('chai-as-promised');
|
||||||
chai.use(chaiAsPromised);
|
chai.use(chaiAsPromised);
|
||||||
var expect = chai.expect;
|
var expect = chai.expect;
|
||||||
|
|
||||||
|
var adminHelper = require('../../../helpers/project-detail-helper');
|
||||||
|
|
||||||
describe('project detail', function() {
|
describe('project detail', function() {
|
||||||
before(async function(){
|
before(async function(){
|
||||||
browser.get(browser.params.glob.host + 'project/project-0/admin/project-profile/details');
|
browser.get(browser.params.glob.host + 'project/project-0/admin/project-profile/details');
|
||||||
|
@ -40,5 +42,40 @@ describe('project detail', function() {
|
||||||
$('button[type="submit"]').click();
|
$('button[type="submit"]').click();
|
||||||
|
|
||||||
expect(utils.notifications.success.open()).to.be.eventually.equal(true);
|
expect(utils.notifications.success.open()).to.be.eventually.equal(true);
|
||||||
|
|
||||||
|
await utils.notifications.success.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('looking for people', async function() {
|
||||||
|
let checked = !! await adminHelper.lookingForPeople().getAttribute('checked');
|
||||||
|
|
||||||
|
if(checked) {
|
||||||
|
adminHelper.toggleIsLookingForPeople();
|
||||||
|
}
|
||||||
|
|
||||||
|
adminHelper.toggleIsLookingForPeople();
|
||||||
|
|
||||||
|
adminHelper.lookingForPeopleReason().sendKeys('looking for people reason');
|
||||||
|
|
||||||
|
$('button[type="submit"]').click();
|
||||||
|
|
||||||
|
checked = !! await adminHelper.lookingForPeople().getAttribute('checked');
|
||||||
|
|
||||||
|
expect(checked).to.be.true;
|
||||||
|
expect(utils.notifications.success.open()).to.be.eventually.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('edit logo', async function() {
|
||||||
|
let imageContainer = $('.image-container');
|
||||||
|
|
||||||
|
let htmlChanges = await utils.common.outerHtmlChanges(imageContainer);
|
||||||
|
|
||||||
|
adminHelper.editLogo();
|
||||||
|
|
||||||
|
await htmlChanges();
|
||||||
|
|
||||||
|
let src = await adminHelper.getLogoSrc().getAttribute('src');
|
||||||
|
|
||||||
|
expect(src).to.contains('upload-image-test.png');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
var utils = require('../../utils');
|
||||||
|
var discoverHelper = require('../../helpers/discover-helper');
|
||||||
|
|
||||||
|
var chai = require('chai');
|
||||||
|
var chaiAsPromised = require('chai-as-promised');
|
||||||
|
|
||||||
|
chai.use(chaiAsPromised);
|
||||||
|
var expect = chai.expect;
|
||||||
|
|
||||||
|
|
||||||
|
describe('discover', () => {
|
||||||
|
before(async () => {
|
||||||
|
browser.get(browser.params.glob.host + 'discover');
|
||||||
|
await utils.common.waitLoader();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('screenshot', async () => {
|
||||||
|
await utils.common.takeScreenshot("discover", "discover-home");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('most liked', () => {
|
||||||
|
it('has projects', () => {
|
||||||
|
let projects = discoverHelper.likedProjects();
|
||||||
|
|
||||||
|
expect(projects.count()).to.be.eventually.above(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rearrange', () => {
|
||||||
|
discoverHelper.rearrangeLike(3);
|
||||||
|
|
||||||
|
let filterText = discoverHelper.getLikeFilterText();
|
||||||
|
let projects = discoverHelper.likedProjects();
|
||||||
|
|
||||||
|
expect(filterText).to.be.eventually.equal('All time');
|
||||||
|
expect(projects.count()).to.be.eventually.equal(5);
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('most active', () => {
|
||||||
|
it('has projects', () => {
|
||||||
|
let projects = discoverHelper.activeProjects();
|
||||||
|
|
||||||
|
expect(projects.count()).to.be.eventually.above(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rearrange', () => {
|
||||||
|
discoverHelper.rearrangeActive(3);
|
||||||
|
|
||||||
|
let filterText = discoverHelper.getActiveFilterText();
|
||||||
|
let projects = discoverHelper.activeProjects();
|
||||||
|
|
||||||
|
expect(filterText).to.be.eventually.equal('All time');
|
||||||
|
expect(projects.count()).to.be.eventually.equal(5);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('featured projects', () => {
|
||||||
|
let projects = discoverHelper.featuredProjects();
|
||||||
|
|
||||||
|
expect(projects.count()).to.be.eventually.above(0);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,123 @@
|
||||||
|
var utils = require('../../utils');
|
||||||
|
var discoverHelper = require('../../helpers/discover-helper');
|
||||||
|
|
||||||
|
var chai = require('chai');
|
||||||
|
var chaiAsPromised = require('chai-as-promised');
|
||||||
|
|
||||||
|
chai.use(chaiAsPromised);
|
||||||
|
var expect = chai.expect;
|
||||||
|
|
||||||
|
|
||||||
|
describe('discover search', () => {
|
||||||
|
before(async () => {
|
||||||
|
browser.get(browser.params.glob.host + 'discover/search');
|
||||||
|
await utils.common.waitLoader();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('screenshot', async () => {
|
||||||
|
await utils.common.takeScreenshot("discover", "discover-search");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('top bar', async () => {
|
||||||
|
after(async () => {
|
||||||
|
browser.get(browser.params.glob.host + 'discover/search');
|
||||||
|
await utils.common.waitLoader();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('filters', async () => {
|
||||||
|
let htmlChanges = await utils.common.outerHtmlChanges(discoverHelper.searchProjectsList());
|
||||||
|
|
||||||
|
discoverHelper.searchFilter(1);
|
||||||
|
|
||||||
|
await htmlChanges();
|
||||||
|
|
||||||
|
let url = await browser.getCurrentUrl();
|
||||||
|
|
||||||
|
let projects = discoverHelper.searchProjects();
|
||||||
|
|
||||||
|
expect(projects.count()).to.be.eventually.above(0);
|
||||||
|
expect(url).to.be.equal(browser.params.glob.host + 'discover/search?filter=kanban');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('search by text', () => {
|
||||||
|
discoverHelper.searchInput().sendKeys('Project Example 0');
|
||||||
|
|
||||||
|
discoverHelper.sendSearch();
|
||||||
|
|
||||||
|
let projects = discoverHelper.searchProjects();
|
||||||
|
expect(projects.count()).to.be.eventually.equal(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('most liked', async () => {
|
||||||
|
after(async () => {
|
||||||
|
browser.get(browser.params.glob.host + 'discover/search');
|
||||||
|
await utils.common.waitLoader();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('default', async () => {
|
||||||
|
discoverHelper.mostLiked();
|
||||||
|
|
||||||
|
utils.common.takeScreenshot("discover", "discover-search-filter");
|
||||||
|
|
||||||
|
let url = await browser.getCurrentUrl();
|
||||||
|
|
||||||
|
expect(url).to.be.equal(browser.params.glob.host + 'discover/search?order_by=-total_fans_last_week');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('filter', async () => {
|
||||||
|
discoverHelper.searchOrder(3);
|
||||||
|
|
||||||
|
let projects = discoverHelper.searchProjects();
|
||||||
|
|
||||||
|
let url = await browser.getCurrentUrl();
|
||||||
|
|
||||||
|
expect(projects.count()).to.be.eventually.above(0);
|
||||||
|
expect(url).to.be.equal(browser.params.glob.host + 'discover/search?order_by=-total_fans');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('clear', () => {
|
||||||
|
discoverHelper.clearOrder();
|
||||||
|
|
||||||
|
let orderSelector = discoverHelper.orderSelectorWrapper();
|
||||||
|
|
||||||
|
expect(orderSelector.isPresent()).to.be.eventually.equal(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('most active', async () => {
|
||||||
|
after(async () => {
|
||||||
|
browser.get(browser.params.glob.host + 'discover/search');
|
||||||
|
await utils.common.waitLoader();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('default', async () => {
|
||||||
|
discoverHelper.mostActived();
|
||||||
|
|
||||||
|
utils.common.takeScreenshot("discover", "discover-search-filter");
|
||||||
|
|
||||||
|
let url = await browser.getCurrentUrl();
|
||||||
|
|
||||||
|
expect(url).to.be.equal(browser.params.glob.host + 'discover/search?order_by=-total_activity_last_week');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('filter', async () => {
|
||||||
|
discoverHelper.searchOrder(3);
|
||||||
|
|
||||||
|
let projects = discoverHelper.searchProjects();
|
||||||
|
|
||||||
|
let url = await browser.getCurrentUrl();
|
||||||
|
|
||||||
|
expect(projects.count()).to.be.eventually.above(0);
|
||||||
|
expect(url).to.be.equal(browser.params.glob.host + 'discover/search?order_by=-total_activity');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('clear', () => {
|
||||||
|
discoverHelper.clearOrder();
|
||||||
|
|
||||||
|
let orderSelector = discoverHelper.orderSelectorWrapper();
|
||||||
|
|
||||||
|
expect(orderSelector.isPresent()).to.be.eventually.equal(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -163,7 +163,7 @@ common.prepare = function() {
|
||||||
browser.get(browser.params.glob.host);
|
browser.get(browser.params.glob.host);
|
||||||
|
|
||||||
return common.closeCookies();
|
return common.closeCookies();
|
||||||
}
|
};
|
||||||
|
|
||||||
common.dragEnd = function(elm) {
|
common.dragEnd = function(elm) {
|
||||||
return browser.wait(async function() {
|
return browser.wait(async function() {
|
||||||
|
|
|
@ -17,7 +17,8 @@ var suites = [
|
||||||
'kanban',
|
'kanban',
|
||||||
'projectHome',
|
'projectHome',
|
||||||
'search',
|
'search',
|
||||||
'team'
|
'team',
|
||||||
|
'discover'
|
||||||
];
|
];
|
||||||
|
|
||||||
var lunchSuites = [];
|
var lunchSuites = [];
|
||||||
|
|
Loading…
Reference in New Issue