Fixed #1543: Emojis support on subjects

stable
Jesús Espino 2017-10-25 18:56:09 +02:00 committed by Alex Hermida
parent 2fcfec7b18
commit e1d9b8d0aa
18 changed files with 50 additions and 114 deletions

View File

@ -495,92 +495,6 @@ DeleteButtonDirective = ($log, $repo, $confirm, $location, $template) ->
module.directive("tgDeleteButton", ["$log", "$tgRepo", "$tgConfirm", "$tgLocation", "$tgTemplate", DeleteButtonDirective]) module.directive("tgDeleteButton", ["$log", "$tgRepo", "$tgConfirm", "$tgLocation", "$tgTemplate", DeleteButtonDirective])
#############################################################################
## Editable subject directive
#############################################################################
EditableSubjectDirective = ($rootscope, $repo, $confirm, $loading, $modelTransform, $template) ->
template = $template.get("common/components/editable-subject.html")
link = ($scope, $el, $attrs, $model) ->
$scope.$on "object:updated", () ->
$el.find('.edit-subject').hide()
$el.find('.view-subject').show()
isEditable = ->
return $scope.project.my_permissions.indexOf($attrs.requiredPerm) != -1
save = (subject) ->
currentLoading = $loading()
.target($el.find('.save-container'))
.start()
transform = $modelTransform.save (item) ->
item.subject = subject
return item
transform.then =>
$confirm.notify("success")
$rootscope.$broadcast("object:updated")
$el.find('.edit-subject').hide()
$el.find('.view-subject').show()
transform.then null, ->
$confirm.notify("error")
transform.finally ->
currentLoading.finish()
return transform
$el.click ->
return if not isEditable()
$el.find('.edit-subject').show()
$el.find('.view-subject').hide()
$el.find('input').focus()
$el.on "click", ".save", (e) ->
e.preventDefault()
subject = $scope.item.subject
save(subject)
$el.on "keyup", "input", (event) ->
if event.keyCode == 13
subject = $scope.item.subject
save(subject)
else if event.keyCode == 27
$scope.$apply () => $model.$modelValue.revert()
$el.find('.edit-subject').hide()
$el.find('.view-subject').show()
$el.find('.edit-subject').hide()
$scope.$watch $attrs.ngModel, (value) ->
return if not value
$scope.item = value
if not isEditable()
$el.find('.view-subject .edit').remove()
$scope.$on "$destroy", ->
$el.off()
return {
link: link
restrict: "EA"
require: "ngModel"
template: template
}
module.directive("tgEditableSubject", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQueueModelTransformation",
"$tgTemplate", EditableSubjectDirective])
############################################################################# #############################################################################
## Common list directives ## Common list directives
############################################################################# #############################################################################

View File

@ -29,7 +29,7 @@ debounce = @.taiga.debounce
module = angular.module("taigaRelatedTasks", []) module = angular.module("taigaRelatedTasks", [])
RelatedTaskRowDirective = ($repo, $compile, $confirm, $rootscope, $loading, $template, $translate) -> RelatedTaskRowDirective = ($repo, $compile, $confirm, $rootscope, $loading, $template, $translate, $emojis) ->
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)
@ -82,7 +82,11 @@ RelatedTaskRowDirective = ($repo, $compile, $confirm, $rootscope, $loading, $tem
delete_task: $scope.project.my_permissions.indexOf("delete_task") != -1 delete_task: $scope.project.my_permissions.indexOf("delete_task") != -1
} }
$el.html($compile(templateView({task: task, perms: perms}))($scope)) $el.html($compile(templateView({
task: task,
perms: perms,
emojify: (text) -> $emojis.replaceEmojiNameByHtmlImgs(_.escape(text))
}))($scope))
$el.on "click", ".edit-task", -> $el.on "click", ".edit-task", ->
renderEdit($model.$modelValue) renderEdit($model.$modelValue)
@ -119,7 +123,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", module.directive("tgRelatedTaskRow", ["$tgRepo", "$compile", "$tgConfirm", "$rootScope", "$tgLoading",
"$tgTemplate", "$translate", RelatedTaskRowDirective]) "$tgTemplate", "$translate", "$tgEmojis", RelatedTaskRowDirective])
RelatedTaskCreateFormDirective = ($repo, $compile, $confirm, $tgmodel, $loading, $analytics) -> RelatedTaskCreateFormDirective = ($repo, $compile, $confirm, $tgmodel, $loading, $analytics) ->

View File

