Merge pull request #447 from AppFlowy-IO/feat_grid_row_animation

Feat grid row animation
This commit is contained in:
Nathan.fooo 2022-04-11 21:07:15 +08:00 committed by GitHub
commit d0d8295e15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 281 additions and 245 deletions

View File

@ -59,7 +59,11 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
rowId: state.cellData.rowId, rowId: state.cellData.rowId,
); );
result.fold( result.fold(
(cell) => add(CheckboxCellEvent.didReceiveCellUpdate(cell)), (cell) {
if (!isClosed) {
add(CheckboxCellEvent.didReceiveCellUpdate(cell));
}
},
(err) => Log.error(err), (err) => Log.error(err),
); );
} }

View File

@ -72,7 +72,11 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
rowId: state.cellData.rowId, rowId: state.cellData.rowId,
); );
result.fold( result.fold(
(cell) => add(DateCellEvent.didReceiveCellUpdate(cell)), (cell) {
if (!isClosed) {
add(DateCellEvent.didReceiveCellUpdate(cell));
}
},
(err) => Log.error(err), (err) => Log.error(err),
); );
} }

View File

@ -59,20 +59,28 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
_listener.updateCellNotifier.addPublishListener((result) { _listener.updateCellNotifier.addPublishListener((result) {
result.fold( result.fold(
(notificationData) async { (notificationData) async {
await _getCellData();
},
(err) => Log.error(err),
);
});
_listener.start();
}
Future<void> _getCellData() async {
final result = await _service.getCell( final result = await _service.getCell(
gridId: state.cellData.gridId, gridId: state.cellData.gridId,
fieldId: state.cellData.field.id, fieldId: state.cellData.field.id,
rowId: state.cellData.rowId, rowId: state.cellData.rowId,
); );
result.fold( result.fold(
(cell) => add(NumberCellEvent.didReceiveCellUpdate(cell)), (cell) {
(err) => Log.error(err), if (!isClosed) {
); add(NumberCellEvent.didReceiveCellUpdate(cell));
}
}, },
(err) => Log.error(err), (err) => Log.error(err),
); );
});
_listener.start();
} }
} }

View File

@ -51,10 +51,14 @@ class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
); );
result.fold( result.fold(
(selectOptionContext) => add(SelectionCellEvent.didReceiveOptions( (selectOptionContext) {
if (!isClosed) {
add(SelectionCellEvent.didReceiveOptions(
selectOptionContext.options, selectOptionContext.options,
selectOptionContext.selectOptions, selectOptionContext.selectOptions,
)), ));
}
},
(err) => Log.error(err), (err) => Log.error(err),
); );
} }

View File

