commit
d335e81061
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -3,9 +3,12 @@
|
|||
## 1.3.0 Dryas hookeriana (Unreleased)
|
||||
|
||||
### Features
|
||||
- GitHub integration (Phase I):
|
||||
+ Add button to login/singin with a GitHub account.
|
||||
+ Create Admin Panel with the GitHub webhooks settings.
|
||||
- Differentiate blocked user stories on a milestone.
|
||||
|
||||
### Misc
|
||||
### Misc
|
||||
- Lots of small and not so small bugfixes.
|
||||
|
||||
|
||||
|
@ -27,12 +30,12 @@
|
|||
|
||||
## 1.1.0 Alnus maximowiczii (2014-10-13)
|
||||
|
||||
### Features ###
|
||||
### Features
|
||||
- Promote an issue to a user story.
|
||||
- Changed configuration format from coffeescript file to json.
|
||||
- Add builtin analytics support.
|
||||
|
||||
### Misc ###
|
||||
### Misc
|
||||
- Fix bug related to stange behavior of browser autofill and angularjs on login page.
|
||||
- Fix bug on userstories ordering on sprints.
|
||||
- Fix bug of projects list visualization on project nav on first page loading.
|
||||
|
@ -40,10 +43,10 @@
|
|||
|
||||
## 1.0.0 (2014-10-07)
|
||||
|
||||
### Features ###
|
||||
### Features
|
||||
- Redesign for taskboard and backlog summaries
|
||||
- Allow feedback for users from the platform
|
||||
- Real time changes for backlog, taskboard, kanban and issues
|
||||
|
||||
### Misc ###
|
||||
### Misc
|
||||
- Lots of small and not so small bugfixes
|
||||
|
|
|
@ -94,18 +94,20 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
|
|||
{templateUrl: "/partials/admin-memberships.html"})
|
||||
$routeProvider.when("/project/:pslug/admin/roles",
|
||||
{templateUrl: "/partials/admin-roles.html"})
|
||||
$routeProvider.when("/project/:pslug/admin/third-parties/github",
|
||||
{templateUrl: "/partials/admin-third-parties-github.html"})
|
||||
|
||||
# User settings
|
||||
$routeProvider.when("/project/:pslug/user-settings/user-profile",
|
||||
{templateUrl: "/partials/user-profile.html"})
|
||||
{templateUrl: "/partials/user-profile.html"})
|
||||
$routeProvider.when("/project/:pslug/user-settings/user-change-password",
|
||||
{templateUrl: "/partials/user-change-password.html"})
|
||||
{templateUrl: "/partials/user-change-password.html"})
|
||||
$routeProvider.when("/project/:pslug/user-settings/user-avatar",
|
||||
{templateUrl: "/partials/user-avatar.html"})
|
||||
{templateUrl: "/partials/user-avatar.html"})
|
||||
$routeProvider.when("/project/:pslug/user-settings/mail-notifications",
|
||||
{templateUrl: "/partials/mail-notifications.html"})
|
||||
{templateUrl: "/partials/mail-notifications.html"})
|
||||
$routeProvider.when("/change-email/:email_token",
|
||||
{templateUrl: "/partials/change-email.html"})
|
||||
{templateUrl: "/partials/change-email.html"})
|
||||
$routeProvider.when("/cancel-account/:cancel_token",
|
||||
{templateUrl: "/partials/cancel-account.html"})
|
||||
|
||||
|
@ -216,6 +218,7 @@ modules = [
|
|||
"taigaUserSettings",
|
||||
"taigaFeedback",
|
||||
"taigaPlugins",
|
||||
"taigaIntegrations",
|
||||
|
||||
# Vendor modules
|
||||
"ngRoute",
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
###
|
||||
# Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
|
||||
# Copyright (C) 2014 Jesús Espino Garcia <jespinog@gmail.com>
|
||||
# Copyright (C) 2014 David Barragán Merino <bameda@dbarragan.com>
|
||||
#
|
||||
# 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: modules/admin/third-parties.coffee
|
||||
###
|
||||
|
||||
taiga = @.taiga
|
||||
|
||||
mixOf = @.taiga.mixOf
|
||||
|
||||
module = angular.module("taigaAdmin")
|
||||
|
||||
|
||||
#############################################################################
|
||||
## Github Controller
|
||||
#############################################################################
|
||||
|
||||
class GithubController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.FiltersMixin)
|
||||
@.$inject = [
|
||||
"$scope",
|
||||
"$tgRepo",
|
||||
"$tgResources",
|
||||
"$routeParams",
|
||||
"$appTitle"
|
||||
]
|
||||
|
||||
constructor: (@scope, @repo, @rs, @params, @appTitle) ->
|
||||
_.bindAll(@)
|
||||
|
||||
@scope.sectionName = "Github" #i18n
|
||||
@scope.project = {}
|
||||
@scope.anyComputableRole = true
|
||||
|
||||
promise = @.loadInitialData()
|
||||
|
||||
promise.then () =>
|
||||
@appTitle.set("Github - " + @scope.project.name)
|
||||
|
||||
promise.then null, @.onInitialDataError.bind(@)
|
||||
|
||||
loadModules: ->
|
||||
return @rs.modules.list(@scope.projectId, "github").then (github) =>
|
||||
@scope.github = github
|
||||
|
||||
loadProject: ->
|
||||
return @rs.projects.get(@scope.projectId).then (project) =>
|
||||
@scope.project = project
|
||||
@scope.$emit('project:loaded', project)
|
||||
@scope.anyComputableRole = _.some(_.map(project.roles, (point) -> point.computable))
|
||||
|
||||
return project
|
||||
|
||||
loadInitialData: ->
|
||||
promise = @repo.resolve({pslug: @params.pslug}).then (data) =>
|
||||
@scope.projectId = data.project
|
||||
return data
|
||||
|
||||
return promise.then(=> @.loadProject())
|
||||
.then(=> @.loadModules())
|
||||
|
||||
|
||||
module.controller("GithubController", GithubController)
|
||||
|
||||
SelectInputText = ->
|
||||
link = ($scope, $el, $attrs) ->
|
||||
$el.on "click", ".select-input-content", () ->
|
||||
$el.find("input").select()
|
||||
$el.find(".help-copy").addClass("visible")
|
||||
|
||||
return {link:link}
|
||||
|
||||
module.directive("tgSelectInputText", SelectInputText)
|
||||
|
||||
#############################################################################
|
||||
## GithubWebhooks Directive
|
||||
#############################################################################
|
||||
|
||||
GithubWebhooksDirective = ($repo, $confirm, $loading) ->
|
||||
link = ($scope, $el, $attrs) ->
|
||||
form = $el.find("form").checksley({"onlyOneErrorElement": true})
|
||||
submit = (target) =>
|
||||
return if not form.validate()
|
||||
|
||||
$loading.start(target)
|
||||
|
||||
promise = $repo.saveAttribute($scope.github, "github")
|
||||
promise.then ->
|
||||
$loading.finish(target)
|
||||
$confirm.notify("success")
|
||||
|
||||
promise.then null, (data) ->
|
||||
$loading.finish(target)
|
||||
form.setErrors(data)
|
||||
if data._error_message
|
||||
$confirm.notify("error", data._error_message)
|
||||
|
||||
$el.on "click", "a.button-green", (event) ->
|
||||
event.preventDefault()
|
||||
target = angular.element(event.currentTarget)
|
||||
submit(target)
|
||||
|
||||
$el.on "submit", "form", (event) ->
|
||||
event.preventDefault()
|
||||
submit()
|
||||
|
||||
return {link:link}
|
||||
|
||||
module.directive("tgGithubWebhooks", ["$tgRepo", "$tgConfirm", "$tgLoading", GithubWebhooksDirective])
|
|
@ -89,6 +89,7 @@ urls = {
|
|||
"project-admin-project-values-issue-severities": "/project/:project/admin/project-values/issue-severities"
|
||||
"project-admin-memberships": "/project/:project/admin/memberships"
|
||||
"project-admin-roles": "/project/:project/admin/roles"
|
||||
"project-admin-third-parties-github": "/project/:project/admin/third-parties/github"
|
||||
|
||||
# User settings
|
||||
"user-settings-user-profile": "/project/:project/user-settings/user-profile"
|
||||
|
|
|
@ -31,6 +31,9 @@ class RepositoryService extends taiga.Service
|
|||
idAttrName = model.getIdAttrName()
|
||||
return "#{@urls.resolve(model.getName())}/#{model[idAttrName]}"
|
||||
|
||||
resolveUrlForAttributeModel: (model) ->
|
||||
return @urls.resolve(model.getName(), model.parent)
|
||||
|
||||
create: (name, data, dataTypes={}, extraParams={}) ->
|
||||
defered = @q.defer()
|
||||
url = @urls.resolve(name)
|
||||
|
@ -89,6 +92,37 @@ class RepositoryService extends taiga.Service
|
|||
|
||||
return defered.promise
|
||||
|
||||
saveAttribute: (model, attribute, patch=true) ->
|
||||
defered = @q.defer()
|
||||
|
||||
if not model.isModified() and patch
|
||||
defered.resolve(model)
|
||||
return defered.promise
|
||||
|
||||
url = @.resolveUrlForAttributeModel(model)
|
||||
|
||||
data = {}
|
||||
|
||||
data[attribute] = model.getAttrs()
|
||||
|
||||
if patch
|
||||
promise = @http.patch(url, data)
|
||||
else
|
||||
promise = @http.put(url, data)
|
||||
|
||||
promise.success (data, status) =>
|
||||
model._isModified = false
|
||||
model._attrs = _.extend(model.getAttrs(), data)
|
||||
model._modifiedAttrs = {}
|
||||
|
||||
model.applyCasts()
|
||||
defered.resolve(model)
|
||||
|
||||
promise.error (data, status) ->
|
||||
defered.reject(data)
|
||||
|
||||
return defered.promise
|
||||
|
||||
refresh: (model) ->
|
||||
defered = @q.defer()
|
||||
|
||||
|
@ -115,6 +149,19 @@ class RepositoryService extends taiga.Service
|
|||
return @http.get(url, params, httpOptions).then (data) =>
|
||||
return _.map(data.data, (x) => @model.make_model(name, x))
|
||||
|
||||
queryOneAttribute: (name, id, attribute, params, options={}) ->
|
||||
url = @urls.resolve(name, id)
|
||||
httpOptions = {headers: {}}
|
||||
|
||||
if not options.enablePagination
|
||||
httpOptions.headers["x-disable-pagination"] = "1"
|
||||
|
||||
return @http.get(url, params, httpOptions).then (data) =>
|
||||
model = @model.make_model(name, data.data[attribute])
|
||||
model.parent = id
|
||||
|
||||
return model
|
||||
|
||||
queryOne: (name, id, params, options={}) ->
|
||||
url = @urls.resolve(name)
|
||||
url = "#{url}/#{id}" if id
|
||||
|
|
|
@ -132,8 +132,12 @@ CreatedByDisplayDirective = ->
|
|||
|
||||
link = ($scope, $el, $attrs) ->
|
||||
render = (model) ->
|
||||
owner = $scope.usersById?[model.owner] or {
|
||||
full_name_display: "external user"
|
||||
photo: "/images/unnamed.png"
|
||||
}
|
||||
html = template({
|
||||
owner: $scope.usersById?[model.owner]
|
||||
owner: owner
|
||||
date: moment(model.created_date).format("DD MMM YYYY HH:mm")
|
||||
})
|
||||
$el.html(html)
|
||||
|
|
|
@ -97,8 +97,6 @@ Loader = () ->
|
|||
startCurrentPageLoader: () ->
|
||||
if config.enabled
|
||||
start()
|
||||
else
|
||||
pageLoaded(true)
|
||||
|
||||
onStart: (fn) ->
|
||||
$rootscope.$on("loader:start", fn)
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
###
|
||||
# Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
|
||||
# Copyright (C) 2014 Jesús Espino Garcia <jespinog@gmail.com>
|
||||
# Copyright (C) 2014 David Barragán Merino <bameda@dbarragan.com>
|
||||
#
|
||||
# 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: modules/integrations.coffee
|
||||
###
|
||||
|
||||
module = angular.module("taigaIntegrations", [])
|
|
@ -0,0 +1,111 @@
|
|||
###
|
||||
# Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
|
||||
# Copyright (C) 2014 Jesús Espino Garcia <jespinog@gmail.com>
|
||||
# Copyright (C) 2014 David Barragán Merino <bameda@dbarragan.com>
|
||||
#
|
||||
# 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: modules/integrations/github.coffee
|
||||
###
|
||||
|
||||
taiga = @.taiga
|
||||
|
||||
module = angular.module("taigaIntegrations")
|
||||
|
||||
AUTH_URL = "https://github.com/login/oauth/authorize"
|
||||
|
||||
|
||||
#############################################################################
|
||||
## User story team requirements button directive
|
||||
#############################################################################
|
||||
|
||||
GithubLoginButtonDirective = ($window, $params, $location, $config, $events, $confirm, $auth, $navUrls, $loader) ->
|
||||
# Login or registar a user with his/her github account.
|
||||
#
|
||||
# Example:
|
||||
# tg-github-login-button()
|
||||
#
|
||||
# Requirements:
|
||||
# - ...
|
||||
|
||||
template = """
|
||||
<a class="button button-github" href="" title="Enter with your github account">
|
||||
<span class="icon icon-github"></span>
|
||||
<span>Login with Github</span>
|
||||
</a>
|
||||
""" #TODO: i18n
|
||||
|
||||
link = ($scope, $el, $attrs) ->
|
||||
clientId = $config.get("gitHubClientId", null)
|
||||
return if not clientId
|
||||
|
||||
renderGitHubButton = ->
|
||||
$el.html(template) if clientId
|
||||
|
||||
loginOnSuccess = (response) ->
|
||||
if $params.next and $params.next != $navUrls.resolve("login")
|
||||
nextUrl = $params.next
|
||||
else
|
||||
nextUrl = $navUrls.resolve("home")
|
||||
|
||||
$events.setupConnection()
|
||||
|
||||
$location.search("next", null)
|
||||
$location.search("token", null)
|
||||
$location.search("state", null)
|
||||
$location.search("code", null)
|
||||
$location.path(nextUrl)
|
||||
|
||||
loginOnError = (response) ->
|
||||
$location.search("state", null)
|
||||
$location.search("code", null)
|
||||
$loader.pageLoaded()
|
||||
|
||||
if response.data.error_message
|
||||
$confirm.notify("light-error", response.data.error_message )
|
||||
else
|
||||
$confirm.notify("light-error", "Our Oompa Loompas have not been able to get you
|
||||
credentials from GitHub.") #TODO: i18n
|
||||
|
||||
loginWithGitHubAccount = ->
|
||||
type = $params.state
|
||||
code = $params.code
|
||||
token = $params.token
|
||||
|
||||
return if not (type == "github" and code)
|
||||
$loader.start()
|
||||
|
||||
data = {code: code, token: token}
|
||||
$auth.login(data, type).then(loginOnSuccess, loginOnError)
|
||||
|
||||
renderGitHubButton()
|
||||
loginWithGitHubAccount()
|
||||
|
||||
$el.on "click", ".button-github", (event) ->
|
||||
redirectToUri = $location.absUrl()
|
||||
url = "#{AUTH_URL}?client_id=#{clientId}&redirect_uri=#{redirectToUri}&state=github&scope=user:email"
|
||||
$window.location.href = url
|
||||
|
||||
$scope.$on "$destroy", ->
|
||||
$el.off()
|
||||
|
||||
return {
|
||||
link: link
|
||||
restrict: "EA"
|
||||
template: ""
|
||||
}
|
||||
|
||||
module.directive("tgGithubLoginButton", ["$window", '$routeParams', "$tgLocation", "$tgConfig", "$tgEvents",
|
||||
"$tgConfirm", "$tgAuth", "$tgNavUrls", "tgLoader",
|
||||
GithubLoginButtonDirective])
|
|
@ -83,6 +83,7 @@ urls = {
|
|||
"issue-types": "/issue-types"
|
||||
"priorities": "/priorities"
|
||||
"severities": "/severities"
|
||||
"project-modules": "/projects/%s/modules"
|
||||
|
||||
# History
|
||||
"history/us": "/history/userstory"
|
||||
|
@ -138,5 +139,6 @@ module.run([
|
|||
"$tgMdRenderResourcesProvider",
|
||||
"$tgHistoryResourcesProvider",
|
||||
"$tgKanbanResourcesProvider",
|
||||
"$tgModulesResourcesProvider",
|
||||
initResources
|
||||
])
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
resourceProvider = ($repo) ->
|
||||
service = {}
|
||||
|
||||
service.list = (projectId, module) ->
|
||||
return $repo.queryOneAttribute("project-modules", projectId, module)
|
||||
|
||||
return (instance) ->
|
||||
instance.modules = service
|
||||
|
||||
|
||||
module = angular.module("taigaResources")
|
||||
module.factory("$tgModulesResourcesProvider", ["$tgRepo", resourceProvider])
|
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
|
@ -0,0 +1,95 @@
|
|||
block head
|
||||
title Taiga Your agile, free, and open source project management tool
|
||||
|
||||
block content
|
||||
div.wrapper.roles(tg-github-webhooks, ng-controller="GithubController as ctrl",
|
||||
ng-init="section='admin'")
|
||||
sidebar.menu-secondary.sidebar(tg-admin-navigation="third-parties")
|
||||
include views/modules/admin-menu
|
||||
sidebar.menu-tertiary.sidebar(tg-admin-navigation="third-parties-github")
|
||||
include views/modules/admin-submenu-third-parties
|
||||
|
||||
section.main.admin-common.admin-third-parties
|
||||
include views/components/mainTitle
|
||||
|
||||
form
|
||||
fieldset
|
||||
label(for="secret-key") Secret key
|
||||
input(type="text", name="secret-key", ng-model="github.secret", placeholder="Secret key", id="secret-key")
|
||||
|
||||
fieldset
|
||||
.select-input-text(tg-select-input-text)
|
||||
div
|
||||
label(for="payload-url") Payload URL
|
||||
.field-with-option
|
||||
input(type="text", ng-model="github.webhooks_url", name="payload-url", readonly="readonly", placeholder="Payload URL", id="payload-url")
|
||||
.option-wrapper.select-input-content
|
||||
.icon.icon-copy
|
||||
.help-copy Copy to clipboard: Ctrl+C
|
||||
|
||||
input(type="submit", class="hidden")
|
||||
a.button.button-green(href="") Save
|
||||
|
||||
|
||||
.help
|
||||
h2 How to use it
|
||||
|
||||
h3 Configure Taiga
|
||||
ol
|
||||
li Fill
|
||||
span Secret key
|
||||
| or use the auto generated one
|
||||
|
||||
li Copy the
|
||||
span Payload URL field.
|
||||
|
||||
h3 Configure Github
|
||||
ol
|
||||
li Go to your github repository.
|
||||
li Click on
|
||||
span Settings
|
||||
| >
|
||||
span Webhooks & Services
|
||||
| >
|
||||
span Add webhook
|
||||
|
||||
li On that screen set the payload url with the payload url of this screen.
|
||||
li Secret must be filled with the same content as the secret field of this screen.
|
||||
li Content type must be
|
||||
span application/json.
|
||||
li Taiga currently listen for three different kind of events:
|
||||
ol
|
||||
li Push events: changing element status via commit message
|
||||
li Issues: issues created in github appear automatically in Taiga
|
||||
li Issue comment: issue comments created in github appear automatically in Taiga
|
||||
|
||||
p Just check "send me everything" or just the events you want Taiga to listen for.
|
||||
|
||||
.img
|
||||
.alt-image Github Webhooke page
|
||||
img(src="/images/github-help.png", alt="webhook")
|
||||
|
||||
h2 Changing elements status via commit message
|
||||
|
||||
p
|
||||
| The status of any issue, task or user story can be changed via commit message.
|
||||
| Just add to your commit message something like:
|
||||
|
||||
code
|
||||
| TG-REF #STATUS
|
||||
|
||||
ul.code-info
|
||||
li
|
||||
span REF:
|
||||
| US/Issue/Task reference of the element you want to modify
|
||||
li
|
||||
span STATUS:
|
||||
| New status slug to set, you can find all of them in:
|
||||
a(href="", tg-nav="project-admin-project-values-us-status:project=project.slug") US STATUSES.
|
||||
|
||||
h3 An example please!
|
||||
|
||||
code
|
||||
| TG-123 #closed
|
||||
|
||||
p In this example, 123 is an issue reference and with this command, the issue will change its status to closed.
|
|
@ -23,6 +23,10 @@ block content
|
|||
tg-nav="project-userstories-detail:project=project.slug, ref=us.ref")
|
||||
span(tg-bo-ref="us.ref")
|
||||
|
||||
p.external-reference(ng-if="issue.external_reference") This issue has been created from
|
||||
a(target="_blank", tg-bo-href="issue.external_reference[1]", title="Go to origin")
|
||||
span {{ issue.external_reference[1] }}
|
||||
|
||||
p.block-desc-container(ng-show="issue.is_blocked")
|
||||
span.block-description-title Blocked
|
||||
span.block-description(ng-bind="issue.blocked_note || 'This issue is blocked'")
|
||||
|
|
|
@ -21,12 +21,18 @@ block content
|
|||
h2.us-title-text
|
||||
span.us-number(tg-bo-ref="task.ref")
|
||||
span.us-name(tg-editable-subject, ng-model="task", required-perm="modify_task")
|
||||
|
||||
h3.us-related-task This task belongs to
|
||||
a(tg-check-permission="view_us", href="", title="Go to user story",
|
||||
tg-nav="project-userstories-detail:project=project.slug, ref=us.ref",
|
||||
ng-if="us")
|
||||
span(tg-bo-ref="us.ref")
|
||||
span(tg-bo-bind="us.subject")
|
||||
|
||||
p.external-reference(ng-if="task.external_reference") This task has been created from
|
||||
a(target="_blank", tg-bo-href="task.external_reference[1]", title="Go to origin")
|
||||
span {{ task.external_reference[1] }}
|
||||
|
||||
p.block-desc-container(ng-show="task.is_blocked")
|
||||
span.block-description-title Blocked
|
||||
span.block-description(ng-bind="task.blocked_note || 'This task is blocked'")
|
||||
|
|
|
@ -28,6 +28,10 @@ block content
|
|||
tg-bo-title="'#' + us.origin_issue.ref + ' ' + us.origin_issue.subject")
|
||||
span(tg-bo-ref="us.origin_issue.ref")
|
||||
|
||||
p.external-reference(ng-if="us.external_reference") This US has been created from
|
||||
a(target="_blank", tg-bo-href="us.external_reference[1]", title="Go to origin")
|
||||
span {{ us.external_reference[1] }}
|
||||
|
||||
p.block-desc-container(ng-show="us.is_blocked")
|
||||
span.block-description-title Blocked
|
||||
span.block-description(ng-bind="us.blocked_note || 'This user story is blocked'")
|
||||
|
|
|
@ -20,3 +20,7 @@ section.admin-menu
|
|||
a(href="" tg-nav="project-admin-roles:project=project.slug")
|
||||
span.title Roles & Permissions
|
||||
span.icon.icon-arrow-right
|
||||
li#adminmenu-third-parties
|
||||
a(href="" tg-nav="project-admin-third-parties-github:project=project.slug")
|
||||
span.title Third parties
|
||||
span.icon.icon-arrow-right
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
section.admin-submenu
|
||||
header
|
||||
h1 Third parties
|
||||
|
||||
nav
|
||||
ul
|
||||
li#adminmenu-third-parties-github
|
||||
a(href="", tg-nav="project-admin-third-parties-github:project=project.slug")
|
||||
span.title Github
|
||||
span.icon.icon-arrow-right
|
|
@ -3,6 +3,7 @@ section.colors-table
|
|||
div.row
|
||||
div.color-column Color
|
||||
div.status-name Name
|
||||
div.status-slug Slug
|
||||
div.is-closed-column Is closed?
|
||||
div.options-column
|
||||
|
||||
|
@ -17,6 +18,9 @@ section.colors-table
|
|||
div.status-name
|
||||
span {{ value.name }}
|
||||
|
||||
div.status-slug
|
||||
span {{ value.slug }}
|
||||
|
||||
div.is-closed-column
|
||||
div.icon.icon-check-square(ng-show="value.is_closed")
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ section.colors-table
|
|||
div.row
|
||||
div.color-column Color
|
||||
div.status-name Name
|
||||
div.status-slug Slug
|
||||
div.is-closed-column Is closed?
|
||||
div.status-wip-limit WIP Limit
|
||||
div.options-column
|
||||
|
@ -19,6 +20,9 @@ section.colors-table
|
|||
div.status-name
|
||||
span {{ value.name }}
|
||||
|
||||
div.status-slug
|
||||
span {{ value.slug }}
|
||||
|
||||
div.is-closed-column
|
||||
div.icon.icon-check-square(ng-show="value.is_closed")
|
||||
|
||||
|
|
|
@ -10,3 +10,5 @@ form.login-form
|
|||
fieldset
|
||||
a.button.button-login.button-gray(href="", title="Log in") Enter
|
||||
input(type="submit", style="display:none")
|
||||
|
||||
fieldset(tg-github-login-button)
|
||||
|
|
|
@ -23,4 +23,4 @@ form.register-form
|
|||
a.button.button-register.button-gray(href="", title="Sign up") Sign up
|
||||
input(type="submit", style="display:none")
|
||||
|
||||
tg-terms-notice
|
||||
tg-terms-notice
|
||||
|
|
|
@ -13,4 +13,6 @@ div.login-form-container(tg-login)
|
|||
a.button.button-login.button-gray(href="", title="Sign in") Sign in
|
||||
input(type="submit", style="display:none")
|
||||
|
||||
fieldset(tg-github-login-button)
|
||||
|
||||
tg-public-register-message
|
||||
|
|
|
@ -17,13 +17,15 @@ div.register-form-container(tg-register)
|
|||
|
||||
fieldset
|
||||
input(type="password", name="password", ng-model="data.password",
|
||||
data-required="true", data-minlength="4",
|
||||
data-required="true", data-minlength="4",
|
||||
placeholder="Set a password (case sensitive)")
|
||||
|
||||
fieldset
|
||||
a.button.button-register.button-gray(href="", title="Sign up") Sign up
|
||||
input(type="submit", class="hidden")
|
||||
|
||||
fieldset(tg-github-login-button)
|
||||
|
||||
// Only displays terms notice when terms plugin is loaded.
|
||||
tg-terms-notice
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ a.button-green {
|
|||
a.button-gray {
|
||||
background: $button-gray;
|
||||
&:hover {
|
||||
background: $button-gray-hover;
|
||||
background: $fresh-taiga;
|
||||
color: $white;
|
||||
}
|
||||
span {
|
||||
|
@ -102,3 +102,18 @@ a.button-bulk {
|
|||
background: $fresh-taiga;
|
||||
}
|
||||
}
|
||||
.button-github {
|
||||
@extend %button;
|
||||
background: $grayer;
|
||||
vertical-align: middle;
|
||||
.icon {
|
||||
@extend %large;
|
||||
color: $white;
|
||||
margin-right: .5rem;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
&:hover {
|
||||
@include transition (background .3s linear);
|
||||
background: $black;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,10 +44,12 @@
|
|||
}
|
||||
.invitation-form {
|
||||
@include table-flex();
|
||||
fieldset {
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
input {
|
||||
background: $white;
|
||||
color: $gray;
|
||||
margin-bottom: 1rem;
|
||||
position: relative;
|
||||
@include placeholder {
|
||||
color: $gray-light;
|
||||
|
@ -80,16 +82,28 @@
|
|||
background: $fresh-taiga;
|
||||
}
|
||||
}
|
||||
.button-github {
|
||||
&:hover {
|
||||
background: $black;
|
||||
}
|
||||
}
|
||||
}
|
||||
.login-form,
|
||||
.register-form {
|
||||
@include table-flex-child(1, 200px, 0, 200px);
|
||||
padding: 1rem;
|
||||
|
||||
text-align: center;
|
||||
.form-header {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
.register-form {
|
||||
fieldset {
|
||||
&:last-child {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.register-text {
|
||||
@extend %small;
|
||||
color: $white;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
.login-main {
|
||||
//@include table-flex(center, center, flex, row, wrap, center);
|
||||
@include display(flex);
|
||||
|
@ -60,11 +58,7 @@
|
|||
.button {
|
||||
color: $white;
|
||||
display: block;
|
||||
margin-bottom: .5rem;
|
||||
text-align: center;
|
||||
&:hover {
|
||||
background: $fresh-taiga;
|
||||
}
|
||||
}
|
||||
a {
|
||||
&:hover {
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
.admin-third-parties {
|
||||
form {
|
||||
margin-top: 1rem;
|
||||
max-width: 700px;
|
||||
width: 100%;
|
||||
}
|
||||
input[type="text"],
|
||||
textarea {
|
||||
@extend %title;
|
||||
}
|
||||
fieldset {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
label {
|
||||
@extend %title;
|
||||
display: block;
|
||||
margin-bottom: .2rem;
|
||||
}
|
||||
textarea {
|
||||
height: 10rem;
|
||||
}
|
||||
.button-green {
|
||||
color: $white;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
.select-input-text {
|
||||
.field-with-option {
|
||||
@include display(flex);
|
||||
}
|
||||
.option-wrapper {
|
||||
@include display(flex);
|
||||
@include align-items(center);
|
||||
border: 1px solid $gray-light;
|
||||
border-left: 0;
|
||||
border-radius: 0 5px 5px 0;
|
||||
cursor: pointer;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
.help-copy {
|
||||
@extend %small;
|
||||
opacity: 0;
|
||||
&.visible {
|
||||
@include transition(opacity .2s linear);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.help {
|
||||
margin-top: 2rem;
|
||||
h3 {
|
||||
font-family: opensans-semibold;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
ol {
|
||||
padding: 0 0 0 2rem;
|
||||
span {
|
||||
font-family: opensans-semibold;
|
||||
}
|
||||
}
|
||||
.img {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.alt-image {
|
||||
@extend %small;
|
||||
font-style: italic;
|
||||
}
|
||||
code {
|
||||
@extend %small;
|
||||
background: $whitish;
|
||||
direction: ltr;
|
||||
display: block;
|
||||
font-family: 'courier new', 'monospace';
|
||||
line-height: 1.4rem;
|
||||
margin-bottom: 1rem;
|
||||
padding: .5rem;
|
||||
unicode-bidi: embed;
|
||||
white-space: pre;
|
||||
width: 100%;
|
||||
}
|
||||
.code-info {
|
||||
padding-left: 1rem;
|
||||
li {
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
span {
|
||||
font-family: opensans-semibold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
.login-form-container {
|
||||
//display: none;
|
||||
.login-password {
|
||||
position: relative;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,10 @@
|
|||
display: block;
|
||||
}
|
||||
}
|
||||
.status-slug {
|
||||
@include table-flex-child(6, 150px, 0);
|
||||
padding: 0 10px;
|
||||
}
|
||||
.options-column {
|
||||
max-width: 100px;
|
||||
opacity: 0;
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
.blocked {
|
||||
.external-reference {
|
||||
color: $white;
|
||||
a {
|
||||
@include transition(color .3s linear);
|
||||
color: $white;
|
||||
&:hover {
|
||||
color: $red-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.external-reference {
|
||||
@extend %small;
|
||||
color: $gray-light;
|
||||
margin-top: .5rem;
|
||||
a {
|
||||
@include transition(color .3s linear);
|
||||
border-left: 1px solid $gray-light;
|
||||
padding: 0 .2rem;
|
||||
&:hover {
|
||||
color: $green-taiga;
|
||||
}
|
||||
&:first-child {
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,5 +6,6 @@
|
|||
"feedbackEnabled": true,
|
||||
"privacyPolicyUrl": null,
|
||||
"termsOfServiceUrl": null,
|
||||
"maxUploadFileSize": null
|
||||
"maxUploadFileSize": null,
|
||||
"gitHubClientId": null
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ paths.coffee = [
|
|||
paths.app + "coffee/modules/base/*.coffee",
|
||||
paths.app + "coffee/modules/resources/*.coffee",
|
||||
paths.app + "coffee/modules/user-settings/*.coffee"
|
||||
paths.app + "coffee/modules/integrations/*.coffee"
|
||||
paths.app + "plugins/**/*.coffee"
|
||||
]
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ exports.files = function () {
|
|||
'modules/common/related-tasks',
|
||||
'modules/common/history',
|
||||
'modules/common/wizard',
|
||||
'modules/common/external-reference',
|
||||
|
||||
//Project modules
|
||||
'modules/home-projects-list',
|
||||
|
@ -120,6 +121,7 @@ exports.files = function () {
|
|||
'modules/admin/admin-project-profile',
|
||||
'modules/admin/default-values',
|
||||
'modules/admin/project-values',
|
||||
'modules/admin/third-parties',
|
||||
|
||||
//Modules user Settings
|
||||
'modules/user-settings/user-profile',
|
||||
|
|
Loading…
Reference in New Issue