Merge branch 'master' of github.com:taigaio/taiga-front

stable
Xavier Julián 2015-04-09 11:53:14 +02:00
commit b6bedb3aec
245 changed files with 2877 additions and 1916 deletions

View File

@ -36,7 +36,7 @@ taiga.generateUniqueSessionIdentifier = ->
taiga.sessionId = taiga.generateUniqueSessionIdentifier()
configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEventsProvider, tgLoaderProvider, $compileProvider) ->
configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEventsProvider, tgLoaderProvider, $compileProvider, $translateProvider) ->
$routeProvider.when("/",
{templateUrl: "project/projects.html", resolve: {loader: tgLoaderProvider.add()}})
@ -236,23 +236,33 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
$compileProvider.debugInfoEnabled(window.taigaConfig.debugInfo || false)
init = ($log, $i18n, $config, $rootscope, $auth, $events, $analytics) ->
$i18n.initialize($config.get("defaultLanguage"))
$translateProvider.useStaticFilesLoader({
prefix: '/locales/locale-',
suffix: '.json'
})
$translateProvider.preferredLanguage('en')
init = ($log, $config, $rootscope, $auth, $events, $analytics, $translate) ->
$log.debug("Initialize application")
$rootscope.contribPlugins = @.taigaContribPlugins
if $auth.isAuthenticated()
$events.setupConnection()
user = $auth.getUser()
$translate.use(user.lang) if user.lang
$analytics.initialize()
modules = [
# Main Global Modules
"taigaBase",
"taigaCommon",
"taigaResources",
"taigaLocales",
"taigaAuth",
"taigaEvents",
@ -281,6 +291,7 @@ modules = [
# Vendor modules
"ngRoute",
"ngAnimate",
"pascalprecht.translate"
].concat(_.map(@.taigaContribPlugins, (plugin) -> plugin.module))
# Main module definition
@ -294,16 +305,17 @@ module.config([
"$tgEventsProvider",
"tgLoaderProvider",
"$compileProvider",
"$translateProvider",
configure
])
module.run([
"$log",
"$tgI18n",
"$tgConfig",
"$rootScope",
"$tgAuth",
"$tgEvents",
"$tgAnalytics",
"$translate"
init
])

View File

@ -30,10 +30,10 @@ MAX_MEMBERSHIP_FIELDSETS = 4
## Create Members Lightbox Directive
#############################################################################
CreateMembersDirective = ($rs, $rootScope, $confirm, $loading ,lightboxService) ->
CreateMembersDirective = ($rs, $rootScope, $confirm, $loading ,lightboxService, $compile) ->
extraTextTemplate = """
<fieldset class="extra-text">
<textarea placeholder="(Optional) Add a personalized text to the invitation. Tell something lovely to your new members ;-)"
<textarea placeholder="{{'LIGHTBOX.CREATE_MEMBER.PLACEHOLDER_INVITATION_TEXT' | translate}}"
maxlength="255">
</textarea>
</fieldset>
@ -42,7 +42,7 @@ CreateMembersDirective = ($rs, $rootScope, $confirm, $loading ,lightboxService)
template = _.template("""
<div class="add-member-wrapper">
<fieldset>
<input type="email" placeholder="Type an Email" <% if(required) { %> data-required="true" <% } %> data-type="email" />
<input type="email" placeholder="{{'LIGHTBOX.CREATE_MEMBER.PLACEHOLDER_TYPE_EMAIL'}}" <% if(required) { %> data-required="true" <% } %> data-type="email" />
</fieldset>
<fieldset>
<select <% if(required) { %> data-required="true" <% } %> data-required="true">
@ -53,19 +53,19 @@ CreateMembersDirective = ($rs, $rootScope, $confirm, $loading ,lightboxService)
<a class="icon icon-plus add-fieldset" href=""></a>
</fieldset>
</div>
""") # i18n
""")
link = ($scope, $el, $attrs) ->
createFieldSet = (required = true)->
ctx = {roleList: $scope.roles, required: required}
return template(ctx)
return $compile(template(ctx))($scope)
resetForm = ->
$el.find("form textarea").remove("")
$el.find("form .add-member-wrapper").remove()
invitations = $el.find(".add-member-forms")
invitations.html(extraTextTemplate)
invitations.html($compile(extraTextTemplate)($scope))
fieldSet = createFieldSet()
invitations.prepend(fieldSet)
@ -155,5 +155,5 @@ CreateMembersDirective = ($rs, $rootScope, $confirm, $loading ,lightboxService)
return {link: link}
module.directive("tgLbCreateMembers", ["$tgResources", "$rootScope", "$tgConfirm", "$tgLoading", "lightboxService",
module.directive("tgLbCreateMembers", ["$tgResources", "$rootScope", "$tgConfirm", "$tgLoading", "lightboxService", "$compile",
CreateMembersDirective])

View File

@ -50,7 +50,6 @@ class MembershipsController extends mixOf(taiga.Controller, taiga.PageMixin, tai
@location, @navUrls, @analytics, @appTitle) ->
bindMethods(@)
@scope.sectionName = "Manage Members" #i18n
@scope.project = {}
@scope.filters = {}
@ -338,32 +337,31 @@ module.directive("tgMembershipsRowRoleSelector", ["$log", "$tgRepo", "$tgConfirm
## Member Actions Directive
#############################################################################
MembershipsRowActionsDirective = ($log, $repo, $rs, $confirm) ->
activedTemplate = _.template("""
<div class="active">
Active
MembershipsRowActionsDirective = ($log, $repo, $rs, $confirm, $compile, $translate) ->
activedTemplate = """
<div class="active", translate="ADMIN.MEMBERSHIP.STATUS_ACTIVE">
</div>
<a class="delete" href="">
<span class="icon icon-delete"></span>
</a>
""") # TODO: i18n
"""
pendingTemplate = _.template("""
pendingTemplate = """
<a class="pending" href="">
Pending
{{'ADMIN.MEMBERSHIP.STATUS_PENDING' | translate}}
<span class="icon icon-reload"></span>
</a>
<a class="delete" href="" title="Delete">
<a class="delete" href="">
<span class="icon icon-delete"></span>
</a>
""") # TODO: i18n
"""
link = ($scope, $el, $attrs) ->
render = (member) ->
if member.user
html = activedTemplate()
html = $compile(activedTemplate)($scope)
else
html = pendingTemplate()
html = $compile(pendingTemplate)($scope)
$el.html(html)
@ -377,29 +375,34 @@ MembershipsRowActionsDirective = ($log, $repo, $rs, $confirm) ->
$el.on "click", ".pending", (event) ->
event.preventDefault()
onSuccess = ->
# TODO: i18n
$confirm.notify("success", "We've sent the invitationi again to '#{$scope.member.email}'.")
text = $translate.instant("ADMIN.MEMBERSHIP.SUCCESS_SEND_INVITATION", {email: $scope.member.email})
$confirm.notify("success", text)
onError = ->
$confirm.notify("error", "We haven't sent the invitation.") # TODO: i18n
text = $translate.instant("ADMIM.MEMBERSHIP.ERROR_SEND_INVITATION")
$confirm.notify("error", text)
$rs.memberships.resendInvitation($scope.member.id).then(onSuccess, onError)
$el.on "click", ".delete", (event) ->
event.preventDefault()
title = "Delete member" # TODO: i18n
message = if member.user then member.full_name else "the invitation to #{member.email}" # TODO: i18n
title = $translate.instant("ADMIN.MEMBERSHIP.DELETE_MEMBER")
defaultMsg = $translate.instant("ADMIN.MEMBERSHIP.DEFAULT_DELETE_MESSAGE")
message = if member.user then member.full_name else defaultMsg
$confirm.askOnDelete(title, message).then (finish) ->
onSuccess = ->
finish()
$ctrl.loadMembers()
$confirm.notify("success", null, "We've deleted #{message}.") # TODO: i18n
text = $translate.instant("ADMIN.MEMBERSHIP.SUCCESS_DELETE")
$confirm.notify("success", null, text)
onError = ->
finish(false)
# TODO: i18in
$confirm.notify("error", null, "We have not been able to delete #{message}.")
text = $translate.instant("ADMIN.MEMBERSHIP.ERROR_DELETE", {message: message})
$confirm.notify("error", null, text)
$repo.remove(member).then(onSuccess, onError)
@ -409,5 +412,4 @@ MembershipsRowActionsDirective = ($log, $repo, $rs, $confirm) ->
return {link: link}
module.directive("tgMembershipsRowActions", ["$log", "$tgRepo", "$tgResources", "$tgConfirm",
MembershipsRowActionsDirective])
module.directive("tgMembershipsRowActions", ["$log", "$tgRepo", "$tgResources", "$tgConfirm", "$compile", "$translate", MembershipsRowActionsDirective])

View File

@ -47,21 +47,26 @@ class ProjectProfileController extends mixOf(taiga.Controller, taiga.PageMixin)
"$q",
"$tgLocation",
"$tgNavUrls",
"$appTitle"
"$appTitle",
"$translate"
]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @appTitle) ->
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @appTitle, @translate) ->
@scope.project = {}
promise = @.loadInitialData()
promise.then =>
@appTitle.set("Project profile - " + @scope.sectionName + " - " + @scope.project.name)
sectionName = @translate.instant( @scope.sectionName)
appTitle = @translate.instant("ADMIN.PROJECT_PROFILE.PAGE_TITLE", {sectionName: sectionName, projectName: @scope.project.name})
@appTitle.set(appTitle)
promise.then null, @.onInitialDataError.bind(@)
@scope.$on "project:loaded", =>
@appTitle.set("Project profile - " + @scope.sectionName + " - " + @scope.project.name)
sectionName = @translate.instant( @scope.sectionName)
appTitle = @translate.instant("ADMIN.PROJECT_PROFILE.PAGE_TITLE", {sectionName: sectionName, projectName: @scope.project.name})
@appTitle.set(appTitle)
loadProject: ->
return @rs.projects.get(@scope.projectId).then (project) =>
@ -217,7 +222,7 @@ module.directive("tgProjectModules", ["$tgRepo", "$tgConfirm", "$tgLoading", Pro
## Project Export Directive
#############################################################################
ProjectExportDirective = ($window, $rs, $confirm) ->
ProjectExportDirective = ($window, $rs, $confirm, $translate) ->
link = ($scope, $el, $attrs) ->
buttonsEl = $el.find(".admin-project-export-buttons")
showButtons = -> buttonsEl.removeClass("hidden")
@ -232,16 +237,22 @@ ProjectExportDirective = ($window, $rs, $confirm) ->
hideSpinner = -> spinnerEl.addClass("hidden")
resultTitleEl = $el.find(".result-title")
setLoadingTitle = -> resultTitleEl.html("We are generating your dump file") # TODO: i18n
setAsyncTitle = -> resultTitleEl.html("We are generating your dump file") # TODO: i18n
setSyncTitle = -> resultTitleEl.html("Your dump file is ready!") # TODO: i18n
loading_title = $translate.instant("ADMIN.PROJECT_EXPORT.LOADING_TITLE")
loading_msg = $translate.instant("ADMIN.PROJECT_EXPORT.LOADING_MESSAGE")
dump_ready_text = -> resultTitleEl.html("ADMIN.PROJECT_EXPORT.DUMP_READY")
asyn_message = -> resultTitleEl.html("ADMIN.PROJECT_EXPORT.ASYN_MESSAGE")
syn_message = -> resultTitleEl.html("ADMIN.PROJECT_EXPORT.SYNC_MESSAGE", {url: url})
setLoadingTitle = -> resultTitleEl.html(loading_text)
setAsyncTitle = -> resultTitleEl.html(loading_text)
setSyncTitle = -> resultTitleEl.html(dump_ready_text)
resultMessageEl = $el.find(".result-message ")
setLoadingMessage = -> resultMessageEl.html("Please don't close this page.") # TODO: i18n
setAsyncMessage = -> resultMessageEl.html("We will send you an email when ready.") # TODO: i18n
setSyncMessage = (url) -> resultMessageEl.html("If the download doesn't start automatically click
<a href='#{url}' download title='Download
the dump file'>here.") # TODO: i18n
setLoadingMessage = -> resultMessageEl.html(loading_msg)
setAsyncMessage = -> resultMessageEl.html(asyn_message)
setSyncMessage = (url) -> resultMessageEl.html(syn_message)
showLoadingMode = ->
showSpinner()
@ -279,15 +290,12 @@ ProjectExportDirective = ($window, $rs, $confirm) ->
onError = (result) =>
showErrorMode()
errorMsg = "Our oompa loompas have some problems generasting your dump.
Please try again. " # TODO: i18n
errorMsg = $translate.instant("ADMIN.PROJECT_PROFILE.ERROR")
if result.status == 429 # TOO MANY REQUESTS
errorMsg = "Sorry, our oompa loompas are very busy right now.
Please try again in a few minutes. " # TODO: i18n
errorMsg = $translate.instant("ADMIN.PROJECT_PROFILE.ERROR_BUSY")
else if result.data?._error_message
errorMsg = "Our oompa loompas have some problems generasting your dump:
#{result.data._error_message}" # TODO: i18n
errorMsg = $translate.instant("ADMIN.PROJECT_PROFILE.ERROR_BUSY", {message: result.data._error_message})
$confirm.notify("error", errorMsg)
@ -296,7 +304,7 @@ ProjectExportDirective = ($window, $rs, $confirm) ->
return {link:link}
module.directive("tgProjectExport", ["$window", "$tgResources", "$tgConfirm", ProjectExportDirective])
module.directive("tgProjectExport", ["$window", "$tgResources", "$tgConfirm", "$translate", ProjectExportDirective])
#############################################################################
@ -310,9 +318,10 @@ class CsvExporterController extends taiga.Controller
"$tgUrls",
"$tgConfirm",
"$tgResources",
"$translate"
]
constructor: (@scope, @rootscope, @urls, @confirm, @rs) ->
constructor: (@scope, @rootscope, @urls, @confirm, @rs, @translate) ->
@rootscope.$on("project:loaded", @.setCsvUuid)
@scope.$watch "csvUuid", (value) =>
if value
@ -337,10 +346,10 @@ class CsvExporterController extends taiga.Controller
return promise
regenerateUuid: ->
#TODO: i18n
if @scope.csvUuid
title = "Change URL"
subtitle = "You going to change the CSV data access url. The previous url will be disabled. Are you sure?"
title = @translate.instant("ADMIN.REPORTS.REGENERATE_TITLE")
subtitle = @translate.instant("ADMIN.REPORTS.REGENERATE_SUBTITLE")
@confirm.ask(title, subtitle).then @._generateUuid
else
@._generateUuid(_.identity)
@ -361,3 +370,48 @@ class CsvExporterIssuesController extends CsvExporterController
module.controller("CsvExporterUserstoriesController", CsvExporterUserstoriesController)
module.controller("CsvExporterTasksController", CsvExporterTasksController)
module.controller("CsvExporterIssuesController", CsvExporterIssuesController)
#############################################################################
## CSV Directive
#############################################################################
CsvUsDirective = () ->
link = ($scope) ->
$scope.csvType = "US"
return {
controller: "CsvExporterUserstoriesController",
templateUrl: "admin/project-csv.html",
link: link,
scope: true
}
module.directive("tgCsvUs", [CsvUsDirective])
CsvTaskDirective = () ->
link = ($scope) ->
$scope.csvType = "Task"
return {
controller: "CsvExporterTasksController",
templateUrl: "admin/project-csv.html",
link: link,
scope: true
}
module.directive("tgCsvTask", [CsvTaskDirective])
CsvIssueDirective = () ->
link = ($scope) ->
$scope.csvType = "Issues"
return {
controller: "CsvExporterIssuesController",
templateUrl: "admin/project-csv.html",
link: link,
scope: true
}
module.directive("tgCsvIssue", [CsvIssueDirective])

View File

@ -46,16 +46,24 @@ class ProjectValuesSectionController extends mixOf(taiga.Controller, taiga.PageM
"$q",
"$tgLocation",
"$tgNavUrls",
"$appTitle"
"$appTitle",
"$translate"
]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @appTitle) ->
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @appTitle, @translate) ->
@scope.project = {}
promise = @.loadInitialData()
promise.then () =>
@appTitle.set("Project values - " + @scope.sectionName + " - " + @scope.project.name)
sectionName = @translate.instant(@scope.sectionName)
title = @translate.instant("ADMIN.PROJECT_VALUES.APP_TITLE", {
"sectionName": sectionName,
"projectName": @scope.project.name
})
@appTitle.set(title)
promise.then null, @.onInitialDataError.bind(@)
@ -275,14 +283,12 @@ ProjectValuesDirective = ($log, $repo, $confirm, $location, animationFrame) ->
if value.id != option.id
choices[option.id] = option.name
#TODO: i18n
title = "Delete value"
subtitle = value.name
replacement = "All items with this value will be changed to"
if _.keys(choices).length == 0
return $confirm.error("You can't delete all values.")
return $confirm.askChoice(title, subtitle, choices, replacement).then (response) ->
if _.keys(choices).length == 0
return $confirm.error("ADMIN.PROJECT_VALUES.ERROR_DELETE_ALL")
$confirm.askChoice("PROJECT.TITLE_ACTION_DELETE_VALUE", subtitle, choices, "ADMIN.PROJECT_VALUES.REPLACEMENT").then (response) ->
onSucces = ->
$ctrl.loadValues().finally ->
response.finish()
@ -299,8 +305,7 @@ ProjectValuesDirective = ($log, $repo, $confirm, $location, animationFrame) ->
return {link:link}
module.directive("tgProjectValues", ["$log", "$tgRepo", "$tgConfirm", "$tgLocation", "animationFrame",
ProjectValuesDirective])
module.directive("tgProjectValues", ["$log", "$tgRepo", "$tgConfirm", "$tgLocation", "animationFrame", ProjectValuesDirective])
#############################################################################
@ -601,11 +606,9 @@ ProjectCustomAttributesDirective = ($log, $confirm, animationFrame) ->
deleteCustomAttribute = (formEl) ->
attr = formEl.scope().attr
title = "Delete custom attribute" # i18n
subtitle = "Remeber that all values in this custom field will be deleted.</br> Are you sure you want to continue?"
message = attr.name
$confirm.ask(title, subtitle, message).then (finish) ->
$confirm.ask("COMMON.CUSTOM_ATTRIBUTES.DELETE", "COMMON.CUSTOM_ATTRIBUTES.CONFIRM_DELETE", message).then (finish) ->
onSucces = ->
$ctrl.loadCustomAttributes().finally ->
finish()

View File

@ -44,20 +44,22 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil
"$q",
"$tgLocation",
"$tgNavUrls",
"$appTitle"
"$appTitle",
"$translate"
]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @appTitle) ->
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @appTitle, @translate) ->
bindMethods(@)
@scope.sectionName = "Permissions" #i18n
@scope.sectionName = "ADMIN.MENU.PERMISSIONS"
@scope.project = {}
@scope.anyComputableRole = true
promise = @.loadInitialData()
promise.then () =>
@appTitle.set("Roles - " + @scope.project.name)
title = @translate.instant("ADMIN.ROLES.SECTION_NAME", {projectName: @scope.project.name})
@appTitle.set(title)
promise.then null, @.onInitialDataError.bind(@)
@ -112,11 +114,7 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil
@scope.$broadcast("role:changed", @scope.role)
delete: ->
# TODO: i18n
title = "Delete Role" # TODO: i18n
subtitle = @scope.role.name
replacement = "All the users with this role will be moved to" # TODO: i18n
warning = "<strong>Be careful, all role estimations will be removed</strong>" # TODO: i18n
choices = {}
for role in @scope.roles
@ -124,9 +122,9 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil
choices[role.id] = role.name
if _.keys(choices).length == 0
return @confirm.error("You can't delete all values.") # TODO: i18n
return @confirm.error(@translate.instant("ADMIN.ROLES.ERROR_DELETE_ALL"))
return @confirm.askChoice(title, subtitle, choices, replacement, warning).then (response) =>
return @confirm.askChoice(@translate.instant("ADMIN.ROLES.TITLE_DELETE_ROLE"), subtitle, choices, @translate.instant("ADMIN.ROLES.REPLACEMENT_ROLE"), @translate.instant("ADMIN.ROLES.WARNING_DELETE_ROLE")).then (response) =>
promise = @repo.remove(@scope.role, {moveTo: response.selected})
promise.then =>
@.loadProject()

View File

@ -40,19 +40,21 @@ class WebhooksController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.
"$routeParams",
"$tgLocation",
"$tgNavUrls",
"$appTitle"
"$appTitle",
"$translate"
]
constructor: (@scope, @repo, @rs, @params, @location, @navUrls, @appTitle) ->
constructor: (@scope, @repo, @rs, @params, @location, @navUrls, @appTitle, @translate) ->
bindMethods(@)
@scope.sectionName = "Webhooks" #i18n
@scope.sectionName = "ADMIN.WEBHOOKS.SECTION_NAME"
@scope.project = {}
promise = @.loadInitialData()
promise.then () =>
@appTitle.set("Webhooks - " + @scope.project.name)
text = @translate.instant("ADMIN.WEBHOOKS.APP_TITLE", {"projectName": @scope.project.name})
@appTitle.set(text)
promise.then null, @.onInitialDataError.bind(@)
@ -85,17 +87,19 @@ module.controller("WebhooksController", WebhooksController)
## Webhook Directive
#############################################################################
WebhookDirective = ($rs, $repo, $confirm, $loading) ->
WebhookDirective = ($rs, $repo, $confirm, $loading, $translate) ->
link = ($scope, $el, $attrs) ->
webhook = $scope.$eval($attrs.tgWebhook)
updateLogs = () ->
prettyDate = $translate.instant("ADMIN.WEBHOOKS.DATE")
$rs.webhooklogs.list(webhook.id).then (webhooklogs) =>
for log in webhooklogs
log.validStatus = 200 <= log.status < 300
log.prettySentHeaders = _.map(_.pairs(log.request_headers), ([header, value]) -> "#{header}: #{value}").join("\n")
log.prettySentData = JSON.stringify(log.request_data)
log.prettyDate = moment(log.created).format("DD MMM YYYY [at] hh:mm:ss") # TODO: i18n
log.prettyDate = moment(log.created).format(prettyDate)
webhook.logs_counter = webhooklogs.length
webhook.logs = webhooklogs
@ -105,9 +109,11 @@ WebhookDirective = ($rs, $repo, $confirm, $loading) ->
textElement = $el.find(".toggle-history")
historyElement = textElement.parents(".single-webhook-wrapper").find(".webhooks-history")
if historyElement.hasClass("open")
textElement.text("(Hide history)") # TODO: i18n
text = $translate.instant("ADMIN.WEBHOOKS.ACTION_HIDE_HISTORY")
textElement.text(text)
else
textElement.text("(Show history)") # TODO: i18n
text = $translate.instant("ADMIN.WEBHOOKS.ACTION_SHOW_HISTORY")
textElement.text(text)
showVisualizationMode = () ->
$el.find(".edition-mode").addClass("hidden")
@ -161,8 +167,8 @@ WebhookDirective = ($rs, $repo, $confirm, $loading) ->
cancel(target)
$el.on "click", ".delete-webhook", () ->
title = "Delete webhook" #TODO: i18n
message = "Webhook '#{webhook.name}'" #TODO: i18n
title = $translate.instant("ADMIN.WEBHOOKS.DELETE")
message = $translate.instant("ADMIN.WEBHOOKS.WEBHOOK_NAME", {name: webhook.name})
$confirm.askOnDelete(title, message).then (finish) =>
onSucces = ->
@ -203,7 +209,7 @@ WebhookDirective = ($rs, $repo, $confirm, $loading) ->
return {link:link}
module.directive("tgWebhook", ["$tgResources", "$tgRepo", "$tgConfirm", "$tgLoading", WebhookDirective])
module.directive("tgWebhook", ["$tgResources", "$tgRepo", "$tgConfirm", "$tgLoading", "$translate", WebhookDirective])
#############################################################################
@ -279,19 +285,21 @@ class GithubController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
"$tgRepo",
"$tgResources",
"$routeParams",
"$appTitle"
"$appTitle",
"$translate"
]
constructor: (@scope, @repo, @rs, @params, @appTitle) ->
constructor: (@scope, @repo, @rs, @params, @appTitle, @translate) ->
bindMethods(@)
@scope.sectionName = "Github" #i18n
@scope.sectionName = @translate.instant("ADMIN.GITHUB.SECTION_NAME")
@scope.project = {}
promise = @.loadInitialData()
promise.then () =>
@appTitle.set("Github - " + @scope.project.name)
title = @translate.instant("ADMIN.GITHUB.APP_TITLE", {projectName: @scope.project.name})
@appTitle.set(title)
promise.then null, @.onInitialDataError.bind(@)
@ -327,18 +335,20 @@ class GitlabController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
"$tgRepo",
"$tgResources",
"$routeParams",
"$appTitle"
"$appTitle",
"$translate"
]
constructor: (@scope, @repo, @rs, @params, @appTitle) ->
constructor: (@scope, @repo, @rs, @params, @appTitle, @translate) ->
bindMethods(@)
@scope.sectionName = "Gitlab" #i18n
@scope.sectionName = @translate.instant("ADMIN.GITLAB.SECTION_NAME")
@scope.project = {}
promise = @.loadInitialData()
promise.then () =>
@appTitle.set("Gitlab - " + @scope.project.name)
title = @translate.instant("ADMIN.GITLAB.APP_TITLE", {projectName: @scope.project.name})
@appTitle.set(title)
promise.then null, @.onInitialDataError.bind(@)
@ -377,18 +387,20 @@ class BitbucketController extends mixOf(taiga.Controller, taiga.PageMixin, taiga
"$tgRepo",
"$tgResources",
"$routeParams",
"$appTitle"
"$appTitle",
"$translate"
]
constructor: (@scope, @repo, @rs, @params, @appTitle) ->
constructor: (@scope, @repo, @rs, @params, @appTitle, @translate) ->
bindMethods(@)
@scope.sectionName = "Bitbucket" #i18n
@scope.sectionName = @translate.instant("ADMIN.BITBUCKET.SECTION_NAME")
@scope.project = {}
promise = @.loadInitialData()
promise.then () =>
@appTitle.set("Bitbucket - " + @scope.project.name)
title = @translate.instant("ADMIN.BITBUCKET.APP_TITLE", {projectName: @scope.project.name})
@appTitle.set(title)
promise.then null, @.onInitialDataError.bind(@)

View File