@ -9,6 +9,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
import 'field/grid_listenr.dart'; import 'field/grid_listenr.dart';
import 'grid_listener.dart'; import 'grid_listener.dart';
import 'grid_service.dart'; import 'grid_service.dart';
import 'row/row_service.dart';
part 'grid_bloc.freezed.dart'; part 'grid_bloc.freezed.dart';
@ -32,12 +33,16 @@ class GridBloc extends Bloc<GridEvent, GridState> {
createRow: (_CreateRow value) { createRow: (_CreateRow value) {
_gridService.createRow(); _gridService.createRow();
}, },
updateDesc: (_Desc value) {},
didReceiveRowUpdate: (_DidReceiveRowUpdate value) { didReceiveRowUpdate: (_DidReceiveRowUpdate value) {
emit(state.copyWith(rows: value.rows)); emit(state.copyWith(rows: value.rows, listState: value.listState));
}, },
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
emit(state.copyWith(fields: value.fields)); final rows = state.rows.map((row) => row.copyWith(fields: value.fields)).toList();
emit(state.copyWith(
rows: rows,
fields: value.fields,
listState: const GridListState.reload(),
));
}, },
); );
}, },
@ -103,7 +108,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
emit(state.copyWith( emit(state.copyWith(
grid: Some(grid), grid: Some(grid),
fields: fields.items, fields: fields.items,
rows: _buildRows(grid.blockOrders), rows: _buildRows(grid.blockOrders, fields.items),
loadingState: GridLoadingState.finish(left(unit)), loadingState: GridLoadingState.finish(left(unit)),
)); ));
}, },
@ -113,49 +118,65 @@ class GridBloc extends Bloc<GridEvent, GridState> {
} }
void _deleteRows(List<RowOrder> deletedRows) { void _deleteRows(List<RowOrder> deletedRows) {
final List<RowOrder> rows = List.from(state.rows); final List<RowData> rows = [];
rows.retainWhere( final List<Tuple2<int, RowData>> deletedIndex = [];
(row) => deletedRows.where((deletedRow) => deletedRow.rowId == row.rowId).isEmpty, final Map<String, RowOrder> deletedRowMap = {for (var rowOrder in deletedRows) rowOrder.rowId: rowOrder};
); state.rows.asMap().forEach((index, value) {
if (deletedRowMap[value.rowId] == null) {
rows.add(value);
} else {
deletedIndex.add(Tuple2(index, value));
}
});
add(GridEvent.didReceiveRowUpdate(rows)); add(GridEvent.didReceiveRowUpdate(rows, GridListState.delete(deletedIndex)));
} }
void _insertRows(List<IndexRowOrder> createdRows) { void _insertRows(List<IndexRowOrder> createdRows) {
final List<RowOrder> rows = List.from(state.rows); final List<RowData> rows = List.from(state.rows);
List<int> insertIndexs = [];
for (final newRow in createdRows) { for (final newRow in createdRows) {
if (newRow.hasIndex()) { if (newRow.hasIndex()) {
rows.insert(newRow.index, newRow.rowOrder); insertIndexs.add(newRow.index);
rows.insert(newRow.index, _toRowData(newRow.rowOrder));
} else { } else {
rows.add(newRow.rowOrder); insertIndexs.add(rows.length);
rows.add(_toRowData(newRow.rowOrder));
} }
} }
add(GridEvent.didReceiveRowUpdate(rows)); add(GridEvent.didReceiveRowUpdate(rows, GridListState.insert(insertIndexs)));
} }
void _updateRows(List<RowOrder> updatedRows) { void _updateRows(List<RowOrder> updatedRows) {
final List<RowOrder> rows = List.from(state.rows); final List<RowData> rows = List.from(state.rows);
final List<int> updatedIndexs = [];
for (final updatedRow in updatedRows) { for (final updatedRow in updatedRows) {
final index = rows.indexWhere((row) => row.rowId == updatedRow.rowId); final index = rows.indexWhere((row) => row.rowId == updatedRow.rowId);
if (index != -1) { if (index != -1) {
rows.removeAt(index); rows.removeAt(index);
rows.insert(index, updatedRow); rows.insert(index, _toRowData(updatedRow));
updatedIndexs.add(index);
} }
} }
add(GridEvent.didReceiveRowUpdate(rows)); add(GridEvent.didReceiveRowUpdate(rows, const GridListState.reload()));
} }
List<RowOrder> _buildRows(List<GridBlockOrder> blockOrders) { List<RowData> _buildRows(List<GridBlockOrder> blockOrders, List<Field> fields) {
return blockOrders.expand((blockOrder) => blockOrder.rowOrders).toList(); return blockOrders.expand((blockOrder) => blockOrder.rowOrders).map((rowOrder) {
return RowData.fromBlockRow(state.gridId, rowOrder, fields);
}).toList();
}
RowData _toRowData(RowOrder rowOrder) {
return RowData.fromBlockRow(state.gridId, rowOrder, state.fields);
} }
} }
@freezed @freezed
class GridEvent with _$GridEvent { class GridEvent with _$GridEvent {
const factory GridEvent.initial() = InitialGrid; const factory GridEvent.initial() = InitialGrid;
const factory GridEvent.updateDesc(String gridId, String desc) = _Desc;
const factory GridEvent.createRow() = _CreateRow; const factory GridEvent.createRow() = _CreateRow;
const factory GridEvent.didReceiveRowUpdate(List<RowOrder> rows) = _DidReceiveRowUpdate; const factory GridEvent.didReceiveRowUpdate(List<RowData> rows, GridListState listState) = _DidReceiveRowUpdate;
const factory GridEvent.didReceiveFieldUpdate(List<Field> fields) = _DidReceiveFieldUpdate; const factory GridEvent.didReceiveFieldUpdate(List<Field> fields) = _DidReceiveFieldUpdate;
} }
@ -163,18 +184,20 @@ class GridEvent with _$GridEvent {
class GridState with _$GridState { class GridState with _$GridState {
const factory GridState({ const factory GridState({
required String gridId, required String gridId,
required GridLoadingState loadingState,
required List<Field> fields,
required List<RowOrder> rows,
required Option<Grid> grid, required Option<Grid> grid,
required List<Field> fields,
required List<RowData> rows,
required GridLoadingState loadingState,
required GridListState listState,
}) = _GridState; }) = _GridState;
factory GridState.initial(String gridId) => GridState( factory GridState.initial(String gridId) => GridState(
loadingState: const _Loading(),
fields: [], fields: [],
rows: [], rows: [],
grid: none(), grid: none(),
gridId: gridId, gridId: gridId,
loadingState: const _Loading(),
listState: const _Reload(),
); );
} }
@ -183,3 +206,10 @@ class GridLoadingState with _$GridLoadingState {
const factory GridLoadingState.loading() = _Loading; const factory GridLoadingState.loading() = _Loading;
const factory GridLoadingState.finish(Either<Unit, FlowyError> successOrFail) = _Finish; const factory GridLoadingState.finish(Either<Unit, FlowyError> successOrFail) = _Finish;
} }
@freezed
class GridListState with _$GridListState {
const factory GridListState.insert(List<int> indexs) = _Insert;
const factory GridListState.delete(List<Tuple2<int, RowData>> indexs) = _Delete;
const factory GridListState.reload() = _Reload;
}

