1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-07 22:35:36 +00:00

Refactor number field

This commit is contained in:
Petr Stribny 2022-02-22 16:24:14 +00:00
parent 7f5dc1c390
commit 704ab3be2f
52 changed files with 256 additions and 382 deletions

View file

@ -1,4 +1,5 @@
from django.utils.functional import lazy
from django.core.exceptions import ValidationError
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
@ -168,3 +169,17 @@ class FileFieldResponseSerializer(
def get_instance_attr(self, instance, name):
return instance[name]
class MustBeEmptyField(serializers.Field):
def __init__(self, error_message, *args, **kwargs):
def validator(value):
raise ValidationError(error_message, code="invalid")
kwargs["write_only"] = True
kwargs["required"] = False
kwargs["validators"] = [validator]
super().__init__(*args, **kwargs)
def to_internal_value(self, data):
return None

View file

@ -18,21 +18,25 @@ def construct_all_possible_field_kwargs(
"url": [{"name": "url"}],
"email": [{"name": "email"}],
"number": [
{"name": "negative_int", "number_type": "INTEGER", "number_negative": True},
{
"name": "negative_int",
"number_negative": True,
"number_decimal_places": 0,
},
{
"name": "positive_int",
"number_type": "INTEGER",
"number_negative": False,
"number_decimal_places": 0,
},
{
"name": "negative_decimal",
"number_type": "DECIMAL",
"number_negative": "True",
"number_decimal_places": 1,
},
{
"name": "positive_decimal",
"number_type": "DECIMAL",
"number_negative": False,
"number_decimal_places": 1,
},
],
"rating": [

View file

@ -37,6 +37,7 @@ from baserow.contrib.database.api.fields.serializers import (
FileFieldRequestSerializer,
SelectOptionSerializer,
FileFieldResponseSerializer,
MustBeEmptyField,
)
from baserow.contrib.database.formula import (
BaserowExpression,
@ -82,8 +83,6 @@ from .fields import (
)
from .handler import FieldHandler
from .models import (
NUMBER_TYPE_INTEGER,
NUMBER_TYPE_DECIMAL,
TextField,
LongTextField,
URLField,
@ -315,8 +314,15 @@ class NumberFieldType(FieldType):
type = "number"
model_class = NumberField
allowed_fields = ["number_type", "number_decimal_places", "number_negative"]
serializer_field_names = ["number_type", "number_decimal_places", "number_negative"]
allowed_fields = ["number_decimal_places", "number_negative"]
serializer_field_names = ["number_decimal_places", "number_negative", "number_type"]
serializer_field_overrides = {
"number_type": MustBeEmptyField(
"The number_type option has been removed and can no longer be provided. "
"Instead set number_decimal_places to 0 for an integer or 1-5 for a "
"decimal."
)
}
def prepare_value_for_db(self, instance, value):
if value is not None:
@ -331,11 +337,7 @@ class NumberFieldType(FieldType):
def get_serializer_field(self, instance, **kwargs):
required = kwargs.get("required", False)
kwargs["decimal_places"] = (
0
if instance.number_type == NUMBER_TYPE_INTEGER
else instance.number_decimal_places
)
kwargs["decimal_places"] = instance.number_decimal_places
if not instance.number_negative:
kwargs["min_value"] = 0
@ -357,7 +359,7 @@ class NumberFieldType(FieldType):
# don't convert it to a string. However if a decimal to preserve any precision
# we keep it as a string.
instance = field_object["field"]
if instance.number_type == NUMBER_TYPE_INTEGER:
if instance.number_decimal_places == 0:
return int(value)
# DRF's Decimal Serializer knows how to quantize and format the decimal
@ -365,11 +367,7 @@ class NumberFieldType(FieldType):
return self.get_serializer_field(instance).to_representation(value)
def get_model_field(self, instance, **kwargs):
kwargs["decimal_places"] = (
0
if instance.number_type == NUMBER_TYPE_INTEGER
else instance.number_decimal_places
)
kwargs["decimal_places"] = instance.number_decimal_places
return models.DecimalField(
max_digits=self.MAX_DIGITS + kwargs["decimal_places"],
@ -379,13 +377,13 @@ class NumberFieldType(FieldType):
)
def random_value(self, instance, fake, cache):
if instance.number_type == NUMBER_TYPE_INTEGER:
if instance.number_decimal_places == 0:
return fake.pyint(
min_value=-10000 if instance.number_negative else 1,
max_value=10000,
step=1,
)
elif instance.number_type == NUMBER_TYPE_DECIMAL:
elif instance.number_decimal_places > 0:
return fake.pydecimal(
min_value=-10000 if instance.number_negative else 1,
max_value=10000,
@ -394,9 +392,7 @@ class NumberFieldType(FieldType):
def get_alter_column_prepare_new_value(self, connection, from_field, to_field):
if connection.vendor == "postgresql":
decimal_places = 0
if to_field.number_type == NUMBER_TYPE_DECIMAL:
decimal_places = to_field.number_decimal_places
decimal_places = to_field.number_decimal_places
function = f"round(p_in::numeric, {decimal_places})"
@ -420,21 +416,14 @@ class NumberFieldType(FieldType):
return value if value is None else str(value)
def to_baserow_formula_type(self, field: NumberField) -> BaserowFormulaType:
if field.number_type == NUMBER_TYPE_INTEGER:
number_decimal_places = 0
else:
number_decimal_places = field.number_decimal_places
return BaserowFormulaNumberType(number_decimal_places=number_decimal_places)
return BaserowFormulaNumberType(
number_decimal_places=field.number_decimal_places
)
def from_baserow_formula_type(
self, formula_type: BaserowFormulaNumberType
) -> NumberField:
if formula_type.number_decimal_places == 0:
number_type = NUMBER_TYPE_INTEGER
else:
number_type = NUMBER_TYPE_DECIMAL
return NumberField(
number_type=number_type,
number_decimal_places=formula_type.number_decimal_places,
number_negative=True,
)

View file

@ -2,7 +2,6 @@ from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils.functional import cached_property
from django.core.validators import MinValueValidator, MaxValueValidator
from baserow.contrib.database.fields.mixins import (
BaseDateMixin,
TimezoneMixin,
@ -26,16 +25,11 @@ from baserow.core.mixins import (
)
from baserow.core.utils import to_snake_case, remove_special_characters
NUMBER_TYPE_INTEGER = "INTEGER"
NUMBER_TYPE_DECIMAL = "DECIMAL"
NUMBER_TYPE_CHOICES = (
("INTEGER", "Integer"),
("DECIMAL", "Decimal"),
)
NUMBER_MAX_DECIMAL_PLACES = 5
NUMBER_DECIMAL_PLACES_CHOICES = [
(0, "1"),
(1, "1.0"),
(2, "1.00"),
(3, "1.000"),
@ -206,12 +200,9 @@ class URLField(Field):
class NumberField(Field):
number_type = models.CharField(
max_length=32, choices=NUMBER_TYPE_CHOICES, default=NUMBER_TYPE_INTEGER
)
number_decimal_places = models.IntegerField(
choices=NUMBER_DECIMAL_PLACES_CHOICES,
default=1,
default=0,
help_text="The amount of digits allowed after the point.",
)
number_negative = models.BooleanField(
@ -219,10 +210,8 @@ class NumberField(Field):
)
def save(self, *args, **kwargs):
"""Check if the number_type and number_decimal_places has a valid choice."""
"""Check if the number_decimal_places has a valid choice."""
if not any(self.number_type in _tuple for _tuple in NUMBER_TYPE_CHOICES):
raise ValueError(f"{self.number_type} is not a valid choice.")
if not any(
self.number_decimal_places in _tuple
for _tuple in NUMBER_DECIMAL_PLACES_CHOICES
@ -396,7 +385,7 @@ class FormulaField(Field):
null=True,
)
number_decimal_places = models.IntegerField(
choices=[(0, "1")] + NUMBER_DECIMAL_PLACES_CHOICES,
choices=NUMBER_DECIMAL_PLACES_CHOICES,
default=None,
null=True,
help_text="The amount of digits allowed after the point.",

View file

@ -1,7 +1,6 @@
# We need to change all NumberFields that are Integers to use DecimalField in Django
# and NUMERIC(50, 0) in Postgres. This migration converts all the existing Integer data
# types in fields to Decimal.
from baserow.contrib.database.fields.models import NUMBER_TYPE_INTEGER
from django.db import migrations, connection
from baserow.contrib.database.fields.models import Field as FieldModel
@ -25,7 +24,7 @@ def forward(apps, schema_editor):
# which could result in an out of memory exception.
tables_schema_editor.atomic.__exit__(None, None, None)
for field in NumberField.objects.filter(number_type=NUMBER_TYPE_INTEGER):
for field in NumberField.objects.filter(number_type="INTEGER"):
table_name = f"database_table_{field.table.id}"
column_name = FieldModel.db_column.__get__(field, FieldModel)
sql = alter_sql(tables_schema_editor, table_name, column_name)

View file

@ -0,0 +1,29 @@
# Generated by Django 3.2.6 on 2022-02-14 13:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("database", "0060_set_ordering_on_tablewebhook_models"),
]
operations = [
migrations.AlterField(
model_name="numberfield",
name="number_decimal_places",
field=models.IntegerField(
choices=[
(0, "1"),
(1, "1.0"),
(2, "1.00"),
(3, "1.000"),
(4, "1.0000"),
(5, "1.00000"),
],
default=0,
help_text="The amount of digits allowed after the point.",
),
),
]

View file

@ -0,0 +1,29 @@
from django.db import migrations
def forward(apps, schema_editor):
"""
If the NumberField.number_type was decimal we keep the decimal places
intact.
If the NumberField.number_type was integer we set the decimal places to
0 as the number field could have any number of decimal places set before.
"""
NumberField = apps.get_model("database", "NumberField")
NumberField.objects.filter(number_type="INTEGER").update(number_decimal_places=0)
def reverse(apps, schema_editor):
...
class Migration(migrations.Migration):
dependencies = [
("database", "0061_change_decimal_places"),
]
operations = [
migrations.RunPython(forward, reverse),
]

View file

@ -0,0 +1,17 @@
# Generated by Django 3.2.6 on 2022-02-14 13:28
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("database", "0062_migrate_number_type"),
]
operations = [
migrations.RemoveField(
model_name="numberfield",
name="number_type",
),
]

View file

@ -59,7 +59,6 @@ def setup_interesting_test_table(data_fixture, user_kwargs=None):
table=decimal_link_table,
name="text_field",
primary=True,
number_type="DECIMAL",
number_decimal_places=3,
number_negative=True,
)

View file

@ -71,8 +71,7 @@
"name": "Walkability",
"order": 6,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -81,8 +80,7 @@
"name": "Transit",
"order": 7,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -98,8 +96,7 @@
"name": "Built",
"order": 9,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -1044,8 +1041,7 @@
"name": "Bathrooms",
"order": 5,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -1054,8 +1050,7 @@
"name": "Bedrooms",
"order": 6,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -1064,8 +1059,7 @@
"name": "Rent",
"order": 7,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -1179,8 +1173,7 @@
"name": "Size (m\u00b2)",
"order": 14,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -2480,8 +2473,7 @@
"name": "Zip Code",
"order": 4,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{

View file

@ -64,8 +64,7 @@
"name": "Duration (minutes)",
"order": 3,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{

View file

@ -1310,8 +1310,7 @@
"name": "Channel Rating (1-5)",
"order": 4,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{

View file

@ -148,8 +148,7 @@
"name": "Pages",
"order": 10,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
}
],

View file

@ -86,8 +86,7 @@
"name": "Word Count",
"order": 11,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{

View file

@ -261,8 +261,7 @@
"name": "Duration (min)",
"order": 2,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -1327,8 +1326,7 @@
"name": "Years of experience",
"order": 5,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -1992,8 +1990,7 @@
"name": "Room capacity",
"order": 3,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
}
],

View file

@ -78,7 +78,6 @@
"name": "Total cost",
"order": 7,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -486,8 +485,7 @@
"name": "Avg duration (min)",
"order": 1,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -523,7 +521,6 @@
"name": "Avg cost",
"order": 3,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -1813,7 +1810,6 @@
"name": "Cost",
"order": 2,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},

View file

@ -63,8 +63,7 @@
"name": "Zip Code",
"order": 4,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -742,8 +741,7 @@
"name": "Floor",
"order": 2,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{

View file

@ -102,7 +102,6 @@
"name": "Cost",
"order": 5,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},

View file

@ -1503,8 +1503,7 @@
"name":"Value (1-10)",
"order":5,
"primary":false,
"number_type":"INTEGER",
"number_decimal_places":1,
"number_decimal_places": 0,
"number_negative":false
}
],

View file

@ -174,8 +174,7 @@
"name": "SSN/TIN",
"order": 24,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -4484,8 +4483,7 @@
"name": "Avg per Week",
"order": 5,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{

View file

@ -47,7 +47,6 @@
"name":"Price",
"order":2,
"primary":false,
"number_type":"DECIMAL",
"number_decimal_places":2,
"number_negative":false
},

View file

@ -131,8 +131,7 @@
"name": "Quantity",
"order": 6,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -188,8 +187,7 @@
"name": "Price",
"order": 9,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -1056,8 +1054,7 @@
"name": "Age",
"order": 5,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -1464,8 +1461,7 @@
"name": "Coverage",
"order": 8,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
}
],

View file

@ -69,8 +69,7 @@
"name": "Asking price",
"order": 5,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -79,8 +78,7 @@
"name": "# of Bedrooms",
"order": 6,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -89,7 +87,6 @@
"name": "# of Bathrooms",
"order": 7,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 1,
"number_negative": false
},
@ -161,8 +158,7 @@
"name": "Size",
"order": 14,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -171,7 +167,6 @@
"name": "HOA fee",
"order": 15,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -195,7 +190,6 @@
"name": "Interest (%)",
"order": 17,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -205,7 +199,6 @@
"name": "Property taxes",
"order": 18,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -215,7 +208,6 @@
"name": "Insurance",
"order": 19,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -2862,8 +2854,7 @@
"name": "Noise level (1-10)",
"order": 4,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -2924,7 +2915,6 @@
"name": "Public transport (km)",
"order": 7,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 1,
"number_negative": false
},
@ -2934,7 +2924,6 @@
"name": "Highway (km)",
"order": 9,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 1,
"number_negative": false
},

