(core) Multiple types in columns mapping

Summary: Mapping for a single column in custom widgets accepts now multiple types as comma separeted list.

Test Plan: Added new

Reviewers: JakubSerafin

Reviewed By: JakubSerafin

Differential Revision: https://phab.getgrist.com/D4042
This commit is contained in:
Jarosław Sadziński 2023-09-13 12:29:36 +02:00
parent 40c5f7b738
commit 2b11000457
2 changed files with 66 additions and 2 deletions

View File

@ -13,7 +13,7 @@ export class ColumnToMapImpl implements Required<ColumnToMap> {
public description: string; public description: string;
// If column is optional (used only on the UI). // If column is optional (used only on the UI).
public optional: boolean; public optional: boolean;
// Type of the column that widget expects. // Type of the column that widget expects. Might be a single or a comma separated list of types.
public type: string; public type: string;
// Description of the type (used to show a placeholder). // Description of the type (used to show a placeholder).
public typeDesc: string; public typeDesc: string;
@ -33,7 +33,7 @@ export class ColumnToMapImpl implements Required<ColumnToMap> {
* Does the column type matches this definition. * Does the column type matches this definition.
*/ */
public canByMapped(pureType: string) { public canByMapped(pureType: string) {
return pureType === this.type return this.type.split(',').includes(pureType)
|| pureType === "Any" || pureType === "Any"
|| this.type === "Any"; || this.type === "Any";
} }

View File

@ -244,6 +244,10 @@ describe('CustomWidgetsConfig', function () {
const text = await this._read('#onRecords'); const text = await this._read('#onRecords');
return JSON.parse(text || 'null'); return JSON.parse(text || 'null');
} }
public async onRecord() {
const text = await this._read('#onRecord');
return JSON.parse(text || 'null');
}
public async onRecordsMappings() { public async onRecordsMappings() {
const text = await this._read('#onRecordsMappings'); const text = await this._read('#onRecordsMappings');
return JSON.parse(text || 'null'); return JSON.parse(text || 'null');
@ -572,6 +576,66 @@ describe('CustomWidgetsConfig', function () {
await revert(); await revert();
}); });
it('should support multiple types in mappings', async () => {
const revert = await gu.begin();
await toggleWidgetMenu();
await clickOption(CUSTOM_URL);
await gu.setWidgetUrl(
createConfigUrl({
columns: [
{name: 'M1', type: 'Date,DateTime'},
{name: 'M2', type: 'Date,DateTime', allowMultiple: true},
],
requiredAccess: 'read table',
})
);
await accept();
await widget.waitForFrame();
// Add B=Date, C=DateTime, D=Numeric
await gu.sendActions([
['AddVisibleColumn', 'Table1', 'B', {type: 'Any'}],
['AddVisibleColumn', 'Table1', 'C', {type: 'Date'}],
['AddVisibleColumn', 'Table1', 'D', {type: 'DateTime'}],
['AddVisibleColumn', 'Table1', 'E', {type: 'Numeric'}],
// Add sample record.
['UpdateRecord', 'Table1', 1, {C: '2019-01-01', D: '2019-01-01 12:00', E: 1}]
]);
await gu.selectSectionByTitle('Widget');
// Make sure we have no mappings
assert.deepEqual(await widget.onRecordsMappings(), null);
// Now see what we are offered for M1.
await toggleDrop(pickerDrop('M1'));
assert.deepEqual(await getOptions(), ['B', 'C', 'D']);
// Make sure they work. First select C.
await clickOption('B');
// Make sure onRecord and onRecordMappings looks legit.
assert.deepEqual(await widget.onRecord(), {id:1, B: null});
assert.deepEqual(await widget.onRecordMappings(), {M1: 'B', M2: []});
// Now select C.
await toggleDrop(pickerDrop('M1'));
await clickOption('C');
assert.deepEqual(await widget.onRecord(), {id:1, C: '2019-01-01T00:00:00.000Z'});
assert.deepEqual(await widget.onRecordMappings(), {M1: 'C', M2: []});
// Now select D.
await toggleDrop(pickerDrop('M1'));
await clickOption('D');
assert.deepEqual(await widget.onRecord(), {id:1, D: '2019-01-01T17:00:00.000Z'});
assert.deepEqual(await widget.onRecordMappings(), {M1: 'D', M2: []});
// Make sure we can select multiple columns for M2 with Date and DateTime.
await click(pickerAdd('M2'));
assert.deepEqual(await getMenuOptions(), ['B', 'C', 'D']);
await clickMenuItem('B');
assert.deepEqual(await widget.onRecordMappings(), {M1: 'D', M2: ['B']});
await click(pickerAdd('M2'));
await clickMenuItem('C');
assert.deepEqual(await widget.onRecordMappings(), {M1: 'D', M2: ['B', 'C']});
await revert();
});
it('should remove mapping when column is deleted', async () => { it('should remove mapping when column is deleted', async () => {
const revert = await gu.begin(); const revert = await gu.begin();
await toggleWidgetMenu(); await toggleWidgetMenu();