mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(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:
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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=[
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
]),
|
||||
]),
|
||||
])
|
||||
|
||||
@@ -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=[
|
||||
|
||||
@@ -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 = ''
|
||||
|
||||
Reference in New Issue
Block a user