Merge pull request #885 from taigaio/rich-text-custom-fields
Rich text custom fieldsremotes/origin/issue/4795/notification_even_they_are_disabled
commit
86897d3469
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -1,11 +1,17 @@
|
|||
# Changelog #
|
||||
|
||||
## 3.1.0 ¿¿?? (¿¿??)
|
||||
|
||||
## 3.1.0 unnamed (unreleased)
|
||||
|
||||
### Features
|
||||
- Contact with the project: if the projects have this module enabled Taiga users can contact them.
|
||||
- Memberships API endpoints now allows using usernames and emails instead of using only emails
|
||||
- Contacts API search by free text: consulting the username, full name and email
|
||||
- Memberships API endpoints now allows using usernames and emails instead of using only emails.
|
||||
- Contacts API search by free text: consulting the username, full name and email.
|
||||
- Ability to create rich text custom fields in Epics, User Stories, Tasks and Isues.
|
||||
|
||||
### Misc
|
||||
- Lots of small and not so small bugfixes.
|
||||
|
||||
|
||||
## 3.0.0 Stellaria Borealis (2016-10-02)
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ class DiffMatchPatch(diff_match_patch.diff_match_patch):
|
|||
|
||||
def get_diff_of_htmls(html1, html2):
|
||||
diffutil = DiffMatchPatch()
|
||||
diffs = diffutil.diff_main(html1, html2)
|
||||
diffs = diffutil.diff_main(html1 or "", html2 or "")
|
||||
diffutil.diff_cleanupSemantic(diffs)
|
||||
return diffutil.diff_pretty_html(diffs)
|
||||
|
||||
|
|
|
@ -21,12 +21,14 @@ from django.utils.translation import ugettext_lazy as _
|
|||
|
||||
TEXT_TYPE = "text"
|
||||
MULTILINE_TYPE = "multiline"
|
||||
RICHTEXT_TYPE = "richtext"
|
||||
DATE_TYPE = "date"
|
||||
URL_TYPE = "url"
|
||||
|
||||
TYPES_CHOICES = (
|
||||
(TEXT_TYPE, _("Text")),
|
||||
(MULTILINE_TYPE, _("Multi-Line Text")),
|
||||
(RICHTEXT_TYPE, _("Rich text")),
|
||||
(DATE_TYPE, _("Date")),
|
||||
(URL_TYPE, _("Url"))
|
||||
)
|
||||
|
|
|
@ -208,13 +208,14 @@ def extract_attachments(obj) -> list:
|
|||
@as_tuple
|
||||
def extract_epic_custom_attributes(obj) -> list:
|
||||
with suppress(ObjectDoesNotExist):
|
||||
custom_attributes_values = obj.custom_attributes_values.attributes_values
|
||||
custom_attributes_values = obj.custom_attributes_values.attributes_values
|
||||
for attr in obj.project.epiccustomattributes.all():
|
||||
with suppress(KeyError):
|
||||
value = custom_attributes_values[str(attr.id)]
|
||||
yield {"id": attr.id,
|
||||
"name": attr.name,
|
||||
"value": value}
|
||||
"value": value,
|
||||
"type": attr.type}
|
||||
|
||||
|
||||
@as_tuple
|
||||
|
@ -226,7 +227,8 @@ def extract_user_story_custom_attributes(obj) -> list:
|
|||
value = custom_attributes_values[str(attr.id)]
|
||||
yield {"id": attr.id,
|
||||
"name": attr.name,
|
||||
"value": value}
|
||||
"value": value,
|
||||
"type": attr.type}
|
||||
|
||||
|
||||
@as_tuple
|
||||
|
@ -238,7 +240,8 @@ def extract_task_custom_attributes(obj) -> list:
|
|||
value = custom_attributes_values[str(attr.id)]
|
||||
yield {"id": attr.id,
|
||||
"name": attr.name,
|
||||
"value": value}
|
||||
"value": value,
|
||||
"type": attr.type}
|
||||
|
||||
|
||||
@as_tuple
|
||||
|
@ -250,7 +253,8 @@ def extract_issue_custom_attributes(obj) -> list:
|
|||
value = custom_attributes_values[str(attr.id)]
|
||||
yield {"id": attr.id,
|
||||
"name": attr.name,
|
||||
"value": value}
|
||||
"value": value,
|
||||
"type": attr.type}
|
||||
|
||||
|
||||
def project_freezer(project) -> dict:
|
||||
|
|
|
@ -30,6 +30,7 @@ from .choices import HistoryType
|
|||
from .choices import HISTORY_TYPE_CHOICES
|
||||
|
||||
from taiga.base.utils.diff import make_diff as make_diff_from_dicts
|
||||
from taiga.projects.custom_attributes.choices import TEXT_TYPE
|
||||
|
||||
# This keys has been removed from freeze_impl so we can have objects where the
|
||||
# previous diff has value for the attribute and we want to prevent their propagation
|
||||
|
@ -250,15 +251,25 @@ class HistoryEntry(models.Model):
|
|||
changes = make_diff_from_dicts(oldcustattrs[aid], newcustattrs[aid],
|
||||
excluded_keys=("name"))
|
||||
|
||||
newcustattr = newcustattrs.get(aid, {})
|
||||
if changes:
|
||||
change_type = newcustattr.get("type", TEXT_TYPE)
|
||||
old_value = oldcustattrs[aid].get("value", "")
|
||||
new_value = newcustattrs[aid].get("value", "")
|
||||
value_diff = get_diff_of_htmls(old_value, new_value)
|
||||
change = {
|
||||
"name": newcustattrs.get(aid, {}).get("name", ""),
|
||||
"changes": changes
|
||||
"name": newcustattr.get("name", ""),
|
||||
"changes": changes,
|
||||
"type": change_type,
|
||||
"value_diff": value_diff
|
||||
}
|
||||
custom_attributes["changed"].append(change)
|
||||
elif aid in oldcustattrs and aid not in newcustattrs:
|
||||
custom_attributes["deleted"].append(oldcustattrs[aid])
|
||||
elif aid not in oldcustattrs and aid in newcustattrs:
|
||||
new_value = newcustattrs[aid].get("value", "")
|
||||
value_diff = get_diff_of_htmls("", new_value)
|
||||
newcustattrs[aid]["value_diff"] = value_diff
|
||||
custom_attributes["new"].append(newcustattrs[aid])
|
||||
|
||||
if custom_attributes["new"] or custom_attributes["changed"] or custom_attributes["deleted"]:
|
||||
|
|
|
@ -170,40 +170,58 @@
|
|||
{# CUSTOM ATTRIBUTES #}
|
||||
{% if values.new %}
|
||||
{% for attr in values['new']%}
|
||||
<tr>
|
||||
<td valign="middle" rowspan="2" class="update-row-name">
|
||||
<h3>{{ attr.name }}</h3>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<span>{{ _("to") }}</span><br>
|
||||
<strong>{{ attr.value|linebreaksbr }}</strong>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if values.changed %}
|
||||
{% for attr in values['changed'] %}
|
||||
{% if attr.changes.value%}
|
||||
{% if attr.type == "richtext" %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<h3>{{ attr.name }}</h3>
|
||||
<p>{{ mdrender(project, attr.value_diff) }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td valign="middle" rowspan="2" class="update-row-name">
|
||||
<h3>{{ attr.name }}</h3>
|
||||
</td>
|
||||
<td valign="top" class="update-row-from">
|
||||
<span>{{ _("from") }}</span><br>
|
||||
<strong>{{ attr.changes.value.0|linebreaksbr }}</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<span>{{ _("to") }}</span><br>
|
||||
<strong>{{ attr.changes.value.1|linebreaksbr }}</strong>
|
||||
<strong>{{ attr.value|linebreaksbr }}</strong>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if values.changed %}
|
||||
{% for attr in values['changed'] %}
|
||||
{% if attr.changes.value%}
|
||||
{% if attr.type == "richtext" %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<h3>{{ attr.name }}</h3>
|
||||
<p>{{ mdrender(project, attr.value_diff) }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td valign="middle" rowspan="2" class="update-row-name">
|
||||
<h3>{{ attr.name }}</h3>
|
||||
</td>
|
||||
<td valign="top" class="update-row-from">
|
||||
<span>{{ _("from") }}</span><br>
|
||||
<strong>{{ attr.changes.value.0|linebreaksbr }}</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<span>{{ _("to") }}</span><br>
|
||||
<strong>{{ attr.changes.value.1|linebreaksbr }}</strong>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if values.deleted %}
|
||||
{% for attr in values['deleted']%}
|
||||
<tr>
|
||||
|
|
|
@ -66,27 +66,27 @@
|
|||
|
||||
{% elif field_name == "custom_attributes" %}
|
||||
{# CUSTOM ATTRIBUTES #}
|
||||
{% elif field_name == "attachments" %}
|
||||
{% if values.new %}
|
||||
{% for attr in values['new']%}
|
||||
{% if values.new %}
|
||||
{% for attr in values['new']%}
|
||||
|
||||
- {{ attr.name }}:
|
||||
* {{ attr.value }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if values.changed %}
|
||||
{% for attr in values['changed'] %}
|
||||
{% if values.changed %}
|
||||
{% for attr in values['changed'] %}
|
||||
- {{ attr.name }}:
|
||||
* {{ _("From:") }} {{ attr.changes.value.0 }}
|
||||
* {{ _("To:") }} {{ attr.changes.value.1 }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if values.deleted %}
|
||||
{% for attr in values['deleted']%}
|
||||
{% if values.deleted %}
|
||||
{% for attr in values['deleted']%}
|
||||
- {{ attr.name }}: {{ _("-deleted-") }}
|
||||
* {{ attr.value }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
|
Loading…
Reference in New Issue