@ -53,7 +53,6 @@ class AuthService extends taiga.Service
setUser: (user) ->
@rootscope.auth = user
@rootscope.$broadcast("i18n:change", user.default_language)
@storage.set("userInfo", user.getAttrs())
@rootscope.user = user
@ -171,7 +170,7 @@ PublicRegisterMessageDirective = ($config, $navUrls, templates) ->
module.directive("tgPublicRegisterMessage", ["$tgConfig", "$tgNavUrls", "$tgTemplate", PublicRegisterMessageDirective])
LoginDirective = ($auth, $confirm, $location, $config, $routeParams, $navUrls, $events) ->
LoginDirective = ($auth, $confirm, $location, $config, $routeParams, $navUrls, $events, $translate) ->
link = ($scope, $el, $attrs) ->
onSuccess = (response) ->
if $routeParams['next'] and $routeParams['next'] != $navUrls.resolve("login")
@ -183,8 +182,8 @@ LoginDirective = ($auth, $confirm, $location, $config, $routeParams, $navUrls, $
$location.path(nextUrl)
onError = (response) ->
$confirm.notify("light-error", "According to our Oompa Loompas, your username/email
or password are incorrect.") #TODO: i18n
$confirm.notify("light-error", $translate.instant("LOGIN_FORM.ERROR_AUTH_INCORRECT"))
submit = debounce 2000, (event) =>
event.preventDefault()
@ -207,13 +206,13 @@ LoginDirective = ($auth, $confirm, $location, $config, $routeParams, $navUrls, $
return {link:link}
module.directive("tgLogin", ["$tgAuth", "$tgConfirm", "$tgLocation", "$tgConfig", "$routeParams",
"$tgNavUrls", "$tgEvents", LoginDirective])
"$tgNavUrls", "$tgEvents", "$translate", LoginDirective])
#############################################################################
## Register Directive
#############################################################################
RegisterDirective = ($auth, $confirm, $location, $navUrls, $config, $analytics) ->
RegisterDirective = ($auth, $confirm, $location, $navUrls, $config, $analytics, $translate) ->
link = ($scope, $el, $attrs) ->
if not $config.get("publicRegisterEnabled")
$location.path($navUrls.resolve("not-found"))
@ -224,12 +223,15 @@ RegisterDirective = ($auth, $confirm, $location, $navUrls, $config, $analytics)
onSuccessSubmit = (response) ->
$analytics.trackEvent("auth", "register", "user registration", 1)
$confirm.notify("success", "Our Oompa Loompas are happy, welcome to Taiga.") #TODO: i18n
$confirm.notify("success", $translate.instant("LOGIN_FORM.SUCCESS"))
$location.path($navUrls.resolve("home"))
onErrorSubmit = (response) ->
if response.data._error_message?
$confirm.notify("light-error", "According to our Oompa Loompas there was an error. #{response.data._error_message}") #TODO: i18n
text = $translate.instant("LOGIN_FORM.ERROR_GENERIC") + " " + response.data._error_message
$confirm.notify("light-error", text + " " + response.data._error_message)
form.setErrors(response.data)
@ -247,27 +249,27 @@ RegisterDirective = ($auth, $confirm, $location, $navUrls, $config, $analytics)
return {link:link}
module.directive("tgRegister", ["$tgAuth", "$tgConfirm", "$tgLocation", "$tgNavUrls", "$tgConfig",
"$tgAnalytics", RegisterDirective])
"$tgAnalytics", "$translate", RegisterDirective])
#############################################################################
## Forgot Password Directive
#############################################################################
ForgotPasswordDirective = ($auth, $confirm, $location, $navUrls) ->
ForgotPasswordDirective = ($auth, $confirm, $location, $navUrls, $translate) ->
link = ($scope, $el, $attrs) ->
$scope.data = {}
form = $el.find("form").checksley()
onSuccessSubmit = (response) ->
$location.path($navUrls.resolve("login"))
$confirm.success("<strong>Check your inbox!</strong><br />
We have sent a mail to<br />
<strong>#{response.data.email}</strong><br />
with the instructions to set a new password") #TODO: i18n
text = $translate.instant("FORGOT_PASSWORD_FORM.SUCCESS", {email: response.data.email})
$confirm.success(text)
onErrorSubmit = (response) ->
$confirm.notify("light-error", "According to our Oompa Loompas,
your are not registered yet.") #TODO: i18n
text = $translate.instant("FORGOT_PASSWORD_FORM.ERROR")
$confirm.notify("light-error", text)
submit = debounce 2000, (event) =>
event.preventDefault()
@ -282,14 +284,14 @@ ForgotPasswordDirective = ($auth, $confirm, $location, $navUrls) ->
return {link:link}
module.directive("tgForgotPassword", ["$tgAuth", "$tgConfirm", "$tgLocation", "$tgNavUrls",
module.directive("tgForgotPassword", ["$tgAuth", "$tgConfirm", "$tgLocation", "$tgNavUrls", "$translate",
ForgotPasswordDirective])
#############################################################################
## Change Password from Recovery Directive
#############################################################################
ChangePasswordFromRecoveryDirective = ($auth, $confirm, $location, $params, $navUrls) ->
ChangePasswordFromRecoveryDirective = ($auth, $confirm, $location, $params, $navUrls, $translate) ->
link = ($scope, $el, $attrs) ->
$scope.data = {}
@ -303,12 +305,15 @@ ChangePasswordFromRecoveryDirective = ($auth, $confirm, $location, $params, $nav
onSuccessSubmit = (response) ->
$location.path($navUrls.resolve("login"))
$confirm.success("Our Oompa Loompas saved your new password.<br />
Try to <strong>sign in</strong> with it.") #TODO: i18n
text = $translate.instant("CHANGE_PASSWORD_RECOVERY_FORM.SUCCESS")
$confirm.success(text)
onErrorSubmit = (response) ->
$confirm.notify("light-error", "One of our Oompa Loompas say
'#{response.data._error_message}'.") #TODO: i18n
text = $translate.instant("COMMON.GENERIC_ERROR", {error: response.data._error_message})
$confirm.notify("light-error", text)
submit = debounce 2000, (event) =>
event.preventDefault()
@ -324,13 +329,13 @@ ChangePasswordFromRecoveryDirective = ($auth, $confirm, $location, $params, $nav
return {link:link}
module.directive("tgChangePasswordFromRecovery", ["$tgAuth", "$tgConfirm", "$tgLocation", "$routeParams",
"$tgNavUrls", ChangePasswordFromRecoveryDirective])
"$tgNavUrls", "$translate", ChangePasswordFromRecoveryDirective])
#############################################################################
## Invitation
#############################################################################
InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics) ->
InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics, $translate) ->
link = ($scope, $el, $attrs) ->
token = $params.token
@ -340,8 +345,9 @@ InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics
promise.then null, (response) ->
$location.path($navUrls.resolve("login"))
$confirm.success("<strong>Ooops, we have a problem</strong><br />
Our Oompa Loompas can't find your invitation.") #TODO: i18n
text = $translate.instant("INVITATION_LOGIN_FORM.NOT_FOUND")
$confirm.success(text)
# Login form
$scope.dataLogin = {token: token}
@ -350,12 +356,14 @@ InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics
onSuccessSubmitLogin = (response) ->
$analytics.trackEvent("auth", "invitationAccept", "invitation accept with existing user", 1)
$location.path($navUrls.resolve("project", {project: $scope.invitation.project_slug}))
$confirm.notify("success", "You've successfully joined this project",
"Welcome to #{_.escape($scope.invitation.project_name)}")
text = $translate.instant("INVITATION_LOGIN_FORM.SUCCESS", {"project_name": $scope.invitation.project_name})
$confirm.notify("success", text)
onErrorSubmitLogin = (response) ->
$confirm.notify("light-error", "According to our Oompa Loompas, your are not registered yet or
typed an invalid password.") #TODO: i18n
text = $translate.instant("INVITATION_LOGIN_FORM.ERROR")
$confirm.notify("light-error", text)
submitLogin = debounce 2000, (event) =>
event.preventDefault()
@ -380,8 +388,9 @@ InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics
"Welcome to #{_.escape($scope.invitation.project_name)}")
onErrorSubmitRegister = (response) ->
$confirm.notify("light-error", "According to our Oompa Loompas, that
username or email is already in use.") #TODO: i18n
text = $translate.instant("LOGIN_FORM.ERROR_AUTH_INCORRECT")
$confirm.notify("light-error", text)
submitRegister = debounce 2000, (event) =>
event.preventDefault()
@ -398,13 +407,13 @@ InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics
return {link:link}
module.directive("tgInvitation", ["$tgAuth", "$tgConfirm", "$tgLocation", "$routeParams",
"$tgNavUrls", "$tgAnalytics", InvitationDirective])
"$tgNavUrls", "$tgAnalytics", "$translate", InvitationDirective])
#############################################################################
## Change Email
#############################################################################
ChangeEmailDirective = ($repo, $model, $auth, $confirm, $location, $params, $navUrls) ->
ChangeEmailDirective = ($repo, $model, $auth, $confirm, $location, $params, $navUrls, $translate) ->
link = ($scope, $el, $attrs) ->
$scope.data = {}
$scope.data.email_token = $params.email_token
@ -414,11 +423,14 @@ ChangeEmailDirective = ($repo, $model, $auth, $confirm, $location, $params, $nav
$repo.queryOne("users", $auth.getUser().id).then (data) =>
$auth.setUser(data)
$location.path($navUrls.resolve("home"))
$confirm.success("Our Oompa Loompas updated your email") #TODO: i18n
text = $translate.instant("CHANGE_EMAIL_FORM.SUCCESS")
$confirm.success(text)
onErrorSubmit = (response) ->
$confirm.notify("error", "One of our Oompa Loompas says
'#{response.data._error_message}'.") #TODO: i18n
text = $translate.instant("COMMON.GENERIC_ERROR", {error: response.data._error_message})
$confirm.notify("light-error", text)
submit = ->
if not form.validate()
@ -438,7 +450,7 @@ ChangeEmailDirective = ($repo, $model, $auth, $confirm, $location, $params, $nav
return {link:link}
module.directive("tgChangeEmail", ["$tgRepo", "$tgModel", "$tgAuth", "$tgConfirm", "$tgLocation", "$routeParams",
"$tgNavUrls", ChangeEmailDirective])
"$tgNavUrls", "$translate", ChangeEmailDirective])
#############################################################################
## Cancel account
@ -453,11 +465,15 @@ CancelAccountDirective = ($repo, $model, $auth, $confirm, $location, $params, $n
onSuccessSubmit = (response) ->
$auth.logout()
$location.path($navUrls.resolve("home"))
$confirm.success("Our Oompa Loompas removed your account") #TODO: i18n
text = $translate.instant("CANCEL_ACCOUNT.SUCCESS")
$confirm.success(text)
onErrorSubmit = (response) ->
$confirm.notify("error", "One of our Oompa Loompas says
'#{response.data._error_message}'.") #TODO: i18n
text = $translate.instant("COMMON.GENERIC_ERROR", {error: response.data._error_message})
$confirm.notify("error", text)
submit = debounce 2000, (event) =>
event.preventDefault()

View File

@ -29,7 +29,7 @@ module = angular.module("taigaBacklog")
## Creare/Edit Sprint Lightbox Directive
#############################################################################
CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading) ->
CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading, $translate) ->
link = ($scope, $el, attrs) ->
hasErrors = false
createSprint = true
@ -86,8 +86,7 @@ CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading)
$confirm.notify("light-error", data.__all__[0])
remove = ->
#TODO: i18n
title = "Delete sprint"
title = $translate.instant("LIGHTBOX.DELETE_SPRINT.TITLE")
message = $scope.sprint.name
$confirm.askOnDelete(title, message).then (finish) =>
@ -129,11 +128,17 @@ CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading)
lastSprintNameDom = $el.find(".last-sprint-name")
if lastSprint?.name?
lastSprintNameDom.html(" last sprint is <strong> #{lastSprint.name} ;-) </strong>")
text = $translate.instant("LIGHTBOX.ADD_EDIT_SPRINT.LAST_SPRINT_NAME", {"lastSprint": lastSprint.name})
lastSprintNameDom.html(text)
$el.find(".delete-sprint").addClass("hidden")
$el.find(".title").text("New sprint") #TODO i18n
$el.find(".button-green").text("Create") #TODO i18n
text = $translate.instant("LIGHTBOX.ADD_EDIT_SPRINT.TITLE")
$el.find(".title").text(text)
text = $translate.instant("COMMON.CREATE")
$el.find(".button-green").text(text)
lightboxService.open($el)
$el.find(".sprint-name").focus()
$el.find(".last-sprint-name").removeClass("disappear")
@ -146,8 +151,13 @@ CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading)
$scope.sprint.estimated_finish = moment($scope.sprint.estimated_finish).format("DD MMM YYYY")
$el.find(".delete-sprint").removeClass("hidden")
$el.find(".title").text("Edit sprint") #TODO i18n
$el.find(".button-green").text("Save") #TODO i18n
editSprint = $translate.instant("BACKLOG.EDIT_SPRINT")
$el.find(".title").text(editSprint)
save = $translate.instant("COMMON.SAVE")
$el.find(".button-green").text(save)
lightboxService.open($el)
$el.find(".sprint-name").focus().select()
$el.find(".last-sprint-name").addClass("disappear")
@ -178,6 +188,7 @@ module.directive("tgLbCreateEditSprint", [
"$tgResources",
"$rootScope",
"lightboxService"
"$tgLoading"
"$tgLoading",
"$translate",
CreateEditSprint
])

View File

@ -49,11 +49,12 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
"$tgNavUrls",
"$tgEvents",
"$tgAnalytics",
"tgLoader"
"tgLoader",
"$translate"
]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q,
@location, @appTitle, @navUrls, @events, @analytics, tgLoader) ->
@location, @appTitle, @navUrls, @events, @analytics, tgLoader, @translate) ->
bindMethods(@)
@scope.sectionName = "Backlog"
@ -509,8 +510,8 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
@rootscope.$broadcast("usform:edit", us)
deleteUserStory: (us) ->
#TODO: i18n
title = "Delete User Story"
title = @translate.instant("US.TITLE_DELETE_ACTION")
message = us.subject
@confirm.askOnDelete(title, message).then (finish) =>
@ -541,12 +542,11 @@ module.controller("BacklogController", BacklogController)
## Backlog Directive
#############################################################################
BacklogDirective = ($repo, $rootscope) ->
BacklogDirective = ($repo, $rootscope, $translate) ->
## Doom line Link
doomLineTemplate = _.template("""
<div class="doom-line"><span>Project Scope [Doomline]</span></div>
<div class="doom-line"><span><%- text %></span></div>
""")
# TODO: i18n
linkDoomLine = ($scope, $el, $attrs, $ctrl) ->
reloadDoomLine = ->
@ -573,7 +573,8 @@ BacklogDirective = ($repo, $rootscope) ->
$el.find(".doom-line").remove()
addDoomLineDom = (element) ->
$(element).before(doomLineTemplate({}))
text = $translate.instant("BACKLOG.DOOMLINE")
$(element).before(doomLineTemplate({"text": text}))
getUsItems = ->
rowElements = $el.find('.backlog-table-body .us-item-row')
@ -643,10 +644,14 @@ BacklogDirective = ($repo, $rootscope) ->
if $ctrl.showTags
elm.addClass("active")
elm.find(".text").text("Hide Tags") # TODO: i18n
text = $translate.instant("BACKLOG.TAGS.HIDE")
elm.find(".text").text(text)
else
elm.removeClass("active")
elm.find(".text").text("Show Tags") # TODO: i18n
text = $translate.instant("BACKLOG.TAGS.SHOW")
elm.find(".text").text(text)
showHideFilter = ($scope, $el, $ctrl) ->
sidebar = $el.find("sidebar.filters-bar")
@ -660,7 +665,10 @@ BacklogDirective = ($repo, $rootscope) ->
sidebar.toggleClass("active")
target.toggleClass("active")
toggleText(target.find(".text"), ["Remove Filters", "Show Filters"]) # TODO: i18n
removeText = $translate.instant("BACKLOG.FILTERS.REMOVE")
showText = $translate.instant("BACKLOG.FILTERS.SHOW")
toggleText(target.find(".text"), [removeText, showText])
if !sidebar.hasClass("active")
$ctrl.resetFilters()
@ -701,14 +709,13 @@ BacklogDirective = ($repo, $rootscope) ->
return {link: link}
module.directive("tgBacklog", ["$tgRepo", "$rootScope", BacklogDirective])
module.directive("tgBacklog", ["$tgRepo", "$rootScope", "$translate", BacklogDirective])
#############################################################################
## User story points directive
#############################################################################
UsRolePointsSelectorDirective = ($rootscope, $template) ->
#TODO: i18n
UsRolePointsSelectorDirective = ($rootscope, $template, $compile, $translate) ->
selectionTemplate = $template.get("backlog/us-role-points-popover.html", true)
link = ($scope, $el, $attrs) ->
@ -718,7 +725,7 @@ UsRolePointsSelectorDirective = ($rootscope, $template) ->
numberOfRoles = _.size(roles)
if numberOfRoles > 1
$el.append(selectionTemplate({"roles":roles}))
$el.append($compile(selectionTemplate({"roles": roles}))($scope))
else
$el.find(".icon-arrow-bottom").remove()
$el.find(".header-points").addClass("not-clickable")
@ -729,7 +736,9 @@ UsRolePointsSelectorDirective = ($rootscope, $template) ->
$scope.$on "uspoints:clear-selection", (ctx, roleId) ->
$el.find(".popover").popover().close()
$el.find(".header-points").text("Points") #TODO: i18n
text = $translate.instant("COMMON.FIELDS.POINTS")
$el.find(".header-points").text(text)
# Dom Event Handlers
$el.on "click", (event) ->
@ -757,7 +766,7 @@ UsRolePointsSelectorDirective = ($rootscope, $template) ->
return {link: link}
module.directive("tgUsRolePointsSelector", ["$rootScope", "$tgTemplate", UsRolePointsSelectorDirective])
module.directive("tgUsRolePointsSelector", ["$rootScope", "$tgTemplate", "$compile", UsRolePointsSelectorDirective])
UsPointsDirective = ($tgEstimationsService, $repo, $tgTemplate) ->
@ -866,7 +875,7 @@ module.directive("tgBacklogUsPoints", ["$tgEstimationsService", "$tgRepo", "$tgT
## Burndown graph directive
#############################################################################
tgBacklogGraphDirective = ->
tgBacklogGraphDirective = ($translate) ->
redrawChart = (element, dataToDraw) ->
width = element.width()
element.height(width/6)
@ -946,18 +955,17 @@ tgBacklogGraphDirective = ->
tooltip: true
tooltipOpts: {
content: (label, xval, yval, flotItem) ->
#TODO: i18n
if flotItem.seriesIndex == 1
return "Optimal pending points for sprint #{xval} should be #{yval}"
return $translate.instant("BACKLOG.OPTIMA", {xval: xval, yval: yval})
else if flotItem.seriesIndex == 2
return "Real pending points for sprint #{xval} is #{yval}"
return $translate.instant("BACKLOG.REAL", {xval: xval, yval: yval})
else if flotItem.seriesIndex == 3
return "Incremented points by team requirements for sprint #{xval} is #{Math.abs(yval)}"
return $translate.instant("BACKLOG.INCREMENT_TEAM", {xval: xval, yval: Math.abs(yval)})
else
return "Incremented points by client requirements for sprint #{xval} is #{Math.abs(yval)}"
return $translate.instant("BACKLOG.INCREMENT_CLIENT", {xval: xval, yval: Math.abs(yval)})
}
}
@ -980,7 +988,7 @@ tgBacklogGraphDirective = ->
return {link: link}
module.directive("tgGmBacklogGraph", tgBacklogGraphDirective)
module.directive("tgGmBacklogGraph", ["$translate", tgBacklogGraphDirective])
#############################################################################

View File

@ -39,7 +39,7 @@ deleteElement = (el) ->
el.off()
el.remove()
BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm) ->
BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm, $translate) ->
# Notes about jquery bug:
# http://stackoverflow.com/questions/5791886/jquery-draggable-shows-
# helper-in-wrong-place-when-scrolled-down-page
@ -54,7 +54,8 @@ BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm) ->
return
filterError = ->
$tgConfirm.notify("error", "You can't drop on backlog when filters are open") #TODO: i18n
text = $translate.instant("BACKLOG.SORTABLE_FILTER_ERROR")
$tgConfirm.notify(text)
$el.sortable({
items: ".us-item-row",
@ -211,6 +212,7 @@ module.directive("tgBacklogSortable", [
"$tgResources",
"$rootScope",
"$tgConfirm",
"$translate",
BacklogSortableDirective
])

View File

@ -85,8 +85,8 @@ module.directive("tgBacklogSprint", ["$tgRepo", "$rootScope", BacklogSprintDirec
## Sprint Header Directive
#############################################################################
BacklogSprintHeaderDirective = ($navUrls, $template) ->
template = $template.get("backlog/sprint-header.html", true)
BacklogSprintHeaderDirective = ($navUrls, $template, $compile) ->
template = $template.get("backlog/sprint-header.html")
link = ($scope, $el, $attrs, $model) ->
isEditable = ->
@ -112,8 +112,13 @@ BacklogSprintHeaderDirective = ($navUrls, $template) ->
isVisible: isVisible()
isEditable: isEditable()
}
$el.html(template(ctx))
templateScope = $scope.$new()
_.assign(templateScope, ctx)
compiledTemplate = $compile(template)(templateScope)
$el.html(compiledTemplate)
$scope.$watch $attrs.ngModel, (sprint) ->
render(sprint)
@ -130,13 +135,13 @@ BacklogSprintHeaderDirective = ($navUrls, $template) ->
require: "ngModel"
}
module.directive("tgBacklogSprintHeader", ["$tgNavUrls", "$tgTemplate", BacklogSprintHeaderDirective])
module.directive("tgBacklogSprintHeader", ["$tgNavUrls", "$tgTemplate", "$compile", BacklogSprintHeaderDirective])
#############################################################################
## Toggle Closed Sprints Directive
#############################################################################
ToggleExcludeClosedSprintsVisualization = ($rootscope, $loading) ->
ToggleExcludeClosedSprintsVisualization = ($rootscope, $loading, $translate) ->
excludeClosedSprints = true
link = ($scope, $el, $attrs) ->
@ -162,14 +167,15 @@ ToggleExcludeClosedSprintsVisualization = ($rootscope, $loading) ->
$scope.$on "closed-sprints:reloaded", (ctx, sprints) =>
$loading.finish(loadingElm)
#TODO: i18n
if sprints.length > 0
text = "Hide closed sprints"
key = "BACKLOG.SPRINTS.ACTION_HIDE_CLOSED_SPRINTS"
else
text = "Show closed sprints"
key = "BACKLOG.SPRINTS.ACTION_SHOW_CLOSED_SPRINTS"
text = $translate.instant(key)
$el.find(".text").text(text)
return {link: link}
module.directive("tgBacklogToggleClosedSprintsVisualization", ["$rootScope", "$tgLoading", ToggleExcludeClosedSprintsVisualization])
module.directive("tgBacklogToggleClosedSprintsVisualization", ["$rootScope", "$tgLoading", "$translate", ToggleExcludeClosedSprintsVisualization])

View File

@ -23,7 +23,7 @@ taiga = @.taiga
groupBy = @.taiga.groupBy
bindOnce = @.taiga.bindOnce
module = angular.module("taigaBase", ["taigaLocales"])
module = angular.module("taigaBase", [])
#############################################################################
## Main Directive

View File

@ -1,74 +0,0 @@
###
# 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/base/i18n.coffee
###
taiga = @.taiga
bindOnce = @.taiga.bindOnce
defaults = {
ns: "app"
fallbackLng: "en"
async: false
lng: "en"
}
class I18nService extends taiga.Service
constructor: (@rootscope, localesEn) ->
@.options = _.clone(defaults, true)
@.options.resStore = {
en: { app: localesEn }
}
setLanguage: (language) ->
i18n.setLng(language)
@rootscope.currentLang = language
@rootscope.$broadcast("i18n:changeLang", language)
initialize: ->
i18n.init(@.options)
@rootscope.t = i18n.t
t: (path, opts) ->
return i18n.t(path, opts)
I18nDirective = ($rootscope, $i18n) ->
link = ($scope, $el, $attrs) ->
values = $attrs.tr.split(",")
options = $attrs.trOpts or '{}'
opts = $scope.$eval(options)
for v in values
if v.indexOf(":") == -1
$el.html(_.escape($i18n.t(v, opts)))
else
[ns, v] = v.split(":")
$el.attr(ns, _.escape($i18n.t(v, opts)))
return {
link: link
restrict: "A"
scope: false
}
module = angular.module("taigaBase")
module.service("$tgI18n", ["$rootScope", "localesEn", I18nService])
module.directive("tr", ["$rootScope", "$tgI18n", I18nDirective])

View File

@ -220,8 +220,8 @@ AttachmentsDirective = ($config, $confirm, $templates) ->
templateFn = ($el, $attrs) ->
maxFileSize = $config.get("maxUploadFileSize", null)
maxFileSize = sizeFormat(maxFileSize) if maxFileSize
maxFileSizeMsg = if maxFileSize then "Maximum upload size is #{maxFileSize}" else "" # TODO: i18n
maxFileSizeMsg = if maxFileSize then $translation.instant("ATTACHMENT.MAX_UPLOAD_SIZE") else ""
maxFileSize = 4000
ctx = {
type: $attrs.type
maxFileSize: maxFileSize
@ -242,7 +242,7 @@ AttachmentsDirective = ($config, $confirm, $templates) ->
module.directive("tgAttachments", ["$tgConfig", "$tgConfirm", "$tgTemplate", AttachmentsDirective])
AttachmentDirective = ($template) ->
AttachmentDirective = ($template, $compile) ->
template = $template.get("attachment/attachment.html", true)
templateEdit = $template.get("attachment/attachment-edit.html", true)
@ -254,7 +254,7 @@ AttachmentDirective = ($template) ->
ctx = {
id: attachment.id
name: attachment.name
created_date: moment(attachment.created_date).format("DD MMM YYYY [at] hh:mm") #TODO: i18n
created_date: moment(attachment.created_date).format("ATTACHMENT.DATE")
url: attachment.url
size: sizeFormat(attachment.size)
description: attachment.description
@ -263,9 +263,9 @@ AttachmentDirective = ($template) ->
}
if edit
html = templateEdit(ctx)
html = $compile(templateEdit(ctx))($scope)
else
html = template(ctx)
html = $compile(template(ctx))($scope)
$el.html(html)
@ -322,4 +322,4 @@ AttachmentDirective = ($template) ->
restrict: "AE"
}
module.directive("tgAttachment", ["$tgTemplate", AttachmentDirective])
module.directive("tgAttachment", ["$tgTemplate", "$compile", AttachmentDirective])

View File

@ -107,7 +107,7 @@ module.directive("tgSprintProgressbar", SprintProgressBarDirective)
## Created-by display directive
#############################################################################
CreatedByDisplayDirective = ($template)->
CreatedByDisplayDirective = ($template, $compile)->
# Display the owner information (full name and photo) and the date of
# creation of an object (like USs, tasks and issues).
#
@ -119,7 +119,7 @@ CreatedByDisplayDirective = ($template)->
# 'owner'(ng-model)
# - scope.usersById object is required.
template = $template.get("common/components/created-by.html", true) # TODO: i18n
template = $template.get("common/components/created-by.html", true)
link = ($scope, $el, $attrs) ->
render = (model) ->
@ -127,10 +127,14 @@ CreatedByDisplayDirective = ($template)->
full_name_display: "external user"
photo: "/images/unnamed.png"
}
html = template({
owner: owner
date: moment(model.created_date).format("DD MMM YYYY HH:mm")
})
html = $compile(html)($scope)
$el.html(html)
bindOnce $scope, $attrs.ngModel, (model) ->
@ -145,18 +149,16 @@ CreatedByDisplayDirective = ($template)->
require: "ngModel"
}
module.directive("tgCreatedByDisplay", ["$tgTemplate", CreatedByDisplayDirective])
module.directive("tgCreatedByDisplay", ["$tgTemplate", "$compile", CreatedByDisplayDirective])
#############################################################################
## Watchers directive
#############################################################################
WatchersDirective = ($rootscope, $confirm, $repo, $qqueue, $template) ->
WatchersDirective = ($rootscope, $confirm, $repo, $qqueue, $template, $compile) ->
# You have to include a div with the tg-lb-watchers directive in the page
# where use this directive
#
# TODO: i18n
template = $template.get("common/components/watchers.html", true)
link = ($scope, $el, $attrs, $model) ->
@ -200,7 +202,7 @@ WatchersDirective = ($rootscope, $confirm, $repo, $qqueue, $template) ->
isEditable: isEditable()
}
html = template(ctx)
html = $compile(template(ctx))($scope)
$el.html(html)
if isEditable() and watchers.length == 0
@ -247,18 +249,17 @@ WatchersDirective = ($rootscope, $confirm, $repo, $qqueue, $template) ->
return {link:link, require:"ngModel"}
module.directive("tgWatchers", ["$rootScope", "$tgConfirm", "$tgRepo", "$tgQqueue", "$tgTemplate", WatchersDirective])
module.directive("tgWatchers", ["$rootScope", "$tgConfirm", "$tgRepo", "$tgQqueue", "$tgTemplate", "$compile",
WatchersDirective])
#############################################################################
## Assigned to directive
#############################################################################
AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $qqueue, $template) ->
AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $qqueue, $template, $translate, $compile) ->
# You have to include a div with the tg-lb-assignedto directive in the page
# where use this directive
#
# TODO: i18n
template = $template.get("common/components/assigned-to.html", true)
link = ($scope, $el, $attrs, $model) ->
@ -291,7 +292,7 @@ AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $qqueue, $template
assignedTo: assignedTo
isEditable: isEditable()
}
html = template(ctx)
html = $compile(template(ctx))($scope)
$el.html(html)
$el.on "click", ".user-assigned", (event) ->
@ -303,7 +304,7 @@ AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $qqueue, $template
$el.on "click", ".icon-delete", (event) ->
event.preventDefault()
return if not isEditable()
title = "Are you sure you want to leave it unassigned?" # TODO: i18n
title = $translate.instant("COMMON.ASSIGNED_TO.CONFIRM_UNASSIGNED")
$confirm.ask(title).then (finish) =>
finish()
@ -326,7 +327,8 @@ AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $qqueue, $template
require:"ngModel"
}
module.directive("tgAssignedTo", ["$rootScope", "$tgConfirm", "$tgRepo", "$tgLoading", "$tgQqueue", "$tgTemplate", AssignedToDirective])
module.directive("tgAssignedTo", ["$rootScope", "$tgConfirm", "$tgRepo", "$tgLoading", "$tgQqueue", "$tgTemplate", "$translate", "$compile",
AssignedToDirective])
#############################################################################
@ -392,7 +394,7 @@ DeleteButtonDirective = ($log, $repo, $confirm, $location, $template) ->
return $log.error "DeleteButtonDirective requires on-delete-title set in scope."
$el.on "click", ".button", (event) ->
title = $scope.$eval($attrs.onDeleteTitle)
title = $attrs.onDeleteTitle
subtitle = $model.$modelValue.subject
$confirm.askOnDelete(title, subtitle).then (finish) =>
@ -471,7 +473,6 @@ EditableSubjectDirective = ($rootscope, $repo, $confirm, $loading, $qqueue, $tem
$el.find('div.edit-subject').hide()
$el.find('div.view-subject span.edit').hide()
$scope.$watch $attrs.ngModel, (value) ->
return if not value
$scope.item = value
@ -490,7 +491,8 @@ EditableSubjectDirective = ($rootscope, $repo, $confirm, $loading, $qqueue, $tem
template: template
}
module.directive("tgEditableSubject", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate", EditableSubjectDirective])
module.directive("tgEditableSubject", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue",
"$tgTemplate", EditableSubjectDirective])
#############################################################################
@ -498,9 +500,9 @@ module.directive("tgEditableSubject", ["$rootScope", "$tgRepo", "$tgConfirm", "$
#############################################################################
EditableDescriptionDirective = ($rootscope, $repo, $confirm, $compile, $loading, $selectedText, $qqueue, $template) ->
template = $template.get("common/components/editable-description.html") # TODO: i18n
noDescriptionMegEditMode = $template.get("common/components/editable-description-msg-edit-mode.html") # TODO: i18n
noDescriptionMegReadMode = $template.get("common/components/editable-description-msg-read-mode.html") # TODO: i18n
template = $template.get("common/components/editable-description.html")
noDescriptionMegEditMode = $template.get("common/components/editable-description-msg-edit-mode.html")
noDescriptionMegReadMode = $template.get("common/components/editable-description-msg-read-mode.html")
link = ($scope, $el, $attrs, $model) ->
$el.find('.edit-description').hide()
@ -569,8 +571,8 @@ EditableDescriptionDirective = ($rootscope, $repo, $confirm, $compile, $loading,
template: template
}
module.directive("tgEditableDescription", ["$rootScope", "$tgRepo", "$tgConfirm",
"$compile", "$tgLoading", "$selectedText", "$tgQqueue", "$tgTemplate", EditableDescriptionDirective])
module.directive("tgEditableDescription", ["$rootScope", "$tgRepo", "$tgConfirm", "$compile", "$tgLoading",
"$selectedText", "$tgQqueue", "$tgTemplate", EditableDescriptionDirective])
#############################################################################
@ -580,14 +582,16 @@ module.directive("tgEditableDescription", ["$rootScope", "$tgRepo", "$tgConfirm"
## completely bindonce, they only serves for visualization of data.
#############################################################################
ListItemIssueStatusDirective = ->
ListItemUsStatusDirective = ->
link = ($scope, $el, $attrs) ->
issue = $scope.$eval($attrs.tgListitemIssueStatus)
bindOnce $scope, "issueStatusById", (issueStatusById) ->
$el.html(issueStatusById[issue.status].name)
us = $scope.$eval($attrs.tgListitemUsStatus)
bindOnce $scope, "usStatusById", (usStatusById) ->
$el.html(usStatusById[us.status].name)
return {link:link}
module.directive("tgListitemUsStatus", ListItemUsStatusDirective)
ListItemTaskStatusDirective = ->
link = ($scope, $el, $attrs) ->
@ -597,14 +601,7 @@ ListItemTaskStatusDirective = ->
return {link:link}
ListItemUsStatusDirective = ->
link = ($scope, $el, $attrs) ->
us = $scope.$eval($attrs.tgListitemUsStatus)
bindOnce $scope, "usStatusById", (usStatusById) ->
$el.html(usStatusById[us.status].name)
return {link:link}
module.directive("tgListitemTaskStatus", ListItemTaskStatusDirective)
ListItemAssignedtoDirective = ($template) ->
@ -626,6 +623,41 @@ ListItemAssignedtoDirective = ($template) ->
module.directive("tgListitemAssignedto", ["$tgTemplate", ListItemAssignedtoDirective])
ListItemIssueStatusDirective = ->
link = ($scope, $el, $attrs) ->
issue = $scope.$eval($attrs.tgListitemIssueStatus)
bindOnce $scope, "issueStatusById", (issueStatusById) ->
$el.html(issueStatusById[issue.status].name)
return {link:link}
module.directive("tgListitemIssueStatus", ListItemIssueStatusDirective)
ListItemTypeDirective = ->
link = ($scope, $el, $attrs) ->
render = (issueTypeById, issue) ->
type = issueTypeById[issue.type]
domNode = $el.find(".level")
domNode.css("background-color", type.color)
domNode.attr("title", type.name)
bindOnce $scope, "issueTypeById", (issueTypeById) ->
issue = $scope.$eval($attrs.tgListitemType)
render(issueTypeById, issue)
$scope.$watch $attrs.tgListitemType, (issue) ->
render($scope.issueTypeById, issue)
return {
link: link
templateUrl: "common/components/level.html"
}
module.directive("tgListitemType", ListItemTypeDirective)
ListItemPriorityDirective = ->
link = ($scope, $el, $attrs) ->
render = (priorityById, issue) ->
@ -648,6 +680,7 @@ ListItemPriorityDirective = ->
module.directive("tgListitemPriority", ListItemPriorityDirective)
ListItemSeverityDirective = ->
link = ($scope, $el, $attrs) ->
render = (severityById, issue) ->
@ -668,26 +701,7 @@ ListItemSeverityDirective = ->
templateUrl: "common/components/level.html"
}
ListItemTypeDirective = ->
link = ($scope, $el, $attrs) ->
render = (issueTypeById, issue) ->
type = issueTypeById[issue.type]
domNode = $el.find(".level")
domNode.css("background-color", type.color)
domNode.attr("title", type.name)
bindOnce $scope, "issueTypeById", (issueTypeById) ->
issue = $scope.$eval($attrs.tgListitemType)
render(issueTypeById, issue)
$scope.$watch $attrs.tgListitemType, (issue) ->
render($scope.issueTypeById, issue)
return {
link: link
templateUrl: "common/components/level.html"
}
module.directive("tgListitemSeverity", ListItemSeverityDirective)
#############################################################################
@ -715,35 +729,27 @@ TgProgressBarDirective = ($template) ->
module.directive("tgProgressBar", ["$tgTemplate", TgProgressBarDirective])
#############################################################################
## Main title directive
#############################################################################
TgMainTitleDirective = ($template) ->
template = $template.get("common/components/main-title.html", true)
render = (el, projectName, sectionName) ->
el.html(template({
projectName: projectName
sectionName: sectionName
}))
TgMainTitleDirective = ($translate) ->
link = ($scope, $el, $attrs) ->
element = angular.element($el)
$scope.$watch "project", (project) ->
render($el, project.name, $scope.sectionName) if project
$scope.$on "project:loaded", (ctx, project) =>
render($el, project.name, $scope.sectionName)
$attrs.$observe "i18nSectionName", (i18nSectionName) ->
trans = $translate(i18nSectionName)
trans.then (sectionName) -> $scope.sectionName = sectionName
trans.catch (sectionName) -> $scope.sectionName = sectionName
$scope.$on "$destroy", ->
$el.off()
return {link: link}
return {
link: link
templateUrl: "common/components/main-title.html"
scope: {
projectName : "=projectName"
}
}
module.directive("tgMainTitle", ["$tgTemplate", TgMainTitleDirective])
module.directive("tgListitemType", ListItemTypeDirective)
module.directive("tgListitemIssueStatus", ListItemIssueStatusDirective)
module.directive("tgListitemSeverity", ListItemSeverityDirective)
module.directive("tgListitemTaskStatus", ListItemTaskStatusDirective)
module.directive("tgListitemUsStatus", ListItemUsStatusDirective)
module.directive("tgMainTitle", ["$translate", TgMainTitleDirective])

View File

@ -27,21 +27,21 @@ bindMethods = @.taiga.bindMethods
NOTIFICATION_MSG = {
"success":
title: "Everything is ok"
message: "Our Oompa Loompas saved all your changes!"
title: "NOTIFICATION.OK"
message: "NOTIFICATION.SAVED"
"error":
title: "Oops, something happened..."
message: "Our Oompa Loompas are sad, your changes were not saved!"
title: "NOTIFICATION.WARNING"
message: "NOTIFICATION.WARNING_TEXT"
"light-error":
title: "Oops, something happened..."
message: "Our Oompa Loompas are sad, your changes were not saved!"
title: "NOTIFICATION.WARNING"
message: "NOTIFICATION.WARNING_TEXT"
}
class ConfirmService extends taiga.Service
@.$inject = ["$q", "lightboxService", "$tgLoading"]
@.$inject = ["$q", "lightboxService", "$tgLoading", "$translate"]
constructor: (@q, @lightboxService, @loading) ->
constructor: (@q, @lightboxService, @loading, @translate) ->
bindMethods(@)
hide: (el)->
@ -51,6 +51,8 @@ class ConfirmService extends taiga.Service
el.off(".confirm-dialog")
ask: (title, subtitle, message, lightboxSelector=".lightbox-generic-ask") ->
defered = @q.defer()
el = angular.element(lightboxSelector)
# Render content
@ -58,8 +60,6 @@ class ConfirmService extends taiga.Service
el.find("span.subtitle").html(subtitle)
el.find("span.message").html(message)
defered = @q.defer()
# Assign event handlers
el.on "click.confirm-dialog", "a.button-green", debounce 2000, (event) =>
event.preventDefault()
@ -80,9 +80,11 @@ class ConfirmService extends taiga.Service
return defered.promise
askOnDelete: (title, message) ->
return @.ask(title, "Are you sure you want to delete?", message) #TODO: i18n
return @.ask(title, @translate.instant("NOTIFICATION.ASK_DELETE"), message)
askChoice: (title, subtitle, choices, replacement, warning, lightboxSelector=".lightbox-ask-choice") ->
defered = @q.defer()
el = angular.element(lightboxSelector)
# Render content
@ -103,7 +105,6 @@ class ConfirmService extends taiga.Service
choicesField.html('')
_.each choices, (value, key) ->
choicesField.append(angular.element("<option value='#{key}'>#{value}</option>"))
defered = @q.defer()
# Assign event handlers
el.on "click.confirm-dialog", "a.button-green", debounce 2000, (event) =>
@ -127,11 +128,12 @@ class ConfirmService extends taiga.Service
return defered.promise
error: (message) ->
defered = @q.defer()
el = angular.element(".lightbox-generic-error")
# Render content
el.find("h2.title").html(message)
defered = @q.defer()
# Assign event handlers
el.on "click.confirm-dialog", "a.button-green", (event) =>
@ -149,12 +151,13 @@ class ConfirmService extends taiga.Service
return defered.promise
success: (title, message) ->
defered = @q.defer()
el = angular.element(".lightbox-generic-success")
# Render content
el.find("h2.title").html(title) if title
el.find("p.message").html(message) if message
defered = @q.defer()
# Assign event handlers
el.on "click.confirm-dialog", "a.button-green", (event) =>
@ -208,12 +211,12 @@ class ConfirmService extends taiga.Service
if title
el.find("h4").html(title)
else
el.find("h4").html(NOTIFICATION_MSG[type].title)
el.find("h4").html(@translate.instant(NOTIFICATION_MSG[type].title))
if message
el.find("p").html(message)
else
el.find("p").html(NOTIFICATION_MSG[type].message)
el.find("p").html(@translate.instant(NOTIFICATION_MSG[type].message))
body = angular.element("body")
body.find(".notification-message .notification-light")

View File

@ -121,7 +121,7 @@ CustomAttributesValuesDirective = ($templates, $storage) ->
module.directive("tgCustomAttributesValues", ["$tgTemplate", "$tgStorage", CustomAttributesValuesDirective])
CustomAttributeValueDirective = ($template, $selectedText) ->
CustomAttributeValueDirective = ($template, $selectedText, $compile) ->
template = $template.get("custom-attributes/custom-attribute-value.html", true)
templateEdit = $template.get("custom-attributes/custom-attribute-value-edit.html", true)
@ -139,8 +139,10 @@ CustomAttributeValueDirective = ($template, $selectedText) ->
if editable and (edit or not value)
html = templateEdit(ctx)
html = $compile(html)($scope)
else
html = template(ctx)
html = $compile(html)($scope)
$el.html(html)
@ -195,4 +197,4 @@ CustomAttributeValueDirective = ($template, $selectedText) ->
restrict: "AE"
}
module.directive("tgCustomAttributeValue", ["$tgTemplate", "$selectedText", CustomAttributeValueDirective])
module.directive("tgCustomAttributeValue", ["$tgTemplate", "$selectedText", "$compile", CustomAttributeValueDirective])

View File

@ -28,7 +28,7 @@ module = angular.module("taigaCommon")
## User story estimation directive (for Lightboxes)
#############################################################################
LbUsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $template) ->
LbUsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $template, $compile) ->
# Display the points of a US and you can edit it.
#
# Example:
@ -40,7 +40,6 @@ LbUsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $
link = ($scope, $el, $attrs, $model) ->
$scope.$watch $attrs.ngModel, (us) ->
console.log "watch"
if us
estimationProcess = $tgEstimationsService.create($el, us, $scope.project)
estimationProcess.onSelectedPointForRole = (roleId, pointId) ->
@ -57,6 +56,7 @@ LbUsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $
mainTemplate = "common/estimation/us-estimation-points-per-role.html"
template = $template.get(mainTemplate, true)
html = template(ctx)
html = $compile(html)($scope)
@$el.html(html)
estimationProcess.render()
@ -69,14 +69,14 @@ LbUsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $
require: "ngModel"
}
module.directive("tgLbUsEstimation", ["$tgEstimationsService", "$rootScope", "$tgRepo", "$tgConfirm", "$tgTemplate", LbUsEstimationDirective])
module.directive("tgLbUsEstimation", ["$tgEstimationsService", "$rootScope", "$tgRepo", "$tgConfirm", "$tgTemplate", "$compile", LbUsEstimationDirective])
#############################################################################
## User story estimation directive
#############################################################################
UsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $qqueue, $template) ->
UsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $qqueue, $template, $compile) ->
# Display the points of a US and you can edit it.
#
# Example:
@ -103,6 +103,7 @@ UsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $qq
mainTemplate = "common/estimation/us-estimation-points-per-role.html"
template = $template.get(mainTemplate, true)
html = template(ctx)
html = $compile(html)($scope)
@$el.html(html)
estimationProcess.render()
@ -116,7 +117,7 @@ UsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $qq
require: "ngModel"
}
module.directive("tgUsEstimation", ["$tgEstimationsService", "$rootScope", "$tgRepo", "$tgConfirm", "$tgQqueue", "$tgTemplate",
module.directive("tgUsEstimation", ["$tgEstimationsService", "$rootScope", "$tgRepo", "$tgConfirm", "$tgQqueue", "$tgTemplate", "$compile"
UsEstimationDirective])

View File

@ -33,15 +33,14 @@ defaultFilter = ->
module.filter("default", defaultFilter)
yesNoFilter = ->
#TODO: i18n
yesNoFilter = ($translate) ->
return (value) ->
if value
return "Yes"
return $translate.instant("COMMON.YES")
return "No"
return $translate.instant("COMMON.NO")
module.filter("yesNo", yesNoFilter)
module.filter("yesNo", ["$translate", yesNoFilter])
unslugify = ->

View File

@ -68,7 +68,7 @@ class HistoryController extends taiga.Controller
return @rs.history.undeleteComment(type, objectId, activityId).then => @.loadHistory(type, objectId)
HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
HistoryDirective = ($log, $loading, $qqueue, $template, $confirm, $translate, $compile) ->
templateChangeDiff = $template.get("common/history/history-change-diff.html", true)
templateChangePoints = $template.get("common/history/history-change-points.html", true)
templateChangeGeneric = $template.get("common/history/history-change-generic.html", true)
@ -96,25 +96,26 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
# Helpers
getHumanizedFieldName = (field) ->
humanizedFieldNames = {
humanizedFieldNames = {}
# US
assigned_to: "assigned to"
is_closed: "is closed"
finish_date: "finish date"
client_requirement: "client requirement"
team_requirement: "team requirement"
humanizedFieldNames.assigned_to = $translate.instant("COMMON.FIELDS.ASSIGNED_TO").toLowerCase()
humanizedFieldNames.is_closed = $translate.instant("IS_CLOSED").toLowerCase()
humanizedFieldNames.finish_date = $translate.instant("US.FIELDS.FINISH_DATE").toLowerCase()
humanizedFieldNames.client_repquirement = $translate.instant("US.FIELDS.CLIENT_REQUIREMENT").toLowerCase()
humanizedFieldNames.team_requirement = $translate.instant("US.FIELDS.TEAM_REQUIREMENT").toLowerCase()
# Task
milestone: "sprint"
user_story: "user story"
is_iocaine: "is iocaine"
humanizedFieldNames.milestone = $translate.instant("TASK.FIELDS.MILESTONE").toLowerCase()
humanizedFieldNames.user_story = $translate.instant("TASK.FIELDS.USER_STORY").toLowerCase()
humanizedFieldNames.is_iocaine = $translate.instant("TASK.FIELDS.IS_IOCAINE").toLowerCase()
# Attachment
is_deprecated: "is deprecated"
humanizedFieldNames.is_deprecated = $translate.instant("TASK.FIELDS.IS_IOCAINE").toLowerCase()
humanizedFieldNames.blocked_note = $translate.instant("TASK.FIELDS.IS_IOCAINE").toLowerCase()
humanizedFieldNames.is_blocked = $translate.instant("TASK.FIELDS.IS_BLOCKED").toLowerCase()
blocked_note: "blocked note"
is_blocked: "is blocked"
} # TODO i18n
return humanizedFieldNames[field] or field
getUserFullName = (userId) ->
@ -152,16 +153,14 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
attachments = _.map value, (changes, type) ->
if type == "new"
return _.map changes, (change) ->
# TODO: i18n
return templateChangeDiff({name: "new attachment", diff: change.filename})
return templateChangeDiff({name: $translate.instant("ACTIVITY.NEW_ATTACHMENT"), diff: change.filename})
else if type == "deleted"
return _.map changes, (change) ->
# TODO: i18n
return templateChangeDiff({name: "deleted attachment", diff: change.filename})
return templateChangeDiff({name: $translate.instant("ACTIVITY.DELETED_ATTACHMENT"), diff: change.filename})
else
return _.map changes, (change) ->
# TODO: i18n
name = "updated attachment #{change.filename}"
name = $tranlsate.instant("ACTIVITY.UPDATED_ATTACHMENT", {filename: change.filename})
diff = _.map change.changes, (values, name) ->
return {
name: getHumanizedFieldName(name)
@ -177,16 +176,19 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
customAttributes = _.map value, (changes, type) ->
if type == "new"
return _.map changes, (change) ->
return templateChangeGeneric({
html = templateChangeGeneric({
name: change.name,
from: formatChange(""),
to: formatChange(change.value)
})
html = $compile(html)($scope)
return html[0].outerHTML
else if type == "deleted"
return _.map changes, (change) ->
# TODO: i18n
return templateChangeDiff({
name: "deleted custom attribute",
name: $translate.instant("ACTIVITY.DELETED_CUSTOM_ATTRIBUTE")
diff: change.name
})
else
@ -207,7 +209,11 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
else if field == "blocked_note"
return templateChangeDiff({name: getHumanizedFieldName("blocked_note"), diff: value[1]})
else if field == "points"
return templateChangePoints({points: value})
html = templateChangePoints({points: value})
html = $compile(html)($scope)
return html[0].outerHTML
else if field == "attachments"
return renderAttachmentEntry(value)
else if field == "custom_attributes"
@ -216,7 +222,11 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
name = getHumanizedFieldName(field)
removed = _.difference(value[0], value[1])
added = _.difference(value[1], value[0])
return templateChangeList({name:name, removed:removed, added: added})
html = templateChangeList({name:name, removed:removed, added: added})
html = $compile(html)($scope)
return html[0].outerHTML
else if field == "assigned_to"
name = getHumanizedFieldName(field)
from = formatChange(value[0] or "Unassigned")
@ -233,13 +243,12 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
renderChangesHelperText = (change) ->
size = countChanges(change)
if size == 1
return "Made #{size} change" # TODO: i18n
return "Made #{size} changes" # TODO: i18n
return $translate.instant("ACTIVITY.SIZE_CHANGE", {size: size})
renderComment = (comment) ->
if (comment.delete_comment_date or comment.delete_comment_user?.name)
return templateDeletedComment({
html = templateDeletedComment({
deleteCommentDate: moment(comment.delete_comment_date).format("DD MMM YYYY HH:mm") if comment.delete_comment_date
deleteCommentUser: comment.delete_comment_user.name
deleteComment: comment.comment_html
@ -247,7 +256,11 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
canRestoreComment: comment.delete_comment_user.pk == $scope.user.id or $scope.project.my_permissions.indexOf("modify_project") > -1
})
return templateActivity({
html = $compile(html)($scope)
return html[0].outerHTML
html = templateActivity({
avatar: getUserAvatar(comment.user.pk)
userFullName: comment.user.name
creationDate: moment(comment.created_at).format("DD MMM YYYY HH:mm")
@ -261,6 +274,10 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
canDeleteComment: comment.user.pk == $scope.user?.id or $scope.project.my_permissions.indexOf("modify_project") > -1
})
html = $compile(html)($scope)
return html[0].outerHTML
renderChange = (change) ->
return templateActivity({
avatar: getUserAvatar(change.user.pk)
@ -281,7 +298,11 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
else
showMore = totalEntries - entries.length
return templateBaseEntries({entries: entries, showMore:showMore})
html = templateBaseEntries({entries: entries, showMore:showMore})
html = $compile(html)($scope)
return html
# Render into DOM (operations with dom mutability)
@ -394,7 +415,9 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
$el.off()
templateFn = ($el, $attrs) ->
return templateBase({ngmodel: $attrs.ngModel, type: $attrs.type, mode: $attrs.mode})
html = templateBase({ngmodel: $attrs.ngModel, type: $attrs.type, mode: $attrs.mode})
return html
return {
controller: HistoryController
@ -405,4 +428,4 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
}
module.directive("tgHistory", ["$log", "$tgLoading", "$tgQqueue", "$tgTemplate", "$tgConfirm", HistoryDirective])
module.directive("tgHistory", ["$log", "$tgLoading", "$tgQqueue", "$tgTemplate", "$tgConfirm", "$translate", "$compile", HistoryDirective])

View File

@ -22,7 +22,7 @@
module = angular.module("taigaCommon")
ImportProjectButtonDirective = ($rs, $confirm, $location, $navUrls) ->
ImportProjectButtonDirective = ($rs, $confirm, $location, $navUrls, $translate) ->
link = ($scope, $el, $attrs) ->
$el.on "click", ".import-project-button", (event) ->
event.preventDefault()
@ -39,29 +39,25 @@ ImportProjectButtonDirective = ($rs, $confirm, $location, $navUrls) ->
onSuccess = (result) ->
loader.stop()
if result.status == 202 # Async mode
title = "Our Oompa Loompas are importing your project" # TODO: i18n
message = "This process could take a few minutes <br/> We will send you
an email when ready" # TODO: i18n
title = $translate.instant("PROJECT.IMPORT.ASYNC_IN_PROGRESS_TITLE")
message = $translate.instant("PROJECT.IMPORT.ASYNC_IN_PROGRESS_MESSAGE")
$confirm.success(title, message)
else # result.status == 201 # Sync mode
ctx = {project: result.data.slug}
$location.path($navUrls.resolve("project-admin-project-profile-details", ctx))
$confirm.notify("success", "Your project has been imported successfuly.") # TODO: i18n
msg = $translate.instant("PROJECT.IMPORT.SYNC_SUCCESS")
$confirm.notify("success", msg)
onError = (result) ->
loader.stop()
console.log "Error", result
errorMsg = "Our oompa loompas have some problems importing your dump data.
Please try again. " # TODO: i18n
errorMsg = $translate.instant("PROJECT.IMPORT.ERROR")
if result.status == 429 # TOO MANY REQUESTS
errorMsg = "Sorry, our oompa loompas are very busy right now.
Please try again in a few minutes. " # TODO: i18n
errorMsg = $translate.instant("PROJECT.IMPORT.ERROR_TOO_MANY_REQUEST")
else if result.data?._error_message
errorMsg = "Our oompa loompas have some problems importing your dump data:
#{result.data._error_message}" # TODO: i18n
errorMsg = $translate.instant("PROJECT.IMPORT.ERROR_MESSAGE", {error_message: result.data._error_message})
$confirm.notify("error", errorMsg)
loader.start()
@ -69,5 +65,5 @@ ImportProjectButtonDirective = ($rs, $confirm, $location, $navUrls) ->
return {link: link}
module.directive("tgImportProjectButton", ["$tgResources", "$tgConfirm", "$location", "$tgNavUrls",
module.directive("tgImportProjectButton", ["$tgResources", "$tgConfirm", "$location", "$tgNavUrls", "$translate",
ImportProjectButtonDirective])

View File

@ -146,9 +146,10 @@ module.directive("lightbox", ["lightboxService", LightboxDirective])
# Issue/Userstory blocking message lightbox directive.
BlockLightboxDirective = ($rootscope, $tgrepo, $confirm, lightboxService, $loading, $qqueue) ->
BlockLightboxDirective = ($rootscope, $tgrepo, $confirm, lightboxService, $loading, $qqueue, $translate) ->
link = ($scope, $el, $attrs, $model) ->
$el.find("h2.title").text($attrs.title)
$translate($attrs.title).then (title) ->
$el.find("h2.title").text(title)
unblock = $qqueue.bindAdd (item, finishCallback) =>
promise = $tgrepo.save(item)
@ -216,14 +217,14 @@ BlockLightboxDirective = ($rootscope, $tgrepo, $confirm, lightboxService, $loadi
require: "ngModel"
}
module.directive("tgLbBlock", ["$rootScope", "$tgRepo", "$tgConfirm", "lightboxService", "$tgLoading", "$tgQqueue", BlockLightboxDirective])
module.directive("tgLbBlock", ["$rootScope", "$tgRepo", "$tgConfirm", "lightboxService", "$tgLoading", "$tgQqueue", "$translate", BlockLightboxDirective])
#############################################################################
## Generic Lightbox Blocking-Message Input Directive
#############################################################################
BlockingMessageInputDirective = ($log, $template) ->
BlockingMessageInputDirective = ($log, $template, $compile) ->
template = $template.get("common/lightbox/lightbox-blocking-message-input.html", true)
link = ($scope, $el, $attrs, $model) ->
@ -246,14 +247,14 @@ BlockingMessageInputDirective = ($log, $template) ->
restrict: "EA"
}
module.directive("tgBlockingMessageInput", ["$log", "$tgTemplate", BlockingMessageInputDirective])
module.directive("tgBlockingMessageInput", ["$log", "$tgTemplate", "$compile", BlockingMessageInputDirective])
#############################################################################
## Create/Edit Userstory Lightbox Directive
#############################################################################
CreateEditUserstoryDirective = ($repo, $model, $rs, $rootScope, lightboxService, $loading) ->
CreateEditUserstoryDirective = ($repo, $model, $rs, $rootScope, lightboxService, $loading, $translate) ->
link = ($scope, $el, attrs) ->
$scope.isNew = true
@ -270,8 +271,8 @@ CreateEditUserstoryDirective = ($repo, $model, $rs, $rootScope, lightboxService,
})
# Update texts for creation
$el.find(".button-green").html("Create") #TODO: i18n
$el.find(".title").html("New user story ") #TODO: i18n
$el.find(".button-green").html($translate.instant("COMMON.CREATE"))
$el.find(".title").html($translate.instant("LIGHTBOX.CREATE_EDIT_US.NEW_US"))
$el.find(".tag-input").val("")
$el.find(".blocked-note").addClass("hidden")
@ -286,8 +287,8 @@ CreateEditUserstoryDirective = ($repo, $model, $rs, $rootScope, lightboxService,
$scope.isNew = false
# Update texts for edition
$el.find(".button-green").html("Save") #TODO: i18n
$el.find(".title").html("Edit user story ") #TODO: i18n
$el.find(".button-green").html($translate.instant("COMMON.SAVE"))
$el.find(".title").html($translate.instant("LIGHTBOX.CREATE_EDIT_US.EDIT_US"))
$el.find(".tag-input").val("")
# Update requirement info (team, client or blocked)
@ -365,6 +366,7 @@ module.directive("tgLbCreateEditUserstory", [
"$rootScope",
"lightboxService",
"$tgLoading",
"$translate",
CreateEditUserstoryDirective
])
@ -427,7 +429,7 @@ module.directive("tgLbCreateBulkUserstories", [
## AssignedTo Lightbox Directive
#############################################################################
AssignedToLightboxDirective = (lightboxService, lightboxKeyboardNavigationService, $template) ->
AssignedToLightboxDirective = (lightboxService, lightboxKeyboardNavigationService, $template, $compile) ->
link = ($scope, $el, $attrs) ->
selectedUser = null
selectedItem = null
@ -461,6 +463,9 @@ AssignedToLightboxDirective = (lightboxService, lightboxKeyboardNavigationServic
}
html = usersTemplate(ctx)
html = $compile(html)($scope)
$el.find("div.watchers").html(html)
lightboxKeyboardNavigationService.init($el)
@ -520,7 +525,7 @@ AssignedToLightboxDirective = (lightboxService, lightboxKeyboardNavigationServic
}
module.directive("tgLbAssignedto", ["lightboxService", "lightboxKeyboardNavigationService", "$tgTemplate", AssignedToLightboxDirective])
module.directive("tgLbAssignedto", ["lightboxService", "lightboxKeyboardNavigationService", "$tgTemplate", "$compile", AssignedToLightboxDirective])
#############################################################################

View File

@ -55,7 +55,7 @@ module = angular.module("taigaCommon")
#############################################################################
## WYSIWYG markitup editor directive
#############################################################################
tgMarkitupDirective = ($rootscope, $rs, $tr, $selectedText, $template) ->
tgMarkitupDirective = ($rootscope, $rs, $selectedText, $template, $compile) ->
previewTemplate = $template.get("common/wysiwyg/wysiwyg-markitup-preview.html", true)
link = ($scope, $el, $attrs, $model) ->
@ -76,7 +76,10 @@ tgMarkitupDirective = ($rootscope, $rs, $tr, $selectedText, $template) ->
markdownDomNode = element.parents(".markdown")
markItUpDomNode = element.parents(".markItUp")
$rs.mdrender.render($scope.projectId, $model.$modelValue).then (data) ->
markdownDomNode.append(previewTemplate({data: data.data}))
html = previewTemplate({data: data.data})
html = $compile(html)($scope)
markdownDomNode.append(html)
markItUpDomNode.hide()
markdown = element.closest(".markdown")
@ -178,42 +181,43 @@ tgMarkitupDirective = ($rootscope, $rs, $tr, $selectedText, $template) ->
setCaretPosition(data.textarea, markdownCaretPositon) if markdownCaretPositon
#I18N
markupSet: [
{
name: $tr.t("markdown-editor.heading-1")
name: "First Level Heading"
key: "1"
placeHolder: $tr.t("markdown-editor.placeholder")
placeHolder: "Your title here..."
closeWith: (markItUp) -> markdownTitle(markItUp, "=")
},
{
name: $tr.t("markdown-editor.heading-2")
name: "Second Level Heading"
key: "2"
placeHolder: $tr.t("markdown-editor.placeholder")
placeHolder: "Your title here..."
closeWith: (markItUp) -> markdownTitle(markItUp, "-")
},
{
name: $tr.t("markdown-editor.heading-3")
name: "Third Level Heading"
key: "3"
openWith: "### "
placeHolder: $tr.t("markdown-editor.placeholder")
placeHolder: "Your title here..."
},
{
separator: "---------------"
},
{
name: $tr.t("markdown-editor.bold")
name: "Bold"
key: "B"
openWith: "**"
closeWith: "**"
},
{
name: $tr.t("markdown-editor.italic")
name: "Italic"
key: "I"
openWith: "_"
closeWith: "_"
},
{
name: $tr.t("markdown-editor.strike")
name: "Strike"
key: "S"
openWith: "~~"
closeWith: "~~"
@ -222,29 +226,29 @@ tgMarkitupDirective = ($rootscope, $rs, $tr, $selectedText, $template) ->
separator: "---------------"
},
{
name: $tr.t("markdown-editor.bulleted-list")
name: "Bulleted List"
openWith: "- "
},
{
name: $tr.t("markdown-editor.numeric-list")
name: "Numeric List"
openWith: (markItUp) -> markItUp.line+". "
},
{
separator: "---------------"
},
{
name: $tr.t("markdown-editor.picture")
name: "Picture"
key: "P"
replaceWith: '![[![Alternative text]!]](<<<[![Url:!:http://]!]>>> "[![Title]!]")'
beforeInsert:(markItUp) -> prepareUrlFormatting(markItUp)
afterInsert:(markItUp) -> urlFormatting(markItUp)
},
{
name: $tr.t("markdown-editor.link")
name: "Link"
key: "L"
openWith: "["
closeWith: '](<<<[![Url:!:http://]!]>>> "[![Title]!]")'
placeHolder: $tr.t("markdown-editor.link-placeholder")
placeHolder: "Your text to link here..."
beforeInsert:(markItUp) -> prepareUrlFormatting(markItUp)
afterInsert:(markItUp) -> urlFormatting(markItUp)
},
@ -252,11 +256,11 @@ tgMarkitupDirective = ($rootscope, $rs, $tr, $selectedText, $template) ->
separator: "---------------"
},
{
name: $tr.t("markdown-editor.quotes")
name: "Quotes"
openWith: "> "
},
{
name: $tr.t("markdown-editor.code-block")
name: "Code Block / Code"
openWith: "```\n"
closeWith: "\n```"
},
@ -264,7 +268,7 @@ tgMarkitupDirective = ($rootscope, $rs, $tr, $selectedText, $template) ->
separator: "---------------"
},
{
name: $tr.t("markdown-editor.preview")
name: "Preview"
call: preview
className: "preview-icon"
},
@ -338,4 +342,4 @@ tgMarkitupDirective = ($rootscope, $rs, $tr, $selectedText, $template) ->
return {link:link, require:"ngModel"}
module.directive("tgMarkitup", ["$rootScope", "$tgResources", "$tgI18n", "$selectedText", "$tgTemplate", tgMarkitupDirective])
module.directive("tgMarkitup", ["$rootScope", "$tgResources", "$selectedText", "$tgTemplate", tgMarkitupDirective])

View File

@ -47,13 +47,14 @@ class IssueDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
"$appTitle",
"$tgAnalytics",
"$tgNavUrls",
"$translate",
"tgLoader"
]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location,
@log, @appTitle, @analytics, @navUrls, tgLoader) ->
@log, @appTitle, @analytics, @navUrls, @translate, tgLoader) ->
@scope.issueRef = @params.issueref
@scope.sectionName = "Issue Details"
@scope.sectionName = @translate.instant("ISSUES.SECTION_NAME")
@.initializeEventHandlers()
promise = @.loadInitialData()
@ -145,7 +146,7 @@ module.controller("IssueDetailController", IssueDetailController)
## Issue status display directive
#############################################################################
IssueStatusDisplayDirective = ($template)->
IssueStatusDisplayDirective = ($template, $compile)->
# Display if a Issue is open or closed and its issueboard status.
#
# Example:
@ -162,6 +163,9 @@ IssueStatusDisplayDirective = ($template)->
html = template({
status: $scope.statusById[issue.status]
})
html = $compile(html)($scope)
$el.html(html)
$scope.$watch $attrs.ngModel, (issue) ->
@ -176,14 +180,14 @@ IssueStatusDisplayDirective = ($template)->
require: "ngModel"
}
module.directive("tgIssueStatusDisplay", ["$tgTemplate", IssueStatusDisplayDirective])
module.directive("tgIssueStatusDisplay", ["$tgTemplate", "$compile", IssueStatusDisplayDirective])
#############################################################################
## Issue status button directive
#############################################################################
IssueStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $template) ->
IssueStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $template, $compile) ->
# Display the status of Issue and you can edit it.
#
# Example:
@ -208,6 +212,9 @@ IssueStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $t
statuses: $scope.statusList
editable: isEditable()
})
html = $compile(html)($scope)
$el.html(html)
save = $qqueue.bindAdd (statusId) =>
@ -259,13 +266,13 @@ IssueStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $t
require: "ngModel"
}
module.directive("tgIssueStatusButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate", IssueStatusButtonDirective])
module.directive("tgIssueStatusButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate", "$compile", IssueStatusButtonDirective])
#############################################################################
## Issue type button directive
#############################################################################
IssueTypeButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $template) ->
IssueTypeButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $template, $compile) ->
# Display the type of Issue and you can edit it.
#
# Example:
@ -285,6 +292,8 @@ IssueTypeButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $tem
render = (issue) =>
type = $scope.typeById[issue.type]
html = $compile(html)($scope)
html = template({
type: type
typees: $scope.typeList
@ -340,14 +349,14 @@ IssueTypeButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $tem
require: "ngModel"
}
module.directive("tgIssueTypeButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate", IssueTypeButtonDirective])
module.directive("tgIssueTypeButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate", "$compile", IssueTypeButtonDirective])
#############################################################################
## Issue severity button directive
#############################################################################
IssueSeverityButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $template) ->
IssueSeverityButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $template, $compile) ->
# Display the severity of Issue and you can edit it.
#
# Example:
@ -372,6 +381,9 @@ IssueSeverityButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue,
severityes: $scope.severityList
editable: isEditable()
})
html = $compile(html)($scope)
$el.html(html)
save = $qqueue.bindAdd (severity) =>
@ -424,14 +436,14 @@ IssueSeverityButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue,
require: "ngModel"
}
module.directive("tgIssueSeverityButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate", IssueSeverityButtonDirective])
module.directive("tgIssueSeverityButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate", "$compile", IssueSeverityButtonDirective])
#############################################################################
## Issue priority button directive
#############################################################################
IssuePriorityButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $template) ->
IssuePriorityButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $template, $compile) ->
# Display the priority of Issue and you can edit it.
#
# Example:
@ -456,6 +468,9 @@ IssuePriorityButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue,
priorityes: $scope.priorityList
editable: isEditable()
})
html = $compile(html)($scope)
$el.html(html)
save = $qqueue.bindAdd (priority) =>
@ -508,14 +523,14 @@ IssuePriorityButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue,
require: "ngModel"
}
module.directive("tgIssuePriorityButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate", IssuePriorityButtonDirective])
module.directive("tgIssuePriorityButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate", "$compile", IssuePriorityButtonDirective])
#############################################################################
## Promote Issue to US button directive
#############################################################################
PromoteIssueToUsButtonDirective = ($rootScope, $repo, $confirm, $qqueue) ->
PromoteIssueToUsButtonDirective = ($rootScope, $repo, $confirm, $qqueue, $translate) ->
link = ($scope, $el, $attrs, $model) ->
save = $qqueue.bindAdd (issue, finish) =>
@ -545,8 +560,8 @@ PromoteIssueToUsButtonDirective = ($rootScope, $repo, $confirm, $qqueue) ->
event.preventDefault()
issue = $model.$modelValue
title = "Promote this issue to a new user story" # TODO: i18n
message = "Are you sure you want to create a new US from this Issue?" # TODO: i18n
title = $translate.instant("ISSUES.CONFIRM_PROMOTE.TITLE")
message = $translate.instant("ISSUES.CONFIRM_PROMOTE.MESSAGE")
subtitle = issue.subject
$confirm.ask(title, subtitle, message).then (finish) =>
@ -563,5 +578,5 @@ PromoteIssueToUsButtonDirective = ($rootScope, $repo, $confirm, $qqueue) ->
link: link
}
module.directive("tgPromoteIssueToUsButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgQqueue",
module.directive("tgPromoteIssueToUsButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgQqueue", "$translate"
PromoteIssueToUsButtonDirective])

