(core) Show summary tables on Raw Data page

Summary:
Summary tables now have their own raw viewsection, and are shown
under Raw Data Tables on the Raw Data page.

Test Plan: Browser and Python tests.

Reviewers: jarek

Reviewed By: jarek

Differential Revision: https://phab.getgrist.com/D3495
This commit is contained in:
George Gevoian
2022-07-06 00:41:09 -07:00
parent 8bab8c18fa
commit a051830aeb
31 changed files with 452 additions and 308 deletions

View File

@@ -73,8 +73,13 @@ class MetaTableExtras(object):
if rec.summarySourceTable else None)
def setAutoRemove(rec, table):
"""Marks the table for removal if it's a summary table with no more view sections."""
table.docmodel.setAutoRemove(rec, rec.summarySourceTable and not rec.viewSections)
"""
Marks the table for removal if it's a summary table with no more (non-raw) view sections.
"""
is_summary_table = rec.summarySourceTable
view_sections_table = table.docmodel.get_table('_grist_Views_section')
has_view_sections = view_sections_table.lookupOne(isRaw=False, tableRef=rec.id)
table.docmodel.setAutoRemove(rec, is_summary_table and not has_view_sections)
class _grist_Tables_column(object):

View File

@@ -960,3 +960,57 @@ def migration29(tdset):
}))
return tdset.apply_doc_actions(doc_actions)
@migration(schema_version=30)
def migration30(tdset):
"""
Add raw view sections for each summary table. This is similar to migration 26, but for
summary tables instead of user tables.
"""
doc_actions = []
tables = list(actions.transpose_bulk_action(tdset.all_tables["_grist_Tables"]))
columns = list(actions.transpose_bulk_action(tdset.all_tables["_grist_Tables_column"]))
new_view_section_id = next_id(tdset, "_grist_Views_section")
for table in sorted(tables, key=lambda t: t.tableId):
if not table.summarySourceTable:
continue
table_columns = [
col for col in columns
if table.id == col.parentId and is_visible_column(col.colId)
]
table_columns.sort(key=lambda c: c.parentPos)
fields = {
"parentId": [new_view_section_id] * len(table_columns),
"colRef": [col.id for col in table_columns],
"parentPos": [col.parentPos for col in table_columns],
}
field_ids = [None] * len(table_columns)
doc_actions += [
actions.AddRecord(
"_grist_Views_section", new_view_section_id, {
"tableRef": table.id,
"parentId": 0,
"parentKey": "record",
"title": "",
"defaultWidth": 100,
"borderWidth": 1,
}
),
actions.UpdateRecord(
"_grist_Tables", table.id, {
"rawViewSectionRef": new_view_section_id,
})
,
actions.BulkAddRecord(
"_grist_Views_section_field", field_ids, fields
),
]
new_view_section_id += 1
return tdset.apply_doc_actions(doc_actions)

View File

@@ -15,7 +15,7 @@ import six
import actions
SCHEMA_VERSION = 29
SCHEMA_VERSION = 30
def make_column(col_id, col_type, formula='', isFormula=False):
return {

View File

@@ -205,7 +205,8 @@ class SummaryActions(object):
result = self.useractions.doAddTable(
encode_summary_table_name(source_table.tableId),
[_get_colinfo_dict(ci, with_id=True) for ci in groupby_colinfo + formula_colinfo],
summarySourceTableRef=source_table.id)
summarySourceTableRef=source_table.id,
raw_section=True)
summary_table = self.docmodel.tables.table.get_record(result['id'])
created = True
# Note that in this case, _get_or_add_columns() below should not add any new columns,

View File