@ -3,7 +3,8 @@ span.belong-to-epic-text-wrapper(tg-repeat="epic in immutable_epics track by epi
a.belong-to-epic-text( a.belong-to-epic-text(
href="" href=""
tg-nav="project-epics-detail:project=epic.getIn(['project', 'slug']),ref=epic.get('ref')" tg-nav="project-epics-detail:project=epic.getIn(['project', 'slug']),ref=epic.get('ref')"
) #{hash}{{epic.get('ref')}} {{epic.get('subject')}} ng-bind-html="'#'+epic.get('ref')+' '+epic.get('subject') | emojify"
)
span.belong-to-epic-label( span.belong-to-epic-label(
ng-style="::{'background-color': epic.get('color')}" ng-style="::{'background-color': epic.get('color')}"
translate="EPICS.EPIC" translate="EPICS.EPIC"

View File

@ -4,4 +4,5 @@ ul.card-tasks(ng-if="vm.isRelatedTasksVisible()")
href="#" href="#"
tg-nav="project-tasks-detail:project=vm.project.slug,ref=task.get('ref')", tg-nav="project-tasks-detail:project=vm.project.slug,ref=task.get('ref')",
ng-class="{'closed-task': task.get('is_closed'), 'blocked-task': task.get('is_blocked')}" ng-class="{'closed-task': task.get('is_closed'), 'blocked-task': task.get('is_blocked')}"
) {{"#" + task.get('ref')}} {{task.get('subject')}} ng-bind-html="'#'+task.get('ref')+' '+task.get('subject') | emojify"
)

View File

@ -6,7 +6,7 @@ h2.card-title
title="#{{ ::vm.item.getIn(['model', 'ref']) }} {{ vm.item.getIn(['model', 'subject'])}}" title="#{{ ::vm.item.getIn(['model', 'ref']) }} {{ vm.item.getIn(['model', 'subject'])}}"
) )
span(ng-if="vm.visible('ref')") {{::"#" + vm.item.getIn(['model', 'ref'])}} span(ng-if="vm.visible('ref')") {{::"#" + vm.item.getIn(['model', 'ref'])}}
span.e2e-title(ng-if="vm.visible('subject')") {{vm.item.getIn(['model', 'subject'])}} span.e2e-title(ng-if="vm.visible('subject')", ng-bind-html="vm.item.getIn(['model', 'subject']) | emojify")
tg-belong-to-epics( tg-belong-to-epics(
format="pill" format="pill"
ng-if="vm.item.getIn(['model', 'epics'])" ng-if="vm.item.getIn(['model', 'epics'])"

View File

@ -7,10 +7,12 @@
span.detail-subject.e2e-title-subject( span.detail-subject.e2e-title-subject(
ng-click="vm.editSubject(true)" ng-click="vm.editSubject(true)"
ng-if="vm.permissions.canEdit" ng-if="vm.permissions.canEdit"
) {{vm.item.subject}} ng-bind-html="vm.item.subject | emojify"
)
span.detail-subject.e2e-title-subject( span.detail-subject.e2e-title-subject(
ng-if="!vm.permissions.canEdit" ng-if="!vm.permissions.canEdit"
) {{vm.item.subject}} ng-bind-html="vm.item.subject | emojify"
)
a( a(
href="" href=""
ng-if="vm.permissions.canEdit" ng-if="vm.permissions.canEdit"
@ -55,7 +57,7 @@
title="{{'TASK.TITLE_LINK_GO_OWNER' | translate}}" title="{{'TASK.TITLE_LINK_GO_OWNER' | translate}}"
) )
span.item-ref {{'#' + vm.item.user_story_extra_info.ref}} span.item-ref {{'#' + vm.item.user_story_extra_info.ref}}
span {{::vm.item.user_story_extra_info.subject}} span(ng-bind-html="vm.item.user_story_extra_info.subject | emojify")
tg-belong-to-epics( tg-belong-to-epics(
ng-if="::vm.item.user_story_extra_info.epics" ng-if="::vm.item.user_story_extra_info.epics"
epics="::vm.item.user_story_extra_info.epics" epics="::vm.item.user_story_extra_info.epics"
@ -69,7 +71,8 @@
ng-repeat="userstory in vm.item.generated_user_stories track by userstory.id" ng-repeat="userstory in vm.item.generated_user_stories track by userstory.id"
tg-check-permission="view_us" tg-check-permission="view_us"
tg-nav="project-userstories-detail:project=vm.project.slug,ref=userstory.ref" tg-nav="project-userstories-detail:project=vm.project.slug,ref=userstory.ref"
) {{'#' + userstory.ref}} {{userstory.subject}} ng-bind-html="'#'+userstory.ref+' '+userstory.subject | emojify"
)
//- Issue origin from github //- Issue origin from github
.issue-external-reference(ng-if="vm.item.external_reference") .issue-external-reference(ng-if="vm.item.external_reference")
@ -91,7 +94,7 @@
title="{{'US.TITLE_LINK_GO_TO_ISSUE' | translate}}" title="{{'US.TITLE_LINK_GO_TO_ISSUE' | translate}}"
) )
span.item-ref {{'#' + vm.item.origin_issue.ref}} span.item-ref {{'#' + vm.item.origin_issue.ref}}
span {{vm.item.origin_issue.subject}} span(ng-bind-html="vm.item.origin_issue.subject | emojify")
//- Blocked description //- Blocked description
.block-desc-container(ng-show="vm.item.is_blocked") .block-desc-container(ng-show="vm.item.is_blocked")