View File

@ -310,7 +310,7 @@ module.controller("IssuesController", IssuesController)
## Issues Directive
#############################################################################
IssuesDirective = ($log, $location, $template) ->
IssuesDirective = ($log, $location, $template, $compile) ->
## Issues Pagination
template = $template.get("issue/issue-paginator.html", true)
@ -360,7 +360,11 @@ IssuesDirective = ($log, $location, $template) ->
else
pages.push({classes: "page", num: i, type: "page"})
$pagEl.html(template(options))
html = template(options)
html = $compile(html)($scope)
$pagEl.html(html)
$scope.$watch "issues", (value) ->
# Do nothing if value is not logical true
@ -427,14 +431,14 @@ IssuesDirective = ($log, $location, $template) ->
return {link:link}
module.directive("tgIssues", ["$log", "$tgLocation", "$tgTemplate", IssuesDirective])
module.directive("tgIssues", ["$log", "$tgLocation", "$tgTemplate", "$compile", IssuesDirective])
#############################################################################
## Issues Filters Directive
#############################################################################
IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template) ->
IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $translate) ->
template = $template.get("issue/issues-filters.html", true)
templateSelected = $template.get("issue/issues-filters-selected.html", true)
@ -590,8 +594,8 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template) -
target = angular.element(event.currentTarget)
customFilterName = target.parent().data('id')
title = "Delete custom filter" # TODO: i18n
message = "the custom filter '#{customFilterName}'" # TODO: i18n
title = $translate.instant("ISSUES.FILTERS.CONFIRM_DELETE.TITLE")
message = $translate.instant("ISSUES.FILTERS.CONFIRM_DELETE.MESSAGE", {customFilterName: customFilterName})
$confirm.askOnDelete(title, message).then (finish) ->
promise = $ctrl.deleteMyFilter(customFilterName)
@ -652,7 +656,7 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template) -
return {link:link}
module.directive("tgIssuesFilters", ["$log", "$tgLocation", "$tgResources", "$tgConfirm", "$tgLoading", "$tgTemplate",
module.directive("tgIssuesFilters", ["$log", "$tgLocation", "$tgResources", "$tgConfirm", "$tgLoading", "$tgTemplate", "$translate",
IssuesFiltersDirective])

View File

@ -307,10 +307,9 @@ module.directive("tgKanban", ["$tgRepo", "$rootScope", KanbanDirective])
## Kanban Archived Status Column Header Control
#############################################################################
KanbanArchivedStatusHeaderDirective = ($rootscope) ->
#TODO: i18N
showArchivedText = "Show archived"
hideArchivedText = "Hide archived"
KanbanArchivedStatusHeaderDirective = ($rootscope, $translate) ->
showArchivedText = $translate.instant("KANBAN.ACTION_SHOW_ARCHIVED")
hideArchivedText = $translate.instant("KANBAN.ACTION_HIDE_ARCHIVED")
link = ($scope, $el, $attrs) ->
status = $scope.$eval($attrs.tgKanbanArchivedStatusHeader)
@ -338,19 +337,18 @@ KanbanArchivedStatusHeaderDirective = ($rootscope) ->
return {link:link}
module.directive("tgKanbanArchivedStatusHeader", [ "$rootScope", KanbanArchivedStatusHeaderDirective])
module.directive("tgKanbanArchivedStatusHeader", [ "$rootScope", "$translate", KanbanArchivedStatusHeaderDirective])
#############################################################################
## Kanban Archived Status Column Intro Directive
#############################################################################
KanbanArchivedStatusIntroDirective = ->
# TODO: i18n
hiddenUserStoriexText = "The user stories in this status are hidden by default"
KanbanArchivedStatusIntroDirective = ($translate) ->
userStories = []
link = ($scope, $el, $attrs) ->
hiddenUserStoriexText = $translate.instant("KANBAN.HIDDEN_USER_STORIES")
status = $scope.$eval($attrs.tgKanbanArchivedStatusIntro)
$el.text(hiddenUserStoriexText)
@ -397,7 +395,7 @@ KanbanArchivedStatusIntroDirective = ->
return {link:link}
module.directive("tgKanbanArchivedStatusIntro", KanbanArchivedStatusIntroDirective)
module.directive("tgKanbanArchivedStatusIntro", ["$translate", KanbanArchivedStatusIntroDirective])
#############################################################################
@ -495,14 +493,14 @@ module.directive("tgKanbanWipLimit", KanbanWipLimitDirective)
## Kanban User Directive
#############################################################################
KanbanUserDirective = ($log) ->
KanbanUserDirective = ($log, $compile) ->
template = _.template("""
<figure class="avatar">
<a href="#" title="Assign User Story" <% if (!clickable) {%>class="not-clickable"<% } %>>
<a href="#" title="{{'US.ASSIGN' | translate}}" <% if (!clickable) {%>class="not-clickable"<% } %>>
<img src="<%- imgurl %>" alt="<%- name %>" class="avatar">
</a>
</figure>
""") # TODO: i18n
""")
clickable = false
@ -527,7 +525,7 @@ KanbanUserDirective = ($log) ->
else
ctx = {name: user.full_name_display, imgurl: user.photo, clickable: clickable}
html = template(ctx)
html = $compile(template(ctx))($scope)
$el.html(html)
username_label.text(ctx.name)
@ -556,4 +554,4 @@ KanbanUserDirective = ($log) ->
return {link: link, require:"ngModel"}
module.directive("tgKanbanUserAvatar", ["$log", KanbanUserDirective])
module.directive("tgKanbanUserAvatar", ["$log", "$compile", KanbanUserDirective])

View File

@ -1,22 +0,0 @@
###
# 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/locales.coffee
###
module = angular.module("taigaLocales", [])

View File

@ -26,7 +26,7 @@ debounce = @.taiga.debounce
module = angular.module("taigaProject")
CreateProject = ($rootscope, $repo, $confirm, $location, $navurls, $rs, $projectUrl, $loading, lightboxService, $cacheFactory) ->
CreateProject = ($rootscope, $repo, $confirm, $location, $navurls, $rs, $projectUrl, $loading, lightboxService, $cacheFactory, $translate) ->
link = ($scope, $el, attrs) ->
$scope.data = {}
$scope.templates = []
@ -41,7 +41,9 @@ CreateProject = ($rootscope, $repo, $confirm, $location, $navurls, $rs, $project
$loading.finish(submitButton)
$rootscope.$broadcast("projects:reload")
$confirm.notify("success", "Success") #TODO: i18n
$confirm.notify("success", $translate.instant("COMMON.SAVE"))
$location.url($projectUrl.get(response))
lightboxService.close($el)
@ -126,7 +128,7 @@ CreateProject = ($rootscope, $repo, $confirm, $location, $navurls, $rs, $project
return {link:link}
module.directive("tgLbCreateProject", ["$rootScope", "$tgRepo", "$tgConfirm", "$location", "$tgNavUrls",
"$tgResources", "$projectUrl", "$tgLoading", "lightboxService", "$cacheFactory", CreateProject])
"$tgResources", "$projectUrl", "$tgLoading", "lightboxService", "$cacheFactory", "$translate", CreateProject])
#############################################################################

View File

@ -25,7 +25,7 @@ debounce = @.taiga.debounce
module = angular.module("taigaRelatedTasks", [])
RelatedTaskRowDirective = ($repo, $compile, $confirm, $rootscope, $loading, $template) ->
RelatedTaskRowDirective = ($repo, $compile, $confirm, $rootscope, $loading, $template, $translate) ->
templateView = $template.get("task/related-task-row.html", true)
templateEdit = $template.get("task/related-task-row-edit.html", true)
@ -79,9 +79,8 @@ RelatedTaskRowDirective = ($repo, $compile, $confirm, $rootscope, $loading, $tem
$el.find('input').focus().select()
$el.on "click", ".delete-task", (event) ->
#TODO: i18n
title = $translate.instant("TASK.TITLE_DELETE_ACTION")
task = $model.$modelValue
title = "Delete Task"
message = task.subject
$confirm.askOnDelete(title, message).then (finish) ->
@ -109,7 +108,7 @@ RelatedTaskRowDirective = ($repo, $compile, $confirm, $rootscope, $loading, $tem
return {link:link, require:"ngModel"}
module.directive("tgRelatedTaskRow", ["$tgRepo", "$compile", "$tgConfirm", "$rootScope", "$tgLoading", "$tgTemplate", RelatedTaskRowDirective])
module.directive("tgRelatedTaskRow", ["$tgRepo", "$compile", "$tgConfirm", "$rootScope", "$tgLoading", "$tgTemplate", "$translate", RelatedTaskRowDirective])
RelatedTaskCreateFormDirective = ($repo, $compile, $confirm, $tgmodel, $loading, $analytics, $template) ->
template = $template.get("task/related-task-create-form.html", true)

View File

@ -24,7 +24,7 @@ taiga = @.taiga
sizeFormat = @.taiga.sizeFormat
resourceProvider = ($config, $repo, $http, $urls, $auth, $q, $rootScope) ->
resourceProvider = ($config, $repo, $http, $urls, $auth, $q, $rootScope, $translate) ->
service = {}
service.get = (projectId) ->
@ -99,7 +99,7 @@ resourceProvider = ($config, $repo, $http, $urls, $auth, $q, $rootScope) ->
statusUpdater("in-progress", null, message, percent)
uploadComplete = (evt) =>
statusUpdater("done", "Importing Project", "This process can take a while, please keep the window open.") # i18n
statusUpdater("done", $translate.instant("PROJECT.IMPORT.TITLE"), $translate.instant("PROJECT.IMPORT.DESCRIPTION"))
uploadFailed = (evt) =>
statusUpdater("error")
@ -141,5 +141,4 @@ resourceProvider = ($config, $repo, $http, $urls, $auth, $q, $rootScope) ->
module = angular.module("taigaResources")
module.factory("$tgProjectsResourcesProvider", ["$tgConfig", "$tgRepo", "$tgHttp", "$tgUrls", "$tgAuth", "$q",
resourceProvider])
module.factory("$tgProjectsResourcesProvider", ["$tgConfig", "$tgRepo", "$tgHttp", "$tgUrls", "$tgAuth", "$q", "$translate", resourceProvider])

View File

@ -85,14 +85,20 @@ SprintGraphDirective = ->
tooltip: true
tooltipOpts:
content: (label, xval, yval, flotItem) ->
#TODO: i18n
formattedDate = moment(xval).format("DD MMM")
roundedValue = Math.round(yval)
if flotItem.seriesIndex == 1
return "Optimal pending points for day #{formattedDate} should be #{roundedValue}"
return $translate.instant("TASKBOARD.CHARTS.OPTIMAL", {
formattedDate: formattedDate,
roundedValue: roundedValue
})
else
return "Real pending points for day #{formattedDate} is #{roundedValue}"
return $translate.instant("TASKBOARD.CHARTS.REAL", {
formattedDate: formattedDate,
roundedValue: roundedValue
})
element.empty()
element.plot(data, options).data("plot")

View File

@ -23,7 +23,7 @@ taiga = @.taiga
bindOnce = @.taiga.bindOnce
debounce = @.taiga.debounce
CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxService) ->
CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxService, $translate) ->
link = ($scope, $el, attrs) ->
$scope.isNew = true
@ -40,10 +40,13 @@ CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxSer
$scope.isNew = true
# Update texts for creation
$el.find(".button-green").html("Create") #TODO: i18n
$el.find(".title").html("New task ") #TODO: i18n
$el.find(".tag-input").val("")
create = $translate.instant("COMMON.CREATE")
$el.find(".button-green").html(create)
newTask = $translate.instant("LIGHTBOX.CREATE_EDIT_TASK.TITLE")
$el.find(".title").html(newTask + " ")
$el.find(".tag-input").val("")
lightboxService.open($el)
$scope.$on "taskform:edit", (ctx, task) ->
@ -51,10 +54,13 @@ CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxSer
$scope.isNew = false
# Update texts for edition
$el.find(".button-green").html("Save") #TODO: i18n
$el.find(".title").html("Edit task ") #TODO: i18n
$el.find(".tag-input").val("")
save = $translate.instant("COMMON.SAVE")
edit = $translate.instant("LIGHTBOX.CREATE_EDIT_TASK.ACTION_EDIT")
$el.find(".button-green").html(save)
$el.find(".title").html(edit + " ")
$el.find(".tag-input").val("")
lightboxService.open($el)
@ -142,6 +148,7 @@ module.directive("tgLbCreateEditTask", [
"$rootScope",
"$tgLoading",
"lightboxService",
"$translate"
CreateEditTaskDirective
])

View File

@ -259,7 +259,6 @@ TaskboardDirective = ($rootscope) ->
event.preventDefault()
target = angular.element(event.currentTarget)
target.toggleClass('active');
#toggleText(target, ["Hide statistics", "Show statistics"]) # TODO: i18n
$rootscope.$broadcast("taskboard:graph:toggle-visibility")
tableBodyDom = $el.find(".taskboard-table-body")

View File

@ -145,7 +145,7 @@ module.controller("TaskDetailController", TaskDetailController)
## Task status display directive
#############################################################################
TaskStatusDisplayDirective = ($template) ->
TaskStatusDisplayDirective = ($template, $compile) ->
# Display if a Task is open or closed and its taskboard status.
#
# Example:
@ -162,6 +162,9 @@ TaskStatusDisplayDirective = ($template) ->
html = template({
status: $scope.statusById[task.status]
})
html = $compile(html)($scope)
$el.html(html)
$scope.$watch $attrs.ngModel, (task) ->
@ -176,14 +179,14 @@ TaskStatusDisplayDirective = ($template) ->
require: "ngModel"
}
module.directive("tgTaskStatusDisplay", ["$tgTemplate", TaskStatusDisplayDirective])
module.directive("tgTaskStatusDisplay", ["$tgTemplate", "$compile", TaskStatusDisplayDirective])
#############################################################################
## Task status button directive
#############################################################################
TaskStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue) ->
TaskStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $translate) ->
# Display the status of Task and you can edit it.
#
# Example:
@ -199,7 +202,7 @@ TaskStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue) ->
<span class="level" style="background-color:<%- status.color %>"></span>
<span class="status-status"><%- status.name %></span>
<% if(editable){ %><span class="icon icon-arrow-bottom"></span><% }%>
<span class="level-name">status</span>
<span class="level-name" translate="COMMON.FIELDS.STATUS"></span>
<ul class="popover pop-status">
<% _.each(statuses, function(st) { %>
@ -208,7 +211,7 @@ TaskStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue) ->
<% }); %>
</ul>
</div>
""") #TODO: i18n
""")
link = ($scope, $el, $attrs, $model) ->
isEditable = ->
@ -217,11 +220,12 @@ TaskStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue) ->
render = (task) =>
status = $scope.statusById[task.status]
html = template({
html = $compile(template({
status: status
statuses: $scope.statusList
editable: isEditable()
})
}))($scope)
$el.html(html)
save = $qqueue.bindAdd (status) =>
@ -274,7 +278,7 @@ TaskStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue) ->
require: "ngModel"
}
module.directive("tgTaskStatusButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue",
module.directive("tgTaskStatusButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$translate",
TaskStatusButtonDirective])

View File

@ -41,18 +41,19 @@ class TeamController extends mixOf(taiga.Controller, taiga.PageMixin)
"$tgNavUrls",
"$appTitle",
"$tgAuth",
"tgLoader"
"tgLoader",
"$translate"
]
constructor: (@scope, @rootscope, @repo, @rs, @params, @q, @location, @navUrls, @appTitle, @auth, tgLoader) ->
@scope.sectionName = "Team"
constructor: (@scope, @rootscope, @repo, @rs, @params, @q, @location, @navUrls, @appTitle, @auth, tgLoader, @translate) ->
@scope.sectionName = "TEAM.SECTION_NAME"
promise = @.loadInitialData()
# On Success
promise.then =>
#TODO: i18n
@appTitle.set("Team - " + @scope.project.name)
text = @translate.instant("TEAM.APP_TITLE", {"projectName": @scope.project.name})
@appTitle.set(text)
# On Error
promise.then null, @.onInitialDataError.bind(@)
@ -211,11 +212,13 @@ module.directive("tgTeamMembers", TeamMembersDirective)
## Leave project Directive
#############################################################################
LeaveProjectDirective = ($repo, $confirm, $location, $rs, $navurls) ->
LeaveProjectDirective = ($repo, $confirm, $location, $rs, $navurls, $translate) ->
link = ($scope, $el, $attrs) ->
$scope.leave = () ->
#TODO: i18n
$confirm.ask("Leave this project", "Are you sure you want to leave the project?").then (finish) =>
leave_project_text = $translate.instant("TEAM.ACTION_LEAVE_PROJECT")
confirm_leave_project_text = $translate.instant("TEAM.CONFIRM_LEAVE_PROJECT")
$confirm.ask(leave_project_text, confirm_leave_project_text).then (finish) =>
promise = $rs.projects.leave($attrs.projectid)
promise.then =>

View File

@ -42,11 +42,12 @@ class UserChangePasswordController extends mixOf(taiga.Controller, taiga.PageMix
"$q",
"$tgLocation",
"$tgNavUrls",
"$tgAuth"
"$tgAuth",
"$translate"
]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @auth) ->
@scope.sectionName = "Change Password" #i18n
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @auth, @translate) ->
@scope.sectionName = @translate.instant("CHANGE_PASSWORD.SECTION_NAME")
@scope.project = {}
@scope.user = @auth.getUser()
@ -74,13 +75,13 @@ module.controller("UserChangePasswordController", UserChangePasswordController)
## User ChangePassword Directive
#############################################################################
UserChangePasswordDirective = ($rs, $confirm, $loading) ->
UserChangePasswordDirective = ($rs, $confirm, $loading, $translate) ->
link = ($scope, $el, $attrs, ctrl) ->
submit = debounce 2000, (event) =>
event.preventDefault()
if $scope.newPassword1 != $scope.newPassword2
$confirm.notify('error', "The passwords dosn't match")
$confirm.notify('error', $translate.instant("CHANGE_PASSWORD.ERROR_PASSWORD_MATCH"))
return
$loading.start(submitButton)

View File

@ -41,17 +41,20 @@ class UserSettingsController extends mixOf(taiga.Controller, taiga.PageMixin)
"$q",
"$tgLocation",
"$tgNavUrls",
"$tgAuth"
"$tgAuth",
"$translate"
]
constructor: (@scope, @rootscope, @config, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @auth) ->
@scope.sectionName = "User Profile" #i18n
constructor: (@scope, @rootscope, @config, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @auth, @translate) ->
@scope.sectionName = "USER_SETTINGS.MENU.SECTION_TITLE"
@scope.project = {}
@scope.user = @auth.getUser()
@scope.lang = @getLan()
maxFileSize = @config.get("maxUploadFileSize", null)
if maxFileSize
@scope.maxFileSizeMsg = "[Max, size: #{sizeFormat(maxFileSize)}" # TODO: i18n
@scope.maxFileSizeMsg = @translate.instant("USER_SETTINGS.AVATAR_MAX_SIZE", {"maxFileSize": sizeFormat(maxFileSize)})
promise = @.loadInitialData()
@ -73,6 +76,10 @@ class UserSettingsController extends mixOf(taiga.Controller, taiga.PageMixin)
openDeleteLightbox: ->
@rootscope.$broadcast("deletelightbox:new", @scope.user)
getLan: ->
return @scope.user.lang ||
@translate.preferredLanguage()
module.controller("UserSettingsController", UserSettingsController)
@ -80,7 +87,7 @@ module.controller("UserSettingsController", UserSettingsController)
## User Profile Directive
#############################################################################
UserProfileDirective = ($confirm, $auth, $repo) ->
UserProfileDirective = ($confirm, $auth, $repo, $translate) ->
link = ($scope, $el, $attrs) ->
submit = debounce 2000, (event) =>
event.preventDefault()
@ -90,13 +97,15 @@ UserProfileDirective = ($confirm, $auth, $repo) ->
changeEmail = $scope.user.isAttributeModified("email")
$scope.user.lang = $scope.lang
$translate.use($scope.user.lang)
onSuccess = (data) =>
$auth.setUser(data)
if changeEmail
$confirm.success("<strong>Check your inbox!</strong><br />
We have sent a mail to your account<br />
with the instructions to set your new address") #TODO: i18n
text = $translate.instant("USER_PROFILE.CHANGE_EMAIL_SUCCESS")
$confirm.success(text)
else
$confirm.notify('success')
@ -113,7 +122,7 @@ UserProfileDirective = ($confirm, $auth, $repo) ->
return {link:link}
module.directive("tgUserProfile", ["$tgConfirm", "$tgAuth", "$tgRepo", UserProfileDirective])
module.directive("tgUserProfile", ["$tgConfirm", "$tgAuth", "$tgRepo", "$translate", UserProfileDirective])
#############################################################################

View File

@ -45,7 +45,7 @@ class UserNotificationsController extends mixOf(taiga.Controller, taiga.PageMixi
]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @auth) ->
@scope.sectionName = "Email Notifications" #i18n
@scope.sectionName = "USER_SETTINGS.NOTIFICATIONS.SECTION_NAME"
@scope.project = {}
@scope.user = @auth.getUser()

View File

@ -154,7 +154,7 @@ module.controller("UserStoryDetailController", UserStoryDetailController)
## User story status display directive
#############################################################################
UsStatusDisplayDirective = ($template) ->
UsStatusDisplayDirective = ($template, $compile) ->
# Display if a US is open or closed and its kanban status.
#
# Example:
@ -164,14 +164,19 @@ UsStatusDisplayDirective = ($template) ->
# - US object (ng-model)
# - scope.statusById object
template = $template.get("common/components/status-display.html", true)
template = $template.get("common/components/status-display.html")
link = ($scope, $el, $attrs) ->
render = (us) ->
html = template({
statusScope = $scope.$new()
_.assign(statusScope, {
is_closed: us.is_closed
status: $scope.statusById[us.status]
})
html = $compile(html)(statusScope)
$el.html(html)
$scope.$watch $attrs.ngModel, (us) ->
@ -186,14 +191,14 @@ UsStatusDisplayDirective = ($template) ->
require: "ngModel"
}
module.directive("tgUsStatusDisplay", ["$tgTemplate", UsStatusDisplayDirective])
module.directive("tgUsStatusDisplay", ["$tgTemplate", "$compile", UsStatusDisplayDirective])
#############################################################################
## User story related tasts progress splay Directive
#############################################################################
UsTasksProgressDisplayDirective = ($template) ->
UsTasksProgressDisplayDirective = ($template, $compile) ->
# Display a progress bar with the stats of completed tasks.
#
# Example:
@ -203,8 +208,6 @@ UsTasksProgressDisplayDirective = ($template) ->
# - Task object list (ng-model)
# - scope.taskStatusById object
template = $template.get("us/us-task-progress.html", true)
link = ($scope, $el, $attrs) ->
render = (tasks) ->
totalTasks = tasks.length
@ -212,12 +215,14 @@ UsTasksProgressDisplayDirective = ($template) ->
progress = if totalTasks > 0 then 100 * totalClosedTasks / totalTasks else 0
html = template({
_.assign($scope, {
totalTasks: totalTasks
totalClosedTasks: totalClosedTasks
progress: progress
progress: progress,
style: {
width: progress + "%"
}
})
$el.html(html)
$scope.$watch $attrs.ngModel, (tasks) ->
render(tasks) if tasks?
@ -226,12 +231,14 @@ UsTasksProgressDisplayDirective = ($template) ->
$el.off()
return {
templateUrl: "us/us-task-progress.html"
link: link
restrict: "EA"
require: "ngModel"
scope: true
}
module.directive("tgUsTasksProgressDisplay", ["$tgTemplate", UsTasksProgressDisplayDirective])
module.directive("tgUsTasksProgressDisplay", ["$tgTemplate", "$compile", UsTasksProgressDisplayDirective])
#############################################################################
@ -326,7 +333,7 @@ module.directive("tgUsStatusButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$t
## User story team requirements button directive
#############################################################################
UsTeamRequirementButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qqueue, $template) ->
UsTeamRequirementButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qqueue, $template, $compile) ->
template = $template.get("us/us-team-requirement-button.html", true)
link = ($scope, $el, $attrs, $model) ->
@ -343,6 +350,8 @@ UsTeamRequirementButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qq
isRequired: us.team_requirement
}
html = template(ctx)
html = $compile(html)($scope)
$el.html(html)
save = $qqueue.bindAdd (team_requirement) =>
@ -383,13 +392,13 @@ UsTeamRequirementButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qq
require: "ngModel"
}
module.directive("tgUsTeamRequirementButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate", UsTeamRequirementButtonDirective])
module.directive("tgUsTeamRequirementButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate", "$compile", UsTeamRequirementButtonDirective])
#############################################################################
## User story client requirements button directive
#############################################################################
UsClientRequirementButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qqueue, $template) ->
UsClientRequirementButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qqueue, $template, $compile) ->
template = $template.get("us/us-client-requirement-button.html", true)
link = ($scope, $el, $attrs, $model) ->
@ -405,7 +414,7 @@ UsClientRequirementButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $
canEdit: canEdit()
isRequired: us.client_requirement
}
html = template(ctx)
html = $compile(template(ctx))($scope)
$el.html(html)
save = $qqueue.bindAdd (client_requirement) =>
@ -443,5 +452,5 @@ UsClientRequirementButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $
require: "ngModel"
}
module.directive("tgUsClientRequirementButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate",
module.directive("tgUsClientRequirementButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate", "$compile",
UsClientRequirementButtonDirective])

View File

@ -49,11 +49,12 @@ class WikiDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
"$appTitle",
"$tgNavUrls",
"$tgAnalytics",
"tgLoader"
"tgLoader",
"$translate"
]
constructor: (@scope, @rootscope, @repo, @model, @confirm, @rs, @params, @q, @location,
@filter, @log, @appTitle, @navUrls, @analytics, tgLoader) ->
@filter, @log, @appTitle, @navUrls, @analytics, tgLoader, @translate) ->
@scope.projectSlug = @params.pslug
@scope.wikiSlug = @params.slug
@scope.sectionName = "Wiki"
@ -111,8 +112,7 @@ class WikiDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
@q.all([@.loadWikiLinks(), @.loadWiki()])
delete: ->
# TODO: i18n
title = "Delete Wiki Page"
title = @translate.instant("WIKI.DELETE_LIGHTBOX_TITLE")
message = unslugify(@scope.wiki.slug)
@confirm.askOnDelete(title, message).then (finish) =>
@ -135,7 +135,7 @@ module.controller("WikiDetailController", WikiDetailController)
## Wiki Summary Directive
#############################################################################
WikiSummaryDirective = ($log, $template) ->
WikiSummaryDirective = ($log, $template, $compile) ->
template = $template.get("wiki/wiki-summary.html", true)
link = ($scope, $el, $attrs, $model) ->
@ -156,6 +156,7 @@ WikiSummaryDirective = ($log, $template) ->
user: user
}
html = template(ctx)
html = $compile(html)($scope)
$el.html(html)
$scope.$watch $attrs.ngModel, (wikiPage) ->
@ -171,7 +172,7 @@ WikiSummaryDirective = ($log, $template) ->
require: "ngModel"
}
module.directive("tgWikiSummary", ["$log", "$tgTemplate", WikiSummaryDirective])
module.directive("tgWikiSummary", ["$log", "$tgTemplate", "$compile", WikiSummaryDirective])
#############################################################################

View File

@ -34,7 +34,7 @@ module = angular.module("taigaWiki")
## Wiki Main Directive
#############################################################################
WikiNavDirective = ($tgrepo, $log, $location, $confirm, $navUrls, $analytics, $loading, $template) ->
WikiNavDirective = ($tgrepo, $log, $location, $confirm, $navUrls, $analytics, $loading, $template, $compile, $translate) ->
template = $template.get("wiki/wiki-nav.html", true)
link = ($scope, $el, $attrs) ->
$ctrl = $el.controller()
@ -53,6 +53,8 @@ WikiNavDirective = ($tgrepo, $log, $location, $confirm, $navUrls, $analytics, $l
deleteWikiLinkPermission: deleteWikiLinkPermission
})
html = $compile(html)($scope)
$el.off()
$el.html(html)
@ -80,8 +82,7 @@ WikiNavDirective = ($tgrepo, $log, $location, $confirm, $navUrls, $analytics, $l
target = angular.element(event.currentTarget)
linkId = target.parents('.wiki-link').data('id')
# TODO: i18n
title = "Delete Wiki Link"
title = $translate.instant("WIKI.DELETE_LIGHTBOX_TITLE")
message = $scope.wikiLinks[linkId].title
$confirm.askOnDelete(title, message).then (finish) =>
@ -143,4 +144,4 @@ WikiNavDirective = ($tgrepo, $log, $location, $confirm, $navUrls, $analytics, $l
return {link:link}
module.directive("tgWikiNav", ["$tgRepo", "$log", "$tgLocation", "$tgConfirm", "$tgNavUrls",
"$tgAnalytics", "$tgLoading", "$tgTemplate", WikiNavDirective])
"$tgAnalytics", "$tgLoading", "$tgTemplate", "$compile", "$translate", WikiNavDirective])

View File

@ -1,63 +0,0 @@
{
"checksley": {
"defaultMessage": "This value seems to be invalid.",
"type-email": "This value should be a valid email.",
"type-url": "This value should be a valid url.",
"type-urlstrict": "This value should be a valid url.",
"type-number": "This value should be a valid number.",
"type-digits": "This value should be digits.",
"type-dateIso": "This value should be a valid date (YYYY-MM-DD).",
"type-alphanum": "This value should be alphanumeric.",
"type-phone": "This value should be a valid phone number.",
"notnull": "This value should not be null.",
"notblank": "This value should not be blank.",
"required": "This value is required.",
"regexp": "This value seems to be invalid.",
"min": "This value should be greater than or equal to %s.",
"max": "This value should be lower than or equal to %s.",
"range": "This value should be between %s and %s.",
"minlength": "This value is too short. It should have %s characters or more.",
"maxlength": "This value is too long. It should have %s characters or less.",
"rangelength": "This value length is invalid. It should be between %s and %s characters long.",
"mincheck": "You must select at least %s choices.",
"maxcheck": "You must select %s choices or less.",
"rangecheck": "You must select between %s and %s choices.",
"equalto": "This value should be the same."
},
"common": {
"subject": "Subject",
"save": "Save",
"blocked": "Blocked",
"cancel": "Cancel",
"status": "Status",
"new-bulk": "New bulk insert",
"one-item-line": "One item per line..."
},
"pagination": {
"next": "Next",
"prev": "Previous"
},
"markdown-editor": {
"heading-1": "First Level Heading",
"heading-2": "Second Level Heading",
"heading-3": "Third Level Heading",
"bold": "Bold",
"italic": "Italic",
"strike": "Strike",
"bulleted-list": "Bulleted List",
"numeric-list": "Numeric List",
"picture": "Picture",
"link": "Link",
"quotes": "Quotes",
"code-block": "Code Block / Code",
"preview": "Preview",
"help": "Help",
"placeholder": "Your title here...",
"link-placeholder": "Your text to link here..."
},
"us": {
"title-new": "New User Story",
"team-requirement": "Team Requirement",
"client-requirement": "Client Requirement"
}
}

872
app/locales/locale-en.json Normal file
View File

@ -0,0 +1,872 @@
{
"COMMON": {
"YES": "Yes",
"NO": "No",
"LOADING": "Loading...",
"LOADING_PROJECT": "Loading project...",
"SAVE": "Save",
"CANCEL": "Cancel",
"ACCEPT": "Accept",
"DELETE": "Delete",
"CREATE": "Create",
"ADD": "Add",
"YES": "Yes",
"NO": "No",
"COPY_TO_CLIPBOARD": "Copy to clipboard: Ctrl+C",
"EDIT": "Edit",
"DRAG": "Drag",
"TAG_LINE": "Your agile, free, and open source project management tool",
"TAG_LINE_2": "LOVE YOUR PROJECT",
"BLOCK": "Block",
"UNBLOCK": "Unblock",
"BLOCKED": "Blocked",
"CREATED_BY": "Created by {{fullDisplayName}}",
"FROM": "from",
"TO": "to",
"CLOSE": "close",
"BLOCKED_NOTE": "Why is this user story blocked?",
"BLOCKED_REASON": "Please explain the reason",
"GO_HOME": "Take me home",
"PLUGINS": "Plugins",
"BETA": "We are on beta!",
"ONE_ITEM_LINE": "One item per line...",
"NEW_BULK": "New bulk insert",
"RELATED_TASKS": "Related tasks",
"LOGOUT": "Logout",
"GENERIC_ERROR": "One of our Oompa Loompas says {{error}}.",
"IOCAINE_TEXT": "Feeling a bit overwhelmed by a task? Make sure others know about it by clicking on Iocaine when editing a task. It's possible to become immune to this (fictional) deadly poison by consuming small amounts over time just as it's possible to get better at what you do by occasionally taking on extra challenges!",
"TAGS": {
"PLACEHOLDER": "I'm it! Tag me...",
"DELETE": "delete tag",
"ADD": "Add tag"
},
"DESCRIPTION": {
"EMPTY": "Empty space is so boring... go on be descriptive... A rose by any other name would smell as sweet...",
"MARKDOWN_HELP": "Markown syntax help",
"NO_DESCRIPTION": "No description yet"
},
"FIELDS": {
"SUBJECT": "Subject",
"NAME": "Name",
"URL": "URL",
"DESCRIPTION": "Description",
"VALUE": "Value",
"SLUG": "Slug",
"COLOR": "Color",
"IS_CLOSED": "Is closed?",
"STATUS": "Status",
"ASSIGNED_TO": "Assigned to",
"POINTS": "Points",
"BLOCKED_NOTE": "blocked note",
"IS_BLOCKED": "is blocked"
},
"ROLES": {
"ALL": "All"
},
"ASSIGNED_TO": {
"NOT_ASSIGNED": "Not assigned",
"DELETE_ASSIGNMENT": "Delete assignment",
"REMOVE_ASSIGNED": "Remove assigned",
"TOO_MANY": "...too many users, keep filtering",
"CONFIRM_UNASSIGNED": "Are you sure you want to leave it unassigned?"
},
"STATUS": {
"CLOSED": "Closed",
"OPEN": "Open"
},
"WATCHERS": {
"ADD": "Add watcher",
"TITLE": "watchers",
"DELETE": "delete watcher"
},
"CUSTOM_ATTRIBUTES": {
"CUSTOM_FIELDS": "Custom Fields",
"SAVE": "Save Custom Field",
"EDIT": "Edit Custom Field",
"DELETE": "Delete custom attribute",
"CONFIRM_DELETE": "Remeber that all values in this custom field will be deleted.</br> Are you sure you want to continue?"
},
"FILTERS": {
"TITLE": "filters",
"INPUT_PLACEHOLDER": "Subject or reference",
"TITLE_ACTION_FILTER_BUTTON": "search",
"BREADCRUMB_TITLE": "back to categories",
"BREADCRUMB_FILTERS": "Filters",
"BREADCRUMB_STATUS": "status"
}
},
"AUTH": {
"INVITED_YOU": "has invited you to join the project",
"NOT_REGISTERED_YET": "Not registered yet?",
"REGISTER": "Register",
"CREATE_ACCOUNT": "create your free account here"
},
"ATTACHMENT": {
"SECTION_NAME": "attachments",
"TITLE": "<%- name %> uploaded on <%- created_date %>",
"DESCIPTION": "Type a short description",
"DEPRECATED_FILE": "Deprecated?",
"ADD": "Add new attachment. <%- maxFileSizeMsg %>",
"MAX_FILE_SIZE": "[Max. size: {{maxFileSize}}]",
"SHOW_DEPRECATED": "+ show deprecated atachments",
"HIDE_DEPRECATED": "- hide deprecated atachments",
"COUNT_DEPRECATED": "({{ctrl.deprecatedAttachmentsCount }} deprecated)",
"MAX_UPLOAD_SIZE": "Maximum upload size is {{maxFileSize}}",
"DATE": "DD MMM YYYY [at] hh:mm",
"FIELDS": {
"IS_DEPRECATED": "is deprecated"
}
},
"PAGINATION": {
"PREVIOUS": "Prev",
"NEXT": "Next"
},
"ADMIN": {
"COMMON": {
"TITLE_ACTION_EDIT_VALUE": "Edit value",
"TITLE_ACTION_DELETE_VALUE": "Delete value"
},
"HELP": "Do you need help? Check out our support page!",
"PROJECT_DEFAULT_VALUES": {
"TITLE": "Default Values",
"SUBTITLE": "Set default values for all selector inputs."
},
"MEMBERSHIPS": {
"TITLE": "Manage members",
"ADD_BUTTON": "+ New member",
"ADD_BUTTON_TITLE": "Add new member"
},
"PROJECT_EXPORT": {
"TITLE": "Export",
"SUBTITLE": "Export your project to save a backup or to create a new one based on this.",
"EXPORT_BUTTON": "Export",
"EXPORT_BUTTON_TITLE": "Export your project",
"LOADING_TITLE": "We are generating your dump file",
"DUMP_READY": "Your dump file is ready!",
"LOADING_MESSAGE": "Please don't close this page.",
"ASYNC_MESSAGE": "We will send you an email when ready.",
"SYNC_MESSAGE": "If the download doesn't start automatically click <a href='{{url}}' download title='Download the dump file'>here.",
"ERROR": "Our oompa loompas have some problems generasting your dump. MPlease try again.",
"ERROR_BUSY": "Sorry, our oompa loompas are very busy right now. Please try again in a few minutes.",
"ERROR_MESSAGE": "Our oompa loompas have some problems generasting your dump: {{message}}"
},
"MODULES": {
"TITLE": "Modules",
"ENABLE": "Enable",
"DISABLE": "Disable",
"BACKLOG": "Backlog",
"BACKLOG_DESCRIPTION": "Manage your user stories to maintain an organized view of upcoming and prioritized work.",
"KANBAN": "Kanban",
"KANBAN_DESCRIPTION": "Organize your project in a lean way with this board.",
"ISSUES": "Issues",
"ISSUES_DESCRIPTION": "Track the bugs, questions and enhancements related to your project. Don't miss anything!",
"WIKI": "Wiki",
"WIKI_DESCRIPTION": "Add, modify, or delete content in collaboration with others. This is the right place for your project documentation.",
"MEETUP": "Meet Up",
"MEETUP_DESCRIPTION": "Choose your videoconference system. Even developers need face to face contact.",
"SELECT_VIDEOCONFERENCE": "Select a videoconference system",
"SALT_CHAT_ROOM": "If you want you can append a salt code to the name of the chat room"
},
"PROJECT_PROFILE": {
"PAGE_TITLE": "Project profile - {{sectionName}} - {{projectName}}",
"PROJECT_DETAILS": "Project details",
"PROJECT_NAME": "Project name",
"PROJECT_SLUG": "Project slug",
"NUMBER_SPRINTS": "Number of sprints",
"NUMBER_US_POINTS": "Number of US points",
"DESCRIPTION": "DESCRIPTION",
"PUBLIC_PROJECT": "Public project",
"PRIVATE_PROJECT": "Private project",
"DELETE": "Delete this project"
},
"REPORTS": {
"TITLE": "Reports",
"SUBTITLE": "Export your project data in CSV format and make your own reports.",
"DESCRIPTION": "Download a CSV file or copy the generated URL and open it in your favourite text editor or spreadsheet to make your own project data reports. You will be able to visualize and analize all your data easily.",
"HELP": "How to use this on my own spreadsheet?",
"REGENERATE_TITLE": "Change URL",
"REGENERATE_SUBTITLE": "You going to change the CSV data access url. The previous url will be disabled. Are you sure?"
},
"CUSTOM_FIELDS": {
"TITLE": "Custom Fields",
"SUBTITLE": "Specify the custom fields for your user stories, tasks and issues",
"US_DESCRIPTION": "User stories custom fields",
"US_ADD": "Add a custom field in user stories",
"TASK_DESCRIPTION": "Tasks custom fields",
"TASK_ADD": "Add a custom field in tasks",
"ISSUE_DESCRIPTION": "Issues custom fields",
"ISSUE_ADD": "Add a custom field in issues"
},
"PROJECT_VALUES": {
"APP_TITLE": "Project values - {{sectionName}} - {{projectName}}",
"REPLACEMENT": "All items with this value will be changed to",
"ERROR_DELETE_ALL": "You can't delete all values."
},
"PROJECT_VALUES_POINTS": {
"TITLE": "Us points",
"SUBTITLE": "Specify the points your user stories could be estimated to",
"ACTION_ADD": "Add new point"
},
"PROJECT_VALUES_PRIORITIES": {
"TITLE": "Issue priorities",
"SUBTITLE": "Specify the priorities your issues will have"
},
"PROJECT_VALUES_SEVERITIES": {
"TITLE": "Issue severities",
"SUBTITLE": "Specify the severities your issues will have"
},
"PROJECT_VALUES_STATUS": {
"TITLE": "Status",
"SUBTITLE": "Specify the statuses your user stories, tasks and issues will go through",
"US_TITLE": "US Statuses",
"TASK_TITLE": "Task Statuses",
"ISSUE_TITLE": "Issue Statuses"
},
"PROJECT_VALUES_TYPES": {
"TITLE": "Types",
"SUBTITLE": "Specify the types your user stories could be estimated to",
"ISSUE_TITLE": "Issues types",
"ACTION_ADD": "Add new {{objName}}"
},
"ROLES": {
"SECTION_NAME": "Roles - {{projectName}}",
"WARNING_NO_ROLE": "Be careful, no role in your project will be able to estimate the point value for user stories",
"HELP_ROLE_ENABLED": "When enabled, members assigned to this role will be able to estimate the point value for user stories",
"COUNT_MEMBERS": "{{ role.members_count }} members with this role",
"TITLE_DELETE_ROLE": "Delete Role",
"REPLACEMENT_ROLE": "All the users with this role will be moved to",
"WARNING_DELETE_ROLE": "<strong>Be careful, all role estimations will be removed</strong>",
"ERROR_DELETE_ALL": "You can't delete all values"
},
"THIRD_PARTIES": {
"SECRET_KEY": "Secret key",
"PAYLOAD_URL": "Payload URL",
"VALID_IPS": "Valid origin ips (separated by ,)"
},
"BITBUCKET": {
"SECTION_NAME": "Bitbucket",
"APP_TITLE": "Bitbucket - {{projectName}}",
"INFO_VERIFYING_IP": "Bitbucket requests are not signed so the best way of verifying the origin is by IP. If the field is empty there will be no IP validation."
},
"GITLAB": {
"SECTION_NAME": "Gitlab",
"APP_TITLE": "Gitlab - {{projectName}}",
"INFO_VERIFYING_IP": "Gitlab requests are not signed so the best way of verifying the origin is by IP. If the field is empty there will be no IP validation."
},
"GITHUB": {
"SECTION_NAME": "Github",
"APP_TITLE": "Github - {{projectName}}"
},
"WEBHOOKS": {
"APP_TITLE": "Webhooks - {{projectName}}",
"SECTION_NAME": "Webhooks",
"SUBTITLE": "Webhooks notify external services about events in Taiga, like comments, user stories....",
"ADD_NEW": "Add a New Webhook",
"TYPE_NAME": "Type the service name",
"TYPE_PAYLOAD_URL": "Type the service payload url",
"TYPE_SERVICE_SECRET": "Type the service secret key",
"SAVE": "Save Webhook",
"CANCEL": "Cancel Webhook",
"TOGGLE_HISTORY": "Toggle history",
"SHOW_HISTORY": "(Show history)",
"TEST": "Test Webhook",
"EDIT": "Edit Webhook",
"DELETE": "Delete Webhook",
"REQUEST": "Request",
"RESEND_REQUEST": "Resend request",
"HEADERS": "Headers",
"PAYLOAD": "Payload",
"RESPONSE": "Response",
"DATE": "DD MMM YYYY [at] hh:mm:ss",
"ACTION_HIDE_HISTORY": "(Hide history)",
"ACTION_SHOW_HISTORY": "(Show history)",
"WEBHOOK_NAME": "Webhook '{{name}}'"
},
"CUSTOM_ATTRIBUTES": {
"ADD": "Add custom field",
"EDIT": "Edit Custom Field",
"DELETE": "Delete Custom Field",
"SAVE_TITLE": "Save Custom Field",
"CANCEL_TITLE": "Cancel creation",
"SET_FIELD_NAME": "Set your custom field name",
"SET_FIELD_DESCRIPTION": "Set your custom field description",
"ACTION_UPDATE": "Update Custom Field",
"ACTION_CANCEL_EDITION": "Cancel edition"
},
"MEMBERSHIP": {
"COLUMN_MEMBER": "Member",
"COLUMN_ADMIN": "Admin",
"COLUMN_ROLE": "Role",
"COLUMN_STATUS": "Status",
"STATUS_ACTIVE": "Active",
"STATUS_PENDING": "Pending",
"DELETE_MEMBER": "Delete member",
"SUCCESS_SEND_INVITATION": "We've sent the invitation again to '{{email}}'.",
"ERROR_SEND_INVITATION": "We haven't sent the invitation.",
"SUCCESS_DELETE": "We've deleted {{message}}.",
"ERROR_DELETE": "We have not been able to delete {{message}}.",
"DEFAULT_DELETE_MESSAGE": "the invitation to {{email}}"
},
"DEFAULT_VALUES": {
"LABEL_POINTS": "Default value for points selector",
"LABEL_US": "Default value for US status selector",
"LABEL_TASK_STATUS": "Default value for task status selector",
"LABEL_PRIORITY": "Default value for priority selector",
"LABEL_SEVERITY": "Default value for severity selector",
"LABEL_ISSUE_TYPE": "Default value for issue type selector",
"LABEL_ISSUE_STATUS": "Default value for issue status selector"
},
"PROJECT": {
"COLORS": {
"ACTION_NEW_STATUS": "+ Add new status"
}
},
"CSV": {
"TITLE": "{{csvType}} reports",
"DOWNLOAD": "Download CSV",
"URL_FIELD_PLACEHOLDER": "Please regenerate CSV url",
"TITLE_REGENERATE_URL": "Regenerate CSV url",
"ACTION_GENERATE_URL": "Generate Url",
"ACTION_REGENERATE": "Regenerate"
},
"STATUS": {
"PLACEHOLDER_WRITE_STATUS_NAME": "Write a name for the new status"
},
"TYPES": {
"PLACEHOLDER_WRITE_NAME": "Write a name for the new element"
},
"US_STATUS": {
"ACTION_ADD_STATUS": "Add new status",
"IS_ARCHIVED_COLUMN": "Is archived?",
"WIP_LIMIT_COLUMN": "WIP Limit",
"PLACEHOLDER_WRITE_NAME": "Write a name for the new status"
},
"MENU": {
"TITLE": "Admin",
"PROJECT": "Project",
"ATTRIBUTES": "Attributes",
"MEMBERS": "Members",
"PERMISSIONS": "Permissions",
"INTEGRATIONS": "Integrations",
"PLUGINS": "Plugins"
},
"SUBMENU": {
"ROLE_UX": "UX",
"ROLE_PRODUCT_OWNER": "Product Owner",
"ROLE_DESIGNER": "Designer",
"ROLE_BACK": "Back",
"ROLE_FRONT": "Front",
"ACTION_NEW_ROLE": "+ New role",
"TITLE_ACTION_NEW_ROLE": "Add new role"
},
"SUBMENU_PROJECT_VALUES": {
"STATUS": "Status",
"POINTS": "Points",
"PRIORITIES": "Priorities",
"SEVERITIES": "Severities",
"TYPES": "Types",
"CUSTOM_FIELDS": "Custom fields"
},
"SUBMENU_PROJECT_PROFILE": {
"TITLE": "Project Profile"
},
"SUBMENU_ROLES": {
"TITLE": "Roles"
},
"SUBMENU_THIDPARTIES": {
"TITLE": "Services"
}
},
"PROJECT": {
"WELCOME": "Welcome",
"SECTION_PROJECTS": "Projects",
"STATS": {
"PROJECT": "project<br/> points",
"DEFINED": "defined<br/> points",
"ASSIGNED": "assigned<br/> points",
"CLOSED": "closed<br/> points"
},
"SECTION": {
"SEARCH": "Search",
"BACKLOG": "Backlog",
"KANBAN": "Kanban",
"ISSUES": "Issues",
"WIKI": "Wiki",
"TEAM": "Team",
"MEETUP": "Meet Up",
"ADMIN": "Admin"
},
"NAVIGATION": {
"SECTION_TITLE": "Your project",
"PLACEHOLDER_SEARCH": "Search in...",
"ACTION_CREATE_PROJECT": "Create project",
"TITLE_ACTION_IMPORT": "Import project",
"TITLE_PRVIOUS_PROJECT": "Show previous projects",
"TITLE_NEXT_PROJECT": "Show next projects"
},
"IMPORT": {
"TITLE": "Importing Project",
"DESCRIPTION": "This process can take a while, please keep the window open.",
"ASYNC_IN_PROGRESS_TITLE": "Our Oompa Loompas are importing your project",
"ASYNC_IN_PROGRESS_MESSAGE": "This process could take a few minutes <br/> We will send you an email when ready",
"ERROR": "Our oompa loompas have some problems importing your dump data. Please try again.",
"ERROR_TOO_MANY_REQUEST": "Sorry, our oompa loompas are very busy right now. Please try again in a few minutes.",
"ERROR_MESSAGE": "Our oompa loompas have some problems importing your dump data: {{error_message}}",
"SYNC_SUCCESS": "Your project has been imported successfuly"
}
},
"LIGHTBOX": {
"DELETE_ACCOUNT": {
"SECTION_NAME": "Delete Taiga Account",
"CONFIRM": "Are you sure you want to delete your Taiga account?",
"SUBTITLE": "We're going to miss you! :-("
},
"DELETE_PROJECT": {
"TITLE": "Delete project",
"QUESTION": "Are you sure you want to delete this project?",
"SUBTITLE": "All project data US/Tasks/Issues/Sprints/WikiPages will be lost! :-(",
"CONFIRM": "Yes, I'm really sure"
},
"ASSIGNED_TO": {
"SELECT": "Select assigned to",
"SEARCH": "Search for users"
},
"ADD_MEMBER": {
"TITLE": "New Member",
"HELP_TEXT": "If users are already registered on Taiga, they will be added automatically. Otherwise they will receive an invitation."
},
"CREATE_ISSUE": {
"TITLE": "Add Issue"
},
"FEEDBACK": {
"TITLE": "Tell us something...",
"COMMENT": "...a bug, some suggestions, something cool... or even your worst nightmare with Taiga",
"ACTION_SEND": "Send feedback"
},
"SEARCH": {
"TITLE": "Search",
"PLACEHOLDER_SEARCH": "What are you looking for?"
},
"ADD_EDIT_SPRINT": {
"TITLE": "New sprint",
"PLACEHOLDER_SPRINT_NAME": "sprint name",
"PLACEHOLDER_SPRINT_START": "Estimated Start",
"PLACEHOLDER_SPRINT_END": "Estimated End",
"ACTION_DELETE_SPRINT": "Do you want to delete this sprint?",
"TITLE_ACTION_DELETE_SPRINT": "delete sprint",
"LAST_SPRINT_NAME": " last sprint is <strong> {{lastSprint}} ;-) </strong>"
},
"CREATE_EDIT_TASK": {
"TITLE": "New task",
"PLACEHOLDER_SUBJECT": "A task subject",
"PLACEHOLDER_STATUS": "Task status",
"OPTION_UNASSIGNED": "Unassigned",
"PLACEHOLDER_SHORT_DESCRIPTION": "Type a short description",
"ACTION_EDIT": "Edit task"
},
"CREATE_EDIT_US": {
"TITLE": "New US",
"PLACEHOLDER_DESCRIPTION": "Please add descriptive text to help others better understand this US",
"NEW_US": "New user story",
"EDIT_US": "Edit user story"
},
"DELETE_SPRINT": {
"TITLE": "Delete sprint"
},
"CREATE_MEMBER": {
"PLACEHOLDER_INVITATION_TEXT": "(Optional) Add a personalized text to the invitation. Tell something lovely to your new members ;-)",
"PLACEHOLDER_TYPE_EMAIL": "Type an Email"
}
},
"US": {
"TOTAL_POINTS": "total",
"ADD": "+ Add a new User Story",
"ADD_BULK": "Add some new User Stories in bulk",
"PROMOTED": "This US has been promoted from Issue",
"TITLE_LINK_GO_TO_ISSUE": "Go to issue",
"EXTERNAL_REFERENCE": "This US has been created from",
"GO_TO_EXTERNAL_REFERENCE": "Go to origin",
"BLOCKED": "This user story is blocked",
"PREVIOUS": "previous user story",
"NEXT": "next user story",
"TITLE_DELETE_ACTION": "Delete User Story",
"LIGHTBOX_TITLE_BLOKING_US": "Blocking us",
"TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} tasks completed",
"ASSIGN": "Assign User Story",
"NOT_ESTIMATED": "Not estimated",
"TOTAL_US_POINTS": "Total Us points",
"FIELDS": {
"TEAM_REQUIREMENT": "Team Requirement",
"CLIENT_REQUIREMENT": "Client Requirement",
"FINISH_DATE": "Finish date"
}
},
"COMMENTS": {
"DELETED_INFO": "Comment deleted by {{deleteCommentUser}} on {{deleteCommentDate}}",
"TITLE": "Comments",
"COMMENT": "Comment",
"TYPE_NEW_COMMENT": "Type a new comment here",
"SHOW_DELETED": "Show deleted comment",
"HIDE_DELETED": "Hide deleted comment",
"RESTORE": "Restore comment"
},
"ACTIVITY": {
"SHOW_ACTIVITY": "Show activity",
"SHOW_MORE": "+ Show previous entries ({{showMore}} more)",
"TITLE": "Activity",
"REMOVED": "removed",
"ADDED": "added",
"US_POINTS": "US points ({{name}})",
"NEW_ATTACHMENT": "new attachment",
"DELETED_ATTACHMENT": "deleted attachment",
"UPDATED_ATTACHMENT": "updated attachment {{filename}}",
"DELETED_CUSTOM_ATTRIBUTE": "deleted custom attribute",
"SIZE_CHANGE": "Made {{size}} {size, plural, one{change} other{changes}}"
},
"BACKLOG": {
"MOVE_US_TO_CURRENT_SPRINT": "Move to Current Sprint",
"SHOW_FILTERS": "Show filters",
"SHOW_TAGS": "Show tags",
"EMPTY": "Your backlog is empty!",
"CREATE_NEW_US": "Create a new US",
"CREATE_NEW_US_EMPTY_HELP": "You may want to create a new user story",
"EXCESS_OF_POINTS": "Excess of points",
"PENDING_POINTS": "Pending Points",
"CLOSED_POINTS": "Closed points",
"COMPACT_SPRINT": "Compact Sprint",
"GO_TO_TASKBOARD": "Go to the taskboard of {{::name}}",
"EDIT_SPRINT": "Edit Sprint",
"CLOSED_POINTS": "closed",
"TOTAL_POINTS": "total",
"STATUS_NAME": "Status Name",
"SORTABLE_FILTER_ERROR": "You can't drop on backlog when filters are open",
"DOOMLINE": "Project Scope [Doomline]",
"CHART": {
"OPTIMAL": "Optimal pending points for sprint {{xval}} should be {{yval}}",
"REAL": "Real pending points for sprint {{xval}} is {{yval}}",
"INCREMENT_TEAM": "Incremented points by team requirements for sprint {{xval}} is {{yval}}",
"INCREMENT_CLIENT": "Incremented points by client requirements for sprint {{xval}} is {{yval}}"
},
"TAGS": {
"SHOW": "Show Tags",
"HIDE": "Hide Tags"
},
"TABLE": {
"COLUMN_US": "User Stories",
"TITLE_COLUMN_POINTS": "Select view per Role"
},
"SPRINT_SUMMARY": {
"TOTAL_POINTS": "total<br />points",
"COMPLETED_POINTS": "completed<br />points",
"OPEN_TASKS": "open<br />tasks",
"CLOSED_TASKS": "closed<br />tasks",
"IOCAINE_DOSES": "iocaine<br />doses",
"SHOW_STATISTICS_TITLE": "Show statistics"
},
"SUMMARY": {
"PROJECT_POINTS": "project<br />points",
"DEFINED_POINTS": "defined<br />points",
"CLOSED_POINTS": "closed<br />points",
"POINTS_PER_SPRINT": "points /<br />sprint"
},
"FILTERS": {
"TITLE": "Filters",
"REMOVE": "Remove Filters",
"SHOW": "Show Filters",
"FILTER_CATEGORY_STATUS": "Status",
"FILTER_CATEGORY_TAGS": "Tags"
},
"SPRINTS": {
"TITLE": "SPRINTS",
"LINK_TASKBOARD": "Sprint Taskboard",
"TITLE_LINK_TASKBOARD": "Go to Taskboard of {{spring.name}}",
"NUMBER_SPRINTS": "<br/>sprints",
"TITLE_ACTION_NEW_SPRINT": "+ New sprint",
"ACTION_NEW_SPRINT": "+ New sprint",
"ACTION_SHOW_CLOSED_SPRINTS": "Show closed sprints",
"ACTION_HIDE_CLOSED_SPRINTS": "Hide closed sprints"
}
},
"ERROR": {
"TEXT1": "Something happened and our Oompa Loompas are working on it.",
"TEXT2": "Try reloading again soon.",
"NOT_FOUND": "Not found",
"NOT_FOUND_TEXT": "Error 404. The page you are looking for no longer exists. Perhaps you can return back to TAIGA homepage and see if you can find what you are looking for.",
"PERMISSION_DENIED": "Permission denied",
"PERMISSION_DENIED_CODE": "Error 403."
},
"TASKBOARD": {
"SECTION_NAME": "Taskboard",
"TITLE_ACTION_ADD": "Add a new Task",
"TITLE_ACTION_ADD_BULK": "Add some new Tasks in bulk",
"TITLE_ACTION_ASSIGN": "Assign task",
"TITLE_ACTION_EDIT": "Edit task",
"TABLE": {
"COLUMN": "User story",
"TITLE_ACTION_FOLD": "Fold column",
"TITLE_ACTION_UNFOLD": "Unfold column",
"TITLE_ACTION_FOLD_ROW": "Fold Row",
"TITLE_ACTION_UNFOLD_ROW": "Unfold Row",
"FIELD_POINTS": "points",
"ROW_UNASSIGED_TASKS_TITLE": "Unassigned tasks"
},
"CHARTS": {
"OPTIMAL": "Optimal pending points for day #{formattedDate} should be {{roundedValue}}",
"REAL": "Real pending points for day {{formattedDate}} is {{roundedValue}}"
}
},
"TASK": {
"PLACEHOLDER_SUBJECT": "Type the new task subject",
"TITLE_SELECT_STATUS": "Status Name",
"LINK_TASKBOARD": "Go to taskboard",
"OWNER_US": "This task belongs to",
"TITLE_LINK_GO_OWNER": "Go to user story",
"ORIGIN_US": "This task has been created from",
"TITLE_LINK_GO_ORIGIN": "Go to user story",
"BLOCKED": "This task is blocked",
"PREVIOUS": "previous task",
"NEXT": "next task",
"TITLE_DELETE_ACTION": "Delete Task",
"LIGHTBOX_TITLE_BLOKING_TASK": "Blocking task",
"FIELDS": {
"MILESTONE": "Sprint",
"USER_STORY": "User story",
"IS_IOCAINE": "Is iocaine"
}
},
"NOTIFICATION": {
"OK": "Everything is ok",
"WARNING": "Oops, something happened...",
"WARNING_TEXT": "Our oompa Loompas are sad, your changes were not saved!",
"SAVED": "Our oompa Loompas saved all your changes!",
"CLOSE": "Close notification",
"MAIL": "Notifications By Mail",
"ASK_DELETE": "Are you sure you want to delete?"
},
"CANCEL_ACCOUNT": {
"TITLE": "Cancel your account",
"SUBTITLE": "We're sorry you are leaving the taiga, we hope you enjoyed your stay :)",
"PLACEHOLDER_INPUT_TOKEN": "cancel account token",
"ACTION_LEAVING": "Yes, I'm leaving!",
"SUCCESS": "Our Oompa Loompas removed your account"
},
"CHANGE_EMAIL_FORM": {
"TITLE": "Change your email",
"SUBTITLE": "One click more and your email will be updated!",
"PLACEHOLDER_INPUT_TOKEN": "change email token",
"ACTION_CHANGE_EMAIL": "Change email",
"SUCCESS": "Our Oompa Loompas updated your email"
},
"CHANGE_PASSWORD_RECOVERY_FORM": {
"TITLE": "Create a new Taiga pass",
"SUBTITLE": "And hey, you may want to eat some more iron-rich food, it's good for your brain :P",
"PLACEHOLDER_RECOVER_PASSWORD_TOKEN": "Recover password token",
"LINK_NEED_TOKEN": "Need one?",
"TITLE_LINK_NEED_TOKEN": "Did you need a token to recover your password because you forgot it?",
"PLACEHOLDER_NEW_PASSWORD": "New password",
"PLACEHOLDER_RE_TYPE_NEW_PASSWORD": "Re-type new password",
"ACTION_RESET_PASSWORD": "Reset Password",
"SUCCESS": "Our Oompa Loompas saved your new password.<br /> Try to <strong>sign in</strong> with it."
},
"FORGOT_PASSWORD_FORM": {
"TITLE": "Oops, did you forget your password?",
"SUBTITLE": "Enter your username or email to get a new one",
"PLACEHOLDER_FIELD": "Username or email",
"ACTION_RESET_PASSWORD": "Reset Password",
"LINK_CANCEL": "Nah, take me back. I think I remember it.",
"SUCCESS": "<strong>Check your inbox!</strong><br />We have sent a mail to<br /><strong>{{email}}</strong><br />with the instructions to set a new password",
"ERROR": "According to our Oompa Loompas, your are not registered yet."
},
"LOGIN_COMMON": {
"HEADER": "I already have a Taiga login",
"PLACEHOLDER_AUTH_NAME": "Username or email (case sensitive)",
"LINK_FORGOT_PASSWORD": "Forgot it?",
"TITLE_LINK_FORGOT_PASSWORD": "Did you forgot your password?",
"ACTION_ENTER": "Enter",
"ACTION_SIGN_IN": "Sign in",
"PLACEHOLDER_AUTH_PASSWORD": "Password (case sensitive)"
},
"LOGIN_FORM": {
"ERROR_AUTH_INCORRECT": "According to our Oompa Loompas, your username/email or password are incorrect.",
"ERROR_GENERIC": "According to our Oompa Loompas there was an error.",
"SUCCESS": "Our Oompa Loompas are happy, welcome to Taiga."
},
"INVITATION_LOGIN_FORM": {
"NOT_FOUND": "<strong>Ooops, we have a problem</strong><br />Our Oompa Loompas can't find your invitation.",
"SUCCESS": "You've successfully joined this project, Welcome to {{project_name}",
"ERROR": "According to our Oompa Loompas, your are not registered yet or typed an invalid password."
},
"REGISTER_FORM": {
"PLACEHOLDER_NAME": "Pick a username (case sensitive)",
"PLACEHOLDER_FULL_NAME": "Pick your full name",
"PLACEHOLDER_EMAIL": "Your email",
"PLACEHOLDER_PASSWORD": "Set a password (case sensitive)",
"ACTION_SIGN_UP": "Sign up",
"TITLE_LINK_LOGIN": "Log in",
"LINK_LOGIN": "Are you already registered? Log in"
},
"ISSUES": {
"SECTION_NAME": "Issue Details",
"ACTION_NEW_ISSUE": "+ NEW ISSUE",
"ACTION_PROMOTE_TO_US": "Promote to User Story",
"PLACEHOLDER_FILTER_NAME": "Write the filter name and press enter",
"PROMOTED": "This issue has been promoted to US:",
"EXTERNAL_REFERENCE": "This issue has been created from",
"GO_TO_EXTERNAL_REFERENCE": "Go to origin",
"BLOCKED": "This issue is blocked",
"TITLE_PREVIOUS_ISSUE": "previous issue",
"TITLE_NEXT_ISSUE": "next issue",
"ACTION_DELETE": "Delete issue",
"LIGHTBOX_TITLE_BLOKING_ISSUE": "Blocking issue",
"FIELDS": {
"PRIORITY": "priority",
"SEVERITY": "severity",
"TYPE": "type"
},
"CONFIRM_PROMOTE": {
"TITLE": "Promote this issue to a new user story",
"MESSAGE": "Are you sure you want to create a new US from this Issue?"
},
"FILTERS": {
"ACTION_SAVE_CUSTOM_FILTER": "save as custom filter",
"CONFIRM_DELETE": {
"TITLE": "Delete custom filter",
"MESSAGE": "the custom filter '{{customFilterName}}'"
},
"FILTER_CATEGORY_TYPE": "Type",
"FILTER_CATEGORY_STATUS": "Status",
"FILTER_CATEGORY_SEVERITY": "Severity",
"FILTER_CATEGORY_PRIORITIES": "Priorities",
"FILTER_CATEGORY_TAGS": "Tags",
"FILTER_CATEGORY_ASSIGNED_TO": "Assigned to",
"FILTER_CATEGORY_CREATED_BY": "Created by",
"CUSTOM_FILTERS": "Custom filters"
},
"TABLE": {
"COLUMN_CREATED": "Created",
"TITLE_ACTION_CHANGE_STATUS": "Change status",
"EMPTY": {
"TITLE": "There are no issues to report :-)",
"SUBTITLE": "Did you find an issue?",
"ACTION_CREATE_ISSUE": "Create a new Issue"
}
}
},
"KANBAN": {
"TITLE_ACTION_FOLD": "Fold column",
"TITLE_ACTION_UNFOLD": "Unfold column",
"TITLE_ACTION_FOLD_CARDS": "Fold cards",
"TITLE_ACTION_UNFOLD_CARDS": "Unfold cards",
"TITLE_ACTION_ADD_US": "Add New User Story",
"TITLE_ACTION_ADD_BULK": "Add New bulk",
"ACTION_SHOW_ARCHIVED": "Show archived",
"ACTION_HIDE_ARCHIVED": "Hide archived",
"HIDDEN_USER_STORIES": "The user stories in this status are hidden by default",
"ARCHIVED": "You have archived",
"UNDO_ARCHIVED": "Drag & drop again to undo"
},
"SEARCH": {
"FILTER_USER_STORIES": "User Stories",
"FILTER_ISSUES": "Issues",
"FILTER_TASKS": "Tasks",
"FILTER_WIKI": "Wiki Pages",
"PLACEHOLDER_SEARCH": "Search in...",
"TITLE_ACTION_SEARCH": "search",
"EMPTY_TITLE": "It looks like nothing was found with your search criteria.",
"EMPTY_DESCRIPTION": "Maybe try one of the tabs above or search again"
},
"TEAM": {
"SECTION_NAME": "Team",
"APP_TITLE": "TEAM - {{projectName}}",
"PLACEHOLDER_INPUT_SEARCH": "Search by username or role...",
"COLUMN_MR_WOLF": "Mr. Wolf",
"EXPLANATION_COLUMN_MR_WOLF": "Closed issues",
"COLUMN_IOCAINE": "Iocaine Drinker",
"EXPLANATION_COLUMN_IOCAINE": "Iocaine doses ingested",
"COLUMN_CERVANTES": "Cervantes",
"EXPLANATION_COLUMN_CERVANTES": "Wiki pages edited",
"COLUMN_BUG_HUNTER": "Total Bug Hunter",
"EXPLANATION_COLUMN_BUG_HUNTER": "Bugs reported",
"COLUMN_NIGHT_SHIFT": "Night Shift",
"EXPLANATION_COLUMN_NIGHT_SHIFT": "Tasks closed",
"COLUMN_TOTAL_POWER": "Total Power",
"EXPLANATION_COLUMN_TOTAL_POWER": "Total Points",
"SECTION_TITLE_TEAM": "Team >",
"SECTION_FILTER_ALL": "All",
"CONFIRM_LEAVE_PROJECT": "Are you sure you want to leave the project?",
"ACTION_LEAVE_PROJECT": "Leave this project"
},
"CHANGE_PASSWORD": {
"SECTION_NAME": "Change password",
"FIELD_CURRENT_PASSWORD": "Current Password",
"PLACEHOLDER_CURRENT_PASSWORD": "Your current password (or empty if you have no password yet)",
"FIELD_NEW_PASSWORD": "New Password",
"FIELD_RETYPE_PASSWORD": "Retype Password",
"ERROR_PASSWORD_MATCH": "The passwords doesn't match"
},
"USER_SETTINGS": {
"AVATAR_MAX_SIZE": "[Max, size: {{maxFileSize}}}",
"MENU": {
"SECTION_TITLE": "User Settings",
"USER_PROFILE": "User profile",
"CHANGE_PASSWORD": "Change password",
"EMAIL_NOTIFICATIONS": "Email notifications"
},
"NOTIFICATIONS": {
"SECTION_NAME": "Email Notifications",
"COLUMN_PROJECT": "Project",
"COLUMN_RECEIVE_ALL": "Receive All",
"COLUMN_ONLY_INVOLVED": "Only Involved",
"COLUMN_NO_NOTIFICATIONS": "No notifications"
},
"POPOVER": {
"USER_PROFILE": "User Profile",
"CHANGE_PASSWORD": "Change Password",
"NOTIFICATIONS": "Notifications",
"FEEDBACK": "Feedback",
"TITLE_AVATAR": "User preferences"
}
},
"USER_PROFILE": {
"IMAGE_HELP": "The image will be cropped to 80x80px.<br>",
"ACTION_CHANGE_IMAGE": "Change",
"ACTION_USE_GRAVATAR": "Use gravatar image",
"ACTION_DELETE_ACCOUNT": "Delete Taiga account",
"CHANGE_EMAIL_SUCCESS": "<strong>Check your inbox!</strong><br />We have sent a mail to your account<br />with the instructions to set your new address",
"CHANGE_PHOTO": "Change photo",
"FIELD": {
"USERNAME": "Username",
"EMAIL": "Email",
"FULL_NAME": "Full name",
"PLACEHOLDER_FULL_NAME": "Set your full name (ex. Íñigo Montoya)",
"BIO": "Bio",
"PLACEHOLDER_BIO": "Tell us something about you",
"LANGUAGE": "Language"
}
},
"WIZARD": {
"SECTION_TITLE_CHOOSE_TEMPLATE": "Choose a template",
"CHOOSE_TEMPLATE_TEXT": "Which template would fit better in your project?",
"SECTION_TITLE_CREATE_PROJECT": "Create Project",
"CREATE_PROJECT_TEXT": "Fresh and clean. So exciting!",
"PROGRESS_TEMPLATE_SELECTION": "Template selection",
"PROGRESS_NAME_DESCRIPTION": "Name and description"
},
"WIKI": {
"PLACEHOLDER_PAGE": "Write your wiki page",
"REMOVE": "Remove this wiki page",
"DELETE_LIGHTBOX_TITLE": "Delete Wiki Page",
"NAVIGATION": {
"SECTION_NAME": "Links",
"ACTION_ADD_LINK": "Add link"
},
"SUMMARY": {
"TIMES_EDITED": "times <br />edited",
"LAST_EDIT": "last <br />edit",
"LAST_MODIFICATION": "last modification"
}
},
"LANGUAGES": {
"ENGLISH": "English"
}
}

View File

@ -2,7 +2,7 @@ ul.paginator
<% if (showPrevious) { %>
li.previous
a(href="", class="previous next_prev_button", class="disabled")
span(i18next="pagination.prev") Prev
span(translate="PAGINATION.PREVIOUS")
<% } %>
<% _.each(pages, function(item) { %>
@ -19,5 +19,5 @@ ul.paginator
<% if (showNext) { %>
li.next
a(href="", class="next next_prev_button", class="disabled")
span(i18next="pagination.next") Next
span(translate="PAGINATION.NEXT")
<% } %>

View File

@ -1,5 +1,5 @@
.check
input(type="checkbox", id!="<%- inputId %>")
div
span.check-text.check-yes Yes
span.check-text.check-no No
span.check-text.check-yes(translate="COMMON.YES")
span.check-text.check-no(translate="COMMON.NO")

View File

@ -1,5 +1,7 @@
doctype html
div.wrapper.memberships(ng-controller="MembershipsController as ctrl",
ng-init="section='admin'", tg-memberships)
ng-init="section='admin'; sectionName='ADMIN.MEMBERSHIPS.TITLE'", tg-memberships)
sidebar.menu-secondary.sidebar(tg-admin-navigation="memberships")
include ../includes/modules/admin-menu
@ -9,8 +11,9 @@ div.wrapper.memberships(ng-controller="MembershipsController as ctrl",
include ../includes/components/mainTitle
.action-buttons
a.button-green(title="Add new member" href="" ng-click="ctrl.addNewMembers()")
span.text + New member
a.button-green(href="", title="{{ ADMIN.MEMBERSHIPS.ADD_BUTTON_TITLE | translate }}",
ng-click="ctrl.addNewMembers()")
span.text(translate="ADMIN.MEMBERSHIPS.ADD_BUTTON")
include ../includes/modules/admin/admin-membership-table

View File

@ -1,5 +1,7 @@
doctype html
div.wrapper(tg-project-default-values, ng-controller="ProjectProfileController as ctrl",
ng-init="section='admin'; sectionName='Default values'")
ng-init="section='admin'; sectionName='ADMIN.PROJECT_DEFAULT_VALUES.TITLE'")
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-profile")
include ../includes/modules/admin-menu
@ -9,7 +11,6 @@ div.wrapper(tg-project-default-values, ng-controller="ProjectProfileController a
section.main.admin-common
header
include ../includes/components/mainTitle
p.total Default Values
p.admin-subtitle(translate="ADMIN.PROJECT_DEFAULT_VALUES.SUBTITLE")
include ../includes/modules/admin/default-values

View File

@ -1,5 +1,8 @@
doctype html
div.wrapper(ng-controller="ProjectProfileController as ctrl",
ng-init="section='admin'; sectionName='Export'")
ng-init="section='admin'; sectionName='ADMIN.PROJECT_EXPORT.TITLE'")
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-profile")
include ../includes/modules/admin-menu
@ -9,18 +12,18 @@ div.wrapper(ng-controller="ProjectProfileController as ctrl",
section.main.admin-common(tg-project-export)
header
include ../includes/components/mainTitle
p.admin-subtitle Export your project to save a backup or to create a new one based on this.
p.admin-subtitle(translate="ADMIN.PROJECT_EXPORT.SUBTITLE")
div.admin-project-export-buttons
a.button-green.button-export(href="", title="Export your project")
span Export
a.button-green.button-export(href="", title="{{ 'ADMIN.PROJECT_EXPORT.EXPORT_BUTTON_TITLE' | translate }}")
span(translate="ADMIN.PROJECT_EXPORT.EXPORT_BUTTON")
div.admin-project-export-result.hidden
div.spin.hidden
img(src="/svg/spinner-circle.svg", alt="loading...")
img(src="/svg/spinner-circle.svg", alt="{{ 'COMMON.LOADING' | translate }}")
h3.result-title
p.result-message
a.help-button(href="https://taiga.io/support/import-export-projects/", target="_blank")
span.icon.icon-help
span Do you need help? Check out our support page!
span(translate="ADMIN.HELP")

View File

@ -1,5 +1,7 @@
doctype html
div.wrapper(tg-project-modules, ng-controller="ProjectProfileController as ctrl",
ng-init="section='admin'; sectionName='Modules'")
ng-init="section='admin'; sectionName='ADMIN.MODULES.TITLE'")
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-profile")
include ../includes/modules/admin-menu
@ -15,76 +17,76 @@ div.wrapper(tg-project-modules, ng-controller="ProjectProfileController as ctrl"
div.icon.icon-backlog
div.desc
p
span Backlog
| Manage your user stories to maintain an organized view of upcoming and prioritized work.
span.title(translate="ADMIN.MODULES.BACKLOG")
span(translate="ADMIN.MODULES.BACKLOG_DESCRIPTION")
div.activate
input.activate-input(type="checkbox", id="functionality-backlog",
ng-model="project.is_backlog_activated")
label.button.button-gray(ng-switch="project.is_backlog_activated",
for="functionality-backlog")
span(ng-switch-when="true") Disable
span(ng-switch-when="false") Enable
span(ng-switch-when="true", translate="ADMIN.MODULES.DISABLE")
span(ng-switch-when="false", translate="ADMIN.MODULES.ENABLE")
div.functionality(ng-class="{true:'active', false:''}[project.is_kanban_activated]")
div.icon.icon-kanban
div.desc
p
span Kanban
| Organize your project in a lean way with this board.
span.title(translate="ADMIN.MODULES.KANBAN")
span(translate="ADMIN.MODULES.KANBAN_DESCRIPTION")
div.activate
input.activate-input(type="checkbox", id="functionality-kanban",
ng-model="project.is_kanban_activated")
label.button.button-gray(ng-switch="project.is_kanban_activated",
for="functionality-kanban")
span(ng-switch-when="true") Disable
span(ng-switch-when="false") Enable
span(ng-switch-when="true", translate="ADMIN.MODULES.DISABLE")
span(ng-switch-when="false", translate="ADMIN.MODULES.ENABLE")
div.functionality(ng-class="{true:'active', false:''}[project.is_issues_activated]")
div.icon.icon-issues
div.desc
p
span Issues
| Track the bugs, questions and enhancements related to your project. Don't miss anything!
span.title(translate="COMMON.ISSUES")
span(translate="ADMIN.MODULES.ISSUES_DESCRIPTION")
div.activate
input.activate-input(type="checkbox", id="functionality-issues",
ng-model="project.is_issues_activated")
label.button.button-gray(ng-switch="project.is_issues_activated",
for="functionality-issues")
span(ng-switch-when="true") Disable
span(ng-switch-when="false") Enable
span(ng-switch-when="true", translate="ADMIN.MODULES.DISABLE")
span(ng-switch-when="false", translate="ADMIN.MODULES.ENABLE")
div.functionality(ng-class="{true:'active', false:''}[project.is_wiki_activated]")
div.icon.icon-wiki
div.desc
p
span Wiki
| Add, modify, or delete content in collaboration with others. This is the right place for your project documentation.
span.title(translate="ADMIN.MODULES.WIKI")
span(translate="ADMIN.MODULES.WIKI_DESCRIPTION")
div.activate
input.activate-input(type="checkbox", id="functionality-wiki",
ng-model="project.is_wiki_activated")
label.button.button-gray(ng-switch="project.is_wiki_activated",
for="functionality-wiki")
span(ng-switch-when="true") Disable
span(ng-switch-when="false") Enable
span(ng-switch-when="true", translate="ADMIN.MODULES.DISABLE")
span(ng-switch-when="false", translate="ADMIN.MODULES.ENABLE")
div.functionality(ng-class="{true:'active', false:''}[isVideoconferenceActivated]")
div.icon.icon-video
div.desc
p
span Meet Up
| Choose your videoconference system. Even developers need face to face contact.
span.title(translate="ADMIN.MODULES.MEETUP")
span(translate="ADMIN.MODULES.MEETUP_DESCRIPTION")
div.activate
input.activate-input(type="checkbox", id="functionality-video",
ng-model="isVideoconferenceActivated")
label.button.button-gray(ng-switch="isVideoconferenceActivated",
for="functionality-video")
span(ng-switch-when="true") Disable
span(ng-switch-when="false") Enable
span(ng-switch-when="true", translate="ADMIN.MODULES.DISABLE")
span(ng-switch-when="false", translate="ADMIN.MODULES.ENABLE")
div.videoconference-attributes.hidden
select(ng-model="project.videoconferences",
ng-options="e.id as e.name for e in [{'id':'appear-in', 'name':'AppearIn'},{'id':'talky', 'name': 'Talky'}]")
option(value="") Select a videoconference system
option(value="", translate="ADMIN.MODULES.SELECT_VIDEOCONFERENCE")
input(type="text", ng-model="project.videoconferences_salt",
placeholder="If you want you can append a salt code to the name of the chat room")
button.button-green.submit-button(type="submit", title="Save") Save
placeholder="{{'ADMIN.MODULES.SALT_CHAT_ROOM' | translate}}")
button.button-green.submit-button(type="submit", title="{{'COMMON.SAVE' | translate}}", translate="COMMON.SAVE")

View File

@ -1,5 +1,7 @@
doctype html
div.wrapper(tg-project-profile, ng-controller="ProjectProfileController as ctrl",
ng-init="section='admin'; sectionName='Project details'")
ng-init="section='admin'; sectionName='ADMIN.PROJECT_PROFILE.PROJECT_DETAILS'")
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-profile")
include ../includes/modules/admin-menu
@ -12,29 +14,29 @@ div.wrapper(tg-project-profile, ng-controller="ProjectProfileController as ctrl"
form
fieldset
label(for="project-name") Project Name
input(type="text", name="name", placeholder="Project name", id="project-name",
label(for="project-name", translate="ADMIN.PROJECT_PROFILE.PROJECT_NAME")
input(type="text", name="name", placeholder="{{'ADMIN.PROJECT_PROFILE.PROJECT_NAME' | translate}}", id="project-name",
ng-model="project.name", data-required="true", maxlength="45")
fieldset
label(for="project-slug") Project Slug
input(type="text", name="slug", placeholder="Slug", id="project-slug",
label(for="project-slug", translate="ADMIN.PROJECT_PROFILE.PROJECT_SLUG")
input(type="text", name="slug", placeholder="{{'ADMIN.PROJECT_PROFILE.PROJECT_SLUG' | translate}}", id="project-slug",
ng-model="project.slug", data-required="true")
fieldset
label(for="project-sprints") Number of sprints
input(type="number", name="total_milestones", min="0", placeholder="Number of sprints",
label(for="project-sprints", translate="ADMIN.PROJECT_PROFILE.NUMBER_SPRINTS")
input(type="number", name="total_milestones", min="0", placeholder="{{'ADMIN.PROJECT_PROFILE.NUMBER_SPRINTS' | translate}}",
id="project-sprints", ng-model="project.total_milestones", data-type="digits")
fieldset
label(for="total-story-points") Number of US points
input(type="number", name="total_story_points", min="0", placeholder="Number of US points",
label(for="total-story-points", translate="ADMIN.PROJECT_PROFILE.NUMBER_US_POINTS")
input(type="number", name="total_story_points", min="0", placeholder="{{'ADMIN.PROJECT_PROFILE.NUMBER_US_POINTS' | translate}}",
id="total-story-points", ng-model="project.total_story_points",
data-type="digits", data-required="true")
fieldset
label(for="project-description") Description
textarea(name="description", placeholder="Description", id="project-description",
label(for="project-description", translate="ADMIN.PROJECT_PROFILE.DESCRIPTION")
textarea(name="description", placeholder="{{'ADMIN.PROJECT_PROFILE.DESCRIPTION' | translate}}", id="project-description",
ng-model="project.description", data-required="true")
div
@ -42,14 +44,14 @@ div.wrapper(tg-project-profile, ng-controller="ProjectProfileController as ctrl"
div
input.privacy-project(type="radio", name="private-project", ng-model="project.is_private", ng-value="false")
label.trans-button(for="public-project")
span Public Project
span(translate="ADMIN.PROJECT_PROFILE.PUBLIC_PROJECT")
div
input.privacy-project(type="radio", name="private-project", ng-model="project.is_private", ng-value="true")
label.trans-button(for="private-project")
span Private Project
span(translate="ADMIN.PROJECT_PROFILE.PRIVATE_PROJECT")
button.button-green.submit-button(type="submit", title="Save") Save
a.delete-project(href="", title="Delete this project", ng-click="ctrl.openDeleteLightbox()") Delete this project
button.button-green.submit-button(type="submit", title="{{'COMMON.SAVE' | translate}}", translate="COMMON.SAVE")
a.delete-project(href="", title="{{'ADMIN.PROJECT_PROFILE.DELETE' | translate}}", ng-click="ctrl.openDeleteLightbox()", translate="ADMIN.PROJECT_PROFILE.DELETE")
div.lightbox.lightbox-delete-project(tg-lb-delete-project)
include ../includes/modules/lightbox-delete-project

View File

@ -1,5 +1,7 @@
doctype html
div.wrapper(ng-controller="ProjectProfileController as ctrl",
ng-init="section='admin'; sectionName='Reports'")
ng-init="section='admin'; sectionName='ADMIN.REPORTS.TITLE'")
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-profile")
include ../includes/modules/admin-menu
@ -9,24 +11,14 @@ div.wrapper(ng-controller="ProjectProfileController as ctrl",
section.main.admin-common(tg-project-export)
header
include ../includes/components/mainTitle
p.admin-subtitle Export your project data in CSV format and make your own reports.
p.admin-subtitle(translate="ADMIN.REPORTS.SUBTITLE")
p Download a CSV file or copy the generated URL and open it in your favourite text editor or spreadsheet to make your own project data reports. You will be able to visualize and analize all your data easily.
p(translate="ADMIN.REPORTS.DESCRIPTION")
- var csvType = "US";
- var controller = "CsvExporterUserstoriesController";
div.admin-attributes-section(tg-csv-us)
div.admin-attributes-section(tg-csv-task)
div.admin-attributes-section
include ../includes/modules/admin/project-csv
- var csvType = "Task";
- var controller = "CsvExporterTasksController";
div.admin-attributes-section
include ../includes/modules/admin/project-csv
- var csvType = "Issues";
- var controller = "CsvExporterIssuesController";
div.admin-attributes-section
include ../includes/modules/admin/project-csv
div(tg-csv-issue)
a.help-button(href="https://taiga.io/support/csv-reports/", target="_blank")
span.icon.icon-help
span How to use this on my own spreadsheet?
span(translate="ADMIN.REPORTS.HELP")

View File

@ -1,4 +1,7 @@
div.wrapper(ng-controller="ProjectValuesSectionController")
doctype html
div.wrapper(ng-controller="ProjectValuesSectionController",
ng-init="sectionName='ADMIN.CUSTOM_FIELDS.TITLE'")
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
include ../includes/modules/admin-menu
@ -7,25 +10,19 @@ div.wrapper(ng-controller="ProjectValuesSectionController")
section.main.admin-common.admin-attributes
include ../includes/components/mainTitle
p.admin-subtitle Specify the custom fields for your user stories, tasks and issues
p.admin-subtitle(translate="ADMIN.CUSTOM_FIELDS.SUBTITLE")
div.admin-attributes-section(tg-project-custom-attributes,
ng-controller="ProjectCustomAttributesController as ctrl",
ng-init="type='userstory';")
- var customFieldSectionTitle = "User stories custom fields"
- var customFieldButtonTitle = "Add a custom field in user stories"
ng-init="type='userstory'; customFieldSectionTitle='ADMIN.CUSTOM_FIELDS.US_DESCRIPTION'; customFieldButtonTitle='ADMIN.CUSTOM_FIELDS.US_ADD'")
include ../includes/modules/admin/admin-custom-attributes
div.admin-attributes-section(tg-project-custom-attributes,
ng-controller="ProjectCustomAttributesController as ctrl",
ng-init="type='task';")
- var customFieldSectionTitle = "Tasks custom fields"
- var customFieldButtonTitle = "Add a custom field in tasks"
ng-init="type='task'; customFieldSectionTitle='ADMIN.CUSTOM_FIELDS.TASK_DESCRIPTION'; customFieldButtonTitle='ADMIN.CUSTOM_FIELDS.TASK_ADD'")
include ../includes/modules/admin/admin-custom-attributes
div.admin-attributes-section(tg-project-custom-attributes,
ng-controller="ProjectCustomAttributesController as ctrl",
ng-init="type='issue';")
- var customFieldSectionTitle = "Issues custom fields"
- var customFieldButtonTitle = "Add a custom field in issues"
ng-init="type='issue'; customFieldSectionTitle='ADMIN.CUSTOM_FIELDS.ISSUE_DESCRIPTION'; customFieldButtonTitle='ADMIN.CUSTOM_FIELDS.ISSUE_ADD'")
include ../includes/modules/admin/admin-custom-attributes

View File

@ -1,3 +1,5 @@
doctype html
div.wrapper(ng-controller="ProjectValuesSectionController")
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
include ../includes/modules/admin-menu
@ -7,9 +9,9 @@ div.wrapper(ng-controller="ProjectValuesSectionController")
section.main.admin-common.admin-attributes
include ../includes/components/mainTitle
p.admin-subtitle Specify the points your user stories could be estimated to
p.admin-subtitle(translate="ADMIN.PROJECT_VALUES_POINTS.SUBTITLE")
div.admin-attributes-section(tg-project-values, ng-controller="ProjectValuesController as ctrl",
ng-init="section='admin'; resource='userstories'; type='points'; sectionName='Us points'",
ng-init="section='admin'; resource='userstories'; type='points'; sectionName='ADMIN.PROJECT_VALUES_POINTS.TITLE'",
type="points")
include ../includes/modules/admin/project-points

View File

@ -1,3 +1,5 @@
doctype html
div.wrapper(ng-controller="ProjectValuesSectionController")
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
include ../includes/modules/admin-menu
@ -7,9 +9,9 @@ div.wrapper(ng-controller="ProjectValuesSectionController")
section.main.admin-common.admin-attributes
include ../includes/components/mainTitle
p.admin-subtitle Specify the priorities your issues will have
p.admin-subtitle(translate="ADMIN.PROJECT_VALUES_PRIORITIES.SUBTITLE")
div.admin-attributes-section(tg-project-values, ng-controller="ProjectValuesController as ctrl",
ng-init="section='admin'; resource='issues'; type='priorities'; sectionName='Issue priorities'; objName='priority'",
ng-init="section='admin'; resource='issues'; type='priorities'; sectionName='ADMIN.PROJECT_VALUES_PRIORITIES.TITLE'; objName='priority'",
type="priorities")
include ../includes/modules/admin/project-types

View File

@ -1,3 +1,5 @@
doctype html
div.wrapper(ng-controller="ProjectValuesSectionController")
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
include ../includes/modules/admin-menu
@ -7,9 +9,9 @@ div.wrapper(ng-controller="ProjectValuesSectionController")
section.main.admin-common.admin-attributes
include ../includes/components/mainTitle
p.admin-subtitle Specify the severities your issues will have
p.admin-subtitle(translate="ADMIN.PROJECT_VALUES_SEVERITIES.SUBTITLE")
div.admin-attributes-section(tg-project-values, ng-controller="ProjectValuesController as ctrl",
ng-init="section='admin'; resource='issues'; type='severities'; sectionName='Issue severities'; objName='severity'",
ng-init="section='admin'; resource='issues'; type='severities'; sectionName='ADMIN.PROJECT_VALUES_SEVERITIES.TITLE'; objName='severity'",
type="severities")
include ../includes/modules/admin/project-types

View File

@ -1,4 +1,7 @@
div.wrapper(ng-controller="ProjectValuesSectionController")
doctype html
div.wrapper(ng-controller="ProjectValuesSectionController",
ng-init="section='admin'; sectionName='ADMIN.PROJECT_VALUES_STATUS.TITLE'")
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
include ../includes/modules/admin-menu
@ -7,19 +10,19 @@ div.wrapper(ng-controller="ProjectValuesSectionController")
section.main.admin-common.admin-attributes
include ../includes/components/mainTitle
p.admin-subtitle Specify the statuses your user stories, tasks and issues will go through
p.admin-subtitle(translate="ADMIN.PROJECT_VALUES_STATUS.SUBTITLE")
div.admin-attributes-section(tg-project-values, ng-controller="ProjectValuesController as ctrl",
ng-init="section='admin'; resource='userstories'; type='userstory-statuses'; sectionName='Us Statuses'",
type="userstory-statuses")
div.admin-attributes-section(tg-project-values, type="userstory-statuses",
ng-controller="ProjectValuesController as ctrl",
ng-init="section='admin'; resource='userstories'; type='userstory-statuses'; sectionName='ADMIN.PROJECT_VALUES_STATUS.US_TITLE'")
include ../includes/modules/admin/project-us-status
div.admin-attributes-section(tg-project-values, ng-controller="ProjectValuesController as ctrl",
ng-init="section='admin'; resource='tasks'; type='task-statuses'; sectionName='Task Statuses'",
type="task-statuses")
div.admin-attributes-section(tg-project-values, type="task-statuses",
ng-controller="ProjectValuesController as ctrl",
ng-init="section='admin'; resource='tasks'; type='task-statuses'; sectionName='ADMIN.PROJECT_VALUES_STATUS.TASK_TITLE'")
include ../includes/modules/admin/project-status
div.admin-attributes-section(tg-project-values, ng-controller="ProjectValuesController as ctrl",
ng-init="section='admin'; resource='issues'; type='issue-statuses'; sectionName='Issue Statuses'",
type="issue-statuses")
div.admin-attributes-section(tg-project-values, type="issue-statuses",
ng-controller="ProjectValuesController as ctrl",
ng-init="section='admin'; resource='issues'; type='issue-statuses'; sectionName='ADMIN.PROJECT_VALUES_STATUS.ISSUE_TITLE'")
include ../includes/modules/admin/project-status

View File

@ -1,4 +1,7 @@
div.wrapper(ng-controller="ProjectValuesSectionController")
doctype html
div.wrapper(ng-controller="ProjectValuesSectionController"
ng-init="sectionName='ADMIN.PROJECT_VALUES_TYPES.TITLE'")
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
include ../includes/modules/admin-menu
@ -7,9 +10,9 @@ div.wrapper(ng-controller="ProjectValuesSectionController")
section.main.admin-common.admin-attributes
include ../includes/components/mainTitle
p.admin-subtitle Specify the types your user stories could be estimated to
p.admin-subtitle(translate="ADMIN.PROJECT_VALUES_TYPES.SUBTITLE")
div.admin-attributes-section(tg-project-values, ng-controller="ProjectValuesController as ctrl",
ng-init="section='admin'; resource='issues'; type='issue-types'; sectionName='Issue types'; objName='type'",
ng-init="section='admin'; resource='issues'; sectionName='ADMIN.PROJECT_VALUES_TYPES.ISSUE_TITLE'; type='issue-types'; objName='type'",
type="issue-types")
include ../includes/modules/admin/project-types

View File

@ -1,3 +1,5 @@
doctype html
div.wrapper.roles(ng-controller="RolesController as ctrl",
ng-init="section='admin'", tg-roles)
sidebar.menu-secondary.sidebar(tg-admin-navigation="roles")
@ -9,29 +11,28 @@ div.wrapper.roles(ng-controller="RolesController as ctrl",
.header-with-actions
include ../includes/components/mainTitle
.action-buttons(ng-if="!role.external_user")
a.button-red.delete-role(href="", title="Delete", ng-click="ctrl.delete()")
span Delete
a.button-red.delete-role(href="", title="{{'COMMON.DELETE' | translate}}", ng-click="ctrl.delete()")
span(translate="COMMON.DELETE")
div(ng-if="!role.external_user")
div(tg-edit-role)
.edit-role
input(type="text", value="{{ role.name }}")
a.save.icon.icon-floppy(href="", title="Save")
a.save.icon.icon-floppy(href="", title="{{'COMMON.SAVE' | translate}}")
p.total
span.role-name(title="{{ role.members_count }} members with this role") {{ role.name }}
span.role-name(title="{{'ADMIN.ROLES.COUNT_MEMBERS' | translate}}") {{ role.name }}
a.edit-value.icon.icon-edit
div.any-computable-role(ng-hide="anyComputableRole") Be careful, no role in your project will be able to estimate the point value for user stories
div.any-computable-role(ng-hide="anyComputableRole", translate="ADMIN.ROLES.WARNING_NO_ROLE")
div.general-category
| When enabled, members assigned to this role will be able to estimate the point value for user stories
div.general-category(translate="ADMIN.ROLES.HELP_ROLE_ENABLED")
div.check
input(type="checkbox", ng-model="role.computable", ng-change="ctrl.setComputable()")
div
span.check-text.check-yes Yes
span.check-text.check-no No
span.check-text.check-yes(translate="COMMON.YES")
span.check-text.check-no(translate="COMMON.NO")
div(ng-if="role.external_user")
p.total

View File

@ -1,3 +1,5 @@
doctype html
div.wrapper.roles(tg-bitbucket-webhooks, ng-controller="BitbucketController as ctrl",
ng-init="section='admin'")
sidebar.menu-secondary.sidebar(tg-admin-navigation="third-parties")
@ -10,25 +12,25 @@ div.wrapper.roles(tg-bitbucket-webhooks, ng-controller="BitbucketController as c
form
fieldset
label(for="secret-key") Secret key
input(type="text", name="secret-key", ng-model="bitbucket.secret", placeholder="Secret key", id="secret-key")
label(for="secret-key", translate="ADMIN.THIRD_PARTIES.SECRET_KEY")
input(type="text", name="secret-key", ng-model="bitbucket.secret", placeholder="{{'ADMIN.THIRD_PARTIES.SECRET_KEY' | translate}}", id="secret-key")
fieldset
.select-input-text(tg-select-input-text)
div
label(for="payload-url") Payload URL
label(for="payload-url", translate="ADMIN.THIRD_PARTIES.PAYLOAD_URL")
.field-with-option
input(type="text", ng-model="bitbucket.webhooks_url", name="payload-url", readonly="readonly", placeholder="Payload URL", id="payload-url")
input(type="text", ng-model="bitbucket.webhooks_url", name="payload-url", readonly="readonly", placeholder="{{'ADMIN.THIRD_PARTIES.PAYLOAD_URL' | translate}}", id="payload-url")
.option-wrapper.select-input-content
.icon.icon-copy
.help-copy Copy to clipboard: Ctrl+C
.help-copy(translate="COMMON.COPY_TO_CLIPBOARD")
fieldset
label(for="valid-origin-ips") Valid origin ips (separated by ,)
input(type="text", name="valid-origin-ips", tg-valid-origin-ips, ng-model="bitbucket.valid_origin_ips", placeholder="Bitbucket requests are not signed so the best way of verifying the origin is by IP. If the field is empty there will be no IP validation.", id="valid-origin-ips")
label(for="valid-origin-ips", translate="ADMIN.THIRD_PARTIES.VALID_IPS")
input(type="text", name="valid-origin-ips", tg-valid-origin-ips, ng-model="bitbucket.valid_origin_ips", placeholder="{{'ADMIN.BITBUCKET.INFO_VERIFYING_IP' | translate}}", id="valid-origin-ips")
button.button-green.submit-button(type="submit", title="Save") Save
button.button-green.submit-button(type="submit", title="{{'COMMON.SAVE' | translate}}", translate="COMMON.SAVE")
a.help-button(href="https://taiga.io/support/bitbucket-integration/", target="_blank")
span.icon.icon-help
span Do you need help? Check out our support page!
span(translate="ADMIN.HELP")

View File

@ -1,3 +1,5 @@
doctype html
div.wrapper.roles(tg-github-webhooks, ng-controller="GithubController as ctrl",
ng-init="section='admin'")
sidebar.menu-secondary.sidebar(tg-admin-navigation="third-parties")
@ -10,21 +12,21 @@ div.wrapper.roles(tg-github-webhooks, ng-controller="GithubController as ctrl",
form
fieldset
label(for="secret-key") Secret key
input(type="text", name="secret-key", ng-model="github.secret", placeholder="Secret key", id="secret-key")
label(for="secret-key", translate="ADMIN.THIRD_PARTIES.SECRET_KEY")
input(type="text", name="secret-key", ng-model="github.secret", placeholder="{{'ADMIN.THIRD_PARTIES.SECRET_KEY' | translate}}", id="secret-key")
fieldset
.select-input-text(tg-select-input-text)
div
label(for="payload-url") Payload URL
label(for="payload-url", translate="ADMIN.THIRD_PARTIES.PAYLOAD_URL")
.field-with-option
input(type="text", ng-model="github.webhooks_url", name="payload-url", readonly="readonly", placeholder="Payload URL", id="payload-url")
input(type="text", ng-model="github.webhooks_url", name="payload-url", readonly="readonly", placeholder="{{'ADMIN.THIRD_PARTIES.PAYLOAD_URL' | translate}}", id="payload-url")
.option-wrapper.select-input-content
.icon.icon-copy
.help-copy Copy to clipboard: Ctrl+C
.help-copy(translate="COMMON.COPY_TO_CLIPBOARD")
button.button-green.submit-button(type="submit", title="Save") Save
button.button-green.submit-button(type="submit", title="{{'COMMON.SAVE' | translate}}")
a.help-button(href="https://taiga.io/support/github-integration/", target="_blank")
span.icon.icon-help
span Do you need help? Check out our support page!
span(translate="ADMIN.HELP")

View File

@ -1,8 +1,6 @@
block head
title Taiga Your agile, free, and open source project management tool
doctype html
block content
div.wrapper.roles(tg-gitlab-webhooks, ng-controller="GitlabController as ctrl",
div.wrapper.roles(tg-gitlab-webhooks, ng-controller="GitlabController as ctrl",
ng-init="section='admin'")
sidebar.menu-secondary.sidebar(tg-admin-navigation="third-parties")
include ../includes/modules/admin-menu
@ -14,25 +12,25 @@ block content
form
fieldset
label(for="secret-key") Secret key
input(type="text", name="secret-key", ng-model="gitlab.secret", placeholder="Secret key", id="secret-key")
label(for="secret-key", translate="ADMIN.THIRD_PARTIES.SECRET_KEY")
input(type="text", name="secret-key", ng-model="gitlab.secret", placeholder="{{'ADMIN.THIRD_PARTIES.SECRET_KEY' | translate}}", id="secret-key")
fieldset
.select-input-text(tg-select-input-text)
div
label(for="payload-url") Payload URL
label(for="payload-url", translate="ADMIN.THIRD_PARTIES.PAYLOAD_URL")
.field-with-option
input(type="text", ng-model="gitlab.webhooks_url", name="payload-url", readonly="readonly", placeholder="Payload URL", id="payload-url")
input(type="text", ng-model="gitlab.webhooks_url", name="payload-url", readonly="readonly", placeholder="{{'ADMIN.THIRD_PARTIES.PAYLOAD_URL' | translate}}", id="payload-url")
.option-wrapper.select-input-content
.icon.icon-copy
.help-copy Copy to clipboard: Ctrl+C
.help-copy(translate="COMMON.COPY_TO_CLIPBOARD")
fieldset
label(for="valid-origin-ips") Valid origin ips (separated by ,)
input(type="text", name="valid-origin-ips", tg-valid-origin-ips, ng-model="gitlab.valid_origin_ips", placeholder="Gitlab requests are not signed so the best way of verifying the origin is by IP. If the field is empty there will be no IP validation.", id="valid-origin-ips")
label(for="valid-origin-ips", translate="ADMIN.THIRD_PARTIES.VALID_IPS")
input(type="text", name="valid-origin-ips", tg-valid-origin-ips, ng-model="gitlab.valid_origin_ips", placeholder="{{'ADMIN.GITLAB.INFO_VERIFYING_IP' | translate}}", id="valid-origin-ips")
button.button-green.submit-button(type="submit", title="Save") Save
button.button-green.submit-button(type="submit", title="{{'COMMON.SAVE' | translate}}", translate="COMMON.SAVE")
a.help-button(href="https://taiga.io/support/gitlab-integration/", target="_blank")
span.icon.icon-help
span Do you need help? Check out our support page!
span(translate="ADMIN.HELP")

View File

@ -1,8 +1,6 @@
block head
title Taiga Your agile, free, and open source project management tool
doctype html
block content
div.wrapper.roles(ng-controller="WebhooksController as ctrl",
div.wrapper.roles(ng-controller="WebhooksController as ctrl",
ng-init="section='admin'")
sidebar.menu-secondary.sidebar(tg-admin-navigation="third-parties")
include ../includes/modules/admin-menu
@ -12,31 +10,31 @@ block content
section.main.admin-common.admin-webhooks(tg-new-webhook)
include ../includes/components/mainTitle
p.admin-subtitle Webhooks notify external services about events in Taiga, like comments, user stories....
p.admin-subtitle(translate="ADMIN.WEBHOOKS.SUBTITLE")
div.webhooks-options
a.button-green.hidden.add-webhook(href="",title="Add a New Webhook") Add Webhook
a.button-green.hidden.add-webhook(href="", title="{{'ADMIN.WEBHOOKS.ADD_NEW' | translate}}", translate="ADMIN.WEBHOOKS.ADD_NEW")
section.webhooks-table.basic-table
div.table-header
div.row
div.webhook-service Name
div.webhook-url URL
div.webhook-service(translate="COMMON.FIELDS.NAME")
div.webhook-url(translate="COMMON.FIELDS.URL")
div.webhook-options
div.table-body
div.single-webhook-wrapper(tg-webhook="webhook", ng-repeat="webhook in webhooks")
div.edition-mode.hidden
form.row
fieldset.webhook-service
input(type="text", name="name", placeholder="Type the service name", data-required="true", ng-model="webhook.name")
input(type="text", name="name", placeholder="{{'ADMIN.WEBHOOKS.TYPE_NAME' | translate}}", data-required="true", ng-model="webhook.name")
div.webhook-url
div.webhook-url-inputs
fieldset
input(type="text", name="url", data-type="url", placeholder="Type the service payload url", data-required="true", ng-model="webhook.url")
input(type="text", name="url", data-type="url", placeholder="{{'ADMIN.WEBHOOKS.TYPE_PAYLOAD_URL' | translate}}", data-required="true", ng-model="webhook.url")
fieldset
input(type="text", name="key", placeholder="Type the service secret key", data-required="true", ng-model="webhook.key")
input(type="text", name="key", placeholder="{{'ADMIN.WEBHOOKS.TYPE_SERVICE_SECRET' | translate}}", data-required="true", ng-model="webhook.key")
div.webhook-options
a.edit-existing.icon.icon-floppy(href="", title="Save Webhook")
a.cancel-existing.icon.icon-delete(href="", title="Cancel Webhook")
a.edit-existing.icon.icon-floppy(href="", title="{{'ADMIN.WEBHOOKS.SAVE' | translate}}")
a.cancel-existing.icon.icon-delete(href="", title="{{'ADMIN.WEBHOOKS.CANCEL' | translate}}")
div.visualization-mode
div.row
@ -44,13 +42,13 @@ block content
span(ng-bind="webhook.name")
div.webhook-url
span(ng-bind="webhook.url")
a.show-history.toggle-history(href="", title="Toggle history", ng-show="webhook.logs_counter") (Show history)
a.show-history.toggle-history(href="", title="{{'ADMIN.WEBHOOKS.TOOGLE_HISTORY' | translate}}", ng-show="webhook.logs_counter", translate="ADMIN.WEBHOOKS.SHOW_HISTORY")
div.webhook-options
div.webhook-options-wrapper
a.test-webhook.icon.icon-check-square(href="", title="Test Webhook")
a.edit-webhook.icon.icon-edit(href="", title="Edit Webhook")
a.delete-webhook.icon.icon-delete(href="", title="Delete Webhook")
a.test-webhook.icon.icon-check-square(href="", title="{{'ADMIN.WEBHOOKS.TEST' | translate}}")
a.edit-webhook.icon.icon-edit(href="", title="{{'ADMIN.WEBHOOKS.EDIT' | translate}}")
a.delete-webhook.icon.icon-delete(href="", title="{{'ADMIN.WEBHOOKS.DELETE' | translate}}")
div.webhooks-history(ng-show="webhook.logs")
div.history-single-wrapper(ng-repeat="log in webhook.logs")
@ -62,38 +60,38 @@ block content
div.history-single-response
div.history-single-request-header
span Request
a.resend-request(href="", title="Resend request", data-log="{{log.id}}")
span(translate="ADMIN.WEBHOOKS.REQUEST")
a.resend-request(href="", title="{{'ADMIN.WEBHOOKS.RESEND_REQUEST' | translate}}", data-log="{{log.id}}")
span.icon.icon-reload
span Resend request
span(translate="ADMIN.WEBHOOKS.RESEND_REQUEST")
div.history-single-request-body
div.response-container
span.response-title Headers
span.response-title(translate="ADMIN.WEBHOOKS.HEADERS")
textarea(name="headers", ng-bind="log.prettySentHeaders")
div.response-container
span.response-title Payload
span.response-title(translate="ADMIN.WEBHOOKS.PAYLOAD")
textarea(name="payload", ng-bind="log.prettySentData")
div.history-single-response-header
span Response
span(translate="ADMIN.WEBHOOKS.RESPONSE")
div.history-single-response-body
div.response-container
textarea(name="response-data", ng-bind="log.response_data")
form.new-webhook-form.row.hidden
fieldset.webhook-service
input(type="text", name="name", placeholder="Type the service name", data-required="true", ng-model="newValue.name")
input(type="text", name="name", placeholder="{{'ADMIN.WEBHOOKS.TYPE_NAME' | translate}}", data-required="true", ng-model="newValue.name")
div.webhook-url
div.webhook-url-inputs
fieldset
input(type="text", name="url", data-type="url", placeholder="Type the service payload url", data-required="true", ng-model="newValue.url")
input(type="text", name="url", data-type="url", placeholder="{{'ADMIN.WEBHOOKS.TYPE_PAYLOAD_URL' | translate}}", data-required="true", ng-model="newValue.url")
fieldset
input(type="text", name="key", placeholder="Type the service secret key", data-required="true", ng-model="newValue.key")
input(type="text", name="key", placeholder="{{'ADMIN.WEBHOOKS.TYPE_SERVICE_SECRET' | translate}}", data-required="true", ng-model="newValue.key")
div.webhook-options
a.add-new.icon.icon-floppy(href="", title="Save Webhook")
a.cancel-new.icon.icon-delete(href="", title="Cancel Webhook")
a.add-new.icon.icon-floppy(href="", title="{{'ADMIN.WEBHOOKS.SAVE' | translate}}")
a.cancel-new.icon.icon-delete(href="", title="{{'ADMIN.WEBHOOKS.CANCEL' | translate}}")
a.help-button(href="https://taiga.io/support/webhooks/", target="_blank")
span.icon.icon-help
span Do you need help? Check out our support page!
span(translate="ADMIN.HELP")

View File

@ -0,0 +1,16 @@
section.project-csv(tg-select-input-text)
div.project-values-title
h2(translate="ADMIN.CSV.TITLE", translate-values='{ csvType: csvType}')
a.button.button-gray(title="{{'ADMIN.CSV.DOWNLOAD' | translate}}", ng-href="{{csvUrl}}", ng-show="csvUrl", target="_blank")
span(translate="ADMIN.CSV.DOWNLOAD")
div.csv-regenerate-field
.field-with-options
input(type="text", placeholder="{{'ADMIN.CSV.URL_FIELD_PLACEHOLDER' | translate}}", readonly, ng-model="csvUrl")
.option-wrapper.select-input-content
.icon.icon-copy
a(href="", title="{{'ADMIN.CSV.TITLE_REGENERATE_URL' | translate}}", ng-click="ctrl.regenerateUuid()")
span.icon.icon-plus(ng-hide="csvUrl")
span(ng-hide="csvUrl", translate="ADMIN.CSV.ACTION_GENERATE_URL")
span.icon.icon-reload(ng-Show="csvUrl")
span(ng-Show="csvUrl", translate="ADMIN.CSV.ACTION_REGENERATE")

View File

@ -1,19 +1,19 @@
.attachment-name
span.icon.icon-document
a(href!="<%- url %>", title!="<%- name %> uploaded on <%- created_date %>", target="_blank")
a(href!="<%- url %>", title!="{{ 'ATTACHMENT.TITLE' | translate}}", target="_blank")
| <%- name %>
.attachment-size
span <%- size %>
.editable.editable-attachment-comment
input(type="text", name="description", maxlength="140",
value!="<%- description %>", placeholder="Type a short description")
value!="<%- description %>", placeholder="{{'ATTACHMENT.DESCRIPTION' | translate}}")
.editable.editable-attachment-deprecated
input(type="checkbox", name="is-deprecated",
id!="attach-<%- id %>-is-deprecated")
label(for!="attach-<%- id %>-is-deprecated") Deprecated?
label(for!="attach-<%- id %>-is-deprecated", translate="{{'ATTACHMENT.DEPRECATED_FILE' | translate}}")
.attachment-settings
a.editable-settings.icon.icon-floppy(href="", title="Save")
a.editable-settings.icon.icon-delete(href="", title="Cancel")
a.editable-settings.icon.icon-floppy(href="", title="{{'COMMON.SAVE' | translate}}")
a.editable-settings.icon.icon-delete(href="", title="{{'COMMON.CANCEL' | translate}}")

View File

@ -1,5 +1,5 @@
.attachment-name
a(href!="<%- url %>", title!="<%- name %> uploaded on <%- created_date %>", target="_blank")
a(href!="<%- url %>", title!="{{ 'ATTACHMENT.TITLE' | translate}}", target="_blank")
span.icon.icon-documents
span <%- name %>
.attachment-size
@ -7,13 +7,13 @@
.attachment-comments
<% if (isDeprecated){ %>
span.deprecated-file (deprecated)
span.deprecated-file {{ 'ATTACHMENT.DEPRECATED' | translate}}
<% } %>
span <%- description %>
<% if (modifyPermission) {%>
.attachment-settings
a.settings.icon.icon-edit(href="", title="Edit")
a.settings.icon.icon-delete(href="", title="Delete")
a.settings.icon.icon-drag-v(href="", title="Drag")
a.settings.icon.icon-edit(href="", title="{{'COMMON.EDIT' | translate}}")
a.settings.icon.icon-delete(href="", title="{{'COMMON.DELETE' | translate}}")
a.settings.icon.icon-drag-v(href="", title="{{'COMMON.DRAG' | translate}}")
<% } %>

View File

@ -2,10 +2,10 @@ section.attachments
.attachments-header
h3.attachments-title
span.attachments-num(tg-bind-html="ctrl.attachmentsCount")
span.attachments-text attachments
.add-attach(tg-check-permission!="modify_<%- type %>", title!="Add new attachment. <%- maxFileSizeMsg %>")
span.attachments-text(translate="ATTACHMENT.SECTION_NAME")
.add-attach(tg-check-permission!="modify_<%- type %>", title!="{{'ATTACHMENT.ADD' | translate}}")
<% if (maxFileSize){ %>
span.size-info.hidden [Max. size: <%- maxFileSize %>]
span.size-info.hidden(translate="ATTACHMENT.MAX_FILE_SIZE", translate-values!="{ 'maxFileSize': '<%- maxFileSize %>'}")
<% }; %>
label(for="add-attach", class="icon icon-plus related-tasks-buttons")
input(id="add-attach", type="file", multiple="multiple")
@ -22,9 +22,7 @@ section.attachments
span(ng-bind="file.progressMessage")
.percentage(ng-style="{'width': file.progressPercent}")
a.more-attachments(href="", title="show deprecated atachments", ng-if="ctrl.deprecatedAttachmentsCount > 0")
span.text(data-type="show") + show deprecated atachments
span.text.hidden(data-type="hide")
| - hide deprecated atachments
span.more-attachments-num
| ({{ctrl.deprecatedAttachmentsCount }} deprecated)
a.more-attachments(href="", title="{{'ATTACHMENT.SHOW_DEPRECATED' | translate}}", ng-if="ctrl.deprecatedAttachmentsCount > 0")
span.text(data-type="show", translate="ATTACHMENT.SHOW_DEPRECATED")
span.text.hidden(data-type="hide", translate="ATTACHMENT.HIDE_DEPRECATED")
span.more-attachments-num(translate="ATTACHMENT.COUNT_DEPRECATED")

View File

@ -1,8 +1,10 @@
doctype html
div.wrapper
div.login-main
div.login-container
h1.logo
img.logo-svg(src="/svg/logo.svg", alt="TAIGA")
p.tagline Your agile, free, and open source project management tool
p.tagline(translate="COMMON.TAG_LINE")
include ../includes/modules/change-password-from-recovery-form

View File

@ -1,9 +1,11 @@
doctype html
include ../includes/components/beta
div.wrapper
div.login-main
div.login-container
img.logo-svg(src="/svg/logo.svg", alt="TAIGA")
h1.logo Taiga
h2.tagline LOVE YOUR PROJECT
h2.tagline(translate="COMMON.TAG_LINE_2")
include ../includes/modules/forgot-form

View File

@ -1,3 +1,5 @@
doctype html
div.wrapper
div.invitation-main
div.invitation-container(tg-invitation)
@ -8,7 +10,7 @@ div.wrapper
span.person-name(tg-bo-bind="invitation.invited_by.full_name_display")
span.invitation-text
p has invited you to join the project
p(translate="AUTH.INVITED_YOU")
p.project-name(tg-bo-bind="invitation.project_name")
div.invitation-form

View File

@ -1,3 +1,3 @@
p.login-text
span Not registered yet?
a(href!='<%- url %>', tg-nav='register', title='Register') create your free account here
span(translate="AUTH.NOT_REGISTERED_YET")
a(href!='<%- url %>', tg-nav='register', title='{{"AUTH.REGISTER" | translate}}', translate="AUTH.CREATE_ACCOUNT")

View File

@ -1,9 +1,11 @@
doctype html
include ../includes/components/beta
div.wrapper
div.login-main
div.login-container
img.logo-svg(src="/svg/logo.svg", alt="TAIGA")
h1.logo Taiga
h2.tagline LOVE YOUR PROJECT
h2.tagline(translate="COMMON.TAG_LINE_2")
include ../includes/modules/login-form

View File

@ -1,8 +1,10 @@
doctype html
div.wrapper
div.login-main
div.login-container
img.logo-svg(src="/svg/logo.svg", alt="TAIGA")
h1.logo Taiga
h2.tagline LOVE YOUR PROJECT
h2.tagline(translate="COMMON.TAG_LINE_2")
include ../includes/modules/register-form

View File

@ -1,5 +1,8 @@
doctype html
div.wrapper(tg-backlog, ng-controller="BacklogController as ctrl",
ng-init="section='backlog'")
sidebar.menu-secondary.extrabar.filters-bar(tg-backlog-filters)
include ../includes/modules/backlog-filters
section.main.backlog
@ -10,23 +13,22 @@ div.wrapper(tg-backlog, ng-controller="BacklogController as ctrl",
include ../includes/modules/burndown
div.backlog-menu
div.backlog-table-options
a.trans-button.move-to-current-sprint(href="", title="Move to Current Sprint",
id="move-to-current-sprint")
a.trans-button.move-to-current-sprint(href="", title="{{'BACKLOG.MOVE_US_TO_CURRENT_SPRINT' | translate}}", id="move-to-current-sprint")
span.icon.icon-move
span.text Move to current Sprint
a.trans-button(href="", title="Show Filters", id="show-filters-button")
span.text(translate="BACKLOG.MOVE_US_TO_CURRENT_SPRINT")
a.trans-button(href="", title="{{'BACKLOG.SHOW_FILTERS' | translate}}", id="show-filters-button")
span.icon.icon-filter
span.text Show Filters
a.trans-button(href="", title="Show Tags", id="show-tags")
span.text(translate="BACKLOG.SHOW_FILTERS") Show Filters
a.trans-button(href="", title="{{'BACKLOG.SHOW_TAGS' | translate}}", id="show-tags")
span.icon.icon-tag
span.text Show Tags
span.text(translate="BACKLOG.SHOW_TAGS")
include ../includes/components/addnewus
section.backlog-table(ng-class="{'hidden': !visibleUserstories.length}")
include ../includes/modules/backlog-table
div.empty.empty-backlog(ng-class="{'hidden': visibleUserstories.length}", tg-backlog-empty-sortable)
span.icon.icon-backlog
span.title Your backlog is empty!
a(href="", title+"Create a new US", ng-click="ctrl.addNewUs('standard')", tg-check-permission="add_us") You may want to create a new user story
span.title(translate="BACKLOG.EMPTY")
a(href="", title="{{'BACKLOG.CREATE_NEW_US' | translate}}", ng-click="ctrl.addNewUs('standard')", tg-check-permission="add_us", translate="BACKLOG.CREATE_NEW_US_EMPTY_HELP")
sidebar.menu-secondary.sidebar
include ../includes/modules/sprints

View File

@ -1,3 +1,3 @@
.defined-points(title="Excess of points")
.project-points-progress(title="Pending Points", style!="width: <%- projectPointsPercentaje %>%")
.closed-points-progress(title="Closed points", style!="width: <%- closedPointsPercentaje %>%")
.defined-points(title="{{'BACKLOG.EXCESS_OF_POINTS' | translate}}")
.project-points-progress(title="{{'BACKLOG.PENDING_POINTS' | translate}}", style!="width: <%- projectPointsPercentaje %>%")
.closed-points-progress(title="{{'BACKLOG.CLOSED_POINTS' | translate}}", style!="width: <%- closedPointsPercentaje %>%")

View File

@ -1,20 +1,16 @@
.sprint-name
a.icon.icon-arrow-up(href="", title="Compact Sprint")
<% if(isVisible){ %>
a(href!="<%- taskboardUrl %>", title!="'Go to the taskboard of '<%- name %>'")
span <%- name %>
<% } %>
a.icon.icon-arrow-up(href="", title="{{'BACKLOG.COMPACT_SPRINT' | translate}}")
a(ng-if="::isVisible", href="{{::taskboardUrl}}", title="{{'BACKLOG.GO_TO_TASKBOARD' | translate}}")
span {{::name}}
<% if(isEditable){ %>
a.icon.icon-edit(href="", title="Edit Sprint")
<% } %>
a.icon.icon-edit(ng-if="::isEditable", href="", title="{{'BACKLOG.EDIT_SPRINT' | translate}}")
.sprint-summary
.sprint-date <%- estimatedDateRange %>
.sprint-date {{::estimatedDateRange}}
ul
li
span.number <%- closedPoints %>
span.description closed
span.number {{::closedPoints}}
span.description(translate="BACKLOG.CLOSED_POINTS")
li
span.number <%- totalPoints %>
span.description total
span.number {{::totalPoints}}
span.description(translate="BACKLOG.TOTAL_POINTS")

View File

@ -1,6 +1,6 @@
ul.popover.pop-role
li
a.clear-selection(href="", title="All") All
a.clear-selection(href="", title="{{'COMMON.ROLES.ALL' | translate}}", translate="COMMON.ROLES.ALL")
<% _.each(roles, function(role) { %>
li
a(href="", class="role", title!="<%- role.name %>", data-role-id!="<%- role.id %>")

View File

@ -4,18 +4,18 @@
<% } %>
.assigned-to
span.assigned-title Assigned to
span.assigned-title(translate="COMMON.FIELDS.ASSIGNED_TO")
a(href="" title="edit assignment", class!="user-assigned <% if(isEditable){ %>editable<% }; %>")
span.assigned-name
<% if (assignedTo) { %>
<%- assignedTo.full_name_display %>
<% } else { %>
| Not assigned
| {{'COMMON.FIELDS.ASSIGNED_TO' | translate}}
<% } %>
<% if(isEditable){ %>
span.icon.icon-arrow-bottom
<% }; %>
<% if (assignedTo!==null && isEditable) { %>
a.icon.icon-delete(href="" title="delete assignment")
a.icon.icon-delete(href="" title="{{'COMMON.ASSIGNED_TO.DELETE_ASSIGNMENT' | translate}}")
<% } %>

View File

@ -1,4 +1,4 @@
a(href="#", class="button button-gray item-block")
span Block
span(translate="COMMON.BLOCK")
a(href="#", class="button button-red item-unblock")
span Unblock
span(translate="COMMON.UNBLOCK")

View File

@ -2,7 +2,6 @@
img(src!="<%- owner.photo %>", alt!="<%- owner.full_name_display %>")
.created-by
span.created-title
| Created by <%- owner.full_name_display %>
span.created-title(translate="COMMON.CREATED_BY", translate-values!="{ 'fullDisplayName': '<%- owner.full_name_display %>'}")
span.created-date
| <%- date %>

View File

@ -1,2 +1,2 @@
a(href="", class="button button-red")
span Delete
span(translate="COMMON.DELETE")

View File

@ -1,2 +1 @@
p.no-description.editable
| Empty space is so boring... go on be descriptive... A rose by any other name would smell as sweet...
p.no-description.editable(translate="COMMON.DESCRIPTION.EMPTY")

View File

@ -1 +1 @@
p.no-description No description yet.
p.no-description(translate="COMMON.NO_DESCRIPTION")

View File

@ -3,9 +3,9 @@
span.edit.icon.icon-edit
.edit-description
textarea(placeholder="Empty space is so boring... go on be descriptive... A rose by any other name would smell as sweet...", ng-model="item.description", tg-markitup="tg-markitup")
a.help-markdown(href="https://taiga.io/support/taiga-markdown-syntax/", target="_blank", title="Mardown syntax help")
textarea(placeholder="{{'COMMON.DESCRIPTION.EMPTY' | translate}}", ng-model="item.description", tg-markitup="tg-markitup")
a.help-markdown(href="https://taiga.io/support/taiga-markdown-syntax/", target="_blank", title="{{'COMMON.MARKDOWN_HELP' | translate}}")
span.icon.icon-help
span Markdown syntax help
span(translate="COMMON.MARKDOWN_HELP")
span.save-container
a.save.icon.icon-floppy(href="", title="Save")
a.save.icon.icon-floppy(href="", title="{{'COMMON.SAVE' | translate}}")

View File

@ -1,7 +1,7 @@
.view-subject
| {{ item.subject }}
a.edit.icon.icon-edit(href="" title="Edit")
a.edit.icon.icon-edit(href="" title="{{'COMMON.EDIT' | translate}}")
.edit-subject
input(type="text", ng-model="item.subject", data-required="true", data-maxlength="500")
span.save-container
a.save.icon.icon-floppy(href="", title="Save")
a.save.icon.icon-floppy(href="", title="{{'COMMON.SAVE' | translate}}")

View File

@ -1,2 +1,4 @@
span.project-name <%- projectName %>
span.green <%- sectionName %>
span.project-name
| {{ projectName }}
span.green
| {{ sectionName }}

View File

@ -1,9 +1,5 @@
span
<% if (status.is_closed) { %>
| Closed
<% } else { %>
| Open
<% } %>
span(translate="STATUS.OPEN", ng-if="status.is_closed")
span(translate="STATUS.CLOSED", ng-if="!status.is_closed")
span(class="us-detail-status", style!="color:<%- status.color %>")
| <%- status.name %>

View File

@ -1,10 +1,10 @@
<% if(isEditable){ %>
.watchers-header
span.title watchers
a.icon.icon-plus.add-watcher(href="", title="Add watcher")
span.title(translate="COMMON.WATCHERS.TITLE")
a.icon.icon-plus.add-watcher(href="", title="{{'COMMON.WATCHERS.ADD' | translate}}")
<% } else if(watchers.length > 0){ %>
.watchers-header
span.title watchers
span.title(translate="COMMON.WATCHERS.TITLE")
<% }; %>
<% _.each(watchers, function(watcher) { %>
@ -16,7 +16,7 @@
span <%- watcher.full_name_display %>
<% if(isEditable){ %>
a.icon.icon-delete(data-watcher-id!="<%- watcher.id %>" href="" title="delete-watcher")
a.icon.icon-delete(data-watcher-id!="<%- watcher.id %>" href="" title="{{'WATCHERS.DELETE' | translate}}")
<% }; %>
<% } %>
<% }); %>

View File

@ -1,7 +1,7 @@
ul.points-per-role
li.total
span.points <%- totalPoints %>
span.role total
span.role(translate="US.TOTAL_POINTS")
<% _.each(roles, function(role) { %>
li(class!="total <% if(editable){ %>clickable<% } %>", data-role-id!="<%- role.id %>", title!="<%- role.name %>")
span.points <%- role.points %>

View File

@ -12,8 +12,7 @@ div(class!="activity-single <%- mode %>")
<% if (comment.length > 0) { %>
<% if ((deleteCommentDate || deleteCommentUser)) { %>
.deleted-comment
span
| Comment deleted by <%- deleteCommentUser %> on <%- deleteCommentDate %>
span(translate="COMMENTS.DELETED_INFO", translate-values!="{ deleteCommentUser: '<%- deleteCommentUser %>', deleteCommentDate: '<% deleteCommentDate %>'}")
<% } %>
.comment.wysiwyg
| <%= comment %>
@ -25,7 +24,7 @@ div(class!="activity-single <%- mode %>")
<% if(changes.length > 0) { %>
.changes
<% if (mode != "activity") { %>
a.changes-title(href="", title="Show activity")
a.changes-title(href="", title="{{'ACTIVITY.SHOW_ACTIVITY' | translate}}")
span <%- changesText %>
span.icon.icon-arrow-up
<% } %>

View File

@ -1,6 +1,5 @@
<% if (showMore > 0) { %>
a(href="" title="Show more" class="show-more show-more-comments")
| + Show previous entries (<%- showMore %> more)
a(href="" title="{{ 'ACTIVITY.SHOW_MORE' | translate}}" class="show-more show-more-comments", translate="ACTIVITY.SHOW_MORE", translate-values!="{showMore: '<%- showMore %>'}")
<% } %>
<% _.each(entries, function(entry) { %>
<%= entry %>

View File

@ -3,21 +3,21 @@ section.history
li
a(href="#", class="active")
span.icon.icon-comment
span.tab-title Comments
span.tab-title(translate="COMMENTS.TITLE")
li
a(href="#")
span.icon.icon-issues
span.tab-title Activity
span.tab-title(translate="ACTIVITY.TITLE")
section.history-comments
.comments-list
div(tg-check-permission!="modify_<%- type %>", tg-toggle-comment, class="add-comment")
textarea(placeholder="Type a new comment here", ng-model!="<%- ngmodel %>.comment", tg-markitup="tg-markitup")
textarea(placeholder="{{'COMMENTS.TYPE_NEW_COMMENT' | translate}}", ng-model!="<%- ngmodel %>.comment", tg-markitup="tg-markitup")
<% if (mode !== "edit") { %>
a(class="help-markdown", href="https://taiga.io/support/taiga-markdown-syntax/", target="_blank", title="Mardown syntax help")
a(class="help-markdown", href="https://taiga.io/support/taiga-markdown-syntax/", target="_blank", title="{{'COMMON.DESCRIPTION.MARKDOWN_HELP' | translate}}")
span.icon.icon-help
span Markdown syntax help
a(href="", title="Comment", class="button button-green save-comment")
span Comment
span(translate="COMMON.DESCRIPTION.MARKDOWN_HELP")
a(href="", title="{{'COMMENTS.COMMENT' | translate}}", class="button button-green save-comment")
span(translate="COMMENTS.COMMENT")
<% } %>
section.history-activity.hidden
.changes-list

View File

@ -3,10 +3,10 @@
span <%- name %>
.activity-fromto
p
strong from
strong(translate="COMMON.FROM")
br
span <%- from %>
p
strong to
strong(translate="COMMON.TO")
br
span <%- to %>

View File

@ -4,14 +4,14 @@
.activity-fromto
<% if (removed.length > 0) { %>
p
strong removed
strong(translate="ACTIVITY.REMOVED")
br
span <%- removed %>
<% } %>
<% if (added.length > 0) { %>
p
strong added
strong(translate="ACTIVITY.ADDED")
br
span <%- added %>
<% } %>

View File

@ -1,14 +1,14 @@
<% _.each(points, function(point, name) { %>
.change-entry
.activity-changed
span US points (<%- name.toLowerCase() %>)
span(translate="ACTIVITY.US_POINTS", translate-values!="<%- name.toLowerCase() %>")
.activity-fromto
p
strong from
strong(translate="COMMON.FROM")
br
span <%- point[0] %>
p
strong to
strong(translate="COMMON.TO")
br
span <%- point[1] %>
<% }); %>

View File

@ -1,11 +1,11 @@
.activity-single.comment.deleted-comment
div
span Comment deleted by <%- deleteCommentUser %> on <%- deleteCommentDate %>
a(href="", title="Show comment", class="show-deleted-comment") (Show deleted comment)
a(href="", title="Show comment", class="hide-deleted-comment hidden") (Hide deleted comment)</a>
span(translate="COMMENTS.DELETED_INFO", translate-values!="{deleteCommentUser: '<%- deleteCommentUser %>', deleteCommentDate: '<%- deleteCommentDate %>'}")
a(href="", title="{{'COMMENTS.SHOW_DELETED' | translate}}", class="show-deleted-comment", translate="COMMENTS.SHOW_DELETED")
a(href="", title="{{'COMMENTS.HIDE_DELETED' | translate}}", class="hide-deleted-comment hidden", translate="COMMENTS.HIDE_DELETED")
.comment-body.wysiwyg <%= deleteComment %>
<% if (canRestoreComment) { %>
a(href="", class="comment-restore", data-activity-id!="<%- activityId %>")
span.icon.icon-reload
span Restore comment
span(translate="COMMENTS.RESTORE")
<% } %>

View File

@ -1,17 +1,17 @@
<% if (selected) { %>
.watcher-single.active
.watcher-avatar
a(href="", title="Assigned to", class="avatar")
a(href="", title="{{'COMMON.ASSIGNED_TO' | translate}}", class="avatar")
img(src!="<%- selected.photo %>")
a(href="", title!="<%- selected.full_name_display %>", class="watcher-name")
| <%-selected.full_name_display %>
a(href="", title="Remove assigned", class="icon icon-delete remove-assigned-to")
a(href="", title="{{'REMOVE_ASSIGNED' | translate}}", class="icon icon-delete remove-assigned-to")
<% } %>
<% _.each(users, function(user) { %>
.watcher-single(data-user-id!="<%- user.id %>")
.watcher-avatar
a(href="#", title="Assigned to", class="avatar")
a(href="#", title="{{'COMMON.ASSIGNED_TO.TITLE' | translate}}", class="avatar")
img(src!="<%- user.photo %>")
a(href="", title!="<%- user.full_name_display %>", class="watcher-name")
| <%- user.full_name_display %>
@ -19,5 +19,5 @@
<% if (showMore) { %>
div(ng-show="filteringUsers", class="more-watchers")
span ...too many users, keep filtering
span(translate="COMMON.ASSIGNED_TO.TOO_MANY")
<% } %>

View File

@ -1,9 +1,9 @@
a.close(href="", title="close")
span.icon.icon-delete
div.form
h2.title Select assigned to
h2.title(translate="LIGHTBOX.ASSIGNED_TO.SELECT")
fieldset
input(type="text", data-maxlength="500", placeholder="Search for users", ng-model="usersSearch")
input(type="text", data-maxlength="500", placeholder="{{'LIGHTBOX.ASSIGNED_TO.SEARCH' | translate}}", ng-model="usersSearch")
//-This block is rendered by the directive
div.watchers

View File

@ -1,9 +1,9 @@
a.close(href="", title="close")
a.close(href="", title="{{'COMMON.CLOSE' | translate}}")
span.icon.icon-delete
div.form
h2.title
fieldset
textarea.reason(placeholder="Please explain the reason")
textarea.reason(placeholder="{{'COMMON.BLOCKED_REASON' | translate}}")
a.button-green(href="")
span Save
span(translate="COMMON.SAVE")

Some files were not shown because too many files have changed in this diff Show More