View file

@ -124,8 +124,7 @@
"name": "Salary",
"order": 6,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{

View file

@ -692,7 +692,6 @@
"name": "Contract Value",
"order": 5,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},

View file

@ -49,8 +49,7 @@
"name": "Resting HR",
"order": 5,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -99,8 +98,7 @@
"name": "Weight (kg)",
"order": 8,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -109,7 +107,6 @@
"name": "Hours of Sleep",
"order": 9,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 1,
"number_negative": false
},
@ -1204,8 +1201,7 @@
"name": "Calories",
"order": 2,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -1777,8 +1773,7 @@
"name": "Difficulty (1-10)",
"order": 4,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{

View file

@ -94,8 +94,7 @@
"name": "Lifetime",
"order": 8,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -120,8 +119,7 @@
"name": "Zip Code",
"order": 11,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -1016,8 +1014,7 @@
"name": "Amount",
"order": 4,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{

View file

@ -622,7 +622,6 @@
"name": "Est. Days",
"order": 4,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 1,
"number_negative": false
},

View file

@ -106,8 +106,7 @@
"name": "Cook Time (min)",
"order": 9,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -116,8 +115,7 @@
"name": "Prep Time (min)",
"order": 10,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{

View file

@ -107,7 +107,6 @@
"name": "Hourly rate",
"order": 9,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -1780,7 +1779,6 @@
"name": "In stock",
"order": 5,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 1,
"number_negative": false
},
@ -1790,7 +1788,6 @@
"name": "Ideal quantity",
"order": 6,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 1,
"number_negative": false
},
@ -2702,7 +2699,6 @@
"name": "Cost to make",
"order": 3,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -3443,7 +3439,6 @@
"name": "Price",
"order": 2,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -4015,7 +4010,6 @@
"name": "Shift duration",
"order": 5,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 1,
"number_negative": false
}