View File

@ -20,7 +20,8 @@
a( a(
tg-nav="project-epics-detail:project=vm.project.slug,ref=vm.epic.get('ref')" tg-nav="project-epics-detail:project=vm.project.slug,ref=vm.epic.get('ref')"
ng-attr-title="{{::vm.epic.get('subject')}}" ng-attr-title="{{::vm.epic.get('subject')}}"
) #{hash}{{::vm.epic.get('ref')}} {{::vm.epic.get('subject')}} ng-bind-html="'#'+vm.epic.get('ref')+' '+vm.epic.get('subject') | emojify"
)
span.epic-pill( span.epic-pill(
ng-style="::{'background-color': vm.epic.get('color')}" ng-style="::{'background-color': vm.epic.get('color')}"
translate="EPICS.EPIC" translate="EPICS.EPIC"

View File

@ -13,7 +13,8 @@
a( a(
tg-nav="project-userstories-detail:project=vm.story.getIn(['project_extra_info', 'slug']),ref=vm.story.get('ref')" tg-nav="project-userstories-detail:project=vm.story.getIn(['project_extra_info', 'slug']),ref=vm.story.get('ref')"
ng-attr-title="{{::vm.story.get('subject')}}" ng-attr-title="{{::vm.story.get('subject')}}"
) #{hash}{{::vm.story.get('ref')}} {{::vm.story.get('subject')}} ng-bind-html="'#'+vm.story.get('ref')+' '+vm.story.get('subject') | emojify"
)
tg-belong-to-epics( tg-belong-to-epics(
ng-if="vm.story.get('epics')" ng-if="vm.story.get('epics')"
format="pill" format="pill"

View File

@ -8,7 +8,8 @@ tg-svg.icon-drag(
a( a(
tg-nav="project-userstories-detail:project=vm.userstory.getIn(['project_extra_info', 'slug']),ref=vm.userstory.get('ref')" tg-nav="project-userstories-detail:project=vm.userstory.getIn(['project_extra_info', 'slug']),ref=vm.userstory.get('ref')"
ng-attr-title="{{vm.userstory.get('subject')}}" ng-attr-title="{{vm.userstory.get('subject')}}"
) #{hash}{{vm.userstory.get('ref')}} {{vm.userstory.get('subject')}} ng-bind-html="'#'+vm.userstory.get('ref')+' '+vm.userstory.get('subject') | emojify"
)
tg-belong-to-epics( tg-belong-to-epics(
format="pill" format="pill"

View File

@ -39,6 +39,11 @@ describe "dutyDirective", () ->
return value return value
provide.value "translateFilter", mockTranslateFilter provide.value "translateFilter", mockTranslateFilter
_mockEmojifyFilter = () ->
mockEmojifyFilter = (value) ->
return value
provide.value "emojifyFilter", mockEmojifyFilter
_mockTgProjectsService = () -> _mockTgProjectsService = () ->
mockTgProjectsService = { mockTgProjectsService = {
projectsById: { projectsById: {
@ -60,6 +65,7 @@ describe "dutyDirective", () ->
_mockTgProjectsService() _mockTgProjectsService()
_mockTranslate() _mockTranslate()
_mockTranslateFilter() _mockTranslateFilter()
_mockEmojifyFilter()
return null return null
beforeEach -> beforeEach ->

View File

@ -39,4 +39,4 @@ a.list-itemtype-ticket(
ng-if="::vm.duty.get('is_blocked')" ng-if="::vm.duty.get('is_blocked')"
title="{{::vm.duty.get('blocked_note')}}" title="{{::vm.duty.get('blocked_note')}}"
) {{ 'COMMON.BLOCKED' | translate }} ) {{ 'COMMON.BLOCKED' | translate }}
span {{ ::duty.get('subject') }} span(ng-bind-html="duty.get('subject') | emojify")

View File

@ -53,25 +53,29 @@
ng-if="::vm.item.get('type') === 'epic'" ng-if="::vm.item.get('type') === 'epic'"
tg-nav="project-epics-detail:project=vm.item.get('project_slug'),ref=vm.item.get('ref')" tg-nav="project-epics-detail:project=vm.item.get('project_slug'),ref=vm.item.get('ref')"
title="#{{ ::vm.item.get('ref') }} {{ ::vm.item.get('subject') }}" title="#{{ ::vm.item.get('ref') }} {{ ::vm.item.get('subject') }}"
) {{ ::vm.item.get('subject') }} ng-bind-html="vm.item.get('subject') | emojify"
)
a.ticket-title( a.ticket-title(
href="#" href="#"
ng-if="::vm.item.get('type') === 'userstory'" ng-if="::vm.item.get('type') === 'userstory'"
tg-nav="project-userstories-detail:project=vm.item.get('project_slug'),ref=vm.item.get('ref')" tg-nav="project-userstories-detail:project=vm.item.get('project_slug'),ref=vm.item.get('ref')"
title="#{{ ::vm.item.get('ref') }} {{ ::vm.item.get('subject') }}" title="#{{ ::vm.item.get('ref') }} {{ ::vm.item.get('subject') }}"
) {{ ::vm.item.get('subject') }} ng-bind-html="vm.item.get('subject') | emojify"
)
a.ticket-title( a.ticket-title(
href="#" href="#"
ng-if="::vm.item.get('type') === 'task'" ng-if="::vm.item.get('type') === 'task'"
tg-nav="project-tasks-detail:project=vm.item.get('project_slug'),ref=vm.item.get('ref')" tg-nav="project-tasks-detail:project=vm.item.get('project_slug'),ref=vm.item.get('ref')"
title="#{{ ::vm.item.get('ref') }} {{ ::vm.item.get('subject') }}" title="#{{ ::vm.item.get('ref') }} {{ ::vm.item.get('subject') }}"
) {{ ::vm.item.get('subject') }} ng-bind-html="vm.item.get('subject') | emojify"
)
a.ticket-title( a.ticket-title(
href="#" href="#"
ng-if="::vm.item.get('type') === 'issue'" ng-if="::vm.item.get('type') === 'issue'"
tg-nav="project-issues-detail:project=vm.item.get('project_slug'),ref=vm.item.get('ref')" tg-nav="project-issues-detail:project=vm.item.get('project_slug'),ref=vm.item.get('ref')"
title="#{{ ::vm.item.get('ref') }} {{ ::vm.item.get('subject') }}" title="#{{ ::vm.item.get('ref') }} {{ ::vm.item.get('subject') }}"
) {{ ::vm.item.get('subject') }} ng-bind-html="vm.item.get('subject') | emojify"
)
div.list-itemtype-track div.list-itemtype-track
span.list-itemtype-track-likers( span.list-itemtype-track-likers(

View File

@ -26,7 +26,7 @@
title="#{{ us.ref }} {{ us.subject }}" title="#{{ us.ref }} {{ us.subject }}"
) )
span(tg-bo-ref="us.ref") span(tg-bo-ref="us.ref")
span(ng-bind="us.subject") span(ng-bind-html="us.subject | emojify")
tg-belong-to-epics( tg-belong-to-epics(
format="pill" format="pill"
ng-if="us.epics" ng-if="us.epics"

View File

@ -53,7 +53,7 @@ section.issues-table.basic-table(ng-class="{empty: !issues.length}")
ng-if="issue.is_blocked" ng-if="issue.is_blocked"
title="{{issue.blocked_note}}" title="{{issue.blocked_note}}"
) {{'ISSUES.TABLE.BLOCKED' | translate}} ) {{'ISSUES.TABLE.BLOCKED' | translate}}
span(ng-bind="issue.subject") span(ng-bind-html="issue.subject | emojify")
div.issue-field(tg-issue-status-inline-edition="issue") div.issue-field(tg-issue-status-inline-edition="issue")

View File

@ -14,7 +14,7 @@ script(type="text/ng-template", id="search-issues")
div.user-stories div.user-stories
div.user-story-name div.user-story-name
a(href="", tg-nav="project-issues-detail:project=project.slug,ref=issue.ref", a(href="", tg-nav="project-issues-detail:project=project.slug,ref=issue.ref",
tg-bo-bind="issue.subject") tg-bind-html="issue.subject | emojify")
div.status(tg-listitem-issue-status="issue") div.status(tg-listitem-issue-status="issue")
div.assigned-to(tg-listitem-assignedto="issue") div.assigned-to(tg-listitem-assignedto="issue")
@ -34,7 +34,7 @@ script(type="text/ng-template", id="search-epics")
div.user-stories div.user-stories
div.user-story-name div.user-story-name
a(href="", tg-nav="project-epics-detail:project=project.slug,ref=epic.ref", a(href="", tg-nav="project-epics-detail:project=project.slug,ref=epic.ref",
tg-bo-bind="epic.subject") tg-bind-html="epic.subject | emojify")
div.status(tg-listitem-epic-status="epic") div.status(tg-listitem-epic-status="epic")
div.empty-search-results(ng-class="{'hidden': epics.length}") div.empty-search-results(ng-class="{'hidden': epics.length}")
@ -56,7 +56,7 @@ script(type="text/ng-template", id="search-userstories")
div.user-stories div.user-stories
div.user-story-name div.user-story-name
a(href="", tg-nav="project-userstories-detail:project=project.slug,ref=us.ref", a(href="", tg-nav="project-userstories-detail:project=project.slug,ref=us.ref",
tg-bo-bind="us.subject") tg-bind-html="us.subject | emojify")
div.sprint div.sprint
div.sprint-link div.sprint-link
a(href="", tg-nav="project-taskboard:project=project.slug,sprint=us.milestone_slug", a(href="", tg-nav="project-taskboard:project=project.slug,sprint=us.milestone_slug",
@ -81,7 +81,7 @@ script(type="text/ng-template", id="search-tasks")
div.user-stories div.user-stories
div.user-story-name div.user-story-name
a(href="", tg-nav="project-tasks-detail:project=project.slug,ref=task.ref", a(href="", tg-nav="project-tasks-detail:project=project.slug,ref=task.ref",
tg-bo-bind="task.subject") tg-bind-html="task.subject | emojify")
div.status(tg-listitem-task-status="task") div.status(tg-listitem-task-status="task")
div.assigned-to(tg-listitem-assignedto="task") div.assigned-to(tg-listitem-assignedto="task")

View File

@ -18,7 +18,7 @@ div.sprint-table(tg-bind-scope, ng-class="{'sprint-empty-wrapper': !sprint.user_
tg-bo-title="'#' + us.ref + ' ' + us.subject", tg-bo-title="'#' + us.ref + ' ' + us.subject",
ng-class="{closed: us.is_closed, blocked: us.is_blocked}") ng-class="{closed: us.is_closed, blocked: us.is_blocked}")
span(tg-bo-ref="us.ref") span(tg-bo-ref="us.ref")
span(tg-bo-bind="us.subject") span(tg-bind-html="us.subject | emojify")
tg-belong-to-epics( tg-belong-to-epics(
format="pill" format="pill"
ng-if="us.epics" ng-if="us.epics"

View File

@ -53,7 +53,7 @@ div.taskboard-table(
tg-nav-get-params="{\"milestone\": {{us.milestone}}}", tg-nav-get-params="{\"milestone\": {{us.milestone}}}",
tg-bo-title="'#' + us.ref + ' ' + us.subject") tg-bo-title="'#' + us.ref + ' ' + us.subject")
span.us-ref(tg-bo-ref="us.ref") span.us-ref(tg-bo-ref="us.ref")
span(ng-bind="us.subject") span(ng-bind-html="us.subject | emojify")
tg-belong-to-epics( tg-belong-to-epics(
format="pill" format="pill"
ng-if="us.epics" ng-if="us.epics"

View File

@ -2,7 +2,7 @@
a.clickable( a.clickable(
tg-nav="project-tasks-detail:project=project.slug,ref=task.ref") tg-nav="project-tasks-detail:project=project.slug,ref=task.ref")
span #<%- task.ref %> span #<%- task.ref %>
span(ng-non-bindable) <%- task.subject %> span(ng-non-bindable) <%= emojify(task.subject) %>
.task-settings .task-settings
<% if(perms.modify_task) { %> <% if(perms.modify_task) { %>