Merge branch 'master' into stable
commit
f154afb5d9
|
@ -2,6 +2,7 @@
|
||||||
dist/
|
dist/
|
||||||
node_modules/
|
node_modules/
|
||||||
app/vendor
|
app/vendor
|
||||||
|
vendor/
|
||||||
config/main.coffee
|
config/main.coffee
|
||||||
bower_components
|
bower_components
|
||||||
app/coffee/modules/locales/locale*.coffee
|
app/coffee/modules/locales/locale*.coffee
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
[main]
|
||||||
|
host = https://www.transifex.com
|
||||||
|
lang_map = sr@latin:sr-latn, zh-Hans:zh-hans, zh-Hant:zh-hant
|
||||||
|
|
||||||
|
[taiga-front.locale-enjson]
|
||||||
|
file_filter = app/locales/locale-<lang>.json
|
||||||
|
source_file = app/locales/locale-en.json
|
||||||
|
source_lang = en
|
||||||
|
type = KEYVALUEJSON
|
17
CHANGELOG.md
17
CHANGELOG.md
|
@ -1,6 +1,23 @@
|
||||||
# Changelog #
|
# Changelog #
|
||||||
|
|
||||||
|
|
||||||
|
## 1.7.0 Empetrum Nigrum (unreleased)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
- Make Taiga translatable (i18n support).
|
||||||
|
- i18n.
|
||||||
|
- Add spanish (es) translation.
|
||||||
|
- Add french (fr) translation.
|
||||||
|
- Add finish (fi) translation.
|
||||||
|
- Add catalan (ca) translation.
|
||||||
|
- Add traditional chinese (zh-Hant) translation.
|
||||||
|
- Add Jitsi to our supported videoconference apps list
|
||||||
|
|
||||||
|
### Misc
|
||||||
|
- New contrib plugin for letschat (by Δndrea Stagi)
|
||||||
|
- Lots of small and not so small bugfixes.
|
||||||
|
|
||||||
|
|
||||||
## 1.6.0 Abies Bifolia (2015-03-17)
|
## 1.6.0 Abies Bifolia (2015-03-17)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
|
@ -44,3 +44,10 @@ All the information about the different installation methods (production, develo
|
||||||
[Taiga has a mailing list](http://groups.google.com/d/forum/taigaio). Feel free to join it and ask any questions you may have.
|
[Taiga has a mailing list](http://groups.google.com/d/forum/taigaio). Feel free to join it and ask any questions you may have.
|
||||||
|
|
||||||
To subscribe for announcements of releases, important changes and so on, please follow [@taigaio](https://twitter.com/taigaio) on Twitter.
|
To subscribe for announcements of releases, important changes and so on, please follow [@taigaio](https://twitter.com/taigaio) on Twitter.
|
||||||
|
|
||||||
|
## Donations ##
|
||||||
|
|
||||||
|
We are grateful for your emails volunteering donations to Taiga. We feel comfortable accepting them under these conditions: The first that we will only do so while we are in the current beta / pre-revenue stage and that whatever money is donated will go towards a bounty fund. Starting Q2 2015 we will be engaging much more actively with our community to help further the development of Taiga, and we will use these donations to reward people working alongside us.
|
||||||
|
|
||||||
|
If you wish to make a donation to this Taiga fund, you can do so via http://www.paypal.com using the email: eposner@taiga.io
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ window.taigaConfig = {
|
||||||
"api": "http://localhost:8000/api/v1/",
|
"api": "http://localhost:8000/api/v1/",
|
||||||
"eventsUrl": null,
|
"eventsUrl": null,
|
||||||
"debug": true,
|
"debug": true,
|
||||||
|
"defaultLanguage": "en",
|
||||||
"publicRegisterEnabled": true,
|
"publicRegisterEnabled": true,
|
||||||
"feedbackEnabled": true,
|
"feedbackEnabled": true,
|
||||||
"privacyPolicyUrl": null,
|
"privacyPolicyUrl": null,
|
||||||
|
|
|
@ -36,7 +36,8 @@ taiga.generateUniqueSessionIdentifier = ->
|
||||||
taiga.sessionId = 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("/",
|
$routeProvider.when("/",
|
||||||
{templateUrl: "project/projects.html", resolve: {loader: tgLoaderProvider.add()}})
|
{templateUrl: "project/projects.html", resolve: {loader: tgLoaderProvider.add()}})
|
||||||
|
|
||||||
|
@ -159,12 +160,12 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
|
||||||
$routeProvider.when("/permission-denied",
|
$routeProvider.when("/permission-denied",
|
||||||
{templateUrl: "error/permission-denied.html"})
|
{templateUrl: "error/permission-denied.html"})
|
||||||
|
|
||||||
$routeProvider.otherwise({redirectTo: '/not-found'})
|
$routeProvider.otherwise({redirectTo: "/not-found"})
|
||||||
$locationProvider.html5Mode({enabled: true, requireBase: false})
|
$locationProvider.html5Mode({enabled: true, requireBase: false})
|
||||||
|
|
||||||
defaultHeaders = {
|
defaultHeaders = {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
"Accept-Language": "en"
|
"Accept-Language": window.taigaConfig.defaultLanguage || "en"
|
||||||
"X-Session-Id": taiga.sessionId
|
"X-Session-Id": taiga.sessionId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,30 +196,30 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
|
||||||
responseError: httpResponseError
|
responseError: httpResponseError
|
||||||
}
|
}
|
||||||
|
|
||||||
$provide.factory("authHttpIntercept", ["$q", "$location", "$tgNavUrls", "lightboxService", authHttpIntercept])
|
$provide.factory("authHttpIntercept", ["$q", "$location", "$tgNavUrls", "lightboxService",
|
||||||
|
authHttpIntercept])
|
||||||
|
|
||||||
$httpProvider.interceptors.push('authHttpIntercept')
|
$httpProvider.interceptors.push("authHttpIntercept")
|
||||||
|
|
||||||
# If there is an error in the version throw a notify error
|
|
||||||
versionCheckHttpIntercept = ($q, $confirm) ->
|
|
||||||
versionErrorMsg = "Someone inside Taiga has changed this before and our Oompa Loompas cannot apply your changes.
|
|
||||||
Please reload and apply your changes again (they will be lost)." #TODO: i18n
|
|
||||||
|
|
||||||
|
# If there is an error in the version throw a notify error.
|
||||||
|
# IMPROVEiMENT: Move this version error handler to USs, issues and tasks repository
|
||||||
|
versionCheckHttpIntercept = ($q) ->
|
||||||
httpResponseError = (response) ->
|
httpResponseError = (response) ->
|
||||||
if response.status == 400 && response.data.version
|
if response.status == 400 && response.data.version
|
||||||
$confirm.notify("error", versionErrorMsg, null, 10000)
|
# HACK: to prevent circular dependencies with [$tgConfirm, $translate]
|
||||||
|
$injector = angular.element("body").injector()
|
||||||
return $q.reject(response)
|
$injector.invoke(["$tgConfirm", "$translate", ($confirm, $translate) =>
|
||||||
|
versionErrorMsg = $translate.instant("ERROR.VERSION_ERROR")
|
||||||
|
$confirm.notify("error", versionErrorMsg, null, 10000)
|
||||||
|
])
|
||||||
|
|
||||||
return $q.reject(response)
|
return $q.reject(response)
|
||||||
|
|
||||||
return {
|
return {responseError: httpResponseError}
|
||||||
responseError: httpResponseError
|
|
||||||
}
|
|
||||||
|
|
||||||
$provide.factory("versionCheckHttpIntercept", ["$q", "$tgConfirm", versionCheckHttpIntercept])
|
$provide.factory("versionCheckHttpIntercept", ["$q", versionCheckHttpIntercept])
|
||||||
|
|
||||||
$httpProvider.interceptors.push('versionCheckHttpIntercept');
|
$httpProvider.interceptors.push("versionCheckHttpIntercept")
|
||||||
|
|
||||||
window.checksley.updateValidators({
|
window.checksley.updateValidators({
|
||||||
linewidth: (val, width) ->
|
linewidth: (val, width) ->
|
||||||
|
@ -230,21 +231,78 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
|
||||||
return valid
|
return valid
|
||||||
})
|
})
|
||||||
|
|
||||||
window.checksley.updateMessages("default", {
|
|
||||||
linewidth: "The subject must have a maximum size of %s"
|
|
||||||
})
|
|
||||||
|
|
||||||
$compileProvider.debugInfoEnabled(window.taigaConfig.debugInfo || false)
|
$compileProvider.debugInfoEnabled(window.taigaConfig.debugInfo || false)
|
||||||
|
|
||||||
init = ($log, $i18n, $config, $rootscope, $auth, $events, $analytics) ->
|
if localStorage.userInfo
|
||||||
$i18n.initialize($config.get("defaultLanguage"))
|
userInfo = JSON.parse(localStorage.userInfo)
|
||||||
|
|
||||||
|
# i18n
|
||||||
|
preferedLangCode = userInfo?.lang || window.taigaConfig.defaultLanguage || "en"
|
||||||
|
|
||||||
|
$translateProvider
|
||||||
|
.useStaticFilesLoader({
|
||||||
|
prefix: "/locales/locale-",
|
||||||
|
suffix: ".json"
|
||||||
|
})
|
||||||
|
.addInterpolation('$translateMessageFormatInterpolation')
|
||||||
|
.preferredLanguage(preferedLangCode)
|
||||||
|
|
||||||
|
if not window.taigaConfig.debugInfo
|
||||||
|
$translateProvider.fallbackLanguage(preferedLangCode)
|
||||||
|
|
||||||
|
|
||||||
|
i18nInit = (lang, $translate) ->
|
||||||
|
# i18n - moment.js
|
||||||
|
moment.locale(lang)
|
||||||
|
|
||||||
|
# i18n - checksley.js
|
||||||
|
messages = {
|
||||||
|
defaultMessage: $translate.instant("COMMON.FORM_ERRORS.DEFAULT_MESSAGE")
|
||||||
|
type: {
|
||||||
|
email: $translate.instant("COMMON.FORM_ERRORS.TYPE_EMAIL")
|
||||||
|
url: $translate.instant("COMMON.FORM_ERRORS.TYPE_URL")
|
||||||
|
urlstrict: $translate.instant("COMMON.FORM_ERRORS.TYPE_URLSTRICT")
|
||||||
|
number: $translate.instant("COMMON.FORM_ERRORS.TYPE_NUMBER")
|
||||||
|
digits: $translate.instant("COMMON.FORM_ERRORS.TYPE_DIGITS")
|
||||||
|
dateIso: $translate.instant("COMMON.FORM_ERRORS.TYPE_DATEISO")
|
||||||
|
alphanum: $translate.instant("COMMON.FORM_ERRORS.TYPE_ALPHANUM")
|
||||||
|
phone: $translate.instant("COMMON.FORM_ERRORS.TYPE_PHONE")
|
||||||
|
}
|
||||||
|
notnull: $translate.instant("COMMON.FORM_ERRORS.NOTNULL")
|
||||||
|
notblank: $translate.instant("COMMON.FORM_ERRORS.NOT_BLANK")
|
||||||
|
required: $translate.instant("COMMON.FORM_ERRORS.REQUIRED")
|
||||||
|
regexp: $translate.instant("COMMON.FORM_ERRORS.REGEXP")
|
||||||
|
min: $translate.instant("COMMON.FORM_ERRORS.MIN")
|
||||||
|
max: $translate.instant("COMMON.FORM_ERRORS.MAX")
|
||||||
|
range: $translate.instant("COMMON.FORM_ERRORS.RANGE")
|
||||||
|
minlength: $translate.instant("COMMON.FORM_ERRORS.MIN_LENGTH")
|
||||||
|
maxlength: $translate.instant("COMMON.FORM_ERRORS.MAX_LENGTH")
|
||||||
|
rangelength: $translate.instant("COMMON.FORM_ERRORS.RANGE_LENGTH")
|
||||||
|
mincheck: $translate.instant("COMMON.FORM_ERRORS.MIN_CHECK")
|
||||||
|
maxcheck: $translate.instant("COMMON.FORM_ERRORS.MAX_CHECK")
|
||||||
|
rangecheck: $translate.instant("COMMON.FORM_ERRORS.RANGE_CHECK")
|
||||||
|
equalto: $translate.instant("COMMON.FORM_ERRORS.EQUAL_TO")
|
||||||
|
}
|
||||||
|
checksley.updateMessages('default', messages)
|
||||||
|
|
||||||
|
|
||||||
|
init = ($log, $config, $rootscope, $auth, $events, $analytics, $translate) ->
|
||||||
$log.debug("Initialize application")
|
$log.debug("Initialize application")
|
||||||
|
|
||||||
|
# Taiga Plugins
|
||||||
$rootscope.contribPlugins = @.taigaContribPlugins
|
$rootscope.contribPlugins = @.taigaContribPlugins
|
||||||
$rootscope.adminPlugins = _.where(@.taigaContribPlugins, {"type": "admin"})
|
$rootscope.adminPlugins = _.where(@.taigaContribPlugins, {"type": "admin"})
|
||||||
|
|
||||||
|
$rootscope.$on "$translateChangeEnd", (e, ctx) ->
|
||||||
|
lang = ctx.language
|
||||||
|
i18nInit(lang, $translate)
|
||||||
|
|
||||||
|
# Load user
|
||||||
if $auth.isAuthenticated()
|
if $auth.isAuthenticated()
|
||||||
$events.setupConnection()
|
$events.setupConnection()
|
||||||
|
user = $auth.getUser()
|
||||||
|
|
||||||
|
# Analytics
|
||||||
$analytics.initialize()
|
$analytics.initialize()
|
||||||
|
|
||||||
|
|
||||||
|
@ -253,7 +311,6 @@ modules = [
|
||||||
"taigaBase",
|
"taigaBase",
|
||||||
"taigaCommon",
|
"taigaCommon",
|
||||||
"taigaResources",
|
"taigaResources",
|
||||||
"taigaLocales",
|
|
||||||
"taigaAuth",
|
"taigaAuth",
|
||||||
"taigaEvents",
|
"taigaEvents",
|
||||||
|
|
||||||
|
@ -261,7 +318,7 @@ modules = [
|
||||||
"taigaRelatedTasks",
|
"taigaRelatedTasks",
|
||||||
"taigaBacklog",
|
"taigaBacklog",
|
||||||
"taigaTaskboard",
|
"taigaTaskboard",
|
||||||
"taigaKanban"
|
"taigaKanban",
|
||||||
"taigaIssues",
|
"taigaIssues",
|
||||||
"taigaUserStories",
|
"taigaUserStories",
|
||||||
"taigaTasks",
|
"taigaTasks",
|
||||||
|
@ -275,13 +332,15 @@ modules = [
|
||||||
"taigaFeedback",
|
"taigaFeedback",
|
||||||
"taigaPlugins",
|
"taigaPlugins",
|
||||||
"taigaIntegrations",
|
"taigaIntegrations",
|
||||||
|
"taigaComponents",
|
||||||
|
|
||||||
# template cache
|
# template cache
|
||||||
"templates"
|
"templates",
|
||||||
|
|
||||||
# Vendor modules
|
# Vendor modules
|
||||||
"ngRoute",
|
"ngRoute",
|
||||||
"ngAnimate",
|
"ngAnimate",
|
||||||
|
"pascalprecht.translate"
|
||||||
].concat(_.map(@.taigaContribPlugins, (plugin) -> plugin.module))
|
].concat(_.map(@.taigaContribPlugins, (plugin) -> plugin.module))
|
||||||
|
|
||||||
# Main module definition
|
# Main module definition
|
||||||
|
@ -295,16 +354,17 @@ module.config([
|
||||||
"$tgEventsProvider",
|
"$tgEventsProvider",
|
||||||
"tgLoaderProvider",
|
"tgLoaderProvider",
|
||||||
"$compileProvider",
|
"$compileProvider",
|
||||||
|
"$translateProvider",
|
||||||
configure
|
configure
|
||||||
])
|
])
|
||||||
|
|
||||||
module.run([
|
module.run([
|
||||||
"$log",
|
"$log",
|
||||||
"$tgI18n",
|
|
||||||
"$tgConfig",
|
"$tgConfig",
|
||||||
"$rootScope",
|
"$rootScope",
|
||||||
"$tgAuth",
|
"$tgAuth",
|
||||||
"$tgEvents",
|
"$tgEvents",
|
||||||
"$tgAnalytics",
|
"$tgAnalytics",
|
||||||
|
"$translate"
|
||||||
init
|
init
|
||||||
])
|
])
|
||||||
|
|
|
@ -30,19 +30,19 @@ MAX_MEMBERSHIP_FIELDSETS = 4
|
||||||
## Create Members Lightbox Directive
|
## Create Members Lightbox Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
CreateMembersDirective = ($rs, $rootScope, $confirm, $loading ,lightboxService) ->
|
CreateMembersDirective = ($rs, $rootScope, $confirm, $loading, lightboxService, $compile) ->
|
||||||
extraTextTemplate = """
|
extraTextTemplate = """
|
||||||
<fieldset class="extra-text">
|
<fieldset class="extra-text">
|
||||||
<textarea placeholder="(Optional) Add a personalized text to the invitation. Tell something lovely to your new members ;-)"
|
<textarea ng-attr-placeholder="{{'LIGHTBOX.CREATE_MEMBER.PLACEHOLDER_INVITATION_TEXT' | translate}}"
|
||||||
maxlength="255">
|
maxlength="255"></textarea>
|
||||||
</textarea>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
template = _.template("""
|
template = _.template("""
|
||||||
<div class="add-member-wrapper">
|
<div class="add-member-wrapper">
|
||||||
<fieldset>
|
<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' | translate}}"
|
||||||
|
<% if(required) { %> data-required="true" <% } %> data-type="email" />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<select <% if(required) { %> data-required="true" <% } %> data-required="true">
|
<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>
|
<a class="icon icon-plus add-fieldset" href=""></a>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
""") # i18n
|
""")
|
||||||
|
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
createFieldSet = (required = true)->
|
createFieldSet = (required = true)->
|
||||||
ctx = {roleList: $scope.roles, required: required}
|
ctx = {roleList: $scope.roles, required: required}
|
||||||
return template(ctx)
|
return $compile(template(ctx))($scope)
|
||||||
|
|
||||||
resetForm = ->
|
resetForm = ->
|
||||||
$el.find("form textarea").remove("")
|
$el.find("form textarea").remove()
|
||||||
$el.find("form .add-member-wrapper").remove()
|
$el.find("form .add-member-wrapper").remove()
|
||||||
|
|
||||||
invitations = $el.find(".add-member-forms")
|
invitations = $el.find(".add-member-forms")
|
||||||
invitations.html(extraTextTemplate)
|
invitations.html($compile(extraTextTemplate)($scope))
|
||||||
|
|
||||||
fieldSet = createFieldSet()
|
fieldSet = createFieldSet()
|
||||||
invitations.prepend(fieldSet)
|
invitations.prepend(fieldSet)
|
||||||
|
@ -84,7 +84,7 @@ CreateMembersDirective = ($rs, $rootScope, $confirm, $loading ,lightboxService)
|
||||||
|
|
||||||
fieldSet.remove()
|
fieldSet.remove()
|
||||||
|
|
||||||
lastActionButton = $el.find("fieldset:last > a")
|
lastActionButton = $el.find(".add-member-wrapper fieldset:last > a")
|
||||||
if lastActionButton.hasClass("icon-delete delete-fieldset")
|
if lastActionButton.hasClass("icon-delete delete-fieldset")
|
||||||
lastActionButton.removeClass("icon-delete delete-fieldset")
|
lastActionButton.removeClass("icon-delete delete-fieldset")
|
||||||
.addClass("icon-plus add-fieldset")
|
.addClass("icon-plus add-fieldset")
|
||||||
|
@ -98,9 +98,10 @@ CreateMembersDirective = ($rs, $rootScope, $confirm, $loading ,lightboxService)
|
||||||
.addClass("icon-delete delete-fieldset")
|
.addClass("icon-delete delete-fieldset")
|
||||||
|
|
||||||
newFieldSet = createFieldSet(false)
|
newFieldSet = createFieldSet(false)
|
||||||
|
|
||||||
fieldSet.after(newFieldSet)
|
fieldSet.after(newFieldSet)
|
||||||
|
|
||||||
|
$scope.$digest() # To compile newFieldSet and translate text
|
||||||
|
|
||||||
if $el.find(".add-member-wrapper").length == MAX_MEMBERSHIP_FIELDSETS
|
if $el.find(".add-member-wrapper").length == MAX_MEMBERSHIP_FIELDSETS
|
||||||
$el.find(".add-member-wrapper fieldset:last > a").removeClass("icon-plus add-fieldset")
|
$el.find(".add-member-wrapper fieldset:last > a").removeClass("icon-plus add-fieldset")
|
||||||
.addClass("icon-delete delete-fieldset")
|
.addClass("icon-delete delete-fieldset")
|
||||||
|
@ -147,7 +148,9 @@ CreateMembersDirective = ($rs, $rootScope, $confirm, $loading ,lightboxService)
|
||||||
if invitations.length
|
if invitations.length
|
||||||
invitation_extra_text = $el.find("form textarea").val()
|
invitation_extra_text = $el.find("form textarea").val()
|
||||||
|
|
||||||
$rs.memberships.bulkCreateMemberships($scope.project.id, invitations, invitation_extra_text).then(onSuccess, onError)
|
promise = $rs.memberships.bulkCreateMemberships($scope.project.id,
|
||||||
|
invitations, invitation_extra_text)
|
||||||
|
promise.then(onSuccess, onError)
|
||||||
|
|
||||||
submitButton = $el.find(".submit-button")
|
submitButton = $el.find(".submit-button")
|
||||||
|
|
||||||
|
@ -155,5 +158,5 @@ CreateMembersDirective = ($rs, $rootScope, $confirm, $loading ,lightboxService)
|
||||||
|
|
||||||
return {link: link}
|
return {link: link}
|
||||||
|
|
||||||
module.directive("tgLbCreateMembers", ["$tgResources", "$rootScope", "$tgConfirm", "$tgLoading", "lightboxService",
|
module.directive("tgLbCreateMembers", ["$tgResources", "$rootScope", "$tgConfirm", "$tgLoading",
|
||||||
CreateMembersDirective])
|
"lightboxService", "$compile", CreateMembersDirective])
|
||||||
|
|
|
@ -50,7 +50,6 @@ class MembershipsController extends mixOf(taiga.Controller, taiga.PageMixin, tai
|
||||||
@location, @navUrls, @analytics, @appTitle) ->
|
@location, @navUrls, @analytics, @appTitle) ->
|
||||||
bindMethods(@)
|
bindMethods(@)
|
||||||
|
|
||||||
@scope.sectionName = "Manage Members" #i18n
|
|
||||||
@scope.project = {}
|
@scope.project = {}
|
||||||
@scope.filters = {}
|
@scope.filters = {}
|
||||||
|
|
||||||
|
@ -236,7 +235,7 @@ module.directive("tgMembershipsRowAvatar", ["$log", "$tgTemplate", MembershipsRo
|
||||||
## Member IsAdminCheckbox Directive
|
## Member IsAdminCheckbox Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
MembershipsRowAdminCheckboxDirective = ($log, $repo, $confirm, $template) ->
|
MembershipsRowAdminCheckboxDirective = ($log, $repo, $confirm, $template, $compile) ->
|
||||||
template = $template.get("admin/admin-memberships-row-checkbox.html", true)
|
template = $template.get("admin/admin-memberships-row-checkbox.html", true)
|
||||||
|
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
|
@ -244,6 +243,8 @@ MembershipsRowAdminCheckboxDirective = ($log, $repo, $confirm, $template) ->
|
||||||
ctx = {inputId: "is-admin-#{member.id}"}
|
ctx = {inputId: "is-admin-#{member.id}"}
|
||||||
|
|
||||||
html = template(ctx)
|
html = template(ctx)
|
||||||
|
html = $compile(html)($scope)
|
||||||
|
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
if not $attrs.tgMembershipsRowAdminCheckbox?
|
if not $attrs.tgMembershipsRowAdminCheckbox?
|
||||||
|
@ -274,8 +275,8 @@ MembershipsRowAdminCheckboxDirective = ($log, $repo, $confirm, $template) ->
|
||||||
return {link: link}
|
return {link: link}
|
||||||
|
|
||||||
|
|
||||||
module.directive("tgMembershipsRowAdminCheckbox", ["$log", "$tgRepo", "$tgConfirm", "$tgTemplate",
|
module.directive("tgMembershipsRowAdminCheckbox", ["$log", "$tgRepo", "$tgConfirm",
|
||||||
MembershipsRowAdminCheckboxDirective])
|
"$tgTemplate", "$compile", MembershipsRowAdminCheckboxDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -338,32 +339,31 @@ module.directive("tgMembershipsRowRoleSelector", ["$log", "$tgRepo", "$tgConfirm
|
||||||
## Member Actions Directive
|
## Member Actions Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
MembershipsRowActionsDirective = ($log, $repo, $rs, $confirm) ->
|
MembershipsRowActionsDirective = ($log, $repo, $rs, $confirm, $compile, $translate) ->
|
||||||
activedTemplate = _.template("""
|
activedTemplate = """
|
||||||
<div class="active">
|
<div class="active", translate="ADMIN.MEMBERSHIP.STATUS_ACTIVE">
|
||||||
Active
|
|
||||||
</div>
|
</div>
|
||||||
<a class="delete" href="">
|
<a class="delete" href="">
|
||||||
<span class="icon icon-delete"></span>
|
<span class="icon icon-delete"></span>
|
||||||
</a>
|
</a>
|
||||||
""") # TODO: i18n
|
"""
|
||||||
|
|
||||||
pendingTemplate = _.template("""
|
pendingTemplate = """
|
||||||
<a class="pending" href="">
|
<a class="pending" href="">
|
||||||
Pending
|
{{'ADMIN.MEMBERSHIP.STATUS_PENDING' | translate}}
|
||||||
<span class="icon icon-reload"></span>
|
<span class="icon icon-reload"></span>
|
||||||
</a>
|
</a>
|
||||||
<a class="delete" href="" title="Delete">
|
<a class="delete" href="">
|
||||||
<span class="icon icon-delete"></span>
|
<span class="icon icon-delete"></span>
|
||||||
</a>
|
</a>
|
||||||
""") # TODO: i18n
|
"""
|
||||||
|
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
render = (member) ->
|
render = (member) ->
|
||||||
if member.user
|
if member.user
|
||||||
html = activedTemplate()
|
html = $compile(activedTemplate)($scope)
|
||||||
else
|
else
|
||||||
html = pendingTemplate()
|
html = $compile(pendingTemplate)($scope)
|
||||||
|
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
|
@ -377,29 +377,34 @@ MembershipsRowActionsDirective = ($log, $repo, $rs, $confirm) ->
|
||||||
$el.on "click", ".pending", (event) ->
|
$el.on "click", ".pending", (event) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
onSuccess = ->
|
onSuccess = ->
|
||||||
# TODO: i18n
|
text = $translate.instant("ADMIN.MEMBERSHIP.SUCCESS_SEND_INVITATION", {email: $scope.member.email})
|
||||||
$confirm.notify("success", "We've sent the invitationi again to '#{$scope.member.email}'.")
|
$confirm.notify("success", text)
|
||||||
onError = ->
|
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)
|
$rs.memberships.resendInvitation($scope.member.id).then(onSuccess, onError)
|
||||||
|
|
||||||
$el.on "click", ".delete", (event) ->
|
$el.on "click", ".delete", (event) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
title = "Delete member" # TODO: i18n
|
title = $translate.instant("ADMIN.MEMBERSHIP.DELETE_MEMBER")
|
||||||
message = if member.user then member.full_name else "the invitation to #{member.email}" # TODO: i18n
|
defaultMsg = $translate.instant("ADMIN.MEMBERSHIP.DEFAULT_DELETE_MESSAGE")
|
||||||
|
message = if member.user then member.full_name else defaultMsg
|
||||||
|
|
||||||
$confirm.askOnDelete(title, message).then (finish) ->
|
$confirm.askOnDelete(title, message).then (finish) ->
|
||||||
onSuccess = ->
|
onSuccess = ->
|
||||||
finish()
|
finish()
|
||||||
$ctrl.loadMembers()
|
$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 = ->
|
onError = ->
|
||||||
finish(false)
|
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)
|
$repo.remove(member).then(onSuccess, onError)
|
||||||
|
|
||||||
|
@ -409,5 +414,4 @@ MembershipsRowActionsDirective = ($log, $repo, $rs, $confirm) ->
|
||||||
return {link: link}
|
return {link: link}
|
||||||
|
|
||||||
|
|
||||||
module.directive("tgMembershipsRowActions", ["$log", "$tgRepo", "$tgResources", "$tgConfirm",
|
module.directive("tgMembershipsRowActions", ["$log", "$tgRepo", "$tgResources", "$tgConfirm", "$compile", "$translate", MembershipsRowActionsDirective])
|
||||||
MembershipsRowActionsDirective])
|
|
||||||
|
|
|
@ -47,21 +47,28 @@ class ProjectProfileController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
"$q",
|
"$q",
|
||||||
"$tgLocation",
|
"$tgLocation",
|
||||||
"$tgNavUrls",
|
"$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 = {}
|
@scope.project = {}
|
||||||
|
|
||||||
promise = @.loadInitialData()
|
promise = @.loadInitialData()
|
||||||
|
|
||||||
promise.then =>
|
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(@)
|
promise.then null, @.onInitialDataError.bind(@)
|
||||||
|
|
||||||
@scope.$on "project:loaded", =>
|
@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: ->
|
loadProject: ->
|
||||||
return @rs.projects.get(@scope.projectId).then (project) =>
|
return @rs.projects.get(@scope.projectId).then (project) =>
|
||||||
|
@ -79,12 +86,22 @@ class ProjectProfileController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
@scope.$emit('project:loaded', project)
|
@scope.$emit('project:loaded', project)
|
||||||
return project
|
return project
|
||||||
|
|
||||||
|
loadTagsColors: ->
|
||||||
|
return @rs.projects.tagsColors(@scope.projectId).then (tags_colors) =>
|
||||||
|
@scope.project.tags_colors = tags_colors
|
||||||
|
|
||||||
|
loadProjectProfile: ->
|
||||||
|
return @q.all([
|
||||||
|
@.loadProject(),
|
||||||
|
@.loadTagsColors()
|
||||||
|
])
|
||||||
|
|
||||||
loadInitialData: ->
|
loadInitialData: ->
|
||||||
promise = @repo.resolve({pslug: @params.pslug}).then (data) =>
|
promise = @repo.resolve({pslug: @params.pslug}).then (data) =>
|
||||||
@scope.projectId = data.project
|
@scope.projectId = data.project
|
||||||
return data
|
return data
|
||||||
|
|
||||||
return promise.then(=> @.loadProject())
|
return promise.then(=> @.loadProjectProfile())
|
||||||
|
|
||||||
openDeleteLightbox: ->
|
openDeleteLightbox: ->
|
||||||
@rootscope.$broadcast("deletelightbox:new", @scope.project)
|
@rootscope.$broadcast("deletelightbox:new", @scope.project)
|
||||||
|
@ -115,7 +132,7 @@ ProjectProfileDirective = ($repo, $confirm, $loading, $navurls, $location) ->
|
||||||
$scope.$emit("project:loaded", $scope.project)
|
$scope.$emit("project:loaded", $scope.project)
|
||||||
|
|
||||||
promise.then null, (data) ->
|
promise.then null, (data) ->
|
||||||
$loading.finish(target)
|
$loading.finish(submitButton)
|
||||||
form.setErrors(data)
|
form.setErrors(data)
|
||||||
if data._error_message
|
if data._error_message
|
||||||
$confirm.notify("error", data._error_message)
|
$confirm.notify("error", data._error_message)
|
||||||
|
@ -126,7 +143,8 @@ ProjectProfileDirective = ($repo, $confirm, $loading, $navurls, $location) ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgProjectProfile", ["$tgRepo", "$tgConfirm", "$tgLoading", "$tgNavUrls", "$tgLocation", ProjectProfileDirective])
|
module.directive("tgProjectProfile", ["$tgRepo", "$tgConfirm", "$tgLoading", "$tgNavUrls", "$tgLocation",
|
||||||
|
ProjectProfileDirective])
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Project Default Values Directive
|
## Project Default Values Directive
|
||||||
|
@ -162,7 +180,8 @@ ProjectDefaultValuesDirective = ($repo, $confirm, $loading) ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgProjectDefaultValues", ["$tgRepo", "$tgConfirm", "$tgLoading", ProjectDefaultValuesDirective])
|
module.directive("tgProjectDefaultValues", ["$tgRepo", "$tgConfirm", "$tgLoading",
|
||||||
|
ProjectDefaultValuesDirective])
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Project Modules Directive
|
## Project Modules Directive
|
||||||
|
@ -217,7 +236,7 @@ module.directive("tgProjectModules", ["$tgRepo", "$tgConfirm", "$tgLoading", Pro
|
||||||
## Project Export Directive
|
## Project Export Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
ProjectExportDirective = ($window, $rs, $confirm) ->
|
ProjectExportDirective = ($window, $rs, $confirm, $translate) ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
buttonsEl = $el.find(".admin-project-export-buttons")
|
buttonsEl = $el.find(".admin-project-export-buttons")
|
||||||
showButtons = -> buttonsEl.removeClass("hidden")
|
showButtons = -> buttonsEl.removeClass("hidden")
|
||||||
|
@ -232,16 +251,23 @@ ProjectExportDirective = ($window, $rs, $confirm) ->
|
||||||
hideSpinner = -> spinnerEl.addClass("hidden")
|
hideSpinner = -> spinnerEl.addClass("hidden")
|
||||||
|
|
||||||
resultTitleEl = $el.find(".result-title")
|
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($translate.instant("ADMIN.PROJECT_EXPORT.DUMP_READY"))
|
||||||
|
asyn_message = -> resultTitleEl.html($translate.instant("ADMIN.PROJECT_EXPORT.ASYNC_MESSAGE"))
|
||||||
|
syn_message = (url) -> resultTitleEl.html($translate.instant("ADMIN.PROJECT_EXPORT.SYNC_MESSAGE", {
|
||||||
|
url: url}))
|
||||||
|
|
||||||
|
setLoadingTitle = -> resultTitleEl.html(loading_title)
|
||||||
|
setAsyncTitle = -> resultTitleEl.html(loading_msg)
|
||||||
|
setSyncTitle = -> resultTitleEl.html(dump_ready_text)
|
||||||
|
|
||||||
resultMessageEl = $el.find(".result-message ")
|
resultMessageEl = $el.find(".result-message ")
|
||||||
setLoadingMessage = -> resultMessageEl.html("Please don't close this page.") # TODO: i18n
|
setLoadingMessage = -> resultMessageEl.html(loading_msg)
|
||||||
setAsyncMessage = -> resultMessageEl.html("We will send you an email when ready.") # TODO: i18n
|
setAsyncMessage = -> resultMessageEl.html(asyn_message)
|
||||||
setSyncMessage = (url) -> resultMessageEl.html("If the download doesn't start automatically click
|
setSyncMessage = (url) -> resultMessageEl.html(syn_message(url))
|
||||||
<a href='#{url}' download title='Download
|
|
||||||
the dump file'>here.") # TODO: i18n
|
|
||||||
|
|
||||||
showLoadingMode = ->
|
showLoadingMode = ->
|
||||||
showSpinner()
|
showSpinner()
|
||||||
|
@ -279,15 +305,13 @@ ProjectExportDirective = ($window, $rs, $confirm) ->
|
||||||
onError = (result) =>
|
onError = (result) =>
|
||||||
showErrorMode()
|
showErrorMode()
|
||||||
|
|
||||||
errorMsg = "Our oompa loompas have some problems generasting your dump.
|
errorMsg = $translate.instant("ADMIN.PROJECT_EXPORT.ERROR")
|
||||||
Please try again. " # TODO: i18n
|
|
||||||
|
|
||||||
if result.status == 429 # TOO MANY REQUESTS
|
if result.status == 429 # TOO MANY REQUESTS
|
||||||
errorMsg = "Sorry, our oompa loompas are very busy right now.
|
errorMsg = $translate.instant("ADMIN.PROJECT_EXPORT.ERROR_BUSY")
|
||||||
Please try again in a few minutes. " # TODO: i18n
|
|
||||||
else if result.data?._error_message
|
else if result.data?._error_message
|
||||||
errorMsg = "Our oompa loompas have some problems generasting your dump:
|
errorMsg = $translate.instant("ADMIN.PROJECT_EXPORT.ERROR_BUSY", {
|
||||||
#{result.data._error_message}" # TODO: i18n
|
message: result.data._error_message})
|
||||||
|
|
||||||
$confirm.notify("error", errorMsg)
|
$confirm.notify("error", errorMsg)
|
||||||
|
|
||||||
|
@ -296,7 +320,8 @@ ProjectExportDirective = ($window, $rs, $confirm) ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgProjectExport", ["$window", "$tgResources", "$tgConfirm", ProjectExportDirective])
|
module.directive("tgProjectExport", ["$window", "$tgResources", "$tgConfirm", "$translate",
|
||||||
|
ProjectExportDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -310,9 +335,10 @@ class CsvExporterController extends taiga.Controller
|
||||||
"$tgUrls",
|
"$tgUrls",
|
||||||
"$tgConfirm",
|
"$tgConfirm",
|
||||||
"$tgResources",
|
"$tgResources",
|
||||||
|
"$translate"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @rootscope, @urls, @confirm, @rs) ->
|
constructor: (@scope, @rootscope, @urls, @confirm, @rs, @translate) ->
|
||||||
@rootscope.$on("project:loaded", @.setCsvUuid)
|
@rootscope.$on("project:loaded", @.setCsvUuid)
|
||||||
@scope.$watch "csvUuid", (value) =>
|
@scope.$watch "csvUuid", (value) =>
|
||||||
if value
|
if value
|
||||||
|
@ -337,10 +363,10 @@ class CsvExporterController extends taiga.Controller
|
||||||
return promise
|
return promise
|
||||||
|
|
||||||
regenerateUuid: ->
|
regenerateUuid: ->
|
||||||
#TODO: i18n
|
|
||||||
if @scope.csvUuid
|
if @scope.csvUuid
|
||||||
title = "Change URL"
|
title = @translate.instant("ADMIN.REPORTS.REGENERATE_TITLE")
|
||||||
subtitle = "You going to change the CSV data access url. The previous url will be disabled. Are you sure?"
|
subtitle = @translate.instant("ADMIN.REPORTS.REGENERATE_SUBTITLE")
|
||||||
|
|
||||||
@confirm.ask(title, subtitle).then @._generateUuid
|
@confirm.ask(title, subtitle).then @._generateUuid
|
||||||
else
|
else
|
||||||
@._generateUuid(_.identity)
|
@._generateUuid(_.identity)
|
||||||
|
@ -361,3 +387,52 @@ class CsvExporterIssuesController extends CsvExporterController
|
||||||
module.controller("CsvExporterUserstoriesController", CsvExporterUserstoriesController)
|
module.controller("CsvExporterUserstoriesController", CsvExporterUserstoriesController)
|
||||||
module.controller("CsvExporterTasksController", CsvExporterTasksController)
|
module.controller("CsvExporterTasksController", CsvExporterTasksController)
|
||||||
module.controller("CsvExporterIssuesController", CsvExporterIssuesController)
|
module.controller("CsvExporterIssuesController", CsvExporterIssuesController)
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
## CSV Directive
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
CsvUsDirective = ($translate) ->
|
||||||
|
link = ($scope) ->
|
||||||
|
$scope.sectionTitle = "ADMIN.CSV.SECTION_TITLE_US"
|
||||||
|
|
||||||
|
return {
|
||||||
|
controller: "CsvExporterUserstoriesController",
|
||||||
|
controllerAs: "ctrl",
|
||||||
|
templateUrl: "admin/project-csv.html",
|
||||||
|
link: link,
|
||||||
|
scope: true
|
||||||
|
}
|
||||||
|
|
||||||
|
module.directive("tgCsvUs", ["$translate", CsvUsDirective])
|
||||||
|
|
||||||
|
|
||||||
|
CsvTaskDirective = ($translate) ->
|
||||||
|
link = ($scope) ->
|
||||||
|
$scope.sectionTitle = "ADMIN.CSV.SECTION_TITLE_TASK"
|
||||||
|
|
||||||
|
return {
|
||||||
|
controller: "CsvExporterTasksController",
|
||||||
|
controllerAs: "ctrl",
|
||||||
|
templateUrl: "admin/project-csv.html",
|
||||||
|
link: link,
|
||||||
|
scope: true
|
||||||
|
}
|
||||||
|
|
||||||
|
module.directive("tgCsvTask", ["$translate", CsvTaskDirective])
|
||||||
|
|
||||||
|
|
||||||
|
CsvIssueDirective = ($translate) ->
|
||||||
|
link = ($scope) ->
|
||||||
|
$scope.sectionTitle = "ADMIN.CSV.SECTION_TITLE_ISSUE"
|
||||||
|
|
||||||
|
return {
|
||||||
|
controller: "CsvExporterIssuesController",
|
||||||
|
controllerAs: "ctrl",
|
||||||
|
templateUrl: "admin/project-csv.html",
|
||||||
|
link: link,
|
||||||
|
scope: true
|
||||||
|
}
|
||||||
|
|
||||||
|
module.directive("tgCsvIssue", ["$translate", CsvIssueDirective])
|
||||||
|
|
|
@ -46,16 +46,24 @@ class ProjectValuesSectionController extends mixOf(taiga.Controller, taiga.PageM
|
||||||
"$q",
|
"$q",
|
||||||
"$tgLocation",
|
"$tgLocation",
|
||||||
"$tgNavUrls",
|
"$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 = {}
|
@scope.project = {}
|
||||||
|
|
||||||
promise = @.loadInitialData()
|
promise = @.loadInitialData()
|
||||||
|
|
||||||
promise.then () =>
|
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(@)
|
promise.then null, @.onInitialDataError.bind(@)
|
||||||
|
|
||||||
|
@ -118,7 +126,7 @@ module.controller("ProjectValuesController", ProjectValuesController)
|
||||||
## Project values directive
|
## Project values directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
ProjectValuesDirective = ($log, $repo, $confirm, $location, animationFrame) ->
|
ProjectValuesDirective = ($log, $repo, $confirm, $location, animationFrame, @translate, $rootscope) ->
|
||||||
## Drag & Drop Link
|
## Drag & Drop Link
|
||||||
|
|
||||||
linkDragAndDrop = ($scope, $el, $attrs) ->
|
linkDragAndDrop = ($scope, $el, $attrs) ->
|
||||||
|
@ -149,6 +157,7 @@ ProjectValuesDirective = ($log, $repo, $confirm, $location, animationFrame) ->
|
||||||
linkValue = ($scope, $el, $attrs) ->
|
linkValue = ($scope, $el, $attrs) ->
|
||||||
$ctrl = $el.controller()
|
$ctrl = $el.controller()
|
||||||
valueType = $attrs.type
|
valueType = $attrs.type
|
||||||
|
objName = $attrs.objname
|
||||||
|
|
||||||
initializeNewValue = ->
|
initializeNewValue = ->
|
||||||
$scope.newValue = {
|
$scope.newValue = {
|
||||||
|
@ -157,7 +166,14 @@ ProjectValuesDirective = ($log, $repo, $confirm, $location, animationFrame) ->
|
||||||
"is_archived": false
|
"is_archived": false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initializeTextTranslations = ->
|
||||||
|
$scope.addNewElementText = @translate.instant("ADMIN.PROJECT_VALUES_#{objName.toUpperCase()}.ACTION_ADD")
|
||||||
|
|
||||||
initializeNewValue()
|
initializeNewValue()
|
||||||
|
initializeTextTranslations()
|
||||||
|
|
||||||
|
$rootscope.$on "$translateChangeEnd", ->
|
||||||
|
$scope.$evalAsync(initializeTextTranslations)
|
||||||
|
|
||||||
goToBottomList = (focus = false) =>
|
goToBottomList = (focus = false) =>
|
||||||
table = $el.find(".table-main")
|
table = $el.find(".table-main")
|
||||||
|
@ -275,14 +291,12 @@ ProjectValuesDirective = ($log, $repo, $confirm, $location, animationFrame) ->
|
||||||
if value.id != option.id
|
if value.id != option.id
|
||||||
choices[option.id] = option.name
|
choices[option.id] = option.name
|
||||||
|
|
||||||
#TODO: i18n
|
|
||||||
title = "Delete value"
|
|
||||||
subtitle = value.name
|
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 = ->
|
onSucces = ->
|
||||||
$ctrl.loadValues().finally ->
|
$ctrl.loadValues().finally ->
|
||||||
response.finish()
|
response.finish()
|
||||||
|
@ -299,8 +313,7 @@ ProjectValuesDirective = ($log, $repo, $confirm, $location, animationFrame) ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgProjectValues", ["$log", "$tgRepo", "$tgConfirm", "$tgLocation", "animationFrame",
|
module.directive("tgProjectValues", ["$log", "$tgRepo", "$tgConfirm", "$tgLocation", "animationFrame", "$translate", "$rootScope", ProjectValuesDirective])
|
||||||
ProjectValuesDirective])
|
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -601,11 +614,9 @@ ProjectCustomAttributesDirective = ($log, $confirm, animationFrame) ->
|
||||||
|
|
||||||
deleteCustomAttribute = (formEl) ->
|
deleteCustomAttribute = (formEl) ->
|
||||||
attr = formEl.scope().attr
|
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
|
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 = ->
|
onSucces = ->
|
||||||
$ctrl.loadCustomAttributes().finally ->
|
$ctrl.loadCustomAttributes().finally ->
|
||||||
finish()
|
finish()
|
||||||
|
|
|
@ -44,20 +44,23 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil
|
||||||
"$q",
|
"$q",
|
||||||
"$tgLocation",
|
"$tgLocation",
|
||||||
"$tgNavUrls",
|
"$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(@)
|
bindMethods(@)
|
||||||
|
|
||||||
@scope.sectionName = "Permissions" #i18n
|
@scope.sectionName = "ADMIN.MENU.PERMISSIONS"
|
||||||
@scope.project = {}
|
@scope.project = {}
|
||||||
@scope.anyComputableRole = true
|
@scope.anyComputableRole = true
|
||||||
|
|
||||||
promise = @.loadInitialData()
|
promise = @.loadInitialData()
|
||||||
|
|
||||||
promise.then () =>
|
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(@)
|
promise.then null, @.onInitialDataError.bind(@)
|
||||||
|
|
||||||
|
@ -65,7 +68,7 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil
|
||||||
return @rs.projects.get(@scope.projectId).then (project) =>
|
return @rs.projects.get(@scope.projectId).then (project) =>
|
||||||
if not project.i_am_owner
|
if not project.i_am_owner
|
||||||
@location.path(@navUrls.resolve("permission-denied"))
|
@location.path(@navUrls.resolve("permission-denied"))
|
||||||
|
|
||||||
@scope.project = project
|
@scope.project = project
|
||||||
|
|
||||||
@scope.$emit('project:loaded', project)
|
@scope.$emit('project:loaded', project)
|
||||||
|
@ -80,7 +83,7 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil
|
||||||
return role
|
return role
|
||||||
|
|
||||||
public_permission = {
|
public_permission = {
|
||||||
"name": "External User",
|
"name": @translate.instant("ADMIN.ROLES.EXTERNAL_USER"),
|
||||||
"permissions": @scope.project.public_permissions,
|
"permissions": @scope.project.public_permissions,
|
||||||
"external_user": true
|
"external_user": true
|
||||||
}
|
}
|
||||||
|
@ -112,29 +115,28 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil
|
||||||
@scope.$broadcast("role:changed", @scope.role)
|
@scope.$broadcast("role:changed", @scope.role)
|
||||||
|
|
||||||
delete: ->
|
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 = {}
|
choices = {}
|
||||||
for role in @scope.roles
|
for role in @scope.roles
|
||||||
if role.id != @scope.role.id
|
if role.id != @scope.role.id
|
||||||
choices[role.id] = role.name
|
choices[role.id] = role.name
|
||||||
|
|
||||||
if _.keys(choices).length == 0
|
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"))
|
||||||
|
|
||||||
|
title = @translate.instant("ADMIN.ROLES.TITLE_DELETE_ROLE")
|
||||||
|
subtitle = @scope.role.name
|
||||||
|
replacement = @translate.instant("ADMIN.ROLES.REPLACEMENT_ROLE")
|
||||||
|
warning = @translate.instant("ADMIN.ROLES.WARNING_DELETE_ROLE")
|
||||||
return @confirm.askChoice(title, subtitle, choices, replacement, warning).then (response) =>
|
return @confirm.askChoice(title, subtitle, choices, replacement, warning).then (response) =>
|
||||||
promise = @repo.remove(@scope.role, {moveTo: response.selected})
|
onSuccess = =>
|
||||||
promise.then =>
|
|
||||||
@.loadProject()
|
@.loadProject()
|
||||||
@.loadRoles().finally ->
|
@.loadRoles().finally =>
|
||||||
response.finish()
|
response.finish()
|
||||||
promise.then null, =>
|
onError = =>
|
||||||
@confirm.notify('error')
|
@confirm.notify('error')
|
||||||
|
|
||||||
|
return @repo.remove(@scope.role, {moveTo: response.selected}).then onSuccess, onError
|
||||||
|
|
||||||
setComputable: debounce 2000, ->
|
setComputable: debounce 2000, ->
|
||||||
onSuccess = =>
|
onSuccess = =>
|
||||||
@confirm.notify("success")
|
@confirm.notify("success")
|
||||||
|
@ -256,14 +258,14 @@ module.directive("tgNewRole", ["$tgRepo", "$tgConfirm", NewRoleDirective])
|
||||||
|
|
||||||
|
|
||||||
# Use category-config.scss styles
|
# Use category-config.scss styles
|
||||||
RolePermissionsDirective = ($rootscope, $repo, $confirm) ->
|
RolePermissionsDirective = ($rootscope, $repo, $confirm, $compile) ->
|
||||||
resumeTemplate = _.template("""
|
resumeTemplate = _.template("""
|
||||||
<div class="resume-title"><%- category.name %></div>
|
<div class="resume-title" translate="<%- category.name %>"></div>
|
||||||
<div class="summary-role">
|
<div class="summary-role">
|
||||||
<div class="count"><%- category.activePermissions %>/<%- category.permissions.length %></div>
|
<div class="count"><%- category.activePermissions %>/<%- category.permissions.length %></div>
|
||||||
<% _.each(category.permissions, function(permission) { %>
|
<% _.each(category.permissions, function(permission) { %>
|
||||||
<div class="role-summary-single <% if(permission.active) { %>active<% } %>"
|
<div class="role-summary-single <% if(permission.active) { %>active<% } %>"
|
||||||
title="<%- permission.description %>"></div>
|
title="{{ '<%- permission.name %>' | translate }}"></div>
|
||||||
<% }) %>
|
<% }) %>
|
||||||
</div>
|
</div>
|
||||||
<div class="icon icon-arrow-bottom"></div>
|
<div class="icon icon-arrow-bottom"></div>
|
||||||
|
@ -277,12 +279,14 @@ RolePermissionsDirective = ($rootscope, $repo, $confirm) ->
|
||||||
<div class="items-container">
|
<div class="items-container">
|
||||||
<% _.each(category.permissions, function(permission) { %>
|
<% _.each(category.permissions, function(permission) { %>
|
||||||
<div class="category-item" data-id="<%- permission.key %>">
|
<div class="category-item" data-id="<%- permission.key %>">
|
||||||
<span><%- permission.description %></span>
|
<span translate="<%- permission.name %>"></span>
|
||||||
<div class="check">
|
<div class="check">
|
||||||
<input type="checkbox" <% if(!permission.editable) { %>disabled="disabled"<% } %> <% if(permission.active) { %>checked="checked"<% } %>/>
|
<input type="checkbox"
|
||||||
|
<% if(!permission.editable) { %> disabled="disabled" <% } %>
|
||||||
|
<% if(permission.active) { %> checked="checked" <% } %>/>
|
||||||
<div></div>
|
<div></div>
|
||||||
<span class="check-text check-yes">Yes</span>
|
<span class="check-text check-yes" translate="COMMON.YES"></span>
|
||||||
<span class="check-text check-no">No</span>
|
<span class="check-text check-no" translate="COMMON.NO"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% }) %>
|
<% }) %>
|
||||||
|
@ -325,58 +329,73 @@ RolePermissionsDirective = ($rootscope, $repo, $confirm) ->
|
||||||
categories = []
|
categories = []
|
||||||
|
|
||||||
milestonePermissions = [
|
milestonePermissions = [
|
||||||
{ key: "view_milestones", description: "View sprints" }
|
{ key: "view_milestones", name: "COMMON.PERMISIONS_CATEGORIES.SPRINTS.VIEW_SPRINTS"}
|
||||||
{ key: "add_milestone", description: "Add sprint" }
|
{ key: "add_milestone", name: "COMMON.PERMISIONS_CATEGORIES.SPRINTS.ADD_SPRINTS"}
|
||||||
{ key: "modify_milestone", description: "Modify sprint" }
|
{ key: "modify_milestone", name: "COMMON.PERMISIONS_CATEGORIES.SPRINTS.MODIFY_SPRINTS"}
|
||||||
{ key: "delete_milestone", description: "Delete sprint" }
|
{ key: "delete_milestone", name: "COMMON.PERMISIONS_CATEGORIES.SPRINTS.DELETE_SPRINTS"}
|
||||||
]
|
]
|
||||||
categories.push({ name: "Sprints", permissions: setActivePermissions(milestonePermissions) })
|
categories.push({
|
||||||
|
name: "COMMON.PERMISIONS_CATEGORIES.SPRINTS.NAME",
|
||||||
|
permissions: setActivePermissions(milestonePermissions)
|
||||||
|
})
|
||||||
|
|
||||||
userStoryPermissions = [
|
userStoryPermissions = [
|
||||||
{ key: "view_us", description: "View user story" }
|
{ key: "view_us", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.VIEW_USER_STORIES"}
|
||||||
{ key: "add_us", description: "Add user story" }
|
{ key: "add_us", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.ADD_USER_STORIES"}
|
||||||
{ key: "modify_us", description: "Modify user story" }
|
{ key: "modify_us", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.MODIFY_USER_STORIES"}
|
||||||
{ key: "delete_us", description: "Delete user story" }
|
{ key: "delete_us", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.DELETE_USER_STORIES"}
|
||||||
]
|
]
|
||||||
categories.push({ name: "User Stories", permissions: setActivePermissions(userStoryPermissions) })
|
categories.push({
|
||||||
|
name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.NAME",
|
||||||
|
permissions: setActivePermissions(userStoryPermissions)
|
||||||
|
})
|
||||||
|
|
||||||
taskPermissions = [
|
taskPermissions = [
|
||||||
{ key: "view_tasks", description: "View tasks" }
|
{ key: "view_tasks", name: "COMMON.PERMISIONS_CATEGORIES.TASKS.VIEW_TASKS"}
|
||||||
{ key: "add_task", description: "Add task" }
|
{ key: "add_task", name: "COMMON.PERMISIONS_CATEGORIES.TASKS.ADD_TASKS"}
|
||||||
{ key: "modify_task", description: "Modify task" }
|
{ key: "modify_task", name: "COMMON.PERMISIONS_CATEGORIES.TASKS.MODIFY_TASKS"}
|
||||||
{ key: "delete_task", description: "Delete task" }
|
{ key: "delete_task", name: "COMMON.PERMISIONS_CATEGORIES.TASKS.DELETE_TASKS"}
|
||||||
]
|
]
|
||||||
categories.push({ name: "Tasks", permissions: setActivePermissions(taskPermissions) })
|
categories.push({
|
||||||
|
name: "COMMON.PERMISIONS_CATEGORIES.TASKS.NAME" ,
|
||||||
|
permissions: setActivePermissions(taskPermissions)
|
||||||
|
})
|
||||||
|
|
||||||
issuePermissions = [
|
issuePermissions = [
|
||||||
{ key: "view_issues", description: "View issues" }
|
{ key: "view_issues", name: "COMMON.PERMISIONS_CATEGORIES.ISSUES.VIEW_ISSUES"}
|
||||||
{ key: "add_issue", description: "Add issue" }
|
{ key: "add_issue", name: "COMMON.PERMISIONS_CATEGORIES.ISSUES.ADD_ISSUES"}
|
||||||
{ key: "modify_issue", description: "Modify issue" }
|
{ key: "modify_issue", name: "COMMON.PERMISIONS_CATEGORIES.ISSUES.MODIFY_ISSUES"}
|
||||||
{ key: "delete_issue", description: "Delete issue" }
|
{ key: "delete_issue", name: "COMMON.PERMISIONS_CATEGORIES.ISSUES.DELETE_ISSUES"}
|
||||||
]
|
]
|
||||||
categories.push({ name: "Issues", permissions: setActivePermissions(issuePermissions) })
|
categories.push({
|
||||||
|
name: "COMMON.PERMISIONS_CATEGORIES.ISSUES.NAME",
|
||||||
|
permissions: setActivePermissions(issuePermissions)
|
||||||
|
})
|
||||||
|
|
||||||
wikiPermissions = [
|
wikiPermissions = [
|
||||||
{ key: "view_wiki_pages", description: "View wiki pages" }
|
{ key: "view_wiki_pages", name: "COMMON.PERMISIONS_CATEGORIES.WIKI.VIEW_WIKI_PAGES"}
|
||||||
{ key: "add_wiki_page", description: "Add wiki page" }
|
{ key: "add_wiki_page", name: "COMMON.PERMISIONS_CATEGORIES.WIKI.ADD_WIKI_PAGES"}
|
||||||
{ key: "modify_wiki_page", description: "Modify wiki page" }
|
{ key: "modify_wiki_page", name: "COMMON.PERMISIONS_CATEGORIES.WIKI.MODIFY_WIKI_PAGES"}
|
||||||
{ key: "delete_wiki_page", description: "Delete wiki page" }
|
{ key: "delete_wiki_page", name: "COMMON.PERMISIONS_CATEGORIES.WIKI.DELETE_WIKI_PAGES"}
|
||||||
{ key: "view_wiki_links", description: "View wiki links" }
|
{ key: "view_wiki_links", name: "COMMON.PERMISIONS_CATEGORIES.WIKI.VIEW_WIKI_LINKS"}
|
||||||
{ key: "add_wiki_link", description: "Add wiki link" }
|
{ key: "add_wiki_link", name: "COMMON.PERMISIONS_CATEGORIES.WIKI.ADD_WIKI_LINKS"}
|
||||||
{ key: "delete_wiki_link", description: "Delete wiki link" }
|
{ key: "delete_wiki_link", name: "COMMON.PERMISIONS_CATEGORIES.WIKI.DELETE_WIKI_LINKS"}
|
||||||
]
|
]
|
||||||
categories.push({ name: "Wiki", permissions: setActivePermissions(wikiPermissions) })
|
categories.push({
|
||||||
|
name: "COMMON.PERMISIONS_CATEGORIES.WIKI.NAME",
|
||||||
|
permissions: setActivePermissions(wikiPermissions)
|
||||||
|
})
|
||||||
|
|
||||||
return setActivePermissionsPerCategory(categories)
|
return setActivePermissionsPerCategory(categories)
|
||||||
|
|
||||||
renderResume = (element, category) ->
|
renderResume = (element, category) ->
|
||||||
element.find(".resume").html(resumeTemplate({category: category}))
|
element.find(".resume").html($compile(resumeTemplate({category: category}))($scope))
|
||||||
|
|
||||||
renderCategory = (category, index) ->
|
renderCategory = (category, index) ->
|
||||||
html = categoryTemplate({category: category, index: index})
|
html = categoryTemplate({category: category, index: index})
|
||||||
html = angular.element(html)
|
html = angular.element(html)
|
||||||
renderResume(html, category)
|
renderResume(html, category)
|
||||||
return html
|
return $compile(html)($scope)
|
||||||
|
|
||||||
renderPermissions = () ->
|
renderPermissions = () ->
|
||||||
$el.off()
|
$el.off()
|
||||||
|
@ -437,4 +456,5 @@ RolePermissionsDirective = ($rootscope, $repo, $confirm) ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgRolePermissions", ["$rootScope", "$tgRepo", "$tgConfirm", RolePermissionsDirective])
|
module.directive("tgRolePermissions", ["$rootScope", "$tgRepo", "$tgConfirm", "$compile",
|
||||||
|
RolePermissionsDirective])
|
||||||
|
|
|
@ -40,19 +40,21 @@ class WebhooksController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.
|
||||||
"$routeParams",
|
"$routeParams",
|
||||||
"$tgLocation",
|
"$tgLocation",
|
||||||
"$tgNavUrls",
|
"$tgNavUrls",
|
||||||
"$appTitle"
|
"$appTitle",
|
||||||
|
"$translate"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @repo, @rs, @params, @location, @navUrls, @appTitle) ->
|
constructor: (@scope, @repo, @rs, @params, @location, @navUrls, @appTitle, @translate) ->
|
||||||
bindMethods(@)
|
bindMethods(@)
|
||||||
|
|
||||||
@scope.sectionName = "Webhooks" #i18n
|
@scope.sectionName = "ADMIN.WEBHOOKS.SECTION_NAME"
|
||||||
@scope.project = {}
|
@scope.project = {}
|
||||||
|
|
||||||
promise = @.loadInitialData()
|
promise = @.loadInitialData()
|
||||||
|
|
||||||
promise.then () =>
|
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(@)
|
promise.then null, @.onInitialDataError.bind(@)
|
||||||
|
|
||||||
|
@ -85,17 +87,19 @@ module.controller("WebhooksController", WebhooksController)
|
||||||
## Webhook Directive
|
## Webhook Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
WebhookDirective = ($rs, $repo, $confirm, $loading) ->
|
WebhookDirective = ($rs, $repo, $confirm, $loading, $translate) ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
webhook = $scope.$eval($attrs.tgWebhook)
|
webhook = $scope.$eval($attrs.tgWebhook)
|
||||||
|
|
||||||
updateLogs = () ->
|
updateLogs = () ->
|
||||||
|
prettyDate = $translate.instant("ADMIN.WEBHOOKS.DATE")
|
||||||
|
|
||||||
$rs.webhooklogs.list(webhook.id).then (webhooklogs) =>
|
$rs.webhooklogs.list(webhook.id).then (webhooklogs) =>
|
||||||
for log in webhooklogs
|
for log in webhooklogs
|
||||||
log.validStatus = 200 <= log.status < 300
|
log.validStatus = 200 <= log.status < 300
|
||||||
log.prettySentHeaders = _.map(_.pairs(log.request_headers), ([header, value]) -> "#{header}: #{value}").join("\n")
|
log.prettySentHeaders = _.map(_.pairs(log.request_headers), ([header, value]) -> "#{header}: #{value}").join("\n")
|
||||||
log.prettySentData = JSON.stringify(log.request_data)
|
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_counter = webhooklogs.length
|
||||||
webhook.logs = webhooklogs
|
webhook.logs = webhooklogs
|
||||||
|
@ -104,10 +108,16 @@ WebhookDirective = ($rs, $repo, $confirm, $loading) ->
|
||||||
updateShowHideHistoryText = () ->
|
updateShowHideHistoryText = () ->
|
||||||
textElement = $el.find(".toggle-history")
|
textElement = $el.find(".toggle-history")
|
||||||
historyElement = textElement.parents(".single-webhook-wrapper").find(".webhooks-history")
|
historyElement = textElement.parents(".single-webhook-wrapper").find(".webhooks-history")
|
||||||
|
|
||||||
if historyElement.hasClass("open")
|
if historyElement.hasClass("open")
|
||||||
textElement.text("(Hide history)") # TODO: i18n
|
text = $translate.instant("ADMIN.WEBHOOKS.ACTION_HIDE_HISTORY")
|
||||||
|
title = $translate.instant("ADMIN.WEBHOOKS.ACTION_HIDE_HISTORY_TITLE")
|
||||||
else
|
else
|
||||||
textElement.text("(Show history)") # TODO: i18n
|
text = $translate.instant("ADMIN.WEBHOOKS.ACTION_SHOW_HISTORY")
|
||||||
|
title = $translate.instant("ADMIN.WEBHOOKS.ACTION_SHOW_HISTORY_TITLE")
|
||||||
|
|
||||||
|
textElement.text(text)
|
||||||
|
textElement.prop("title", title)
|
||||||
|
|
||||||
showVisualizationMode = () ->
|
showVisualizationMode = () ->
|
||||||
$el.find(".edition-mode").addClass("hidden")
|
$el.find(".edition-mode").addClass("hidden")
|
||||||
|
@ -161,8 +171,8 @@ WebhookDirective = ($rs, $repo, $confirm, $loading) ->
|
||||||
cancel(target)
|
cancel(target)
|
||||||
|
|
||||||
$el.on "click", ".delete-webhook", () ->
|
$el.on "click", ".delete-webhook", () ->
|
||||||
title = "Delete webhook" #TODO: i18n
|
title = $translate.instant("ADMIN.WEBHOOKS.DELETE")
|
||||||
message = "Webhook '#{webhook.name}'" #TODO: i18n
|
message = $translate.instant("ADMIN.WEBHOOKS.WEBHOOK_NAME", {name: webhook.name})
|
||||||
|
|
||||||
$confirm.askOnDelete(title, message).then (finish) =>
|
$confirm.askOnDelete(title, message).then (finish) =>
|
||||||
onSucces = ->
|
onSucces = ->
|
||||||
|
@ -203,7 +213,7 @@ WebhookDirective = ($rs, $repo, $confirm, $loading) ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgWebhook", ["$tgResources", "$tgRepo", "$tgConfirm", "$tgLoading", WebhookDirective])
|
module.directive("tgWebhook", ["$tgResources", "$tgRepo", "$tgConfirm", "$tgLoading", "$translate", WebhookDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -279,19 +289,21 @@ class GithubController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
|
||||||
"$tgRepo",
|
"$tgRepo",
|
||||||
"$tgResources",
|
"$tgResources",
|
||||||
"$routeParams",
|
"$routeParams",
|
||||||
"$appTitle"
|
"$appTitle",
|
||||||
|
"$translate"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @repo, @rs, @params, @appTitle) ->
|
constructor: (@scope, @repo, @rs, @params, @appTitle, @translate) ->
|
||||||
bindMethods(@)
|
bindMethods(@)
|
||||||
|
|
||||||
@scope.sectionName = "Github" #i18n
|
@scope.sectionName = @translate.instant("ADMIN.GITHUB.SECTION_NAME")
|
||||||
@scope.project = {}
|
@scope.project = {}
|
||||||
|
|
||||||
promise = @.loadInitialData()
|
promise = @.loadInitialData()
|
||||||
|
|
||||||
promise.then () =>
|
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(@)
|
promise.then null, @.onInitialDataError.bind(@)
|
||||||
|
|
||||||
|
@ -327,18 +339,20 @@ class GitlabController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
|
||||||
"$tgRepo",
|
"$tgRepo",
|
||||||
"$tgResources",
|
"$tgResources",
|
||||||
"$routeParams",
|
"$routeParams",
|
||||||
"$appTitle"
|
"$appTitle",
|
||||||
|
"$translate"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @repo, @rs, @params, @appTitle) ->
|
constructor: (@scope, @repo, @rs, @params, @appTitle, @translate) ->
|
||||||
bindMethods(@)
|
bindMethods(@)
|
||||||
|
|
||||||
@scope.sectionName = "Gitlab" #i18n
|
@scope.sectionName = @translate.instant("ADMIN.GITLAB.SECTION_NAME")
|
||||||
@scope.project = {}
|
@scope.project = {}
|
||||||
promise = @.loadInitialData()
|
promise = @.loadInitialData()
|
||||||
|
|
||||||
promise.then () =>
|
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(@)
|
promise.then null, @.onInitialDataError.bind(@)
|
||||||
|
|
||||||
|
@ -377,18 +391,20 @@ class BitbucketController extends mixOf(taiga.Controller, taiga.PageMixin, taiga
|
||||||
"$tgRepo",
|
"$tgRepo",
|
||||||
"$tgResources",
|
"$tgResources",
|
||||||
"$routeParams",
|
"$routeParams",
|
||||||
"$appTitle"
|
"$appTitle",
|
||||||
|
"$translate"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @repo, @rs, @params, @appTitle) ->
|
constructor: (@scope, @repo, @rs, @params, @appTitle, @translate) ->
|
||||||
bindMethods(@)
|
bindMethods(@)
|
||||||
|
|
||||||
@scope.sectionName = "Bitbucket" #i18n
|
@scope.sectionName = @translate.instant("ADMIN.BITBUCKET.SECTION_NAME")
|
||||||
@scope.project = {}
|
@scope.project = {}
|
||||||
promise = @.loadInitialData()
|
promise = @.loadInitialData()
|
||||||
|
|
||||||
promise.then () =>
|
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(@)
|
promise.then null, @.onInitialDataError.bind(@)
|
||||||
|
|
||||||
|
|
|
@ -34,11 +34,17 @@ class AuthService extends taiga.Service
|
||||||
"$tgModel",
|
"$tgModel",
|
||||||
"$tgResources",
|
"$tgResources",
|
||||||
"$tgHttp",
|
"$tgHttp",
|
||||||
"$tgUrls"]
|
"$tgUrls",
|
||||||
|
"$tgConfig",
|
||||||
|
"$translate"]
|
||||||
|
|
||||||
constructor: (@rootscope, @storage, @model, @rs, @http, @urls) ->
|
constructor: (@rootscope, @storage, @model, @rs, @http, @urls, @config, @translate) ->
|
||||||
super()
|
super()
|
||||||
|
|
||||||
|
_setLocales: ->
|
||||||
|
lang = @rootscope.user.lang || @config.get("defaultLanguage") || "en"
|
||||||
|
@translate.use(lang)
|
||||||
|
|
||||||
getUser: ->
|
getUser: ->
|
||||||
if @rootscope.user
|
if @rootscope.user
|
||||||
return @rootscope.user
|
return @rootscope.user
|
||||||
|
@ -47,16 +53,18 @@ class AuthService extends taiga.Service
|
||||||
if userData
|
if userData
|
||||||
user = @model.make_model("users", userData)
|
user = @model.make_model("users", userData)
|
||||||
@rootscope.user = user
|
@rootscope.user = user
|
||||||
|
@._setLocales()
|
||||||
return user
|
return user
|
||||||
|
|
||||||
return null
|
return null
|
||||||
|
|
||||||
setUser: (user) ->
|
setUser: (user) ->
|
||||||
@rootscope.auth = user
|
@rootscope.auth = user
|
||||||
@rootscope.$broadcast("i18n:change", user.default_language)
|
|
||||||
@storage.set("userInfo", user.getAttrs())
|
@storage.set("userInfo", user.getAttrs())
|
||||||
@rootscope.user = user
|
@rootscope.user = user
|
||||||
|
|
||||||
|
@._setLocales()
|
||||||
|
|
||||||
clear: ->
|
clear: ->
|
||||||
@rootscope.auth = null
|
@rootscope.auth = null
|
||||||
@rootscope.user = null
|
@rootscope.user = null
|
||||||
|
@ -171,7 +179,7 @@ PublicRegisterMessageDirective = ($config, $navUrls, templates) ->
|
||||||
module.directive("tgPublicRegisterMessage", ["$tgConfig", "$tgNavUrls", "$tgTemplate", PublicRegisterMessageDirective])
|
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) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
onSuccess = (response) ->
|
onSuccess = (response) ->
|
||||||
if $routeParams['next'] and $routeParams['next'] != $navUrls.resolve("login")
|
if $routeParams['next'] and $routeParams['next'] != $navUrls.resolve("login")
|
||||||
|
@ -183,8 +191,8 @@ LoginDirective = ($auth, $confirm, $location, $config, $routeParams, $navUrls, $
|
||||||
$location.path(nextUrl)
|
$location.path(nextUrl)
|
||||||
|
|
||||||
onError = (response) ->
|
onError = (response) ->
|
||||||
$confirm.notify("light-error", "According to our Oompa Loompas, your username/email
|
$confirm.notify("light-error", $translate.instant("LOGIN_FORM.ERROR_AUTH_INCORRECT"))
|
||||||
or password are incorrect.") #TODO: i18n
|
|
||||||
submit = debounce 2000, (event) =>
|
submit = debounce 2000, (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
|
@ -207,13 +215,13 @@ LoginDirective = ($auth, $confirm, $location, $config, $routeParams, $navUrls, $
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgLogin", ["$tgAuth", "$tgConfirm", "$tgLocation", "$tgConfig", "$routeParams",
|
module.directive("tgLogin", ["$tgAuth", "$tgConfirm", "$tgLocation", "$tgConfig", "$routeParams",
|
||||||
"$tgNavUrls", "$tgEvents", LoginDirective])
|
"$tgNavUrls", "$tgEvents", "$translate", LoginDirective])
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Register Directive
|
## Register Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
RegisterDirective = ($auth, $confirm, $location, $navUrls, $config, $analytics) ->
|
RegisterDirective = ($auth, $confirm, $location, $navUrls, $config, $analytics, $translate) ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
if not $config.get("publicRegisterEnabled")
|
if not $config.get("publicRegisterEnabled")
|
||||||
$location.path($navUrls.resolve("not-found"))
|
$location.path($navUrls.resolve("not-found"))
|
||||||
|
@ -224,12 +232,15 @@ RegisterDirective = ($auth, $confirm, $location, $navUrls, $config, $analytics)
|
||||||
|
|
||||||
onSuccessSubmit = (response) ->
|
onSuccessSubmit = (response) ->
|
||||||
$analytics.trackEvent("auth", "register", "user registration", 1)
|
$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"))
|
$location.path($navUrls.resolve("home"))
|
||||||
|
|
||||||
onErrorSubmit = (response) ->
|
onErrorSubmit = (response) ->
|
||||||
if response.data._error_message?
|
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)
|
form.setErrors(response.data)
|
||||||
|
|
||||||
|
@ -247,25 +258,27 @@ RegisterDirective = ($auth, $confirm, $location, $navUrls, $config, $analytics)
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgRegister", ["$tgAuth", "$tgConfirm", "$tgLocation", "$tgNavUrls", "$tgConfig",
|
module.directive("tgRegister", ["$tgAuth", "$tgConfirm", "$tgLocation", "$tgNavUrls", "$tgConfig",
|
||||||
"$tgAnalytics", RegisterDirective])
|
"$tgAnalytics", "$translate", RegisterDirective])
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Forgot Password Directive
|
## Forgot Password Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
ForgotPasswordDirective = ($auth, $confirm, $location, $navUrls) ->
|
ForgotPasswordDirective = ($auth, $confirm, $location, $navUrls, $translate) ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
$scope.data = {}
|
$scope.data = {}
|
||||||
form = $el.find("form").checksley()
|
form = $el.find("form").checksley()
|
||||||
|
|
||||||
onSuccessSubmit = (response) ->
|
onSuccessSubmit = (response) ->
|
||||||
$location.path($navUrls.resolve("login"))
|
$location.path($navUrls.resolve("login"))
|
||||||
$confirm.success("<strong>Check your inbox!</strong><br />
|
|
||||||
We have sent you an email with the instructions to set a new password") #TODO: i18n
|
text = $translate.instant("FORGOT_PASSWORD_FORM.SUCCESS")
|
||||||
|
$confirm.success(text)
|
||||||
|
|
||||||
onErrorSubmit = (response) ->
|
onErrorSubmit = (response) ->
|
||||||
$confirm.notify("light-error", "According to our Oompa Loompas,
|
text = $translate.instant("FORGOT_PASSWORD_FORM.ERROR")
|
||||||
your are not registered yet.") #TODO: i18n
|
|
||||||
|
$confirm.notify("light-error", text)
|
||||||
|
|
||||||
submit = debounce 2000, (event) =>
|
submit = debounce 2000, (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@ -280,14 +293,14 @@ ForgotPasswordDirective = ($auth, $confirm, $location, $navUrls) ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgForgotPassword", ["$tgAuth", "$tgConfirm", "$tgLocation", "$tgNavUrls",
|
module.directive("tgForgotPassword", ["$tgAuth", "$tgConfirm", "$tgLocation", "$tgNavUrls", "$translate",
|
||||||
ForgotPasswordDirective])
|
ForgotPasswordDirective])
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Change Password from Recovery Directive
|
## Change Password from Recovery Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
ChangePasswordFromRecoveryDirective = ($auth, $confirm, $location, $params, $navUrls) ->
|
ChangePasswordFromRecoveryDirective = ($auth, $confirm, $location, $params, $navUrls, $translate) ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
$scope.data = {}
|
$scope.data = {}
|
||||||
|
|
||||||
|
@ -301,12 +314,15 @@ ChangePasswordFromRecoveryDirective = ($auth, $confirm, $location, $params, $nav
|
||||||
|
|
||||||
onSuccessSubmit = (response) ->
|
onSuccessSubmit = (response) ->
|
||||||
$location.path($navUrls.resolve("login"))
|
$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) ->
|
onErrorSubmit = (response) ->
|
||||||
$confirm.notify("light-error", "One of our Oompa Loompas say
|
text = $translate.instant("COMMON.GENERIC_ERROR", {error: response.data._error_message})
|
||||||
'#{response.data._error_message}'.") #TODO: i18n
|
|
||||||
|
$confirm.notify("light-error", text)
|
||||||
|
|
||||||
submit = debounce 2000, (event) =>
|
submit = debounce 2000, (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@ -322,13 +338,13 @@ ChangePasswordFromRecoveryDirective = ($auth, $confirm, $location, $params, $nav
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgChangePasswordFromRecovery", ["$tgAuth", "$tgConfirm", "$tgLocation", "$routeParams",
|
module.directive("tgChangePasswordFromRecovery", ["$tgAuth", "$tgConfirm", "$tgLocation", "$routeParams",
|
||||||
"$tgNavUrls", ChangePasswordFromRecoveryDirective])
|
"$tgNavUrls", "$translate", ChangePasswordFromRecoveryDirective])
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Invitation
|
## Invitation
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics) ->
|
InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics, $translate) ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
token = $params.token
|
token = $params.token
|
||||||
|
|
||||||
|
@ -338,8 +354,9 @@ InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics
|
||||||
|
|
||||||
promise.then null, (response) ->
|
promise.then null, (response) ->
|
||||||
$location.path($navUrls.resolve("login"))
|
$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
|
# Login form
|
||||||
$scope.dataLogin = {token: token}
|
$scope.dataLogin = {token: token}
|
||||||
|
@ -348,12 +365,14 @@ InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics
|
||||||
onSuccessSubmitLogin = (response) ->
|
onSuccessSubmitLogin = (response) ->
|
||||||
$analytics.trackEvent("auth", "invitationAccept", "invitation accept with existing user", 1)
|
$analytics.trackEvent("auth", "invitationAccept", "invitation accept with existing user", 1)
|
||||||
$location.path($navUrls.resolve("project", {project: $scope.invitation.project_slug}))
|
$location.path($navUrls.resolve("project", {project: $scope.invitation.project_slug}))
|
||||||
$confirm.notify("success", "You've successfully joined this project",
|
text = $translate.instant("INVITATION_LOGIN_FORM.SUCCESS", {"project_name": $scope.invitation.project_name})
|
||||||
"Welcome to #{_.escape($scope.invitation.project_name)}")
|
|
||||||
|
$confirm.notify("success", text)
|
||||||
|
|
||||||
onErrorSubmitLogin = (response) ->
|
onErrorSubmitLogin = (response) ->
|
||||||
$confirm.notify("light-error", "According to our Oompa Loompas, your are not registered yet or
|
text = $translate.instant("INVITATION_LOGIN_FORM.ERROR")
|
||||||
typed an invalid password.") #TODO: i18n
|
|
||||||
|
$confirm.notify("light-error", text)
|
||||||
|
|
||||||
submitLogin = debounce 2000, (event) =>
|
submitLogin = debounce 2000, (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@ -378,8 +397,9 @@ InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics
|
||||||
"Welcome to #{_.escape($scope.invitation.project_name)}")
|
"Welcome to #{_.escape($scope.invitation.project_name)}")
|
||||||
|
|
||||||
onErrorSubmitRegister = (response) ->
|
onErrorSubmitRegister = (response) ->
|
||||||
$confirm.notify("light-error", "According to our Oompa Loompas, that
|
text = $translate.instant("LOGIN_FORM.ERROR_AUTH_INCORRECT")
|
||||||
username or email is already in use.") #TODO: i18n
|
|
||||||
|
$confirm.notify("light-error", text)
|
||||||
|
|
||||||
submitRegister = debounce 2000, (event) =>
|
submitRegister = debounce 2000, (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@ -396,13 +416,13 @@ InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgInvitation", ["$tgAuth", "$tgConfirm", "$tgLocation", "$routeParams",
|
module.directive("tgInvitation", ["$tgAuth", "$tgConfirm", "$tgLocation", "$routeParams",
|
||||||
"$tgNavUrls", "$tgAnalytics", InvitationDirective])
|
"$tgNavUrls", "$tgAnalytics", "$translate", InvitationDirective])
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Change Email
|
## Change Email
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
ChangeEmailDirective = ($repo, $model, $auth, $confirm, $location, $params, $navUrls) ->
|
ChangeEmailDirective = ($repo, $model, $auth, $confirm, $location, $params, $navUrls, $translate) ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
$scope.data = {}
|
$scope.data = {}
|
||||||
$scope.data.email_token = $params.email_token
|
$scope.data.email_token = $params.email_token
|
||||||
|
@ -412,11 +432,14 @@ ChangeEmailDirective = ($repo, $model, $auth, $confirm, $location, $params, $nav
|
||||||
$repo.queryOne("users", $auth.getUser().id).then (data) =>
|
$repo.queryOne("users", $auth.getUser().id).then (data) =>
|
||||||
$auth.setUser(data)
|
$auth.setUser(data)
|
||||||
$location.path($navUrls.resolve("home"))
|
$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) ->
|
onErrorSubmit = (response) ->
|
||||||
$confirm.notify("error", "One of our Oompa Loompas says
|
text = $translate.instant("COMMON.GENERIC_ERROR", {error: response.data._error_message})
|
||||||
'#{response.data._error_message}'.") #TODO: i18n
|
|
||||||
|
$confirm.notify("light-error", text)
|
||||||
|
|
||||||
submit = ->
|
submit = ->
|
||||||
if not form.validate()
|
if not form.validate()
|
||||||
|
@ -436,7 +459,7 @@ ChangeEmailDirective = ($repo, $model, $auth, $confirm, $location, $params, $nav
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgChangeEmail", ["$tgRepo", "$tgModel", "$tgAuth", "$tgConfirm", "$tgLocation", "$routeParams",
|
module.directive("tgChangeEmail", ["$tgRepo", "$tgModel", "$tgAuth", "$tgConfirm", "$tgLocation", "$routeParams",
|
||||||
"$tgNavUrls", ChangeEmailDirective])
|
"$tgNavUrls", "$translate", ChangeEmailDirective])
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Cancel account
|
## Cancel account
|
||||||
|
@ -451,11 +474,15 @@ CancelAccountDirective = ($repo, $model, $auth, $confirm, $location, $params, $n
|
||||||
onSuccessSubmit = (response) ->
|
onSuccessSubmit = (response) ->
|
||||||
$auth.logout()
|
$auth.logout()
|
||||||
$location.path($navUrls.resolve("home"))
|
$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) ->
|
onErrorSubmit = (response) ->
|
||||||
$confirm.notify("error", "One of our Oompa Loompas says
|
text = $translate.instant("COMMON.GENERIC_ERROR", {error: response.data._error_message})
|
||||||
'#{response.data._error_message}'.") #TODO: i18n
|
|
||||||
|
$confirm.notify("error", text)
|
||||||
|
|
||||||
submit = debounce 2000, (event) =>
|
submit = debounce 2000, (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
|
@ -116,6 +116,9 @@ BacklogFiltersDirective = ($log, $location, $templates) ->
|
||||||
$scope.$on "filters:loaded", (ctx, filters) ->
|
$scope.$on "filters:loaded", (ctx, filters) ->
|
||||||
initializeSelectedFilters(filters)
|
initializeSelectedFilters(filters)
|
||||||
|
|
||||||
|
$scope.$on "filters:update", (ctx, filters) ->
|
||||||
|
renderFilters(filters)
|
||||||
|
|
||||||
## Dom Event Handlers
|
## Dom Event Handlers
|
||||||
$el.on "click", ".filters-cats > ul > li > a", (event) ->
|
$el.on "click", ".filters-cats > ul > li > a", (event) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
|
@ -29,7 +29,7 @@ module = angular.module("taigaBacklog")
|
||||||
## Creare/Edit Sprint Lightbox Directive
|
## Creare/Edit Sprint Lightbox Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading) ->
|
CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading, $translate) ->
|
||||||
link = ($scope, $el, attrs) ->
|
link = ($scope, $el, attrs) ->
|
||||||
hasErrors = false
|
hasErrors = false
|
||||||
createSprint = true
|
createSprint = true
|
||||||
|
@ -43,8 +43,10 @@ CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading)
|
||||||
|
|
||||||
submit = debounce 2000, (event) =>
|
submit = debounce 2000, (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
target = angular.element(event.currentTarget)
|
target = angular.element(event.currentTarget)
|
||||||
|
prettyDate = $translate.instant("COMMON.PICKERDATE.FORMAT")
|
||||||
|
|
||||||
|
submitButton = $el.find(".submit-button")
|
||||||
form = $el.find("form").checksley()
|
form = $el.find("form").checksley()
|
||||||
|
|
||||||
if not form.validate()
|
if not form.validate()
|
||||||
|
@ -57,13 +59,15 @@ CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading)
|
||||||
broadcastEvent = null
|
broadcastEvent = null
|
||||||
|
|
||||||
if createSprint
|
if createSprint
|
||||||
newSprint.estimated_start = moment(newSprint.estimated_start).format("YYYY-MM-DD")
|
newSprint.estimated_start = moment(newSprint.estimated_start, prettyDate).format("YYYY-MM-DD")
|
||||||
newSprint.estimated_finish = moment(newSprint.estimated_finish).format("YYYY-MM-DD")
|
newSprint.estimated_finish = moment(newSprint.estimated_finish,prettyDate).format("YYYY-MM-DD")
|
||||||
promise = $repo.create("milestones", newSprint)
|
promise = $repo.create("milestones", newSprint)
|
||||||
broadcastEvent = "sprintform:create:success"
|
broadcastEvent = "sprintform:create:success"
|
||||||
else
|
else
|
||||||
newSprint.setAttr("estimated_start", moment(newSprint.estimated_start).format("YYYY-MM-DD"))
|
newSprint.setAttr("estimated_start",
|
||||||
newSprint.setAttr("estimated_finish", moment(newSprint.estimated_finish).format("YYYY-MM-DD"))
|
moment(newSprint.estimated_start, prettyDate).format("YYYY-MM-DD"))
|
||||||
|
newSprint.setAttr("estimated_finish",
|
||||||
|
moment(newSprint.estimated_finish, prettyDate).format("YYYY-MM-DD"))
|
||||||
promise = $repo.save(newSprint)
|
promise = $repo.save(newSprint)
|
||||||
broadcastEvent = "sprintform:edit:success"
|
broadcastEvent = "sprintform:edit:success"
|
||||||
|
|
||||||
|
@ -86,8 +90,7 @@ CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading)
|
||||||
$confirm.notify("light-error", data.__all__[0])
|
$confirm.notify("light-error", data.__all__[0])
|
||||||
|
|
||||||
remove = ->
|
remove = ->
|
||||||
#TODO: i18n
|
title = $translate.instant("LIGHTBOX.DELETE_SPRINT.TITLE")
|
||||||
title = "Delete sprint"
|
|
||||||
message = $scope.sprint.name
|
message = $scope.sprint.name
|
||||||
|
|
||||||
$confirm.askOnDelete(title, message).then (finish) =>
|
$confirm.askOnDelete(title, message).then (finish) =>
|
||||||
|
@ -107,6 +110,7 @@ CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading)
|
||||||
form.reset()
|
form.reset()
|
||||||
|
|
||||||
createSprint = true
|
createSprint = true
|
||||||
|
prettyDate = $translate.instant("COMMON.PICKERDATE.FORMAT")
|
||||||
$scope.sprint.project = projectId
|
$scope.sprint.project = projectId
|
||||||
$scope.sprint.name = null
|
$scope.sprint.name = null
|
||||||
$scope.sprint.slug = null
|
$scope.sprint.slug = null
|
||||||
|
@ -118,36 +122,50 @@ CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading)
|
||||||
estimatedStart = moment($scope.sprint.estimated_start)
|
estimatedStart = moment($scope.sprint.estimated_start)
|
||||||
else if lastSprint?
|
else if lastSprint?
|
||||||
estimatedStart = moment(lastSprint.estimated_finish)
|
estimatedStart = moment(lastSprint.estimated_finish)
|
||||||
$scope.sprint.estimated_start = estimatedStart.format("DD MMM YYYY")
|
$scope.sprint.estimated_start = estimatedStart.format(prettyDate)
|
||||||
|
|
||||||
estimatedFinish = moment().add(2, "weeks")
|
estimatedFinish = moment().add(2, "weeks")
|
||||||
if $scope.sprint.estimated_finish
|
if $scope.sprint.estimated_finish
|
||||||
estimatedFinish = moment($scope.sprint.estimated_finish)
|
estimatedFinish = moment($scope.sprint.estimated_finish)
|
||||||
else if lastSprint?
|
else if lastSprint?
|
||||||
estimatedFinish = moment(lastSprint.estimated_finish).add(2, "weeks")
|
estimatedFinish = moment(lastSprint.estimated_finish).add(2, "weeks")
|
||||||
$scope.sprint.estimated_finish = estimatedFinish.format("DD MMM YYYY")
|
$scope.sprint.estimated_finish = estimatedFinish.format(prettyDate)
|
||||||
|
|
||||||
lastSprintNameDom = $el.find(".last-sprint-name")
|
lastSprintNameDom = $el.find(".last-sprint-name")
|
||||||
if lastSprint?.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(".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)
|
lightboxService.open($el)
|
||||||
$el.find(".sprint-name").focus()
|
$el.find(".sprint-name").focus()
|
||||||
$el.find(".last-sprint-name").removeClass("disappear")
|
$el.find(".last-sprint-name").removeClass("disappear")
|
||||||
|
|
||||||
$scope.$on "sprintform:edit", (ctx, sprint) ->
|
$scope.$on "sprintform:edit", (ctx, sprint) ->
|
||||||
createSprint = false
|
createSprint = false
|
||||||
|
prettyDate = $translate.instant("COMMON.PICKERDATE.FORMAT")
|
||||||
|
|
||||||
$scope.$apply ->
|
$scope.$apply ->
|
||||||
$scope.sprint = sprint
|
$scope.sprint = sprint
|
||||||
$scope.sprint.estimated_start = moment($scope.sprint.estimated_start).format("DD MMM YYYY")
|
$scope.sprint.estimated_start = moment($scope.sprint.estimated_start).format(prettyDate)
|
||||||
$scope.sprint.estimated_finish = moment($scope.sprint.estimated_finish).format("DD MMM YYYY")
|
$scope.sprint.estimated_finish = moment($scope.sprint.estimated_finish).format(prettyDate)
|
||||||
|
|
||||||
$el.find(".delete-sprint").removeClass("hidden")
|
$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)
|
lightboxService.open($el)
|
||||||
$el.find(".sprint-name").focus().select()
|
$el.find(".sprint-name").focus().select()
|
||||||
$el.find(".last-sprint-name").addClass("disappear")
|
$el.find(".last-sprint-name").addClass("disappear")
|
||||||
|
@ -158,8 +176,6 @@ CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading)
|
||||||
else
|
else
|
||||||
$el.find(".last-sprint-name").removeClass("disappear")
|
$el.find(".last-sprint-name").removeClass("disappear")
|
||||||
|
|
||||||
submitButton = $el.find(".submit-button")
|
|
||||||
|
|
||||||
$el.on "submit", "form", submit
|
$el.on "submit", "form", submit
|
||||||
|
|
||||||
$el.on "click", ".delete-sprint .icon-delete", (event) ->
|
$el.on "click", ".delete-sprint .icon-delete", (event) ->
|
||||||
|
@ -178,6 +194,7 @@ module.directive("tgLbCreateEditSprint", [
|
||||||
"$tgResources",
|
"$tgResources",
|
||||||
"$rootScope",
|
"$rootScope",
|
||||||
"lightboxService"
|
"lightboxService"
|
||||||
"$tgLoading"
|
"$tgLoading",
|
||||||
|
"$translate",
|
||||||
CreateEditSprint
|
CreateEditSprint
|
||||||
])
|
])
|
||||||
|
|
|
@ -49,14 +49,15 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
"$tgNavUrls",
|
"$tgNavUrls",
|
||||||
"$tgEvents",
|
"$tgEvents",
|
||||||
"$tgAnalytics",
|
"$tgAnalytics",
|
||||||
"tgLoader"
|
"tgLoader",
|
||||||
|
"$translate"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q,
|
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q,
|
||||||
@location, @appTitle, @navUrls, @events, @analytics, tgLoader) ->
|
@location, @appTitle, @navUrls, @events, @analytics, tgLoader, @translate) ->
|
||||||
bindMethods(@)
|
bindMethods(@)
|
||||||
|
|
||||||
@scope.sectionName = "Backlog"
|
@scope.sectionName = @translate.instant("BACKLOG.SECTION_NAME")
|
||||||
@showTags = false
|
@showTags = false
|
||||||
@activeFilters = false
|
@activeFilters = false
|
||||||
|
|
||||||
|
@ -439,12 +440,16 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
return _.pick(@location.search(), "statuses", "tags", "q")
|
return _.pick(@location.search(), "statuses", "tags", "q")
|
||||||
|
|
||||||
generateFilters: ->
|
generateFilters: ->
|
||||||
|
urlfilters = @.getUrlFilters()
|
||||||
@scope.filters = {}
|
@scope.filters = {}
|
||||||
|
|
||||||
#tags
|
#tags
|
||||||
plainTags = _.flatten(_.filter(_.map(@scope.visibleUserstories, "tags")))
|
plainTags = _.flatten(_.filter(_.map(@scope.visibleUserstories, "tags")))
|
||||||
plainTags.sort()
|
plainTags.sort()
|
||||||
|
|
||||||
|
if plainTags.length == 0 and urlfilters["tags"]
|
||||||
|
plainTags.push(urlfilters["tags"])
|
||||||
|
|
||||||
@scope.filters.tags = _.map _.countBy(plainTags), (v, k) =>
|
@scope.filters.tags = _.map _.countBy(plainTags), (v, k) =>
|
||||||
obj = {
|
obj = {
|
||||||
id: k,
|
id: k,
|
||||||
|
@ -466,6 +471,9 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
if status
|
if status
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
if plainStatuses.length == 0 and urlfilters["statuses"]
|
||||||
|
plainStatuses.push(urlfilters["statuses"])
|
||||||
|
|
||||||
@scope.filters.statuses = _.map _.countBy(plainStatuses), (v, k) =>
|
@scope.filters.statuses = _.map _.countBy(plainStatuses), (v, k) =>
|
||||||
obj = {
|
obj = {
|
||||||
id: k,
|
id: k,
|
||||||
|
@ -491,12 +499,19 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
|
|
||||||
## Template actions
|
## Template actions
|
||||||
|
|
||||||
|
updateUserStoryStatus: () ->
|
||||||
|
@.setSearchDataFilters()
|
||||||
|
@.filterVisibleUserstories()
|
||||||
|
@.generateFilters()
|
||||||
|
@rootscope.$broadcast("filters:update", @scope.filters['statuses'])
|
||||||
|
@.loadProjectStats()
|
||||||
|
|
||||||
editUserStory: (us) ->
|
editUserStory: (us) ->
|
||||||
@rootscope.$broadcast("usform:edit", us)
|
@rootscope.$broadcast("usform:edit", us)
|
||||||
|
|
||||||
deleteUserStory: (us) ->
|
deleteUserStory: (us) ->
|
||||||
#TODO: i18n
|
title = @translate.instant("US.TITLE_DELETE_ACTION")
|
||||||
title = "Delete User Story"
|
|
||||||
message = us.subject
|
message = us.subject
|
||||||
|
|
||||||
@confirm.askOnDelete(title, message).then (finish) =>
|
@confirm.askOnDelete(title, message).then (finish) =>
|
||||||
|
@ -527,12 +542,11 @@ module.controller("BacklogController", BacklogController)
|
||||||
## Backlog Directive
|
## Backlog Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
BacklogDirective = ($repo, $rootscope) ->
|
BacklogDirective = ($repo, $rootscope, $translate) ->
|
||||||
## Doom line Link
|
## Doom line Link
|
||||||
doomLineTemplate = _.template("""
|
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) ->
|
linkDoomLine = ($scope, $el, $attrs, $ctrl) ->
|
||||||
reloadDoomLine = ->
|
reloadDoomLine = ->
|
||||||
|
@ -559,7 +573,8 @@ BacklogDirective = ($repo, $rootscope) ->
|
||||||
$el.find(".doom-line").remove()
|
$el.find(".doom-line").remove()
|
||||||
|
|
||||||
addDoomLineDom = (element) ->
|
addDoomLineDom = (element) ->
|
||||||
$(element).before(doomLineTemplate({}))
|
text = $translate.instant("BACKLOG.DOOMLINE")
|
||||||
|
$(element).before(doomLineTemplate({"text": text}))
|
||||||
|
|
||||||
getUsItems = ->
|
getUsItems = ->
|
||||||
rowElements = $el.find('.backlog-table-body .us-item-row')
|
rowElements = $el.find('.backlog-table-body .us-item-row')
|
||||||
|
@ -629,10 +644,14 @@ BacklogDirective = ($repo, $rootscope) ->
|
||||||
|
|
||||||
if $ctrl.showTags
|
if $ctrl.showTags
|
||||||
elm.addClass("active")
|
elm.addClass("active")
|
||||||
elm.find(".text").text("Hide Tags") # TODO: i18n
|
|
||||||
|
text = $translate.instant("BACKLOG.TAGS.HIDE")
|
||||||
|
elm.find(".text").text(text)
|
||||||
else
|
else
|
||||||
elm.removeClass("active")
|
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) ->
|
showHideFilter = ($scope, $el, $ctrl) ->
|
||||||
sidebar = $el.find("sidebar.filters-bar")
|
sidebar = $el.find("sidebar.filters-bar")
|
||||||
|
@ -646,7 +665,10 @@ BacklogDirective = ($repo, $rootscope) ->
|
||||||
sidebar.toggleClass("active")
|
sidebar.toggleClass("active")
|
||||||
target.toggleClass("active")
|
target.toggleClass("active")
|
||||||
|
|
||||||
toggleText(target.find(".text"), ["Remove Filters", "Show Filters"]) # TODO: i18n
|
hideText = $translate.instant("BACKLOG.FILTERS.HIDE")
|
||||||
|
showText = $translate.instant("BACKLOG.FILTERS.SHOW")
|
||||||
|
|
||||||
|
toggleText(target.find(".text"), [hideText, showText])
|
||||||
|
|
||||||
if !sidebar.hasClass("active")
|
if !sidebar.hasClass("active")
|
||||||
$ctrl.resetFilters()
|
$ctrl.resetFilters()
|
||||||
|
@ -687,14 +709,13 @@ BacklogDirective = ($repo, $rootscope) ->
|
||||||
return {link: link}
|
return {link: link}
|
||||||
|
|
||||||
|
|
||||||
module.directive("tgBacklog", ["$tgRepo", "$rootScope", BacklogDirective])
|
module.directive("tgBacklog", ["$tgRepo", "$rootScope", "$translate", BacklogDirective])
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## User story points directive
|
## User story points directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
UsRolePointsSelectorDirective = ($rootscope, $template) ->
|
UsRolePointsSelectorDirective = ($rootscope, $template, $compile, $translate) ->
|
||||||
#TODO: i18n
|
|
||||||
selectionTemplate = $template.get("backlog/us-role-points-popover.html", true)
|
selectionTemplate = $template.get("backlog/us-role-points-popover.html", true)
|
||||||
|
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
|
@ -704,7 +725,7 @@ UsRolePointsSelectorDirective = ($rootscope, $template) ->
|
||||||
numberOfRoles = _.size(roles)
|
numberOfRoles = _.size(roles)
|
||||||
|
|
||||||
if numberOfRoles > 1
|
if numberOfRoles > 1
|
||||||
$el.append(selectionTemplate({"roles":roles}))
|
$el.append($compile(selectionTemplate({"roles": roles}))($scope))
|
||||||
else
|
else
|
||||||
$el.find(".icon-arrow-bottom").remove()
|
$el.find(".icon-arrow-bottom").remove()
|
||||||
$el.find(".header-points").addClass("not-clickable")
|
$el.find(".header-points").addClass("not-clickable")
|
||||||
|
@ -715,7 +736,9 @@ UsRolePointsSelectorDirective = ($rootscope, $template) ->
|
||||||
|
|
||||||
$scope.$on "uspoints:clear-selection", (ctx, roleId) ->
|
$scope.$on "uspoints:clear-selection", (ctx, roleId) ->
|
||||||
$el.find(".popover").popover().close()
|
$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
|
# Dom Event Handlers
|
||||||
$el.on "click", (event) ->
|
$el.on "click", (event) ->
|
||||||
|
@ -743,7 +766,7 @@ UsRolePointsSelectorDirective = ($rootscope, $template) ->
|
||||||
|
|
||||||
return {link: link}
|
return {link: link}
|
||||||
|
|
||||||
module.directive("tgUsRolePointsSelector", ["$rootScope", "$tgTemplate", UsRolePointsSelectorDirective])
|
module.directive("tgUsRolePointsSelector", ["$rootScope", "$tgTemplate", "$compile", UsRolePointsSelectorDirective])
|
||||||
|
|
||||||
|
|
||||||
UsPointsDirective = ($tgEstimationsService, $repo, $tgTemplate) ->
|
UsPointsDirective = ($tgEstimationsService, $repo, $tgTemplate) ->
|
||||||
|
@ -848,11 +871,12 @@ UsPointsDirective = ($tgEstimationsService, $repo, $tgTemplate) ->
|
||||||
|
|
||||||
module.directive("tgBacklogUsPoints", ["$tgEstimationsService", "$tgRepo", "$tgTemplate", UsPointsDirective])
|
module.directive("tgBacklogUsPoints", ["$tgEstimationsService", "$tgRepo", "$tgTemplate", UsPointsDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Burndown graph directive
|
## Burndown graph directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
tgBacklogGraphDirective = ->
|
BurndownBacklogGraphDirective = ($translate) ->
|
||||||
redrawChart = (element, dataToDraw) ->
|
redrawChart = (element, dataToDraw) ->
|
||||||
width = element.width()
|
width = element.width()
|
||||||
element.height(width/6)
|
element.height(width/6)
|
||||||
|
@ -908,13 +932,20 @@ tgBacklogGraphDirective = ->
|
||||||
}
|
}
|
||||||
xaxis: {
|
xaxis: {
|
||||||
ticks: dataToDraw.milestones.length
|
ticks: dataToDraw.milestones.length
|
||||||
axisLabel: "Sprints"
|
axisLabel: $translate.instant("BACKLOG.CHART.XAXIS_LABEL"),
|
||||||
axisLabelUseCanvas: true
|
axisLabelUseCanvas: true
|
||||||
axisLabelFontSizePixels: 14
|
axisLabelFontSizePixels: 12
|
||||||
axisLabelFontFamily: "Verdana, Arial, Helvetica, Tahoma, sans-serif"
|
axisLabelFontFamily: "Verdana, Arial, Helvetica, Tahoma, sans-serif"
|
||||||
axisLabelPadding: 15
|
axisLabelPadding: 5
|
||||||
tickFormatter: (val, axis) -> ""
|
tickFormatter: (val, axis) -> ""
|
||||||
}
|
}
|
||||||
|
yaxis: {
|
||||||
|
axisLabel: $translate.instant("BACKLOG.CHART.YAXIS_LABEL"),
|
||||||
|
axisLabelUseCanvas: true
|
||||||
|
axisLabelFontSizePixels: 12
|
||||||
|
axisLabelFontFamily: "Verdana, Arial, Helvetica, Tahoma, sans-serif"
|
||||||
|
axisLabelPadding: 5
|
||||||
|
}
|
||||||
series: {
|
series: {
|
||||||
shadowSize: 0
|
shadowSize: 0
|
||||||
lines: {
|
lines: {
|
||||||
|
@ -932,18 +963,18 @@ tgBacklogGraphDirective = ->
|
||||||
tooltip: true
|
tooltip: true
|
||||||
tooltipOpts: {
|
tooltipOpts: {
|
||||||
content: (label, xval, yval, flotItem) ->
|
content: (label, xval, yval, flotItem) ->
|
||||||
#TODO: i18n
|
|
||||||
if flotItem.seriesIndex == 1
|
if flotItem.seriesIndex == 1
|
||||||
return "Optimal pending points for sprint #{xval} should be #{yval}"
|
ctx = {xval: xval, yval: yval}
|
||||||
|
return $translate.instant("BACKLOG.CHART.OPTIMAL", ctx)
|
||||||
else if flotItem.seriesIndex == 2
|
else if flotItem.seriesIndex == 2
|
||||||
return "Real pending points for sprint #{xval} is #{yval}"
|
ctx = {xval: xval, yval: yval}
|
||||||
|
return $translate.instant("BACKLOG.CHART.REAL", ctx)
|
||||||
else if flotItem.seriesIndex == 3
|
else if flotItem.seriesIndex == 3
|
||||||
return "Incremented points by team requirements for sprint #{xval} is #{Math.abs(yval)}"
|
ctx = {xval: xval, yval: Math.abs(yval)}
|
||||||
|
return $translate.instant("BACKLOG.CHART.INCREMENT_TEAM", ctx)
|
||||||
else
|
else
|
||||||
return "Incremented points by client requirements for sprint #{xval} is #{Math.abs(yval)}"
|
ctx = {xval: xval, yval: Math.abs(yval)}
|
||||||
|
return $translate.instant("BACKLOG.CHART.INCREMENT_CLIENT", ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -965,8 +996,7 @@ tgBacklogGraphDirective = ->
|
||||||
|
|
||||||
return {link: link}
|
return {link: link}
|
||||||
|
|
||||||
|
module.directive("tgBurndownBacklogGraph", ["$translate", BurndownBacklogGraphDirective])
|
||||||
module.directive("tgGmBacklogGraph", tgBacklogGraphDirective)
|
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
|
@ -39,7 +39,7 @@ deleteElement = (el) ->
|
||||||
el.off()
|
el.off()
|
||||||
el.remove()
|
el.remove()
|
||||||
|
|
||||||
BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm) ->
|
BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm, $translate) ->
|
||||||
# Notes about jquery bug:
|
# Notes about jquery bug:
|
||||||
# http://stackoverflow.com/questions/5791886/jquery-draggable-shows-
|
# http://stackoverflow.com/questions/5791886/jquery-draggable-shows-
|
||||||
# helper-in-wrong-place-when-scrolled-down-page
|
# helper-in-wrong-place-when-scrolled-down-page
|
||||||
|
@ -54,7 +54,7 @@ BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm) ->
|
||||||
return
|
return
|
||||||
|
|
||||||
filterError = ->
|
filterError = ->
|
||||||
text = "You can't drop on backlog when filters are open"
|
text = $translate.instant("BACKLOG.SORTABLE_FILTER_ERROR")
|
||||||
$tgConfirm.notify("error", text)
|
$tgConfirm.notify("error", text)
|
||||||
|
|
||||||
$el.sortable({
|
$el.sortable({
|
||||||
|
@ -215,6 +215,7 @@ module.directive("tgBacklogSortable", [
|
||||||
"$tgResources",
|
"$tgResources",
|
||||||
"$rootScope",
|
"$rootScope",
|
||||||
"$tgConfirm",
|
"$tgConfirm",
|
||||||
|
"$translate",
|
||||||
BacklogSortableDirective
|
BacklogSortableDirective
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
|
@ -85,10 +85,12 @@ module.directive("tgBacklogSprint", ["$tgRepo", "$rootScope", BacklogSprintDirec
|
||||||
## Sprint Header Directive
|
## Sprint Header Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
BacklogSprintHeaderDirective = ($navUrls, $template) ->
|
BacklogSprintHeaderDirective = ($navUrls, $template, $compile, $translate) ->
|
||||||
template = $template.get("backlog/sprint-header.html", true)
|
template = $template.get("backlog/sprint-header.html")
|
||||||
|
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
|
prettyDate = $translate.instant("BACKLOG.SPRINTS.DATE")
|
||||||
|
|
||||||
isEditable = ->
|
isEditable = ->
|
||||||
return $scope.project.my_permissions.indexOf("modify_milestone") != -1
|
return $scope.project.my_permissions.indexOf("modify_milestone") != -1
|
||||||
|
|
||||||
|
@ -99,8 +101,8 @@ BacklogSprintHeaderDirective = ($navUrls, $template) ->
|
||||||
taskboardUrl = $navUrls.resolve("project-taskboard",
|
taskboardUrl = $navUrls.resolve("project-taskboard",
|
||||||
{project: $scope.project.slug, sprint: sprint.slug})
|
{project: $scope.project.slug, sprint: sprint.slug})
|
||||||
|
|
||||||
start = moment(sprint.estimated_start).format("DD MMM YYYY")
|
start = moment(sprint.estimated_start).format(prettyDate)
|
||||||
finish = moment(sprint.estimated_finish).format("DD MMM YYYY")
|
finish = moment(sprint.estimated_finish).format(prettyDate)
|
||||||
estimatedDateRange = "#{start}-#{finish}"
|
estimatedDateRange = "#{start}-#{finish}"
|
||||||
|
|
||||||
ctx = {
|
ctx = {
|
||||||
|
@ -112,8 +114,13 @@ BacklogSprintHeaderDirective = ($navUrls, $template) ->
|
||||||
isVisible: isVisible()
|
isVisible: isVisible()
|
||||||
isEditable: isEditable()
|
isEditable: isEditable()
|
||||||
}
|
}
|
||||||
$el.html(template(ctx))
|
|
||||||
|
|
||||||
|
templateScope = $scope.$new()
|
||||||
|
|
||||||
|
_.assign(templateScope, ctx)
|
||||||
|
|
||||||
|
compiledTemplate = $compile(template)(templateScope)
|
||||||
|
$el.html(compiledTemplate)
|
||||||
|
|
||||||
$scope.$watch $attrs.ngModel, (sprint) ->
|
$scope.$watch $attrs.ngModel, (sprint) ->
|
||||||
render(sprint)
|
render(sprint)
|
||||||
|
@ -130,13 +137,15 @@ BacklogSprintHeaderDirective = ($navUrls, $template) ->
|
||||||
require: "ngModel"
|
require: "ngModel"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgBacklogSprintHeader", ["$tgNavUrls", "$tgTemplate", BacklogSprintHeaderDirective])
|
module.directive("tgBacklogSprintHeader", ["$tgNavUrls", "$tgTemplate", "$compile", "$translate"
|
||||||
|
BacklogSprintHeaderDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Toggle Closed Sprints Directive
|
## Toggle Closed Sprints Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
ToggleExcludeClosedSprintsVisualization = ($rootscope, $loading) ->
|
ToggleExcludeClosedSprintsVisualization = ($rootscope, $loading, $translate) ->
|
||||||
excludeClosedSprints = true
|
excludeClosedSprints = true
|
||||||
|
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
|
@ -162,14 +171,16 @@ ToggleExcludeClosedSprintsVisualization = ($rootscope, $loading) ->
|
||||||
$scope.$on "closed-sprints:reloaded", (ctx, sprints) =>
|
$scope.$on "closed-sprints:reloaded", (ctx, sprints) =>
|
||||||
$loading.finish(loadingElm)
|
$loading.finish(loadingElm)
|
||||||
|
|
||||||
#TODO: i18n
|
|
||||||
if sprints.length > 0
|
if sprints.length > 0
|
||||||
text = "Hide closed sprints"
|
key = "BACKLOG.SPRINTS.ACTION_HIDE_CLOSED_SPRINTS"
|
||||||
else
|
else
|
||||||
text = "Show closed sprints"
|
key = "BACKLOG.SPRINTS.ACTION_SHOW_CLOSED_SPRINTS"
|
||||||
|
|
||||||
|
text = $translate.instant(key)
|
||||||
|
|
||||||
$el.find(".text").text(text)
|
$el.find(".text").text(text)
|
||||||
|
|
||||||
return {link: link}
|
return {link: link}
|
||||||
|
|
||||||
module.directive("tgBacklogToggleClosedSprintsVisualization", ["$rootScope", "$tgLoading", ToggleExcludeClosedSprintsVisualization])
|
module.directive("tgBacklogToggleClosedSprintsVisualization", ["$rootScope", "$tgLoading", "$translate",
|
||||||
|
ToggleExcludeClosedSprintsVisualization])
|
||||||
|
|
|
@ -23,7 +23,7 @@ taiga = @.taiga
|
||||||
groupBy = @.taiga.groupBy
|
groupBy = @.taiga.groupBy
|
||||||
bindOnce = @.taiga.bindOnce
|
bindOnce = @.taiga.bindOnce
|
||||||
|
|
||||||
module = angular.module("taigaBase", ["taigaLocales"])
|
module = angular.module("taigaBase", [])
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Main Directive
|
## Main Directive
|
||||||
|
|
|
@ -22,16 +22,25 @@
|
||||||
taiga = @.taiga
|
taiga = @.taiga
|
||||||
|
|
||||||
class HttpService extends taiga.Service
|
class HttpService extends taiga.Service
|
||||||
@.$inject = ["$http", "$q", "$tgStorage"]
|
@.$inject = ["$http", "$q", "$tgStorage", "$rootScope"]
|
||||||
|
|
||||||
|
constructor: (@http, @q, @storage, @rootScope) ->
|
||||||
|
super()
|
||||||
|
|
||||||
headers: ->
|
headers: ->
|
||||||
|
headers = {}
|
||||||
|
|
||||||
|
# Authorization
|
||||||
token = @storage.get('token')
|
token = @storage.get('token')
|
||||||
if token
|
if token
|
||||||
return {"Authorization":"Bearer #{token}"}
|
headers["Authorization"] = "Bearer #{token}"
|
||||||
return {}
|
|
||||||
|
|
||||||
constructor: (@http, @q, @storage) ->
|
# Accept-Language
|
||||||
super()
|
lang = @rootScope.user?.lang
|
||||||
|
if lang
|
||||||
|
headers["Accept-Language"] = lang
|
||||||
|
|
||||||
|
return headers
|
||||||
|
|
||||||
request: (options) ->
|
request: (options) ->
|
||||||
options.headers = _.merge({}, options.headers or {}, @.headers())
|
options.headers = _.merge({}, options.headers or {}, @.headers())
|
||||||
|
|
|
@ -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])
|
|
|
@ -28,9 +28,9 @@ module = angular.module("taigaCommon")
|
||||||
|
|
||||||
|
|
||||||
class AttachmentsController extends taiga.Controller
|
class AttachmentsController extends taiga.Controller
|
||||||
@.$inject = ["$scope", "$rootScope", "$tgRepo", "$tgResources", "$tgConfirm", "$q"]
|
@.$inject = ["$scope", "$rootScope", "$tgRepo", "$tgResources", "$tgConfirm", "$q", "$translate"]
|
||||||
|
|
||||||
constructor: (@scope, @rootscope, @repo, @rs, @confirm, @q) ->
|
constructor: (@scope, @rootscope, @repo, @rs, @confirm, @q, @translate) ->
|
||||||
bindMethods(@)
|
bindMethods(@)
|
||||||
@.type = null
|
@.type = null
|
||||||
@.objectId = null
|
@.objectId = null
|
||||||
|
@ -75,10 +75,13 @@ class AttachmentsController extends taiga.Controller
|
||||||
|
|
||||||
promise = promise.then null, (data) =>
|
promise = promise.then null, (data) =>
|
||||||
@scope.$emit("attachments:size-error") if data.status == 413
|
@scope.$emit("attachments:size-error") if data.status == 413
|
||||||
|
|
||||||
index = @.uploadingAttachments.indexOf(attachment)
|
index = @.uploadingAttachments.indexOf(attachment)
|
||||||
@.uploadingAttachments.splice(index, 1)
|
@.uploadingAttachments.splice(index, 1)
|
||||||
@confirm.notify("error", "We have not been able to upload '#{attachment.name}'.
|
|
||||||
#{data.data._error_message}")
|
message = @translate.instant("ATTACHMENT.ERROR_UPLOAD_ATTACHMENT", {
|
||||||
|
fileName: attachment.name, errorMessage: data.data._error_message})
|
||||||
|
@confirm.notify("error", message)
|
||||||
return @q.reject(data)
|
return @q.reject(data)
|
||||||
|
|
||||||
return promise
|
return promise
|
||||||
|
@ -130,8 +133,8 @@ class AttachmentsController extends taiga.Controller
|
||||||
|
|
||||||
# Remove one concrete attachment.
|
# Remove one concrete attachment.
|
||||||
removeAttachment: (attachment) ->
|
removeAttachment: (attachment) ->
|
||||||
title = "Delete attachment" #TODO: i18in
|
title = @translate.instant("ATTACHMENT.TITLE_LIGHTBOX_DELETE_ATTACHMENT")
|
||||||
message = "the attachment '#{attachment.name}'" #TODO: i18in
|
message = @translate.instant("ATTACHMENT.MSG_LIGHTBOX_DELETE_ATTACHMENT", {fileName: attachment.name})
|
||||||
|
|
||||||
return @confirm.askOnDelete(title, message).then (finish) =>
|
return @confirm.askOnDelete(title, message).then (finish) =>
|
||||||
onSuccess = =>
|
onSuccess = =>
|
||||||
|
@ -143,7 +146,8 @@ class AttachmentsController extends taiga.Controller
|
||||||
|
|
||||||
onError = =>
|
onError = =>
|
||||||
finish(false)
|
finish(false)
|
||||||
@confirm.notify("error", null, "We have not been able to delete #{message}.")
|
message = @translate.instant("ATTACHMENT.ERROR_DELETE_ATTACHMENT", {errorMessage: message})
|
||||||
|
@confirm.notify("error", null, message)
|
||||||
return @q.reject()
|
return @q.reject()
|
||||||
|
|
||||||
return @repo.remove(attachment).then(onSuccess, onError)
|
return @repo.remove(attachment).then(onSuccess, onError)
|
||||||
|
@ -155,7 +159,7 @@ class AttachmentsController extends taiga.Controller
|
||||||
return not item.is_deprecated
|
return not item.is_deprecated
|
||||||
|
|
||||||
|
|
||||||
AttachmentsDirective = ($config, $confirm, $templates) ->
|
AttachmentsDirective = ($config, $confirm, $templates, $translate) ->
|
||||||
template = $templates.get("attachment/attachments.html", true)
|
template = $templates.get("attachment/attachments.html", true)
|
||||||
|
|
||||||
link = ($scope, $el, $attrs, $ctrls) ->
|
link = ($scope, $el, $attrs, $ctrls) ->
|
||||||
|
@ -220,8 +224,7 @@ AttachmentsDirective = ($config, $confirm, $templates) ->
|
||||||
templateFn = ($el, $attrs) ->
|
templateFn = ($el, $attrs) ->
|
||||||
maxFileSize = $config.get("maxUploadFileSize", null)
|
maxFileSize = $config.get("maxUploadFileSize", null)
|
||||||
maxFileSize = sizeFormat(maxFileSize) if maxFileSize
|
maxFileSize = sizeFormat(maxFileSize) if maxFileSize
|
||||||
maxFileSizeMsg = if maxFileSize then "Maximum upload size is #{maxFileSize}" else "" # TODO: i18n
|
maxFileSizeMsg = if maxFileSize then $translate.instant("ATTACHMENT.MAX_UPLOAD_SIZE", {maxFileSize: maxFileSize}) else ""
|
||||||
|
|
||||||
ctx = {
|
ctx = {
|
||||||
type: $attrs.type
|
type: $attrs.type
|
||||||
maxFileSize: maxFileSize
|
maxFileSize: maxFileSize
|
||||||
|
@ -239,10 +242,10 @@ AttachmentsDirective = ($config, $confirm, $templates) ->
|
||||||
template: templateFn
|
template: templateFn
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgAttachments", ["$tgConfig", "$tgConfirm", "$tgTemplate", AttachmentsDirective])
|
module.directive("tgAttachments", ["$tgConfig", "$tgConfirm", "$tgTemplate", "$translate", AttachmentsDirective])
|
||||||
|
|
||||||
|
|
||||||
AttachmentDirective = ($template) ->
|
AttachmentDirective = ($template, $compile, $translate) ->
|
||||||
template = $template.get("attachment/attachment.html", true)
|
template = $template.get("attachment/attachment.html", true)
|
||||||
templateEdit = $template.get("attachment/attachment-edit.html", true)
|
templateEdit = $template.get("attachment/attachment-edit.html", true)
|
||||||
|
|
||||||
|
@ -254,7 +257,9 @@ AttachmentDirective = ($template) ->
|
||||||
ctx = {
|
ctx = {
|
||||||
id: attachment.id
|
id: attachment.id
|
||||||
name: attachment.name
|
name: attachment.name
|
||||||
created_date: moment(attachment.created_date).format("DD MMM YYYY [at] hh:mm") #TODO: i18n
|
title : $translate.instant("ATTACHMENT.TITLE", {
|
||||||
|
fileName: attachment.name,
|
||||||
|
date: moment(attachment.created_date).format($translate.instant("ATTACHMENT.DATE"))})
|
||||||
url: attachment.url
|
url: attachment.url
|
||||||
size: sizeFormat(attachment.size)
|
size: sizeFormat(attachment.size)
|
||||||
description: attachment.description
|
description: attachment.description
|
||||||
|
@ -263,9 +268,9 @@ AttachmentDirective = ($template) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
if edit
|
if edit
|
||||||
html = templateEdit(ctx)
|
html = $compile(templateEdit(ctx))($scope)
|
||||||
else
|
else
|
||||||
html = template(ctx)
|
html = $compile(template(ctx))($scope)
|
||||||
|
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
|
@ -322,4 +327,4 @@ AttachmentDirective = ($template) ->
|
||||||
restrict: "AE"
|
restrict: "AE"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgAttachment", ["$tgTemplate", AttachmentDirective])
|
module.directive("tgAttachment", ["$tgTemplate", "$compile", "$translate", AttachmentDirective])
|
||||||
|
|
|
@ -29,10 +29,11 @@ module = angular.module("taigaCommon")
|
||||||
## Date Range Directive (used mainly for sprint date range)
|
## Date Range Directive (used mainly for sprint date range)
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
DateRangeDirective = ->
|
DateRangeDirective = ($translate) ->
|
||||||
renderRange = ($el, first, second) ->
|
renderRange = ($el, first, second) ->
|
||||||
initDate = moment(first).format("DD MMM YYYY")
|
prettyDate = $translate.instant("BACKLOG.SPRINTS.DATE")
|
||||||
endDate = moment(second).format("DD MMM YYYY")
|
initDate = moment(first).format(prettyDate)
|
||||||
|
endDate = moment(second).format(prettyDate)
|
||||||
$el.html("#{initDate}-#{endDate}")
|
$el.html("#{initDate}-#{endDate}")
|
||||||
|
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
|
@ -44,34 +45,75 @@ DateRangeDirective = ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgDateRange", DateRangeDirective)
|
module.directive("tgDateRange", ["$translate", DateRangeDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Date Selector Directive (using pikaday)
|
## Date Selector Directive (using pikaday)
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
DateSelectorDirective =->
|
DateSelectorDirective = ($rootscope, $translate) ->
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
selectedDate = null
|
selectedDate = null
|
||||||
$el.picker = new Pikaday({
|
|
||||||
field: $el[0]
|
initialize = () ->
|
||||||
format: "DD MMM YYYY"
|
$el.picker = new Pikaday({
|
||||||
onSelect: (date) =>
|
field: $el[0]
|
||||||
selectedDate = date
|
onSelect: (date) =>
|
||||||
onOpen: =>
|
selectedDate = date
|
||||||
$el.picker.setDate(selectedDate) if selectedDate?
|
onOpen: =>
|
||||||
})
|
$el.picker.setDate(selectedDate) if selectedDate?
|
||||||
|
i18n: {
|
||||||
|
previousMonth: $translate.instant("COMMON.PICKERDATE.PREV_MONTH"),
|
||||||
|
nextMonth: $translate.instant("COMMON.PICKERDATE.NEXT_MONTH"),
|
||||||
|
months: [$translate.instant("COMMON.PICKERDATE.MONTHS.JAN"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.MONTHS.FEB"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.MONTHS.MAR"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.MONTHS.APR"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.MONTHS.MAY"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.MONTHS.JUN"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.MONTHS.JUL"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.MONTHS.AUG"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.MONTHS.SEP"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.MONTHS.OCT"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.MONTHS.NOV"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.MONTHS.DEC")],
|
||||||
|
weekdays: [$translate.instant("COMMON.PICKERDATE.WEEK_DAYS.SUN"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.WEEK_DAYS.MON"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.WEEK_DAYS.TUE"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.WEEK_DAYS.WED"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.WEEK_DAYS.THU"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.WEEK_DAYS.FRI"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.WEEK_DAYS.SAT")],
|
||||||
|
weekdaysShort: [$translate.instant("COMMON.PICKERDATE.WEEK_DAYS_SHORT.SUN"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.WEEK_DAYS_SHORT.MON"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.WEEK_DAYS_SHORT.TUE"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.WEEK_DAYS_SHORT.WED"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.WEEK_DAYS_SHORT.THU"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.WEEK_DAYS_SHORT.FRI"),
|
||||||
|
$translate.instant("COMMON.PICKERDATE.WEEK_DAYS_SHORT.SAT")]
|
||||||
|
},
|
||||||
|
isRTL: $translate.instant("COMMON.PICKERDATE.IS_RTL") == "true",
|
||||||
|
firstDay: parseInt($translate.instant("COMMON.PICKERDATE.FIRST_DAY_OF_WEEK"), 10),
|
||||||
|
format: $translate.instant("COMMON.PICKERDATE.FORMAT")
|
||||||
|
})
|
||||||
|
|
||||||
|
unbind = $rootscope.$on "$translateChangeEnd", (ctx) => initialize()
|
||||||
|
|
||||||
$scope.$watch $attrs.ngModel, (val) ->
|
$scope.$watch $attrs.ngModel, (val) ->
|
||||||
|
initialize() if val? and not $el.picker
|
||||||
$el.picker.setDate(val) if val?
|
$el.picker.setDate(val) if val?
|
||||||
|
|
||||||
|
$scope.$on "$destroy", ->
|
||||||
|
$el.off()
|
||||||
|
unbind()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
link: link
|
link: link
|
||||||
require: "ngModel"
|
require: "ngModel"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgDateSelector", DateSelectorDirective)
|
module.directive("tgDateSelector", ["$rootScope", "$translate", DateSelectorDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -98,6 +140,9 @@ SprintProgressBarDirective = ->
|
||||||
|
|
||||||
renderProgress($el, percentage, visual_percentage)
|
renderProgress($el, percentage, visual_percentage)
|
||||||
|
|
||||||
|
$scope.$on "$destroy", ->
|
||||||
|
$el.off()
|
||||||
|
|
||||||
return {link: link}
|
return {link: link}
|
||||||
|
|
||||||
module.directive("tgSprintProgressbar", SprintProgressBarDirective)
|
module.directive("tgSprintProgressbar", SprintProgressBarDirective)
|
||||||
|
@ -107,7 +152,7 @@ module.directive("tgSprintProgressbar", SprintProgressBarDirective)
|
||||||
## Created-by display directive
|
## Created-by display directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
CreatedByDisplayDirective = ($template)->
|
CreatedByDisplayDirective = ($template, $compile, $translate)->
|
||||||
# Display the owner information (full name and photo) and the date of
|
# Display the owner information (full name and photo) and the date of
|
||||||
# creation of an object (like USs, tasks and issues).
|
# creation of an object (like USs, tasks and issues).
|
||||||
#
|
#
|
||||||
|
@ -119,18 +164,22 @@ CreatedByDisplayDirective = ($template)->
|
||||||
# 'owner'(ng-model)
|
# 'owner'(ng-model)
|
||||||
# - scope.usersById object is required.
|
# - 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) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
render = (model) ->
|
render = (model) ->
|
||||||
owner = $scope.usersById?[model.owner] or {
|
owner = $scope.usersById?[model.owner] or {
|
||||||
full_name_display: "external user"
|
full_name_display: $translate.instant("COMMON.EXTERNAL_USER")
|
||||||
photo: "/images/unnamed.png"
|
photo: "/images/unnamed.png"
|
||||||
}
|
}
|
||||||
|
|
||||||
html = template({
|
html = template({
|
||||||
owner: owner
|
owner: owner
|
||||||
date: moment(model.created_date).format("DD MMM YYYY HH:mm")
|
date: moment(model.created_date).format($translate.instant("COMMON.DATETIME"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
html = $compile(html)($scope)
|
||||||
|
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
bindOnce $scope, $attrs.ngModel, (model) ->
|
bindOnce $scope, $attrs.ngModel, (model) ->
|
||||||
|
@ -145,18 +194,16 @@ CreatedByDisplayDirective = ($template)->
|
||||||
require: "ngModel"
|
require: "ngModel"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgCreatedByDisplay", ["$tgTemplate", CreatedByDisplayDirective])
|
module.directive("tgCreatedByDisplay", ["$tgTemplate", "$compile", "$translate", CreatedByDisplayDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Watchers directive
|
## Watchers directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
WatchersDirective = ($rootscope, $confirm, $repo, $qqueue, $template) ->
|
WatchersDirective = ($rootscope, $confirm, $repo, $qqueue, $template, $compile, $translate) ->
|
||||||
# You have to include a div with the tg-lb-watchers directive in the page
|
# You have to include a div with the tg-lb-watchers directive in the page
|
||||||
# where use this directive
|
# where use this directive
|
||||||
#
|
|
||||||
# TODO: i18n
|
|
||||||
template = $template.get("common/components/watchers.html", true)
|
template = $template.get("common/components/watchers.html", true)
|
||||||
|
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
|
@ -200,7 +247,7 @@ WatchersDirective = ($rootscope, $confirm, $repo, $qqueue, $template) ->
|
||||||
isEditable: isEditable()
|
isEditable: isEditable()
|
||||||
}
|
}
|
||||||
|
|
||||||
html = template(ctx)
|
html = $compile(template(ctx))($scope)
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
if isEditable() and watchers.length == 0
|
if isEditable() and watchers.length == 0
|
||||||
|
@ -213,7 +260,7 @@ WatchersDirective = ($rootscope, $confirm, $repo, $qqueue, $template) ->
|
||||||
target = angular.element(event.currentTarget)
|
target = angular.element(event.currentTarget)
|
||||||
watcherId = target.data("watcher-id")
|
watcherId = target.data("watcher-id")
|
||||||
|
|
||||||
title = "Delete watcher"
|
title = $translate.instant("COMMON.WATCHERS.TITLE_LIGHTBOX_DELETE_WARTCHER")
|
||||||
message = $scope.usersById[watcherId].full_name_display
|
message = $scope.usersById[watcherId].full_name_display
|
||||||
|
|
||||||
$confirm.askOnDelete(title, message).then (finish) =>
|
$confirm.askOnDelete(title, message).then (finish) =>
|
||||||
|
@ -247,18 +294,17 @@ WatchersDirective = ($rootscope, $confirm, $repo, $qqueue, $template) ->
|
||||||
|
|
||||||
return {link:link, require:"ngModel"}
|
return {link:link, require:"ngModel"}
|
||||||
|
|
||||||
module.directive("tgWatchers", ["$rootScope", "$tgConfirm", "$tgRepo", "$tgQqueue", "$tgTemplate", WatchersDirective])
|
module.directive("tgWatchers", ["$rootScope", "$tgConfirm", "$tgRepo", "$tgQqueue", "$tgTemplate", "$compile",
|
||||||
|
"$translate", WatchersDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Assigned to directive
|
## 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
|
# You have to include a div with the tg-lb-assignedto directive in the page
|
||||||
# where use this directive
|
# where use this directive
|
||||||
#
|
|
||||||
# TODO: i18n
|
|
||||||
template = $template.get("common/components/assigned-to.html", true)
|
template = $template.get("common/components/assigned-to.html", true)
|
||||||
|
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
|
@ -291,7 +337,7 @@ AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $qqueue, $template
|
||||||
assignedTo: assignedTo
|
assignedTo: assignedTo
|
||||||
isEditable: isEditable()
|
isEditable: isEditable()
|
||||||
}
|
}
|
||||||
html = template(ctx)
|
html = $compile(template(ctx))($scope)
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
$el.on "click", ".user-assigned", (event) ->
|
$el.on "click", ".user-assigned", (event) ->
|
||||||
|
@ -303,7 +349,7 @@ AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $qqueue, $template
|
||||||
$el.on "click", ".icon-delete", (event) ->
|
$el.on "click", ".icon-delete", (event) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
return if not isEditable()
|
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) =>
|
$confirm.ask(title).then (finish) =>
|
||||||
finish()
|
finish()
|
||||||
|
@ -326,7 +372,8 @@ AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $qqueue, $template
|
||||||
require:"ngModel"
|
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 +439,7 @@ DeleteButtonDirective = ($log, $repo, $confirm, $location, $template) ->
|
||||||
return $log.error "DeleteButtonDirective requires on-delete-title set in scope."
|
return $log.error "DeleteButtonDirective requires on-delete-title set in scope."
|
||||||
|
|
||||||
$el.on "click", ".button", (event) ->
|
$el.on "click", ".button", (event) ->
|
||||||
title = $scope.$eval($attrs.onDeleteTitle)
|
title = $attrs.onDeleteTitle
|
||||||
subtitle = $model.$modelValue.subject
|
subtitle = $model.$modelValue.subject
|
||||||
|
|
||||||
$confirm.askOnDelete(title, subtitle).then (finish) =>
|
$confirm.askOnDelete(title, subtitle).then (finish) =>
|
||||||
|
@ -471,7 +518,6 @@ EditableSubjectDirective = ($rootscope, $repo, $confirm, $loading, $qqueue, $tem
|
||||||
$el.find('div.edit-subject').hide()
|
$el.find('div.edit-subject').hide()
|
||||||
$el.find('div.view-subject span.edit').hide()
|
$el.find('div.view-subject span.edit').hide()
|
||||||
|
|
||||||
|
|
||||||
$scope.$watch $attrs.ngModel, (value) ->
|
$scope.$watch $attrs.ngModel, (value) ->
|
||||||
return if not value
|
return if not value
|
||||||
$scope.item = value
|
$scope.item = value
|
||||||
|
@ -490,7 +536,8 @@ EditableSubjectDirective = ($rootscope, $repo, $confirm, $loading, $qqueue, $tem
|
||||||
template: template
|
template: template
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgEditableSubject", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate", EditableSubjectDirective])
|
module.directive("tgEditableSubject", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue",
|
||||||
|
"$tgTemplate", EditableSubjectDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -498,9 +545,9 @@ module.directive("tgEditableSubject", ["$rootScope", "$tgRepo", "$tgConfirm", "$
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
EditableDescriptionDirective = ($rootscope, $repo, $confirm, $compile, $loading, $selectedText, $qqueue, $template) ->
|
EditableDescriptionDirective = ($rootscope, $repo, $confirm, $compile, $loading, $selectedText, $qqueue, $template) ->
|
||||||
template = $template.get("common/components/editable-description.html") # TODO: i18n
|
template = $template.get("common/components/editable-description.html")
|
||||||
noDescriptionMegEditMode = $template.get("common/components/editable-description-msg-edit-mode.html") # TODO: i18n
|
noDescriptionMegEditMode = $template.get("common/components/editable-description-msg-edit-mode.html")
|
||||||
noDescriptionMegReadMode = $template.get("common/components/editable-description-msg-read-mode.html") # TODO: i18n
|
noDescriptionMegReadMode = $template.get("common/components/editable-description-msg-read-mode.html")
|
||||||
|
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
$el.find('.edit-description').hide()
|
$el.find('.edit-description').hide()
|
||||||
|
@ -555,9 +602,9 @@ EditableDescriptionDirective = ($rootscope, $repo, $confirm, $compile, $loading,
|
||||||
if isEditable()
|
if isEditable()
|
||||||
$el.find('.view-description .edit').show()
|
$el.find('.view-description .edit').show()
|
||||||
$el.find('.view-description .us-content').addClass('editable')
|
$el.find('.view-description .us-content').addClass('editable')
|
||||||
$scope.noDescriptionMsg = noDescriptionMegEditMode
|
$scope.noDescriptionMsg = $compile(noDescriptionMegEditMode)($scope)
|
||||||
else
|
else
|
||||||
$scope.noDescriptionMsg = noDescriptionMegReadMode
|
$scope.noDescriptionMsg = $compile(noDescriptionMegReadMode)($scope)
|
||||||
|
|
||||||
$scope.$on "$destroy", ->
|
$scope.$on "$destroy", ->
|
||||||
$el.off()
|
$el.off()
|
||||||
|
@ -569,8 +616,8 @@ EditableDescriptionDirective = ($rootscope, $repo, $confirm, $compile, $loading,
|
||||||
template: template
|
template: template
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgEditableDescription", ["$rootScope", "$tgRepo", "$tgConfirm",
|
module.directive("tgEditableDescription", ["$rootScope", "$tgRepo", "$tgConfirm", "$compile", "$tgLoading",
|
||||||
"$compile", "$tgLoading", "$selectedText", "$tgQqueue", "$tgTemplate", EditableDescriptionDirective])
|
"$selectedText", "$tgQqueue", "$tgTemplate", EditableDescriptionDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -580,14 +627,16 @@ module.directive("tgEditableDescription", ["$rootScope", "$tgRepo", "$tgConfirm"
|
||||||
## completely bindonce, they only serves for visualization of data.
|
## completely bindonce, they only serves for visualization of data.
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
ListItemIssueStatusDirective = ->
|
ListItemUsStatusDirective = ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
issue = $scope.$eval($attrs.tgListitemIssueStatus)
|
us = $scope.$eval($attrs.tgListitemUsStatus)
|
||||||
bindOnce $scope, "issueStatusById", (issueStatusById) ->
|
bindOnce $scope, "usStatusById", (usStatusById) ->
|
||||||
$el.html(issueStatusById[issue.status].name)
|
$el.html(usStatusById[us.status].name)
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
|
module.directive("tgListitemUsStatus", ListItemUsStatusDirective)
|
||||||
|
|
||||||
|
|
||||||
ListItemTaskStatusDirective = ->
|
ListItemTaskStatusDirective = ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
|
@ -597,14 +646,7 @@ ListItemTaskStatusDirective = ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
|
module.directive("tgListitemTaskStatus", ListItemTaskStatusDirective)
|
||||||
ListItemUsStatusDirective = ->
|
|
||||||
link = ($scope, $el, $attrs) ->
|
|
||||||
us = $scope.$eval($attrs.tgListitemUsStatus)
|
|
||||||
bindOnce $scope, "usStatusById", (usStatusById) ->
|
|
||||||
$el.html(usStatusById[us.status].name)
|
|
||||||
|
|
||||||
return {link:link}
|
|
||||||
|
|
||||||
|
|
||||||
ListItemAssignedtoDirective = ($template) ->
|
ListItemAssignedtoDirective = ($template) ->
|
||||||
|
@ -626,6 +668,41 @@ ListItemAssignedtoDirective = ($template) ->
|
||||||
|
|
||||||
module.directive("tgListitemAssignedto", ["$tgTemplate", ListItemAssignedtoDirective])
|
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 = ->
|
ListItemPriorityDirective = ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
render = (priorityById, issue) ->
|
render = (priorityById, issue) ->
|
||||||
|
@ -648,6 +725,7 @@ ListItemPriorityDirective = ->
|
||||||
|
|
||||||
module.directive("tgListitemPriority", ListItemPriorityDirective)
|
module.directive("tgListitemPriority", ListItemPriorityDirective)
|
||||||
|
|
||||||
|
|
||||||
ListItemSeverityDirective = ->
|
ListItemSeverityDirective = ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
render = (severityById, issue) ->
|
render = (severityById, issue) ->
|
||||||
|
@ -668,26 +746,7 @@ ListItemSeverityDirective = ->
|
||||||
templateUrl: "common/components/level.html"
|
templateUrl: "common/components/level.html"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.directive("tgListitemSeverity", ListItemSeverityDirective)
|
||||||
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"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -715,35 +774,27 @@ TgProgressBarDirective = ($template) ->
|
||||||
|
|
||||||
module.directive("tgProgressBar", ["$tgTemplate", TgProgressBarDirective])
|
module.directive("tgProgressBar", ["$tgTemplate", TgProgressBarDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Main title directive
|
## Main title directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
TgMainTitleDirective = ($template) ->
|
TgMainTitleDirective = ($translate) ->
|
||||||
template = $template.get("common/components/main-title.html", true)
|
|
||||||
|
|
||||||
render = (el, projectName, sectionName) ->
|
|
||||||
el.html(template({
|
|
||||||
projectName: projectName
|
|
||||||
sectionName: sectionName
|
|
||||||
}))
|
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
element = angular.element($el)
|
$attrs.$observe "i18nSectionName", (i18nSectionName) ->
|
||||||
$scope.$watch "project", (project) ->
|
trans = $translate(i18nSectionName)
|
||||||
render($el, project.name, $scope.sectionName) if project
|
trans.then (sectionName) -> $scope.sectionName = sectionName
|
||||||
|
trans.catch (sectionName) -> $scope.sectionName = sectionName
|
||||||
$scope.$on "project:loaded", (ctx, project) =>
|
|
||||||
render($el, project.name, $scope.sectionName)
|
|
||||||
|
|
||||||
$scope.$on "$destroy", ->
|
$scope.$on "$destroy", ->
|
||||||
$el.off()
|
$el.off()
|
||||||
|
|
||||||
return {link: link}
|
return {
|
||||||
|
link: link
|
||||||
|
templateUrl: "common/components/main-title.html"
|
||||||
|
scope: {
|
||||||
|
projectName : "=projectName"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.directive("tgMainTitle", ["$tgTemplate", TgMainTitleDirective])
|
module.directive("tgMainTitle", ["$translate", TgMainTitleDirective])
|
||||||
|
|
||||||
module.directive("tgListitemType", ListItemTypeDirective)
|
|
||||||
module.directive("tgListitemIssueStatus", ListItemIssueStatusDirective)
|
|
||||||
module.directive("tgListitemSeverity", ListItemSeverityDirective)
|
|
||||||
module.directive("tgListitemTaskStatus", ListItemTaskStatusDirective)
|
|
||||||
module.directive("tgListitemUsStatus", ListItemUsStatusDirective)
|
|
||||||
|
|
|
@ -27,21 +27,21 @@ bindMethods = @.taiga.bindMethods
|
||||||
|
|
||||||
NOTIFICATION_MSG = {
|
NOTIFICATION_MSG = {
|
||||||
"success":
|
"success":
|
||||||
title: "Everything is ok"
|
title: "NOTIFICATION.OK"
|
||||||
message: "Our Oompa Loompas saved all your changes!"
|
message: "NOTIFICATION.SAVED"
|
||||||
"error":
|
"error":
|
||||||
title: "Oops, something happened..."
|
title: "NOTIFICATION.WARNING"
|
||||||
message: "Our Oompa Loompas are sad, your changes were not saved!"
|
message: "NOTIFICATION.WARNING_TEXT"
|
||||||
"light-error":
|
"light-error":
|
||||||
title: "Oops, something happened..."
|
title: "NOTIFICATION.WARNING"
|
||||||
message: "Our Oompa Loompas are sad, your changes were not saved!"
|
message: "NOTIFICATION.WARNING_TEXT"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ConfirmService extends taiga.Service
|
class ConfirmService extends taiga.Service
|
||||||
@.$inject = ["$q", "lightboxService", "$tgLoading"]
|
@.$inject = ["$q", "lightboxService", "$tgLoading", "$translate"]
|
||||||
|
|
||||||
constructor: (@q, @lightboxService, @loading) ->
|
constructor: (@q, @lightboxService, @loading, @translate) ->
|
||||||
bindMethods(@)
|
bindMethods(@)
|
||||||
|
|
||||||
hide: (el)->
|
hide: (el)->
|
||||||
|
@ -51,6 +51,8 @@ class ConfirmService extends taiga.Service
|
||||||
el.off(".confirm-dialog")
|
el.off(".confirm-dialog")
|
||||||
|
|
||||||
ask: (title, subtitle, message, lightboxSelector=".lightbox-generic-ask") ->
|
ask: (title, subtitle, message, lightboxSelector=".lightbox-generic-ask") ->
|
||||||
|
defered = @q.defer()
|
||||||
|
|
||||||
el = angular.element(lightboxSelector)
|
el = angular.element(lightboxSelector)
|
||||||
|
|
||||||
# Render content
|
# Render content
|
||||||
|
@ -58,8 +60,6 @@ class ConfirmService extends taiga.Service
|
||||||
el.find("span.subtitle").html(subtitle)
|
el.find("span.subtitle").html(subtitle)
|
||||||
el.find("span.message").html(message)
|
el.find("span.message").html(message)
|
||||||
|
|
||||||
defered = @q.defer()
|
|
||||||
|
|
||||||
# Assign event handlers
|
# Assign event handlers
|
||||||
el.on "click.confirm-dialog", "a.button-green", debounce 2000, (event) =>
|
el.on "click.confirm-dialog", "a.button-green", debounce 2000, (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@ -80,9 +80,11 @@ class ConfirmService extends taiga.Service
|
||||||
return defered.promise
|
return defered.promise
|
||||||
|
|
||||||
askOnDelete: (title, message) ->
|
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") ->
|
askChoice: (title, subtitle, choices, replacement, warning, lightboxSelector=".lightbox-ask-choice") ->
|
||||||
|
defered = @q.defer()
|
||||||
|
|
||||||
el = angular.element(lightboxSelector)
|
el = angular.element(lightboxSelector)
|
||||||
|
|
||||||
# Render content
|
# Render content
|
||||||
|
@ -103,7 +105,6 @@ class ConfirmService extends taiga.Service
|
||||||
choicesField.html('')
|
choicesField.html('')
|
||||||
_.each choices, (value, key) ->
|
_.each choices, (value, key) ->
|
||||||
choicesField.append(angular.element("<option value='#{key}'>#{value}</option>"))
|
choicesField.append(angular.element("<option value='#{key}'>#{value}</option>"))
|
||||||
defered = @q.defer()
|
|
||||||
|
|
||||||
# Assign event handlers
|
# Assign event handlers
|
||||||
el.on "click.confirm-dialog", "a.button-green", debounce 2000, (event) =>
|
el.on "click.confirm-dialog", "a.button-green", debounce 2000, (event) =>
|
||||||
|
@ -127,11 +128,12 @@ class ConfirmService extends taiga.Service
|
||||||
return defered.promise
|
return defered.promise
|
||||||
|
|
||||||
error: (message) ->
|
error: (message) ->
|
||||||
|
defered = @q.defer()
|
||||||
|
|
||||||
el = angular.element(".lightbox-generic-error")
|
el = angular.element(".lightbox-generic-error")
|
||||||
|
|
||||||
# Render content
|
# Render content
|
||||||
el.find("h2.title").html(message)
|
el.find("h2.title").html(message)
|
||||||
defered = @q.defer()
|
|
||||||
|
|
||||||
# Assign event handlers
|
# Assign event handlers
|
||||||
el.on "click.confirm-dialog", "a.button-green", (event) =>
|
el.on "click.confirm-dialog", "a.button-green", (event) =>
|
||||||
|
@ -149,12 +151,13 @@ class ConfirmService extends taiga.Service
|
||||||
return defered.promise
|
return defered.promise
|
||||||
|
|
||||||
success: (title, message) ->
|
success: (title, message) ->
|
||||||
|
defered = @q.defer()
|
||||||
|
|
||||||
el = angular.element(".lightbox-generic-success")
|
el = angular.element(".lightbox-generic-success")
|
||||||
|
|
||||||
# Render content
|
# Render content
|
||||||
el.find("h2.title").html(title) if title
|
el.find("h2.title").html(title) if title
|
||||||
el.find("p.message").html(message) if message
|
el.find("p.message").html(message) if message
|
||||||
defered = @q.defer()
|
|
||||||
|
|
||||||
# Assign event handlers
|
# Assign event handlers
|
||||||
el.on "click.confirm-dialog", "a.button-green", (event) =>
|
el.on "click.confirm-dialog", "a.button-green", (event) =>
|
||||||
|
@ -208,12 +211,12 @@ class ConfirmService extends taiga.Service
|
||||||
if title
|
if title
|
||||||
el.find("h4").html(title)
|
el.find("h4").html(title)
|
||||||
else
|
else
|
||||||
el.find("h4").html(NOTIFICATION_MSG[type].title)
|
el.find("h4").html(@translate.instant(NOTIFICATION_MSG[type].title))
|
||||||
|
|
||||||
if message
|
if message
|
||||||
el.find("p").html(message)
|
el.find("p").html(message)
|
||||||
else
|
else
|
||||||
el.find("p").html(NOTIFICATION_MSG[type].message)
|
el.find("p").html(@translate.instant(NOTIFICATION_MSG[type].message))
|
||||||
|
|
||||||
body = angular.element("body")
|
body = angular.element("body")
|
||||||
body.find(".notification-message .notification-light")
|
body.find(".notification-message .notification-light")
|
||||||
|
|
|
@ -121,7 +121,7 @@ CustomAttributesValuesDirective = ($templates, $storage) ->
|
||||||
module.directive("tgCustomAttributesValues", ["$tgTemplate", "$tgStorage", CustomAttributesValuesDirective])
|
module.directive("tgCustomAttributesValues", ["$tgTemplate", "$tgStorage", CustomAttributesValuesDirective])
|
||||||
|
|
||||||
|
|
||||||
CustomAttributeValueDirective = ($template, $selectedText) ->
|
CustomAttributeValueDirective = ($template, $selectedText, $compile) ->
|
||||||
template = $template.get("custom-attributes/custom-attribute-value.html", true)
|
template = $template.get("custom-attributes/custom-attribute-value.html", true)
|
||||||
templateEdit = $template.get("custom-attributes/custom-attribute-value-edit.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)
|
if editable and (edit or not value)
|
||||||
html = templateEdit(ctx)
|
html = templateEdit(ctx)
|
||||||
|
html = $compile(html)($scope)
|
||||||
else
|
else
|
||||||
html = template(ctx)
|
html = template(ctx)
|
||||||
|
html = $compile(html)($scope)
|
||||||
|
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
|
@ -168,11 +170,13 @@ CustomAttributeValueDirective = ($template, $selectedText) ->
|
||||||
return if $selectedText.get().length
|
return if $selectedText.get().length
|
||||||
render(attributeValue, true)
|
render(attributeValue, true)
|
||||||
$el.find("input[name='description']").focus().select()
|
$el.find("input[name='description']").focus().select()
|
||||||
|
$scope.$apply()
|
||||||
|
|
||||||
$el.on "click", "a.icon-edit", (event) ->
|
$el.on "click", "a.icon-edit", (event) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
render(attributeValue, true)
|
render(attributeValue, true)
|
||||||
$el.find("input[name='description']").focus().select()
|
$el.find("input[name='description']").focus().select()
|
||||||
|
$scope.$apply()
|
||||||
|
|
||||||
## Actions (on edit mode)
|
## Actions (on edit mode)
|
||||||
submit = debounce 2000, (event) =>
|
submit = debounce 2000, (event) =>
|
||||||
|
@ -195,4 +199,4 @@ CustomAttributeValueDirective = ($template, $selectedText) ->
|
||||||
restrict: "AE"
|
restrict: "AE"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgCustomAttributeValue", ["$tgTemplate", "$selectedText", CustomAttributeValueDirective])
|
module.directive("tgCustomAttributeValue", ["$tgTemplate", "$selectedText", "$compile", CustomAttributeValueDirective])
|
||||||
|
|
|
@ -28,7 +28,7 @@ module = angular.module("taigaCommon")
|
||||||
## User story estimation directive (for Lightboxes)
|
## 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.
|
# Display the points of a US and you can edit it.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
@ -56,6 +56,7 @@ LbUsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $
|
||||||
mainTemplate = "common/estimation/us-estimation-points-per-role.html"
|
mainTemplate = "common/estimation/us-estimation-points-per-role.html"
|
||||||
template = $template.get(mainTemplate, true)
|
template = $template.get(mainTemplate, true)
|
||||||
html = template(ctx)
|
html = template(ctx)
|
||||||
|
html = $compile(html)($scope)
|
||||||
@$el.html(html)
|
@$el.html(html)
|
||||||
|
|
||||||
estimationProcess.render()
|
estimationProcess.render()
|
||||||
|
@ -68,14 +69,14 @@ LbUsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $
|
||||||
require: "ngModel"
|
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
|
## 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.
|
# Display the points of a US and you can edit it.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
@ -102,6 +103,7 @@ UsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $qq
|
||||||
mainTemplate = "common/estimation/us-estimation-points-per-role.html"
|
mainTemplate = "common/estimation/us-estimation-points-per-role.html"
|
||||||
template = $template.get(mainTemplate, true)
|
template = $template.get(mainTemplate, true)
|
||||||
html = template(ctx)
|
html = template(ctx)
|
||||||
|
html = $compile(html)($scope)
|
||||||
@$el.html(html)
|
@$el.html(html)
|
||||||
|
|
||||||
estimationProcess.render()
|
estimationProcess.render()
|
||||||
|
@ -115,7 +117,7 @@ UsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $qq
|
||||||
require: "ngModel"
|
require: "ngModel"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgUsEstimation", ["$tgEstimationsService", "$rootScope", "$tgRepo", "$tgConfirm", "$tgQqueue", "$tgTemplate",
|
module.directive("tgUsEstimation", ["$tgEstimationsService", "$rootScope", "$tgRepo", "$tgConfirm", "$tgQqueue", "$tgTemplate", "$compile"
|
||||||
UsEstimationDirective])
|
UsEstimationDirective])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,15 +33,14 @@ defaultFilter = ->
|
||||||
module.filter("default", defaultFilter)
|
module.filter("default", defaultFilter)
|
||||||
|
|
||||||
|
|
||||||
yesNoFilter = ->
|
yesNoFilter = ($translate) ->
|
||||||
#TODO: i18n
|
|
||||||
return (value) ->
|
return (value) ->
|
||||||
if 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 = ->
|
unslugify = ->
|
||||||
|
|
|
@ -68,7 +68,7 @@ class HistoryController extends taiga.Controller
|
||||||
return @rs.history.undeleteComment(type, objectId, activityId).then => @.loadHistory(type, objectId)
|
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)
|
templateChangeDiff = $template.get("common/history/history-change-diff.html", true)
|
||||||
templateChangePoints = $template.get("common/history/history-change-points.html", true)
|
templateChangePoints = $template.get("common/history/history-change-points.html", true)
|
||||||
templateChangeGeneric = $template.get("common/history/history-change-generic.html", true)
|
templateChangeGeneric = $template.get("common/history/history-change-generic.html", true)
|
||||||
|
@ -87,6 +87,9 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
|
||||||
showAllComments = false
|
showAllComments = false
|
||||||
showAllActivity = false
|
showAllActivity = false
|
||||||
|
|
||||||
|
getPrettyDateFormat = ->
|
||||||
|
return $translate.instant("ACTIVITY.DATETIME")
|
||||||
|
|
||||||
bindOnce $scope, $attrs.ngModel, (model) ->
|
bindOnce $scope, $attrs.ngModel, (model) ->
|
||||||
type = $attrs.type
|
type = $attrs.type
|
||||||
objectId = model.id
|
objectId = model.id
|
||||||
|
@ -97,24 +100,40 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
|
||||||
# Helpers
|
# Helpers
|
||||||
getHumanizedFieldName = (field) ->
|
getHumanizedFieldName = (field) ->
|
||||||
humanizedFieldNames = {
|
humanizedFieldNames = {
|
||||||
# US
|
subject : $translate.instant("ACTIVITY.FIELDS.SUBJECT")
|
||||||
assigned_to: "assigned to"
|
name: $translate.instant("ACTIVITY.FIELDS.NAME")
|
||||||
is_closed: "is closed"
|
description : $translate.instant("ACTIVITY.FIELDS.DESCRIPTION")
|
||||||
finish_date: "finish date"
|
content: $translate.instant("ACTIVITY.FIELDS.CONTENT")
|
||||||
client_requirement: "client requirement"
|
status: $translate.instant("ACTIVITY.FIELDS.STATUS")
|
||||||
team_requirement: "team requirement"
|
is_closed : $translate.instant("ACTIVITY.FIELDS.IS_CLOSED")
|
||||||
|
finish_date : $translate.instant("ACTIVITY.FIELDS.FINISH_DATE")
|
||||||
|
type: $translate.instant("ACTIVITY.FIELDS.TYPE")
|
||||||
|
priority: $translate.instant("ACTIVITY.FIELDS.PRIORITY")
|
||||||
|
severity: $translate.instant("ACTIVITY.FIELDS.SEVERITY")
|
||||||
|
assigned_to : $translate.instant("ACTIVITY.FIELDS.ASSIGNED_TO")
|
||||||
|
watchers : $translate.instant("ACTIVITY.FIELDS.WATCHERS")
|
||||||
|
milestone : $translate.instant("ACTIVITY.FIELDS.MILESTONE")
|
||||||
|
user_story: $translate.instant("ACTIVITY.FIELDS.USER_STORY")
|
||||||
|
project: $translate.instant("ACTIVITY.FIELDS.PROJECT")
|
||||||
|
is_blocked: $translate.instant("ACTIVITY.FIELDS.IS_BLOCKED")
|
||||||
|
blocked_note: $translate.instant("ACTIVITY.FIELDS.BLOCKED_NOTE")
|
||||||
|
points: $translate.instant("ACTIVITY.FIELDS.POINTS")
|
||||||
|
client_requirement : $translate.instant("ACTIVITY.FIELDS.CLIENT_REQUIREMENT")
|
||||||
|
team_requirement : $translate.instant("ACTIVITY.FIELDS.TEAM_REQUIREMENT")
|
||||||
|
is_iocaine: $translate.instant("ACTIVITY.FIELDS.IS_IOCAINE")
|
||||||
|
tags: $translate.instant("ACTIVITY.FIELDS.TAGS")
|
||||||
|
attachments : $translate.instant("ACTIVITY.FIELDS.ATTACHMENTS")
|
||||||
|
is_deprecated: $translate.instant("ACTIVITY.FIELDS.IS_DEPRECATED")
|
||||||
|
blocked_note: $translate.instant("ACTIVITY.FIELDS.BLOCKED_NOTE")
|
||||||
|
is_blocked: $translate.instant("ACTIVITY.FIELDS.IS_BLOCKED")
|
||||||
|
order: $translate.instant("ACTIVITY.FIELDS.ORDER")
|
||||||
|
backlog_order: $translate.instant("ACTIVITY.FIELDS.BACKLOG_ORDER")
|
||||||
|
sprint_order: $translate.instant("ACTIVITY.FIELDS.SPRINT_ORDER")
|
||||||
|
kanban_order: $translate.instant("ACTIVITY.FIELDS.KANBAN_ORDER")
|
||||||
|
taskboard_order: $translate.instant("ACTIVITY.FIELDS.TASKBOARD_ORDER")
|
||||||
|
us_order: $translate.instant("ACTIVITY.FIELDS.US_ORDER")
|
||||||
|
}
|
||||||
|
|
||||||
# Task
|
|
||||||
milestone: "sprint"
|
|
||||||
user_story: "user story"
|
|
||||||
is_iocaine: "is iocaine"
|
|
||||||
|
|
||||||
# Attachment
|
|
||||||
is_deprecated: "is deprecated"
|
|
||||||
|
|
||||||
blocked_note: "blocked note"
|
|
||||||
is_blocked: "is blocked"
|
|
||||||
} # TODO i18n
|
|
||||||
return humanizedFieldNames[field] or field
|
return humanizedFieldNames[field] or field
|
||||||
|
|
||||||
getUserFullName = (userId) ->
|
getUserFullName = (userId) ->
|
||||||
|
@ -132,17 +151,17 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
|
||||||
formatChange = (change) ->
|
formatChange = (change) ->
|
||||||
if _.isArray(change)
|
if _.isArray(change)
|
||||||
if change.length == 0
|
if change.length == 0
|
||||||
return "empty"
|
return $translate.instant("ACTIVITY.VALUES.EMPTY")
|
||||||
return change.join(", ")
|
return change.join(", ")
|
||||||
|
|
||||||
if change == ""
|
if change == ""
|
||||||
return "empty"
|
return $translate.instant("ACTIVITY.VALUES.EMPTY")
|
||||||
|
|
||||||
if not change? or change == false
|
if not change? or change == false
|
||||||
return "no"
|
return $translate.instant("ACTIVITY.VALUES.NO")
|
||||||
|
|
||||||
if change == true
|
if change == true
|
||||||
return "yes"
|
return $translate.instant("ACTIVITY.VALUES.YES")
|
||||||
|
|
||||||
return change
|
return change
|
||||||
|
|
||||||
|
@ -152,22 +171,26 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
|
||||||
attachments = _.map value, (changes, type) ->
|
attachments = _.map value, (changes, type) ->
|
||||||
if type == "new"
|
if type == "new"
|
||||||
return _.map changes, (change) ->
|
return _.map changes, (change) ->
|
||||||
# TODO: i18n
|
return templateChangeDiff({
|
||||||
return templateChangeDiff({name: "new attachment", diff: change.filename})
|
name: $translate.instant("ACTIVITY.NEW_ATTACHMENT"),
|
||||||
|
diff: change.filename
|
||||||
|
})
|
||||||
else if type == "deleted"
|
else if type == "deleted"
|
||||||
return _.map changes, (change) ->
|
return _.map changes, (change) ->
|
||||||
# TODO: i18n
|
return templateChangeDiff({
|
||||||
return templateChangeDiff({name: "deleted attachment", diff: change.filename})
|
name: $translate.instant("ACTIVITY.DELETED_ATTACHMENT"),
|
||||||
|
diff: change.filename
|
||||||
|
})
|
||||||
else
|
else
|
||||||
return _.map changes, (change) ->
|
return _.map changes, (change) ->
|
||||||
# TODO: i18n
|
name = $translate.instant("ACTIVITY.UPDATED_ATTACHMENT", {filename: change.filename})
|
||||||
name = "updated attachment #{change.filename}"
|
|
||||||
diff = _.map change.changes, (values, name) ->
|
diff = _.map change.changes, (values, name) ->
|
||||||
return {
|
return {
|
||||||
name: getHumanizedFieldName(name)
|
name: getHumanizedFieldName(name)
|
||||||
from: formatChange(values[0])
|
from: formatChange(values[0])
|
||||||
to: formatChange(values[1])
|
to: formatChange(values[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
return templateChangeAttachment({name: name, diff: diff})
|
return templateChangeAttachment({name: name, diff: diff})
|
||||||
|
|
||||||
|
@ -177,16 +200,19 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
|
||||||
customAttributes = _.map value, (changes, type) ->
|
customAttributes = _.map value, (changes, type) ->
|
||||||
if type == "new"
|
if type == "new"
|
||||||
return _.map changes, (change) ->
|
return _.map changes, (change) ->
|
||||||
return templateChangeGeneric({
|
html = templateChangeGeneric({
|
||||||
name: change.name,
|
name: change.name,
|
||||||
from: formatChange(""),
|
from: formatChange(""),
|
||||||
to: formatChange(change.value)
|
to: formatChange(change.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
html = $compile(html)($scope)
|
||||||
|
|
||||||
|
return html[0].outerHTML
|
||||||
else if type == "deleted"
|
else if type == "deleted"
|
||||||
return _.map changes, (change) ->
|
return _.map changes, (change) ->
|
||||||
# TODO: i18n
|
|
||||||
return templateChangeDiff({
|
return templateChangeDiff({
|
||||||
name: "deleted custom attribute",
|
name: $translate.instant("ACTIVITY.DELETED_CUSTOM_ATTRIBUTE")
|
||||||
diff: change.name
|
diff: change.name
|
||||||
})
|
})
|
||||||
else
|
else
|
||||||
|
@ -207,7 +233,11 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
|
||||||
else if field == "blocked_note"
|
else if field == "blocked_note"
|
||||||
return templateChangeDiff({name: getHumanizedFieldName("blocked_note"), diff: value[1]})
|
return templateChangeDiff({name: getHumanizedFieldName("blocked_note"), diff: value[1]})
|
||||||
else if field == "points"
|
else if field == "points"
|
||||||
return templateChangePoints({points: value})
|
html = templateChangePoints({points: value})
|
||||||
|
|
||||||
|
html = $compile(html)($scope)
|
||||||
|
|
||||||
|
return html[0].outerHTML
|
||||||
else if field == "attachments"
|
else if field == "attachments"
|
||||||
return renderAttachmentEntry(value)
|
return renderAttachmentEntry(value)
|
||||||
else if field == "custom_attributes"
|
else if field == "custom_attributes"
|
||||||
|
@ -216,11 +246,15 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
|
||||||
name = getHumanizedFieldName(field)
|
name = getHumanizedFieldName(field)
|
||||||
removed = _.difference(value[0], value[1])
|
removed = _.difference(value[0], value[1])
|
||||||
added = _.difference(value[1], value[0])
|
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"
|
else if field == "assigned_to"
|
||||||
name = getHumanizedFieldName(field)
|
name = getHumanizedFieldName(field)
|
||||||
from = formatChange(value[0] or "Unassigned")
|
from = formatChange(value[0] or $translate.instant("ACTIVITY.VALUES.UNASSIGNED"))
|
||||||
to = formatChange(value[1] or "Unassigned")
|
to = formatChange(value[1] or $translate.instant("ACTIVITY.VALUES.UNASSIGNED"))
|
||||||
return templateChangeGeneric({name:name, from:from, to: to})
|
return templateChangeGeneric({name:name, from:from, to: to})
|
||||||
else
|
else
|
||||||
name = getHumanizedFieldName(field)
|
name = getHumanizedFieldName(field)
|
||||||
|
@ -233,44 +267,51 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
|
||||||
|
|
||||||
renderChangesHelperText = (change) ->
|
renderChangesHelperText = (change) ->
|
||||||
size = countChanges(change)
|
size = countChanges(change)
|
||||||
if size == 1
|
return $translate.instant("ACTIVITY.SIZE_CHANGE", {size: size}, 'messageformat')
|
||||||
return "Made #{size} change" # TODO: i18n
|
|
||||||
return "Made #{size} changes" # TODO: i18n
|
|
||||||
|
|
||||||
renderComment = (comment) ->
|
renderComment = (comment) ->
|
||||||
if (comment.delete_comment_date or comment.delete_comment_user?.name)
|
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
|
deleteCommentDate: moment(comment.delete_comment_date).format(getPrettyDateFormat()) if comment.delete_comment_date
|
||||||
deleteCommentUser: comment.delete_comment_user.name
|
deleteCommentUser: comment.delete_comment_user.name
|
||||||
deleteComment: comment.comment_html
|
deleteComment: comment.comment_html
|
||||||
activityId: comment.id
|
activityId: comment.id
|
||||||
canRestoreComment: comment.delete_comment_user.pk == $scope.user.id or $scope.project.my_permissions.indexOf("modify_project") > -1
|
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)
|
avatar: getUserAvatar(comment.user.pk)
|
||||||
userFullName: comment.user.name
|
userFullName: comment.user.name
|
||||||
creationDate: moment(comment.created_at).format("DD MMM YYYY HH:mm")
|
creationDate: moment(comment.created_at).format(getPrettyDateFormat())
|
||||||
comment: comment.comment_html
|
comment: comment.comment_html
|
||||||
changesText: renderChangesHelperText(comment)
|
changesText: renderChangesHelperText(comment)
|
||||||
changes: renderChangeEntries(comment)
|
changes: renderChangeEntries(comment)
|
||||||
mode: "comment"
|
mode: "comment"
|
||||||
deleteCommentDate: moment(comment.delete_comment_date).format("DD MMM YYYY HH:mm") if comment.delete_comment_date
|
deleteCommentDate: moment(comment.delete_comment_date).format(getPrettyDateFormat()) if comment.delete_comment_date
|
||||||
deleteCommentUser: comment.delete_comment_user.name if comment.delete_comment_user?.name
|
deleteCommentUser: comment.delete_comment_user.name if comment.delete_comment_user?.name
|
||||||
activityId: comment.id
|
activityId: comment.id
|
||||||
canDeleteComment: comment.user.pk == $scope.user?.id or $scope.project.my_permissions.indexOf("modify_project") > -1
|
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) ->
|
renderChange = (change) ->
|
||||||
return templateActivity({
|
return templateActivity({
|
||||||
avatar: getUserAvatar(change.user.pk)
|
avatar: getUserAvatar(change.user.pk)
|
||||||
userFullName: change.user.name
|
userFullName: change.user.name
|
||||||
creationDate: moment(change.created_at).format("DD MMM YYYY HH:mm")
|
creationDate: moment(change.created_at).format(getPrettyDateFormat())
|
||||||
comment: change.comment_html
|
comment: change.comment_html
|
||||||
changes: renderChangeEntries(change)
|
changes: renderChangeEntries(change)
|
||||||
changesText: ""
|
changesText: ""
|
||||||
mode: "activity"
|
mode: "activity"
|
||||||
deleteCommentDate: moment(change.delete_comment_date).format("DD MMM YYYY HH:mm") if change.delete_comment_date
|
deleteCommentDate: moment(change.delete_comment_date).format(getPrettyDateFormat()) if change.delete_comment_date
|
||||||
deleteCommentUser: change.delete_comment_user.name if change.delete_comment_user?.name
|
deleteCommentUser: change.delete_comment_user.name if change.delete_comment_user?.name
|
||||||
activityId: change.id
|
activityId: change.id
|
||||||
})
|
})
|
||||||
|
@ -281,7 +322,9 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
|
||||||
else
|
else
|
||||||
showMore = totalEntries - entries.length
|
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)
|
# Render into DOM (operations with dom mutability)
|
||||||
|
|
||||||
|
@ -394,7 +437,9 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) ->
|
||||||
$el.off()
|
$el.off()
|
||||||
|
|
||||||
templateFn = ($el, $attrs) ->
|
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 {
|
return {
|
||||||
controller: HistoryController
|
controller: HistoryController
|
||||||
|
@ -405,4 +450,5 @@ 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])
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
module = angular.module("taigaCommon")
|
module = angular.module("taigaCommon")
|
||||||
|
|
||||||
|
|
||||||
ImportProjectButtonDirective = ($rs, $confirm, $location, $navUrls) ->
|
ImportProjectButtonDirective = ($rs, $confirm, $location, $navUrls, $translate) ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
$el.on "click", ".import-project-button", (event) ->
|
$el.on "click", ".import-project-button", (event) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@ -34,34 +34,29 @@ ImportProjectButtonDirective = ($rs, $confirm, $location, $navUrls) ->
|
||||||
file = event.target.files[0]
|
file = event.target.files[0]
|
||||||
return if not file
|
return if not file
|
||||||
|
|
||||||
loader = $confirm.loader("Uploading dump file")
|
loader = $confirm.loader($translate.instant("PROJECT.IMPORT.UPLOADING_FILE"))
|
||||||
|
|
||||||
onSuccess = (result) ->
|
onSuccess = (result) ->
|
||||||
loader.stop()
|
loader.stop()
|
||||||
if result.status == 202 # Async mode
|
if result.status == 202 # Async mode
|
||||||
title = "Our Oompa Loompas are importing your project" # TODO: i18n
|
title = $translate.instant("PROJECT.IMPORT.ASYNC_IN_PROGRESS_TITLE")
|
||||||
message = "This process could take a few minutes <br/> We will send you
|
message = $translate.instant("PROJECT.IMPORT.ASYNC_IN_PROGRESS_MESSAGE")
|
||||||
an email when ready" # TODO: i18n
|
|
||||||
$confirm.success(title, message)
|
$confirm.success(title, message)
|
||||||
|
|
||||||
else # result.status == 201 # Sync mode
|
else # result.status == 201 # Sync mode
|
||||||
ctx = {project: result.data.slug}
|
ctx = {project: result.data.slug}
|
||||||
$location.path($navUrls.resolve("project-admin-project-profile-details", ctx))
|
$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) ->
|
onError = (result) ->
|
||||||
loader.stop()
|
loader.stop()
|
||||||
console.log "Error", result
|
errorMsg = $translate.instant("PROJECT.IMPORT.ERROR")
|
||||||
errorMsg = "Our oompa loompas have some problems importing your dump data.
|
|
||||||
Please try again. " # TODO: i18n
|
|
||||||
|
|
||||||
if result.status == 429 # TOO MANY REQUESTS
|
if result.status == 429 # TOO MANY REQUESTS
|
||||||
errorMsg = "Sorry, our oompa loompas are very busy right now.
|
errorMsg = $translate.instant("PROJECT.IMPORT.ERROR_TOO_MANY_REQUEST")
|
||||||
Please try again in a few minutes. " # TODO: i18n
|
|
||||||
else if result.data?._error_message
|
else if result.data?._error_message
|
||||||
errorMsg = "Our oompa loompas have some problems importing your dump data:
|
errorMsg = $translate.instant("PROJECT.IMPORT.ERROR_MESSAGE", {error_message: result.data._error_message})
|
||||||
#{result.data._error_message}" # TODO: i18n
|
|
||||||
|
|
||||||
$confirm.notify("error", errorMsg)
|
$confirm.notify("error", errorMsg)
|
||||||
|
|
||||||
loader.start()
|
loader.start()
|
||||||
|
@ -69,5 +64,5 @@ ImportProjectButtonDirective = ($rs, $confirm, $location, $navUrls) ->
|
||||||
|
|
||||||
return {link: link}
|
return {link: link}
|
||||||
|
|
||||||
module.directive("tgImportProjectButton", ["$tgResources", "$tgConfirm", "$location", "$tgNavUrls",
|
module.directive("tgImportProjectButton", ["$tgResources", "$tgConfirm", "$location", "$tgNavUrls", "$translate",
|
||||||
ImportProjectButtonDirective])
|
ImportProjectButtonDirective])
|
||||||
|
|
|
@ -86,7 +86,10 @@ class LightboxKeyboardNavigationService extends taiga.Service
|
||||||
|
|
||||||
# Key: enter
|
# Key: enter
|
||||||
if code == 13
|
if code == 13
|
||||||
activeElement.trigger("click")
|
if $el.find(".watcher-single").length == 1
|
||||||
|
$el.find('.watcher-single:first').trigger("click")
|
||||||
|
else
|
||||||
|
activeElement.trigger("click")
|
||||||
|
|
||||||
# Key: down
|
# Key: down
|
||||||
else if code == 40
|
else if code == 40
|
||||||
|
@ -143,9 +146,10 @@ module.directive("lightbox", ["lightboxService", LightboxDirective])
|
||||||
|
|
||||||
# Issue/Userstory blocking message lightbox directive.
|
# 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) ->
|
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) =>
|
unblock = $qqueue.bindAdd (item, finishCallback) =>
|
||||||
promise = $tgrepo.save(item)
|
promise = $tgrepo.save(item)
|
||||||
|
@ -213,14 +217,14 @@ BlockLightboxDirective = ($rootscope, $tgrepo, $confirm, lightboxService, $loadi
|
||||||
require: "ngModel"
|
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
|
## Generic Lightbox Blocking-Message Input Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
BlockingMessageInputDirective = ($log, $template) ->
|
BlockingMessageInputDirective = ($log, $template, $compile) ->
|
||||||
template = $template.get("common/lightbox/lightbox-blocking-message-input.html", true)
|
template = $template.get("common/lightbox/lightbox-blocking-message-input.html", true)
|
||||||
|
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
|
@ -243,14 +247,14 @@ BlockingMessageInputDirective = ($log, $template) ->
|
||||||
restrict: "EA"
|
restrict: "EA"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgBlockingMessageInput", ["$log", "$tgTemplate", BlockingMessageInputDirective])
|
module.directive("tgBlockingMessageInput", ["$log", "$tgTemplate", "$compile", BlockingMessageInputDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Create/Edit Userstory Lightbox Directive
|
## Create/Edit Userstory Lightbox Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
CreateEditUserstoryDirective = ($repo, $model, $rs, $rootScope, lightboxService, $loading) ->
|
CreateEditUserstoryDirective = ($repo, $model, $rs, $rootScope, lightboxService, $loading, $translate) ->
|
||||||
link = ($scope, $el, attrs) ->
|
link = ($scope, $el, attrs) ->
|
||||||
$scope.isNew = true
|
$scope.isNew = true
|
||||||
|
|
||||||
|
@ -267,8 +271,8 @@ CreateEditUserstoryDirective = ($repo, $model, $rs, $rootScope, lightboxService,
|
||||||
})
|
})
|
||||||
|
|
||||||
# Update texts for creation
|
# Update texts for creation
|
||||||
$el.find(".button-green").html("Create") #TODO: i18n
|
$el.find(".button-green").html($translate.instant("COMMON.CREATE"))
|
||||||
$el.find(".title").html("New user story ") #TODO: i18n
|
$el.find(".title").html($translate.instant("LIGHTBOX.CREATE_EDIT_US.NEW_US"))
|
||||||
$el.find(".tag-input").val("")
|
$el.find(".tag-input").val("")
|
||||||
|
|
||||||
$el.find(".blocked-note").addClass("hidden")
|
$el.find(".blocked-note").addClass("hidden")
|
||||||
|
@ -283,8 +287,8 @@ CreateEditUserstoryDirective = ($repo, $model, $rs, $rootScope, lightboxService,
|
||||||
$scope.isNew = false
|
$scope.isNew = false
|
||||||
|
|
||||||
# Update texts for edition
|
# Update texts for edition
|
||||||
$el.find(".button-green").html("Save") #TODO: i18n
|
$el.find(".button-green").html($translate.instant("COMMON.SAVE"))
|
||||||
$el.find(".title").html("Edit user story ") #TODO: i18n
|
$el.find(".title").html($translate.instant("LIGHTBOX.CREATE_EDIT_US.EDIT_US"))
|
||||||
$el.find(".tag-input").val("")
|
$el.find(".tag-input").val("")
|
||||||
|
|
||||||
# Update requirement info (team, client or blocked)
|
# Update requirement info (team, client or blocked)
|
||||||
|
@ -362,6 +366,7 @@ module.directive("tgLbCreateEditUserstory", [
|
||||||
"$rootScope",
|
"$rootScope",
|
||||||
"lightboxService",
|
"lightboxService",
|
||||||
"$tgLoading",
|
"$tgLoading",
|
||||||
|
"$translate",
|
||||||
CreateEditUserstoryDirective
|
CreateEditUserstoryDirective
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -424,7 +429,7 @@ module.directive("tgLbCreateBulkUserstories", [
|
||||||
## AssignedTo Lightbox Directive
|
## AssignedTo Lightbox Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
AssignedToLightboxDirective = (lightboxService, lightboxKeyboardNavigationService, $template) ->
|
AssignedToLightboxDirective = (lightboxService, lightboxKeyboardNavigationService, $template, $compile) ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
selectedUser = null
|
selectedUser = null
|
||||||
selectedItem = null
|
selectedItem = null
|
||||||
|
@ -458,6 +463,9 @@ AssignedToLightboxDirective = (lightboxService, lightboxKeyboardNavigationServic
|
||||||
}
|
}
|
||||||
|
|
||||||
html = usersTemplate(ctx)
|
html = usersTemplate(ctx)
|
||||||
|
|
||||||
|
html = $compile(html)($scope)
|
||||||
|
|
||||||
$el.find("div.watchers").html(html)
|
$el.find("div.watchers").html(html)
|
||||||
lightboxKeyboardNavigationService.init($el)
|
lightboxKeyboardNavigationService.init($el)
|
||||||
|
|
||||||
|
@ -517,7 +525,7 @@ AssignedToLightboxDirective = (lightboxService, lightboxKeyboardNavigationServic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module.directive("tgLbAssignedto", ["lightboxService", "lightboxKeyboardNavigationService", "$tgTemplate", AssignedToLightboxDirective])
|
module.directive("tgLbAssignedto", ["lightboxService", "lightboxKeyboardNavigationService", "$tgTemplate", "$compile", AssignedToLightboxDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -554,6 +562,7 @@ WatchersLightboxDirective = ($repo, lightboxService, lightboxKeyboardNavigationS
|
||||||
|
|
||||||
html = usersTemplate(ctx)
|
html = usersTemplate(ctx)
|
||||||
$el.find("div.watchers").html(html)
|
$el.find("div.watchers").html(html)
|
||||||
|
lightboxKeyboardNavigationService.init($el)
|
||||||
|
|
||||||
closeLightbox = () ->
|
closeLightbox = () ->
|
||||||
lightboxKeyboardNavigationService.stop()
|
lightboxKeyboardNavigationService.stop()
|
||||||
|
|
|
@ -99,7 +99,7 @@ module.directive("tgColorizeTags", ColorizeTagsDirective)
|
||||||
## TagLine Directive (for Lightboxes)
|
## TagLine Directive (for Lightboxes)
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
LbTagLineDirective = ($rs, $template) ->
|
LbTagLineDirective = ($rs, $template, $compile) ->
|
||||||
ENTER_KEY = 13
|
ENTER_KEY = 13
|
||||||
COMMA_KEY = 188
|
COMMA_KEY = 188
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ LbTagLineDirective = ($rs, $template) ->
|
||||||
if tag.color
|
if tag.color
|
||||||
tag.style = "border-left: 5px solid #{tag.color}"
|
tag.style = "border-left: 5px solid #{tag.color}"
|
||||||
|
|
||||||
html = templateTags(ctx)
|
html = $compile(templateTags(ctx))($scope)
|
||||||
$el.find("div.tags-container").html(html)
|
$el.find("div.tags-container").html(html)
|
||||||
|
|
||||||
showSaveButton = -> $el.find(".save").removeClass("hidden")
|
showSaveButton = -> $el.find(".save").removeClass("hidden")
|
||||||
|
@ -221,14 +221,14 @@ LbTagLineDirective = ($rs, $template) ->
|
||||||
templateUrl: "common/tag/lb-tag-line.html"
|
templateUrl: "common/tag/lb-tag-line.html"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgLbTagLine", ["$tgResources", "$tgTemplate", LbTagLineDirective])
|
module.directive("tgLbTagLine", ["$tgResources", "$tgTemplate", "$compile", LbTagLineDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## TagLine Directive (for detail pages)
|
## TagLine Directive (for detail pages)
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
TagLineDirective = ($rootScope, $repo, $rs, $confirm, $qqueue, $template) ->
|
TagLineDirective = ($rootScope, $repo, $rs, $confirm, $qqueue, $template, $compile) ->
|
||||||
ENTER_KEY = 13
|
ENTER_KEY = 13
|
||||||
ESC_KEY = 27
|
ESC_KEY = 27
|
||||||
COMMA_KEY = 188
|
COMMA_KEY = 188
|
||||||
|
@ -237,7 +237,10 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $qqueue, $template) ->
|
||||||
|
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
isEditable = ->
|
isEditable = ->
|
||||||
return $scope.project.my_permissions.indexOf($attrs.requiredPerm) != -1
|
if $attrs.requiredPerm?
|
||||||
|
return $scope.project.my_permissions.indexOf($attrs.requiredPerm) != -1
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
## Render
|
## Render
|
||||||
renderTags = (tags, tagsColors) ->
|
renderTags = (tags, tagsColors) ->
|
||||||
|
@ -245,7 +248,7 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $qqueue, $template) ->
|
||||||
tags: _.map(tags, (t) -> {name: t, color: tagsColors[t]})
|
tags: _.map(tags, (t) -> {name: t, color: tagsColors[t]})
|
||||||
isEditable: isEditable()
|
isEditable: isEditable()
|
||||||
}
|
}
|
||||||
html = templateTags(ctx)
|
html = $compile(templateTags(ctx))($scope)
|
||||||
$el.find("div.tags-container").html(html)
|
$el.find("div.tags-container").html(html)
|
||||||
|
|
||||||
renderInReadModeOnly = ->
|
renderInReadModeOnly = ->
|
||||||
|
@ -362,7 +365,7 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $qqueue, $template) ->
|
||||||
|
|
||||||
deleteValue(value)
|
deleteValue(value)
|
||||||
|
|
||||||
bindOnce $scope, "project", (project) ->
|
bindOnce $scope, "project.tags_colors", (tags_colors) ->
|
||||||
if not isEditable()
|
if not isEditable()
|
||||||
renderInReadModeOnly()
|
renderInReadModeOnly()
|
||||||
return
|
return
|
||||||
|
@ -376,7 +379,7 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $qqueue, $template) ->
|
||||||
menu.css("left", position.left)
|
menu.css("left", position.left)
|
||||||
|
|
||||||
$el.find("input").autocomplete({
|
$el.find("input").autocomplete({
|
||||||
source: _.keys(project.tags_colors)
|
source: _.keys(tags_colors)
|
||||||
position: {
|
position: {
|
||||||
my: "left top",
|
my: "left top",
|
||||||
using: positioningFunction
|
using: positioningFunction
|
||||||
|
@ -406,4 +409,5 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $qqueue, $template) ->
|
||||||
templateUrl: "common/tag/tag-line.html"
|
templateUrl: "common/tag/tag-line.html"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgTagLine", ["$rootScope", "$tgRepo", "$tgResources", "$tgConfirm", "$tgQqueue", "$tgTemplate", TagLineDirective])
|
module.directive("tgTagLine", ["$rootScope", "$tgRepo", "$tgResources", "$tgConfirm", "$tgQqueue",
|
||||||
|
"$tgTemplate", "$compile", TagLineDirective])
|
||||||
|
|
|
@ -55,16 +55,13 @@ module = angular.module("taigaCommon")
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## WYSIWYG markitup editor directive
|
## WYSIWYG markitup editor directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
tgMarkitupDirective = ($rootscope, $rs, $tr, $selectedText, $template) ->
|
MarkitupDirective = ($rootscope, $rs, $selectedText, $template, $compile, $translate) ->
|
||||||
previewTemplate = $template.get("common/wysiwyg/wysiwyg-markitup-preview.html", true)
|
previewTemplate = $template.get("common/wysiwyg/wysiwyg-markitup-preview.html", true)
|
||||||
|
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
element = angular.element($el)
|
element = angular.element($el)
|
||||||
previewDomNode = $("<div/>", {class: "preview"})
|
previewDomNode = $("<div/>", {class: "preview"})
|
||||||
|
|
||||||
#openHelp = ->
|
|
||||||
# window.open($rootscope.urls.wikiHelpUrl(), "_blank")
|
|
||||||
|
|
||||||
closePreviewMode = ->
|
closePreviewMode = ->
|
||||||
element.parents(".markdown").find(".preview").remove()
|
element.parents(".markdown").find(".preview").remove()
|
||||||
element.parents(".markItUp").show()
|
element.parents(".markItUp").show()
|
||||||
|
@ -76,7 +73,10 @@ tgMarkitupDirective = ($rootscope, $rs, $tr, $selectedText, $template) ->
|
||||||
markdownDomNode = element.parents(".markdown")
|
markdownDomNode = element.parents(".markdown")
|
||||||
markItUpDomNode = element.parents(".markItUp")
|
markItUpDomNode = element.parents(".markItUp")
|
||||||
$rs.mdrender.render($scope.projectId, $model.$modelValue).then (data) ->
|
$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()
|
markItUpDomNode.hide()
|
||||||
|
|
||||||
markdown = element.closest(".markdown")
|
markdown = element.closest(".markdown")
|
||||||
|
@ -130,168 +130,14 @@ tgMarkitupDirective = ($rootscope, $rs, $tr, $selectedText, $template) ->
|
||||||
else
|
else
|
||||||
return cursorPosition
|
return cursorPosition
|
||||||
|
|
||||||
markdownSettings =
|
|
||||||
nameSpace: "markdown"
|
|
||||||
onShiftEnter: {keepDefault:false, openWith:"\n\n"}
|
|
||||||
onEnter:
|
|
||||||
keepDefault: false,
|
|
||||||
replaceWith: () -> "\n"
|
|
||||||
afterInsert: (data) ->
|
|
||||||
lines = data.textarea.value.split("\n")
|
|
||||||
cursorLine = data.textarea.value[0..(data.caretPosition - 1)].split("\n").length
|
|
||||||
newLineContent = data.textarea.value[data.caretPosition..].split("\n")[0]
|
|
||||||
lastLine = lines[cursorLine - 1]
|
|
||||||
|
|
||||||
# unordered list -
|
|
||||||
match = lastLine.match /^(\s*- ).*/
|
|
||||||
|
|
||||||
if match
|
|
||||||
emptyListItem = lastLine.match /^(\s*)\-\s$/
|
|
||||||
|
|
||||||
if emptyListItem
|
|
||||||
markdownCaretPositon = addLine(data.textarea, cursorLine - 1)
|
|
||||||
else
|
|
||||||
markdownCaretPositon = addLine(data.textarea, cursorLine, "#{match[1]}")
|
|
||||||
|
|
||||||
# unordered list *
|
|
||||||
match = lastLine.match /^(\s*\* ).*/
|
|
||||||
|
|
||||||
if match
|
|
||||||
emptyListItem = lastLine.match /^(\s*\* )$/
|
|
||||||
|
|
||||||
if emptyListItem
|
|
||||||
markdownCaretPositon = addLine(data.textarea, cursorLine - 1)
|
|
||||||
else
|
|
||||||
markdownCaretPositon = addLine(data.textarea, cursorLine, "#{match[1]}")
|
|
||||||
|
|
||||||
# ordered list
|
|
||||||
match = lastLine.match /^(\s*)(\d+)\.\s/
|
|
||||||
|
|
||||||
if match
|
|
||||||
emptyListItem = lastLine.match /^(\s*)(\d+)\.\s$/
|
|
||||||
|
|
||||||
if emptyListItem
|
|
||||||
markdownCaretPositon = addLine(data.textarea, cursorLine - 1)
|
|
||||||
else
|
|
||||||
markdownCaretPositon = addLine(data.textarea, cursorLine, "#{match[1] + (parseInt(match[2], 10) + 1)}. ")
|
|
||||||
|
|
||||||
|
|
||||||
setCaretPosition(data.textarea, markdownCaretPositon) if markdownCaretPositon
|
|
||||||
|
|
||||||
markupSet: [
|
|
||||||
{
|
|
||||||
name: $tr.t("markdown-editor.heading-1")
|
|
||||||
key: "1"
|
|
||||||
placeHolder: $tr.t("markdown-editor.placeholder")
|
|
||||||
closeWith: (markItUp) -> markdownTitle(markItUp, "=")
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: $tr.t("markdown-editor.heading-2")
|
|
||||||
key: "2"
|
|
||||||
placeHolder: $tr.t("markdown-editor.placeholder")
|
|
||||||
closeWith: (markItUp) -> markdownTitle(markItUp, "-")
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: $tr.t("markdown-editor.heading-3")
|
|
||||||
key: "3"
|
|
||||||
openWith: "### "
|
|
||||||
placeHolder: $tr.t("markdown-editor.placeholder")
|
|
||||||
},
|
|
||||||
{
|
|
||||||
separator: "---------------"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: $tr.t("markdown-editor.bold")
|
|
||||||
key: "B"
|
|
||||||
openWith: "**"
|
|
||||||
closeWith: "**"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: $tr.t("markdown-editor.italic")
|
|
||||||
key: "I"
|
|
||||||
openWith: "_"
|
|
||||||
closeWith: "_"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: $tr.t("markdown-editor.strike")
|
|
||||||
key: "S"
|
|
||||||
openWith: "~~"
|
|
||||||
closeWith: "~~"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
separator: "---------------"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: $tr.t("markdown-editor.bulleted-list")
|
|
||||||
openWith: "- "
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: $tr.t("markdown-editor.numeric-list")
|
|
||||||
openWith: (markItUp) -> markItUp.line+". "
|
|
||||||
},
|
|
||||||
{
|
|
||||||
separator: "---------------"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: $tr.t("markdown-editor.picture")
|
|
||||||
key: "P"
|
|
||||||
replaceWith: '![[![Alternative text]!]](<<<[![Url:!:http://]!]>>> "[![Title]!]")'
|
|
||||||
beforeInsert:(markItUp) -> prepareUrlFormatting(markItUp)
|
|
||||||
afterInsert:(markItUp) -> urlFormatting(markItUp)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: $tr.t("markdown-editor.link")
|
|
||||||
key: "L"
|
|
||||||
openWith: "["
|
|
||||||
closeWith: '](<<<[![Url:!:http://]!]>>> "[![Title]!]")'
|
|
||||||
placeHolder: $tr.t("markdown-editor.link-placeholder")
|
|
||||||
beforeInsert:(markItUp) -> prepareUrlFormatting(markItUp)
|
|
||||||
afterInsert:(markItUp) -> urlFormatting(markItUp)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
separator: "---------------"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: $tr.t("markdown-editor.quotes")
|
|
||||||
openWith: "> "
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: $tr.t("markdown-editor.code-block")
|
|
||||||
openWith: "```\n"
|
|
||||||
closeWith: "\n```"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
separator: "---------------"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: $tr.t("markdown-editor.preview")
|
|
||||||
call: preview
|
|
||||||
className: "preview-icon"
|
|
||||||
},
|
|
||||||
# {
|
|
||||||
# separator: "---------------"
|
|
||||||
# },
|
|
||||||
# {
|
|
||||||
# name: $tr.t("markdown-editor.help")
|
|
||||||
# call: openHelp
|
|
||||||
# className: "help"
|
|
||||||
# }
|
|
||||||
]
|
|
||||||
afterInsert: (event) ->
|
|
||||||
target = angular.element(event.textarea)
|
|
||||||
$model.$setViewValue(target.val())
|
|
||||||
|
|
||||||
prepareUrlFormatting = (markItUp) ->
|
prepareUrlFormatting = (markItUp) ->
|
||||||
console.log(markItUp)
|
|
||||||
regex = /(<<<|>>>)/gi
|
regex = /(<<<|>>>)/gi
|
||||||
result = 0
|
result = 0
|
||||||
indices = []
|
indices = []
|
||||||
(indices.push(result.index)) while ( (result = regex.exec(markItUp.textarea.value)) )
|
(indices.push(result.index)) while ( (result = regex.exec(markItUp.textarea.value)) )
|
||||||
markItUp.donotparse = indices
|
markItUp.donotparse = indices
|
||||||
console.log(indices)
|
|
||||||
|
|
||||||
urlFormatting = (markItUp) ->
|
urlFormatting = (markItUp) ->
|
||||||
console.log(markItUp.donotparse)
|
|
||||||
regex = /<<</gi
|
regex = /<<</gi
|
||||||
result = 0
|
result = 0
|
||||||
startIndex = 0
|
startIndex = 0
|
||||||
|
@ -329,13 +175,186 @@ tgMarkitupDirective = ($rootscope, $rs, $tr, $selectedText, $template) ->
|
||||||
|
|
||||||
return "\n"+heading+"\n"
|
return "\n"+heading+"\n"
|
||||||
|
|
||||||
element.markItUp(markdownSettings)
|
renderMarkItUp = () ->
|
||||||
|
markdownSettings =
|
||||||
|
nameSpace: "markdown"
|
||||||
|
onShiftEnter: {keepDefault:false, openWith:"\n\n"}
|
||||||
|
onEnter:
|
||||||
|
keepDefault: false,
|
||||||
|
replaceWith: () -> "\n"
|
||||||
|
afterInsert: (data) ->
|
||||||
|
lines = data.textarea.value.split("\n")
|
||||||
|
cursorLine = data.textarea.value[0..(data.caretPosition - 1)].split("\n").length
|
||||||
|
newLineContent = data.textarea.value[data.caretPosition..].split("\n")[0]
|
||||||
|
lastLine = lines[cursorLine - 1]
|
||||||
|
|
||||||
|
# unordered list -
|
||||||
|
match = lastLine.match /^(\s*- ).*/
|
||||||
|
|
||||||
|
if match
|
||||||
|
emptyListItem = lastLine.match /^(\s*)\-\s$/
|
||||||
|
|
||||||
|
if emptyListItem
|
||||||
|
nline = cursorLine - 1
|
||||||
|
replace = null
|
||||||
|
else
|
||||||
|
nline = cursorLine
|
||||||
|
replace = "#{match[1]}"
|
||||||
|
|
||||||
|
markdownCaretPositon = addLine(data.textarea, nline, replace)
|
||||||
|
|
||||||
|
# unordered list *
|
||||||
|
match = lastLine.match /^(\s*\* ).*/
|
||||||
|
|
||||||
|
if match
|
||||||
|
emptyListItem = lastLine.match /^(\s*\* )$/
|
||||||
|
|
||||||
|
if emptyListItem
|
||||||
|
nline = cursorLine - 1
|
||||||
|
replace = null
|
||||||
|
else
|
||||||
|
nline = cursorLine
|
||||||
|
replace = "#{match[1]}"
|
||||||
|
|
||||||
|
markdownCaretPositon = addLine(data.textarea, nline, replace)
|
||||||
|
|
||||||
|
# ordered list
|
||||||
|
match = lastLine.match /^(\s*)(\d+)\.\s/
|
||||||
|
|
||||||
|
if match
|
||||||
|
emptyListItem = lastLine.match /^(\s*)(\d+)\.\s$/
|
||||||
|
|
||||||
|
if emptyListItem
|
||||||
|
nline = cursorLine - 1
|
||||||
|
replace = null
|
||||||
|
else
|
||||||
|
nline = cursorLine
|
||||||
|
replace = "#{match[1] + (parseInt(match[2], 10) + 1)}. "
|
||||||
|
|
||||||
|
markdownCaretPositon = addLine(data.textarea, nline, replace)
|
||||||
|
|
||||||
|
setCaretPosition(data.textarea, markdownCaretPositon) if markdownCaretPositon
|
||||||
|
|
||||||
|
markupSet: [
|
||||||
|
{
|
||||||
|
name: $translate.instant("COMMON.WYSIWYG.H1_BUTTON")
|
||||||
|
key: "1"
|
||||||
|
placeHolder: $translate.instant("COMMON.WYSIWYG.H1_SAMPLE_TEXT")
|
||||||
|
closeWith: (markItUp) -> markdownTitle(markItUp, "=")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $translate.instant("COMMON.WYSIWYG.H2_BUTTON")
|
||||||
|
key: "2"
|
||||||
|
placeHolder: $translate.instant("COMMON.WYSIWYG.H2_SAMPLE_TEXT")
|
||||||
|
closeWith: (markItUp) -> markdownTitle(markItUp, "-")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $translate.instant("COMMON.WYSIWYG.H3_BUTTON")
|
||||||
|
key: "3"
|
||||||
|
openWith: "### "
|
||||||
|
placeHolder: $translate.instant("COMMON.WYSIWYG.H3_SAMPLE_TEXT")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
separator: "---------------"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $translate.instant("COMMON.WYSIWYG.BOLD_BUTTON")
|
||||||
|
key: "B"
|
||||||
|
openWith: "**"
|
||||||
|
closeWith: "**"
|
||||||
|
placeHolder: $translate.instant("COMMON.WYSIWYG.BOLD_BUTTON_SAMPLE_TEXT")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $translate.instant("COMMON.WYSIWYG.ITALIC_SAMPLE_TEXT")
|
||||||
|
key: "I"
|
||||||
|
openWith: "_"
|
||||||
|
closeWith: "_"
|
||||||
|
placeHolder: $translate.instant("COMMON.WYSIWYG.ITALIC_SAMPLE_TEXT")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $translate.instant("COMMON.WYSIWYG.STRIKE_BUTTON")
|
||||||
|
key: "S"
|
||||||
|
openWith: "~~"
|
||||||
|
closeWith: "~~"
|
||||||
|
placeHolder: $translate.instant("COMMON.WYSIWYG.STRIKE_SAMPLE_TEXT")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
separator: "---------------"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $translate.instant("COMMON.WYSIWYG.BULLETED_LIST_BUTTON")
|
||||||
|
openWith: "- "
|
||||||
|
placeHolder: $translate.instant("COMMON.WYSIWYG.BULLETED_LIST_SAMPLE_TEXT")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $translate.instant("COMMON.WYSIWYG.NUMERIC_LIST_BUTTON")
|
||||||
|
openWith: (markItUp) -> markItUp.line+". "
|
||||||
|
placeHolder: $translate.instant("COMMON.WYSIWYG.NUMERIC_LIST_SAMPLE_TEXT")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
separator: "---------------"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $translate.instant("COMMON.WYSIWYG.PICTURE_BUTTON")
|
||||||
|
key: "P"
|
||||||
|
openWith: "'
|
||||||
|
placeHolder: $translate.instant("COMMON.WYSIWYG.PICTURE_SAMPLE_TEXT")
|
||||||
|
beforeInsert:(markItUp) -> prepareUrlFormatting(markItUp)
|
||||||
|
afterInsert:(markItUp) -> urlFormatting(markItUp)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $translate.instant("COMMON.WYSIWYG.LINK_BUTTON")
|
||||||
|
key: "L"
|
||||||
|
openWith: "["
|
||||||
|
closeWith: '](<<<[![Url:!:http://]!]>>> "[![Title]!]")'
|
||||||
|
placeHolder: $translate.instant("COMMON.WYSIWYG.LINK_SAMPLE_TEXT")
|
||||||
|
beforeInsert:(markItUp) -> prepareUrlFormatting(markItUp)
|
||||||
|
afterInsert:(markItUp) -> urlFormatting(markItUp)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
separator: "---------------"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $translate.instant("COMMON.WYSIWYG.QUOTE_BLOCK_BUTTON")
|
||||||
|
openWith: "> "
|
||||||
|
placeHolder: $translate.instant("COMMON.WYSIWYG.QUOTE_BLOCK_SAMPLE_TEXT")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $translate.instant("COMMON.WYSIWYG.CODE_BLOCK_BUTTON")
|
||||||
|
openWith: "```\n"
|
||||||
|
placeHolder: $translate.instant("COMMON.WYSIWYG.CODE_BLOCK_SAMPLE_TEXT")
|
||||||
|
closeWith: "\n```"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
separator: "---------------"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: $translate.instant("COMMON.WYSIWYG.PREVIEW_BUTTON")
|
||||||
|
call: preview
|
||||||
|
className: "preview-icon"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
afterInsert: (event) ->
|
||||||
|
target = angular.element(event.textarea)
|
||||||
|
$model.$setViewValue(target.val())
|
||||||
|
|
||||||
|
element
|
||||||
|
.markItUpRemove()
|
||||||
|
.markItUp(markdownSettings)
|
||||||
|
|
||||||
|
renderMarkItUp()
|
||||||
|
|
||||||
|
unbind = $rootscope.$on "$translateChangeEnd", renderMarkItUp
|
||||||
|
|
||||||
element.on "keypress", (event) ->
|
element.on "keypress", (event) ->
|
||||||
$scope.$apply()
|
$scope.$apply()
|
||||||
|
|
||||||
$scope.$on "$destroy", ->
|
$scope.$on "$destroy", ->
|
||||||
$el.off()
|
$el.off()
|
||||||
|
unbind()
|
||||||
|
|
||||||
return {link:link, require:"ngModel"}
|
return {link:link, require:"ngModel"}
|
||||||
|
|
||||||
module.directive("tgMarkitup", ["$rootScope", "$tgResources", "$tgI18n", "$selectedText", "$tgTemplate", tgMarkitupDirective])
|
module.directive("tgMarkitup", ["$rootScope", "$tgResources", "$selectedText", "$tgTemplate", "$compile",
|
||||||
|
"$translate", MarkitupDirective])
|
||||||
|
|
|
@ -47,13 +47,14 @@ class IssueDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
"$appTitle",
|
"$appTitle",
|
||||||
"$tgAnalytics",
|
"$tgAnalytics",
|
||||||
"$tgNavUrls",
|
"$tgNavUrls",
|
||||||
|
"$translate",
|
||||||
"tgLoader"
|
"tgLoader"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location,
|
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.issueRef = @params.issueref
|
||||||
@scope.sectionName = "Issue Details"
|
@scope.sectionName = @translate.instant("ISSUES.SECTION_NAME")
|
||||||
@.initializeEventHandlers()
|
@.initializeEventHandlers()
|
||||||
|
|
||||||
promise = @.loadInitialData()
|
promise = @.loadInitialData()
|
||||||
|
@ -145,7 +146,7 @@ module.controller("IssueDetailController", IssueDetailController)
|
||||||
## Issue status display directive
|
## Issue status display directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
IssueStatusDisplayDirective = ($template)->
|
IssueStatusDisplayDirective = ($template, $compile)->
|
||||||
# Display if a Issue is open or closed and its issueboard status.
|
# Display if a Issue is open or closed and its issueboard status.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
@ -165,6 +166,9 @@ IssueStatusDisplayDirective = ($template)->
|
||||||
is_closed: status.is_closed
|
is_closed: status.is_closed
|
||||||
status: status
|
status: status
|
||||||
})
|
})
|
||||||
|
|
||||||
|
html = $compile(html)($scope)
|
||||||
|
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
$scope.$watch $attrs.ngModel, (issue) ->
|
$scope.$watch $attrs.ngModel, (issue) ->
|
||||||
|
@ -179,14 +183,14 @@ IssueStatusDisplayDirective = ($template)->
|
||||||
require: "ngModel"
|
require: "ngModel"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgIssueStatusDisplay", ["$tgTemplate", IssueStatusDisplayDirective])
|
module.directive("tgIssueStatusDisplay", ["$tgTemplate", "$compile", IssueStatusDisplayDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Issue status button directive
|
## 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.
|
# Display the status of Issue and you can edit it.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
@ -211,6 +215,9 @@ IssueStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $t
|
||||||
statuses: $scope.statusList
|
statuses: $scope.statusList
|
||||||
editable: isEditable()
|
editable: isEditable()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
html = $compile(html)($scope)
|
||||||
|
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
save = $qqueue.bindAdd (statusId) =>
|
save = $qqueue.bindAdd (statusId) =>
|
||||||
|
@ -262,13 +269,13 @@ IssueStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $t
|
||||||
require: "ngModel"
|
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
|
## 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.
|
# Display the type of Issue and you can edit it.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
@ -293,6 +300,9 @@ IssueTypeButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $tem
|
||||||
typees: $scope.typeList
|
typees: $scope.typeList
|
||||||
editable: isEditable()
|
editable: isEditable()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
html = $compile(html)($scope)
|
||||||
|
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
save = $qqueue.bindAdd (type) =>
|
save = $qqueue.bindAdd (type) =>
|
||||||
|
@ -343,14 +353,14 @@ IssueTypeButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $tem
|
||||||
require: "ngModel"
|
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
|
## 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.
|
# Display the severity of Issue and you can edit it.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
@ -375,6 +385,9 @@ IssueSeverityButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue,
|
||||||
severityes: $scope.severityList
|
severityes: $scope.severityList
|
||||||
editable: isEditable()
|
editable: isEditable()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
html = $compile(html)($scope)
|
||||||
|
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
save = $qqueue.bindAdd (severity) =>
|
save = $qqueue.bindAdd (severity) =>
|
||||||
|
@ -427,14 +440,14 @@ IssueSeverityButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue,
|
||||||
require: "ngModel"
|
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
|
## 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.
|
# Display the priority of Issue and you can edit it.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
@ -459,6 +472,9 @@ IssuePriorityButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue,
|
||||||
priorityes: $scope.priorityList
|
priorityes: $scope.priorityList
|
||||||
editable: isEditable()
|
editable: isEditable()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
html = $compile(html)($scope)
|
||||||
|
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
save = $qqueue.bindAdd (priority) =>
|
save = $qqueue.bindAdd (priority) =>
|
||||||
|
@ -511,14 +527,14 @@ IssuePriorityButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue,
|
||||||
require: "ngModel"
|
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
|
## Promote Issue to US button directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
PromoteIssueToUsButtonDirective = ($rootScope, $repo, $confirm, $qqueue) ->
|
PromoteIssueToUsButtonDirective = ($rootScope, $repo, $confirm, $qqueue, $translate) ->
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
|
|
||||||
save = $qqueue.bindAdd (issue, finish) =>
|
save = $qqueue.bindAdd (issue, finish) =>
|
||||||
|
@ -548,8 +564,8 @@ PromoteIssueToUsButtonDirective = ($rootScope, $repo, $confirm, $qqueue) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
issue = $model.$modelValue
|
issue = $model.$modelValue
|
||||||
|
|
||||||
title = "Promote this issue to a new user story" # TODO: i18n
|
title = $translate.instant("ISSUES.CONFIRM_PROMOTE.TITLE")
|
||||||
message = "Are you sure you want to create a new US from this Issue?" # TODO: i18n
|
message = $translate.instant("ISSUES.CONFIRM_PROMOTE.MESSAGE")
|
||||||
subtitle = issue.subject
|
subtitle = issue.subject
|
||||||
|
|
||||||
$confirm.ask(title, subtitle, message).then (finish) =>
|
$confirm.ask(title, subtitle, message).then (finish) =>
|
||||||
|
@ -566,5 +582,5 @@ PromoteIssueToUsButtonDirective = ($rootScope, $repo, $confirm, $qqueue) ->
|
||||||
link: link
|
link: link
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgPromoteIssueToUsButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgQqueue",
|
module.directive("tgPromoteIssueToUsButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgQqueue", "$translate"
|
||||||
PromoteIssueToUsButtonDirective])
|
PromoteIssueToUsButtonDirective])
|
||||||
|
|
|
@ -51,12 +51,14 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
|
||||||
"$tgNavUrls",
|
"$tgNavUrls",
|
||||||
"$tgEvents",
|
"$tgEvents",
|
||||||
"$tgAnalytics",
|
"$tgAnalytics",
|
||||||
"tgLoader"
|
"tgLoader",
|
||||||
|
"$translate"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @urls, @params, @q, @location, @appTitle,
|
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @urls, @params, @q, @location, @appTitle,
|
||||||
@navUrls, @events, @analytics, tgLoader) ->
|
@navUrls, @events, @analytics, tgLoader, @translate) ->
|
||||||
@scope.sectionName = "Issues"
|
|
||||||
|
@scope.sectionName = @translate.instant("ISSUES.LIST_SECTION_NAME")
|
||||||
@scope.filters = {}
|
@scope.filters = {}
|
||||||
|
|
||||||
if _.isEmpty(@location.search())
|
if _.isEmpty(@location.search())
|
||||||
|
@ -310,7 +312,7 @@ module.controller("IssuesController", IssuesController)
|
||||||
## Issues Directive
|
## Issues Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
IssuesDirective = ($log, $location, $template) ->
|
IssuesDirective = ($log, $location, $template, $compile) ->
|
||||||
## Issues Pagination
|
## Issues Pagination
|
||||||
template = $template.get("issue/issue-paginator.html", true)
|
template = $template.get("issue/issue-paginator.html", true)
|
||||||
|
|
||||||
|
@ -360,7 +362,11 @@ IssuesDirective = ($log, $location, $template) ->
|
||||||
else
|
else
|
||||||
pages.push({classes: "page", num: i, type: "page"})
|
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) ->
|
$scope.$watch "issues", (value) ->
|
||||||
# Do nothing if value is not logical true
|
# Do nothing if value is not logical true
|
||||||
|
@ -427,14 +433,14 @@ IssuesDirective = ($log, $location, $template) ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgIssues", ["$log", "$tgLocation", "$tgTemplate", IssuesDirective])
|
module.directive("tgIssues", ["$log", "$tgLocation", "$tgTemplate", "$compile", IssuesDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Issues Filters Directive
|
## Issues Filters Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template) ->
|
IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $translate, $compile) ->
|
||||||
template = $template.get("issue/issues-filters.html", true)
|
template = $template.get("issue/issues-filters.html", true)
|
||||||
templateSelected = $template.get("issue/issues-filters-selected.html", true)
|
templateSelected = $template.get("issue/issues-filters-selected.html", true)
|
||||||
|
|
||||||
|
@ -468,6 +474,7 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template) -
|
||||||
f.style = "border-left: 3px solid #{f.color}"
|
f.style = "border-left: 3px solid #{f.color}"
|
||||||
|
|
||||||
html = templateSelected({filters:selectedFilters})
|
html = templateSelected({filters:selectedFilters})
|
||||||
|
html = $compile(html)($scope)
|
||||||
$el.find(".filters-applied").html(html)
|
$el.find(".filters-applied").html(html)
|
||||||
|
|
||||||
if selectedFilters.length > 0
|
if selectedFilters.length > 0
|
||||||
|
@ -481,6 +488,7 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template) -
|
||||||
f.style = "border-left: 3px solid #{f.color}"
|
f.style = "border-left: 3px solid #{f.color}"
|
||||||
|
|
||||||
html = template({filters:filters})
|
html = template({filters:filters})
|
||||||
|
html = $compile(html)($scope)
|
||||||
$el.find(".filter-list").html(html)
|
$el.find(".filter-list").html(html)
|
||||||
|
|
||||||
toggleFilterSelection = (type, id) ->
|
toggleFilterSelection = (type, id) ->
|
||||||
|
@ -533,12 +541,13 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template) -
|
||||||
|
|
||||||
$scope.$on "filters:issueupdate", (ctx, filters) ->
|
$scope.$on "filters:issueupdate", (ctx, filters) ->
|
||||||
html = template({filters:filters.statuses})
|
html = template({filters:filters.statuses})
|
||||||
|
html = $compile(html)($scope)
|
||||||
$el.find(".filter-list").html(html)
|
$el.find(".filter-list").html(html)
|
||||||
|
|
||||||
selectQFilter = debounceLeading 100, (value) ->
|
selectQFilter = debounceLeading 100, (value) ->
|
||||||
return if value is undefined
|
return if value is undefined
|
||||||
|
|
||||||
$ctrl.replaceFilter("page", null)
|
$ctrl.replaceFilter("page", null, true)
|
||||||
|
|
||||||
if value.length == 0
|
if value.length == 0
|
||||||
$ctrl.replaceFilter("q", null)
|
$ctrl.replaceFilter("q", null)
|
||||||
|
@ -590,8 +599,8 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template) -
|
||||||
|
|
||||||
target = angular.element(event.currentTarget)
|
target = angular.element(event.currentTarget)
|
||||||
customFilterName = target.parent().data('id')
|
customFilterName = target.parent().data('id')
|
||||||
title = "Delete custom filter" # TODO: i18n
|
title = $translate.instant("ISSUES.FILTERS.CONFIRM_DELETE.TITLE")
|
||||||
message = "the custom filter '#{customFilterName}'" # TODO: i18n
|
message = $translate.instant("ISSUES.FILTERS.CONFIRM_DELETE.MESSAGE", {customFilterName: customFilterName})
|
||||||
|
|
||||||
$confirm.askOnDelete(title, message).then (finish) ->
|
$confirm.askOnDelete(title, message).then (finish) ->
|
||||||
promise = $ctrl.deleteMyFilter(customFilterName)
|
promise = $ctrl.deleteMyFilter(customFilterName)
|
||||||
|
@ -615,6 +624,7 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template) -
|
||||||
$el.find('.save-filters').hide()
|
$el.find('.save-filters').hide()
|
||||||
$el.find('.my-filter-name').removeClass("hidden")
|
$el.find('.my-filter-name').removeClass("hidden")
|
||||||
$el.find('.my-filter-name').focus()
|
$el.find('.my-filter-name').focus()
|
||||||
|
$scope.$apply()
|
||||||
|
|
||||||
$el.on "keyup", ".my-filter-name", (event) ->
|
$el.on "keyup", ".my-filter-name", (event) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@ -652,8 +662,8 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template) -
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgIssuesFilters", ["$log", "$tgLocation", "$tgResources", "$tgConfirm", "$tgLoading", "$tgTemplate",
|
module.directive("tgIssuesFilters", ["$log", "$tgLocation", "$tgResources", "$tgConfirm", "$tgLoading",
|
||||||
IssuesFiltersDirective])
|
"$tgTemplate", "$translate", "$compile", IssuesFiltersDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -708,7 +718,28 @@ IssueStatusInlineEditionDirective = ($repo, $template, $rootscope) ->
|
||||||
updateIssueStatus($el, issue, $scope.issueStatusById)
|
updateIssueStatus($el, issue, $scope.issueStatusById)
|
||||||
|
|
||||||
$scope.$apply () ->
|
$scope.$apply () ->
|
||||||
$repo.save(issue).then
|
$repo.save(issue).then ->
|
||||||
|
|
||||||
|
for filter in $scope.filters.statuses
|
||||||
|
if filter.id == issue.status
|
||||||
|
filter.count++
|
||||||
|
|
||||||
|
$rootscope.$broadcast("filters:issueupdate", $scope.filters)
|
||||||
|
|
||||||
|
filtering = false
|
||||||
|
|
||||||
|
for filter in $scope.filters.statuses
|
||||||
|
if filter.selected == true
|
||||||
|
filtering = true
|
||||||
|
if filter.id == issue.status
|
||||||
|
return
|
||||||
|
|
||||||
|
if not filtering
|
||||||
|
return
|
||||||
|
|
||||||
|
for el, i in $scope.issues
|
||||||
|
if el and el.id == issue.id
|
||||||
|
$scope.issues.splice(i, 1)
|
||||||
|
|
||||||
for filter in $scope.filters.statuses
|
for filter in $scope.filters.statuses
|
||||||
if filter.id == issue.status
|
if filter.id == issue.status
|
||||||
|
@ -732,7 +763,8 @@ IssueStatusInlineEditionDirective = ($repo, $template, $rootscope) ->
|
||||||
|
|
||||||
return {link: link}
|
return {link: link}
|
||||||
|
|
||||||
module.directive("tgIssueStatusInlineEdition", ["$tgRepo", "$tgTemplate", "$rootScope", IssueStatusInlineEditionDirective])
|
module.directive("tgIssueStatusInlineEdition", ["$tgRepo", "$tgTemplate", "$rootScope",
|
||||||
|
IssueStatusInlineEditionDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -783,4 +815,5 @@ IssueAssignedToInlineEditionDirective = ($repo, $rootscope, popoverService) ->
|
||||||
|
|
||||||
return {link: link}
|
return {link: link}
|
||||||
|
|
||||||
module.directive("tgIssueAssignedToInlineEdition", ["$tgRepo", "$rootScope", IssueAssignedToInlineEditionDirective])
|
module.directive("tgIssueAssignedToInlineEdition", ["$tgRepo", "$rootScope",
|
||||||
|
IssueAssignedToInlineEditionDirective])
|
||||||
|
|
|
@ -62,15 +62,16 @@ class KanbanController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
|
||||||
"$tgNavUrls",
|
"$tgNavUrls",
|
||||||
"$tgEvents",
|
"$tgEvents",
|
||||||
"$tgAnalytics",
|
"$tgAnalytics",
|
||||||
"tgLoader"
|
"tgLoader",
|
||||||
|
"$translate"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location,
|
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location,
|
||||||
@appTitle, @navUrls, @events, @analytics, tgLoader) ->
|
@appTitle, @navUrls, @events, @analytics, tgLoader, @translate) ->
|
||||||
|
|
||||||
bindMethods(@)
|
bindMethods(@)
|
||||||
|
|
||||||
@scope.sectionName = "Kanban"
|
@scope.sectionName = @translate.instant("KANBAN.SECTION_NAME")
|
||||||
@scope.statusViewModes = {}
|
@scope.statusViewModes = {}
|
||||||
@.initializeEventHandlers()
|
@.initializeEventHandlers()
|
||||||
|
|
||||||
|
@ -307,10 +308,9 @@ module.directive("tgKanban", ["$tgRepo", "$rootScope", KanbanDirective])
|
||||||
## Kanban Archived Status Column Header Control
|
## Kanban Archived Status Column Header Control
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
KanbanArchivedStatusHeaderDirective = ($rootscope) ->
|
KanbanArchivedStatusHeaderDirective = ($rootscope, $translate) ->
|
||||||
#TODO: i18N
|
showArchivedText = $translate.instant("KANBAN.ACTION_SHOW_ARCHIVED")
|
||||||
showArchivedText = "Show archived"
|
hideArchivedText = $translate.instant("KANBAN.ACTION_HIDE_ARCHIVED")
|
||||||
hideArchivedText = "Hide archived"
|
|
||||||
|
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
status = $scope.$eval($attrs.tgKanbanArchivedStatusHeader)
|
status = $scope.$eval($attrs.tgKanbanArchivedStatusHeader)
|
||||||
|
@ -338,19 +338,18 @@ KanbanArchivedStatusHeaderDirective = ($rootscope) ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgKanbanArchivedStatusHeader", [ "$rootScope", KanbanArchivedStatusHeaderDirective])
|
module.directive("tgKanbanArchivedStatusHeader", [ "$rootScope", "$translate", KanbanArchivedStatusHeaderDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Kanban Archived Status Column Intro Directive
|
## Kanban Archived Status Column Intro Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
KanbanArchivedStatusIntroDirective = ->
|
KanbanArchivedStatusIntroDirective = ($translate) ->
|
||||||
# TODO: i18n
|
|
||||||
hiddenUserStoriexText = "The user stories in this status are hidden by default"
|
|
||||||
userStories = []
|
userStories = []
|
||||||
|
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
|
hiddenUserStoriexText = $translate.instant("KANBAN.HIDDEN_USER_STORIES")
|
||||||
status = $scope.$eval($attrs.tgKanbanArchivedStatusIntro)
|
status = $scope.$eval($attrs.tgKanbanArchivedStatusIntro)
|
||||||
$el.text(hiddenUserStoriexText)
|
$el.text(hiddenUserStoriexText)
|
||||||
|
|
||||||
|
@ -397,7 +396,7 @@ KanbanArchivedStatusIntroDirective = ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgKanbanArchivedStatusIntro", KanbanArchivedStatusIntroDirective)
|
module.directive("tgKanbanArchivedStatusIntro", ["$translate", KanbanArchivedStatusIntroDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -471,17 +470,20 @@ KanbanWipLimitDirective = ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
$el.disableSelection()
|
$el.disableSelection()
|
||||||
|
|
||||||
redrawWipLimit = ->
|
status = $scope.$eval($attrs.tgKanbanWipLimit)
|
||||||
|
|
||||||
|
redrawWipLimit = =>
|
||||||
$el.find(".kanban-wip-limit").remove()
|
$el.find(".kanban-wip-limit").remove()
|
||||||
timeout 200, ->
|
timeout 200, =>
|
||||||
element = $el.find(".kanban-task")[$scope.$eval($attrs.tgKanbanWipLimit)]
|
element = $el.find(".kanban-task")[status.wip_limit]
|
||||||
if element
|
if element
|
||||||
angular.element(element).before("<div class='kanban-wip-limit'></div>")
|
angular.element(element).before("<div class='kanban-wip-limit'></div>")
|
||||||
|
|
||||||
$scope.$on "redraw:wip", redrawWipLimit
|
if status and not status.is_archived
|
||||||
$scope.$on "kanban:us:move", redrawWipLimit
|
$scope.$on "redraw:wip", redrawWipLimit
|
||||||
$scope.$on "usform:new:success", redrawWipLimit
|
$scope.$on "kanban:us:move", redrawWipLimit
|
||||||
$scope.$on "usform:bulk:success", redrawWipLimit
|
$scope.$on "usform:new:success", redrawWipLimit
|
||||||
|
$scope.$on "usform:bulk:success", redrawWipLimit
|
||||||
|
|
||||||
$scope.$on "$destroy", ->
|
$scope.$on "$destroy", ->
|
||||||
$el.off()
|
$el.off()
|
||||||
|
@ -495,14 +497,14 @@ module.directive("tgKanbanWipLimit", KanbanWipLimitDirective)
|
||||||
## Kanban User Directive
|
## Kanban User Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
KanbanUserDirective = ($log) ->
|
KanbanUserDirective = ($log, $compile) ->
|
||||||
template = _.template("""
|
template = _.template("""
|
||||||
<figure class="avatar">
|
<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">
|
<img src="<%- imgurl %>" alt="<%- name %>" class="avatar">
|
||||||
</a>
|
</a>
|
||||||
</figure>
|
</figure>
|
||||||
""") # TODO: i18n
|
""")
|
||||||
|
|
||||||
clickable = false
|
clickable = false
|
||||||
|
|
||||||
|
@ -527,7 +529,7 @@ KanbanUserDirective = ($log) ->
|
||||||
else
|
else
|
||||||
ctx = {name: user.full_name_display, imgurl: user.photo, clickable: clickable}
|
ctx = {name: user.full_name_display, imgurl: user.photo, clickable: clickable}
|
||||||
|
|
||||||
html = template(ctx)
|
html = $compile(template(ctx))($scope)
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
username_label.text(ctx.name)
|
username_label.text(ctx.name)
|
||||||
|
|
||||||
|
@ -556,4 +558,4 @@ KanbanUserDirective = ($log) ->
|
||||||
|
|
||||||
return {link: link, require:"ngModel"}
|
return {link: link, require:"ngModel"}
|
||||||
|
|
||||||
module.directive("tgKanbanUserAvatar", ["$log", KanbanUserDirective])
|
module.directive("tgKanbanUserAvatar", ["$log", "$compile", KanbanUserDirective])
|
||||||
|
|
|
@ -249,15 +249,19 @@ ProjectMenuDirective = ($log, $compile, $auth, $rootscope, $tgAuth, $location, $
|
||||||
container.replaceWith(dom)
|
container.replaceWith(dom)
|
||||||
|
|
||||||
videoConferenceUrl = (project) ->
|
videoConferenceUrl = (project) ->
|
||||||
|
urlSeparator = "-"
|
||||||
if project.videoconferences == "appear-in"
|
if project.videoconferences == "appear-in"
|
||||||
baseUrl = "https://appear.in/"
|
baseUrl = "https://appear.in/"
|
||||||
else if project.videoconferences == "talky"
|
else if project.videoconferences == "talky"
|
||||||
baseUrl = "https://talky.io/"
|
baseUrl = "https://talky.io/"
|
||||||
|
else if project.videoconferences == "jitsi"
|
||||||
|
urlSeparator = ""
|
||||||
|
baseUrl = "https://meet.jit.si/"
|
||||||
else
|
else
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
if project.videoconferences_salt
|
if project.videoconferences_salt
|
||||||
url = "#{project.slug}-#{project.videoconferences_salt}"
|
url = "#{project.slug}#{urlSeparator}#{project.videoconferences_salt}"
|
||||||
else
|
else
|
||||||
url = "#{project.slug}"
|
url = "#{project.slug}"
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ debounce = @.taiga.debounce
|
||||||
|
|
||||||
module = angular.module("taigaProject")
|
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) ->
|
link = ($scope, $el, attrs) ->
|
||||||
$scope.data = {}
|
$scope.data = {}
|
||||||
$scope.templates = []
|
$scope.templates = []
|
||||||
|
@ -41,7 +41,9 @@ CreateProject = ($rootscope, $repo, $confirm, $location, $navurls, $rs, $project
|
||||||
|
|
||||||
$loading.finish(submitButton)
|
$loading.finish(submitButton)
|
||||||
$rootscope.$broadcast("projects:reload")
|
$rootscope.$broadcast("projects:reload")
|
||||||
$confirm.notify("success", "Success") #TODO: i18n
|
|
||||||
|
$confirm.notify("success", $translate.instant("COMMON.SAVE"))
|
||||||
|
|
||||||
$location.url($projectUrl.get(response))
|
$location.url($projectUrl.get(response))
|
||||||
lightboxService.close($el)
|
lightboxService.close($el)
|
||||||
|
|
||||||
|
@ -126,7 +128,7 @@ CreateProject = ($rootscope, $repo, $confirm, $location, $navurls, $rs, $project
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgLbCreateProject", ["$rootScope", "$tgRepo", "$tgConfirm", "$location", "$tgNavUrls",
|
module.directive("tgLbCreateProject", ["$rootScope", "$tgRepo", "$tgConfirm", "$location", "$tgNavUrls",
|
||||||
"$tgResources", "$projectUrl", "$tgLoading", "lightboxService", "$cacheFactory", CreateProject])
|
"$tgResources", "$projectUrl", "$tgLoading", "lightboxService", "$cacheFactory", "$translate", CreateProject])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
|
@ -25,7 +25,7 @@ debounce = @.taiga.debounce
|
||||||
|
|
||||||
module = angular.module("taigaRelatedTasks", [])
|
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)
|
templateView = $template.get("task/related-task-row.html", true)
|
||||||
templateEdit = $template.get("task/related-task-row-edit.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.find('input').focus().select()
|
||||||
|
|
||||||
$el.on "click", ".delete-task", (event) ->
|
$el.on "click", ".delete-task", (event) ->
|
||||||
#TODO: i18n
|
title = $translate.instant("TASK.TITLE_DELETE_ACTION")
|
||||||
task = $model.$modelValue
|
task = $model.$modelValue
|
||||||
title = "Delete Task"
|
|
||||||
message = task.subject
|
message = task.subject
|
||||||
|
|
||||||
$confirm.askOnDelete(title, message).then (finish) ->
|
$confirm.askOnDelete(title, message).then (finish) ->
|
||||||
|
@ -109,7 +108,7 @@ RelatedTaskRowDirective = ($repo, $compile, $confirm, $rootscope, $loading, $tem
|
||||||
|
|
||||||
return {link:link, require:"ngModel"}
|
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) ->
|
RelatedTaskCreateFormDirective = ($repo, $compile, $confirm, $tgmodel, $loading, $analytics, $template) ->
|
||||||
template = $template.get("task/related-task-create-form.html", true)
|
template = $template.get("task/related-task-create-form.html", true)
|
||||||
|
|
|
@ -24,59 +24,42 @@ taiga = @.taiga
|
||||||
class ResourcesService extends taiga.Service
|
class ResourcesService extends taiga.Service
|
||||||
|
|
||||||
urls = {
|
urls = {
|
||||||
|
# Auth
|
||||||
"auth": "/auth"
|
"auth": "/auth"
|
||||||
"auth-register": "/auth/register"
|
"auth-register": "/auth/register"
|
||||||
"invitations": "/invitations"
|
"invitations": "/invitations"
|
||||||
"permissions": "/permissions"
|
|
||||||
"roles": "/roles"
|
# User
|
||||||
"projects": "/projects"
|
|
||||||
"memberships": "/memberships"
|
|
||||||
"notify-policies": "/notify-policies"
|
|
||||||
"bulk-create-memberships": "/memberships/bulk_create"
|
|
||||||
"milestones": "/milestones"
|
|
||||||
"userstories": "/userstories"
|
|
||||||
"bulk-create-us": "/userstories/bulk_create"
|
|
||||||
"bulk-update-us-backlog-order": "/userstories/bulk_update_backlog_order"
|
|
||||||
"bulk-update-us-sprint-order": "/userstories/bulk_update_sprint_order"
|
|
||||||
"bulk-update-us-kanban-order": "/userstories/bulk_update_kanban_order"
|
|
||||||
"userstories-restore": "/userstories/%s/restore"
|
|
||||||
"tasks": "/tasks"
|
|
||||||
"bulk-create-tasks": "/tasks/bulk_create"
|
|
||||||
"bulk-update-task-taskboard-order": "/tasks/bulk_update_taskboard_order"
|
|
||||||
"tasks-restore": "/tasks/%s/restore"
|
|
||||||
"issues": "/issues"
|
|
||||||
"bulk-create-issues": "/issues/bulk_create"
|
|
||||||
"issues-restore": "/issues/%s/restore"
|
|
||||||
"wiki": "/wiki"
|
|
||||||
"wiki-restore": "/wiki/%s/restore"
|
|
||||||
"wiki-links": "/wiki-links"
|
|
||||||
"choices/userstory-statuses": "/userstory-statuses"
|
|
||||||
"choices/userstory-statuses/bulk-update-order": "/userstory-statuses/bulk_update_order"
|
|
||||||
"choices/points": "/points"
|
|
||||||
"choices/points/bulk-update-order": "/points/bulk_update_order"
|
|
||||||
"choices/task-statuses": "/task-statuses"
|
|
||||||
"choices/task-statuses/bulk-update-order": "/task-statuses/bulk_update_order"
|
|
||||||
"choices/issue-statuses": "/issue-statuses"
|
|
||||||
"choices/issue-statuses/bulk-update-order": "/issue-statuses/bulk_update_order"
|
|
||||||
"choices/issue-types": "/issue-types"
|
|
||||||
"choices/issue-types/bulk-update-order": "/issue-types/bulk_update_order"
|
|
||||||
"choices/priorities": "/priorities"
|
|
||||||
"choices/priorities/bulk-update-order": "/priorities/bulk_update_order"
|
|
||||||
"choices/severities": "/severities"
|
|
||||||
"choices/severities/bulk-update-order": "/severities/bulk_update_order"
|
|
||||||
"search": "/search"
|
|
||||||
"sites": "/sites"
|
|
||||||
"project-templates": "/project-templates"
|
|
||||||
"site-members": "/site-members"
|
|
||||||
"site-projects": "/site-projects"
|
|
||||||
"users": "/users"
|
"users": "/users"
|
||||||
"users-password-recovery": "/users/password_recovery"
|
"users-password-recovery": "/users/password_recovery"
|
||||||
"users-change-password-from-recovery": "/users/change_password_from_recovery"
|
"users-change-password-from-recovery": "/users/change_password_from_recovery"
|
||||||
"users-change-password": "/users/change_password"
|
"users-change-password": "/users/change_password"
|
||||||
"users-change-email": "/users/change_email"
|
"users-change-email": "/users/change_email"
|
||||||
"users-cancel-account": "/users/cancel"
|
"users-cancel-account": "/users/cancel"
|
||||||
|
|
||||||
|
# User - Notification
|
||||||
|
"notify-policies": "/notify-policies"
|
||||||
|
|
||||||
|
# User - Storage
|
||||||
"user-storage": "/user-storage"
|
"user-storage": "/user-storage"
|
||||||
|
|
||||||
|
# Memberships
|
||||||
|
"memberships": "/memberships"
|
||||||
|
"bulk-create-memberships": "/memberships/bulk_create"
|
||||||
|
|
||||||
|
# Roles & Permissions
|
||||||
|
"roles": "/roles"
|
||||||
|
"permissions": "/permissions"
|
||||||
|
|
||||||
|
# Resolver
|
||||||
"resolver": "/resolver"
|
"resolver": "/resolver"
|
||||||
|
|
||||||
|
# Project
|
||||||
|
"projects": "/projects"
|
||||||
|
"project-templates": "/project-templates"
|
||||||
|
"project-modules": "/projects/%s/modules"
|
||||||
|
|
||||||
|
# Project Values - Choises
|
||||||
"userstory-statuses": "/userstory-statuses"
|
"userstory-statuses": "/userstory-statuses"
|
||||||
"points": "/points"
|
"points": "/points"
|
||||||
"task-statuses": "/task-statuses"
|
"task-statuses": "/task-statuses"
|
||||||
|
@ -84,11 +67,30 @@ urls = {
|
||||||
"issue-types": "/issue-types"
|
"issue-types": "/issue-types"
|
||||||
"priorities": "/priorities"
|
"priorities": "/priorities"
|
||||||
"severities": "/severities"
|
"severities": "/severities"
|
||||||
"project-modules": "/projects/%s/modules"
|
|
||||||
"webhooks": "/webhooks"
|
# Milestones/Sprints
|
||||||
"webhooks-test": "/webhooks/%s/test"
|
"milestones": "/milestones"
|
||||||
"webhooklogs": "/webhooklogs"
|
|
||||||
"webhooklogs-resend": "/webhooklogs/%s/resend"
|
# User stories
|
||||||
|
"userstories": "/userstories"
|
||||||
|
"bulk-create-us": "/userstories/bulk_create"
|
||||||
|
"bulk-update-us-backlog-order": "/userstories/bulk_update_backlog_order"
|
||||||
|
"bulk-update-us-sprint-order": "/userstories/bulk_update_sprint_order"
|
||||||
|
"bulk-update-us-kanban-order": "/userstories/bulk_update_kanban_order"
|
||||||
|
|
||||||
|
# Tasks
|
||||||
|
"tasks": "/tasks"
|
||||||
|
"bulk-create-tasks": "/tasks/bulk_create"
|
||||||
|
"bulk-update-task-taskboard-order": "/tasks/bulk_update_taskboard_order"
|
||||||
|
|
||||||
|
# Issues
|
||||||
|
"issues": "/issues"
|
||||||
|
"bulk-create-issues": "/issues/bulk_create"
|
||||||
|
|
||||||
|
# Wiki pages
|
||||||
|
"wiki": "/wiki"
|
||||||
|
"wiki-restore": "/wiki/%s/restore"
|
||||||
|
"wiki-links": "/wiki-links"
|
||||||
|
|
||||||
# History
|
# History
|
||||||
"history/us": "/history/userstory"
|
"history/us": "/history/userstory"
|
||||||
|
@ -107,22 +109,34 @@ urls = {
|
||||||
"custom-attributes/issue": "/issue-custom-attributes"
|
"custom-attributes/issue": "/issue-custom-attributes"
|
||||||
"custom-attributes/task": "/task-custom-attributes"
|
"custom-attributes/task": "/task-custom-attributes"
|
||||||
|
|
||||||
# Custom field values
|
# Custom Attributess - Values
|
||||||
"custom-attributes-values/userstory": "/userstories/custom-attributes-values"
|
"custom-attributes-values/userstory": "/userstories/custom-attributes-values"
|
||||||
"custom-attributes-values/issue": "/issues/custom-attributes-values"
|
"custom-attributes-values/issue": "/issues/custom-attributes-values"
|
||||||
"custom-attributes-values/task": "/tasks/custom-attributes-values"
|
"custom-attributes-values/task": "/tasks/custom-attributes-values"
|
||||||
|
|
||||||
# Feedback
|
# Webhooks
|
||||||
"feedback": "/feedback"
|
"webhooks": "/webhooks"
|
||||||
|
"webhooks-test": "/webhooks/%s/test"
|
||||||
|
"webhooklogs": "/webhooklogs"
|
||||||
|
"webhooklogs-resend": "/webhooklogs/%s/resend"
|
||||||
|
|
||||||
|
# Reports - CSV
|
||||||
|
"userstories-csv": "/userstories/csv?uuid=%s"
|
||||||
|
"tasks-csv": "/tasks/csv?uuid=%s"
|
||||||
|
"issues-csv": "/issues/csv?uuid=%s"
|
||||||
|
|
||||||
|
# Search
|
||||||
|
"search": "/search"
|
||||||
|
|
||||||
# Export/Import
|
# Export/Import
|
||||||
"exporter": "/exporter"
|
"exporter": "/exporter"
|
||||||
"importer": "/importer/load_dump"
|
"importer": "/importer/load_dump"
|
||||||
|
|
||||||
# CSV
|
# Feedback
|
||||||
"userstories-csv": "/userstories/csv?uuid=%s"
|
"feedback": "/feedback"
|
||||||
"tasks-csv": "/tasks/csv?uuid=%s"
|
|
||||||
"issues-csv": "/issues/csv?uuid=%s"
|
# locales
|
||||||
|
"locales": "/locales"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Initialize api urls service
|
# Initialize api urls service
|
||||||
|
@ -168,5 +182,6 @@ module.run([
|
||||||
"$tgModulesResourcesProvider",
|
"$tgModulesResourcesProvider",
|
||||||
"$tgWebhooksResourcesProvider",
|
"$tgWebhooksResourcesProvider",
|
||||||
"$tgWebhookLogsResourcesProvider",
|
"$tgWebhookLogsResourcesProvider",
|
||||||
|
"$tgLocalesResourcesProvider",
|
||||||
initResources
|
initResources
|
||||||
])
|
])
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2015 Andrey Antukh <niwi@niwi.be>
|
||||||
|
# Copyright (C) 2015 Jesús Espino Garcia <jespinog@gmail.com>
|
||||||
|
# Copyright (C) 2015 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/resources/locales.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
|
||||||
|
taiga = @.taiga
|
||||||
|
sizeFormat = @.taiga.sizeFormat
|
||||||
|
|
||||||
|
|
||||||
|
resourceProvider = ($repo) ->
|
||||||
|
service = {
|
||||||
|
list: -> return $repo.queryMany("locales")
|
||||||
|
}
|
||||||
|
|
||||||
|
return (instance) ->
|
||||||
|
instance.locales = service
|
||||||
|
|
||||||
|
|
||||||
|
module = angular.module("taigaResources")
|
||||||
|
module.factory("$tgLocalesResourcesProvider", ["$tgRepo", resourceProvider])
|
||||||
|
|
|
@ -24,7 +24,7 @@ taiga = @.taiga
|
||||||
sizeFormat = @.taiga.sizeFormat
|
sizeFormat = @.taiga.sizeFormat
|
||||||
|
|
||||||
|
|
||||||
resourceProvider = ($config, $repo, $http, $urls, $auth, $q, $rootScope) ->
|
resourceProvider = ($config, $repo, $http, $urls, $auth, $q, $translate) ->
|
||||||
service = {}
|
service = {}
|
||||||
|
|
||||||
service.get = (projectId) ->
|
service.get = (projectId) ->
|
||||||
|
@ -85,21 +85,31 @@ resourceProvider = ($config, $repo, $http, $urls, $auth, $q, $rootScope) ->
|
||||||
|
|
||||||
maxFileSize = $config.get("maxUploadFileSize", null)
|
maxFileSize = $config.get("maxUploadFileSize", null)
|
||||||
if maxFileSize and file.size > maxFileSize
|
if maxFileSize and file.size > maxFileSize
|
||||||
|
errorMsg = $translate.instant("PROJECT.IMPORT.ERROR_MAX_SIZE_EXCEEDED", {
|
||||||
|
fileName: file.name
|
||||||
|
fileSize: sizeFormat(file.size)
|
||||||
|
maxFileSize: sizeFormat(maxFileSize)
|
||||||
|
})
|
||||||
|
|
||||||
response = {
|
response = {
|
||||||
status: 413,
|
status: 413,
|
||||||
data: _error_message: "'#{file.name}' (#{sizeFormat(file.size)}) is too heavy for our oompa
|
data: _error_message: errorMsg
|
||||||
loompas, try it with a smaller than (#{sizeFormat(maxFileSize)})"
|
|
||||||
}
|
}
|
||||||
defered.reject(response)
|
defered.reject(response)
|
||||||
return defered.promise
|
return defered.promise
|
||||||
|
|
||||||
uploadProgress = (evt) =>
|
uploadProgress = (evt) =>
|
||||||
percent = Math.round((evt.loaded / evt.total) * 100)
|
percent = Math.round((evt.loaded / evt.total) * 100)
|
||||||
message = "Uloaded #{sizeFormat(evt.loaded)} of #{sizeFormat(evt.total)}"
|
message = $translate.instant("PROJECT.IMPORT.UPLOAD_IN_PROGRESS_MESSAGE", {
|
||||||
|
uploadedSize: sizeFormat(evt.loaded)
|
||||||
|
totalSize: sizeFormat(evt.total)
|
||||||
|
})
|
||||||
statusUpdater("in-progress", null, message, percent)
|
statusUpdater("in-progress", null, message, percent)
|
||||||
|
|
||||||
uploadComplete = (evt) =>
|
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) =>
|
uploadFailed = (evt) =>
|
||||||
statusUpdater("error")
|
statusUpdater("error")
|
||||||
|
@ -141,5 +151,5 @@ resourceProvider = ($config, $repo, $http, $urls, $auth, $q, $rootScope) ->
|
||||||
|
|
||||||
|
|
||||||
module = angular.module("taigaResources")
|
module = angular.module("taigaResources")
|
||||||
module.factory("$tgProjectsResourcesProvider", ["$tgConfig", "$tgRepo", "$tgHttp", "$tgUrls", "$tgAuth", "$q",
|
module.factory("$tgProjectsResourcesProvider", ["$tgConfig", "$tgRepo", "$tgHttp", "$tgUrls", "$tgAuth",
|
||||||
resourceProvider])
|
"$q", "$translate", resourceProvider])
|
||||||
|
|
|
@ -34,7 +34,7 @@ module = angular.module("taigaTaskboard")
|
||||||
## Sprint burndown graph directive
|
## Sprint burndown graph directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
SprintGraphDirective = ->
|
SprintGraphDirective = ($translate)->
|
||||||
redrawChart = (element, dataToDraw) ->
|
redrawChart = (element, dataToDraw) ->
|
||||||
width = element.width()
|
width = element.width()
|
||||||
element.height(240)
|
element.height(240)
|
||||||
|
@ -64,13 +64,18 @@ SprintGraphDirective = ->
|
||||||
max: _.last(days)
|
max: _.last(days)
|
||||||
mode: "time"
|
mode: "time"
|
||||||
daysNames: days
|
daysNames: days
|
||||||
axisLabel: 'Day'
|
axisLabel: $translate.instant("TASKBOARD.CHARTS.XAXIS_LABEL")
|
||||||
axisLabelUseCanvas: true
|
axisLabelUseCanvas: true
|
||||||
axisLabelFontSizePixels: 12
|
axisLabelFontSizePixels: 12
|
||||||
axisLabelFontFamily: 'Verdana, Arial, Helvetica, Tahoma, sans-serif'
|
axisLabelFontFamily: 'Verdana, Arial, Helvetica, Tahoma, sans-serif'
|
||||||
axisLabelPadding: 5
|
axisLabelPadding: 5
|
||||||
yaxis:
|
yaxis:
|
||||||
min: 0
|
min: 0
|
||||||
|
axisLabel: $translate.instant("TASKBOARD.CHARTS.YAXIS_LABEL")
|
||||||
|
axisLabelUseCanvas: true
|
||||||
|
axisLabelFontSizePixels: 12
|
||||||
|
axisLabelFontFamily: 'Verdana, Arial, Helvetica, Tahoma, sans-serif'
|
||||||
|
axisLabelPadding: 5
|
||||||
series:
|
series:
|
||||||
shadowSize: 0
|
shadowSize: 0
|
||||||
lines:
|
lines:
|
||||||
|
@ -85,14 +90,20 @@ SprintGraphDirective = ->
|
||||||
tooltip: true
|
tooltip: true
|
||||||
tooltipOpts:
|
tooltipOpts:
|
||||||
content: (label, xval, yval, flotItem) ->
|
content: (label, xval, yval, flotItem) ->
|
||||||
#TODO: i18n
|
formattedDate = moment(xval).format($translate.instant("TASKBOARD.CHARTS.DATE"))
|
||||||
formattedDate = moment(xval).format("DD MMM")
|
|
||||||
roundedValue = Math.round(yval)
|
roundedValue = Math.round(yval)
|
||||||
|
|
||||||
if flotItem.seriesIndex == 1
|
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
|
else
|
||||||
return "Real pending points for day #{formattedDate} is #{roundedValue}"
|
return $translate.instant("TASKBOARD.CHARTS.REAL", {
|
||||||
|
formattedDate: formattedDate,
|
||||||
|
roundedValue: roundedValue
|
||||||
|
})
|
||||||
|
|
||||||
element.empty()
|
element.empty()
|
||||||
element.plot(data, options).data("plot")
|
element.plot(data, options).data("plot")
|
||||||
|
@ -121,5 +132,4 @@ SprintGraphDirective = ->
|
||||||
|
|
||||||
return {link: link}
|
return {link: link}
|
||||||
|
|
||||||
|
module.directive("tgSprintGraph", ["$translate", SprintGraphDirective])
|
||||||
module.directive("tgSprintGraph", SprintGraphDirective)
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ taiga = @.taiga
|
||||||
bindOnce = @.taiga.bindOnce
|
bindOnce = @.taiga.bindOnce
|
||||||
debounce = @.taiga.debounce
|
debounce = @.taiga.debounce
|
||||||
|
|
||||||
CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxService) ->
|
CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxService, $translate) ->
|
||||||
link = ($scope, $el, attrs) ->
|
link = ($scope, $el, attrs) ->
|
||||||
$scope.isNew = true
|
$scope.isNew = true
|
||||||
|
|
||||||
|
@ -40,10 +40,13 @@ CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxSer
|
||||||
$scope.isNew = true
|
$scope.isNew = true
|
||||||
|
|
||||||
# Update texts for creation
|
# Update texts for creation
|
||||||
$el.find(".button-green").html("Create") #TODO: i18n
|
create = $translate.instant("COMMON.CREATE")
|
||||||
$el.find(".title").html("New task ") #TODO: i18n
|
$el.find(".button-green").html(create)
|
||||||
$el.find(".tag-input").val("")
|
|
||||||
|
|
||||||
|
newTask = $translate.instant("LIGHTBOX.CREATE_EDIT_TASK.TITLE")
|
||||||
|
$el.find(".title").html(newTask + " ")
|
||||||
|
|
||||||
|
$el.find(".tag-input").val("")
|
||||||
lightboxService.open($el)
|
lightboxService.open($el)
|
||||||
|
|
||||||
$scope.$on "taskform:edit", (ctx, task) ->
|
$scope.$on "taskform:edit", (ctx, task) ->
|
||||||
|
@ -51,10 +54,13 @@ CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxSer
|
||||||
$scope.isNew = false
|
$scope.isNew = false
|
||||||
|
|
||||||
# Update texts for edition
|
# Update texts for edition
|
||||||
$el.find(".button-green").html("Save") #TODO: i18n
|
save = $translate.instant("COMMON.SAVE")
|
||||||
$el.find(".title").html("Edit task ") #TODO: i18n
|
edit = $translate.instant("LIGHTBOX.CREATE_EDIT_TASK.ACTION_EDIT")
|
||||||
$el.find(".tag-input").val("")
|
|
||||||
|
|
||||||
|
$el.find(".button-green").html(save)
|
||||||
|
$el.find(".title").html(edit + " ")
|
||||||
|
|
||||||
|
$el.find(".tag-input").val("")
|
||||||
lightboxService.open($el)
|
lightboxService.open($el)
|
||||||
|
|
||||||
|
|
||||||
|
@ -142,6 +148,7 @@ module.directive("tgLbCreateEditTask", [
|
||||||
"$rootScope",
|
"$rootScope",
|
||||||
"$tgLoading",
|
"$tgLoading",
|
||||||
"lightboxService",
|
"lightboxService",
|
||||||
|
"$translate"
|
||||||
CreateEditTaskDirective
|
CreateEditTaskDirective
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
|
@ -50,13 +50,14 @@ class TaskboardController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
"$tgEvents"
|
"$tgEvents"
|
||||||
"$tgAnalytics",
|
"$tgAnalytics",
|
||||||
"tgLoader"
|
"tgLoader"
|
||||||
|
"$translate"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @appTitle, @location, @navUrls,
|
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @appTitle, @location, @navUrls,
|
||||||
@events, @analytics, tgLoader) ->
|
@events, @analytics, tgLoader, @translate) ->
|
||||||
bindMethods(@)
|
bindMethods(@)
|
||||||
|
|
||||||
@scope.sectionName = "Taskboard"
|
@scope.sectionName = @translate.instant("TASKBOARD.SECTION_NAME")
|
||||||
@.initializeEventHandlers()
|
@.initializeEventHandlers()
|
||||||
|
|
||||||
promise = @.loadInitialData()
|
promise = @.loadInitialData()
|
||||||
|
@ -259,7 +260,6 @@ TaskboardDirective = ($rootscope) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
target = angular.element(event.currentTarget)
|
target = angular.element(event.currentTarget)
|
||||||
target.toggleClass('active');
|
target.toggleClass('active');
|
||||||
#toggleText(target, ["Hide statistics", "Show statistics"]) # TODO: i18n
|
|
||||||
$rootscope.$broadcast("taskboard:graph:toggle-visibility")
|
$rootscope.$broadcast("taskboard:graph:toggle-visibility")
|
||||||
|
|
||||||
tableBodyDom = $el.find(".taskboard-table-body")
|
tableBodyDom = $el.find(".taskboard-table-body")
|
||||||
|
|
|
@ -26,6 +26,7 @@ groupBy = @.taiga.groupBy
|
||||||
|
|
||||||
module = angular.module("taigaTasks")
|
module = angular.module("taigaTasks")
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Task Detail Controller
|
## Task Detail Controller
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -44,13 +45,14 @@ class TaskDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
"$appTitle",
|
"$appTitle",
|
||||||
"$tgNavUrls",
|
"$tgNavUrls",
|
||||||
"$tgAnalytics",
|
"$tgAnalytics",
|
||||||
|
"$translate",
|
||||||
"tgLoader"
|
"tgLoader"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location,
|
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location,
|
||||||
@log, @appTitle, @navUrls, @analytics, tgLoader) ->
|
@log, @appTitle, @navUrls, @analytics, @translate, tgLoader) ->
|
||||||
@scope.taskRef = @params.taskref
|
@scope.taskRef = @params.taskref
|
||||||
@scope.sectionName = "Task Details"
|
@scope.sectionName = @translate.instant("TASK.SECTION_NAME")
|
||||||
@.initializeEventHandlers()
|
@.initializeEventHandlers()
|
||||||
|
|
||||||
promise = @.loadInitialData()
|
promise = @.loadInitialData()
|
||||||
|
@ -145,7 +147,7 @@ module.controller("TaskDetailController", TaskDetailController)
|
||||||
## Task status display directive
|
## Task status display directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
TaskStatusDisplayDirective = ($template) ->
|
TaskStatusDisplayDirective = ($template, $compile) ->
|
||||||
# Display if a Task is open or closed and its taskboard status.
|
# Display if a Task is open or closed and its taskboard status.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
@ -165,6 +167,9 @@ TaskStatusDisplayDirective = ($template) ->
|
||||||
is_closed: status.is_closed
|
is_closed: status.is_closed
|
||||||
status: status
|
status: status
|
||||||
})
|
})
|
||||||
|
|
||||||
|
html = $compile(html)($scope)
|
||||||
|
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
$scope.$watch $attrs.ngModel, (task) ->
|
$scope.$watch $attrs.ngModel, (task) ->
|
||||||
|
@ -179,14 +184,14 @@ TaskStatusDisplayDirective = ($template) ->
|
||||||
require: "ngModel"
|
require: "ngModel"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgTaskStatusDisplay", ["$tgTemplate", TaskStatusDisplayDirective])
|
module.directive("tgTaskStatusDisplay", ["$tgTemplate", "$compile", TaskStatusDisplayDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Task status button directive
|
## Task status button directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
TaskStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue) ->
|
TaskStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $compile, $translate) ->
|
||||||
# Display the status of Task and you can edit it.
|
# Display the status of Task and you can edit it.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
@ -202,7 +207,7 @@ TaskStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue) ->
|
||||||
<span class="level" style="background-color:<%- status.color %>"></span>
|
<span class="level" style="background-color:<%- status.color %>"></span>
|
||||||
<span class="status-status"><%- status.name %></span>
|
<span class="status-status"><%- status.name %></span>
|
||||||
<% if(editable){ %><span class="icon icon-arrow-bottom"></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">
|
<ul class="popover pop-status">
|
||||||
<% _.each(statuses, function(st) { %>
|
<% _.each(statuses, function(st) { %>
|
||||||
|
@ -211,7 +216,7 @@ TaskStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue) ->
|
||||||
<% }); %>
|
<% }); %>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
""") #TODO: i18n
|
""")
|
||||||
|
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
isEditable = ->
|
isEditable = ->
|
||||||
|
@ -220,11 +225,12 @@ TaskStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue) ->
|
||||||
render = (task) =>
|
render = (task) =>
|
||||||
status = $scope.statusById[task.status]
|
status = $scope.statusById[task.status]
|
||||||
|
|
||||||
html = template({
|
html = $compile(template({
|
||||||
status: status
|
status: status
|
||||||
statuses: $scope.statusList
|
statuses: $scope.statusList
|
||||||
editable: isEditable()
|
editable: isEditable()
|
||||||
})
|
}))($scope)
|
||||||
|
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
save = $qqueue.bindAdd (status) =>
|
save = $qqueue.bindAdd (status) =>
|
||||||
|
@ -278,14 +284,15 @@ TaskStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgTaskStatusButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue",
|
module.directive("tgTaskStatusButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue",
|
||||||
TaskStatusButtonDirective])
|
"$compile", "$translate", TaskStatusButtonDirective])
|
||||||
|
|
||||||
|
|
||||||
TaskIsIocaineButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qqueue) ->
|
TaskIsIocaineButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qqueue, $compile) ->
|
||||||
template = _.template("""
|
template = _.template("""
|
||||||
<fieldset title="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!">
|
<fieldset title="{{ 'TASK.TITLE_ACTION_IOCAINE' | translate }}">
|
||||||
<label for="is-iocaine"
|
<label for="is-iocaine"
|
||||||
class="button button-gray is-iocaine <% if(isEditable){ %>editable<% }; %> <% if(isIocaine){ %>active<% }; %>">
|
translate="TASK.ACTION_IOCAINE"
|
||||||
|
class="button button-gray is-iocaine <% if(isEditable){ %>editable<% }; %> <% if(isIocaine){ %>active<% }; %>">
|
||||||
Iocaine
|
Iocaine
|
||||||
</label>
|
</label>
|
||||||
<input type="checkbox" id="is-iocaine" name="is-iocaine"/>
|
<input type="checkbox" id="is-iocaine" name="is-iocaine"/>
|
||||||
|
@ -305,7 +312,7 @@ TaskIsIocaineButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qqueue
|
||||||
isIocaine: task.is_iocaine
|
isIocaine: task.is_iocaine
|
||||||
isEditable: isEditable()
|
isEditable: isEditable()
|
||||||
}
|
}
|
||||||
html = template(ctx)
|
html = $compile(template(ctx))($scope)
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
save = $qqueue.bindAdd (is_iocaine) =>
|
save = $qqueue.bindAdd (is_iocaine) =>
|
||||||
|
@ -347,4 +354,5 @@ TaskIsIocaineButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qqueue
|
||||||
require: "ngModel"
|
require: "ngModel"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgTaskIsIocaineButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", TaskIsIocaineButtonDirective])
|
module.directive("tgTaskIsIocaineButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue",
|
||||||
|
"$compile", TaskIsIocaineButtonDirective])
|
||||||
|
|
|
@ -41,18 +41,20 @@ class TeamController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
"$tgNavUrls",
|
"$tgNavUrls",
|
||||||
"$appTitle",
|
"$appTitle",
|
||||||
"$tgAuth",
|
"$tgAuth",
|
||||||
"tgLoader"
|
"tgLoader",
|
||||||
|
"$translate"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @rootscope, @repo, @rs, @params, @q, @location, @navUrls, @appTitle, @auth, tgLoader) ->
|
constructor: (@scope, @rootscope, @repo, @rs, @params, @q, @location, @navUrls, @appTitle, @auth, tgLoader,
|
||||||
@scope.sectionName = "Team"
|
@translate) ->
|
||||||
|
@scope.sectionName = "TEAM.SECTION_NAME"
|
||||||
|
|
||||||
promise = @.loadInitialData()
|
promise = @.loadInitialData()
|
||||||
|
|
||||||
# On Success
|
# On Success
|
||||||
promise.then =>
|
promise.then =>
|
||||||
#TODO: i18n
|
text = @translate.instant("TEAM.APP_TITLE", {"projectName": @scope.project.name})
|
||||||
@appTitle.set("Team - " + @scope.project.name)
|
@appTitle.set(text)
|
||||||
|
|
||||||
# On Error
|
# On Error
|
||||||
promise.then null, @.onInitialDataError.bind(@)
|
promise.then null, @.onInitialDataError.bind(@)
|
||||||
|
@ -137,6 +139,7 @@ class TeamController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
|
|
||||||
module.controller("TeamController", TeamController)
|
module.controller("TeamController", TeamController)
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Team Filters Directive
|
## Team Filters Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -148,6 +151,7 @@ TeamFiltersDirective = () ->
|
||||||
|
|
||||||
module.directive("tgTeamFilters", [TeamFiltersDirective])
|
module.directive("tgTeamFilters", [TeamFiltersDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Team Member Stats Directive
|
## Team Member Stats Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -166,6 +170,7 @@ TeamMemberStatsDirective = () ->
|
||||||
|
|
||||||
module.directive("tgTeamMemberStats", TeamMemberStatsDirective)
|
module.directive("tgTeamMemberStats", TeamMemberStatsDirective)
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Team Current User Directive
|
## Team Current User Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -185,6 +190,7 @@ TeamMemberCurrentUserDirective = () ->
|
||||||
|
|
||||||
module.directive("tgTeamCurrentUser", TeamMemberCurrentUserDirective)
|
module.directive("tgTeamCurrentUser", TeamMemberCurrentUserDirective)
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Team Members Directive
|
## Team Members Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -207,15 +213,18 @@ TeamMembersDirective = () ->
|
||||||
|
|
||||||
module.directive("tgTeamMembers", TeamMembersDirective)
|
module.directive("tgTeamMembers", TeamMembersDirective)
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Leave project Directive
|
## Leave project Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
LeaveProjectDirective = ($repo, $confirm, $location, $rs, $navurls) ->
|
LeaveProjectDirective = ($repo, $confirm, $location, $rs, $navurls, $translate) ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
$scope.leave = () ->
|
$scope.leave = () ->
|
||||||
#TODO: i18n
|
leave_project_text = $translate.instant("TEAM.ACTION_LEAVE_PROJECT")
|
||||||
$confirm.ask("Leave this project", "Are you sure you want to leave the project?").then (finish) =>
|
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 = $rs.projects.leave($attrs.projectid)
|
||||||
|
|
||||||
promise.then =>
|
promise.then =>
|
||||||
|
@ -233,10 +242,17 @@ LeaveProjectDirective = ($repo, $confirm, $location, $rs, $navurls) ->
|
||||||
link: link
|
link: link
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgLeaveProject", ["$tgRepo", "$tgConfirm", "$tgLocation", "$tgResources", "$tgNavUrls", LeaveProjectDirective])
|
module.directive("tgLeaveProject", ["$tgRepo", "$tgConfirm", "$tgLocation", "$tgResources", "$tgNavUrls", "$translate",
|
||||||
|
LeaveProjectDirective])
|
||||||
|
|
||||||
module.filter 'membersRoleFilter', () ->
|
|
||||||
(input, filtersRole) ->
|
#############################################################################
|
||||||
if filtersRole?
|
## Team Filters
|
||||||
return _.filter(input, {role: filtersRole.id})
|
#############################################################################
|
||||||
return input
|
|
||||||
|
membersFilter = ->
|
||||||
|
return (members, filtersQ, filtersRole) ->
|
||||||
|
return _.filter members, (m) -> (not filtersRole or m.role == filtersRole.id) and
|
||||||
|
(not filtersQ or m.full_name.search(new RegExp(filtersQ, "i")) >= 0)
|
||||||
|
|
||||||
|
module.filter('membersFilter', membersFilter)
|
||||||
|
|
|
@ -42,11 +42,12 @@ class UserChangePasswordController extends mixOf(taiga.Controller, taiga.PageMix
|
||||||
"$q",
|
"$q",
|
||||||
"$tgLocation",
|
"$tgLocation",
|
||||||
"$tgNavUrls",
|
"$tgNavUrls",
|
||||||
"$tgAuth"
|
"$tgAuth",
|
||||||
|
"$translate"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @auth) ->
|
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @auth, @translate) ->
|
||||||
@scope.sectionName = "Change Password" #i18n
|
@scope.sectionName = @translate.instant("CHANGE_PASSWORD.SECTION_NAME")
|
||||||
@scope.project = {}
|
@scope.project = {}
|
||||||
@scope.user = @auth.getUser()
|
@scope.user = @auth.getUser()
|
||||||
|
|
||||||
|
@ -74,13 +75,13 @@ module.controller("UserChangePasswordController", UserChangePasswordController)
|
||||||
## User ChangePassword Directive
|
## User ChangePassword Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
UserChangePasswordDirective = ($rs, $confirm, $loading) ->
|
UserChangePasswordDirective = ($rs, $confirm, $loading, $translate) ->
|
||||||
link = ($scope, $el, $attrs, ctrl) ->
|
link = ($scope, $el, $attrs, ctrl) ->
|
||||||
submit = debounce 2000, (event) =>
|
submit = debounce 2000, (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
if $scope.newPassword1 != $scope.newPassword2
|
if $scope.newPassword1 != $scope.newPassword2
|
||||||
$confirm.notify('error', "The passwords dosn't match")
|
$confirm.notify('error', $translate.instant("CHANGE_PASSWORD.ERROR_PASSWORD_MATCH"))
|
||||||
return
|
return
|
||||||
|
|
||||||
$loading.start(submitButton)
|
$loading.start(submitButton)
|
||||||
|
|
|
@ -41,17 +41,21 @@ class UserSettingsController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
"$q",
|
"$q",
|
||||||
"$tgLocation",
|
"$tgLocation",
|
||||||
"$tgNavUrls",
|
"$tgNavUrls",
|
||||||
"$tgAuth"
|
"$tgAuth",
|
||||||
|
"$translate"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @rootscope, @config, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @auth) ->
|
constructor: (@scope, @rootscope, @config, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @auth, @translate) ->
|
||||||
@scope.sectionName = "User Profile" #i18n
|
@scope.sectionName = "USER_SETTINGS.MENU.SECTION_TITLE"
|
||||||
|
|
||||||
@scope.project = {}
|
@scope.project = {}
|
||||||
@scope.user = @auth.getUser()
|
@scope.user = @auth.getUser()
|
||||||
|
@scope.lang = @getLan()
|
||||||
|
|
||||||
maxFileSize = @config.get("maxUploadFileSize", null)
|
maxFileSize = @config.get("maxUploadFileSize", null)
|
||||||
if maxFileSize
|
if maxFileSize
|
||||||
@scope.maxFileSizeMsg = "[Max, size: #{sizeFormat(maxFileSize)}" # TODO: i18n
|
@translate("USER_SETTINGS.AVATAR_MAX_SIZE", {"maxFileSize": sizeFormat(maxFileSize)}).then (text) =>
|
||||||
|
@scope.maxFileSizeMsg = text
|
||||||
|
|
||||||
promise = @.loadInitialData()
|
promise = @.loadInitialData()
|
||||||
|
|
||||||
|
@ -63,16 +67,26 @@ class UserSettingsController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
@scope.$emit('project:loaded', project)
|
@scope.$emit('project:loaded', project)
|
||||||
return project
|
return project
|
||||||
|
|
||||||
|
loadLocales: ->
|
||||||
|
return @rs.locales.list().then (locales) =>
|
||||||
|
@scope.locales = locales
|
||||||
|
return locales
|
||||||
|
|
||||||
loadInitialData: ->
|
loadInitialData: ->
|
||||||
promise = @repo.resolve({pslug: @params.pslug}).then (data) =>
|
promise = @repo.resolve({pslug: @params.pslug}).then (data) =>
|
||||||
@scope.projectId = data.project
|
@scope.projectId = data.project
|
||||||
return data
|
return data
|
||||||
|
|
||||||
return promise.then(=> @.loadProject())
|
return @q.all([promise.then(=> @.loadProject()),
|
||||||
|
@.loadLocales()])
|
||||||
|
|
||||||
openDeleteLightbox: ->
|
openDeleteLightbox: ->
|
||||||
@rootscope.$broadcast("deletelightbox:new", @scope.user)
|
@rootscope.$broadcast("deletelightbox:new", @scope.user)
|
||||||
|
|
||||||
|
getLan: ->
|
||||||
|
return @scope.user.lang ||
|
||||||
|
@translate.preferredLanguage()
|
||||||
|
|
||||||
module.controller("UserSettingsController", UserSettingsController)
|
module.controller("UserSettingsController", UserSettingsController)
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,7 +94,7 @@ module.controller("UserSettingsController", UserSettingsController)
|
||||||
## User Profile Directive
|
## User Profile Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
UserProfileDirective = ($confirm, $auth, $repo) ->
|
UserProfileDirective = ($confirm, $auth, $repo, $translate) ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
submit = debounce 2000, (event) =>
|
submit = debounce 2000, (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@ -89,14 +103,14 @@ UserProfileDirective = ($confirm, $auth, $repo) ->
|
||||||
return if not form.validate()
|
return if not form.validate()
|
||||||
|
|
||||||
changeEmail = $scope.user.isAttributeModified("email")
|
changeEmail = $scope.user.isAttributeModified("email")
|
||||||
|
$scope.user.lang = $scope.lang
|
||||||
|
|
||||||
onSuccess = (data) =>
|
onSuccess = (data) =>
|
||||||
$auth.setUser(data)
|
$auth.setUser(data)
|
||||||
|
|
||||||
if changeEmail
|
if changeEmail
|
||||||
$confirm.success("<strong>Check your inbox!</strong><br />
|
text = $translate.instant("USER_PROFILE.CHANGE_EMAIL_SUCCESS")
|
||||||
We have sent a mail to your account<br />
|
$confirm.success(text)
|
||||||
with the instructions to set your new address") #TODO: i18n
|
|
||||||
else
|
else
|
||||||
$confirm.notify('success')
|
$confirm.notify('success')
|
||||||
|
|
||||||
|
@ -113,7 +127,7 @@ UserProfileDirective = ($confirm, $auth, $repo) ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgUserProfile", ["$tgConfirm", "$tgAuth", "$tgRepo", UserProfileDirective])
|
module.directive("tgUserProfile", ["$tgConfirm", "$tgAuth", "$tgRepo", "$translate", UserProfileDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
|
@ -45,7 +45,7 @@ class UserNotificationsController extends mixOf(taiga.Controller, taiga.PageMixi
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @auth) ->
|
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.project = {}
|
||||||
@scope.user = @auth.getUser()
|
@scope.user = @auth.getUser()
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ module.directive("tgUserNotifications", UserNotificationsDirective)
|
||||||
## User Notifications List Directive
|
## User Notifications List Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
UserNotificationsListDirective = ($repo, $confirm) ->
|
UserNotificationsListDirective = ($repo, $confirm, $compile) ->
|
||||||
template = _.template("""
|
template = _.template("""
|
||||||
<% _.each(notifyPolicies, function (notifyPolicy, index) { %>
|
<% _.each(notifyPolicies, function (notifyPolicy, index) { %>
|
||||||
<div class="policy-table-row" data-index="<%- index %>">
|
<div class="policy-table-row" data-index="<%- index %>">
|
||||||
|
@ -104,7 +104,8 @@ UserNotificationsListDirective = ($repo, $confirm) ->
|
||||||
<input type="radio"
|
<input type="radio"
|
||||||
name="policy-<%- notifyPolicy.id %>" id="policy-all-<%- notifyPolicy.id %>"
|
name="policy-<%- notifyPolicy.id %>" id="policy-all-<%- notifyPolicy.id %>"
|
||||||
value="2" <% if (notifyPolicy.notify_level == 2) { %>checked="checked"<% } %>/>
|
value="2" <% if (notifyPolicy.notify_level == 2) { %>checked="checked"<% } %>/>
|
||||||
<label for="policy-all-<%- notifyPolicy.id %>">All</label>
|
<label for="policy-all-<%- notifyPolicy.id %>"
|
||||||
|
translate="USER_SETTINGS.NOTIFICATIONS.OPTION_ALL"></label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
<div class="policy-table-involved">
|
<div class="policy-table-involved">
|
||||||
|
@ -112,7 +113,8 @@ UserNotificationsListDirective = ($repo, $confirm) ->
|
||||||
<input type="radio"
|
<input type="radio"
|
||||||
name="policy-<%- notifyPolicy.id %>" id="policy-involved-<%- notifyPolicy.id %>"
|
name="policy-<%- notifyPolicy.id %>" id="policy-involved-<%- notifyPolicy.id %>"
|
||||||
value="1" <% if (notifyPolicy.notify_level == 1) { %>checked="checked"<% } %> />
|
value="1" <% if (notifyPolicy.notify_level == 1) { %>checked="checked"<% } %> />
|
||||||
<label for="policy-involved-<%- notifyPolicy.id %>">Involved</label>
|
<label for="policy-involved-<%- notifyPolicy.id %>"
|
||||||
|
translate="USER_SETTINGS.NOTIFICATIONS.OPTION_INVOLVED"></label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
<div class="policy-table-none">
|
<div class="policy-table-none">
|
||||||
|
@ -120,7 +122,8 @@ UserNotificationsListDirective = ($repo, $confirm) ->
|
||||||
<input type="radio"
|
<input type="radio"
|
||||||
name="policy-<%- notifyPolicy.id %>" id="policy-none-<%- notifyPolicy.id %>"
|
name="policy-<%- notifyPolicy.id %>" id="policy-none-<%- notifyPolicy.id %>"
|
||||||
value="3" <% if (notifyPolicy.notify_level == 3) { %>checked="checked"<% } %> />
|
value="3" <% if (notifyPolicy.notify_level == 3) { %>checked="checked"<% } %> />
|
||||||
<label for="policy-none-<%- notifyPolicy.id %>">None</label>
|
<label for="policy-none-<%- notifyPolicy.id %>"
|
||||||
|
translate="USER_SETTINGS.NOTIFICATIONS.OPTION_NONE"></label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -130,13 +133,17 @@ UserNotificationsListDirective = ($repo, $confirm) ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
render = ->
|
render = ->
|
||||||
$el.off()
|
$el.off()
|
||||||
$el.html(template({notifyPolicies: $scope.notifyPolicies}))
|
|
||||||
|
ctx = {notifyPolicies: $scope.notifyPolicies}
|
||||||
|
html = template(ctx)
|
||||||
|
|
||||||
|
$el.html($compile(html)($scope))
|
||||||
|
|
||||||
$el.on "change", "input[type=radio]", (event) ->
|
$el.on "change", "input[type=radio]", (event) ->
|
||||||
target = angular.element(event.currentTarget)
|
target = angular.element(event.currentTarget)
|
||||||
|
|
||||||
policyIndex = target.parents(".policy-table-row").data('index')
|
policyIndex = target.parents(".policy-table-row").data('index')
|
||||||
policy = $scope.notifyPolicies[policyIndex]
|
policy = $scope.notifyPolicies[policyIndex]
|
||||||
|
|
||||||
prev_level = policy.notify_level
|
prev_level = policy.notify_level
|
||||||
policy.notify_level = parseInt(target.val(), 10)
|
policy.notify_level = parseInt(target.val(), 10)
|
||||||
|
|
||||||
|
@ -145,7 +152,9 @@ UserNotificationsListDirective = ($repo, $confirm) ->
|
||||||
|
|
||||||
onError = ->
|
onError = ->
|
||||||
$confirm.notify("error")
|
$confirm.notify("error")
|
||||||
target.parents(".policy-table-row").find("input[value=#{prev_level}]").prop("checked", true)
|
target.parents(".policy-table-row")
|
||||||
|
.find("input[value=#{prev_level}]")
|
||||||
|
.prop("checked", true)
|
||||||
|
|
||||||
$repo.save(policy).then(onSuccess, onError)
|
$repo.save(policy).then(onSuccess, onError)
|
||||||
|
|
||||||
|
@ -156,4 +165,5 @@ UserNotificationsListDirective = ($repo, $confirm) ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgUserNotificationsList", ["$tgRepo", "$tgConfirm", UserNotificationsListDirective])
|
module.directive("tgUserNotificationsList", ["$tgRepo", "$tgConfirm", "$compile",
|
||||||
|
UserNotificationsListDirective])
|
||||||
|
|
|
@ -45,13 +45,14 @@ class UserStoryDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
"$appTitle",
|
"$appTitle",
|
||||||
"$tgNavUrls",
|
"$tgNavUrls",
|
||||||
"$tgAnalytics",
|
"$tgAnalytics",
|
||||||
|
"$translate",
|
||||||
"tgLoader"
|
"tgLoader"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location,
|
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location,
|
||||||
@log, @appTitle, @navUrls, @analytics, tgLoader) ->
|
@log, @appTitle, @navUrls, @analytics, @translate, tgLoader) ->
|
||||||
@scope.usRef = @params.usref
|
@scope.usRef = @params.usref
|
||||||
@scope.sectionName = "User Story Details"
|
@scope.sectionName = @translate.instant("US.SECTION_NAME")
|
||||||
@.initializeEventHandlers()
|
@.initializeEventHandlers()
|
||||||
|
|
||||||
promise = @.loadInitialData()
|
promise = @.loadInitialData()
|
||||||
|
@ -178,7 +179,7 @@ module.controller("UserStoryDetailController", UserStoryDetailController)
|
||||||
## User story status display directive
|
## User story status display directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
UsStatusDisplayDirective = ($template) ->
|
UsStatusDisplayDirective = ($template, $compile) ->
|
||||||
# Display if a US is open or closed and its kanban status.
|
# Display if a US is open or closed and its kanban status.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
@ -192,10 +193,14 @@ UsStatusDisplayDirective = ($template) ->
|
||||||
|
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
render = (us) ->
|
render = (us) ->
|
||||||
|
status = $scope.statusById[us.status]
|
||||||
|
|
||||||
html = template({
|
html = template({
|
||||||
is_closed: us.is_closed
|
is_closed: us.is_closed
|
||||||
status: $scope.statusById[us.status]
|
status: status
|
||||||
})
|
})
|
||||||
|
|
||||||
|
html = $compile(html)($scope)
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
$scope.$watch $attrs.ngModel, (us) ->
|
$scope.$watch $attrs.ngModel, (us) ->
|
||||||
|
@ -210,14 +215,14 @@ UsStatusDisplayDirective = ($template) ->
|
||||||
require: "ngModel"
|
require: "ngModel"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgUsStatusDisplay", ["$tgTemplate", UsStatusDisplayDirective])
|
module.directive("tgUsStatusDisplay", ["$tgTemplate", "$compile", UsStatusDisplayDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## User story related tasts progress splay Directive
|
## User story related tasts progress splay Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
UsTasksProgressDisplayDirective = ($template) ->
|
UsTasksProgressDisplayDirective = ($template, $compile) ->
|
||||||
# Display a progress bar with the stats of completed tasks.
|
# Display a progress bar with the stats of completed tasks.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
@ -227,8 +232,6 @@ UsTasksProgressDisplayDirective = ($template) ->
|
||||||
# - Task object list (ng-model)
|
# - Task object list (ng-model)
|
||||||
# - scope.taskStatusById object
|
# - scope.taskStatusById object
|
||||||
|
|
||||||
template = $template.get("us/us-task-progress.html", true)
|
|
||||||
|
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
render = (tasks) ->
|
render = (tasks) ->
|
||||||
totalTasks = tasks.length
|
totalTasks = tasks.length
|
||||||
|
@ -236,12 +239,14 @@ UsTasksProgressDisplayDirective = ($template) ->
|
||||||
|
|
||||||
progress = if totalTasks > 0 then 100 * totalClosedTasks / totalTasks else 0
|
progress = if totalTasks > 0 then 100 * totalClosedTasks / totalTasks else 0
|
||||||
|
|
||||||
html = template({
|
_.assign($scope, {
|
||||||
totalTasks: totalTasks
|
totalTasks: totalTasks
|
||||||
totalClosedTasks: totalClosedTasks
|
totalClosedTasks: totalClosedTasks
|
||||||
progress: progress
|
progress: progress,
|
||||||
|
style: {
|
||||||
|
width: progress + "%"
|
||||||
|
}
|
||||||
})
|
})
|
||||||
$el.html(html)
|
|
||||||
|
|
||||||
$scope.$watch $attrs.ngModel, (tasks) ->
|
$scope.$watch $attrs.ngModel, (tasks) ->
|
||||||
render(tasks) if tasks?
|
render(tasks) if tasks?
|
||||||
|
@ -250,12 +255,14 @@ UsTasksProgressDisplayDirective = ($template) ->
|
||||||
$el.off()
|
$el.off()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
templateUrl: "us/us-task-progress.html"
|
||||||
link: link
|
link: link
|
||||||
restrict: "EA"
|
restrict: "EA"
|
||||||
require: "ngModel"
|
require: "ngModel"
|
||||||
|
scope: true
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgUsTasksProgressDisplay", ["$tgTemplate", UsTasksProgressDisplayDirective])
|
module.directive("tgUsTasksProgressDisplay", ["$tgTemplate", "$compile", UsTasksProgressDisplayDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -350,7 +357,7 @@ module.directive("tgUsStatusButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$t
|
||||||
## User story team requirements button directive
|
## 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)
|
template = $template.get("us/us-team-requirement-button.html", true)
|
||||||
|
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
|
@ -367,6 +374,8 @@ UsTeamRequirementButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qq
|
||||||
isRequired: us.team_requirement
|
isRequired: us.team_requirement
|
||||||
}
|
}
|
||||||
html = template(ctx)
|
html = template(ctx)
|
||||||
|
html = $compile(html)($scope)
|
||||||
|
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
save = $qqueue.bindAdd (team_requirement) =>
|
save = $qqueue.bindAdd (team_requirement) =>
|
||||||
|
@ -407,13 +416,13 @@ UsTeamRequirementButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qq
|
||||||
require: "ngModel"
|
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
|
## 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)
|
template = $template.get("us/us-client-requirement-button.html", true)
|
||||||
|
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
|
@ -429,7 +438,7 @@ UsClientRequirementButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $
|
||||||
canEdit: canEdit()
|
canEdit: canEdit()
|
||||||
isRequired: us.client_requirement
|
isRequired: us.client_requirement
|
||||||
}
|
}
|
||||||
html = template(ctx)
|
html = $compile(template(ctx))($scope)
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
save = $qqueue.bindAdd (client_requirement) =>
|
save = $qqueue.bindAdd (client_requirement) =>
|
||||||
|
@ -467,5 +476,5 @@ UsClientRequirementButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $
|
||||||
require: "ngModel"
|
require: "ngModel"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgUsClientRequirementButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate",
|
module.directive("tgUsClientRequirementButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue", "$tgTemplate", "$compile",
|
||||||
UsClientRequirementButtonDirective])
|
UsClientRequirementButtonDirective])
|
||||||
|
|
|
@ -49,11 +49,12 @@ class WikiDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
"$appTitle",
|
"$appTitle",
|
||||||
"$tgNavUrls",
|
"$tgNavUrls",
|
||||||
"$tgAnalytics",
|
"$tgAnalytics",
|
||||||
"tgLoader"
|
"tgLoader",
|
||||||
|
"$translate"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@scope, @rootscope, @repo, @model, @confirm, @rs, @params, @q, @location,
|
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.projectSlug = @params.pslug
|
||||||
@scope.wikiSlug = @params.slug
|
@scope.wikiSlug = @params.slug
|
||||||
@scope.sectionName = "Wiki"
|
@scope.sectionName = "Wiki"
|
||||||
|
@ -111,8 +112,7 @@ class WikiDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
@q.all([@.loadWikiLinks(), @.loadWiki()])
|
@q.all([@.loadWikiLinks(), @.loadWiki()])
|
||||||
|
|
||||||
delete: ->
|
delete: ->
|
||||||
# TODO: i18n
|
title = @translate.instant("WIKI.DELETE_LIGHTBOX_TITLE")
|
||||||
title = "Delete Wiki Page"
|
|
||||||
message = unslugify(@scope.wiki.slug)
|
message = unslugify(@scope.wiki.slug)
|
||||||
|
|
||||||
@confirm.askOnDelete(title, message).then (finish) =>
|
@confirm.askOnDelete(title, message).then (finish) =>
|
||||||
|
@ -135,7 +135,7 @@ module.controller("WikiDetailController", WikiDetailController)
|
||||||
## Wiki Summary Directive
|
## Wiki Summary Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
WikiSummaryDirective = ($log, $template) ->
|
WikiSummaryDirective = ($log, $template, $compile, $translate) ->
|
||||||
template = $template.get("wiki/wiki-summary.html", true)
|
template = $template.get("wiki/wiki-summary.html", true)
|
||||||
|
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
|
@ -152,10 +152,11 @@ WikiSummaryDirective = ($log, $template) ->
|
||||||
|
|
||||||
ctx = {
|
ctx = {
|
||||||
totalEditions: wiki.editions
|
totalEditions: wiki.editions
|
||||||
lastModifiedDate: moment(wiki.modified_date).format("DD MMM YYYY HH:mm")
|
lastModifiedDate: moment(wiki.modified_date).format($translate.instant("WIKI.DATETIME"))
|
||||||
user: user
|
user: user
|
||||||
}
|
}
|
||||||
html = template(ctx)
|
html = template(ctx)
|
||||||
|
html = $compile(html)($scope)
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
$scope.$watch $attrs.ngModel, (wikiPage) ->
|
$scope.$watch $attrs.ngModel, (wikiPage) ->
|
||||||
|
@ -171,7 +172,7 @@ WikiSummaryDirective = ($log, $template) ->
|
||||||
require: "ngModel"
|
require: "ngModel"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgWikiSummary", ["$log", "$tgTemplate", WikiSummaryDirective])
|
module.directive("tgWikiSummary", ["$log", "$tgTemplate", "$compile", "$translate", WikiSummaryDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
@ -215,7 +216,7 @@ EditableWikiContentDirective = ($window, $document, $repo, $confirm, $loading, $
|
||||||
if not wiki.id?
|
if not wiki.id?
|
||||||
$analytics.trackEvent("wikipage", "create", "create wiki page", 1)
|
$analytics.trackEvent("wikipage", "create", "create wiki page", 1)
|
||||||
|
|
||||||
$model.$setViewValue wikiPage
|
$model.$setViewValue wikiPage.clone()
|
||||||
|
|
||||||
$confirm.notify("success")
|
$confirm.notify("success")
|
||||||
switchToReadMode()
|
switchToReadMode()
|
||||||
|
|
|
@ -34,7 +34,7 @@ module = angular.module("taigaWiki")
|
||||||
## Wiki Main Directive
|
## 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)
|
template = $template.get("wiki/wiki-nav.html", true)
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
$ctrl = $el.controller()
|
$ctrl = $el.controller()
|
||||||
|
@ -53,6 +53,8 @@ WikiNavDirective = ($tgrepo, $log, $location, $confirm, $navUrls, $analytics, $l
|
||||||
deleteWikiLinkPermission: deleteWikiLinkPermission
|
deleteWikiLinkPermission: deleteWikiLinkPermission
|
||||||
})
|
})
|
||||||
|
|
||||||
|
html = $compile(html)($scope)
|
||||||
|
|
||||||
$el.off()
|
$el.off()
|
||||||
$el.html(html)
|
$el.html(html)
|
||||||
|
|
||||||
|
@ -80,8 +82,7 @@ WikiNavDirective = ($tgrepo, $log, $location, $confirm, $navUrls, $analytics, $l
|
||||||
target = angular.element(event.currentTarget)
|
target = angular.element(event.currentTarget)
|
||||||
linkId = target.parents('.wiki-link').data('id')
|
linkId = target.parents('.wiki-link').data('id')
|
||||||
|
|
||||||
# TODO: i18n
|
title = $translate.instant("WIKI.DELETE_LIGHTBOX_TITLE")
|
||||||
title = "Delete Wiki Link"
|
|
||||||
message = $scope.wikiLinks[linkId].title
|
message = $scope.wikiLinks[linkId].title
|
||||||
|
|
||||||
$confirm.askOnDelete(title, message).then (finish) =>
|
$confirm.askOnDelete(title, message).then (finish) =>
|
||||||
|
@ -143,4 +144,4 @@ WikiNavDirective = ($tgrepo, $log, $location, $confirm, $navUrls, $analytics, $l
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgWikiNav", ["$tgRepo", "$log", "$tgLocation", "$tgConfirm", "$tgNavUrls",
|
module.directive("tgWikiNav", ["$tgRepo", "$log", "$tgLocation", "$tgConfirm", "$tgNavUrls",
|
||||||
"$tgAnalytics", "$tgLoading", "$tgTemplate", WikiNavDirective])
|
"$tgAnalytics", "$tgLoading", "$tgTemplate", "$compile", "$translate", WikiNavDirective])
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
/*!
|
||||||
|
* jQuery UI Touch Punch 0.2.3
|
||||||
|
*
|
||||||
|
* Copyright 2011–2014, Dave Furfero
|
||||||
|
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||||
|
*
|
||||||
|
* Depends:
|
||||||
|
* jquery.ui.widget.js
|
||||||
|
* jquery.ui.mouse.js
|
||||||
|
*/
|
||||||
|
!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);
|
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,5 @@
|
||||||
###
|
###
|
||||||
# Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
|
# Copyright (C) 2015 Taiga Agile LLC
|
||||||
# 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
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License as
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
@ -16,7 +14,7 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
# File: modules/locales.coffee
|
# File: components.module.coffee
|
||||||
###
|
###
|
||||||
|
|
||||||
module = angular.module("taigaLocales", [])
|
angular.module("taigaComponents", [])
|
|
@ -2,7 +2,7 @@ ul.paginator
|
||||||
<% if (showPrevious) { %>
|
<% if (showPrevious) { %>
|
||||||
li.previous
|
li.previous
|
||||||
a(href="", class="previous next_prev_button", class="disabled")
|
a(href="", class="previous next_prev_button", class="disabled")
|
||||||
span(i18next="pagination.prev") Prev
|
span(translate="PAGINATION.PREVIOUS")
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<% _.each(pages, function(item) { %>
|
<% _.each(pages, function(item) { %>
|
||||||
|
@ -19,5 +19,5 @@ ul.paginator
|
||||||
<% if (showNext) { %>
|
<% if (showNext) { %>
|
||||||
li.next
|
li.next
|
||||||
a(href="", class="next next_prev_button", class="disabled")
|
a(href="", class="next next_prev_button", class="disabled")
|
||||||
span(i18next="pagination.next") Next
|
span(translate="PAGINATION.NEXT")
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.check
|
.check
|
||||||
input(type="checkbox", id!="<%- inputId %>")
|
input(type="checkbox", id!="<%- inputId %>")
|
||||||
div
|
div
|
||||||
span.check-text.check-yes Yes
|
span.check-text.check-yes(translate="COMMON.YES")
|
||||||
span.check-text.check-no No
|
span.check-text.check-no(translate="COMMON.NO")
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper.memberships(ng-controller="MembershipsController as ctrl",
|
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")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="memberships")
|
||||||
include ../includes/modules/admin-menu
|
include ../includes/modules/admin-menu
|
||||||
|
|
||||||
|
@ -9,8 +11,9 @@ div.wrapper.memberships(ng-controller="MembershipsController as ctrl",
|
||||||
include ../includes/components/mainTitle
|
include ../includes/components/mainTitle
|
||||||
|
|
||||||
.action-buttons
|
.action-buttons
|
||||||
a.button-green(title="Add new member" href="" ng-click="ctrl.addNewMembers()")
|
a.button-green(href="", title="{{ ADMIN.MEMBERSHIPS.ADD_BUTTON_TITLE | translate }}",
|
||||||
span.text + New member
|
ng-click="ctrl.addNewMembers()")
|
||||||
|
span.text(translate="ADMIN.MEMBERSHIPS.ADD_BUTTON")
|
||||||
|
|
||||||
include ../includes/modules/admin/admin-membership-table
|
include ../includes/modules/admin/admin-membership-table
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper(tg-project-default-values, ng-controller="ProjectProfileController as ctrl",
|
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")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-profile")
|
||||||
include ../includes/modules/admin-menu
|
include ../includes/modules/admin-menu
|
||||||
|
|
||||||
|
@ -9,7 +11,6 @@ div.wrapper(tg-project-default-values, ng-controller="ProjectProfileController a
|
||||||
section.main.admin-common
|
section.main.admin-common
|
||||||
header
|
header
|
||||||
include ../includes/components/mainTitle
|
include ../includes/components/mainTitle
|
||||||
|
p.admin-subtitle(translate="ADMIN.PROJECT_DEFAULT_VALUES.SUBTITLE")
|
||||||
p.total Default Values
|
|
||||||
|
|
||||||
include ../includes/modules/admin/default-values
|
include ../includes/modules/admin/default-values
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper(ng-controller="ProjectProfileController as ctrl",
|
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")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-profile")
|
||||||
include ../includes/modules/admin-menu
|
include ../includes/modules/admin-menu
|
||||||
|
|
||||||
|
@ -9,18 +12,18 @@ div.wrapper(ng-controller="ProjectProfileController as ctrl",
|
||||||
section.main.admin-common(tg-project-export)
|
section.main.admin-common(tg-project-export)
|
||||||
header
|
header
|
||||||
include ../includes/components/mainTitle
|
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
|
div.admin-project-export-buttons
|
||||||
a.button-green.button-export(href="", title="Export your project")
|
a.button-green.button-export(href="", title="{{ 'ADMIN.PROJECT_EXPORT.EXPORT_BUTTON_TITLE' | translate }}")
|
||||||
span Export
|
span(translate="ADMIN.PROJECT_EXPORT.EXPORT_BUTTON")
|
||||||
|
|
||||||
div.admin-project-export-result.hidden
|
div.admin-project-export-result.hidden
|
||||||
div.spin.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
|
h3.result-title
|
||||||
p.result-message
|
p.result-message
|
||||||
|
|
||||||
a.help-button(href="https://taiga.io/support/import-export-projects/", target="_blank")
|
a.help-button(href="https://taiga.io/support/import-export-projects/", target="_blank")
|
||||||
span.icon.icon-help
|
span.icon.icon-help
|
||||||
span Do you need help? Check out our support page!
|
span(translate="ADMIN.HELP")
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper(tg-project-modules, ng-controller="ProjectProfileController as ctrl",
|
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")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-profile")
|
||||||
include ../includes/modules/admin-menu
|
include ../includes/modules/admin-menu
|
||||||
|
|
||||||
|
@ -15,76 +17,76 @@ div.wrapper(tg-project-modules, ng-controller="ProjectProfileController as ctrl"
|
||||||
div.icon.icon-backlog
|
div.icon.icon-backlog
|
||||||
div.desc
|
div.desc
|
||||||
p
|
p
|
||||||
span Backlog
|
span.title(translate="ADMIN.MODULES.BACKLOG")
|
||||||
| Manage your user stories to maintain an organized view of upcoming and prioritized work.
|
span(translate="ADMIN.MODULES.BACKLOG_DESCRIPTION")
|
||||||
div.activate
|
div.activate
|
||||||
input.activate-input(type="checkbox", id="functionality-backlog",
|
input.activate-input(type="checkbox", id="functionality-backlog",
|
||||||
ng-model="project.is_backlog_activated")
|
ng-model="project.is_backlog_activated")
|
||||||
label.button.button-gray(ng-switch="project.is_backlog_activated",
|
label.button.button-gray(ng-switch="project.is_backlog_activated",
|
||||||
for="functionality-backlog")
|
for="functionality-backlog")
|
||||||
span(ng-switch-when="true") Disable
|
span(ng-switch-when="true", translate="ADMIN.MODULES.DISABLE")
|
||||||
span(ng-switch-when="false") Enable
|
span(ng-switch-when="false", translate="ADMIN.MODULES.ENABLE")
|
||||||
|
|
||||||
div.functionality(ng-class="{true:'active', false:''}[project.is_kanban_activated]")
|
div.functionality(ng-class="{true:'active', false:''}[project.is_kanban_activated]")
|
||||||
div.icon.icon-kanban
|
div.icon.icon-kanban
|
||||||
div.desc
|
div.desc
|
||||||
p
|
p
|
||||||
span Kanban
|
span.title(translate="ADMIN.MODULES.KANBAN")
|
||||||
| Organize your project in a lean way with this board.
|
span(translate="ADMIN.MODULES.KANBAN_DESCRIPTION")
|
||||||
div.activate
|
div.activate
|
||||||
input.activate-input(type="checkbox", id="functionality-kanban",
|
input.activate-input(type="checkbox", id="functionality-kanban",
|
||||||
ng-model="project.is_kanban_activated")
|
ng-model="project.is_kanban_activated")
|
||||||
label.button.button-gray(ng-switch="project.is_kanban_activated",
|
label.button.button-gray(ng-switch="project.is_kanban_activated",
|
||||||
for="functionality-kanban")
|
for="functionality-kanban")
|
||||||
span(ng-switch-when="true") Disable
|
span(ng-switch-when="true", translate="ADMIN.MODULES.DISABLE")
|
||||||
span(ng-switch-when="false") Enable
|
span(ng-switch-when="false", translate="ADMIN.MODULES.ENABLE")
|
||||||
|
|
||||||
div.functionality(ng-class="{true:'active', false:''}[project.is_issues_activated]")
|
div.functionality(ng-class="{true:'active', false:''}[project.is_issues_activated]")
|
||||||
div.icon.icon-issues
|
div.icon.icon-issues
|
||||||
div.desc
|
div.desc
|
||||||
p
|
p
|
||||||
span Issues
|
span.title(translate="ADMIN.MODULES.ISSUES")
|
||||||
| Track the bugs, questions and enhancements related to your project. Don't miss anything!
|
span(translate="ADMIN.MODULES.ISSUES_DESCRIPTION")
|
||||||
div.activate
|
div.activate
|
||||||
input.activate-input(type="checkbox", id="functionality-issues",
|
input.activate-input(type="checkbox", id="functionality-issues",
|
||||||
ng-model="project.is_issues_activated")
|
ng-model="project.is_issues_activated")
|
||||||
label.button.button-gray(ng-switch="project.is_issues_activated",
|
label.button.button-gray(ng-switch="project.is_issues_activated",
|
||||||
for="functionality-issues")
|
for="functionality-issues")
|
||||||
span(ng-switch-when="true") Disable
|
span(ng-switch-when="true", translate="ADMIN.MODULES.DISABLE")
|
||||||
span(ng-switch-when="false") Enable
|
span(ng-switch-when="false", translate="ADMIN.MODULES.ENABLE")
|
||||||
|
|
||||||
div.functionality(ng-class="{true:'active', false:''}[project.is_wiki_activated]")
|
div.functionality(ng-class="{true:'active', false:''}[project.is_wiki_activated]")
|
||||||
div.icon.icon-wiki
|
div.icon.icon-wiki
|
||||||
div.desc
|
div.desc
|
||||||
p
|
p
|
||||||
span Wiki
|
span.title(translate="ADMIN.MODULES.WIKI")
|
||||||
| Add, modify, or delete content in collaboration with others. This is the right place for your project documentation.
|
span(translate="ADMIN.MODULES.WIKI_DESCRIPTION")
|
||||||
div.activate
|
div.activate
|
||||||
input.activate-input(type="checkbox", id="functionality-wiki",
|
input.activate-input(type="checkbox", id="functionality-wiki",
|
||||||
ng-model="project.is_wiki_activated")
|
ng-model="project.is_wiki_activated")
|
||||||
label.button.button-gray(ng-switch="project.is_wiki_activated",
|
label.button.button-gray(ng-switch="project.is_wiki_activated",
|
||||||
for="functionality-wiki")
|
for="functionality-wiki")
|
||||||
span(ng-switch-when="true") Disable
|
span(ng-switch-when="true", translate="ADMIN.MODULES.DISABLE")
|
||||||
span(ng-switch-when="false") Enable
|
span(ng-switch-when="false", translate="ADMIN.MODULES.ENABLE")
|
||||||
|
|
||||||
div.functionality(ng-class="{true:'active', false:''}[isVideoconferenceActivated]")
|
div.functionality(ng-class="{true:'active', false:''}[isVideoconferenceActivated]")
|
||||||
div.icon.icon-video
|
div.icon.icon-video
|
||||||
div.desc
|
div.desc
|
||||||
p
|
p
|
||||||
span Meet Up
|
span.title(translate="ADMIN.MODULES.MEETUP")
|
||||||
| Choose your videoconference system. Even developers need face to face contact.
|
span(translate="ADMIN.MODULES.MEETUP_DESCRIPTION")
|
||||||
div.activate
|
div.activate
|
||||||
input.activate-input(type="checkbox", id="functionality-video",
|
input.activate-input(type="checkbox", id="functionality-video",
|
||||||
ng-model="isVideoconferenceActivated")
|
ng-model="isVideoconferenceActivated")
|
||||||
label.button.button-gray(ng-switch="isVideoconferenceActivated",
|
label.button.button-gray(ng-switch="isVideoconferenceActivated",
|
||||||
for="functionality-video")
|
for="functionality-video")
|
||||||
span(ng-switch-when="true") Disable
|
span(ng-switch-when="true", translate="ADMIN.MODULES.DISABLE")
|
||||||
span(ng-switch-when="false") Enable
|
span(ng-switch-when="false", translate="ADMIN.MODULES.ENABLE")
|
||||||
|
|
||||||
div.videoconference-attributes.hidden
|
div.videoconference-attributes.hidden
|
||||||
select(ng-model="project.videoconferences",
|
select(ng-model="project.videoconferences",
|
||||||
ng-options="e.id as e.name for e in [{'id':'appear-in', 'name':'AppearIn'},{'id':'talky', 'name': 'Talky'}]")
|
ng-options="e.id as e.name for e in [{'id':'appear-in', 'name':'AppearIn'},{'id':'jitsi', 'name': 'Jitsi'},{'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",
|
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")
|
placeholder="{{'ADMIN.MODULES.SALT_CHAT_ROOM' | translate}}")
|
||||||
button.button-green.submit-button(type="submit", title="Save") Save
|
button.button-green.submit-button(type="submit", title="{{'COMMON.SAVE' | translate}}", translate="COMMON.SAVE")
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper(tg-project-profile, ng-controller="ProjectProfileController as ctrl",
|
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")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-profile")
|
||||||
include ../includes/modules/admin-menu
|
include ../includes/modules/admin-menu
|
||||||
|
|
||||||
|
@ -12,29 +14,33 @@ div.wrapper(tg-project-profile, ng-controller="ProjectProfileController as ctrl"
|
||||||
|
|
||||||
form
|
form
|
||||||
fieldset
|
fieldset
|
||||||
label(for="project-name") Project Name
|
label(for="project-name", translate="ADMIN.PROJECT_PROFILE.PROJECT_NAME")
|
||||||
input(type="text", name="name", placeholder="Project name", id="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")
|
ng-model="project.name", data-required="true", maxlength="45")
|
||||||
|
|
||||||
fieldset
|
fieldset
|
||||||
label(for="project-slug") Project Slug
|
label(for="project-slug", translate="ADMIN.PROJECT_PROFILE.PROJECT_SLUG")
|
||||||
input(type="text", name="slug", placeholder="Slug", id="project-slug",
|
input(type="text", name="slug", placeholder="{{'ADMIN.PROJECT_PROFILE.PROJECT_SLUG' | translate}}", id="project-slug",
|
||||||
ng-model="project.slug", data-required="true")
|
ng-model="project.slug", data-required="true")
|
||||||
|
|
||||||
fieldset
|
fieldset
|
||||||
label(for="project-sprints") Number of sprints
|
label(for="project-sprints", translate="ADMIN.PROJECT_PROFILE.NUMBER_SPRINTS")
|
||||||
input(type="number", name="total_milestones", min="0", placeholder="Number of 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")
|
id="project-sprints", ng-model="project.total_milestones", data-type="digits")
|
||||||
|
|
||||||
fieldset
|
fieldset
|
||||||
label(for="total-story-points") 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="Number of 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",
|
id="total-story-points", ng-model="project.total_story_points",
|
||||||
data-type="digits", data-required="true")
|
data-type="digits", data-required="true")
|
||||||
|
|
||||||
fieldset
|
fieldset
|
||||||
label(for="project-description") Description
|
label(for="tags", translate="ADMIN.PROJECT_PROFILE.TAGS")
|
||||||
textarea(name="description", placeholder="Description", id="project-description",
|
div.tags-block(tg-lb-tag-line, ng-model="project.tags")
|
||||||
|
|
||||||
|
fieldset
|
||||||
|
label(for="project-description", translate="ADMIN.PROJECT_PROFILE.DESCRIPTION")
|
||||||
|
textarea(name="description", ng-attr-placeholder="{{'ADMIN.PROJECT_PROFILE.DESCRIPTION' | translate}}", id="project-description",
|
||||||
ng-model="project.description", data-required="true")
|
ng-model="project.description", data-required="true")
|
||||||
|
|
||||||
div
|
div
|
||||||
|
@ -42,14 +48,14 @@ div.wrapper(tg-project-profile, ng-controller="ProjectProfileController as ctrl"
|
||||||
div
|
div
|
||||||
input.privacy-project(type="radio", name="private-project", ng-model="project.is_private", ng-value="false")
|
input.privacy-project(type="radio", name="private-project", ng-model="project.is_private", ng-value="false")
|
||||||
label.trans-button(for="public-project")
|
label.trans-button(for="public-project")
|
||||||
span Public Project
|
span(translate="ADMIN.PROJECT_PROFILE.PUBLIC_PROJECT")
|
||||||
div
|
div
|
||||||
input.privacy-project(type="radio", name="private-project", ng-model="project.is_private", ng-value="true")
|
input.privacy-project(type="radio", name="private-project", ng-model="project.is_private", ng-value="true")
|
||||||
label.trans-button(for="private-project")
|
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
|
button.button-green.submit-button(type="submit", title="{{'COMMON.SAVE' | translate}}", translate="COMMON.SAVE")
|
||||||
a.delete-project(href="", title="Delete this project", ng-click="ctrl.openDeleteLightbox()") Delete this project
|
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)
|
div.lightbox.lightbox-delete-project(tg-lb-delete-project)
|
||||||
include ../includes/modules/lightbox-delete-project
|
include ../includes/modules/lightbox-delete-project
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper(ng-controller="ProjectProfileController as ctrl",
|
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")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-profile")
|
||||||
include ../includes/modules/admin-menu
|
include ../includes/modules/admin-menu
|
||||||
|
|
||||||
|
@ -9,24 +11,15 @@ div.wrapper(ng-controller="ProjectProfileController as ctrl",
|
||||||
section.main.admin-common(tg-project-export)
|
section.main.admin-common(tg-project-export)
|
||||||
header
|
header
|
||||||
include ../includes/components/mainTitle
|
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";
|
div.admin-attributes-section(tg-csv-us)
|
||||||
- var controller = "CsvExporterUserstoriesController";
|
div.admin-attributes-section(tg-csv-task)
|
||||||
div.admin-attributes-section
|
div.admin-attributes-section(tg-csv-issue)
|
||||||
include ../includes/modules/admin/project-csv
|
|
||||||
|
|
||||||
- var csvType = "Task";
|
div
|
||||||
- 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
|
|
||||||
a.help-button(href="https://taiga.io/support/csv-reports/", target="_blank")
|
a.help-button(href="https://taiga.io/support/csv-reports/", target="_blank")
|
||||||
span.icon.icon-help
|
span.icon.icon-help
|
||||||
span How to use this on my own spreadsheet?
|
span(translate="ADMIN.REPORTS.HELP")
|
||||||
|
|
|
@ -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")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
|
||||||
include ../includes/modules/admin-menu
|
include ../includes/modules/admin-menu
|
||||||
|
|
||||||
|
@ -7,25 +10,19 @@ div.wrapper(ng-controller="ProjectValuesSectionController")
|
||||||
|
|
||||||
section.main.admin-common.admin-attributes
|
section.main.admin-common.admin-attributes
|
||||||
include ../includes/components/mainTitle
|
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,
|
div.admin-attributes-section(tg-project-custom-attributes,
|
||||||
ng-controller="ProjectCustomAttributesController as ctrl",
|
ng-controller="ProjectCustomAttributesController as ctrl",
|
||||||
ng-init="type='userstory';")
|
ng-init="type='userstory'; customFieldSectionTitle='ADMIN.CUSTOM_FIELDS.US_DESCRIPTION'; customFieldButtonTitle='ADMIN.CUSTOM_FIELDS.US_ADD'")
|
||||||
- var customFieldSectionTitle = "User stories custom fields"
|
|
||||||
- var customFieldButtonTitle = "Add a custom field in user stories"
|
|
||||||
include ../includes/modules/admin/admin-custom-attributes
|
include ../includes/modules/admin/admin-custom-attributes
|
||||||
|
|
||||||
div.admin-attributes-section(tg-project-custom-attributes,
|
div.admin-attributes-section(tg-project-custom-attributes,
|
||||||
ng-controller="ProjectCustomAttributesController as ctrl",
|
ng-controller="ProjectCustomAttributesController as ctrl",
|
||||||
ng-init="type='task';")
|
ng-init="type='task'; customFieldSectionTitle='ADMIN.CUSTOM_FIELDS.TASK_DESCRIPTION'; customFieldButtonTitle='ADMIN.CUSTOM_FIELDS.TASK_ADD'")
|
||||||
- var customFieldSectionTitle = "Tasks custom fields"
|
|
||||||
- var customFieldButtonTitle = "Add a custom field in tasks"
|
|
||||||
include ../includes/modules/admin/admin-custom-attributes
|
include ../includes/modules/admin/admin-custom-attributes
|
||||||
|
|
||||||
div.admin-attributes-section(tg-project-custom-attributes,
|
div.admin-attributes-section(tg-project-custom-attributes,
|
||||||
ng-controller="ProjectCustomAttributesController as ctrl",
|
ng-controller="ProjectCustomAttributesController as ctrl",
|
||||||
ng-init="type='issue';")
|
ng-init="type='issue'; customFieldSectionTitle='ADMIN.CUSTOM_FIELDS.ISSUE_DESCRIPTION'; customFieldButtonTitle='ADMIN.CUSTOM_FIELDS.ISSUE_ADD'")
|
||||||
- var customFieldSectionTitle = "Issues custom fields"
|
|
||||||
- var customFieldButtonTitle = "Add a custom field in issues"
|
|
||||||
include ../includes/modules/admin/admin-custom-attributes
|
include ../includes/modules/admin/admin-custom-attributes
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper(ng-controller="ProjectValuesSectionController")
|
div.wrapper(ng-controller="ProjectValuesSectionController")
|
||||||
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
|
||||||
include ../includes/modules/admin-menu
|
include ../includes/modules/admin-menu
|
||||||
|
@ -7,9 +9,10 @@ div.wrapper(ng-controller="ProjectValuesSectionController")
|
||||||
|
|
||||||
section.main.admin-common.admin-attributes
|
section.main.admin-common.admin-attributes
|
||||||
include ../includes/components/mainTitle
|
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",
|
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'",
|
||||||
|
objName="points",
|
||||||
type="points")
|
type="points")
|
||||||
include ../includes/modules/admin/project-points
|
include ../includes/modules/admin/project-points
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper(ng-controller="ProjectValuesSectionController")
|
div.wrapper(ng-controller="ProjectValuesSectionController")
|
||||||
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
|
||||||
include ../includes/modules/admin-menu
|
include ../includes/modules/admin-menu
|
||||||
|
@ -7,9 +9,10 @@ div.wrapper(ng-controller="ProjectValuesSectionController")
|
||||||
|
|
||||||
section.main.admin-common.admin-attributes
|
section.main.admin-common.admin-attributes
|
||||||
include ../includes/components/mainTitle
|
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",
|
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="priorities",
|
||||||
type="priorities")
|
type="priorities")
|
||||||
include ../includes/modules/admin/project-types
|
include ../includes/modules/admin/project-types
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper(ng-controller="ProjectValuesSectionController")
|
div.wrapper(ng-controller="ProjectValuesSectionController")
|
||||||
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
|
||||||
include ../includes/modules/admin-menu
|
include ../includes/modules/admin-menu
|
||||||
|
@ -7,9 +9,10 @@ div.wrapper(ng-controller="ProjectValuesSectionController")
|
||||||
|
|
||||||
section.main.admin-common.admin-attributes
|
section.main.admin-common.admin-attributes
|
||||||
include ../includes/components/mainTitle
|
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",
|
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="severities",
|
||||||
type="severities")
|
type="severities")
|
||||||
include ../includes/modules/admin/project-types
|
include ../includes/modules/admin/project-types
|
||||||
|
|
|
@ -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")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
|
||||||
include ../includes/modules/admin-menu
|
include ../includes/modules/admin-menu
|
||||||
|
|
||||||
|
@ -7,19 +10,22 @@ div.wrapper(ng-controller="ProjectValuesSectionController")
|
||||||
|
|
||||||
section.main.admin-common.admin-attributes
|
section.main.admin-common.admin-attributes
|
||||||
include ../includes/components/mainTitle
|
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",
|
div.admin-attributes-section(tg-project-values, type="userstory-statuses",
|
||||||
ng-init="section='admin'; resource='userstories'; type='userstory-statuses'; sectionName='Us Statuses'",
|
ng-controller="ProjectValuesController as ctrl",
|
||||||
type="userstory-statuses")
|
ng-init="section='admin'; resource='userstories'; type='userstory-statuses'; sectionName='ADMIN.PROJECT_VALUES_STATUS.US_TITLE'",
|
||||||
|
objName="status")
|
||||||
include ../includes/modules/admin/project-us-status
|
include ../includes/modules/admin/project-us-status
|
||||||
|
|
||||||
div.admin-attributes-section(tg-project-values, ng-controller="ProjectValuesController as ctrl",
|
div.admin-attributes-section(tg-project-values, type="task-statuses",
|
||||||
ng-init="section='admin'; resource='tasks'; type='task-statuses'; sectionName='Task Statuses'",
|
ng-controller="ProjectValuesController as ctrl",
|
||||||
type="task-statuses")
|
ng-init="section='admin'; resource='tasks'; type='task-statuses'; sectionName='ADMIN.PROJECT_VALUES_STATUS.TASK_TITLE'"
|
||||||
|
objName="status")
|
||||||
include ../includes/modules/admin/project-status
|
include ../includes/modules/admin/project-status
|
||||||
|
|
||||||
div.admin-attributes-section(tg-project-values, ng-controller="ProjectValuesController as ctrl",
|
div.admin-attributes-section(tg-project-values, type="issue-statuses",
|
||||||
ng-init="section='admin'; resource='issues'; type='issue-statuses'; sectionName='Issue Statuses'",
|
ng-controller="ProjectValuesController as ctrl",
|
||||||
type="issue-statuses")
|
ng-init="section='admin'; resource='issues'; type='issue-statuses'; sectionName='ADMIN.PROJECT_VALUES_STATUS.ISSUE_TITLE'",
|
||||||
|
objName="status")
|
||||||
include ../includes/modules/admin/project-status
|
include ../includes/modules/admin/project-status
|
||||||
|
|
|
@ -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")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="project-values")
|
||||||
include ../includes/modules/admin-menu
|
include ../includes/modules/admin-menu
|
||||||
|
|
||||||
|
@ -7,9 +10,10 @@ div.wrapper(ng-controller="ProjectValuesSectionController")
|
||||||
|
|
||||||
section.main.admin-common.admin-attributes
|
section.main.admin-common.admin-attributes
|
||||||
include ../includes/components/mainTitle
|
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",
|
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="types",
|
||||||
type="issue-types")
|
type="issue-types")
|
||||||
include ../includes/modules/admin/project-types
|
include ../includes/modules/admin/project-types
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper.roles(ng-controller="RolesController as ctrl",
|
div.wrapper.roles(ng-controller="RolesController as ctrl",
|
||||||
ng-init="section='admin'", tg-roles)
|
ng-init="section='admin'", tg-roles)
|
||||||
sidebar.menu-secondary.sidebar(tg-admin-navigation="roles")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="roles")
|
||||||
|
@ -6,32 +8,31 @@ div.wrapper.roles(ng-controller="RolesController as ctrl",
|
||||||
include ../includes/modules/admin-submenu-roles
|
include ../includes/modules/admin-submenu-roles
|
||||||
|
|
||||||
section.main.admin-roles.admin-common
|
section.main.admin-roles.admin-common
|
||||||
.header-with-actions
|
header.header-with-actions
|
||||||
include ../includes/components/mainTitle
|
include ../includes/components/mainTitle
|
||||||
.action-buttons(ng-if="!role.external_user")
|
.action-buttons(ng-if="!role.external_user")
|
||||||
a.button-red.delete-role(href="", title="Delete", ng-click="ctrl.delete()")
|
a.button-red.delete-role(href="", title="{{'COMMON.DELETE' | translate}}", ng-click="ctrl.delete()")
|
||||||
span Delete
|
span(translate="COMMON.DELETE")
|
||||||
|
|
||||||
|
|
||||||
div(ng-if="!role.external_user")
|
div(ng-if="!role.external_user")
|
||||||
div(tg-edit-role)
|
div(tg-edit-role)
|
||||||
.edit-role
|
.edit-role
|
||||||
input(type="text", value="{{ role.name }}")
|
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
|
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
|
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
|
div.general-category(translate="ADMIN.ROLES.HELP_ROLE_ENABLED")
|
||||||
| When enabled, members assigned to this role will be able to estimate the point value for user stories
|
|
||||||
div.check
|
div.check
|
||||||
input(type="checkbox", ng-model="role.computable", ng-change="ctrl.setComputable()")
|
input(type="checkbox", ng-model="role.computable", ng-change="ctrl.setComputable()")
|
||||||
div
|
div
|
||||||
span.check-text.check-yes Yes
|
span.check-text.check-yes(translate="COMMON.YES")
|
||||||
span.check-text.check-no No
|
span.check-text.check-no(translate="COMMON.NO")
|
||||||
|
|
||||||
div(ng-if="role.external_user")
|
div(ng-if="role.external_user")
|
||||||
p.total
|
p.total
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper.roles(tg-bitbucket-webhooks, ng-controller="BitbucketController as ctrl",
|
div.wrapper.roles(tg-bitbucket-webhooks, ng-controller="BitbucketController as ctrl",
|
||||||
ng-init="section='admin'")
|
ng-init="section='admin'")
|
||||||
sidebar.menu-secondary.sidebar(tg-admin-navigation="third-parties")
|
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
|
form
|
||||||
fieldset
|
fieldset
|
||||||
label(for="secret-key") Secret key
|
label(for="secret-key", translate="ADMIN.THIRD_PARTIES.SECRET_KEY")
|
||||||
input(type="text", name="secret-key", ng-model="bitbucket.secret", placeholder="Secret key", id="secret-key")
|
input(type="text", name="secret-key", ng-model="bitbucket.secret", placeholder="{{'ADMIN.THIRD_PARTIES.SECRET_KEY' | translate}}", id="secret-key")
|
||||||
|
|
||||||
fieldset
|
fieldset
|
||||||
.select-input-text(tg-select-input-text)
|
.select-input-text(tg-select-input-text)
|
||||||
div
|
div
|
||||||
label(for="payload-url") Payload URL
|
label(for="payload-url", translate="ADMIN.THIRD_PARTIES.PAYLOAD_URL")
|
||||||
.field-with-option
|
.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
|
.option-wrapper.select-input-content
|
||||||
.icon.icon-copy
|
.icon.icon-copy
|
||||||
.help-copy Copy to clipboard: Ctrl+C
|
.help-copy(translate="COMMON.COPY_TO_CLIPBOARD")
|
||||||
|
|
||||||
fieldset
|
fieldset
|
||||||
label(for="valid-origin-ips") Valid origin ips (separated by ,)
|
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="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")
|
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")
|
a.help-button(href="https://taiga.io/support/bitbucket-integration/", target="_blank")
|
||||||
span.icon.icon-help
|
span.icon.icon-help
|
||||||
span Do you need help? Check out our support page!
|
span(translate="ADMIN.HELP")
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper.roles(tg-github-webhooks, ng-controller="GithubController as ctrl",
|
div.wrapper.roles(tg-github-webhooks, ng-controller="GithubController as ctrl",
|
||||||
ng-init="section='admin'")
|
ng-init="section='admin'")
|
||||||
sidebar.menu-secondary.sidebar(tg-admin-navigation="third-parties")
|
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
|
form
|
||||||
fieldset
|
fieldset
|
||||||
label(for="secret-key") Secret key
|
label(for="secret-key", translate="ADMIN.THIRD_PARTIES.SECRET_KEY")
|
||||||
input(type="text", name="secret-key", ng-model="github.secret", placeholder="Secret key", id="secret-key")
|
input(type="text", name="secret-key", ng-model="github.secret", placeholder="{{'ADMIN.THIRD_PARTIES.SECRET_KEY' | translate}}", id="secret-key")
|
||||||
|
|
||||||
fieldset
|
fieldset
|
||||||
.select-input-text(tg-select-input-text)
|
.select-input-text(tg-select-input-text)
|
||||||
div
|
div
|
||||||
label(for="payload-url") Payload URL
|
label(for="payload-url", translate="ADMIN.THIRD_PARTIES.PAYLOAD_URL")
|
||||||
.field-with-option
|
.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
|
.option-wrapper.select-input-content
|
||||||
.icon.icon-copy
|
.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}}", translate="COMMON.SAVE")
|
||||||
|
|
||||||
a.help-button(href="https://taiga.io/support/github-integration/", target="_blank")
|
a.help-button(href="https://taiga.io/support/github-integration/", target="_blank")
|
||||||
span.icon.icon-help
|
span.icon.icon-help
|
||||||
span Do you need help? Check out our support page!
|
span(translate="ADMIN.HELP")
|
||||||
|
|
|
@ -1,38 +1,36 @@
|
||||||
block head
|
doctype html
|
||||||
title Taiga Your agile, free, and open source project management tool
|
|
||||||
|
|
||||||
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'")
|
||||||
ng-init="section='admin'")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="third-parties")
|
||||||
sidebar.menu-secondary.sidebar(tg-admin-navigation="third-parties")
|
include ../includes/modules/admin-menu
|
||||||
include ../includes/modules/admin-menu
|
sidebar.menu-tertiary.sidebar(tg-admin-navigation="third-parties-gitlab")
|
||||||
sidebar.menu-tertiary.sidebar(tg-admin-navigation="third-parties-gitlab")
|
include ../includes/modules/admin-submenu-third-parties
|
||||||
include ../includes/modules/admin-submenu-third-parties
|
|
||||||
|
|
||||||
section.main.admin-common.admin-third-parties
|
section.main.admin-common.admin-third-parties
|
||||||
include ../includes/components/mainTitle
|
include ../includes/components/mainTitle
|
||||||
|
|
||||||
form
|
form
|
||||||
fieldset
|
fieldset
|
||||||
label(for="secret-key") Secret key
|
label(for="secret-key", translate="ADMIN.THIRD_PARTIES.SECRET_KEY")
|
||||||
input(type="text", name="secret-key", ng-model="gitlab.secret", placeholder="Secret key", id="secret-key")
|
input(type="text", name="secret-key", ng-model="gitlab.secret", placeholder="{{'ADMIN.THIRD_PARTIES.SECRET_KEY' | translate}}", id="secret-key")
|
||||||
|
|
||||||
fieldset
|
fieldset
|
||||||
.select-input-text(tg-select-input-text)
|
.select-input-text(tg-select-input-text)
|
||||||
div
|
div
|
||||||
label(for="payload-url") Payload URL
|
label(for="payload-url", translate="ADMIN.THIRD_PARTIES.PAYLOAD_URL")
|
||||||
.field-with-option
|
.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
|
.option-wrapper.select-input-content
|
||||||
.icon.icon-copy
|
.icon.icon-copy
|
||||||
.help-copy Copy to clipboard: Ctrl+C
|
.help-copy(translate="COMMON.COPY_TO_CLIPBOARD")
|
||||||
|
|
||||||
fieldset
|
fieldset
|
||||||
label(for="valid-origin-ips") Valid origin ips (separated by ,)
|
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="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")
|
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")
|
a.help-button(href="https://taiga.io/support/gitlab-integration/", target="_blank")
|
||||||
span.icon.icon-help
|
span.icon.icon-help
|
||||||
span Do you need help? Check out our support page!
|
span(translate="ADMIN.HELP")
|
||||||
|
|
|
@ -1,99 +1,97 @@
|
||||||
block head
|
doctype html
|
||||||
title Taiga Your agile, free, and open source project management tool
|
|
||||||
|
|
||||||
block content
|
div.wrapper.roles(ng-controller="WebhooksController as ctrl",
|
||||||
div.wrapper.roles(ng-controller="WebhooksController as ctrl",
|
ng-init="section='admin'")
|
||||||
ng-init="section='admin'")
|
sidebar.menu-secondary.sidebar(tg-admin-navigation="third-parties")
|
||||||
sidebar.menu-secondary.sidebar(tg-admin-navigation="Webhooks")
|
include ../includes/modules/admin-menu
|
||||||
include ../includes/modules/admin-menu
|
sidebar.menu-tertiary.sidebar(tg-admin-navigation="third-parties-webhooks")
|
||||||
sidebar.menu-tertiary.sidebar(tg-admin-navigation="third-parties-webhooks")
|
include ../includes/modules/admin-submenu-third-parties
|
||||||
include ../includes/modules/admin-submenu-third-parties
|
|
||||||
|
|
||||||
section.main.admin-common.admin-webhooks(tg-new-webhook)
|
section.main.admin-common.admin-webhooks(tg-new-webhook)
|
||||||
include ../includes/components/mainTitle
|
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
|
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
|
section.webhooks-table.basic-table
|
||||||
div.table-header
|
div.table-header
|
||||||
div.row
|
div.row
|
||||||
div.webhook-service Name
|
div.webhook-service(translate="COMMON.FIELDS.NAME")
|
||||||
div.webhook-url URL
|
div.webhook-url(translate="COMMON.FIELDS.URL")
|
||||||
div.webhook-options
|
div.webhook-options
|
||||||
div.table-body
|
div.table-body
|
||||||
div.single-webhook-wrapper(tg-webhook="webhook", ng-repeat="webhook in webhooks")
|
div.single-webhook-wrapper(tg-webhook="webhook", ng-repeat="webhook in webhooks")
|
||||||
div.edition-mode.hidden
|
div.edition-mode.hidden
|
||||||
form.row
|
form.row
|
||||||
fieldset.webhook-service
|
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
|
||||||
div.webhook-url-inputs
|
div.webhook-url-inputs
|
||||||
fieldset
|
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
|
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
|
div.webhook-options
|
||||||
a.edit-existing.icon.icon-floppy(href="", title="Save Webhook")
|
a.edit-existing.icon.icon-floppy(href="", title="{{'ADMIN.WEBHOOKS.SAVE' | translate}}")
|
||||||
a.cancel-existing.icon.icon-delete(href="", title="Cancel Webhook")
|
a.cancel-existing.icon.icon-delete(href="", title="{{'ADMIN.WEBHOOKS.CANCEL' | translate}}")
|
||||||
|
|
||||||
div.visualization-mode
|
div.visualization-mode
|
||||||
div.row
|
div.row
|
||||||
div.webhook-service
|
div.webhook-service
|
||||||
span(ng-bind="webhook.name")
|
span(ng-bind="webhook.name")
|
||||||
div.webhook-url
|
div.webhook-url
|
||||||
span(ng-bind="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.SHOW_HISTORY_TITLE' | translate}}", ng-show="webhook.logs_counter", translate="ADMIN.WEBHOOKS.SHOW_HISTORY")
|
||||||
|
|
||||||
div.webhook-options
|
div.webhook-options
|
||||||
div.webhook-options-wrapper
|
div.webhook-options-wrapper
|
||||||
a.test-webhook.icon.icon-check-square(href="", title="Test Webhook")
|
a.test-webhook.icon.icon-check-square(href="", title="{{'ADMIN.WEBHOOKS.TEST' | translate}}")
|
||||||
a.edit-webhook.icon.icon-edit(href="", title="Edit Webhook")
|
a.edit-webhook.icon.icon-edit(href="", title="{{'ADMIN.WEBHOOKS.EDIT' | translate}}")
|
||||||
a.delete-webhook.icon.icon-delete(href="", title="Delete Webhook")
|
a.delete-webhook.icon.icon-delete(href="", title="{{'ADMIN.WEBHOOKS.DELETE' | translate}}")
|
||||||
|
|
||||||
div.webhooks-history(ng-show="webhook.logs")
|
div.webhooks-history(ng-show="webhook.logs")
|
||||||
div.history-single-wrapper(ng-repeat="log in webhook.logs")
|
div.history-single-wrapper(ng-repeat="log in webhook.logs")
|
||||||
div.history-single
|
div.history-single
|
||||||
div
|
div
|
||||||
span.history-response-icon(ng-class="log.validStatus ? 'history-success' : 'history-error'", title="{{log.status}}")
|
span.history-response-icon(ng-class="log.validStatus ? 'history-success' : 'history-error'", title="{{log.status}}")
|
||||||
span.history-date(ng-bind="log.prettyDate")
|
span.history-date(ng-bind="log.prettyDate")
|
||||||
span.toggle-log.icon.icon-arrow-bottom
|
span.toggle-log.icon.icon-arrow-bottom
|
||||||
|
|
||||||
div.history-single-response
|
div.history-single-response
|
||||||
div.history-single-request-header
|
div.history-single-request-header
|
||||||
span Request
|
span(translate="ADMIN.WEBHOOKS.REQUEST")
|
||||||
a.resend-request(href="", title="Resend request", data-log="{{log.id}}")
|
a.resend-request(href="", title="{{'ADMIN.WEBHOOKS.RESEND_REQUEST' | translate}}", data-log="{{log.id}}")
|
||||||
span.icon.icon-reload
|
span.icon.icon-reload
|
||||||
span Resend request
|
span(translate="ADMIN.WEBHOOKS.RESEND_REQUEST")
|
||||||
div.history-single-request-body
|
div.history-single-request-body
|
||||||
div.response-container
|
div.response-container
|
||||||
span.response-title Headers
|
span.response-title(translate="ADMIN.WEBHOOKS.HEADERS")
|
||||||
textarea(name="headers", ng-bind="log.prettySentHeaders")
|
textarea(name="headers", ng-bind="log.prettySentHeaders")
|
||||||
|
|
||||||
div.response-container
|
div.response-container
|
||||||
span.response-title Payload
|
span.response-title(translate="ADMIN.WEBHOOKS.PAYLOAD")
|
||||||
textarea(name="payload", ng-bind="log.prettySentData")
|
textarea(name="payload", ng-bind="log.prettySentData")
|
||||||
|
|
||||||
div.history-single-response-header
|
div.history-single-response-header
|
||||||
span Response
|
span(translate="ADMIN.WEBHOOKS.RESPONSE")
|
||||||
div.history-single-response-body
|
div.history-single-response-body
|
||||||
div.response-container
|
div.response-container
|
||||||
textarea(name="response-data", ng-bind="log.response_data")
|
textarea(name="response-data", ng-bind="log.response_data")
|
||||||
|
|
||||||
form.new-webhook-form.row.hidden
|
form.new-webhook-form.row.hidden
|
||||||
fieldset.webhook-service
|
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
|
||||||
div.webhook-url-inputs
|
div.webhook-url-inputs
|
||||||
fieldset
|
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
|
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
|
div.webhook-options
|
||||||
a.add-new.icon.icon-floppy(href="", title="Save Webhook")
|
a.add-new.icon.icon-floppy(href="", title="{{'ADMIN.WEBHOOKS.SAVE' | translate}}")
|
||||||
a.cancel-new.icon.icon-delete(href="", title="Cancel Webhook")
|
a.cancel-new.icon.icon-delete(href="", title="{{'ADMIN.WEBHOOKS.CANCEL' | translate}}")
|
||||||
|
|
||||||
a.help-button(href="https://taiga.io/support/webhooks/", target="_blank")
|
a.help-button(href="https://taiga.io/support/webhooks/", target="_blank")
|
||||||
span.icon.icon-help
|
span.icon.icon-help
|
||||||
span Do you need help? Check out our support page!
|
span(translate="ADMIN.HELP")
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
section.project-csv(tg-select-input-text)
|
||||||
|
div.project-values-title
|
||||||
|
h2(translate="{{::sectionTitle}}")
|
||||||
|
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
|
||||||
|
div.field-with-options
|
||||||
|
input(type="text", placeholder="{{'ADMIN.CSV.URL_FIELD_PLACEHOLDER' | translate}}",
|
||||||
|
readonly, ng-model="csvUrl")
|
||||||
|
div.option-wrapper.select-input-content
|
||||||
|
div.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")
|
|
@ -1,19 +1,19 @@
|
||||||
.attachment-name
|
.attachment-name
|
||||||
span.icon.icon-document
|
span.icon.icon-document
|
||||||
a(href!="<%- url %>", title!="<%- name %> uploaded on <%- created_date %>", target="_blank")
|
a(href!="<%- url %>", title!="<%- title %>", target="_blank")
|
||||||
| <%- name %>
|
| <%- name %>
|
||||||
.attachment-size
|
.attachment-size
|
||||||
span <%- size %>
|
span <%- size %>
|
||||||
|
|
||||||
.editable.editable-attachment-comment
|
.editable.editable-attachment-comment
|
||||||
input(type="text", name="description", maxlength="140",
|
input(type="text", name="description", maxlength="140",
|
||||||
value!="<%- description %>", placeholder="Type a short description")
|
value!="<%- description %>", placeholder="{{'ATTACHMENT.DESCRIPTION' | translate}}")
|
||||||
|
|
||||||
.editable.editable-attachment-deprecated
|
.editable.editable-attachment-deprecated
|
||||||
input(type="checkbox", name="is-deprecated",
|
input(type="checkbox", name="is-deprecated",
|
||||||
id!="attach-<%- id %>-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
|
.attachment-settings
|
||||||
a.editable-settings.icon.icon-floppy(href="", title="Save")
|
a.editable-settings.icon.icon-floppy(href="", title="{{'COMMON.SAVE' | translate}}")
|
||||||
a.editable-settings.icon.icon-delete(href="", title="Cancel")
|
a.editable-settings.icon.icon-delete(href="", title="{{'COMMON.CANCEL' | translate}}")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.attachment-name
|
.attachment-name
|
||||||
a(href!="<%- url %>", title!="<%- name %> uploaded on <%- created_date %>", target="_blank")
|
a(href!="<%- url %>", title!="<%- title %>", target="_blank")
|
||||||
span.icon.icon-documents
|
span.icon.icon-documents
|
||||||
span <%- name %>
|
span <%- name %>
|
||||||
.attachment-size
|
.attachment-size
|
||||||
|
@ -7,13 +7,13 @@
|
||||||
|
|
||||||
.attachment-comments
|
.attachment-comments
|
||||||
<% if (isDeprecated){ %>
|
<% if (isDeprecated){ %>
|
||||||
span.deprecated-file (deprecated)
|
span.deprecated-file {{'ATTACHMENT.DEPRECATED' | translate}}
|
||||||
<% } %>
|
<% } %>
|
||||||
span <%- description %>
|
span <%- description %>
|
||||||
|
|
||||||
<% if (modifyPermission) {%>
|
<% if (modifyPermission) {%>
|
||||||
.attachment-settings
|
.attachment-settings
|
||||||
a.settings.icon.icon-edit(href="", title="Edit")
|
a.settings.icon.icon-edit(href="", title="{{'COMMON.EDIT' | translate}}")
|
||||||
a.settings.icon.icon-delete(href="", title="Delete")
|
a.settings.icon.icon-delete(href="", title="{{'COMMON.DELETE' | translate}}")
|
||||||
a.settings.icon.icon-drag-v(href="", title="Drag")
|
a.settings.icon.icon-drag-v(href="", title="{{'COMMON.DRAG' | translate}}")
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
|
@ -2,10 +2,10 @@ section.attachments
|
||||||
.attachments-header
|
.attachments-header
|
||||||
h3.attachments-title
|
h3.attachments-title
|
||||||
span.attachments-num(tg-bind-html="ctrl.attachmentsCount")
|
span.attachments-num(tg-bind-html="ctrl.attachmentsCount")
|
||||||
span.attachments-text attachments
|
span.attachments-text(translate="ATTACHMENT.SECTION_NAME")
|
||||||
.add-attach(tg-check-permission!="modify_<%- type %>", title!="Add new attachment. <%- maxFileSizeMsg %>")
|
.add-attach(tg-check-permission!="modify_<%- type %>", title!="{{'ATTACHMENT.ADD' | translate}}")
|
||||||
<% if (maxFileSize){ %>
|
<% 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")
|
label(for="add-attach", class="icon icon-plus related-tasks-buttons")
|
||||||
input(id="add-attach", type="file", multiple="multiple")
|
input(id="add-attach", type="file", multiple="multiple")
|
||||||
|
@ -22,9 +22,7 @@ section.attachments
|
||||||
span(ng-bind="file.progressMessage")
|
span(ng-bind="file.progressMessage")
|
||||||
.percentage(ng-style="{'width': file.progressPercent}")
|
.percentage(ng-style="{'width': file.progressPercent}")
|
||||||
|
|
||||||
a.more-attachments(href="", title="show deprecated atachments", ng-if="ctrl.deprecatedAttachmentsCount > 0")
|
a.more-attachments(href="", title="{{'ATTACHMENT.SHOW_DEPRECATED' | translate}}", ng-if="ctrl.deprecatedAttachmentsCount > 0")
|
||||||
span.text(data-type="show") + show deprecated atachments
|
span.text(data-type="show", translate="ATTACHMENT.SHOW_DEPRECATED")
|
||||||
span.text.hidden(data-type="hide")
|
span.text.hidden(data-type="hide", translate="ATTACHMENT.HIDE_DEPRECATED")
|
||||||
| - hide deprecated atachments
|
span.more-attachments-num(translate="ATTACHMENT.COUNT_DEPRECATED", translate-values="{counter: '{{ctrl.deprecatedAttachmentsCount}}'}")
|
||||||
span.more-attachments-num
|
|
||||||
| ({{ctrl.deprecatedAttachmentsCount }} deprecated)
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper
|
div.wrapper
|
||||||
div.login-main
|
div.login-main
|
||||||
div.login-container
|
div.login-container
|
||||||
h1.logo
|
h1.logo
|
||||||
img.logo-svg(src="/svg/logo.svg", alt="TAIGA")
|
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
|
include ../includes/modules/change-password-from-recovery-form
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
include ../includes/components/beta
|
include ../includes/components/beta
|
||||||
div.wrapper
|
div.wrapper
|
||||||
div.login-main
|
div.login-main
|
||||||
div.login-container
|
div.login-container
|
||||||
img.logo-svg(src="/svg/logo.svg", alt="TAIGA")
|
img.logo-svg(src="/svg/logo.svg", alt="TAIGA")
|
||||||
h1.logo Taiga
|
h1.logo Taiga
|
||||||
h2.tagline LOVE YOUR PROJECT
|
h2.tagline(translate="COMMON.TAG_LINE_2")
|
||||||
|
|
||||||
include ../includes/modules/forgot-form
|
include ../includes/modules/forgot-form
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper
|
div.wrapper
|
||||||
div.invitation-main
|
div.invitation-main
|
||||||
div.invitation-container(tg-invitation)
|
div.invitation-container(tg-invitation)
|
||||||
|
@ -8,7 +10,7 @@ div.wrapper
|
||||||
span.person-name(tg-bo-bind="invitation.invited_by.full_name_display")
|
span.person-name(tg-bo-bind="invitation.invited_by.full_name_display")
|
||||||
|
|
||||||
span.invitation-text
|
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")
|
p.project-name(tg-bo-bind="invitation.project_name")
|
||||||
|
|
||||||
div.invitation-form
|
div.invitation-form
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
p.login-text
|
p.login-text
|
||||||
span Not registered yet?
|
span(translate="AUTH.NOT_REGISTERED_YET")
|
||||||
a(href!='<%- url %>', tg-nav='register', title='Register') create your free account here
|
|
|
||||||
|
a(href!='<%- url %>', tg-nav='register', title='{{"AUTH.REGISTER" | translate}}', translate="AUTH.CREATE_ACCOUNT")
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
include ../includes/components/beta
|
include ../includes/components/beta
|
||||||
div.wrapper
|
div.wrapper
|
||||||
div.login-main
|
div.login-main
|
||||||
div.login-container
|
div.login-container
|
||||||
img.logo-svg(src="/svg/logo.svg", alt="TAIGA")
|
img.logo-svg(src="/svg/logo.svg", alt="TAIGA")
|
||||||
h1.logo Taiga
|
h1.logo Taiga
|
||||||
h2.tagline LOVE YOUR PROJECT
|
h2.tagline(translate="COMMON.TAG_LINE_2")
|
||||||
|
|
||||||
include ../includes/modules/login-form
|
include ../includes/modules/login-form
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper
|
div.wrapper
|
||||||
div.login-main
|
div.login-main
|
||||||
div.login-container
|
div.login-container
|
||||||
img.logo-svg(src="/svg/logo.svg", alt="TAIGA")
|
img.logo-svg(src="/svg/logo.svg", alt="TAIGA")
|
||||||
h1.logo Taiga
|
h1.logo Taiga
|
||||||
h2.tagline LOVE YOUR PROJECT
|
h2.tagline(translate="COMMON.TAG_LINE_2")
|
||||||
|
|
||||||
include ../includes/modules/register-form
|
include ../includes/modules/register-form
|
||||||
|
|
|
@ -1,32 +1,48 @@
|
||||||
|
doctype html
|
||||||
|
|
||||||
div.wrapper(tg-backlog, ng-controller="BacklogController as ctrl",
|
div.wrapper(tg-backlog, ng-controller="BacklogController as ctrl",
|
||||||
ng-init="section='backlog'")
|
ng-init="section='backlog'")
|
||||||
|
|
||||||
sidebar.menu-secondary.extrabar.filters-bar(tg-backlog-filters)
|
sidebar.menu-secondary.extrabar.filters-bar(tg-backlog-filters)
|
||||||
include ../includes/modules/backlog-filters
|
include ../includes/modules/backlog-filters
|
||||||
section.main.backlog
|
section.main.backlog
|
||||||
include ../includes/components/mainTitle
|
include ../includes/components/mainTitle
|
||||||
include ../includes/components/summary
|
include ../includes/components/summary
|
||||||
|
|
||||||
div.graphics-container.burndown-container
|
div.graphics-container.burndown-container
|
||||||
div.burndown(tg-gm-backlog-graph)
|
div.burndown(tg-burndown-backlog-graph)
|
||||||
include ../includes/modules/burndown
|
include ../includes/modules/burndown
|
||||||
|
|
||||||
div.backlog-menu
|
div.backlog-menu
|
||||||
div.backlog-table-options
|
div.backlog-table-options
|
||||||
a.trans-button.move-to-current-sprint(href="", title="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")
|
id="move-to-current-sprint")
|
||||||
span.icon.icon-move
|
span.icon.icon-move
|
||||||
span.text Move to current Sprint
|
span.text(translate="BACKLOG.MOVE_US_TO_CURRENT_SPRINT")
|
||||||
a.trans-button(href="", title="Show Filters", id="show-filters-button")
|
a.trans-button(href="",
|
||||||
|
title="{{'BACKLOG.FILTERS.TOGGLE' | translate}}",
|
||||||
|
id="show-filters-button")
|
||||||
span.icon.icon-filter
|
span.icon.icon-filter
|
||||||
span.text Show Filters
|
span.text(translate="BACKLOG.FILTERS.SHOW")
|
||||||
a.trans-button(href="", title="Show Tags", id="show-tags")
|
a.trans-button(href="",
|
||||||
|
title="{{'BACKLOG.TAGS.TOGGLE' | translate}}",
|
||||||
|
id="show-tags")
|
||||||
span.icon.icon-tag
|
span.icon.icon-tag
|
||||||
span.text Show Tags
|
span.text(translate="BACKLOG.TAGS.SHOW")
|
||||||
include ../includes/components/addnewus
|
include ../includes/components/addnewus
|
||||||
|
|
||||||
section.backlog-table(ng-class="{'hidden': !visibleUserstories.length}")
|
section.backlog-table(ng-class="{'hidden': !visibleUserstories.length}")
|
||||||
include ../includes/modules/backlog-table
|
include ../includes/modules/backlog-table
|
||||||
|
|
||||||
div.empty.empty-backlog(ng-class="{'hidden': visibleUserstories.length}", tg-backlog-empty-sortable)
|
div.empty.empty-backlog(ng-class="{'hidden': visibleUserstories.length}", tg-backlog-empty-sortable)
|
||||||
span.icon.icon-backlog
|
span.icon.icon-backlog
|
||||||
span.title Your backlog is empty!
|
span.title(translate="BACKLOG.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
|
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
|
sidebar.menu-secondary.sidebar
|
||||||
include ../includes/modules/sprints
|
include ../includes/modules/sprints
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
.defined-points(title="Excess of points")
|
.defined-points(title="{{'BACKLOG.EXCESS_OF_POINTS' | translate}}")
|
||||||
.project-points-progress(title="Pending Points", style!="width: <%- projectPointsPercentaje %>%")
|
|
||||||
.closed-points-progress(title="Closed points", style!="width: <%- closedPointsPercentaje %>%")
|
.project-points-progress(title="{{'BACKLOG.PENDING_POINTS' | translate}}",
|
||||||
|
style!="width: <%- projectPointsPercentaje %>%")
|
||||||
|
.closed-points-progress(title="{{'BACKLOG.CLOSED_POINTS' | translate}}",
|
||||||
|
style!="width: <%- closedPointsPercentaje %>%")
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
.sprint-name
|
.sprint-name
|
||||||
a.icon.icon-arrow-up(href="", title="Compact Sprint")
|
a.icon.icon-arrow-up(href="", title="{{'BACKLOG.COMPACT_SPRINT' | translate}}")
|
||||||
<% if(isVisible){ %>
|
a(ng-if="::isVisible", href="{{::taskboardUrl}}", title="{{'BACKLOG.GO_TO_TASKBOARD' | translate}}")
|
||||||
a(href!="<%- taskboardUrl %>", title!="'Go to the taskboard of '<%- name %>'")
|
span {{::name}}
|
||||||
span <%- name %>
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
<% if(isEditable){ %>
|
a.icon.icon-edit(ng-if="::isEditable", href="", title="{{'BACKLOG.EDIT_SPRINT' | translate}}")
|
||||||
a.icon.icon-edit(href="", title="Edit Sprint")
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
.sprint-summary
|
.sprint-summary
|
||||||
.sprint-date <%- estimatedDateRange %>
|
.sprint-date {{::estimatedDateRange}}
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
span.number <%- closedPoints %>
|
span.number {{::closedPoints}}
|
||||||
span.description closed
|
span.description(translate="BACKLOG.CLOSED_POINTS")
|
||||||
li
|
li
|
||||||
span.number <%- totalPoints %>
|
span.number {{::totalPoints}}
|
||||||
span.description total
|
span.description(translate="BACKLOG.TOTAL_POINTS")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
ul.popover.pop-role
|
ul.popover.pop-role
|
||||||
li
|
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) { %>
|
<% _.each(roles, function(role) { %>
|
||||||
li
|
li
|
||||||
a(href="", class="role", title!="<%- role.name %>", data-role-id!="<%- role.id %>")
|
a(href="", class="role", title!="<%- role.name %>", data-role-id!="<%- role.id %>")
|
||||||
|
|
|
@ -4,18 +4,19 @@
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
.assigned-to
|
.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<% }; %>")
|
a(href="" title="{{ 'COMMON.ASSIGNED_TO.TITLE_ACTION_EDIT_ASSIGNMENT'|translate }}",
|
||||||
|
class!="user-assigned <% if(isEditable){ %>editable<% }; %>")
|
||||||
span.assigned-name
|
span.assigned-name
|
||||||
<% if (assignedTo) { %>
|
<% if (assignedTo) { %>
|
||||||
<%- assignedTo.full_name_display %>
|
<%- assignedTo.full_name_display %>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
| Not assigned
|
| {{ 'COMMON.ASSIGNED_TO.NOT_ASSIGNED'|translate }}
|
||||||
<% } %>
|
<% } %>
|
||||||
<% if(isEditable){ %>
|
<% if(isEditable){ %>
|
||||||
span.icon.icon-arrow-bottom
|
span.icon.icon-arrow-bottom
|
||||||
<% }; %>
|
<% }; %>
|
||||||
<% if (assignedTo!==null && isEditable) { %>
|
<% if (assignedTo!==null && isEditable) { %>
|
||||||
a.icon.icon-delete(href="" title="delete assignment")
|
a.icon.icon-delete(href="" title="{{'COMMON.ASSIGNED_TO.DELETE_ASSIGNMENT' | translate}}")
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
a(href="#", class="button button-gray item-block")
|
a(href="#", class="button button-gray item-block")
|
||||||
span Block
|
span(translate="COMMON.BLOCK")
|
||||||
a(href="#", class="button button-red item-unblock")
|
a(href="#", class="button button-red item-unblock")
|
||||||
span Unblock
|
span(translate="COMMON.UNBLOCK")
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
img(src!="<%- owner.photo %>", alt!="<%- owner.full_name_display %>")
|
img(src!="<%- owner.photo %>", alt!="<%- owner.full_name_display %>")
|
||||||
|
|
||||||
.created-by
|
.created-by
|
||||||
span.created-title
|
span.created-title(translate="COMMON.CREATED_BY", translate-values!="{ 'fullDisplayName': '<%- owner.full_name_display %>'}")
|
||||||
| Created by <%- owner.full_name_display %>
|
|
||||||
span.created-date
|
span.created-date
|
||||||
| <%- date %>
|
| <%- date %>
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
a(href="", class="button button-red")
|
a(href="", class="button button-red")
|
||||||
span Delete
|
span(translate="COMMON.DELETE")
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue