Merge pull request #978 from AppFlowy-IO/feat/support_group_checkbox

chore: support group by checkbox field
This commit is contained in:
Nathan.fooo 2022-09-05 12:44:02 +08:00 committed by GitHub
commit d9aba78727
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 247 additions and 107 deletions

View File

@ -1,4 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:collection';
import 'package:app_flowy/plugins/grid/application/block/block_cache.dart'; import 'package:app_flowy/plugins/grid/application/block/block_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart'; import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
@ -12,7 +14,6 @@ import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:collection';
import 'board_data_controller.dart'; import 'board_data_controller.dart';
import 'group_controller.dart'; import 'group_controller.dart';
@ -164,12 +165,17 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
boardController.clear(); boardController.clear();
// //
List<AFBoardColumnData> columns = groups.map((group) { List<AFBoardColumnData> columns = groups
.where((group) => fieldController.getField(group.fieldId) != null)
.map((group) {
return AFBoardColumnData( return AFBoardColumnData(
id: group.groupId, id: group.groupId,
name: group.desc, name: group.desc,
items: _buildRows(group), items: _buildRows(group),
customData: group, customData: BoardCustomData(
group: group,
fieldContext: fieldController.getField(group.fieldId)!,
),
); );
}).toList(); }).toList();
boardController.addColumns(columns); boardController.addColumns(columns);
@ -177,6 +183,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
for (final group in groups) { for (final group in groups) {
final delegate = GroupControllerDelegateImpl( final delegate = GroupControllerDelegateImpl(
controller: boardController, controller: boardController,
fieldController: fieldController,
onNewColumnItem: (groupId, row, index) { onNewColumnItem: (groupId, row, index) {
add(BoardEvent.didCreateRow(groupId, row, index)); add(BoardEvent.didCreateRow(groupId, row, index));
}, },
@ -238,10 +245,8 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
List<AFColumnItem> _buildRows(GroupPB group) { List<AFColumnItem> _buildRows(GroupPB group) {
final items = group.rows.map((row) { final items = group.rows.map((row) {
return BoardColumnItem( final fieldContext = fieldController.getField(group.fieldId);
row: row, return BoardColumnItem(row: row, fieldContext: fieldContext!);
fieldId: group.fieldId,
);
}).toList(); }).toList();
return <AFColumnItem>[...items]; return <AFColumnItem>[...items];
@ -332,15 +337,11 @@ class GridFieldEquatable extends Equatable {
class BoardColumnItem extends AFColumnItem { class BoardColumnItem extends AFColumnItem {
final RowPB row; final RowPB row;
final GridFieldContext fieldContext;
final String fieldId;
final bool requestFocus;
BoardColumnItem({ BoardColumnItem({
required this.row, required this.row,
required this.fieldId, required this.fieldContext,
this.requestFocus = false,
}); });
@override @override
@ -348,24 +349,29 @@ class BoardColumnItem extends AFColumnItem {
} }
class GroupControllerDelegateImpl extends GroupControllerDelegate { class GroupControllerDelegateImpl extends GroupControllerDelegate {
final GridFieldController fieldController;
final AFBoardDataController controller; final AFBoardDataController controller;
final void Function(String, RowPB, int?) onNewColumnItem; final void Function(String, RowPB, int?) onNewColumnItem;
GroupControllerDelegateImpl({ GroupControllerDelegateImpl({
required this.controller, required this.controller,
required this.fieldController,
required this.onNewColumnItem, required this.onNewColumnItem,
}); });
@override @override
void insertRow(GroupPB group, RowPB row, int? index) { void insertRow(GroupPB group, RowPB row, int? index) {
final fieldContext = fieldController.getField(group.fieldId);
if (fieldContext == null) {
Log.warn("FieldContext should not be null");
return;
}
if (index != null) { if (index != null) {
final item = BoardColumnItem(row: row, fieldId: group.fieldId); final item = BoardColumnItem(row: row, fieldContext: fieldContext);
controller.insertColumnItem(group.groupId, index, item); controller.insertColumnItem(group.groupId, index, item);
} else { } else {
final item = BoardColumnItem( final item = BoardColumnItem(row: row, fieldContext: fieldContext);
row: row,
fieldId: group.fieldId,
);
controller.addColumnItem(group.groupId, item); controller.addColumnItem(group.groupId, item);
} }
} }
@ -377,22 +383,25 @@ class GroupControllerDelegateImpl extends GroupControllerDelegate {
@override @override
void updateRow(GroupPB group, RowPB row) { void updateRow(GroupPB group, RowPB row) {
final fieldContext = fieldController.getField(group.fieldId);
if (fieldContext == null) {
Log.warn("FieldContext should not be null");
return;
}
controller.updateColumnItem( controller.updateColumnItem(
group.groupId, group.groupId,
BoardColumnItem( BoardColumnItem(row: row, fieldContext: fieldContext),
row: row,
fieldId: group.fieldId,
),
); );
} }
@override @override
void addNewRow(GroupPB group, RowPB row, int? index) { void addNewRow(GroupPB group, RowPB row, int? index) {
final item = BoardColumnItem( final fieldContext = fieldController.getField(group.fieldId);
row: row, if (fieldContext == null) {
fieldId: group.fieldId, Log.warn("FieldContext should not be null");
requestFocus: true, return;
); }
final item = BoardColumnItem(row: row, fieldContext: fieldContext);
if (index != null) { if (index != null) {
controller.insertColumnItem(group.groupId, index, item); controller.insertColumnItem(group.groupId, index, item);
@ -414,3 +423,29 @@ class BoardEditingRow {
required this.index, required this.index,
}); });
} }
class BoardCustomData {
final GroupPB group;
final GridFieldContext fieldContext;
BoardCustomData({
required this.group,
required this.fieldContext,
});
CheckboxGroup? asCheckboxGroup() {
if (fieldType != FieldType.Checkbox) return null;
return CheckboxGroup(group);
}
FieldType get fieldType => fieldContext.fieldType;
}
class CheckboxGroup {
final GroupPB group;
CheckboxGroup(this.group);
// Hardcode value: "Yes" that equal to the value defined in Rust
// pub const CHECK: &str = "Yes";
bool get isCheck => group.groupId == "Yes";
}

View File

@ -17,7 +17,7 @@ import 'package:flowy_infra_ui/style_widget/text.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/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/group.pbserver.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import '../../grid/application/row/row_cache.dart'; import '../../grid/application/row/row_cache.dart';
@ -36,8 +36,7 @@ class BoardPage extends StatelessWidget {
create: (context) => create: (context) =>
BoardBloc(view: view)..add(const BoardEvent.initial()), BoardBloc(view: view)..add(const BoardEvent.initial()),
child: BlocBuilder<BoardBloc, BoardState>( child: BlocBuilder<BoardBloc, BoardState>(
buildWhen: (previous, current) => buildWhen: (p, c) => p.loadingState != c.loadingState,
previous.loadingState != current.loadingState,
builder: (context, state) { builder: (context, state) {
return state.loadingState.map( return state.loadingState.map(
loading: (_) => loading: (_) =>
@ -84,36 +83,15 @@ class _BoardContentState extends State<BoardContent> {
child: BlocBuilder<BoardBloc, BoardState>( child: BlocBuilder<BoardBloc, BoardState>(
buildWhen: (previous, current) => previous.groupIds != current.groupIds, buildWhen: (previous, current) => previous.groupIds != current.groupIds,
builder: (context, state) { builder: (context, state) {
final theme = context.read<AppTheme>(); final column = Column(
children: [const _ToolbarBlocAdaptor(), _buildBoard(context)],
);
return Container( return Container(
color: theme.surface, color: context.read<AppTheme>().surface,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20), padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column( child: column,
children: [
const _ToolbarBlocAdaptor(),
Expanded(
child: AFBoard(
key: UniqueKey(),
scrollManager: scrollManager,
scrollController: scrollController,
dataController: context.read<BoardBloc>().boardController,
headerBuilder: _buildHeader,
footBuilder: _buildFooter,
cardBuilder: (_, column, columnItem) => _buildCard(
context,
column,
columnItem,
),
columnConstraints:
const BoxConstraints.tightFor(width: 300),
config: AFBoardConfig(
columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
),
),
),
],
),
), ),
); );
}, },
@ -121,6 +99,27 @@ class _BoardContentState extends State<BoardContent> {
); );
} }
Expanded _buildBoard(BuildContext context) {
return Expanded(
child: AFBoard(
scrollManager: scrollManager,
scrollController: scrollController,
dataController: context.read<BoardBloc>().boardController,
headerBuilder: _buildHeader,
footBuilder: _buildFooter,
cardBuilder: (_, column, columnItem) => _buildCard(
context,
column,
columnItem,
),
columnConstraints: const BoxConstraints.tightFor(width: 300),
config: AFBoardConfig(
columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
),
),
);
}
void _handleEditState(BoardState state, BuildContext context) { void _handleEditState(BoardState state, BuildContext context) {
state.editingRow.fold( state.editingRow.fold(
() => null, () => null,
@ -152,6 +151,7 @@ class _BoardContentState extends State<BoardContent> {
BuildContext context, BuildContext context,
AFBoardColumnData columnData, AFBoardColumnData columnData,
) { ) {
final boardCustomData = columnData.customData as BoardCustomData;
return AppFlowyColumnHeader( return AppFlowyColumnHeader(
title: Flexible( title: Flexible(
fit: FlexFit.tight, fit: FlexFit.tight,
@ -162,6 +162,7 @@ class _BoardContentState extends State<BoardContent> {
color: context.read<AppTheme>().textColor, color: context.read<AppTheme>().textColor,
), ),
), ),
icon: _buildHeaderIcon(boardCustomData),
addIcon: SizedBox( addIcon: SizedBox(
height: 20, height: 20,
width: 20, width: 20,
@ -181,7 +182,9 @@ class _BoardContentState extends State<BoardContent> {
} }
Widget _buildFooter(BuildContext context, AFBoardColumnData columnData) { Widget _buildFooter(BuildContext context, AFBoardColumnData columnData) {
final group = columnData.customData as GroupPB; final boardCustomData = columnData.customData as BoardCustomData;
final group = boardCustomData.group;
if (group.isDefault) { if (group.isDefault) {
return const SizedBox(); return const SizedBox();
} else { } else {
@ -246,7 +249,7 @@ class _BoardContentState extends State<BoardContent> {
child: BoardCard( child: BoardCard(
gridId: gridId, gridId: gridId,
groupId: column.id, groupId: column.id,
fieldId: boardColumnItem.fieldId, fieldId: boardColumnItem.fieldContext.id,
isEditing: isEditing, isEditing: isEditing,
cellBuilder: cellBuilder, cellBuilder: cellBuilder,
dataController: cardController, dataController: cardController,
@ -319,3 +322,38 @@ extension HexColor on Color {
return Color(int.parse(buffer.toString(), radix: 16)); return Color(int.parse(buffer.toString(), radix: 16));
} }
} }
Widget? _buildHeaderIcon(BoardCustomData customData) {
Widget? widget;
switch (customData.fieldType) {
case FieldType.Checkbox:
final group = customData.asCheckboxGroup()!;
if (group.isCheck) {
widget = svgWidget('editor/editor_check');
} else {
widget = svgWidget('editor/editor_uncheck');
}
break;
case FieldType.DateTime:
break;
case FieldType.MultiSelect:
break;
case FieldType.Number:
break;
case FieldType.RichText:
break;
case FieldType.SingleSelect:
break;
case FieldType.URL:
break;
}
if (widget != null) {
widget = SizedBox(
width: 20,
height: 20,
child: widget,
);
}
return widget;
}

View File

@ -7,6 +7,7 @@ import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import '../row/row_cache.dart'; import '../row/row_cache.dart';
@ -35,12 +36,12 @@ class GridFieldController {
final SettingListener _settingListener; final SettingListener _settingListener;
final Map<OnReceiveFields, VoidCallback> _fieldCallbackMap = {}; final Map<OnReceiveFields, VoidCallback> _fieldCallbackMap = {};
final Map<OnChangeset, OnChangeset> _changesetCallbackMap = {}; final Map<OnChangeset, OnChangeset> _changesetCallbackMap = {};
_GridFieldNotifier? _fieldNotifier = _GridFieldNotifier();
List<String> _groupFieldIds = [];
final GridFFIService _gridFFIService; final GridFFIService _gridFFIService;
final SettingFFIService _settingFFIService; final SettingFFIService _settingFFIService;
_GridFieldNotifier? _fieldNotifier = _GridFieldNotifier();
final Map<String, GridGroupConfigurationPB> _configurationByFieldId = {};
List<GridFieldContext> get fieldContexts => List<GridFieldContext> get fieldContexts =>
[..._fieldNotifier?.fieldContexts ?? []]; [..._fieldNotifier?.fieldContexts ?? []];
@ -67,31 +68,43 @@ class GridFieldController {
//Listen on setting changes //Listen on setting changes
_settingListener.start(onSettingUpdated: (result) { _settingListener.start(onSettingUpdated: (result) {
result.fold( result.fold(
(setting) => _updateFieldsWhenSettingChanged(setting), (setting) => _updateGroupConfiguration(setting),
(r) => Log.error(r), (r) => Log.error(r),
); );
}); });
_settingFFIService.getSetting().then((result) { _settingFFIService.getSetting().then((result) {
result.fold( result.fold(
(setting) => _updateFieldsWhenSettingChanged(setting), (setting) => _updateGroupConfiguration(setting),
(err) => Log.error(err), (err) => Log.error(err),
); );
}); });
} }
void _updateFieldsWhenSettingChanged(GridSettingPB setting) { GridFieldContext? getField(String fieldId) {
_groupFieldIds = setting.groupConfigurations.items final fields = _fieldNotifier?.fieldContexts
.map((item) => item.groupFieldId) .where(
(element) => element.id == fieldId,
)
.toList(); .toList();
if (fields?.isEmpty ?? true) {
return null;
}
return fields!.first;
}
void _updateGroupConfiguration(GridSettingPB setting) {
_configurationByFieldId.clear();
for (final configuration in setting.groupConfigurations.items) {
_configurationByFieldId[configuration.fieldId] = configuration;
}
_updateFieldContexts(); _updateFieldContexts();
} }
void _updateFieldContexts() { void _updateFieldContexts() {
if (_fieldNotifier != null) { if (_fieldNotifier != null) {
for (var field in _fieldNotifier!.fieldContexts) { for (var field in _fieldNotifier!.fieldContexts) {
if (_groupFieldIds.contains(field.id)) { if (_configurationByFieldId[field.id] != null) {
field._isGroupField = true; field._isGroupField = true;
} else { } else {
field._isGroupField = false; field._isGroupField = false;

View File

@ -31,7 +31,7 @@ typedef AFBoardColumnCardBuilder = Widget Function(
typedef AFBoardColumnHeaderBuilder = Widget? Function( typedef AFBoardColumnHeaderBuilder = Widget? Function(
BuildContext context, BuildContext context,
AFBoardColumnData headerData, AFBoardColumnData columnData,
); );
typedef AFBoardColumnFooterBuilder = Widget Function( typedef AFBoardColumnFooterBuilder = Widget Function(

View File

@ -44,14 +44,14 @@ pub struct GridGroupConfigurationPB {
pub id: String, pub id: String,
#[pb(index = 2)] #[pb(index = 2)]
pub group_field_id: String, pub field_id: String,
} }
impl std::convert::From<&GroupConfigurationRevision> for GridGroupConfigurationPB { impl std::convert::From<&GroupConfigurationRevision> for GridGroupConfigurationPB {
fn from(rev: &GroupConfigurationRevision) -> Self { fn from(rev: &GroupConfigurationRevision) -> Self {
GridGroupConfigurationPB { GridGroupConfigurationPB {
id: rev.id.clone(), id: rev.id.clone(),
group_field_id: rev.field_id.clone(), field_id: rev.field_id.clone(),
} }
} }
} }

View File

@ -182,7 +182,6 @@ pub fn delete_select_option_cell(option_id: String, field_rev: &FieldRevision) -
CellRevision::new(data) CellRevision::new(data)
} }
/// If the cell data is not String type, it should impl this trait.
/// Deserialize the String into cell specific data type. /// Deserialize the String into cell specific data type.
pub trait FromCellString { pub trait FromCellString {
fn from_cell_str(s: &str) -> FlowyResult<Self> fn from_cell_str(s: &str) -> FlowyResult<Self>

View File

@ -1,13 +1,16 @@
use crate::entities::GroupChangesetPB; use crate::entities::GroupChangesetPB;
use crate::services::group::controller::MoveGroupRowContext; use crate::services::group::controller::MoveGroupRowContext;
use flowy_grid_data_model::revision::RowRevision; use flowy_grid_data_model::revision::{CellRevision, RowRevision};
pub trait GroupAction: Send + Sync { pub trait GroupAction: Send + Sync {
type CellDataType; type CellDataType;
fn default_cell_rev(&self) -> Option<CellRevision> {
None
}
fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool; fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool;
fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB>; fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB>;
fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB>; fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB>;
fn move_row(&mut self, cell_data: &Self::CellDataType, context: MoveGroupRowContext) -> Vec<GroupChangesetPB>; fn move_row(&mut self, cell_data: &Self::CellDataType, context: MoveGroupRowContext) -> Vec<GroupChangesetPB>;
} }

View File

@ -7,7 +7,6 @@ use flowy_error::FlowyResult;
use flowy_grid_data_model::revision::{ use flowy_grid_data_model::revision::{
FieldRevision, GroupConfigurationContentSerde, GroupRevision, RowChangeset, RowRevision, TypeOptionDataDeserializer, FieldRevision, GroupConfigurationContentSerde, GroupRevision, RowChangeset, RowRevision, TypeOptionDataDeserializer,
}; };
use std::marker::PhantomData; use std::marker::PhantomData;
use std::sync::Arc; use std::sync::Arc;
@ -193,9 +192,14 @@ where
#[tracing::instrument(level = "trace", skip_all, fields(row_count=%row_revs.len(), group_result))] #[tracing::instrument(level = "trace", skip_all, fields(row_count=%row_revs.len(), group_result))]
fn fill_groups(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()> { fn fill_groups(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()> {
for row_rev in row_revs { for row_rev in row_revs {
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { let cell_rev = match row_rev.cells.get(&self.field_id) {
None => self.default_cell_rev(),
Some(cell_rev) => Some(cell_rev.clone()),
};
if let Some(cell_rev) = cell_rev {
let mut grouped_rows: Vec<GroupedRow> = vec![]; let mut grouped_rows: Vec<GroupedRow> = vec![];
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev); let cell_bytes = decode_any_cell_data(cell_rev.data, field_rev);
let cell_data = cell_bytes.parser::<P>()?; let cell_data = cell_bytes.parser::<P>()?;
for group in self.group_ctx.concrete_groups() { for group in self.group_ctx.concrete_groups() {
if self.can_group(&group.filter_content, &cell_data) { if self.can_group(&group.filter_content, &cell_data) {

View File

@ -1,4 +1,4 @@
use crate::entities::GroupChangesetPB; use crate::entities::{GroupChangesetPB, InsertedRowPB, RowPB};
use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK}; use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK};
use crate::services::group::action::GroupAction; use crate::services::group::action::GroupAction;
use crate::services::group::configuration::GroupContext; use crate::services::group::configuration::GroupContext;
@ -6,8 +6,11 @@ use crate::services::group::controller::{
GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext, GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext,
}; };
use crate::services::group::GeneratedGroup; use crate::services::cell::insert_checkbox_cell;
use flowy_grid_data_model::revision::{CheckboxGroupConfigurationRevision, FieldRevision, GroupRevision, RowRevision}; use crate::services::group::{move_group_row, GeneratedGroup};
use flowy_grid_data_model::revision::{
CellRevision, CheckboxGroupConfigurationRevision, FieldRevision, GroupRevision, RowRevision,
};
pub type CheckboxGroupController = GenericGroupController< pub type CheckboxGroupController = GenericGroupController<
CheckboxGroupConfigurationRevision, CheckboxGroupConfigurationRevision,
@ -20,30 +23,79 @@ pub type CheckboxGroupContext = GroupContext<CheckboxGroupConfigurationRevision>
impl GroupAction for CheckboxGroupController { impl GroupAction for CheckboxGroupController {
type CellDataType = CheckboxCellData; type CellDataType = CheckboxCellData;
fn can_group(&self, _content: &str, _cell_data: &Self::CellDataType) -> bool { fn default_cell_rev(&self) -> Option<CellRevision> {
false Some(CellRevision::new(UNCHECK.to_string()))
} }
fn add_row_if_match(&mut self, _row_rev: &RowRevision, _cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> { fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool {
todo!() return if cell_data.is_check() {
content == CHECK
} else {
content == UNCHECK
};
} }
fn remove_row_if_match( fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
&mut self, let mut changesets = vec![];
_row_rev: &RowRevision, self.group_ctx.iter_mut_groups(|group| {
_cell_data: &Self::CellDataType, let mut changeset = GroupChangesetPB::new(group.id.clone());
) -> Vec<GroupChangesetPB> { let is_contained = group.contains_row(&row_rev.id);
todo!() if group.id == CHECK && cell_data.is_check() {
if !is_contained {
let row_pb = RowPB::from(row_rev);
changeset.inserted_rows.push(InsertedRowPB::new(row_pb.clone()));
group.add_row(row_pb);
}
} else {
if is_contained {
changeset.deleted_rows.push(row_rev.id.clone());
group.remove_row(&row_rev.id);
}
}
if !changeset.is_empty() {
changesets.push(changeset);
}
});
changesets
} }
fn move_row(&mut self, _cell_data: &Self::CellDataType, _context: MoveGroupRowContext) -> Vec<GroupChangesetPB> { fn remove_row_if_match(&mut self, row_rev: &RowRevision, _cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
todo!() let mut changesets = vec![];
self.group_ctx.iter_mut_groups(|group| {
let mut changeset = GroupChangesetPB::new(group.id.clone());
if group.contains_row(&row_rev.id) {
changeset.deleted_rows.push(row_rev.id.clone());
group.remove_row(&row_rev.id);
}
if !changeset.is_empty() {
changesets.push(changeset);
}
});
changesets
}
fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
let mut group_changeset = vec![];
self.group_ctx.iter_mut_groups(|group| {
if let Some(changeset) = move_group_row(group, &mut context) {
group_changeset.push(changeset);
}
});
group_changeset
} }
} }
impl GroupController for CheckboxGroupController { impl GroupController for CheckboxGroupController {
fn will_create_row(&mut self, _row_rev: &mut RowRevision, _field_rev: &FieldRevision, _group_id: &str) { fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) {
todo!() match self.group_ctx.get_group(group_id) {
None => tracing::warn!("Can not find the group: {}", group_id),
Some((_, group)) => {
let is_check = group.id == CHECK;
let cell_rev = insert_checkbox_cell(is_check, field_rev);
row_rev.cells.insert(field_rev.id.clone(), cell_rev);
}
}
} }
} }
@ -58,13 +110,13 @@ impl GroupGenerator for CheckboxGroupGenerator {
_type_option: &Option<Self::TypeOptionType>, _type_option: &Option<Self::TypeOptionType>,
) -> Vec<GeneratedGroup> { ) -> Vec<GeneratedGroup> {
let check_group = GeneratedGroup { let check_group = GeneratedGroup {
group_rev: GroupRevision::new("true".to_string(), CHECK.to_string()), group_rev: GroupRevision::new(CHECK.to_string(), "".to_string()),
filter_content: "".to_string(), filter_content: CHECK.to_string(),
}; };
let uncheck_group = GeneratedGroup { let uncheck_group = GeneratedGroup {
group_rev: GroupRevision::new("false".to_string(), UNCHECK.to_string()), group_rev: GroupRevision::new(UNCHECK.to_string(), "".to_string()),
filter_content: "".to_string(), filter_content: UNCHECK.to_string(),
}; };
vec![check_group, uncheck_group] vec![check_group, uncheck_group]
} }

View File

@ -46,10 +46,10 @@ impl GroupAction for MultiSelectGroupController {
changesets changesets
} }
fn move_row(&mut self, cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> { fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
let mut group_changeset = vec![]; let mut group_changeset = vec![];
self.group_ctx.iter_mut_groups(|group| { self.group_ctx.iter_mut_groups(|group| {
if let Some(changeset) = move_select_option_row(group, cell_data, &mut context) { if let Some(changeset) = move_group_row(group, &mut context) {
group_changeset.push(changeset); group_changeset.push(changeset);
} }
}); });

View File

@ -46,10 +46,10 @@ impl GroupAction for SingleSelectGroupController {
changesets changesets
} }
fn move_row(&mut self, cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> { fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
let mut group_changeset = vec![]; let mut group_changeset = vec![];
self.group_ctx.iter_mut_groups(|group| { self.group_ctx.iter_mut_groups(|group| {
if let Some(changeset) = move_select_option_row(group, cell_data, &mut context) { if let Some(changeset) = move_group_row(group, &mut context) {
group_changeset.push(changeset); group_changeset.push(changeset);
} }
}); });

View File

@ -62,11 +62,7 @@ pub fn remove_select_option_row(
} }
} }
pub fn move_select_option_row( pub fn move_group_row(group: &mut Group, context: &mut MoveGroupRowContext) -> Option<GroupChangesetPB> {
group: &mut Group,
_cell_data: &SelectOptionCellDataPB,
context: &mut MoveGroupRowContext,
) -> Option<GroupChangesetPB> {
let mut changeset = GroupChangesetPB::new(group.id.clone()); let mut changeset = GroupChangesetPB::new(group.id.clone());
let MoveGroupRowContext { let MoveGroupRowContext {
row_rev, row_rev,