View File

@ -6,6 +6,7 @@ import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart';
import 'package:flowy_infra_ui/widget/error_page.dart'; import 'package:flowy_infra_ui/widget/error_page.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Field;
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'controller/grid_scroll.dart'; import 'controller/grid_scroll.dart';
@ -90,10 +91,7 @@ class _FlowyGridState extends State<FlowyGrid> {
return const Center(child: CircularProgressIndicator.adaptive()); return const Center(child: CircularProgressIndicator.adaptive());
} }
// _key.currentState.insertItem(index) final child = SizedBox(
final child = BlocBuilder<GridBloc, GridState>(
builder: (context, state) {
return SizedBox(
width: GridLayout.headerWidth(state.fields), width: GridLayout.headerWidth(state.fields),
child: ScrollConfiguration( child: ScrollConfiguration(
behavior: const ScrollBehavior().copyWith(scrollbars: false), behavior: const ScrollBehavior().copyWith(scrollbars: false),
@ -102,15 +100,13 @@ class _FlowyGridState extends State<FlowyGrid> {
controller: _scrollController.verticalController, controller: _scrollController.verticalController,
slivers: [ slivers: [
_renderToolbar(state.gridId), _renderToolbar(state.gridId),
GridHeader(gridId: state.gridId, fields: List.from(state.fields)), _renderGridHeader(state.gridId),
_renderRows(gridId: state.gridId, context: context), _renderRows(gridId: state.gridId, context: context),
const GridFooter(), const GridFooter(),
], ],
), ),
), ),
); );
},
);
return _wrapScrollbar(child); return _wrapScrollbar(child);
}, },
@ -130,12 +126,22 @@ class _FlowyGridState extends State<FlowyGrid> {
); );
} }
Widget _renderGridHeader(String gridId) {
return BlocSelector<GridBloc, GridState, List<Field>>(
selector: (state) => state.fields,
builder: (context, fields) {
return GridHeader(gridId: gridId, fields: List.from(fields));
},
);
}
Widget _renderToolbar(String gridId) { Widget _renderToolbar(String gridId) {
return BlocBuilder<GridBloc, GridState>( return BlocSelector<GridBloc, GridState, List<Field>>(
builder: (context, state) { selector: (state) => state.fields,
builder: (context, fields) {
final toolbarContext = GridToolbarContext( final toolbarContext = GridToolbarContext(
gridId: gridId, gridId: gridId,
fields: state.fields, fields: fields,
); );
return SliverToBoxAdapter( return SliverToBoxAdapter(
@ -146,44 +152,40 @@ class _FlowyGridState extends State<FlowyGrid> {
} }
Widget _renderRows({required String gridId, required BuildContext context}) { Widget _renderRows({required String gridId, required BuildContext context}) {
return BlocBuilder<GridBloc, GridState>( return BlocConsumer<GridBloc, GridState>(
buildWhen: (previous, current) { listener: (context, state) {
final rowChanged = previous.rows.length != current.rows.length; state.listState.map(
// final fieldChanged = previous.fields.length != current.fields.length; insert: (value) {
return rowChanged; for (final index in value.indexs) {
_key.currentState?.insertItem(index);
}
}, },
delete: (value) {
for (final index in value.indexs) {
_key.currentState?.removeItem(index.value1, (context, animation) => _renderRow(index.value2, animation));
}
},
reload: (updatedIndexs) {},
);
},
buildWhen: (previous, current) => false,
builder: (context, state) { builder: (context, state) {
return SliverList( return SliverAnimatedList(
delegate: SliverChildBuilderDelegate( key: _key,
(context, index) { initialItemCount: context.read<GridBloc>().state.rows.length,
final blockRow = context.read<GridBloc>().state.rows[index]; itemBuilder: (BuildContext context, int index, Animation<double> animation) {
final fields = context.read<GridBloc>().state.fields; final rowData = context.read<GridBloc>().state.rows[index];
final rowData = RowData.fromBlockRow(gridId, blockRow, fields); return _renderRow(rowData, animation);
return GridRowWidget(data: rowData, key: ValueKey(rowData.rowId));
}, },
childCount: context.read<GridBloc>().state.rows.length, );
addRepaintBoundaries: true,
addAutomaticKeepAlives: true,
));
// return SliverAnimatedList(
// key: _key,
// initialItemCount: context.read<GridBloc>().state.rows.length,
// itemBuilder: (BuildContext context, int index, Animation<double> animation) {
// final blockRow = context.read<GridBloc>().state.rows[index];
// final fields = context.read<GridBloc>().state.fields;
// final rowData = RowData.fromBlockRow(blockRow, fields);
// return _renderRow(rowData, animation);
// },
// );
}, },
); );
} }
// Widget _renderRow(RowData rowData, Animation<double> animation) { Widget _renderRow(RowData rowData, Animation<double> animation) {
// return SizeTransition( return SizeTransition(
// sizeFactor: animation, sizeFactor: animation,
// child: GridRowWidget(data: rowData, key: ValueKey(rowData.rowId)), child: GridRowWidget(data: rowData, key: ValueKey(rowData.rowId)),
// ); );
// } }
} }

View File

@ -190,11 +190,10 @@ impl std::default::Default for TimeFormat {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::services::field::DateTypeOption;
use crate::services::field::FieldBuilder; use crate::services::field::FieldBuilder;
use crate::services::field::{DateFormat, DateTypeOption, TimeFormat}; use crate::services::row::CellDataOperation;
use crate::services::row::{CellDataOperation, TypeOptionCellData};
use flowy_grid_data_model::entities::FieldType; use flowy_grid_data_model::entities::FieldType;
use strum::IntoEnumIterator;
#[test] #[test]
fn date_description_invalid_input_test() { fn date_description_invalid_input_test() {
@ -206,79 +205,79 @@ mod tests {
); );
} }
#[test] // #[test]
fn date_description_date_format_test() { // fn date_description_date_format_test() {
let mut type_option = DateTypeOption::default(); // let mut type_option = DateTypeOption::default();
let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); // let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
for date_format in DateFormat::iter() { // for date_format in DateFormat::iter() {
type_option.date_format = date_format; // type_option.date_format = date_format;
match date_format { // match date_format {
DateFormat::Friendly => { // DateFormat::Friendly => {
assert_eq!( // assert_eq!(
"Mar 14,2022 17:56".to_owned(), // "Mar 14,2022 17:56".to_owned(),
type_option.decode_cell_data(data("1647251762"), &field_meta) // type_option.decode_cell_data(data("1647251762"), &field_meta)
); // );
assert_eq!( // assert_eq!(
"Mar 14,2022 17:56".to_owned(), // "Mar 14,2022 17:56".to_owned(),
type_option.decode_cell_data(data("Mar 14,2022 17:56"), &field_meta) // type_option.decode_cell_data(data("Mar 14,2022 17:56"), &field_meta)
); // );
} // }
DateFormat::US => { // DateFormat::US => {
assert_eq!( // assert_eq!(
"2022/03/14 17:56".to_owned(), // "2022/03/14 17:56".to_owned(),
type_option.decode_cell_data(data("1647251762"), &field_meta) // type_option.decode_cell_data(data("1647251762"), &field_meta)
); // );
assert_eq!( // assert_eq!(
"2022/03/14 17:56".to_owned(), // "2022/03/14 17:56".to_owned(),
type_option.decode_cell_data(data("2022/03/14 17:56"), &field_meta) // type_option.decode_cell_data(data("2022/03/14 17:56"), &field_meta)
); // );
} // }
DateFormat::ISO => { // DateFormat::ISO => {
assert_eq!( // assert_eq!(
"2022-03-14 17:56".to_owned(), // "2022-03-14 17:56".to_owned(),
type_option.decode_cell_data(data("1647251762"), &field_meta) // type_option.decode_cell_data(data("1647251762"), &field_meta)
); // );
} // }
DateFormat::Local => { // DateFormat::Local => {
assert_eq!( // assert_eq!(
"2022/03/14 17:56".to_owned(), // "2022/03/14 17:56".to_owned(),
type_option.decode_cell_data(data("1647251762"), &field_meta) // type_option.decode_cell_data(data("1647251762"), &field_meta)
); // );
} // }
} // }
} // }
} // }
#[test] // #[test]
fn date_description_time_format_test() { // fn date_description_time_format_test() {
let mut type_option = DateTypeOption::default(); // let mut type_option = DateTypeOption::default();
let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); // let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
for time_format in TimeFormat::iter() { // for time_format in TimeFormat::iter() {
type_option.time_format = time_format; // type_option.time_format = time_format;
match time_format { // match time_format {
TimeFormat::TwentyFourHour => { // TimeFormat::TwentyFourHour => {
assert_eq!( // assert_eq!(
"Mar 14,2022 17:56".to_owned(), // "Mar 14,2022 17:56".to_owned(),
type_option.today_from_timestamp(1647251762) // type_option.today_from_timestamp(1647251762)
); // );
assert_eq!( // assert_eq!(
"Mar 14,2022 17:56".to_owned(), // "Mar 14,2022 17:56".to_owned(),
type_option.decode_cell_data(data("1647251762"), &field_meta) // type_option.decode_cell_data(data("1647251762"), &field_meta)
); // );
} // }
TimeFormat::TwelveHour => { // TimeFormat::TwelveHour => {
assert_eq!( // assert_eq!(
"Mar 14,2022 05:56:02 PM".to_owned(), // "Mar 14,2022 05:56:02 PM".to_owned(),
type_option.today_from_timestamp(1647251762) // type_option.today_from_timestamp(1647251762)
); // );
assert_eq!( // assert_eq!(
"Mar 14,2022 05:56:02 PM".to_owned(), // "Mar 14,2022 05:56:02 PM".to_owned(),
type_option.decode_cell_data(data("1647251762"), &field_meta) // type_option.decode_cell_data(data("1647251762"), &field_meta)
); // );
} // }
} // }
} // }
} // }
#[test] #[test]
#[should_panic] #[should_panic]
@ -287,7 +286,7 @@ mod tests {
type_option.apply_changeset("he", None).unwrap(); type_option.apply_changeset("he", None).unwrap();
} }
fn data(s: &str) -> String { // fn data(s: &str) -> String {
TypeOptionCellData::new(s, FieldType::DateTime).json() // TypeOptionCellData::new(s, FieldType::DateTime).json()
} // }
} }

