Browse Source

chore: add get single select type option data

nathan 2 years ago
parent
commit
2e4df44c29

+ 4 - 2
frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx

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

+ 51 - 6
frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx

@@ -1,5 +1,10 @@
 import React from 'react';
-import { SelectOptionCellDataPB, ViewLayoutTypePB } from '../../../services/backend';
+import {
+  FieldType,
+  SelectOptionCellDataPB,
+  SingleSelectTypeOptionPB,
+  ViewLayoutTypePB,
+} from '../../../services/backend';
 import { Log } from '../../utils/log';
 import {
   assertFieldName,
@@ -11,10 +16,14 @@ import {
   makeSingleSelectCellController,
   openTestDatabase,
 } 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 { None, Some } from 'ts-results';
 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 = () => {
   async function createBuildInGrid() {
@@ -95,8 +104,8 @@ export const TestDeleteRow = () => {
 
   return TestButton('Test delete row', testDeleteRow);
 };
-export const TestCreateSelectOption = () => {
-  async function testCreateOption() {
+export const TestCreateSelectOptionInCell = () => {
+  async function testCreateOptionInCell() {
     const view = await createTestDatabaseView(ViewLayoutTypePB.Grid);
     const databaseController = await openTestDatabase(view.id);
     await databaseController.open().then((result) => result.unwrap());
@@ -111,7 +120,7 @@ export const TestCreateSelectOption = () => {
             console.log(option);
           },
         });
-        const backendSvc = new SelectOptionBackendService(cellController.cellIdentifier);
+        const backendSvc = new SelectOptionCellBackendService(cellController.cellIdentifier);
         await backendSvc.createOption({ name: 'option' + index });
         await cellController.dispose();
       }
@@ -119,7 +128,43 @@ export const TestCreateSelectOption = () => {
     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 = () => {

+ 24 - 10
frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts

@@ -14,6 +14,20 @@ import {
 } from '../../../../../services/backend/events/flowy-database';
 
 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) {}
 
   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) => {
     const payload = SelectOptionChangesetPB.fromObject({ cell_identifier: this._cellIdentifier() });
     payload.update_options.push(option);
@@ -59,16 +83,6 @@ export class SelectOptionBackendService {
     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 = () => {
     return CellIdPB.fromObject({
       view_id: this.cellIdentifier.viewId,

+ 19 - 7
frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts

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

+ 3 - 3
frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts

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