diff --git a/app/coffee/app.coffee b/app/coffee/app.coffee
index 51d14005..c94ff19a 100644
--- a/app/coffee/app.coffee
+++ b/app/coffee/app.coffee
@@ -510,6 +510,7 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
prefix: "/locales/locale-",
suffix: ".json"
})
+ .useSanitizeValueStrategy('escapeParameters')
.addInterpolation('$translateMessageFormatInterpolation')
.preferredLanguage(preferedLangCode)
@@ -669,6 +670,7 @@ modules = [
"templates",
# Vendor modules
+ "ngSanitize",
"ngRoute",
"ngAnimate",
"ngAria",
diff --git a/app/coffee/modules/common/components.coffee b/app/coffee/modules/common/components.coffee
index b71abdb4..6f41595a 100644
--- a/app/coffee/modules/common/components.coffee
+++ b/app/coffee/modules/common/components.coffee
@@ -135,27 +135,18 @@ CreatedByDisplayDirective = ($template, $compile, $translate, $navUrls)->
# 'owner'(ng-model)
# - scope.usersById object is required.
- template = $template.get("common/components/created-by.html", true)
-
link = ($scope, $el, $attrs) ->
- render = (model) ->
- owner = model.owner_extra_info or {
- full_name_display: $translate.instant("COMMON.EXTERNAL_USER")
- photo: "/images/user-noimage.png"
- }
-
- html = template({
- owner: owner
- url: if owner?.is_active then $navUrls.resolve("user-profile", {username: owner.username}) else ""
- date: moment(model.created_date).format($translate.instant("COMMON.DATETIME"))
- })
-
- html = $compile(html)($scope)
-
- $el.html(html)
-
bindOnce $scope, $attrs.ngModel, (model) ->
- render(model) if model?
+ if model?
+ $scope.owner = model.owner_extra_info or {
+ full_name_display: $translate.instant("COMMON.EXTERNAL_USER")
+ photo: "/images/user-noimage.png"
+ }
+
+ $scope.url = if $scope.owner?.is_active then $navUrls.resolve("user-profile", {username: $scope.owner.username}) else ""
+
+
+ $scope.date = moment(model.created_date).format($translate.instant("COMMON.DATETIME"))
$scope.$on "$destroy", ->
$el.off()
@@ -163,13 +154,14 @@ CreatedByDisplayDirective = ($template, $compile, $translate, $navUrls)->
return {
link: link
restrict: "EA"
- require: "ngModel"
+ require: "ngModel",
+ scope: true,
+ templateUrl: "common/components/created-by.html"
}
module.directive("tgCreatedByDisplay", ["$tgTemplate", "$compile", "$translate", "$tgNavUrls",
CreatedByDisplayDirective])
-
#############################################################################
## Watchers directive
#############################################################################
diff --git a/app/modules/user-timeline/user-timeline-item/user-timeline-item-title.service.coffee b/app/modules/user-timeline/user-timeline-item/user-timeline-item-title.service.coffee
index f362ddf7..772d05e3 100644
--- a/app/modules/user-timeline/user-timeline-item/user-timeline-item-title.service.coffee
+++ b/app/modules/user-timeline/user-timeline-item/user-timeline-item-title.service.coffee
@@ -21,7 +21,8 @@ unslugify = @.taiga.unslugify
class UserTimelineItemTitle
@.$inject = [
- "$translate"
+ "$translate",
+ "$sce"
]
_fieldTranslationKey: {
@@ -105,7 +106,7 @@ class UserTimelineItemTitle
return _.escape(timeline.getIn(['data', 'value_diff', 'value']).keySeq().first())
}
- constructor: (@translate) ->
+ constructor: (@translate, @sce) ->
_translateTitleParams: (param, timeline, event) ->
@@ -152,7 +153,18 @@ class UserTimelineItemTitle
return params
getTitle: (timeline, event, type) ->
- return @translate.instant(type.key, @._getParams(timeline, event, type))
+ params = @._getParams(timeline, event, type)
+
+ paramsKeys = {}
+ Object.keys(params).forEach (key) -> paramsKeys[key] = '{{' +key + '}}'
+
+ translation = @translate.instant(type.key, paramsKeys)
+
+ Object.keys(params).forEach (key) ->
+ find = '{{' +key + '}}'
+ translation = translation.replace(new RegExp(find, 'g'), params[key])
+
+ return translation
angular.module("taigaUserTimeline")
.service("tgUserTimelineItemTitle", UserTimelineItemTitle)
diff --git a/app/modules/user-timeline/user-timeline-item/user-timeline-item-title.service.spec.coffee b/app/modules/user-timeline/user-timeline-item/user-timeline-item-title.service.spec.coffee
index ef60ffce..5855c0fc 100644
--- a/app/modules/user-timeline/user-timeline-item/user-timeline-item-title.service.spec.coffee
+++ b/app/modules/user-timeline/user-timeline-item/user-timeline-item-title.service.spec.coffee
@@ -72,12 +72,8 @@ describe "tgUserTimelineItemTitle", ->
.withArgs('COMMON.SEE_USER_PROFILE', {username: timeline.getIn(['data', 'user', 'username'])})
.returns('user-param')
- usernamelink = sinon.match ((value) ->
- return value.username == 'oo'
- ), "usernamelink"
-
mockTranslate.instant
- .withArgs('TITLE_USER_NAME', usernamelink)
+ .withArgs('TITLE_USER_NAME', {username: '{{username}}'})
.returns('title_ok')
title = mySvc.getTitle(timeline, event, type)
@@ -106,12 +102,8 @@ describe "tgUserTimelineItemTitle", ->
.withArgs('COMMON.SEE_USER_PROFILE', {username: timeline.getIn(['data', 'user', 'username'])})
.returns('user-param')
- usernamelink = sinon.match ((value) ->
- return value.username == 'oo'
- ), "usernamelink"
-
mockTranslate.instant
- .withArgs('TITLE_USER_NAME', usernamelink)
+ .withArgs('TITLE_USER_NAME', {username: '{{username}}'})
.returns('title_ok')
title = mySvc.getTitle(timeline, event, type)
@@ -138,12 +130,8 @@ describe "tgUserTimelineItemTitle", ->
.withArgs('COMMON.FIELDS.STATUS')
.returns('field-params')
- fieldparam = sinon.match ((value) ->
- return value.field_name == 'field-params'
- ), "fieldparam"
-
mockTranslate.instant
- .withArgs('TITLE_FIELD', fieldparam)
+ .withArgs('TITLE_FIELD', {field_name: '{{field_name}}'})
.returns('title_ok')
title = mySvc.getTitle(timeline, event, type)
@@ -168,7 +156,7 @@ describe "tgUserTimelineItemTitle", ->
}
mockTranslate.instant
- .withArgs('NEW_VALUE', {new_value: 'new'})
+ .withArgs('NEW_VALUE', {new_value: '{{new_value}}'})
.returns('new_value_ok')
title = mySvc.getTitle(timeline, event, type)
@@ -191,12 +179,8 @@ describe "tgUserTimelineItemTitle", ->
translate_params: ['project_name']
}
- projectparam = sinon.match ((value) ->
- return value.project_name == 'project_name'
- ), "projectparam"
-
mockTranslate.instant
- .withArgs('TITLE_PROJECT', projectparam)
+ .withArgs('TITLE_PROJECT', {project_name: '{{project_name}}'})
.returns('title_ok')
title = mySvc.getTitle(timeline, event, type)
@@ -224,7 +208,7 @@ describe "tgUserTimelineItemTitle", ->
), "milestoneparam"
mockTranslate.instant
- .withArgs('TITLE_MILESTONE', milestoneparam)
+ .withArgs('TITLE_MILESTONE', {sprint_name: '{{sprint_name}}'})
.returns('title_ok')
title = mySvc.getTitle(timeline, event, type)
@@ -250,12 +234,8 @@ describe "tgUserTimelineItemTitle", ->
translate_params: ['obj_name']
}
- objparam = sinon.match ((value) ->
- return value.obj_name == '#123 subject'
- ), "objparam"
-
mockTranslate.instant
- .withArgs('TITLE_OBJ', objparam)
+ .withArgs('TITLE_OBJ', obj_name: '{{obj_name}}')
.returns('title_ok')
title = mySvc.getTitle(timeline, event, type)
@@ -280,12 +260,8 @@ describe "tgUserTimelineItemTitle", ->
translate_params: ['obj_name']
}
- objparam = sinon.match ((value) ->
- return value.obj_name == 'Slug wiki'
- ), "objparam"
-
mockTranslate.instant
- .withArgs('TITLE_OBJ', objparam)
+ .withArgs('TITLE_OBJ', {obj_name: '{{obj_name}}'})
.returns('title_ok')
title = mySvc.getTitle(timeline, event, type)
@@ -315,7 +291,7 @@ describe "tgUserTimelineItemTitle", ->
), "objparam"
mockTranslate.instant
- .withArgs('TITLE_OBJ', objparam)
+ .withArgs('TITLE_OBJ', {obj_name: '{{obj_name}}'})
.returns('title_ok')
title = mySvc.getTitle(timeline, event, type)
@@ -349,7 +325,7 @@ describe "tgUserTimelineItemTitle", ->
), "objparam"
mockTranslate.instant
- .withArgs('TITLE_OBJ', objparam)
+ .withArgs('TITLE_OBJ', {us_name: '{{us_name}}'})
.returns('title_ok')
title = mySvc.getTitle(timeline, event, type)
diff --git a/app/partials/common/components/created-by.jade b/app/partials/common/components/created-by.jade
index 03ed8980..3689afef 100644
--- a/app/partials/common/components/created-by.jade
+++ b/app/partials/common/components/created-by.jade
@@ -1,9 +1,9 @@
.user-avatar
- a(href!="<%- url %>", title!="<%- owner.full_name_display %>")
- img(src!="<%- owner.photo %>", alt!="<%- owner.full_name_display %>")
+ a(href="{{url}}", title="{{owner.full_name_display}}")
+ img(src="{{owner.photo}}", alt="{{owner.full_name_display}}")
.created-by
- a(href!="<%- url %>", title!="<%- owner.full_name_display %>")
- span.created-title(translate="COMMON.CREATED_BY", translate-values!="{ 'fullDisplayName': '<%- owner.full_name_display %>'}")
+ a(href="{{url}}", title="{{owner.full_name_display}}")
+ span.created-title(translate="COMMON.CREATED_BY", translate-values="{ 'fullDisplayName': owner.full_name_display}")
span.created-date
- | <%- date %>
+ | {{date}}