View file

@ -461,7 +461,6 @@
"name": "Duration",
"order": 7,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -503,7 +502,6 @@
"name": "Cost",
"order": 13,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -1388,7 +1386,6 @@
"name": "Cost",
"order": 4,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -1927,7 +1924,6 @@
"name": "Cost",
"order": 5,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -3130,7 +3126,6 @@
"name": "Cost",
"order": 5,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -3731,7 +3726,6 @@
"name": "Cost",
"order": 2,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},
@ -3741,7 +3735,6 @@
"name": "Budget",
"order": 3,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},

View file

@ -998,8 +998,7 @@
"name": "Est time (min)",
"order": 6,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -1829,7 +1828,6 @@
"name": "Price",
"order": 8,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
}
@ -2338,8 +2336,7 @@
"name": "Time to read (min)",
"order": 4,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
}
],
@ -2656,7 +2653,6 @@
"name": "Admission",
"order": 3,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
},

View file

@ -72,8 +72,7 @@
"name": "Capacity",
"order": 6,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -82,8 +81,7 @@
"name": "Rental Cost",
"order": 7,
"primary": false,
"number_type": "INTEGER",
"number_decimal_places": 2,
"number_decimal_places": 0,
"number_negative": false
},
{
@ -1328,7 +1326,6 @@
"name": "Cost",
"order": 6,
"primary": false,
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": false
}

