diff --git a/taiga/projects/custom_attributes/choices.py b/taiga/projects/custom_attributes/choices.py index a4cedf34..606b8c57 100644 --- a/taiga/projects/custom_attributes/choices.py +++ b/taiga/projects/custom_attributes/choices.py @@ -24,11 +24,17 @@ MULTILINE_TYPE = "multiline" RICHTEXT_TYPE = "richtext" DATE_TYPE = "date" URL_TYPE = "url" +DROPDOWN_TYPE = "dropdown" +CHECKBOX_TYPE = "checkbox" +NUMBER_TYPE = "number" TYPES_CHOICES = ( (TEXT_TYPE, _("Text")), (MULTILINE_TYPE, _("Multi-Line Text")), (RICHTEXT_TYPE, _("Rich text")), (DATE_TYPE, _("Date")), - (URL_TYPE, _("Url")) + (URL_TYPE, _("Url")), + (DROPDOWN_TYPE, _("Dropdown")), + (CHECKBOX_TYPE, _("Checkbox")), + (NUMBER_TYPE, _("Number")), ) diff --git a/taiga/projects/custom_attributes/migrations/0013_auto_20181022_1624.py b/taiga/projects/custom_attributes/migrations/0013_auto_20181022_1624.py new file mode 100644 index 00000000..bd90e4a7 --- /dev/null +++ b/taiga/projects/custom_attributes/migrations/0013_auto_20181022_1624.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.2 on 2018-10-22 16:24 +from __future__ import unicode_literals + +import django.core.serializers.json +from django.db import migrations, models +import taiga.base.db.models.fields.json + + +class Migration(migrations.Migration): + + dependencies = [ + ('custom_attributes', '0012_auto_20161201_1628'), + ] + + operations = [ + migrations.AddField( + model_name='epiccustomattribute', + name='extra', + field=taiga.base.db.models.fields.json.JSONField(blank=True, default=None, encoder=django.core.serializers.json.DjangoJSONEncoder, null=True), + ), + migrations.AddField( + model_name='issuecustomattribute', + name='extra', + field=taiga.base.db.models.fields.json.JSONField(blank=True, default=None, encoder=django.core.serializers.json.DjangoJSONEncoder, null=True), + ), + migrations.AddField( + model_name='taskcustomattribute', + name='extra', + field=taiga.base.db.models.fields.json.JSONField(blank=True, default=None, encoder=django.core.serializers.json.DjangoJSONEncoder, null=True), + ), + migrations.AddField( + model_name='userstorycustomattribute', + name='extra', + field=taiga.base.db.models.fields.json.JSONField(blank=True, default=None, encoder=django.core.serializers.json.DjangoJSONEncoder, null=True), + ), + migrations.AlterField( + model_name='epiccustomattribute', + name='type', + field=models.CharField(choices=[('text', 'Text'), ('multiline', 'Multi-Line Text'), ('richtext', 'Rich text'), ('date', 'Date'), ('url', 'Url'), ('dropdown', 'Dropdown')], default='text', max_length=16, verbose_name='type'), + ), + migrations.AlterField( + model_name='issuecustomattribute', + name='type', + field=models.CharField(choices=[('text', 'Text'), ('multiline', 'Multi-Line Text'), ('richtext', 'Rich text'), ('date', 'Date'), ('url', 'Url'), ('dropdown', 'Dropdown')], default='text', max_length=16, verbose_name='type'), + ), + migrations.AlterField( + model_name='taskcustomattribute', + name='type', + field=models.CharField(choices=[('text', 'Text'), ('multiline', 'Multi-Line Text'), ('richtext', 'Rich text'), ('date', 'Date'), ('url', 'Url'), ('dropdown', 'Dropdown')], default='text', max_length=16, verbose_name='type'), + ), + migrations.AlterField( + model_name='userstorycustomattribute', + name='type', + field=models.CharField(choices=[('text', 'Text'), ('multiline', 'Multi-Line Text'), ('richtext', 'Rich text'), ('date', 'Date'), ('url', 'Url'), ('dropdown', 'Dropdown')], default='text', max_length=16, verbose_name='type'), + ), + ] diff --git a/taiga/projects/custom_attributes/migrations/0014_auto_20181025_0711.py b/taiga/projects/custom_attributes/migrations/0014_auto_20181025_0711.py new file mode 100644 index 00000000..514fccd6 --- /dev/null +++ b/taiga/projects/custom_attributes/migrations/0014_auto_20181025_0711.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.2 on 2018-10-25 07:11 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('custom_attributes', '0013_auto_20181022_1624'), + ] + + operations = [ + migrations.AlterField( + model_name='epiccustomattribute', + name='type', + field=models.CharField(choices=[('text', 'Text'), ('multiline', 'Multi-Line Text'), ('richtext', 'Rich text'), ('date', 'Date'), ('url', 'Url'), ('dropdown', 'Dropdown'), ('checkbox', 'Checkbox'), ('number', 'Number')], default='text', max_length=16, verbose_name='type'), + ), + migrations.AlterField( + model_name='issuecustomattribute', + name='type', + field=models.CharField(choices=[('text', 'Text'), ('multiline', 'Multi-Line Text'), ('richtext', 'Rich text'), ('date', 'Date'), ('url', 'Url'), ('dropdown', 'Dropdown'), ('checkbox', 'Checkbox'), ('number', 'Number')], default='text', max_length=16, verbose_name='type'), + ), + migrations.AlterField( + model_name='taskcustomattribute', + name='type', + field=models.CharField(choices=[('text', 'Text'), ('multiline', 'Multi-Line Text'), ('richtext', 'Rich text'), ('date', 'Date'), ('url', 'Url'), ('dropdown', 'Dropdown'), ('checkbox', 'Checkbox'), ('number', 'Number')], default='text', max_length=16, verbose_name='type'), + ), + migrations.AlterField( + model_name='userstorycustomattribute', + name='type', + field=models.CharField(choices=[('text', 'Text'), ('multiline', 'Multi-Line Text'), ('richtext', 'Rich text'), ('date', 'Date'), ('url', 'Url'), ('dropdown', 'Dropdown'), ('checkbox', 'Checkbox'), ('number', 'Number')], default='text', max_length=16, verbose_name='type'), + ), + ] diff --git a/taiga/projects/custom_attributes/models.py b/taiga/projects/custom_attributes/models.py index d239e70d..42df12cd 100644 --- a/taiga/projects/custom_attributes/models.py +++ b/taiga/projects/custom_attributes/models.py @@ -41,7 +41,7 @@ class AbstractCustomAttribute(models.Model): order = models.BigIntegerField(null=False, blank=False, default=timestamp_ms, verbose_name=_("order")) project = models.ForeignKey("projects.Project", null=False, blank=False, related_name="%(class)ss", verbose_name=_("project")) - + extra = JSONField(blank=True, default=None, null=True) created_date = models.DateTimeField(null=False, blank=False, default=timezone.now, verbose_name=_("created date")) modified_date = models.DateTimeField(null=False, blank=False, diff --git a/taiga/projects/custom_attributes/serializers.py b/taiga/projects/custom_attributes/serializers.py index 8c6d3f06..60189fab 100644 --- a/taiga/projects/custom_attributes/serializers.py +++ b/taiga/projects/custom_attributes/serializers.py @@ -32,6 +32,7 @@ class BaseCustomAttributeSerializer(serializers.LightSerializer): type = Field() order = Field() project = Field(attr="project_id") + extra = Field() created_date = Field() modified_date = Field() diff --git a/taiga/projects/history/models.py b/taiga/projects/history/models.py index f2560a6a..5d67360f 100644 --- a/taiga/projects/history/models.py +++ b/taiga/projects/history/models.py @@ -30,7 +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 +from taiga.projects.custom_attributes.choices import CHECKBOX_TYPE, NUMBER_TYPE, 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 @@ -262,13 +262,19 @@ class HistoryEntry(models.Model): if aid in oldcustattrs and aid in newcustattrs: 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) + + if change_type in [NUMBER_TYPE, CHECKBOX_TYPE]: + old_value = oldcustattrs[aid].get("value") + new_value = newcustattrs[aid].get("value") + value_diff = [old_value, new_value] + else: + old_value = oldcustattrs[aid].get("value", "") + new_value = newcustattrs[aid].get("value", "") + value_diff = get_diff_of_htmls(old_value, + new_value) change = { "name": newcustattr.get("name", ""), "changes": changes, @@ -279,8 +285,15 @@ class HistoryEntry(models.Model): 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) + newcustattr = newcustattrs.get(aid, {}) + change_type = newcustattr.get("type", TEXT_TYPE) + if change_type in [NUMBER_TYPE, CHECKBOX_TYPE]: + old_value = None + new_value = newcustattrs[aid].get("value") + value_diff = [old_value, new_value] + else: + 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])