View File

@ -65,57 +65,53 @@ impl CellDataOperation for RichTextTypeOption {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::services::field::FieldBuilder;
use crate::services::field::*;
use crate::services::row::{CellDataOperation, TypeOptionCellData};
use flowy_grid_data_model::entities::FieldType;
#[test] // #[test]
fn text_description_test() { // fn text_description_test() {
let type_option = RichTextTypeOption::default(); // let type_option = RichTextTypeOption::default();
//
// date // // date
let date_time_field_meta = FieldBuilder::from_field_type(&FieldType::DateTime).build(); // let date_time_field_meta = FieldBuilder::from_field_type(&FieldType::DateTime).build();
let data = TypeOptionCellData::new("1647251762", FieldType::DateTime).json(); // let data = TypeOptionCellData::new("1647251762", FieldType::DateTime).json();
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data, &date_time_field_meta), // type_option.decode_cell_data(data, &date_time_field_meta),
"Mar 14,2022 17:56".to_owned() // "Mar 14,2022 17:56".to_owned()
); // );
//
// Single select // // Single select
let done_option = SelectOption::new("Done"); // let done_option = SelectOption::new("Done");
let done_option_id = done_option.id.clone(); // let done_option_id = done_option.id.clone();
let single_select = SingleSelectTypeOptionBuilder::default().option(done_option); // let single_select = SingleSelectTypeOptionBuilder::default().option(done_option);
let single_select_field_meta = FieldBuilder::new(single_select).build(); // let single_select_field_meta = FieldBuilder::new(single_select).build();
let cell_data = TypeOptionCellData::new(&done_option_id, FieldType::SingleSelect).json(); // let cell_data = TypeOptionCellData::new(&done_option_id, FieldType::SingleSelect).json();
assert_eq!( // assert_eq!(
type_option.decode_cell_data(cell_data, &single_select_field_meta), // type_option.decode_cell_data(cell_data, &single_select_field_meta),
"Done".to_owned() // "Done".to_owned()
); // );
//
// Multiple select // // Multiple select
let google_option = SelectOption::new("Google"); // let google_option = SelectOption::new("Google");
let facebook_option = SelectOption::new("Facebook"); // let facebook_option = SelectOption::new("Facebook");
let ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR); // let ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR);
let cell_data_changeset = SelectOptionCellChangeset::from_insert(&ids).cell_data(); // let cell_data_changeset = SelectOptionCellChangeset::from_insert(&ids).cell_data();
let multi_select = MultiSelectTypeOptionBuilder::default() // let multi_select = MultiSelectTypeOptionBuilder::default()
.option(google_option) // .option(google_option)
.option(facebook_option); // .option(facebook_option);
let multi_select_field_meta = FieldBuilder::new(multi_select).build(); // let multi_select_field_meta = FieldBuilder::new(multi_select).build();
let multi_type_option = MultiSelectTypeOption::from(&multi_select_field_meta); // let multi_type_option = MultiSelectTypeOption::from(&multi_select_field_meta);
let cell_data = multi_type_option.apply_changeset(cell_data_changeset, None).unwrap(); // let cell_data = multi_type_option.apply_changeset(cell_data_changeset, None).unwrap();
assert_eq!( // assert_eq!(
type_option.decode_cell_data(cell_data, &multi_select_field_meta), // type_option.decode_cell_data(cell_data, &multi_select_field_meta),
"Google,Facebook".to_owned() // "Google,Facebook".to_owned()
); // );
//
//Number // //Number
let number = NumberTypeOptionBuilder::default().set_format(NumberFormat::USD); // let number = NumberTypeOptionBuilder::default().set_format(NumberFormat::USD);
let number_field_meta = FieldBuilder::new(number).build(); // let number_field_meta = FieldBuilder::new(number).build();
let data = TypeOptionCellData::new("18443", FieldType::Number).json(); // let data = TypeOptionCellData::new("18443", FieldType::Number).json();
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data, &number_field_meta), // type_option.decode_cell_data(data, &number_field_meta),
"$18,443".to_owned() // "$18,443".to_owned()
); // );
} // }
} }

