From 50821f655d45101fa8be6606fda253e60c8f6cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaros=C5=82aw=20Sadzi=C5=84ski?= Date: Tue, 4 Jan 2022 12:54:06 +0100 Subject: [PATCH] (core) Duplicate page should copy filters. Summary: Duplicate page also copies filters for all sections. Test Plan: nbrowser tests Reviewers: cyprien, alexmojaki Reviewed By: cyprien, alexmojaki Subscribers: alexmojaki Differential Revision: https://phab.getgrist.com/D3203 --- app/client/aclui/AccessRules.ts | 22 +---------- app/client/components/duplicatePage.ts | 52 +++++++++++++++++++------- app/common/DocActions.ts | 22 ++++++++++- 3 files changed, 61 insertions(+), 35 deletions(-) diff --git a/app/client/aclui/AccessRules.ts b/app/client/aclui/AccessRules.ts index bf8a8a15..db86e5dd 100644 --- a/app/client/aclui/AccessRules.ts +++ b/app/client/aclui/AccessRules.ts @@ -26,7 +26,7 @@ import { summarizePermissionSet } from 'app/common/ACLPermissions'; import {ACLRuleCollection, SPECIAL_RULES_TABLE_ID} from 'app/common/ACLRuleCollection'; -import {BulkColValues, RowRecord, UserAction} from 'app/common/DocActions'; +import {BulkColValues, getColValues, RowRecord, UserAction} from 'app/common/DocActions'; import { FormulaProperties, getFormulaProperties, @@ -1371,26 +1371,6 @@ function syncRecords(tableData: TableData, newRecords: RowRecord[], return {userActions, rowIdMap}; } -/** - * Convert a list of rows into an object with columns of values, used for - * BulkAddRecord/BulkUpdateRecord actions. - */ -function getColValues(records: RowRecord[]): BulkColValues { - const colIdSet = new Set(); - for (const r of records) { - for (const c of Object.keys(r)) { - if (c !== 'id') { - colIdSet.add(c); - } - } - } - const result: BulkColValues = {}; - for (const colId of colIdSet) { - result[colId] = records.map(r => r[colId]); - } - return result; -} - /** * Convert a list of [before, after] rows into an object of changes, skipping columns which * haven't changed. diff --git a/app/client/components/duplicatePage.ts b/app/client/components/duplicatePage.ts index 6395b70f..18ece246 100644 --- a/app/client/components/duplicatePage.ts +++ b/app/client/components/duplicatePage.ts @@ -3,7 +3,7 @@ import { ViewFieldRec, ViewSectionRec } from 'app/client/models/DocModel'; import { cssField, cssInput, cssLabel} from 'app/client/ui/MakeCopyMenu'; import { IPageWidget, toPageWidget } from 'app/client/ui/PageWidgetPicker'; import { confirmModal } from 'app/client/ui2018/modals'; -import { BulkColValues, RowRecord, UserAction } from 'app/common/DocActions'; +import { BulkColValues, getColValues, RowRecord, UserAction } from 'app/common/DocActions'; import { arrayRepeat } from 'app/common/gutil'; import { schema } from 'app/common/schema'; import { dom } from 'grainjs'; @@ -53,12 +53,6 @@ async function makeDuplicate(gristDoc: GristDoc, pageId: number, pageName: strin results.map(res => res.sectionRef) ) as {[id: number]: number}; - // update layout spec - const viewLayoutSpec = patchLayoutSpec(sourceView.layoutSpecObj.peek(), viewSectionIdMap); - await gristDoc.docData.sendAction( - ['UpdateRecord', '_grist_Views', viewRef, { layoutSpec: JSON.stringify(viewLayoutSpec)}] - ); - // update the view fields const destViewSections = viewSections.map((vs) => ( gristDoc.docModel.viewSections.rowModels[viewSectionIdMap[vs.getRowId()]] @@ -70,14 +64,48 @@ async function makeDuplicate(gristDoc: GristDoc, pageId: number, pageName: strin flatten(viewSections.map((vs) => vs.viewFields.peek().peek().map((field) => field.getRowId()))), flatten(newViewFieldIds)) as {[id: number]: number}; - // update the view sections - await updateViewSections(gristDoc, destViewSections, viewSections, viewFieldsIdMap, viewSectionIdMap); + // update layout spec + const viewLayoutSpec = patchLayoutSpec(sourceView.layoutSpecObj.peek(), viewSectionIdMap); + await Promise.all([ + gristDoc.docData.sendAction( + ['UpdateRecord', '_grist_Views', viewRef, { layoutSpec: JSON.stringify(viewLayoutSpec)}] + ), + updateViewSections(gristDoc, destViewSections, viewSections, viewFieldsIdMap, viewSectionIdMap), + copyFilters(gristDoc, viewSections, viewSectionIdMap) + ]); }); // Give copy focus await gristDoc.openDocPage(viewRef); } +/** + * Copies _grist_Filters from source sections. + */ +async function copyFilters( + gristDoc: GristDoc, + srcViewSections: ViewSectionRec[], + viewSectionMap: {[id: number]: number}) { + + // Get all filters for selected sections. + const filters: RowRecord[] = []; + const table = gristDoc.docData.getMetaTable('_grist_Filters'); + for (const srcViewSection of srcViewSections) { + const sectionFilters = table + .filterRecords({ viewSectionRef : srcViewSection.id.peek()}) + .map(filter => ({ + // Replace section ref with destination ref. + ...filter, viewSectionRef : viewSectionMap[srcViewSection.id.peek()] + })); + filters.push(...sectionFilters); + } + if (filters.length) { + const filterInfo = getColValues(filters); + await gristDoc.docData.sendAction(['BulkAddRecord', '_grist_Filters', + new Array(filters.length).fill(null), filterInfo]); + } +} + /** * Update all of destViewSections with srcViewSections, use fieldsMap to patch the section layout * (for detail/cardlist sections), use viewSectionMap to patch the sections ids for linking. @@ -99,11 +127,9 @@ async function updateViewSections(gristDoc: GristDoc, destViewSections: ViewSect } // transpose data - const sectionsInfo = {} as BulkColValues; - forEach(records[0], (val, key) => sectionsInfo[key] = records.map(rec => rec[key])); + const sectionsInfo = getColValues(records); - // ditch column ids and parentId - delete sectionsInfo.id; + // ditch column parentId delete sectionsInfo.parentId; // send action diff --git a/app/common/DocActions.ts b/app/common/DocActions.ts index 7a21c1ed..ff798e08 100644 --- a/app/common/DocActions.ts +++ b/app/common/DocActions.ts @@ -3,7 +3,7 @@ */ // Some definitions have moved to be part of plugin API. -import { CellValue } from 'app/plugin/GristData'; +import { CellValue, RowRecord } from 'app/plugin/GristData'; export { CellValue, RowRecord } from 'app/plugin/GristData'; // Part of a special CellValue used for comparisons, embedding several versions of a CellValue. @@ -182,3 +182,23 @@ export function fromTableDataAction(tableData: TableDataAction): TableColValues const colValues: BulkColValues = tableData[3]; return {id: rowIds, ...colValues}; } + +/** + * Convert a list of rows into an object with columns of values, used for + * BulkAddRecord/BulkUpdateRecord actions. + */ +export function getColValues(records: RowRecord[]): BulkColValues { + const colIdSet = new Set(); + for (const r of records) { + for (const c of Object.keys(r)) { + if (c !== 'id') { + colIdSet.add(c); + } + } + } + const result: BulkColValues = {}; + for (const colId of colIdSet) { + result[colId] = records.map(r => r[colId]); + } + return result; +}