소스 검색

test: add save date cell and checkbox cell (#2167)

* test: add save date cell and checkbox cell

* chore: add move field test

* ci: fix tauri build
Nathan.fooo 2 년 전
부모
커밋
cb149ec73d

+ 1 - 1
frontend/appflowy_tauri/src-tauri/src/init.rs

@@ -10,7 +10,7 @@ pub fn init_flowy_core() -> AppFlowyCore {
   }
   data_path.push("data");
 
-  std::env::set_var("RUST_LOG", "debug");
+  std::env::set_var("RUST_LOG", "trace");
   let server_config = get_client_server_configuration().unwrap();
   let config = AppFlowyCoreConfig::new(
     data_path.to_str().unwrap(),

+ 5 - 1
frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditRow.tsx

@@ -108,7 +108,11 @@ export const EditRow = ({
 
   const onDragEnd: OnDragEndResponder = (result) => {
     if (!result.destination?.index) return;
-    void controller.moveField(result.source.droppableId, result.source.index, result.destination.index);
+    void controller.moveField({
+      fieldId: result.source.droppableId,
+      fromIndex: result.source.index,
+      toIndex: result.destination.index,
+    });
   };
 
   return (

+ 12 - 0
frontend/appflowy_tauri/src/appflowy_app/components/tests/DatabaseTestHelper.ts

@@ -12,6 +12,7 @@ import { RowInfo } from '../../stores/effects/database/row/row_cache';
 import { RowController } from '../../stores/effects/database/row/row_controller';
 import {
   CellControllerBuilder,
+  CheckboxCellController,
   DateCellController,
   NumberCellController,
   SelectOptionCellController,
@@ -126,6 +127,17 @@ export async function makeDateCellController(
   return Some(builder.build() as DateCellController);
 }
 
+export async function makeCheckboxCellController(
+  fieldId: string,
+  rowInfo: RowInfo,
+  databaseController: DatabaseController
+): Promise<Option<CheckboxCellController>> {
+  const builder = await makeCellControllerBuilder(fieldId, rowInfo, FieldType.Checkbox, databaseController).then(
+    (result) => result.unwrap()
+  );
+  return Some(builder.build() as CheckboxCellController);
+}
+
 export async function makeURLCellController(
   fieldId: string,
   rowInfo: RowInfo,

+ 6 - 0
frontend/appflowy_tauri/src/appflowy_app/components/tests/TestAPI.tsx

@@ -8,10 +8,13 @@ import {
   TestDeleteField,
   TestDeleteRow,
   TestEditCell,
+  TestEditCheckboxCell,
+  TestEditDateCell,
   TestEditField,
   TestEditTextCell,
   TestEditURLCell,
   TestGetSingleSelectFieldData,
+  TestMoveField,
   TestSwitchFromMultiSelectToText,
   TestSwitchFromSingleSelectToNumber,
 } from './TestGrid';
@@ -37,9 +40,12 @@ export const TestAPI = () => {
         <TestEditCell></TestEditCell>
         <TestEditTextCell></TestEditTextCell>
         <TestEditURLCell></TestEditURLCell>
+        <TestEditDateCell></TestEditDateCell>
+        <TestEditCheckboxCell></TestEditCheckboxCell>
         <TestCreateSelectOptionInCell></TestCreateSelectOptionInCell>
         <TestGetSingleSelectFieldData></TestGetSingleSelectFieldData>
         <TestEditField></TestEditField>
+        <TestMoveField></TestMoveField>
         <TestCreateNewField></TestCreateNewField>
         <TestDeleteField></TestDeleteField>
         <TestSwitchFromSingleSelectToNumber></TestSwitchFromSingleSelectToNumber>

+ 83 - 0
frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGrid.tsx

@@ -8,6 +8,7 @@ import {
 } from '@/services/backend';
 import { Log } from '$app/utils/log';
 import {
+  assert,
   assertFieldName,
   assertNumberOfFields,
   assertNumberOfRows,
@@ -16,6 +17,8 @@ import {
   createTestDatabaseView,
   editTextCell,
   findFirstFieldInfoWithFieldType,
+  makeCheckboxCellController,
+  makeDateCellController,
   makeMultiSelectCellController,
   makeSingleSelectCellController,
   makeTextCellController,
@@ -27,6 +30,8 @@ import { TypeOptionController } from '$app/stores/effects/database/field/type_op
 import { None, Some } from 'ts-results';
 import { RowBackendService } from '$app/stores/effects/database/row/row_bd_svc';
 import { makeNumberTypeOptionContext } from '$app/stores/effects/database/field/type_option/type_option_context';
+import { CalendarData } from '$app/stores/effects/database/cell/controller_builder';
+import { DatabaseEventMoveField } from '@/services/backend/events/flowy-database';
 
 export const RunAllGridTests = () => {
   async function run() {
@@ -138,6 +143,57 @@ async function testEditURLCell() {
   await new Promise((resolve) => setTimeout(resolve, 200));
 }
 
+async function testEditDateCell() {
+  const view = await createTestDatabaseView(ViewLayoutTypePB.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(ViewLayoutTypePB.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(ViewLayoutTypePB.Grid);
   const databaseController = await openTestDatabase(view.id);
@@ -196,6 +252,24 @@ async function testCreateOptionInCell() {
   await databaseController.dispose();
 }
 
+async function testMoveField() {
+  const view = await createTestDatabaseView(ViewLayoutTypePB.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(ViewLayoutTypePB.Grid);
   const databaseController = await openTestDatabase(view.id);
@@ -360,6 +434,12 @@ export const 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);
 };
@@ -382,6 +462,9 @@ 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);
 };

+ 1 - 1
frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/controller_builder.ts

@@ -23,7 +23,7 @@ export type SelectOptionCellController = CellController<SelectOptionCellDataPB,
 export type DateCellController = CellController<DateCellDataPB, CalendarData>;
 
 export class CalendarData {
-  constructor(public readonly date: Date, public readonly time?: string) {}
+  constructor(public readonly date: Date, public readonly includeTime: boolean, public readonly time?: string) {}
 }
 
 export type URLCellController = CellController<URLCellDataPB, string>;

+ 2 - 1
frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_persistence.ts

@@ -25,11 +25,12 @@ export class DateCellDataPersistence extends CellDataPersistence<CalendarData> {
 
   save(data: CalendarData): Promise<Result<void, FlowyError>> {
     const payload = DateChangesetPB.fromObject({ cell_path: _makeCellPath(this.cellIdentifier) });
-    payload.date = data.date.getUTCMilliseconds.toString();
+    payload.date = ((data.date.getTime() / 1000) | 0).toString();
     payload.is_utc = true;
     if (data.time !== undefined) {
       payload.time = data.time;
     }
+    payload.include_time = data.includeTime;
     return DatabaseEventUpdateDateCell(payload);
   }
 }

+ 10 - 10
frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts

@@ -98,16 +98,6 @@ export class DatabaseBackendService {
     return DatabaseEventMoveGroup(payload);
   };
 
-  moveField = (fieldId: string, fromIndex: number, toIndex: number) => {
-    const payload = MoveFieldPayloadPB.fromObject({
-      view_id: this.viewId,
-      field_id: fieldId,
-      from_index: fromIndex,
-      to_index: toIndex,
-    });
-    return DatabaseEventMoveField(payload);
-  };
-
   /// Get all fields in database
   getFields = async (fieldIds?: FieldIdPB[]) => {
     const payload = GetFieldPayloadPB.fromObject({ view_id: this.viewId });
@@ -125,6 +115,16 @@ export class DatabaseBackendService {
     return DatabaseEventGetGroup(payload);
   };
 
+  moveField = (params: { fieldId: string; fromIndex: number; toIndex: number }) => {
+    const payload = MoveFieldPayloadPB.fromObject({
+      view_id: this.viewId,
+      field_id: params.fieldId,
+      from_index: params.fromIndex,
+      to_index: params.toIndex,
+    });
+    return DatabaseEventMoveField(payload);
+  };
+
   /// Get all groups in database
   /// It should only call once after the board open
   loadGroups = () => {

+ 3 - 3
frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts

@@ -1,7 +1,7 @@
 import { DatabaseBackendService } from './database_bd_svc';
 import { FieldController, FieldInfo } from './field/field_controller';
 import { DatabaseViewCache } from './view/database_view_cache';
-import { DatabasePB, FlowyError, GroupPB } from '@/services/backend';
+import { DatabasePB, GroupPB, FlowyError } from '@/services/backend';
 import { RowChangedReason, RowInfo } from './row/row_cache';
 import { Err, Ok } from 'ts-results';
 import { DatabaseGroupController } from './group/group_controller';
@@ -102,8 +102,8 @@ export class DatabaseController {
     return this.backendService.moveGroup(fromGroupId, toGroupId);
   };
 
-  moveField = (fieldId: string, fromIndex: number, toIndex: number) => {
-    return this.backendService.moveField(fieldId, fromIndex, toIndex);
+  moveField = (params: { fieldId: string; fromIndex: number; toIndex: number }) => {
+    return this.backendService.moveField(params);
   };
 
   private loadGroup = async () => {

+ 5 - 7
frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts

@@ -36,8 +36,8 @@ export class FieldController {
     }
   };
 
-  subscribe = (callbacks: { onNumOfFieldsChanged?: (fieldInfos: readonly FieldInfo[]) => void}) => {
-     this.numOfFieldsNotifier.observer.subscribe((fieldInfos) => {
+  subscribe = (callbacks: { onNumOfFieldsChanged?: (fieldInfos: readonly FieldInfo[]) => void }) => {
+    this.numOfFieldsNotifier.observer.subscribe((fieldInfos) => {
       callbacks.onNumOfFieldsChanged?.(fieldInfos);
     });
   };
@@ -63,12 +63,10 @@ export class FieldController {
     }
 
     const deletedFieldIds = deletedFields.map((field) => field.field_id);
-    const predicate = (element: FieldInfo) => {
-      !deletedFieldIds.includes(element.field.id);
+    const predicate = (element: FieldInfo): boolean => {
+      return !deletedFieldIds.includes(element.field.id);
     };
-    const newFieldInfos = [...this.fieldInfos];
-    newFieldInfos.filter(predicate);
-    this.numOfFieldsNotifier.fieldInfos = newFieldInfos;
+    this.numOfFieldsNotifier.fieldInfos = [...this.fieldInfos].filter(predicate);
   };
 
   private _insertFields = (insertedFields: IndexFieldPB[]) => {