diff --git a/CHANGELOG.md b/CHANGELOG.md
index ad2e8f5b..1f05dcd6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
### Features
- Show a confirmation notice when you exit edit mode by pressing ESC in the markdown inputs.
+- Add the tribe button to link stories from tree.taiga.io with gigs in tribe.taiga.io.
### Misc
- Lots of small and not so small bugfixes.
diff --git a/app-loader/app-loader.coffee b/app-loader/app-loader.coffee
index 6cbe2f03..cee8fe74 100644
--- a/app-loader/app-loader.coffee
+++ b/app-loader/app-loader.coffee
@@ -3,6 +3,7 @@ window._version = "___VERSION___"
window.taigaConfig = {
"api": "http://localhost:8000/api/v1/",
"eventsUrl": null,
+ "tribeHost": null,
"eventsMaxMissedHeartbeats": 5,
"eventsHeartbeatIntervalTime": 60000,
"debug": true,
diff --git a/app/coffee/modules/userstories/detail.coffee b/app/coffee/modules/userstories/detail.coffee
index 8836c8e7..db09821d 100644
--- a/app/coffee/modules/userstories/detail.coffee
+++ b/app/coffee/modules/userstories/detail.coffee
@@ -50,15 +50,18 @@ class UserStoryDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
"$tgNavUrls",
"$tgAnalytics",
"$translate",
+ "$tgConfig",
"$tgQueueModelTransformation"
]
- constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location,
- @log, @appMetaService, @navUrls, @analytics, @translate, @modelTransform) ->
+ constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @log, @appMetaService,
+ @navUrls, @analytics, @translate, @configService, @modelTransform) ->
bindMethods(@)
@scope.usRef = @params.usref
@scope.sectionName = @translate.instant("US.SECTION_NAME")
+ @scope.tribeEnabled = @configService.config.tribeHost
+
@.initializeEventHandlers()
promise = @.loadInitialData()
@@ -239,6 +242,17 @@ class UserStoryDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
return @rs.userstories.unwatch(@scope.usId).then(onSuccess, onError)
+ onTribeInfo: ->
+ publishTitle = @translate.instant("US.TRIBE.PUBLISH_MORE_INFO_TITLE")
+ image = $('
')
+ .attr({
+ 'src': "/#{window._version}/images/monster-fight.png",
+ 'alt': @translate.instant("US.TRIBE.PUBLISH_MORE_INFO_TITLE")
+ })
+ text = @translate.instant("US.TRIBE.PUBLISH_MORE_INFO_TEXT")
+ publishDesc = $('
').append(image).append(text)
+ @confirm.success(publishTitle, publishDesc)
+
module.controller("UserStoryDetailController", UserStoryDetailController)
diff --git a/app/images/monster-fight.png b/app/images/monster-fight.png
new file mode 100644
index 00000000..9dd83f36
Binary files /dev/null and b/app/images/monster-fight.png differ
diff --git a/app/images/tribe-logo.png b/app/images/tribe-logo.png
new file mode 100644
index 00000000..5b4643c5
Binary files /dev/null and b/app/images/tribe-logo.png differ
diff --git a/app/locales/taiga/locale-en.json b/app/locales/taiga/locale-en.json
index 379c312b..bf80f4f2 100644
--- a/app/locales/taiga/locale-en.json
+++ b/app/locales/taiga/locale-en.json
@@ -993,6 +993,17 @@
"ASSIGN": "Assign User Story",
"NOT_ESTIMATED": "Not estimated",
"TOTAL_US_POINTS": "Total Us points",
+ "TRIBE": {
+ "PUBLISH": "Publish as Gig in Taiga Tribe",
+ "PUBLISH_INFO": "More info",
+ "PUBLISH_TITLE": "More info on publishing in Taiga Tribe",
+ "PUBLISHED_AS_GIG": "Story published as Gig in Taiga Tribe",
+ "EDIT_LINK": "Edit link",
+ "CLOSE": "Close",
+ "SYNCHRONIZE_LINK": "synchronize with Taiga Tribe",
+ "PUBLISH_MORE_INFO_TITLE": "Do you need somebody for this task?",
+ "PUBLISH_MORE_INFO_TEXT": "If you need help with a particular piece of work you can easily create gigs on Taiga Tribe and receive help from all over the world. You will be able to control and manage the gig enjoying a great community eager to contribute.
TaigaTribe was born as a Taiga sibling. Both platforms can live separately but we believe that there is much power in using them combined so we are making sure the integration works like a charm.
"
+ },
"FIELDS": {
"TEAM_REQUIREMENT": "Team Requirement",
"CLIENT_REQUIREMENT": "Client Requirement",
diff --git a/app/modules/components/tribe-button/tribe-button.directive.coffee b/app/modules/components/tribe-button/tribe-button.directive.coffee
new file mode 100644
index 00000000..4f961f06
--- /dev/null
+++ b/app/modules/components/tribe-button/tribe-button.directive.coffee
@@ -0,0 +1,37 @@
+###
+# Copyright (C) 2014-2015 Taiga Agile LLC
+#
+# 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 .
+#
+# File: tribe-button.directive.coffee
+###
+
+TribeButtonDirective = (configService) ->
+ link = (scope, el, attrs) ->
+
+ scope.vm = {}
+ scope.vm.tribeHost = configService.config.tribeHost
+
+ return {
+ scope: {usId: "=", projectSlug: "="}
+ controllerAs: "vm",
+ templateUrl: "components/tribe-button/tribe-button.html",
+ link: link
+ }
+
+TribeButtonDirective.$inject = [
+ "$tgConfig"
+]
+
+angular.module("taigaComponents").directive("tgTribeButton", TribeButtonDirective)
diff --git a/app/modules/components/tribe-button/tribe-button.jade b/app/modules/components/tribe-button/tribe-button.jade
new file mode 100644
index 00000000..1d1cad90
--- /dev/null
+++ b/app/modules/components/tribe-button/tribe-button.jade
@@ -0,0 +1,10 @@
+a.button-tribe(
+ ng-href="{{::vm.tribeHost}}/gigs/import-from-taiga?project={{projectSlug}}&us={{usId}}",
+ title="{{ 'US.TRIBE.PUBLISH' | translate }}"
+ target="_blank"
+)
+ img.tribe-logo(
+ src="/#{v}/images/tribe-logo.png"
+ alt="{{ 'US.TRIBE.PUBLISH' | translate }}"
+ )
+ span {{ 'US.TRIBE.PUBLISH' | translate }}
diff --git a/app/modules/components/tribe-button/tribe-linked.directive.coffee b/app/modules/components/tribe-button/tribe-linked.directive.coffee
new file mode 100644
index 00000000..0c062aaf
--- /dev/null
+++ b/app/modules/components/tribe-button/tribe-linked.directive.coffee
@@ -0,0 +1,48 @@
+###
+# Copyright (C) 2014-2015 Taiga Agile LLC
+#
+# 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 .
+#
+# File: tribe-linked.directive.coffee
+###
+
+TribeLinkedDirective = (configService) ->
+ link = (scope, el, attrs) ->
+
+ scope.vm = {}
+
+ scope.vm.tribeHost = configService.config.tribeHost
+
+ scope.vm.show = () ->
+ scope.vm.open = true
+
+ scope.vm.hide = (event) ->
+ scope.vm.open = false
+
+ directive = {
+ templateUrl: "components/tribe-button/tribe-linked.html",
+ scope: {
+ gigTitle: "=",
+ gigId: "="
+ },
+ link: link
+ }
+
+ return directive
+
+TribeLinkedDirective.$inject = [
+ "$tgConfig"
+]
+
+angular.module("taigaComponents").directive("tgTribeLinked", TribeLinkedDirective)
diff --git a/app/modules/components/tribe-button/tribe-linked.jade b/app/modules/components/tribe-button/tribe-linked.jade
new file mode 100644
index 00000000..6be83206
--- /dev/null
+++ b/app/modules/components/tribe-button/tribe-linked.jade
@@ -0,0 +1,33 @@
+.tribe-linked.js-tribe-linked(ng-class="{'is-active': vm.open, 'is-inactive': vm.open == false}")
+ .tribe-linked-inner
+ .tribe-linked-header
+ img.tribe-logo(
+ ng-click="vm.show()"
+ alt=""
+ title="{{ 'US.TRIBE.PUBLISHED_AS_GIG' | translate }}"
+ src="/#{v}/images/tribe-logo.png"
+ )
+ p.title {{ "US.TRIBE.PUBLISHED_AS_GIG" | translate }}
+ a.close(
+ ng-click="vm.hide()"
+ href=""
+ title="{{ 'US.TRIBE.CLOSE' | translate }}"
+ )
+ svg.icon.icon-remove
+ use(xlink:href="#icon-remove")
+
+ a.gig-title(
+ href="{{::vm.tribeHost}}/gigs/{{gigId}}"
+ title="gigTitle"
+ target="_blank"
+ ) {{gigTitle}}
+
+ a.delete-link(
+ href="{{::vm.tribeHost}}/gigs/{{gigId}}/link-with-taiga?from=taiga"
+ title="{{ 'US.TRIBE.EDIT_LINK' | translate }}"
+ ) {{ 'US.TRIBE.EDIT_LINK' | translate }}
+
+ a.synchronize-link.button-tribe(
+ ng-href="{{::vm.tribeHost}}/gigs/sync/{{gigId}}?from=taiga"
+ title="{{ 'US.TRIBE.SINCHRONIZE_LINK' }}"
+ ) {{ 'US.TRIBE.SYNCHRONIZE_LINK' | translate }}
diff --git a/app/modules/components/tribe-button/tribe-linked.scss b/app/modules/components/tribe-button/tribe-linked.scss
new file mode 100644
index 00000000..0da433ef
--- /dev/null
+++ b/app/modules/components/tribe-button/tribe-linked.scss
@@ -0,0 +1,123 @@
+.tribe-linked {
+ margin-left: auto;
+ overflow: hidden;
+ position: absolute;
+ right: 0;
+ top: 0;
+ z-index: 99;
+ .tribe-linked-inner {
+ padding: .5rem;
+ transition: .2s;
+ &:hover {
+ background: $white;
+ cursor: pointer;
+ }
+ .title,
+ .gig-title,
+ .delete-link,
+ .synchronize-link,
+ .close {
+ display: none;
+ opacity: 0;
+ }
+ }
+ .tribe-logo {
+ height: 2rem;
+ width: 2rem;
+ }
+ &.is-active {
+ animation-duration: 1s;
+ animation-name: slideTribeInner;
+ background: $white;
+ box-shadow: 1px 1px 5px rgba($grayer, .2);
+ overflow: hidden;
+ .tribe-linked-inner {
+ height: 100%;
+ min-width: 300px;
+ .title,
+ .gig-title,
+ .delete-link,
+ .synchronize-link,
+ .close {
+ animation-duration: 1.25s;
+ animation-name: fadeInFromNone;
+ display: block;
+ opacity: 1;
+ }
+ }
+ .tribe-linked-header {
+ align-items: center;
+ display: flex;
+ margin-bottom: 1rem;
+ }
+ .tribe-logo {
+ margin-right: .5rem;
+ vertical-align: text-bottom;
+ }
+ svg {
+ fill: $red-light;
+ height: 1.5rem;
+ max-height: 1.5rem;
+ max-width: 1.5rem;
+ transition: all .2s;
+ width: 1.5rem;
+ &:hover {
+ fill: $red;
+ }
+ }
+ .title {
+ margin-bottom: 0;
+ }
+ .gig-title {
+ @include font-type(light);
+ color: $tribe-primary;
+ margin-bottom: .5rem;
+ }
+ .delete-link {
+ @include font-type(light);
+ @include font-size(small);
+ color: $primary;
+ display: block;
+ margin-bottom: 1rem;
+ }
+ .synchronize-link {
+ display: block;
+ padding: .5rem;
+ }
+ .close {
+ align-self: flex-start;
+ margin-left: 1rem;
+ }
+ }
+}
+
+@keyframes slideTribeInner {
+ 0% {
+ max-height: 60px;
+ width: 100px;
+ }
+ 20% {
+ max-height: 60px;
+ width: 300px;
+ }
+ 100% {
+ max-height: 225px;
+ }
+}
+
+@keyframes fadeInFromNone {
+ 0% {
+ display: none;
+ opacity: 0;
+ }
+
+ 80% {
+ display: block;
+ opacity: 0;
+ }
+
+ 100% {
+ display: block;
+ opacity: 1;
+ }
+}
diff --git a/app/modules/external-apps/external-app.scss b/app/modules/external-apps/external-app.scss
index 17f5ff08..cc00b2b3 100644
--- a/app/modules/external-apps/external-app.scss
+++ b/app/modules/external-apps/external-app.scss
@@ -3,9 +3,12 @@
text-align: center;
width: 480px;
.logo {
- height: 6rem;
+ height: 4rem;
margin: 0 auto;
- width: 6rem;
+ width: 4rem;
+ }
+ svg {
+ @include svg-size(4rem);
}
h1 {
margin-bottom: 0;
diff --git a/app/partials/us/us-detail.jade b/app/partials/us/us-detail.jade
index 20a72a44..0896a232 100644
--- a/app/partials/us/us-detail.jade
+++ b/app/partials/us/us-detail.jade
@@ -107,6 +107,12 @@ div.wrapper(
ng-model="us"
)
+ tg-tribe-linked(
+ ng-if="tribeEnabled && us.tribe_gig",
+ gig-title="us.tribe_gig.title"
+ gig-id="us.tribe_gig.id"
+ )
+
tg-us-estimation.ticket-estimation(ng-model="us")
section.ticket-assigned-to(
@@ -129,6 +135,16 @@ div.wrapper(
required-perm="modify_us"
)
+ section.ticket-to-tribe(ng-if="tribeEnabled && !us.tribe_gig")
+ tg-tribe-button(
+ us-id="us.id"
+ project-slug="project.slug"
+ )
+ a.tribe-more-info(
+ href=""
+ title="{{'US.TRIBE.PUBLISH_TITLE' | translate}}"
+ ng-click="ctrl.onTribeInfo()"
+ ) {{'US.TRIBE.PUBLISH_INFO' | translate}}
section.ticket-detail-settings
tg-us-team-requirement-button(ng-model="us")
diff --git a/app/styles/components/buttons.scss b/app/styles/components/buttons.scss
index 99795199..f6f95f46 100755
--- a/app/styles/components/buttons.scss
+++ b/app/styles/components/buttons.scss
@@ -130,3 +130,28 @@ a.button-gray {
background: $black;
}
}
+
+.button-tribe {
+ @extend %button;
+ align-items: center;
+ background: $tribe-primary;
+ display: flex;
+ padding: .4rem;
+ padding-left: 1.5rem;
+ &:hover,
+ &.active {
+ background: $tribe-secondary;
+ color: $white;
+ }
+ .tribe-logo {
+ margin-right: .5rem;
+ width: 1.5rem;
+ }
+}
+
+.tribe-more-info {
+ @include font-size(small);
+ color: $primary;
+ display: inline-block;
+ margin-top: .5rem;
+}
diff --git a/app/themes/high-contrast/variables.scss b/app/themes/high-contrast/variables.scss
index 861556da..cd5ef6e6 100755
--- a/app/themes/high-contrast/variables.scss
+++ b/app/themes/high-contrast/variables.scss
@@ -31,8 +31,8 @@ $red-amaranth: #e91e63;
$purple-eggplant: #9c27b0;
$yellow-pear: #ffc107;
-$tribe-primary: #98e0eb;
-$tribe-secondary: #107a8a;
+$tribe-primary: #107a8a;
+$tribe-secondary: darken($tribe-primary, 10%);
$top-icon-color: $white;
$dropdown-color: rgba(darken($primary-dark, 20%), 1);
diff --git a/app/themes/material-design/variables.scss b/app/themes/material-design/variables.scss
index cf662a5d..c76c2e0b 100755
--- a/app/themes/material-design/variables.scss
+++ b/app/themes/material-design/variables.scss
@@ -31,8 +31,8 @@ $red-amaranth: #e91e63;
$purple-eggplant: #9c27b0;
$yellow-pear: #ffc107;
-$tribe-primary: #98e0eb;
-$tribe-secondary: #107a8a;
+$tribe-primary: #107a8a;
+$tribe-secondary: darken($tribe-primary, 10%);
$top-icon-color: $white;
$dropdown-color: rgba(darken($primary-dark, 20%), 1);
diff --git a/app/themes/taiga/variables.scss b/app/themes/taiga/variables.scss
index 3eaa69df..e8d00c10 100755
--- a/app/themes/taiga/variables.scss
+++ b/app/themes/taiga/variables.scss
@@ -31,8 +31,8 @@ $red-amaranth: #e43050;
$purple-eggplant: #810061;
$yellow-pear: #bbe831;
-$tribe-primary: #98e0eb;
-$tribe-secondary: #107a8a;
+$tribe-primary: #107a8a;
+$tribe-secondary: darken($tribe-primary, 10%);
$top-icon-color: #11241f;
$dropdown-color: rgba(darken($grayer, 20%), 1);
diff --git a/conf/conf.example.json b/conf/conf.example.json
index 1779eec1..7868fbf1 100644
--- a/conf/conf.example.json
+++ b/conf/conf.example.json
@@ -13,5 +13,6 @@
"privacyPolicyUrl": null,
"termsOfServiceUrl": null,
"maxUploadFileSize": null,
- "contribPlugins": []
+ "contribPlugins": [],
+ "tribeHost": null
}