View File

@ -19,7 +19,7 @@ pub fn create_default_workspace() -> Workspace {
}; };
Workspace { Workspace {
id: workspace_id.to_string(), id: workspace_id,
name, name,
desc, desc,
apps, apps,
@ -38,7 +38,7 @@ fn create_default_app(workspace_id: String, time: chrono::DateTime<Utc>) -> App
}; };
App { App {
id: app_id.to_string(), id: app_id,
workspace_id, workspace_id,
name, name,
desc, desc,
@ -56,7 +56,7 @@ fn create_default_view(app_id: String, time: chrono::DateTime<Utc>) -> View {
let data_type = ViewDataType::TextBlock; let data_type = ViewDataType::TextBlock;
View { View {
id: view_id.to_string(), id: view_id,
belong_to_id: app_id, belong_to_id: app_id,
name, name,
desc, desc,

View File

@ -12,14 +12,3 @@ fn grid_default_serde_test() {
let json = serde_json::to_string(&grid).unwrap(); let json = serde_json::to_string(&grid).unwrap();
assert_eq!(json, r#"{"grid_id":"1","fields":[],"blocks":[]}"#) assert_eq!(json, r#"{"grid_id":"1","fields":[],"blocks":[]}"#)
} }
fn create_field(field_id: &str) -> FieldMeta {
let mut field = FieldMeta::new("Text Field", "", FieldType::RichText);
field.id = field_id.to_string();
field
}
#[allow(dead_code)]
fn uuid() -> String {
uuid::Uuid::new_v4().to_string()
}

View File

@ -163,10 +163,10 @@ impl GridBlockMetaPad {
None => Ok(None), None => Ok(None),
Some(delta) => { Some(delta) => {
tracing::debug!("[GridBlockMeta] Composing delta {}", delta.to_delta_str()); tracing::debug!("[GridBlockMeta] Composing delta {}", delta.to_delta_str());
tracing::debug!( // tracing::debug!(
"[GridBlockMeta] current delta: {}", // "[GridBlockMeta] current delta: {}",
self.delta.to_str().unwrap_or_else(|_| "".to_string()) // self.delta.to_str().unwrap_or_else(|_| "".to_string())
); // );
self.delta = self.delta.compose(&delta)?; self.delta = self.delta.compose(&delta)?;
Ok(Some(GridBlockMetaChange { delta, md5: self.md5() })) Ok(Some(GridBlockMetaChange { delta, md5: self.md5() }))
} }