chore: add get single select type option data

This commit is contained in:
nathan 2023-03-01 20:16:25 +08:00
parent f58c91fb3f
commit 2e4df44c29
5 changed files with 101 additions and 28 deletions

View File

@ -4,11 +4,12 @@ import {
TestCreateGrid, TestCreateGrid,
TestCreateNewField, TestCreateNewField,
TestCreateRow, TestCreateRow,
TestCreateSelectOption, TestCreateSelectOptionInCell,
TestDeleteField, TestDeleteField,
TestDeleteRow, TestDeleteRow,
TestEditCell, TestEditCell,
TestEditField, TestEditField,
TestGetSingleSelectFieldData,
} from './TestGrid'; } from './TestGrid';
export const TestAPI = () => { export const TestAPI = () => {
@ -20,7 +21,8 @@ export const TestAPI = () => {
<TestCreateRow></TestCreateRow> <TestCreateRow></TestCreateRow>
<TestDeleteRow></TestDeleteRow> <TestDeleteRow></TestDeleteRow>
<TestEditCell></TestEditCell> <TestEditCell></TestEditCell>
<TestCreateSelectOption></TestCreateSelectOption> <TestCreateSelectOptionInCell></TestCreateSelectOptionInCell>
<TestGetSingleSelectFieldData></TestGetSingleSelectFieldData>
<TestEditField></TestEditField> <TestEditField></TestEditField>
<TestCreateNewField></TestCreateNewField> <TestCreateNewField></TestCreateNewField>
<TestDeleteField></TestDeleteField> <TestDeleteField></TestDeleteField>

View File

@ -1,5 +1,10 @@
import React from 'react'; import React from 'react';
import { SelectOptionCellDataPB, ViewLayoutTypePB } from '../../../services/backend'; import {
FieldType,
SelectOptionCellDataPB,
SingleSelectTypeOptionPB,
ViewLayoutTypePB,
} from '../../../services/backend';
import { Log } from '../../utils/log'; import { Log } from '../../utils/log';
import { import {
assertFieldName, assertFieldName,
@ -11,10 +16,14 @@ import {
makeSingleSelectCellController, makeSingleSelectCellController,
openTestDatabase, openTestDatabase,
} from './DatabaseTestHelper'; } from './DatabaseTestHelper';
import { SelectOptionBackendService } from '../../stores/effects/database/cell/select_option_bd_svc'; import {
SelectOptionBackendService,
SelectOptionCellBackendService,
} from '../../stores/effects/database/cell/select_option_bd_svc';
import { TypeOptionController } from '../../stores/effects/database/field/type_option/type_option_controller'; import { TypeOptionController } from '../../stores/effects/database/field/type_option/type_option_controller';
import { None, Some } from 'ts-results'; import { None, Some } from 'ts-results';
import { RowBackendService } from '../../stores/effects/database/row/row_bd_svc'; import { RowBackendService } from '../../stores/effects/database/row/row_bd_svc';
import { makeSingleSelectTypeOptionContext } from '../../stores/effects/database/field/type_option/type_option_context';
export const TestCreateGrid = () => { export const TestCreateGrid = () => {
async function createBuildInGrid() { async function createBuildInGrid() {
@ -95,8 +104,8 @@ export const TestDeleteRow = () => {
return TestButton('Test delete row', testDeleteRow); return TestButton('Test delete row', testDeleteRow);
}; };
export const TestCreateSelectOption = () => { export const TestCreateSelectOptionInCell = () => {
async function testCreateOption() { async function testCreateOptionInCell() {
const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); const view = await createTestDatabaseView(ViewLayoutTypePB.Grid);
const databaseController = await openTestDatabase(view.id); const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap()); await databaseController.open().then((result) => result.unwrap());
@ -111,7 +120,7 @@ export const TestCreateSelectOption = () => {
console.log(option); console.log(option);
}, },
}); });
const backendSvc = new SelectOptionBackendService(cellController.cellIdentifier); const backendSvc = new SelectOptionCellBackendService(cellController.cellIdentifier);
await backendSvc.createOption({ name: 'option' + index }); await backendSvc.createOption({ name: 'option' + index });
await cellController.dispose(); await cellController.dispose();
} }
@ -119,7 +128,43 @@ export const TestCreateSelectOption = () => {
await databaseController.dispose(); await databaseController.dispose();
} }
return TestButton('Test create a select option', testCreateOption); return TestButton('Test create a select option in cell', testCreateOptionInCell);
};
export const TestGetSingleSelectFieldData = () => {
async function testGetSingleSelectFieldData() {
const view = await createTestDatabaseView(ViewLayoutTypePB.Grid);
const databaseController = await openTestDatabase(view.id);
await databaseController.open().then((result) => result.unwrap());
// Find the single select column
const singleSelect = databaseController.fieldController.fieldInfos.find(
(fieldInfo) => fieldInfo.field.field_type === FieldType.SingleSelect
)!;
const typeOptionController = new TypeOptionController(view.id, Some(singleSelect));
const singleSelectTypeOptionContext = makeSingleSelectTypeOptionContext(typeOptionController);
// Create options
const singleSelectTypeOptionPB: SingleSelectTypeOptionPB = await singleSelectTypeOptionContext
.getTypeOption()
.then((result) => result.unwrap());
const backendSvc = new SelectOptionBackendService(view.id, singleSelect.field.id);
const option1 = await backendSvc.createOption({ name: 'Task 1' }).then((result) => result.unwrap());
singleSelectTypeOptionPB.options.splice(0, 0, option1);
const option2 = await backendSvc.createOption({ name: 'Task 2' }).then((result) => result.unwrap());
singleSelectTypeOptionPB.options.splice(0, 0, option2);
const option3 = await backendSvc.createOption({ name: 'Task 3' }).then((result) => result.unwrap());
singleSelectTypeOptionPB.options.splice(0, 0, option3);
await singleSelectTypeOptionContext.setTypeOption(singleSelectTypeOptionPB);
// Read options
const options = singleSelectTypeOptionPB.options;
console.log(options);
await databaseController.dispose();
}
return TestButton('Test get single-select column data', testGetSingleSelectFieldData);
}; };
export const TestEditField = () => { export const TestEditField = () => {

View File

@ -14,6 +14,20 @@ import {
} from '../../../../../services/backend/events/flowy-database'; } from '../../../../../services/backend/events/flowy-database';
export class SelectOptionBackendService { export class SelectOptionBackendService {
constructor(public readonly viewId: string, public readonly fieldId: string) {}
createOption = async (params: { name: string }) => {
const payload = CreateSelectOptionPayloadPB.fromObject({
option_name: params.name,
view_id: this.viewId,
field_id: this.fieldId,
});
return DatabaseEventCreateSelectOption(payload);
};
}
export class SelectOptionCellBackendService {
constructor(public readonly cellIdentifier: CellIdentifier) {} constructor(public readonly cellIdentifier: CellIdentifier) {}
createOption = async (params: { name: string; isSelect?: boolean }) => { createOption = async (params: { name: string; isSelect?: boolean }) => {
@ -31,6 +45,16 @@ export class SelectOptionBackendService {
} }
}; };
private _insertOption = (option: SelectOptionPB, isSelect: boolean) => {
const payload = SelectOptionChangesetPB.fromObject({ cell_identifier: this._cellIdentifier() });
if (isSelect) {
payload.insert_options.push(option);
} else {
payload.update_options.push(option);
}
return DatabaseEventUpdateSelectOption(payload);
};
updateOption = (option: SelectOptionPB) => { updateOption = (option: SelectOptionPB) => {
const payload = SelectOptionChangesetPB.fromObject({ cell_identifier: this._cellIdentifier() }); const payload = SelectOptionChangesetPB.fromObject({ cell_identifier: this._cellIdentifier() });
payload.update_options.push(option); payload.update_options.push(option);
@ -59,16 +83,6 @@ export class SelectOptionBackendService {
return DatabaseEventUpdateSelectOptionCell(payload); return DatabaseEventUpdateSelectOptionCell(payload);
}; };
private _insertOption = (option: SelectOptionPB, isSelect: boolean) => {
const payload = SelectOptionChangesetPB.fromObject({ cell_identifier: this._cellIdentifier() });
if (isSelect) {
payload.insert_options.push(option);
} else {
payload.update_options.push(option);
}
return DatabaseEventUpdateSelectOption(payload);
};
private _cellIdentifier = () => { private _cellIdentifier = () => {
return CellIdPB.fromObject({ return CellIdPB.fromObject({
view_id: this.cellIdentifier.viewId, view_id: this.cellIdentifier.viewId,

View File

@ -11,6 +11,7 @@ import {
URLTypeOptionPB, URLTypeOptionPB,
} from '../../../../../../services/backend'; } from '../../../../../../services/backend';
import { utf8Decoder, utf8Encoder } from '../../cell/data_parser'; import { utf8Decoder, utf8Encoder } from '../../cell/data_parser';
import { DatabaseFieldObserver } from '../field_observer';
abstract class TypeOptionSerde<T> { abstract class TypeOptionSerde<T> {
abstract deserialize(buffer: Uint8Array): T; abstract deserialize(buffer: Uint8Array): T;
@ -164,9 +165,17 @@ class ChecklistTypeOptionSerde extends TypeOptionSerde<ChecklistTypeOptionPB> {
export class TypeOptionContext<T> { export class TypeOptionContext<T> {
private typeOption: Option<T>; private typeOption: Option<T>;
private fieldObserver: DatabaseFieldObserver;
constructor(public readonly parser: TypeOptionSerde<T>, private readonly controller: TypeOptionController) { constructor(public readonly parser: TypeOptionSerde<T>, private readonly controller: TypeOptionController) {
this.typeOption = None; this.typeOption = None;
this.fieldObserver = new DatabaseFieldObserver(controller.fieldId);
void this.fieldObserver.subscribe({
onFieldsChanged: () => {
void this.getTypeOption();
},
});
} }
get viewId(): string { get viewId(): string {
@ -174,20 +183,23 @@ export class TypeOptionContext<T> {
} }
getTypeOption = async (): Promise<Result<T, FlowyError>> => { getTypeOption = async (): Promise<Result<T, FlowyError>> => {
if (this.typeOption.some) {
return Ok(this.typeOption.val);
}
const result = await this.controller.getTypeOption(); const result = await this.controller.getTypeOption();
if (result.ok) { if (result.ok) {
return Ok(this.parser.deserialize(result.val.type_option_data)); const typeOption = this.parser.deserialize(result.val.type_option_data);
this.typeOption = Some(typeOption);
return Ok(typeOption);
} else { } else {
return result; return result;
} }
}; };
setTypeOption = (typeOption: T) => { // Save the typeOption to disk
this.controller.typeOption = this.parser.serialize(typeOption); setTypeOption = async (typeOption: T) => {
await this.controller.saveTypeOption(this.parser.serialize(typeOption));
this.typeOption = Some(typeOption); this.typeOption = Some(typeOption);
}; };
dispose = async () => {
await this.fieldObserver.unsubscribe();
};
} }

View File

@ -59,10 +59,10 @@ export class TypeOptionController {
} }
}; };
set typeOption(data: Uint8Array) { saveTypeOption = async (data: Uint8Array) => {
if (this.typeOptionData.some) { if (this.typeOptionData.some) {
this.typeOptionData.val.type_option_data = data; this.typeOptionData.val.type_option_data = data;
void this.fieldBackendSvc?.updateTypeOption(data).then((result) => { await this.fieldBackendSvc?.updateTypeOption(data).then((result) => {
if (result.err) { if (result.err) {
Log.error(result.val); Log.error(result.val);
} }
@ -70,7 +70,7 @@ export class TypeOptionController {
} else { } else {
throw Error('Unexpect empty type option data. Should call initialize first'); throw Error('Unexpect empty type option data. Should call initialize first');
} }
} };
deleteField = async () => { deleteField = async () => {
if (this.fieldBackendSvc === undefined) { if (this.fieldBackendSvc === undefined) {