@@ -228,10 +228,10 @@ class TestColumnActions(test_engine.EngineTestCase):
Field(11, colRef=16),
Field(12, colRef=17),
]),
Section(5, parentKey="record", tableRef=3, fields=[
Field(13, colRef=18),
Field(14, colRef=20),
Field(15, colRef=21),
Section(6, parentKey="record", tableRef=3, fields=[
Field(16, colRef=18),
Field(17, colRef=20),
Field(18, colRef=21),
]),
]),
View(2, sections=[
@@ -315,10 +315,10 @@ class TestColumnActions(test_engine.EngineTestCase):
Field(10, colRef=15),
Field(12, colRef=17),
]),
Section(5, parentKey="record", tableRef=3, fields=[
Field(13, colRef=18),
Field(14, colRef=20),
Field(15, colRef=21),
Section(6, parentKey="record", tableRef=3, fields=[
Field(16, colRef=18),
Field(17, colRef=20),
Field(18, colRef=21),
]),
]),
View(2, sections=[
@@ -372,9 +372,9 @@ class TestColumnActions(test_engine.EngineTestCase):
Field(10, colRef=15),
Field(12, colRef=17),
]),
Section(5, parentKey="record", tableRef=4, fields=[
Field(14, colRef=23),
Field(15, colRef=24),
Section(6, parentKey="record", tableRef=4, fields=[
Field(17, colRef=23),
Field(18, colRef=24),
]),
]),
View(2, sections=[

View File

@@ -126,9 +126,9 @@ class TestSummary(test_engine.EngineTestCase):
formula="SUM($group.amount)"),
])
summary_view1 = View(2, sections=[
Section(2, parentKey="record", tableRef=2, fields=[
Field(4, colRef=15),
Field(5, colRef=16),
Section(3, parentKey="record", tableRef=2, fields=[
Field(6, colRef=15),
Field(7, colRef=16),
])
])
self.assertTables([self.starting_table, summary_table1])
@@ -156,10 +156,10 @@ class TestSummary(test_engine.EngineTestCase):
formula="SUM($group.amount)"),
])
summary_view2 = View(3, sections=[
Section(3, parentKey="record", tableRef=3, fields=[
Field(6, colRef=17),
Field(7, colRef=19),
Field(8, colRef=20),
Section(5, parentKey="record", tableRef=3, fields=[
Field(11, colRef=17),
Field(12, colRef=19),
Field(13, colRef=20),
])
])
self.assertTables([self.starting_table, summary_table1, summary_table2])
@@ -197,11 +197,11 @@ class TestSummary(test_engine.EngineTestCase):
formula="SUM($group.amount)"),
])
summary_view3 = View(4, sections=[
Section(4, parentKey="record", tableRef=4, fields=[
Field(9, colRef=21),
Field(10, colRef=22),
Field(11, colRef=24),
Field(12, colRef=25),
Section(7, parentKey="record", tableRef=4, fields=[
Field(18, colRef=21),
Field(19, colRef=22),
Field(20, colRef=24),
Field(21, colRef=25),
])
])
self.assertTables([self.starting_table, summary_table1, summary_table2, summary_table3])
@@ -281,11 +281,11 @@ class Address:
formula="SUM($group.amount)"),
])
summary_view = View(1, sections=[
Section(1, parentKey="record", tableRef=2, fields=[
Field(1, colRef=14),
Field(2, colRef=15),
Field(3, colRef=17),
Field(4, colRef=18),
Section(2, parentKey="record", tableRef=2, fields=[
Field(5, colRef=14),
Field(6, colRef=15),
Field(7, colRef=17),
Field(8, colRef=18),
])
])
self.assertTables([self.starting_table, summary_table])
@@ -296,19 +296,19 @@ class Address:
self.apply_user_action(["CreateViewSection", 1, 0, "record", [12,11], None])
self.apply_user_action(["CreateViewSection", 1, 0, "record", [11,12], None])
summary_view2 = View(2, sections=[
Section(2, parentKey="record", tableRef=2, fields=[
Field(5, colRef=15),
Field(6, colRef=14),
Field(7, colRef=17),
Field(8, colRef=18),
Section(3, parentKey="record", tableRef=2, fields=[
Field(9, colRef=15),
Field(10, colRef=14),
Field(11, colRef=17),
Field(12, colRef=18),
])
])
summary_view3 = View(3, sections=[
Section(3, parentKey="record", tableRef=2, fields=[
Field(9, colRef=14),
Field(10, colRef=15),
Field(11, colRef=17),
Field(12, colRef=18),
Section(4, parentKey="record", tableRef=2, fields=[
Field(13, colRef=14),
Field(14, colRef=15),
Field(15, colRef=17),
Field(16, colRef=18),
])
])
# Verify that we have a new view, but are reusing the table.

View File

@@ -83,11 +83,13 @@ class TestSummary2(test_engine.EngineTestCase):
])
# We should now have two sections for table 2 (the one with two group-by fields).
# We should now have three sections for table 2 (the one with two group-by fields). One for
# the raw summary table view, and two for the non-raw views.
self.assertTableData('_grist_Views_section', cols="subset", data=[
["id", "parentId", "tableRef"],
[1, 1, 2],
[5, 5, 2],
[1, 0, 2],
[2, 1, 2],
[9, 5, 2],
], rows=lambda r: r.tableRef.id == 2)
self.assertTableData('_grist_Views_section_field', cols="subset", data=[
["id", "parentId", "colRef"],
@@ -95,11 +97,11 @@ class TestSummary2(test_engine.EngineTestCase):
[2, 1, 15],
[3, 1, 17],
[4, 1, 18],
[8, 1, 23],
[16, 5, 14],
[17, 5, 15],
[18, 5, 17],
[19, 5, 18], # new section doesn't automatically get 'average' column
[15, 1, 23],
[17, 5, 24],
[18, 5, 26],
[19, 5, 27],
[20, 5, 28], # new section doesn't automatically get 'average' column
], rows=lambda r: r.parentId.id in {1,5})
@@ -433,11 +435,11 @@ class TestSummary2(test_engine.EngineTestCase):
]),
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=2, fields=[
Field(1, colRef=14),
Field(2, colRef=15),
Field(3, colRef=17),
Field(4, colRef=18),
Section(2, parentKey="record", tableRef=2, fields=[
Field(5, colRef=14),
Field(6, colRef=15),
Field(7, colRef=17),
Field(8, colRef=18),
])
])])
self.assertEqual(get_helper_cols('Address'), ['#summary#GristSummary_7_Address'])
@@ -451,7 +453,7 @@ class TestSummary2(test_engine.EngineTestCase):
])
# Now change the group-by to just one of the columns ('state')
self.apply_user_action(["UpdateSummaryViewSection", 1, [12]])
self.apply_user_action(["UpdateSummaryViewSection", 2, [12]])
self.assertTables([
self.starting_table,
# Note that Table #2 is gone at this point, since it's unused.
@@ -463,10 +465,10 @@ class TestSummary2(test_engine.EngineTestCase):
]),
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=3, fields=[
Field(2, colRef=19),
Field(3, colRef=21),
Field(4, colRef=22),
Section(2, parentKey="record", tableRef=3, fields=[
Field(6, colRef=19),
Field(7, colRef=21),
Field(8, colRef=22),
])
])])
self.assertTableData('GristSummary_7_Address2', cols="subset", data=[
@@ -486,7 +488,7 @@ class TestSummary2(test_engine.EngineTestCase):
])
# Change group-by to a different single column ('city')
self.apply_user_action(["UpdateSummaryViewSection", 1, [11]])
self.apply_user_action(["UpdateSummaryViewSection", 2, [11]])
self.assertTables([
self.starting_table,
# Note that Table #3 is gone at this point, since it's unused.
@@ -498,10 +500,10 @@ class TestSummary2(test_engine.EngineTestCase):
]),
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=4, fields=[
Field(5, colRef=23),
Field(3, colRef=25),
Field(4, colRef=26),
Section(2, parentKey="record", tableRef=4, fields=[
Field(15, colRef=23),
Field(7, colRef=25),
Field(8, colRef=26),
])
])])
self.assertTableData('GristSummary_7_Address', cols="subset", data=[
@@ -525,7 +527,7 @@ class TestSummary2(test_engine.EngineTestCase):
])
# Change group-by to no columns (totals)
self.apply_user_action(["UpdateSummaryViewSection", 1, []])
self.apply_user_action(["UpdateSummaryViewSection", 2, []])
self.assertTables([
self.starting_table,
# Note that Table #4 is gone at this point, since it's unused.
@@ -536,9 +538,9 @@ class TestSummary2(test_engine.EngineTestCase):
]),
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=5, fields=[
Field(3, colRef=28),
Field(4, colRef=29),
Section(2, parentKey="record", tableRef=5, fields=[
Field(7, colRef=28),
Field(8, colRef=29),
])
])])
self.assertTableData('GristSummary_7_Address2', cols="subset", data=[
@@ -548,7 +550,7 @@ class TestSummary2(test_engine.EngineTestCase):
self.assertEqual(get_helper_cols('Address'), ['#summary#GristSummary_7_Address2'])
# Back to full circle, but with group-by columns differently arranged.
self.apply_user_action(["UpdateSummaryViewSection", 1, [12,11]])
self.apply_user_action(["UpdateSummaryViewSection", 2, [12,11]])
self.assertTables([
self.starting_table,
# Note that Table #5 is gone at this point, since it's unused.
@@ -561,11 +563,11 @@ class TestSummary2(test_engine.EngineTestCase):
]),
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=6, fields=[
Field(5, colRef=30),
Field(6, colRef=31),
Field(3, colRef=33),
Field(4, colRef=34),
Section(2, parentKey="record", tableRef=6, fields=[
Field(22, colRef=30),
Field(23, colRef=31),
Field(7, colRef=33),
Field(8, colRef=34),
])
])])
self.assertTableData('GristSummary_7_Address', cols="subset", data=[
@@ -595,23 +597,23 @@ class TestSummary2(test_engine.EngineTestCase):
]),
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=6, fields=[
Field(5, colRef=30),
Field(6, colRef=31),
Field(3, colRef=33),
Field(4, colRef=34),
]),
Section(2, parentKey="record", tableRef=6, fields=[
Field(7, colRef=31),
Field(8, colRef=30),
Field(9, colRef=33),
Field(10, colRef=34),
Field(22, colRef=30),
Field(23, colRef=31),
Field(7, colRef=33),
Field(8, colRef=34),
]),
Section(7, parentKey="record", tableRef=6, fields=[
Field(24, colRef=31),
Field(25, colRef=30),
Field(26, colRef=33),
Field(27, colRef=34),
])
])])
self.assertEqual(get_helper_cols('Address'), ['#summary#GristSummary_7_Address'])
# Change one view section, and ensure there are now two summary tables.
self.apply_user_action(["UpdateSummaryViewSection", 2, []])
self.apply_user_action(["UpdateSummaryViewSection", 7, []])
self.assertTables([
self.starting_table,
Table(6, "GristSummary_7_Address", 0, 1, columns=[
@@ -628,22 +630,22 @@ class TestSummary2(test_engine.EngineTestCase):
]),
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=6, fields=[
Field(5, colRef=30),
Field(6, colRef=31),
Field(3, colRef=33),
Field(4, colRef=34),
Section(2, parentKey="record", tableRef=6, fields=[
Field(22, colRef=30),
Field(23, colRef=31),
Field(7, colRef=33),
Field(8, colRef=34),
]),
Section(2, parentKey="record", tableRef=7, fields=[
Field(9, colRef=36),
Field(10, colRef=37),
Section(7, parentKey="record", tableRef=7, fields=[
Field(26, colRef=36),
Field(27, colRef=37),
])
])])
self.assertEqual(get_helper_cols('Address'), ['#summary#GristSummary_7_Address',
'#summary#GristSummary_7_Address2'])
# Delete one view section, and see that the summary table is gone.
self.apply_user_action(["RemoveViewSection", 2])
self.apply_user_action(["RemoveViewSection", 7])
self.assertTables([
self.starting_table,
# Note that Table #7 is gone at this point, since it's now unused.
@@ -656,18 +658,18 @@ class TestSummary2(test_engine.EngineTestCase):
])
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=6, fields=[
Field(5, colRef=30),
Field(6, colRef=31),
Field(3, colRef=33),
Field(4, colRef=34),
Section(2, parentKey="record", tableRef=6, fields=[
Field(22, colRef=30),
Field(23, colRef=31),
Field(7, colRef=33),
Field(8, colRef=34),
])
])])
self.assertEqual(get_helper_cols('Address'), ['#summary#GristSummary_7_Address'])
# Change the section to add and then remove the "amount" to the group-by column; check that
# column "amount" was correctly restored
self.apply_user_action(["UpdateSummaryViewSection", 1, [11, 12, 13]])
self.apply_user_action(["UpdateSummaryViewSection", 2, [11, 12, 13]])
self.assertTables([
self.starting_table,
Table(7, "GristSummary_7_Address2", 0, 1, columns=[
@@ -679,14 +681,14 @@ class TestSummary2(test_engine.EngineTestCase):
]),
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=7, fields=[
Field(6, colRef=35),
Field(5, colRef=36),
Field(7, colRef=37),
Field(3, colRef=39),
Section(2, parentKey="record", tableRef=7, fields=[
Field(23, colRef=35),
Field(22, colRef=36),
Field(28, colRef=37),
Field(7, colRef=39),
])
])])
self.apply_user_action(["UpdateSummaryViewSection", 1, [11,12]])
self.apply_user_action(["UpdateSummaryViewSection", 2, [11,12]])
self.assertTables([
self.starting_table,
Table(8, "GristSummary_7_Address", 0, 1, columns=[
@@ -699,18 +701,18 @@ class TestSummary2(test_engine.EngineTestCase):
]),
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=8, fields=[
Field(6, colRef=40),
Field(5, colRef=41),
Field(7, colRef=42),
Field(3, colRef=44),
Section(2, parentKey="record", tableRef=8, fields=[
Field(23, colRef=40),
Field(22, colRef=41),
Field(28, colRef=42),
Field(7, colRef=44),
])
])])
# Hide a formula and update group by columns; check that the formula columns had not been
# deleted
self.apply_user_action(['RemoveRecord', '_grist_Views_section_field', 7])
self.apply_user_action(["UpdateSummaryViewSection", 1, [11]])
self.apply_user_action(["UpdateSummaryViewSection", 2, [11]])
self.assertTables([
self.starting_table,
Table(9, "GristSummary_7_Address2", 0, 1, columns=[
@@ -721,9 +723,9 @@ class TestSummary2(test_engine.EngineTestCase):
]),
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=9, fields=[
Field(6, colRef=45),
Field(3, colRef=48),
Section(2, parentKey="record", tableRef=9, fields=[
Field(23, colRef=45),
Field(28, colRef=46),
])
])])
@@ -754,11 +756,11 @@ class TestSummary2(test_engine.EngineTestCase):
]),
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=2, fields=[
Field(1, colRef=14),
Field(2, colRef=16),
Field(3, colRef=17),
Field(4, colRef=18),
Section(2, parentKey="record", tableRef=2, fields=[
Field(4, colRef=14),
Field(5, colRef=16),
Field(6, colRef=17),
Field(8, colRef=18),
])
])])
self.assertTableData('GristSummary_7_Address', cols="subset", data=[
@@ -770,7 +772,7 @@ class TestSummary2(test_engine.EngineTestCase):
])
# Change the section to add "city" as a group-by column; check that the formula is gone.
self.apply_user_action(["UpdateSummaryViewSection", 1, [11,12]])
self.apply_user_action(["UpdateSummaryViewSection", 2, [11,12]])
self.assertTables([
self.starting_table,
Table(3, "GristSummary_7_Address2", 0, 1, columns=[
@@ -782,12 +784,12 @@ class TestSummary2(test_engine.EngineTestCase):
]),
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=3, fields=[
Section(2, parentKey="record", tableRef=3, fields=[
# We requested 'city' to come before 'state', check that this is the case.
Field(4, colRef=19),
Field(1, colRef=20),
Field(2, colRef=22),
Field(3, colRef=23),
Field(13, colRef=19),
Field(4, colRef=20),
Field(5, colRef=22),
Field(6, colRef=23),
])
])])
@@ -830,27 +832,27 @@ class TestSummary2(test_engine.EngineTestCase):
]),
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=2, fields=[
Field(1, colRef=14),
Field(2, colRef=15),
Field(3, colRef=17),
Field(4, colRef=18),
Section(2, parentKey="record", tableRef=2, fields=[
Field(5, colRef=14),
Field(6, colRef=15),
Field(7, colRef=17),
Field(8, colRef=18),
])
]), View(2, sections=[
Section(2, parentKey="record", tableRef=3, fields=[
Field(5, colRef=20),
Field(6, colRef=21),
Section(4, parentKey="record", tableRef=3, fields=[
Field(11, colRef=20),
Field(12, colRef=21),
]),
Section(3, parentKey="record", tableRef=2, fields=[
Field(7, colRef=14),
Field(8, colRef=15),
Field(9, colRef=17),
Field(10, colRef=18),
Section(5, parentKey="record", tableRef=2, fields=[
Field(13, colRef=14),
Field(14, colRef=15),
Field(15, colRef=17),
Field(16, colRef=18),
]),
Section(4, parentKey="record", tableRef=4, fields=[
Field(11, colRef=22),
Field(12, colRef=24),
Field(13, colRef=25),
Section(7, parentKey="record", tableRef=4, fields=[
Field(20, colRef=22),
Field(21, colRef=24),
Field(22, colRef=25),
])
])])
@@ -869,11 +871,11 @@ class TestSummary2(test_engine.EngineTestCase):
]),
])
self.assertViews([View(1, sections=[
Section(1, parentKey="record", tableRef=2, fields=[
Field(1, colRef=14),
Field(2, colRef=15),
Field(3, colRef=17),
Field(4, colRef=18),
Section(2, parentKey="record", tableRef=2, fields=[
Field(5, colRef=14),
Field(6, colRef=15),
Field(7, colRef=17),
Field(8, colRef=18),
])
])])
@@ -885,10 +887,10 @@ class TestSummary2(test_engine.EngineTestCase):
self.load_sample(self.sample)
self.apply_user_action(["CreateViewSection", 1, 0, "record", [11,12], None])
self.apply_user_action(["UpdateRecord", "_grist_Views_section", 1,
self.apply_user_action(["UpdateRecord", "_grist_Views_section", 2,
{"sortColRefs": "[15,14,-17]"}])
# We should have a single summary table, and a single section referring to it.
# We should have a single summary table, and a single (non-raw) section referring to it.
self.assertTables([
self.starting_table,
Table(2, "GristSummary_7_Address", 0, 1, columns=[
@@ -901,11 +903,12 @@ class TestSummary2(test_engine.EngineTestCase):
])
self.assertTableData('_grist_Views_section', cols="subset", data=[
["id", "tableRef", "sortColRefs"],
[1, 2, "[15,14,-17]"],
[1, 2, ""], # This is the raw section.
[2, 2, "[15,14,-17]"],
])
# Now change the group-by to just one of the columns ('state')
self.apply_user_action(["UpdateSummaryViewSection", 1, [12]])
self.apply_user_action(["UpdateSummaryViewSection", 2, [12]])
self.assertTables([
self.starting_table,
# Note that Table #2 is gone at this point, since it's unused.
@@ -919,7 +922,8 @@ class TestSummary2(test_engine.EngineTestCase):
# Verify that sortColRefs refers to new columns.
self.assertTableData('_grist_Views_section', cols="subset", data=[
["id", "tableRef", "sortColRefs"],
[1, 3, "[19,-21]"],
[2, 3, "[19,-21]"],
[3, 3, ""], # This is the raw section.
])
#----------------------------------------------------------------------
@@ -953,8 +957,10 @@ class TestSummary2(test_engine.EngineTestCase):
])
self.assertTableData('_grist_Views_section', cols="subset", data=[
["id", "parentId", "tableRef"],
[1, 1, 2],
[2, 2, 3],
[1, 0, 2],
[2, 1, 2],
[3, 0, 3],
[4, 2, 3],
])
self.assertTableData('_grist_Views_section_field', cols="subset", data=[
["id", "parentId", "colRef"],
@@ -962,13 +968,20 @@ class TestSummary2(test_engine.EngineTestCase):
[2, 1, 15],
[3, 1, 17],
[4, 1, 18],
[7, 1, 22],
[5, 2, 20],
[6, 2, 21],
[13, 1, 22],
[5, 2, 14],
[6, 2, 15],
[7, 2, 17],
[8, 2, 18],
[14, 2, 22],
[9, 3, 20],
[10, 3, 21],
[11, 4, 20],
[12, 4, 21],
], sort=lambda r: (r.parentId, r.id))
# Now save one section as a separate table, i.e. "detach" it from its source.
self.apply_user_action(["DetachSummaryViewSection", 1])
self.apply_user_action(["DetachSummaryViewSection", 2])
# Check the table and columns for all the summary tables.
self.assertTables([
@@ -992,25 +1005,25 @@ class TestSummary2(test_engine.EngineTestCase):
# We should now have two sections for table 2 (the one with two group-by fields).
self.assertTableData('_grist_Views_section', cols="subset", rows=lambda r: r.parentId, data=[
["id", "parentId", "tableRef"],
[1, 1, 4],
[2, 2, 3],
[3, 3, 4],
[2, 1, 4],
[4, 2, 3],
[5, 3, 4],
])
self.assertTableData(
'_grist_Views_section_field', cols="subset", rows=lambda r: r.parentId.parentId, data=[
["id", "parentId", "colRef"],
[1, 1, 24],
[2, 1, 25],
[3, 1, 26],
[4, 1, 27],
[7, 1, 28],
[5, 2, 20],
[6, 2, 21],
[8, 3, 24],
[9, 3, 25],
[10, 3, 26],
[11, 3, 27],
[12, 3, 28],
[5, 2, 24],
[6, 2, 25],
[7, 2, 26],
[8, 2, 27],
[14, 2, 28],
[11, 4, 20],
[12, 4, 21],
[15, 5, 24],
[16, 5, 25],
[17, 5, 26],
[18, 5, 27],
[19, 5, 28],
], sort=lambda r: (r.parentId, r.id))
# Check that the data is as we expect.
@@ -1039,7 +1052,7 @@ class TestSummary2(test_engine.EngineTestCase):
# Add a summary table and detach it. Then add a summary table of that table.
self.load_sample(self.sample)
self.apply_user_action(["CreateViewSection", 1, 0, "record", [11,12], None])
self.apply_user_action(["DetachSummaryViewSection", 1])
self.apply_user_action(["DetachSummaryViewSection", 2])
# Create a summary of the detached table (tableRef 3) by state (colRef 21).
self.apply_user_action(["CreateViewSection", 3, 0, "record", [21], None])

View File

@@ -310,7 +310,7 @@ class TestSummaryChoiceList(EngineTestCase):
self.assertTableData('GristSummary_6_Source2', data=summary_data)
# Verify that "DetachSummaryViewSection" useraction works correctly.
self.apply_user_action(["DetachSummaryViewSection", 2])
self.apply_user_action(["DetachSummaryViewSection", 4])
self.assertTables([
self.starting_table, summary_table1, summary_table3, summary_table4,

View File

@@ -100,15 +100,15 @@ class TestTableActions(test_engine.EngineTestCase):
Field(14, colRef=3),
Field(15, colRef=4),
]),
Section(6, parentKey="record", tableRef=3, fields=[
Field(16, colRef=9),
Field(17, colRef=11),
Field(18, colRef=12),
Section(7, parentKey="record", tableRef=3, fields=[
Field(19, colRef=9),
Field(20, colRef=11),
Field(21, colRef=12),
]),
Section(7, parentKey="record", tableRef=2, fields=[
Field(19, colRef=6),
Field(20, colRef=7),
Field(21, colRef=8),
Section(8, parentKey="record", tableRef=2, fields=[
Field(22, colRef=6),
Field(23, colRef=7),
Field(24, colRef=8),
]),
]),
])
@@ -300,9 +300,9 @@ class TestTableActions(test_engine.EngineTestCase):
]),
]),
View(3, sections=[
Section(7, parentKey="record", tableRef=2, fields=[
Field(19, colRef=6),
Field(21, colRef=8),
Section(8, parentKey="record", tableRef=2, fields=[
Field(22, colRef=6),
Field(24, colRef=8),
]),
]),
])

View File

@@ -172,9 +172,9 @@ class TestUserActions(test_engine.EngineTestCase):
Section(2, parentKey="record", tableRef=1, fields=[
Field(2, colRef=21),
]),
Section(3, parentKey="record", tableRef=2, fields=[
Field(3, colRef=22),
Field(4, colRef=24),
Section(4, parentKey="record", tableRef=2, fields=[
Field(5, colRef=22),
Field(6, colRef=24),
]),
])
self.assertTables([self.starting_table, summary_table])
@@ -255,8 +255,8 @@ class TestUserActions(test_engine.EngineTestCase):
Column(35, "count", "Int", isFormula=True, formula="len($group)", summarySourceCol=0),
])
self.assertTables([self.starting_table, new_table, new_table2, new_table3, summary_table])
new_view.sections.append(Section(6, parentKey="record", tableRef=5, fields=[
Field(16, colRef=35)
new_view.sections.append(Section(7, parentKey="record", tableRef=5, fields=[
Field(17, colRef=35)
]))
self.assertViews([new_view])
@@ -315,21 +315,21 @@ class TestUserActions(test_engine.EngineTestCase):
Field(8, colRef=3),
Field(9, colRef=4),
]),
Section(4, parentKey="record", tableRef=2, fields=[
Field(10, colRef=5),
Field(11, colRef=7),
Field(12, colRef=8),
Section(5, parentKey="record", tableRef=2, fields=[
Field(13, colRef=5),
Field(14, colRef=7),
Field(15, colRef=8),
]),
Section(7, parentKey='record', tableRef=3, fields=[
Field(18, colRef=10),
Field(19, colRef=11),
Field(20, colRef=12),
Section(8, parentKey='record', tableRef=3, fields=[
Field(21, colRef=10),
Field(22, colRef=11),
Field(23, colRef=12),
]),
]),
View(3, sections=[
Section(5, parentKey="chart", tableRef=1, fields=[
Field(13, colRef=2),
Field(14, colRef=3),
Section(6, parentKey="chart", tableRef=1, fields=[
Field(16, colRef=2),
Field(17, colRef=3),
]),
])
])
@@ -469,8 +469,8 @@ class TestUserActions(test_engine.EngineTestCase):
self.assertTableData('_grist_Tables', cols="subset", data=[
['id', 'tableId', 'primaryViewId', 'rawViewSectionRef'],
[1, 'Z', 1, 2],
[2, 'GristSummary_1_Z', 0, 0],
[3, 'Table1', 0, 6],
[2, 'GristSummary_1_Z', 0, 4],
[3, 'Table1', 0, 7],
])
self.assertTableData('_grist_Views', cols="subset", data=[
['id', 'name'],
@@ -486,9 +486,9 @@ class TestUserActions(test_engine.EngineTestCase):
self.assertTableData('_grist_Tables', cols="subset", data=[
['id', 'tableId', 'primaryViewId', 'rawViewSectionRef'],
[1, 'Z', 1, 2],
[2, 'GristSummary_1_Z', 0, 0],
[3, 'Table1', 0, 6],
[4, 'Stations', 4, 9],
[2, 'GristSummary_1_Z', 0, 4],
[3, 'Table1', 0, 7],
[4, 'Stations', 4, 10],
])
self.assertTableData('_grist_Views', cols="subset", data=[
['id', 'name'],
@@ -546,27 +546,27 @@ class TestUserActions(test_engine.EngineTestCase):
Field(8, colRef=3),
Field(9, colRef=4),
]),
Section(4, parentKey="record", tableRef=2, fields=[
Field(10, colRef=5),
Field(11, colRef=7),
Field(12, colRef=8),
Section(5, parentKey="record", tableRef=2, fields=[
Field(13, colRef=5),
Field(14, colRef=7),
Field(15, colRef=8),
]),
Section(7, parentKey='record', tableRef=3, fields=[
Field(18, colRef=10),
Field(19, colRef=11),
Field(20, colRef=12),
Section(8, parentKey='record', tableRef=3, fields=[
Field(21, colRef=10),
Field(22, colRef=11),
Field(23, colRef=12),
]),
]),
View(3, sections=[
Section(5, parentKey="chart", tableRef=1, fields=[
Field(13, colRef=2),
Field(14, colRef=3),
Section(6, parentKey="chart", tableRef=1, fields=[
Field(16, colRef=2),
Field(17, colRef=3),
]),
])
])
# Remove a couple of sections. Ensure their fields get removed.
self.apply_user_action(['BulkRemoveRecord', '_grist_Views_section', [4, 7]])
self.apply_user_action(['BulkRemoveRecord', '_grist_Views_section', [5, 8]])
self.assertViews([
View(1, sections=[
@@ -584,9 +584,9 @@ class TestUserActions(test_engine.EngineTestCase):
])
]),
View(3, sections=[
Section(5, parentKey="chart", tableRef=1, fields=[
Field(13, colRef=2),
Field(14, colRef=3),
Section(6, parentKey="chart", tableRef=1, fields=[
Field(16, colRef=2),
Field(17, colRef=3),
]),
])
])
@@ -607,13 +607,13 @@ class TestUserActions(test_engine.EngineTestCase):
orig_method()
self.engine.assert_schema_consistent = types.MethodType(override, self.engine)
# Do a non-sschema action to ensure it doesn't get called.
# Do a non-schema action to ensure it doesn't get called.
self.apply_user_action(['UpdateRecord', '_grist_Views', 2, {'name': 'A'}])
self.assertEqual(count_calls[0], 0)
# Do a schema action to ensure it gets called: this causes a table rename.
# 7 is id of raw view section for the Tabl1 table
self.apply_user_action(['UpdateRecord', '_grist_Views_section', 6, {'title': 'C'}])
self.apply_user_action(['UpdateRecord', '_grist_Views_section', 7, {'title': 'C'}])
self.assertEqual(count_calls[0], 1)
self.assertTableData('_grist_Tables', cols="subset", data=[

View File

@@ -455,10 +455,17 @@ class UserActions(object):
if (
table_id == "_grist_Views_section"
and any(rec.isRaw for i, rec in self._bulk_action_iter(table_id, row_ids))
# Only these fields are allowed to be modified
and not set(column_values) <= {"title", "options", "sortColRefs"}
):
raise ValueError("Cannot modify raw view section")
allowed_fields = {"title", "options", "sortColRefs"}
has_summary_section = any(rec.tableRef.summarySourceTable
for i, rec in self._bulk_action_iter(table_id, row_ids))
if has_summary_section:
# When a group-by column is removed from a summary source table, the source table reference
# changes; we pre-emptively allow changes to tableRef here to avoid blocking such actions.
allowed_fields.add("tableRef")
if not set(column_values) <= allowed_fields:
raise ValueError("Cannot modify raw view section")
if (
table_id == "_grist_Views_section_field"
@@ -1734,12 +1741,12 @@ class UserActions(object):
if raw_section:
# Create raw view section
raw_section = self._create_plain_view_section(
raw_section = self.create_plain_view_section(
result["id"],
table_id,
self._docmodel.view_sections,
"record",
table_title
table_title if not summarySourceTableRef else ""
)
if primary_view or raw_section:
@@ -1800,7 +1807,7 @@ class UserActions(object):
if groupby_colrefs is not None:
section = self._summary.create_new_summary_section(table, groupby_cols, view, section_type)
else:
section = self._create_plain_view_section(
section = self.create_plain_view_section(
table.id,
table.tableId,
view.viewSections,
@@ -1813,7 +1820,7 @@ class UserActions(object):
'sectionRef': section.id
}
def _create_plain_view_section(self, tableRef, tableId, view_sections, section_type, title):
def create_plain_view_section(self, tableRef, tableId, view_sections, section_type, title):
# If title is the same as tableId leave it empty
if title == tableId:
title = ''