View file

@ -51,7 +51,6 @@ def test_list_fields(api_client, data_fixture):
assert response_json[1]["id"] == field_3.id
assert response_json[1]["type"] == "number"
assert not response_json[1]["primary"]
assert response_json[1]["number_type"] == field_3.number_type
assert response_json[1]["number_decimal_places"] == field_3.number_decimal_places
assert response_json[1]["number_negative"] == field_3.number_negative
@ -390,15 +389,13 @@ def test_update_field(api_client, data_fixture):
assert response.status_code == HTTP_200_OK
assert response_json["name"] == "Test 1"
assert response_json["type"] == "number"
assert response_json["number_type"] == "INTEGER"
assert response_json["number_decimal_places"] == 1
assert response_json["number_decimal_places"] == 0
assert response_json["number_negative"]
url = reverse("api:database:fields:item", kwargs={"field_id": text.id})
response = api_client.patch(
url,
{
"number_type": "DECIMAL",
"number_decimal_places": 2,
"number_negative": False,
},
@ -409,7 +406,6 @@ def test_update_field(api_client, data_fixture):
assert response.status_code == HTTP_200_OK
assert response_json["name"] == "Test 1"
assert response_json["type"] == "number"
assert response_json["number_type"] == "DECIMAL"
assert response_json["number_decimal_places"] == 2
assert not response_json["number_negative"]
@ -424,7 +420,6 @@ def test_update_field(api_client, data_fixture):
assert response.status_code == HTTP_200_OK
assert response_json["name"] == "Test 2"
assert response_json["type"] == "boolean"
assert "number_type" not in response_json
assert "number_decimal_places" not in response_json
assert "number_negative" not in response_json
@ -457,6 +452,31 @@ def test_update_field(api_client, data_fixture):
assert response.json()["error"] == "ERROR_REQUEST_BODY_VALIDATION"
@pytest.mark.django_db
def test_update_field_number_type_deprecation_error(api_client, data_fixture):
user, token = data_fixture.create_user_and_token()
table = data_fixture.create_database_table(user=user)
number_field = data_fixture.create_number_field(
table=table, number_decimal_places=1
)
url = reverse("api:database:fields:item", kwargs={"field_id": number_field.id})
response = api_client.patch(
url,
{"number_type": "INTEGER"},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
assert response.status_code == HTTP_400_BAD_REQUEST
assert response.json()["error"] == "ERROR_REQUEST_BODY_VALIDATION"
assert response.json()["detail"]["number_type"][0]["error"] == (
"The number_type option has been removed and can no longer be provided. "
"Instead set number_decimal_places to 0 for an integer or 1-5 for a "
"decimal."
)
@pytest.mark.django_db
def test_delete_field(api_client, data_fixture):
user, token = data_fixture.create_user_and_token()

View file

@ -633,7 +633,7 @@ def test_number_field_type(api_client, data_fixture):
{
"name": "PositiveInt",
"type": "number",
"number_type": "INTEGER",
"number_decimal_places": 0,
"number_negative": False,
},
format="json",
@ -653,7 +653,7 @@ def test_number_field_type(api_client, data_fixture):
{
"name": "NegativeInt",
"type": "number",
"number_type": "INTEGER",
"number_decimal_places": 0,
"number_negative": True,
},
format="json",
@ -673,7 +673,6 @@ def test_number_field_type(api_client, data_fixture):
{
"name": "PositiveDecimal",
"type": "number",
"number_type": "DECIMAL",
"number_negative": False,
"number_decimal_places": 2,
},
@ -694,7 +693,6 @@ def test_number_field_type(api_client, data_fixture):
{
"name": "NegativeDecimal",
"type": "number",
"number_type": "DECIMAL",
"number_negative": True,
"number_decimal_places": 2,
},

View file

@ -19,7 +19,7 @@ def test_altering_value_of_referenced_field(
table = data_fixture.create_database_table(user=user)
response = api_client.post(
reverse("api:database:fields:list", kwargs={"table_id": table.id}),
{"name": "number", "type": "number", "number_type": "INTEGER"},
{"name": "number", "type": "number", "number_decimal_places": 0},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
@ -702,7 +702,6 @@ def test_altering_type_of_underlying_causes_type_update(api_client, data_fixture
{
"name": "text",
"type": "number",
"number_type": "DECIMAL",
"number_decimal_places": 2,
},
format="json",
@ -897,7 +896,7 @@ def test_can_type_an_invalid_formula_field(
table = data_fixture.create_database_table(user=user)
response = api_client.post(
reverse("api:database:fields:list", kwargs={"table_id": table.id}),
{"name": "number", "type": "number", "number_type": "INTEGER"},
{"name": "number", "type": "number", "number_decimal_places": 0},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
@ -935,7 +934,7 @@ def test_can_type_a_valid_formula_field(
table = data_fixture.create_database_table(user=user)
response = api_client.post(
reverse("api:database:fields:list", kwargs={"table_id": table.id}),
{"name": "number", "type": "number", "number_type": "INTEGER"},
{"name": "number", "type": "number", "number_decimal_places": 0},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
@ -981,7 +980,7 @@ def test_type_endpoint_returns_error_for_bad_syntax(
table = data_fixture.create_database_table(user=user)
response = api_client.post(
reverse("api:database:fields:list", kwargs={"table_id": table.id}),
{"name": "number", "type": "number", "number_type": "INTEGER"},
{"name": "number", "type": "number", "number_decimal_places": 0},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
@ -1018,7 +1017,7 @@ def test_type_endpoint_returns_error_for_missing_parameters(
table = data_fixture.create_database_table(user=user)
response = api_client.post(
reverse("api:database:fields:list", kwargs={"table_id": table.id}),
{"name": "number", "type": "number", "number_type": "INTEGER"},
{"name": "number", "type": "number", "number_decimal_places": 0},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
@ -1055,7 +1054,7 @@ def test_type_endpoint_returns_error_for_missing_field(
table = data_fixture.create_database_table(user=user)
response = api_client.post(
reverse("api:database:fields:list", kwargs={"table_id": table.id}),
{"name": "number", "type": "number", "number_type": "INTEGER"},
{"name": "number", "type": "number", "number_decimal_places": 0},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
@ -1080,7 +1079,7 @@ def test_type_endpoint_returns_error_for_non_formula_field(
table = data_fixture.create_database_table(user=user)
response = api_client.post(
reverse("api:database:fields:list", kwargs={"table_id": table.id}),
{"name": "number", "type": "number", "number_type": "INTEGER"},
{"name": "number", "type": "number", "number_decimal_places": 0},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
@ -1164,7 +1163,7 @@ def test_type_endpoint_returns_error_if_not_permissioned_for_field(
table = data_fixture.create_database_table(user=user)
response = api_client.post(
reverse("api:database:fields:list", kwargs={"table_id": table.id}),
{"name": "number", "type": "number", "number_type": "INTEGER"},
{"name": "number", "type": "number", "number_decimal_places": 0},
format="json",
HTTP_AUTHORIZATION=f"JWT {token}",
)
@ -1249,7 +1248,6 @@ def test_altering_type_of_underlying_causes_type_update_nested(
{
"name": "text",
"type": "number",
"number_type": "DECIMAL",
"number_decimal_places": 2,
},
format="json",

View file

@ -25,7 +25,6 @@ def test_get_table_serializer(data_fixture):
table=table,
order=4,
name="Price",
number_type="DECIMAL",
number_negative=True,
number_decimal_places=2,
)
@ -148,7 +147,6 @@ def test_get_table_serializer(data_fixture):
table=table,
order=0,
name="Sale price",
number_type="DECIMAL",
number_decimal_places=3,
number_negative=True,
)

View file

@ -11,7 +11,6 @@ from rest_framework.status import (
from baserow.contrib.database.fields.handler import FieldHandler
from baserow.contrib.database.fields.registries import field_type_registry
from baserow.contrib.database.fields.models import NUMBER_TYPE_DECIMAL
from baserow.contrib.database.rows.handler import RowHandler
from baserow.contrib.database.table.cache import (
invalidate_table_model_cache_and_related_models,
@ -653,7 +652,7 @@ def test_create_row_with_blank_decimal_field(api_client, data_fixture):
user, jwt_token = data_fixture.create_user_and_token()
table = data_fixture.create_database_table(user=user)
decimal_field = data_fixture.create_number_field(
table=table, order=1, name="TestDecimal", number_type=NUMBER_TYPE_DECIMAL
table=table, order=1, name="TestDecimal", number_decimal_places=1
)
response = api_client.post(
@ -981,7 +980,6 @@ def test_update_row(api_client, data_fixture):
table=table_3,
order=0,
name="Price",
number_type="DECIMAL",
number_decimal_places=2,
)
model_3 = table_3.get_model()

View file

@ -280,8 +280,7 @@ def test_meta_submit_form_view(api_client, data_fixture):
"field": {
"id": number_field.id,
"type": "number",
"number_type": "INTEGER",
"number_decimal_places": 1,
"number_decimal_places": 0,
"number_negative": False,
},
}

View file

@ -710,7 +710,6 @@ def setup_testing_table(data_fixture):
price_field = data_fixture.create_number_field(
table=table,
name="Price",
number_type="DECIMAL",
number_decimal_places=2,
number_negative=True,
order=4,

View file

@ -207,17 +207,7 @@ def test_create_field(send_mock, data_fixture):
user=user,
table=table,
type_name="number",
name="Test number field",
number_type="NOT_EXISTING",
)
with pytest.raises(ValueError):
handler.create_field(
user=user,
table=table,
type_name="number",
name="Test number field",
number_type="DECIMAL",
name="Test decimal with oversized decimal places value",
number_decimal_places=9999,
)
@ -226,8 +216,7 @@ def test_create_field(send_mock, data_fixture):
table=table,
type_name="number",
name="Test number field",
number_type="INTEGER",
number_decimal_places=2,
number_decimal_places=0,
number_negative=True,
)
@ -235,8 +224,7 @@ def test_create_field(send_mock, data_fixture):
assert number_field.name == "Test number field"
assert number_field.order == 2
assert number_field.table == table
assert number_field.number_type == "INTEGER"
assert number_field.number_decimal_places == 2
assert number_field.number_decimal_places == 0
assert number_field.number_negative
handler.create_field(
@ -395,12 +383,12 @@ def test_update_field(send_mock, data_fixture):
field=field,
new_type_name="number",
name="Number field",
number_type="INTEGER",
number_decimal_places=0,
number_negative=False,
)
assert field.name == "Number field"
assert field.number_type == "INTEGER"
assert field.number_decimal_places == 0
assert field.number_negative is False
assert not hasattr(field, "text_default")
@ -416,13 +404,11 @@ def test_update_field(send_mock, data_fixture):
field=field,
new_type_name="number",
name="Price field",
number_type="DECIMAL",
number_decimal_places=2,
number_negative=True,
)
assert field.name == "Price field"
assert field.number_type == "DECIMAL"
assert field.number_decimal_places == 2
assert field.number_negative is True
@ -439,7 +425,6 @@ def test_update_field(send_mock, data_fixture):
field.refresh_from_db()
assert field.name == "Active"
assert not hasattr(field, "number_type")
assert not hasattr(field, "number_decimal_places")
assert not hasattr(field, "number_negative")
@ -1077,7 +1062,7 @@ def test_can_convert_formula_to_numeric_field(data_fixture):
field=existing_formula_field,
new_type_name="number",
name="Price field",
number_type="INTEGER",
number_decimal_places=0,
number_negative=True,
)

View file

@ -5,7 +5,7 @@ from decimal import Decimal
from django.contrib.contenttypes.models import ContentType
from baserow.contrib.database.fields.handler import FieldHandler
from baserow.contrib.database.fields.models import NumberField, NUMBER_TYPE_DECIMAL
from baserow.contrib.database.fields.models import NumberField
from baserow.contrib.database.fields.registries import field_type_registry
@ -29,7 +29,7 @@ from baserow.contrib.database.fields.registries import field_type_registry
None,
None,
],
{"number_type": "INTEGER", "number_negative": False},
{"number_decimal_places": 0, "number_negative": False},
),
(
[
@ -47,7 +47,7 @@ from baserow.contrib.database.fields.registries import field_type_registry
None,
None,
],
{"number_type": "INTEGER", "number_negative": True},
{"number_decimal_places": 0, "number_negative": True},
),
(
[
@ -66,7 +66,6 @@ from baserow.contrib.database.fields.registries import field_type_registry
None,
],
{
"number_type": "DECIMAL",
"number_negative": False,
"number_decimal_places": 1,
},
@ -88,7 +87,6 @@ from baserow.contrib.database.fields.registries import field_type_registry
None,
],
{
"number_type": "DECIMAL",
"number_negative": True,
"number_decimal_places": 3,
},
@ -139,7 +137,6 @@ def test_alter_number_field_column_type_negative(data_fixture):
decimal_field = data_fixture.create_number_field(
table=table,
order=2,
number_type="DECIMAL",
number_negative=True,
number_decimal_places=2,
)
@ -170,7 +167,6 @@ def test_alter_number_field_column_type_negative(data_fixture):
def test_import_export_number_field(data_fixture):
number_field = data_fixture.create_number_field(
name="Number field",
number_type="DECIMAL",
number_negative=True,
number_decimal_places=2,
)
@ -179,7 +175,6 @@ def test_import_export_number_field(data_fixture):
number_field_imported = number_field_type.import_serialized(
number_field.table, number_serialized, {}
)
assert number_field.number_type == number_field_imported.number_type
assert number_field.number_negative == number_field_imported.number_negative
assert number_field.number_decimal_places == (
number_field_imported.number_decimal_places
@ -192,7 +187,6 @@ def test_content_type_still_set_when_save_overridden(data_fixture):
field = NumberField(
number_negative=False,
number_decimal_places=1,
number_type=NUMBER_TYPE_DECIMAL,
order=1,
table=table,
)

View file

@ -137,14 +137,14 @@ def test_rating_field_modification(data_fixture):
integer_field = data_fixture.create_number_field(
table=table,
name="integer",
number_type="INTEGER",
number_decimal_places=0,
number_negative=True,
)
decimal_field = data_fixture.create_number_field(
table=table,
name="decimal",
number_type="DECIMAL",
number_decimal_places=1,
number_negative=True,
)
@ -267,14 +267,13 @@ def test_rating_field_modification(data_fixture):
user=user,
field=integer_field,
new_type_name="number",
number_type="INTEGER",
number_decimal_places=0,
number_negative=True,
)
field_handler.update_field(
user=user,
field=decimal_field,
new_type_name="number",
number_type="DECIMAL",
number_negative=True,
number_decimal_places=2,
)

View file

@ -121,7 +121,6 @@ def test_create_row(send_mock, data_fixture):
price_field = data_fixture.create_number_field(
table=table,
name="Price",
number_type="DECIMAL",
number_decimal_places=2,
number_negative=False,
)
@ -258,7 +257,6 @@ def test_get_row(data_fixture):
price_field = data_fixture.create_number_field(
table=table,
name="Price",
number_type="DECIMAL",
number_decimal_places=2,
number_negative=False,
)
@ -303,7 +301,6 @@ def test_update_row(send_mock, data_fixture):
price_field = data_fixture.create_number_field(
table=table,
name="Price",
number_type="DECIMAL",
number_decimal_places=2,
number_negative=False,
)
@ -465,7 +462,6 @@ def test_restore_row(send_mock, data_fixture):
price_field = data_fixture.create_number_field(
table=table,
name="Price",
number_type="DECIMAL",
number_decimal_places=2,
number_negative=False,
)
@ -565,7 +561,6 @@ def test_has_row(data_fixture):
price_field = data_fixture.create_number_field(
table=table,
name="Price",
number_type="DECIMAL",
number_decimal_places=2,
number_negative=False,
)

View file

@ -75,7 +75,6 @@ def test_get_table_model(data_fixture):
table=table_2,
order=0,
name="Sale price",
number_type="DECIMAL",
number_decimal_places=3,
number_negative=True,
)

View file

@ -68,7 +68,7 @@ def test_equal_filter_type(data_fixture):
long_text_field = data_fixture.create_long_text_field(table=table)
integer_field = data_fixture.create_number_field(table=table)
decimal_field = data_fixture.create_number_field(
table=table, number_type="DECIMAL", number_decimal_places=2
table=table, number_decimal_places=2
)
boolean_field = data_fixture.create_boolean_field(table=table)
formula_field = data_fixture.create_formula_field(table=table, formula="'test'")
@ -204,7 +204,7 @@ def test_not_equal_filter_type(data_fixture):
long_text_field = data_fixture.create_long_text_field(table=table)
integer_field = data_fixture.create_number_field(table=table)
decimal_field = data_fixture.create_number_field(
table=table, number_type="DECIMAL", number_decimal_places=2
table=table, number_decimal_places=2
)
boolean_field = data_fixture.create_boolean_field(table=table)
formula_field = data_fixture.create_formula_field(table=table, formula="'test'")
@ -347,7 +347,6 @@ def test_contains_filter_type(data_fixture):
)
number_field = data_fixture.create_number_field(
table=table,
number_type="DECIMAL",
number_negative=True,
number_decimal_places=2,
)
@ -567,7 +566,6 @@ def test_contains_not_filter_type(data_fixture):
)
number_field = data_fixture.create_number_field(
table=table,
number_type="DECIMAL",
number_negative=True,
number_decimal_places=2,
)
@ -967,7 +965,6 @@ def test_higher_than_filter_type(data_fixture):
integer_field = data_fixture.create_number_field(table=table, number_negative=True)
decimal_field = data_fixture.create_number_field(
table=table,
number_type="DECIMAL",
number_decimal_places=2,
number_negative=True,
)
@ -1118,7 +1115,6 @@ def test_lower_than_filter_type(data_fixture):
integer_field = data_fixture.create_number_field(table=table, number_negative=True)
decimal_field = data_fixture.create_number_field(
table=table,
number_type="DECIMAL",
number_decimal_places=2,
number_negative=True,
)
@ -2214,7 +2210,7 @@ def test_empty_filter_type(data_fixture):
long_text_field = data_fixture.create_long_text_field(table=table)
integer_field = data_fixture.create_number_field(table=table)
decimal_field = data_fixture.create_number_field(
table=table, number_type="DECIMAL", number_decimal_places=2
table=table, number_decimal_places=2
)
date_field = data_fixture.create_date_field(table=table)
date_time_field = data_fixture.create_date_field(
@ -2369,7 +2365,7 @@ def test_not_empty_filter_type(data_fixture):
long_text_field = data_fixture.create_long_text_field(table=table)
integer_field = data_fixture.create_number_field(table=table)
decimal_field = data_fixture.create_number_field(
table=table, number_type="DECIMAL", number_decimal_places=2
table=table, number_decimal_places=2
)
date_field = data_fixture.create_date_field(table=table)
date_time_field = data_fixture.create_date_field(

View file

@ -16,6 +16,9 @@
tools, e.g. to various REST clients.
* Added search to gallery views.
* Views supporting search are properly updated when a column with a matching default value is added.
* **breaking change** Number field has been changed and doesn't use `number_type` property
anymore. The property `number_decimal_places` can be now set to `0` to indicate integers
instead.
## Released (2022-01-13 1.8.2)

View file

@ -1,87 +0,0 @@
<template>
<div>
<div class="control">
<label class="control__label control__label--small">{{
$t('fieldFormulaNumberSubForm.typeLabel')
}}</label>
<div class="control__elements">
<Dropdown
:class="{ 'dropdown--error': $v.numberType.$error }"
:value="numberType"
@input="changeNumberType($event)"
@hide="$v.numberType.$touch()"
>
<DropdownItem
:name="$t('fieldFormulaNumberSubForm.integer') + ' (1)'"
value="INTEGER"
></DropdownItem>
<DropdownItem
:name="$t('fieldFormulaNumberSubForm.decimal') + ' (1.0)'"
value="DECIMAL"
></DropdownItem>
</Dropdown>
</div>
</div>
<div v-show="numberType === 'DECIMAL'" class="control">
<label class="control__label control__label--small">{{
$t('fieldFormulaNumberSubForm.decimalPlacesLabel')
}}</label>
<div class="control__elements">
<Dropdown
v-model="values.number_decimal_places"
:class="{ 'dropdown--error': $v.values.number_decimal_places.$error }"
@hide="$v.values.number_decimal_places.$touch()"
>
<DropdownItem name="1.0" :value="1"></DropdownItem>
<DropdownItem name="1.00" :value="2"></DropdownItem>
<DropdownItem name="1.000" :value="3"></DropdownItem>
<DropdownItem name="1.0000" :value="4"></DropdownItem>
<DropdownItem name="1.00000" :value="5"></DropdownItem>
</Dropdown>
</div>
</div>
</div>
</template>
<script>
import { required } from 'vuelidate/lib/validators'
import form from '@baserow/modules/core/mixins/form'
import fieldSubForm from '@baserow/modules/database/mixins/fieldSubForm'
export default {
name: 'FieldNumberSubForm',
mixins: [form, fieldSubForm],
data() {
return {
allowedValues: ['number_decimal_places'],
values: {
number_decimal_places: 0,
},
}
},
computed: {
numberType() {
return this.values.number_decimal_places === 0 ? 'INTEGER' : 'DECIMAL'
},
},
methods: {
changeNumberType(newValue) {
if (newValue === 'INTEGER') {
this.values.number_decimal_places = 0
} else {
this.values.number_decimal_places = 1
}
},
},
validations: {
values: {
number_decimal_places: { required },
},
numberType: {
required,
},
},
}
</script>

View file

@ -1,27 +1,6 @@
<template>
<div>
<div class="control">
<label class="control__label control__label--small">{{
$t('fieldNumberSubForm.typeLabel')
}}</label>
<div class="control__elements">
<Dropdown
v-model="values.number_type"
:class="{ 'dropdown--error': $v.values.number_type.$error }"
@hide="$v.values.number_type.$touch()"
>
<DropdownItem
:name="$t('fieldNumberSubForm.integer') + ' (1)'"
value="INTEGER"
></DropdownItem>
<DropdownItem
:name="$t('fieldNumberSubForm.decimal') + ' (1.0)'"
value="DECIMAL"
></DropdownItem>
</Dropdown>
</div>
</div>
<div v-show="values.number_type === 'DECIMAL'" class="control">
<label class="control__label control__label--small">{{
$t('fieldNumberSubForm.decimalPlacesLabel')
}}</label>
@ -31,15 +10,16 @@
:class="{ 'dropdown--error': $v.values.number_decimal_places.$error }"
@hide="$v.values.number_decimal_places.$touch()"
>
<DropdownItem name="1.0" :value="1"></DropdownItem>
<DropdownItem name="1.00" :value="2"></DropdownItem>
<DropdownItem name="1.000" :value="3"></DropdownItem>
<DropdownItem name="1.0000" :value="4"></DropdownItem>
<DropdownItem name="1.00000" :value="5"></DropdownItem>
<DropdownItem name="0 (1)" :value="0"></DropdownItem>
<DropdownItem name="1 (1.0)" :value="1"></DropdownItem>
<DropdownItem name="2 (1.00)" :value="2"></DropdownItem>
<DropdownItem name="3 (1.000)" :value="3"></DropdownItem>
<DropdownItem name="4 (1.0000)" :value="4"></DropdownItem>
<DropdownItem name="5 (1.00000)" :value="5"></DropdownItem>
</Dropdown>
</div>
</div>
<div class="control">
<div v-if="allowSetNumberNegative" class="control">
<div class="control__elements">
<Checkbox v-model="values.number_negative">{{
$t('fieldNumberSubForm.allowNegative')
@ -58,23 +38,29 @@ import fieldSubForm from '@baserow/modules/database/mixins/fieldSubForm'
export default {
name: 'FieldNumberSubForm',
mixins: [form, fieldSubForm],
props: {
allowSetNumberNegative: {
type: Boolean,
required: false,
default: true,
},
},
data() {
let allowedValues = ['number_decimal_places']
let values = { number_decimal_places: 0 }
if (this.allowSetNumberNegative) {
allowedValues = [...allowedValues, 'number_negative']
values = { ...values, number_negative: false }
}
return {
allowedValues: [
'number_type',
'number_decimal_places',
'number_negative',
],
values: {
number_type: 'INTEGER',
number_decimal_places: 1,
number_negative: false,
},
allowedValues,
values,
}
},
validations: {
values: {
number_type: { required },
number_decimal_places: { required },
},
},

View file

@ -1,11 +1,12 @@
<template>
<div>
<FieldFormulaNumberSubForm
<FieldNumberSubForm
v-if="formulaType === 'number'"
:default-values="defaultValues"
:table="table"
:allow-set-number-negative="false"
>
</FieldFormulaNumberSubForm>
</FieldNumberSubForm>
<FieldDateSubForm
v-else-if="['date', 'last_modified', 'created_on'].includes(formulaType)"
:default-values="defaultValues"
@ -15,14 +16,14 @@
</div>
</template>
<script>
import FieldFormulaNumberSubForm from '@baserow/modules/database/components/field/FieldFormulaNumberSubForm'
import FieldNumberSubForm from '@baserow/modules/database/components/field/FieldNumberSubForm'
import FieldDateSubForm from '@baserow/modules/database/components/field/FieldDateSubForm'
import form from '@baserow/modules/core/mixins/form'
import fieldSubForm from '@baserow/modules/database/mixins/fieldSubForm'
export default {
name: 'FormulaTypeSubForms',
components: { FieldFormulaNumberSubForm, FieldDateSubForm },
components: { FieldNumberSubForm, FieldDateSubForm },
mixins: [form, fieldSubForm],
props: {
table: {

View file

@ -865,21 +865,19 @@ export class NumberFieldType extends FieldType {
if (value === '' || isNaN(value) || value === undefined || value === null) {
return null
}
const decimalPlaces =
field.number_type === 'DECIMAL' ? field.number_decimal_places : 0
let number = new BigNumber(value)
if (!field.number_negative && number.isLessThan(0)) {
number = 0
}
return number.toFixed(decimalPlaces)
return number.toFixed(field.number_decimal_places)
}
getDocsDataType(field) {
return field.number_type === 'DECIMAL' ? 'decimal' : 'number'
return field.number_decimal_places > 0 ? 'decimal' : 'number'
}
getDocsDescription(field) {
let t = field.number_type === 'INTEGER' ? 'number' : 'decimal'
let t = field.number_decimal_places === 0 ? 'number' : 'decimal'
if (!field.number_negative) {
t += 'Positive'
}
@ -889,7 +887,7 @@ export class NumberFieldType extends FieldType {
}
getDocsRequestExample(field) {
if (field.number_type === 'DECIMAL') {
if (field.number_decimal_places > 0) {
let number = '0.'
for (let i = 1; i <= field.number_decimal_places; i++) {
number += '0'

View file

@ -35,9 +35,8 @@ const mockedFields = {
primary: false,
table_id: 42,
type: 'number',
number_decimal_places: 1,
number_decimal_places: 0,
number_negative: false,
number_type: 'INTEGER',
},
rating: {
id: 16,