(core) Polish and enable Reference List widget

Summary:
Adds Reference List as a widget type.

Reference List is similar to Choice List: multiple references can be added
to each cell through a similar editor, and the individual references
will always reflect their current value from the referenced table.

Test Plan: Browser tests.

Reviewers: dsagal

Reviewed By: dsagal

Subscribers: paulfitz, jarek, alexmojaki, dsagal

Differential Revision: https://phab.getgrist.com/D2959
This commit is contained in:
George Gevoian
2021-08-12 11:06:40 -07:00
parent 34e9ad3498
commit 79f6f605f8
16 changed files with 594 additions and 93 deletions

View File

@@ -131,7 +131,7 @@ class ReferenceRelation(Relation):
self.inverse_map.setdefault(target_row_id, set()).add(referring_row_id)
def remove_reference(self, referring_row_id, target_row_id):
self.inverse_map[target_row_id].remove(referring_row_id)
self.inverse_map[target_row_id].discard(referring_row_id)
def clear(self):
self.inverse_map.clear()

View File

@@ -166,9 +166,15 @@ class Text(BaseColumnType):
@classmethod
def typeConvert(cls, value):
# When converting NULLs (that typically show up as a plain empty cell for Numeric or Date
# columns) to Text, it makes more sense to end up with a plain blank text cell.
return '' if value is None else value
if value is None:
# When converting NULLs (that typically show up as a plain empty cell for Numeric or Date
# columns) to Text, it makes more sense to end up with a plain blank text cell.
return ''
elif isinstance(value, bool):
# Normalize True/False to true/false (Toggle columns use true/false).
return str(value).lower()
else:
return value
class Blob(BaseColumnType):
@@ -350,6 +356,8 @@ class ChoiceList(BaseColumnType):
@classmethod
def typeConvert(cls, value):
if value is None:
return value
if isinstance(value, six.string_types) and not value.startswith('['):
# Try to parse as CSV. If this doesn't work, we'll still try usual conversions later.
try:
@@ -357,6 +365,8 @@ class ChoiceList(BaseColumnType):
return tuple(t.strip() for t in tags if t.strip())
except Exception:
pass
if not isinstance(value, (tuple, list)):
value = [Choice.typeConvert(value)]
return value
@classmethod
@@ -434,7 +444,7 @@ class Reference(Id):
@classmethod
def typeConvert(cls, value, ref_table, visible_col=None): # pylint: disable=arguments-differ
if ref_table and visible_col:
if value and ref_table and visible_col:
return ref_table.lookupOne(**{visible_col: value}) or six.text_type(value)
else:
return value
@@ -478,7 +488,7 @@ class ReferenceList(BaseColumnType):
def typeConvert(cls, value, ref_table, visible_col=None): # noqa # pylint: disable=arguments-differ
# TODO this is based on Reference.typeConvert.
# It doesn't make much sense as a conversion but I don't know what would
if ref_table and visible_col:
if value and ref_table and visible_col:
return ref_table.lookupRecords(**{visible_col: value}) or six.text_type(value)
else:
return value