commit
102bdc1e80
|
@ -5,8 +5,9 @@
|
||||||
### Features
|
### Features
|
||||||
- Contact with the project: if the projects have this module enabled Taiga users can contact them.
|
- Contact with the project: if the projects have this module enabled Taiga users can contact them.
|
||||||
- Velocity forecasting. Create sprints according to team velocity.
|
- Velocity forecasting. Create sprints according to team velocity.
|
||||||
- Remove bower
|
- Remove bower, now use only npm packages.
|
||||||
- Add new wysiwyg editor (like the Medunm editor) with emojis, local storage changes, mentions...
|
- Add new wysiwyg editor (like the Medunm editor) with emojis, local storage changes, mentions...
|
||||||
|
- Add rich text custom fields (with a wysiwyg editor like descreption or comments).
|
||||||
|
|
||||||
### Misc
|
### Misc
|
||||||
- Lots of small and not so small bugfixes.
|
- Lots of small and not so small bugfixes.
|
||||||
|
|
|
@ -406,6 +406,7 @@ module.directive("tgColorSelection", ColorSelectionDirective)
|
||||||
# Custom attributes types (see taiga-back/taiga/projects/custom_attributes/choices.py)
|
# Custom attributes types (see taiga-back/taiga/projects/custom_attributes/choices.py)
|
||||||
TEXT_TYPE = "text"
|
TEXT_TYPE = "text"
|
||||||
MULTILINE_TYPE = "multiline"
|
MULTILINE_TYPE = "multiline"
|
||||||
|
RICHTEXT_TYPE = "richtext"
|
||||||
DATE_TYPE = "date"
|
DATE_TYPE = "date"
|
||||||
URL_TYPE = "url"
|
URL_TYPE = "url"
|
||||||
|
|
||||||
|
@ -419,6 +420,10 @@ TYPE_CHOICES = [
|
||||||
key: MULTILINE_TYPE,
|
key: MULTILINE_TYPE,
|
||||||
name: "ADMIN.CUSTOM_FIELDS.FIELD_TYPE_MULTI"
|
name: "ADMIN.CUSTOM_FIELDS.FIELD_TYPE_MULTI"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: RICHTEXT_TYPE,
|
||||||
|
name: "ADMIN.CUSTOM_FIELDS.FIELD_TYPE_RICHTEXT"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: DATE_TYPE,
|
key: DATE_TYPE,
|
||||||
name: "ADMIN.CUSTOM_FIELDS.FIELD_TYPE_DATE"
|
name: "ADMIN.CUSTOM_FIELDS.FIELD_TYPE_DATE"
|
||||||
|
|
|
@ -32,6 +32,7 @@ module = angular.module("taigaCommon")
|
||||||
|
|
||||||
# Custom attributes types (see taiga-back/taiga/projects/custom_attributes/choices.py)
|
# Custom attributes types (see taiga-back/taiga/projects/custom_attributes/choices.py)
|
||||||
TEXT_TYPE = "text"
|
TEXT_TYPE = "text"
|
||||||
|
RICHTEXT_TYPE = "url"
|
||||||
MULTILINE_TYPE = "multiline"
|
MULTILINE_TYPE = "multiline"
|
||||||
DATE_TYPE = "date"
|
DATE_TYPE = "date"
|
||||||
URL_TYPE = "url"
|
URL_TYPE = "url"
|
||||||
|
@ -53,6 +54,10 @@ TYPE_CHOICES = [
|
||||||
{
|
{
|
||||||
key: URL_TYPE,
|
key: URL_TYPE,
|
||||||
name: "ADMIN.CUSTOM_FIELDS.FIELD_TYPE_URL"
|
name: "ADMIN.CUSTOM_FIELDS.FIELD_TYPE_URL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: RICHTEXT_TYPE,
|
||||||
|
name: "ADMIN.CUSTOM_FIELDS.FIELD_TYPE_RICHTEXT"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -193,6 +198,15 @@ CustomAttributeValueDirective = ($template, $selectedText, $compile, $translate,
|
||||||
requiredEditionPerm = $attrs.requiredEditionPerm
|
requiredEditionPerm = $attrs.requiredEditionPerm
|
||||||
return permissions.indexOf(requiredEditionPerm) > -1
|
return permissions.indexOf(requiredEditionPerm) > -1
|
||||||
|
|
||||||
|
$scope.saveCustomRichText = (markdown, callback) =>
|
||||||
|
attributeValue.value = markdown
|
||||||
|
$ctrl.updateAttributeValue(attributeValue).then ->
|
||||||
|
callback()
|
||||||
|
render(attributeValue, false)
|
||||||
|
|
||||||
|
$scope.cancelCustomRichText= () =>
|
||||||
|
render(attributeValue, false)
|
||||||
|
|
||||||
submit = debounce 2000, (event) =>
|
submit = debounce 2000, (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
|
@ -214,6 +228,9 @@ CustomAttributeValueDirective = ($template, $selectedText, $compile, $translate,
|
||||||
|
|
||||||
# Bootstrap
|
# Bootstrap
|
||||||
attributeValue = $scope.$eval($attrs.tgCustomAttributeValue)
|
attributeValue = $scope.$eval($attrs.tgCustomAttributeValue)
|
||||||
|
if attributeValue.value == null or attributeValue.value == undefined
|
||||||
|
attributeValue.value = ""
|
||||||
|
$scope.customAttributeValue = attributeValue
|
||||||
render(attributeValue)
|
render(attributeValue)
|
||||||
|
|
||||||
## Actions (on view mode)
|
## Actions (on view mode)
|
||||||
|
|
|
@ -573,6 +573,7 @@
|
||||||
"ISSUE_DESCRIPTION": "Issues custom fields",
|
"ISSUE_DESCRIPTION": "Issues custom fields",
|
||||||
"ISSUE_ADD": "Add a custom field in issues",
|
"ISSUE_ADD": "Add a custom field in issues",
|
||||||
"FIELD_TYPE_TEXT": "Text",
|
"FIELD_TYPE_TEXT": "Text",
|
||||||
|
"FIELD_TYPE_RICHTEXT": "Rich text",
|
||||||
"FIELD_TYPE_MULTI": "Multi-line",
|
"FIELD_TYPE_MULTI": "Multi-line",
|
||||||
"FIELD_TYPE_DATE": "Date",
|
"FIELD_TYPE_DATE": "Date",
|
||||||
"FIELD_TYPE_URL": "Url"
|
"FIELD_TYPE_URL": "Url"
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2016 Andrey Antukh <niwi@niwi.nz>
|
||||||
|
# Copyright (C) 2014-2016 Jesús Espino Garcia <jespinog@gmail.com>
|
||||||
|
# Copyright (C) 2014-2016 David Barragán Merino <bameda@dbarragan.com>
|
||||||
|
# Copyright (C) 2014-2016 Alejandro Alonso <alejandro.alonso@kaleidos.net>
|
||||||
|
# Copyright (C) 2014-2016 Juan Francisco Alcántara <juanfran.alcantara@kaleidos.net>
|
||||||
|
# Copyright (C) 2014-2016 Xavi Julian <xavier.julian@kaleidos.net>
|
||||||
|
#
|
||||||
|
# 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/components/wysiwyg/comment-edit-wysiwyg.directive.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
CustomFieldEditWysiwyg = (attachmentsFullService) ->
|
||||||
|
link = ($scope, $el, $attrs) ->
|
||||||
|
types = {
|
||||||
|
userstories: "us",
|
||||||
|
issues: "issue",
|
||||||
|
tasks: "task"
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadFile = (file, cb) ->
|
||||||
|
return attachmentsFullService.addAttachment($scope.vm.projectId, $scope.vm.comment.comment.id, types[$scope.vm.comment.comment._name], file).then (result) ->
|
||||||
|
cb(result.getIn(['file', 'name']), result.getIn(['file', 'url']))
|
||||||
|
|
||||||
|
$scope.uploadFiles = (files, cb) ->
|
||||||
|
for file in files
|
||||||
|
uploadFile(file, cb)
|
||||||
|
|
||||||
|
return {
|
||||||
|
scope: true,
|
||||||
|
link: link,
|
||||||
|
template: """
|
||||||
|
<div>
|
||||||
|
<tg-wysiwyg
|
||||||
|
editonly
|
||||||
|
content='customAttributeValue.value'
|
||||||
|
on-save="saveCustomRichText(text, cb)"
|
||||||
|
on-cancel="cancelCustomRichText()"
|
||||||
|
on-upload-file='uploadFiles(files, cb)'>
|
||||||
|
</tg-wysiwyg>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
angular.module("taigaComponents")
|
||||||
|
.directive("tgCustomFieldEditWysiwyg", ["tgAttachmentsFullService", CustomFieldEditWysiwyg])
|
|
@ -1,19 +1,29 @@
|
||||||
.diff-custom-new(
|
.diff-status-wrapper(
|
||||||
ng-if="vm.diff.new.length"
|
ng-if="vm.diff.new.length"
|
||||||
ng-repeat="newCustom in vm.diff.new"
|
ng-repeat="newCustom in vm.diff.new"
|
||||||
)
|
)
|
||||||
span.key(translate="ACTIVITY.CREATED_CUSTOM_ATTRIBUTE")
|
span.key(translate="ACTIVITY.CREATED_CUSTOM_ATTRIBUTE")
|
||||||
span.diff ({{newCustom.name}})
|
span.diff ({{newCustom.name}})
|
||||||
span.diff {{newCustom.value}}
|
|
||||||
|
span(ng-if="newCustom.type == 'richtext'")
|
||||||
.diff-custom-new(
|
p.diff(tg-bo-html="newCustom.value_diff")
|
||||||
|
|
||||||
|
span(ng-if="newCustom.type != 'richtext'")
|
||||||
|
span.diff {{newCustom.value}}
|
||||||
|
|
||||||
|
.diff-status-wrapper(
|
||||||
ng-if="vm.diff.changed.length"
|
ng-if="vm.diff.changed.length"
|
||||||
ng-repeat="changeCustom in vm.diff.changed"
|
ng-repeat="changeCustom in vm.diff.changed"
|
||||||
)
|
)
|
||||||
span.key(translate="ACTIVITY.UPDATED_CUSTOM_ATTRIBUTE")
|
span.key(translate="ACTIVITY.UPDATED_CUSTOM_ATTRIBUTE")
|
||||||
span.diff ({{changeCustom.name}})
|
span.diff ({{changeCustom.name}})
|
||||||
span.diff {{changeCustom.changes.value[0]}}
|
|
||||||
tg-svg(
|
span(ng-if="changeCustom.type == 'richtext'")
|
||||||
svg-icon="icon-arrow-right"
|
p.diff(tg-bo-html="changeCustom.value_diff")
|
||||||
)
|
|
||||||
span.diff {{changeCustom.changes.value[1]}}
|
span(ng-if="changeCustom.type != 'richtext'")
|
||||||
|
span.diff {{changeCustom.changes.value[0]}}
|
||||||
|
tg-svg(
|
||||||
|
svg-icon="icon-arrow-right"
|
||||||
|
)
|
||||||
|
span.diff {{changeCustom.changes.value[1]}}
|
||||||
|
|
|
@ -13,6 +13,8 @@ form.custom-field-single.editable
|
||||||
input#custom-field-value(name="value", type="text", value!="<%- value %>")
|
input#custom-field-value(name="value", type="text", value!="<%- value %>")
|
||||||
<% } else if (type=="multiline") { %>
|
<% } else if (type=="multiline") { %>
|
||||||
textarea#custom-field-value(name="value") <%- value %>
|
textarea#custom-field-value(name="value") <%- value %>
|
||||||
|
<% } else if (type=="richtext") { %>
|
||||||
|
tg-custom-field-edit-wysiwyg()
|
||||||
<% } else if (type=="date") { %>
|
<% } else if (type=="date") { %>
|
||||||
input#custom-field-value(name="value", type="text", data-pikaday, value!="<%- value %>")
|
input#custom-field-value(name="value", type="text", data-pikaday, value!="<%- value %>")
|
||||||
<% } else if (type=="url") { %>
|
<% } else if (type=="url") { %>
|
||||||
|
@ -21,6 +23,8 @@ form.custom-field-single.editable
|
||||||
input#custom-field-value(name="value", type="text", value!="<%- value %>")
|
input#custom-field-value(name="value", type="text", value!="<%- value %>")
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
|
<% if (type != "richtext") { %>
|
||||||
div.custom-field-options
|
div.custom-field-options
|
||||||
a.js-save-description(href="", title="{{'COMMON.CUSTOM_ATTRIBUTES.SAVE' | translate}}")
|
a.js-save-description(href="", title="{{'COMMON.CUSTOM_ATTRIBUTES.SAVE' | translate}}")
|
||||||
tg-svg(svg-icon="icon-save")
|
tg-svg(svg-icon="icon-save")
|
||||||
|
<% } %>
|
||||||
|
|
|
@ -7,14 +7,19 @@
|
||||||
<%- description %>
|
<%- description %>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
|
<% if (type=="url") { %>
|
||||||
.custom-field-value.js-value-view-mode
|
.custom-field-value.js-value-view-mode
|
||||||
span
|
span
|
||||||
<% if (type=="url") { %>
|
|
||||||
a(href!="<%- value %>")
|
a(href!="<%- value %>")
|
||||||
<%- value %>
|
<%- value %>
|
||||||
<% } else { %>
|
<% } else if (type=="richtext") { %>
|
||||||
|
.custom-field-value.js-value-view-mode.wysiwyg
|
||||||
|
div(ng-bind-html!="\'<%- value %>\'|markdownToHTML")
|
||||||
|
<% } else { %>
|
||||||
|
.custom-field-value.js-value-view-mode
|
||||||
|
span
|
||||||
<%- value %>
|
<%- value %>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<% if (isEditable) { %>
|
<% if (isEditable) { %>
|
||||||
.custom-field-options
|
.custom-field-options
|
||||||
|
|
|
@ -30,6 +30,10 @@ section.custom-fields-table.basic-table
|
||||||
ng-switch-default
|
ng-switch-default
|
||||||
translate="ADMIN.CUSTOM_FIELDS.FIELD_TYPE_TEXT"
|
translate="ADMIN.CUSTOM_FIELDS.FIELD_TYPE_TEXT"
|
||||||
)
|
)
|
||||||
|
span(
|
||||||
|
ng-switch-when="richtext"
|
||||||
|
translate="ADMIN.CUSTOM_FIELDS.FIELD_TYPE_RICHTEXT"
|
||||||
|
)
|
||||||
span(
|
span(
|
||||||
ng-switch-when="multiline"
|
ng-switch-when="multiline"
|
||||||
translate="ADMIN.CUSTOM_FIELDS.FIELD_TYPE_MULTI"
|
translate="ADMIN.CUSTOM_FIELDS.FIELD_TYPE_MULTI"
|
||||||
|
|
|
@ -71,6 +71,9 @@
|
||||||
padding: 0 1rem 0 2rem;
|
padding: 0 1rem 0 2rem;
|
||||||
&.js-value-view-mode {
|
&.js-value-view-mode {
|
||||||
white-space: pre-line;
|
white-space: pre-line;
|
||||||
|
&.wysiwyg {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
form {
|
form {
|
||||||
|
|
Loading…
Reference in New Issue