);
};
async function createBuildInGrid() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
databaseController.subscribe({
onViewChanged: (databasePB) => {
Log.debug('Did receive database:' + databasePB);
},
// onRowsChanged: async (rows) => {
// if (rows.length !== 3) {
// throw Error('Expected number of rows is 3, but receive ' + rows.length);
// }
// },
onFieldsChanged: (fields) => {
if (fields.length !== 3) {
throw Error('Expected number of fields is 3, but receive ' + fields.length);
}
},
});
await databaseController.open().then((result) => result.unwrap());
await databaseController.dispose();
}
async function testEditGridCell() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
for (const [index, row] of databaseController.databaseViewCache.rowInfos.entries()) {
const cellContent = index.toString();
const fieldInfo = findFirstFieldInfoWithFieldType(row, FieldType.RichText).unwrap();
await editTextCell(fieldInfo.field.id, row, databaseController, cellContent);
await assertTextCell(fieldInfo.field.id, row, databaseController, cellContent);
}
}
async function testEditTextCell() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
const row = databaseController.databaseViewCache.rowInfos[0];
const textField = findFirstFieldInfoWithFieldType(row, FieldType.RichText).unwrap();
const textCellController = await makeTextCellController(textField.field.id, row, databaseController).then((result) =>
result.unwrap()
);
textCellController.subscribeChanged({
onCellChanged: (content) => {
Log.info('Receive text:', content);
},
});
await textCellController.saveCellData('hello react');
await new Promise((resolve) => setTimeout(resolve, 200));
await databaseController.dispose();
}
async function testEditURLCell() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
const typeOptionController = new TypeOptionController(view.id, None, FieldType.URL);
await typeOptionController.initialize();
const row = databaseController.databaseViewCache.rowInfos[0];
const urlCellController = await makeURLCellController(typeOptionController.fieldId, row, databaseController).then(
(result) => result.unwrap()
);
urlCellController.subscribeChanged({
onCellChanged: (content) => {
const pb = content.unwrap();
Log.info('Receive url data:', pb.url, pb.content);
},
});
await urlCellController.saveCellData('hello react');
await new Promise((resolve) => setTimeout(resolve, 200));
await urlCellController.saveCellData('appflowy.io');
await new Promise((resolve) => setTimeout(resolve, 200));
}
async function testEditDateCell() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
const typeOptionController = new TypeOptionController(view.id, None, FieldType.DateTime);
await typeOptionController.initialize();
const row = databaseController.databaseViewCache.rowInfos[0];
const dateCellController = await makeDateCellController(typeOptionController.fieldId, row, databaseController).then(
(result) => result.unwrap()
);
dateCellController.subscribeChanged({
onCellChanged: (content) => {
const pb = content.unwrap();
Log.info('Receive date data:', pb.date, pb.time);
},
});
const date = new CalendarData(new Date(), true, '13:00');
await dateCellController.saveCellData(date);
await new Promise((resolve) => setTimeout(resolve, 200));
}
async function testCheckboxCell() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
const typeOptionController = new TypeOptionController(view.id, None, FieldType.Checkbox);
await typeOptionController.initialize();
const row = databaseController.databaseViewCache.rowInfos[0];
const checkboxCellController = await makeCheckboxCellController(
typeOptionController.fieldId,
row,
databaseController
).then((result) => result.unwrap());
checkboxCellController.subscribeChanged({
onCellChanged: (content) => {
const pb = content.unwrap();
Log.info('Receive checkbox data:', pb);
},
});
await checkboxCellController.saveCellData('true');
await new Promise((resolve) => setTimeout(resolve, 200));
}
async function testCreateRow() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
await assertNumberOfRows(view.id, 3);
// Create a row from a DatabaseController or create using the RowBackendService
await databaseController.createRow();
await assertNumberOfRows(view.id, 4);
await databaseController.dispose();
}
async function testDeleteRow() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
const rows = databaseController.databaseViewCache.rowInfos;
const svc = new RowBackendService(view.id);
await svc.deleteRow(rows[0].row.id);
await assertNumberOfRows(view.id, 2);
// Wait the databaseViewCache get the change notification and
// update the rows.
await new Promise((resolve) => setTimeout(resolve, 200));
if (databaseController.databaseViewCache.rowInfos.length !== 2) {
throw Error('The number of rows is not match');
}
await databaseController.dispose();
}
async function testCreateOptionInCell() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
for (const [index, row] of databaseController.databaseViewCache.rowInfos.entries()) {
if (index === 0) {
const fieldInfo = findFirstFieldInfoWithFieldType(row, FieldType.SingleSelect).unwrap();
const cellController = await makeSingleSelectCellController(fieldInfo.field.id, row, databaseController).then(
(result) => result.unwrap()
);
// eslint-disable-next-line @typescript-eslint/await-thenable
await cellController.subscribeChanged({
onCellChanged: (value) => {
if (value.some) {
const option: SelectOptionCellDataPB = value.unwrap();
console.log(option);
}
},
});
const backendSvc = new SelectOptionCellBackendService(cellController.cellIdentifier);
await backendSvc.createOption({ name: 'option' + index });
await cellController.dispose();
}
}
await databaseController.dispose();
}
async function testMoveField() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
databaseController.subscribe({
onFieldsChanged: (value) => {
Log.info('Receive fields data:', value);
},
});
const fieldInfos = [...databaseController.fieldController.fieldInfos];
const field_id = fieldInfos[0].field.id;
await databaseController.moveField({ fieldId: field_id, fromIndex: 0, toIndex: 1 });
await new Promise((resolve) => setTimeout(resolve, 200));
assert(databaseController.fieldController.fieldInfos[1].field.id === field_id);
}
async function testGetSingleSelectFieldData() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
// Find the single select column
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const singleSelect = databaseController.fieldController.fieldInfos.find(
(fieldInfo) => fieldInfo.field.field_type === FieldType.SingleSelect
)!;
// Create options
const singleSelectTypeOptionContext = await createSingleSelectOptions(view.id, singleSelect, [
'Task 1',
'Task 2',
'Task 3',
]);
// Read options
const options = await singleSelectTypeOptionContext.getTypeOption().then((result) => result.unwrap());
console.log(options);
await databaseController.dispose();
}
async function testSwitchFromSingleSelectToNumber() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
// Find the single select column
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const singleSelect = databaseController.fieldController.fieldInfos.find(
(fieldInfo) => fieldInfo.field.field_type === FieldType.SingleSelect
)!;
const typeOptionController = new TypeOptionController(view.id, Some(singleSelect));
await typeOptionController.switchToField(FieldType.Number);
// Check the number type option
const numberTypeOptionContext = makeNumberTypeOptionContext(typeOptionController);
const numberTypeOption: NumberTypeOptionPB = await numberTypeOptionContext
.getTypeOption()
.then((result) => result.unwrap());
const format: NumberFormat = numberTypeOption.format;
if (format !== NumberFormat.Num) {
throw Error('The default format should be number');
}
await databaseController.dispose();
}
async function testSwitchFromMultiSelectToRichText() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
// Create multi-select field
const typeOptionController = new TypeOptionController(view.id, None, FieldType.MultiSelect);
await typeOptionController.initialize();
// Insert options to first row
const row = databaseController.databaseViewCache.rowInfos[0];
const multiSelectField = typeOptionController.getFieldInfo();
// const multiSelectField = findFirstFieldInfoWithFieldType(row, FieldType.MultiSelect).unwrap();
const selectOptionCellController = await makeMultiSelectCellController(
multiSelectField.field.id,
row,
databaseController
).then((result) => result.unwrap());
const backendSvc = new SelectOptionCellBackendService(selectOptionCellController.cellIdentifier);
await backendSvc.createOption({ name: 'A' });
await backendSvc.createOption({ name: 'B' });
await backendSvc.createOption({ name: 'C' });
const selectOptionCellData = await selectOptionCellController.getCellData().then((result) => result.unwrap());
if (selectOptionCellData.options.length !== 3) {
throw Error('The options should equal to 3');
}
if (selectOptionCellData.select_options.length !== 3) {
throw Error('The selected options should equal to 3');
}
await selectOptionCellController.dispose();
// Switch to RichText field type
await typeOptionController.switchToField(FieldType.RichText).then((result) => result.unwrap());
if (typeOptionController.fieldType !== FieldType.RichText) {
throw Error('The field type should be text');
}
const textCellController = await makeTextCellController(multiSelectField.field.id, row, databaseController).then(
(result) => result.unwrap()
);
const cellContent = await textCellController.getCellData();
if (cellContent.unwrap() !== 'A,B,C') {
throw Error('The cell content should be A,B,C, but receive: ' + cellContent.unwrap());
}
await databaseController.dispose();
}
async function testEditField() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
const fieldInfos = databaseController.fieldController.fieldInfos;
// Modify the name of the field
const firstFieldInfo = fieldInfos[0];
const controller = new TypeOptionController(view.id, Some(firstFieldInfo));
await controller.initialize();
const newName = 'hello world';
await controller.setFieldName(newName);
await new Promise((resolve) => setTimeout(resolve, 200));
await assertFieldName(view.id, firstFieldInfo.field.id, firstFieldInfo.field.field_type, newName);
await databaseController.dispose();
}
async function testCreateNewField() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
await assertNumberOfFields(view.id, 3);
// Modify the name of the field
const controller = new TypeOptionController(view.id, None);
await controller.initialize();
await assertNumberOfFields(view.id, 4);
await databaseController.dispose();
}
async function testDeleteField() {
const view = await createTestDatabaseView(ViewLayoutPB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
// Modify the name of the field.
// The fieldInfos[0] is the primary field by default, we can't delete it.
// So let choose the second fieldInfo.
const fieldInfo = databaseController.fieldController.fieldInfos[1];
const controller = new TypeOptionController(view.id, Some(fieldInfo));
await controller.initialize();
await assertNumberOfFields(view.id, 3);
await controller.deleteField();
await assertNumberOfFields(view.id, 2);
await databaseController.dispose();
}
export const TestCreateGrid = () => {
return TestButton('Test create build-in grid', createBuildInGrid);
};
export const TestEditCell = () => {
return TestButton('Test editing cell', testEditGridCell);
};
export const TestEditTextCell = () => {
return TestButton('Test editing text cell', testEditTextCell);
};
export const TestEditURLCell = () => {
return TestButton('Test editing URL cell', testEditURLCell);
};
export const TestEditDateCell = () => {
return TestButton('Test editing date cell', testEditDateCell);
};
export const TestEditCheckboxCell = () => {
return TestButton('Test editing checkbox cell', testCheckboxCell);
};
export const TestCreateRow = () => {
return TestButton('Test create row', testCreateRow);
};
export const TestDeleteRow = () => {
return TestButton('Test delete row', testDeleteRow);
};
export const TestCreateSelectOptionInCell = () => {
return TestButton('Test create a select option in cell', testCreateOptionInCell);
};
export const TestGetSingleSelectFieldData = () => {
return TestButton('Test get single-select column data', testGetSingleSelectFieldData);
};
export const TestSwitchFromSingleSelectToNumber = () => {
return TestButton('Test switch from single-select to number column', testSwitchFromSingleSelectToNumber);
};
export const TestSwitchFromMultiSelectToText = () => {
return TestButton('Test switch from multi-select to text column', testSwitchFromMultiSelectToRichText);
};
export const TestMoveField = () => {
return TestButton('Test move field', testMoveField);
};
export const TestEditField = () => {
return TestButton('Test edit the column name', testEditField);
};
export const TestCreateNewField = () => {
return TestButton('Test create a new column', testCreateNewField);
};
export const TestDeleteField = () => {
return TestButton('Test delete a new column', testDeleteField);
};
export const TestButton = (title: string, onClick: () => void) => {
return (