mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge pull request #934 from AppFlowy-IO/feat/board_default_column
feat: support board no status column
This commit is contained in:
commit
ee1f9d4335
@ -221,5 +221,10 @@
|
||||
"timeHintTextInTwelveHour": "12:00 AM",
|
||||
"timeHintTextInTwentyFourHour": "12:00"
|
||||
}
|
||||
},
|
||||
"board": {
|
||||
"column": {
|
||||
"create_new_card": "New"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||
import 'package:app_flowy/plugins/board/application/card/card_data_controller.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
|
||||
@ -9,12 +10,14 @@ import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart'
|
||||
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/cell_builder.dart';
|
||||
import 'package:app_flowy/plugins/grid/presentation/widgets/row/row_detail.dart';
|
||||
import 'package:appflowy_board/appflowy_board.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/image.dart';
|
||||
import 'package:flowy_infra/theme.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.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-grid/block_entities.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/group.pbserver.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../../grid/application/row/row_cache.dart';
|
||||
@ -109,7 +112,7 @@ class _BoardContentState extends State<BoardContent> {
|
||||
column,
|
||||
columnItem,
|
||||
),
|
||||
columnConstraints: const BoxConstraints.tightFor(width: 240),
|
||||
columnConstraints: const BoxConstraints.tightFor(width: 300),
|
||||
config: AFBoardConfig(
|
||||
columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
||||
),
|
||||
@ -154,7 +157,11 @@ class _BoardContentState extends State<BoardContent> {
|
||||
}
|
||||
|
||||
Widget _buildFooter(BuildContext context, AFBoardColumnData columnData) {
|
||||
return AppFlowyColumnFooter(
|
||||
final group = columnData.customData as GroupPB;
|
||||
if (group.isDefault) {
|
||||
return const SizedBox();
|
||||
} else {
|
||||
return AppFlowyColumnFooter(
|
||||
icon: SizedBox(
|
||||
height: 20,
|
||||
width: 20,
|
||||
@ -164,7 +171,7 @@ class _BoardContentState extends State<BoardContent> {
|
||||
),
|
||||
),
|
||||
title: FlowyText.medium(
|
||||
"New",
|
||||
LocaleKeys.board_column_create_new_card.tr(),
|
||||
fontSize: 14,
|
||||
color: context.read<AppTheme>().textColor,
|
||||
),
|
||||
@ -172,7 +179,9 @@ class _BoardContentState extends State<BoardContent> {
|
||||
margin: config.footerPadding,
|
||||
onAddButtonClick: () {
|
||||
context.read<BoardBloc>().add(BoardEvent.createRow(columnData.id));
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildCard(
|
||||
|
@ -93,14 +93,15 @@ BoxDecoration _makeBoxDecoration(BuildContext context) {
|
||||
final theme = context.read<AppTheme>();
|
||||
final borderSide = BorderSide(color: theme.shader6, width: 1.0);
|
||||
return BoxDecoration(
|
||||
color: theme.surface,
|
||||
color: Colors.transparent,
|
||||
border: Border.fromBorderSide(borderSide),
|
||||
boxShadow: [
|
||||
boxShadow: const [
|
||||
BoxShadow(
|
||||
color: theme.shader6,
|
||||
spreadRadius: 0,
|
||||
blurRadius: 2,
|
||||
offset: Offset.zero)
|
||||
color: Colors.transparent,
|
||||
spreadRadius: 0,
|
||||
blurRadius: 2,
|
||||
offset: Offset.zero,
|
||||
)
|
||||
],
|
||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||
);
|
||||
@ -120,8 +121,9 @@ class _CardEnterRegion extends StatelessWidget {
|
||||
builder: (context, onEnter, _) {
|
||||
List<Widget> children = [child];
|
||||
if (onEnter) {
|
||||
children.add(CardAccessoryContainer(accessories: accessories)
|
||||
.positioned(right: 0));
|
||||
children.add(CardAccessoryContainer(
|
||||
accessories: accessories,
|
||||
).positioned(right: 0));
|
||||
}
|
||||
|
||||
return MouseRegion(
|
||||
|
@ -81,6 +81,9 @@ pub struct GroupPB {
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub rows: Vec<RowPB>,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub is_default: bool,
|
||||
}
|
||||
|
||||
impl std::convert::From<Group> for GroupPB {
|
||||
@ -90,6 +93,7 @@ impl std::convert::From<Group> for GroupPB {
|
||||
group_id: group.id,
|
||||
desc: group.name,
|
||||
rows: group.rows,
|
||||
is_default: group.is_default,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -176,6 +176,12 @@ pub fn insert_select_option_cell(option_id: String, field_rev: &FieldRevision) -
|
||||
CellRevision::new(data)
|
||||
}
|
||||
|
||||
pub fn delete_select_option_cell(option_id: String, field_rev: &FieldRevision) -> CellRevision {
|
||||
let cell_data = SelectOptionCellChangeset::from_delete(&option_id).to_str();
|
||||
let data = apply_cell_data_changeset(cell_data, None, field_rev).unwrap();
|
||||
CellRevision::new(data)
|
||||
}
|
||||
|
||||
/// If the cell data is not String type, it should impl this trait.
|
||||
/// Deserialize the String into cell specific data type.
|
||||
pub trait FromCellString {
|
||||
|
@ -142,7 +142,7 @@ impl GridViewManager {
|
||||
.move_group_row(&row_rev, &mut row_changeset, &to_group_id, to_row_id.clone())
|
||||
.await;
|
||||
|
||||
if row_changeset.is_empty() == false {
|
||||
if !row_changeset.is_empty() {
|
||||
with_row_changeset(row_changeset).await;
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,10 @@ impl<T> std::fmt::Display for GenericGroupConfiguration<T> {
|
||||
self.groups_map.iter().for_each(|(_, group)| {
|
||||
let _ = f.write_fmt(format_args!("Group:{} has {} rows \n", group.id, group.rows.len()));
|
||||
});
|
||||
let _ = f.write_fmt(format_args!(
|
||||
"Default group has {} rows \n",
|
||||
self.default_group.rows.len()
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -41,6 +45,8 @@ pub struct GenericGroupConfiguration<C> {
|
||||
configuration_content: PhantomData<C>,
|
||||
field_rev: Arc<FieldRevision>,
|
||||
groups_map: IndexMap<String, Group>,
|
||||
/// default_group is used to store the rows that don't belong to any groups.
|
||||
default_group: Group,
|
||||
writer: Arc<dyn GroupConfigurationWriter>,
|
||||
}
|
||||
|
||||
@ -55,6 +61,15 @@ where
|
||||
reader: Arc<dyn GroupConfigurationReader>,
|
||||
writer: Arc<dyn GroupConfigurationWriter>,
|
||||
) -> FlowyResult<Self> {
|
||||
let default_group_id = format!("{}_default_group", view_id);
|
||||
let default_group = Group {
|
||||
id: default_group_id,
|
||||
field_id: field_rev.id.clone(),
|
||||
name: format!("No {}", field_rev.name),
|
||||
is_default: true,
|
||||
rows: vec![],
|
||||
content: "".to_string(),
|
||||
};
|
||||
let configuration = match reader.get_group_configuration(field_rev.clone()).await {
|
||||
None => {
|
||||
let default_group_configuration = default_group_configuration(&field_rev);
|
||||
@ -71,6 +86,7 @@ where
|
||||
view_id,
|
||||
field_rev,
|
||||
groups_map: IndexMap::new(),
|
||||
default_group,
|
||||
writer,
|
||||
configuration,
|
||||
configuration_content: PhantomData,
|
||||
@ -82,7 +98,9 @@ where
|
||||
}
|
||||
|
||||
pub(crate) fn clone_groups(&self) -> Vec<Group> {
|
||||
self.groups_map.values().cloned().collect()
|
||||
let mut groups: Vec<Group> = self.groups_map.values().cloned().collect();
|
||||
groups.push(self.default_group.clone());
|
||||
groups
|
||||
}
|
||||
|
||||
pub(crate) fn merge_groups(&mut self, groups: Vec<Group>) -> FlowyResult<Option<GroupViewChangesetPB>> {
|
||||
@ -160,6 +178,10 @@ where
|
||||
self.groups_map.get_mut(group_id)
|
||||
}
|
||||
|
||||
pub(crate) fn get_mut_default_group(&mut self) -> &mut Group {
|
||||
&mut self.default_group
|
||||
}
|
||||
|
||||
pub(crate) fn move_group(&mut self, from_id: &str, to_id: &str) -> FlowyResult<()> {
|
||||
let from_index = self.groups_map.get_index_of(from_id);
|
||||
let to_index = self.groups_map.get_index_of(to_id);
|
||||
@ -263,7 +285,7 @@ fn merge_groups(old_groups: &[GroupRevision], groups: Vec<Group>) -> MergeGroupR
|
||||
}
|
||||
|
||||
// Find out the new groups
|
||||
let new_groups = group_map.into_values().collect::<Vec<Group>>();
|
||||
let new_groups = group_map.into_values();
|
||||
for (index, group) in new_groups.into_iter().enumerate() {
|
||||
merge_result.add_insert_group(index, group);
|
||||
}
|
||||
@ -291,7 +313,7 @@ impl MergeGroupResult {
|
||||
}
|
||||
|
||||
fn add_group(&mut self, group: Group) {
|
||||
self.groups.push(group.clone());
|
||||
self.groups.push(group);
|
||||
}
|
||||
|
||||
fn add_insert_group(&mut self, index: usize, group: Group) {
|
||||
@ -309,11 +331,10 @@ fn make_group_view_changeset(
|
||||
inserted_groups: Vec<InsertedGroupPB>,
|
||||
updated_group: Vec<Group>,
|
||||
) -> GroupViewChangesetPB {
|
||||
let changeset = GroupViewChangesetPB {
|
||||
GroupViewChangesetPB {
|
||||
view_id,
|
||||
inserted_groups,
|
||||
deleted_groups: vec![],
|
||||
update_groups: updated_group.into_iter().map(GroupPB::from).collect(),
|
||||
};
|
||||
changeset
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, RowPB};
|
||||
use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, InsertedRowPB, RowPB};
|
||||
use crate::services::cell::{decode_any_cell_data, CellBytesParser};
|
||||
use crate::services::group::action::GroupAction;
|
||||
use crate::services::group::configuration::GenericGroupConfiguration;
|
||||
@ -11,8 +11,6 @@ use flowy_grid_data_model::revision::{
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
|
||||
const DEFAULT_GROUP_ID: &str = "default_group";
|
||||
|
||||
// Each kind of group must implement this trait to provide custom group
|
||||
// operations. For example, insert cell data to the row_rev when creating
|
||||
// a new row.
|
||||
@ -72,8 +70,6 @@ pub struct GenericGroupController<C, T, G, P> {
|
||||
pub field_id: String,
|
||||
pub type_option: Option<T>,
|
||||
pub configuration: GenericGroupConfiguration<C>,
|
||||
/// default_group is used to store the rows that don't belong to any groups.
|
||||
default_group: Group,
|
||||
group_action_phantom: PhantomData<G>,
|
||||
cell_parser_phantom: PhantomData<P>,
|
||||
}
|
||||
@ -92,22 +88,82 @@ where
|
||||
let type_option = field_rev.get_type_option_entry::<T>(field_type_rev);
|
||||
let groups = G::generate_groups(&field_rev.id, &configuration, &type_option);
|
||||
let _ = configuration.merge_groups(groups)?;
|
||||
let default_group = Group::new(
|
||||
DEFAULT_GROUP_ID.to_owned(),
|
||||
field_rev.id.clone(),
|
||||
format!("No {}", field_rev.name),
|
||||
"".to_string(),
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
field_id: field_rev.id.clone(),
|
||||
default_group,
|
||||
type_option,
|
||||
configuration,
|
||||
group_action_phantom: PhantomData,
|
||||
cell_parser_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/69413164/how-to-fix-this-clippy-warning-needless-collect
|
||||
#[allow(clippy::needless_collect)]
|
||||
fn update_default_group(
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
other_group_changesets: &[GroupChangesetPB],
|
||||
) -> GroupChangesetPB {
|
||||
let default_group = self.configuration.get_mut_default_group();
|
||||
|
||||
// [other_group_inserted_row] contains all the inserted rows except the default group.
|
||||
let other_group_inserted_row = other_group_changesets
|
||||
.iter()
|
||||
.flat_map(|changeset| &changeset.inserted_rows)
|
||||
.collect::<Vec<&InsertedRowPB>>();
|
||||
|
||||
// Calculate the inserted_rows of the default_group
|
||||
let default_group_inserted_row = other_group_changesets
|
||||
.iter()
|
||||
.flat_map(|changeset| &changeset.deleted_rows)
|
||||
.cloned()
|
||||
.filter(|row_id| {
|
||||
// if the [other_group_inserted_row] contains the row_id of the row
|
||||
// which means the row should not move to the default group.
|
||||
!other_group_inserted_row
|
||||
.iter()
|
||||
.any(|inserted_row| &inserted_row.row.id == row_id)
|
||||
})
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
let mut changeset = GroupChangesetPB::new(default_group.id.clone());
|
||||
if !default_group_inserted_row.is_empty() {
|
||||
changeset.inserted_rows.push(InsertedRowPB::new(row_rev.into()));
|
||||
default_group.add_row(row_rev.into());
|
||||
}
|
||||
|
||||
// [other_group_delete_rows] contains all the deleted rows except the default group.
|
||||
let other_group_delete_rows: Vec<String> = other_group_changesets
|
||||
.iter()
|
||||
.flat_map(|changeset| &changeset.deleted_rows)
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
let default_group_deleted_rows = other_group_changesets
|
||||
.iter()
|
||||
.flat_map(|changeset| &changeset.inserted_rows)
|
||||
.filter(|inserted_row| {
|
||||
// if the [other_group_delete_rows] contain the inserted_row, which means this row should move
|
||||
// out from the default_group.
|
||||
let inserted_row_id = &inserted_row.row.id;
|
||||
!other_group_delete_rows.iter().any(|row_id| inserted_row_id == row_id)
|
||||
})
|
||||
.collect::<Vec<&InsertedRowPB>>();
|
||||
|
||||
let mut deleted_row_ids = vec![];
|
||||
for row in &default_group.rows {
|
||||
if default_group_deleted_rows
|
||||
.iter()
|
||||
.any(|deleted_row| deleted_row.row.id == row.id)
|
||||
{
|
||||
deleted_row_ids.push(row.id.clone());
|
||||
}
|
||||
}
|
||||
default_group.rows.retain(|row| !deleted_row_ids.contains(&row.id));
|
||||
changeset.deleted_rows.extend(deleted_row_ids);
|
||||
changeset
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, T, G, P> GroupControllerSharedOperation for GenericGroupController<C, T, G, P>
|
||||
@ -124,11 +180,7 @@ where
|
||||
}
|
||||
|
||||
fn groups(&self) -> Vec<Group> {
|
||||
let mut groups = self.configuration.clone_groups();
|
||||
if self.default_group.is_empty() == false {
|
||||
groups.insert(0, self.default_group.clone());
|
||||
}
|
||||
groups
|
||||
self.configuration.clone_groups()
|
||||
}
|
||||
|
||||
fn get_group(&self, group_id: &str) -> Option<(usize, Group)> {
|
||||
@ -138,7 +190,6 @@ where
|
||||
|
||||
#[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<Vec<Group>> {
|
||||
// let mut ungrouped_rows = vec![];
|
||||
for row_rev in row_revs {
|
||||
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
|
||||
let mut grouped_rows: Vec<GroupedRow> = vec![];
|
||||
@ -154,8 +205,7 @@ where
|
||||
}
|
||||
|
||||
if grouped_rows.is_empty() {
|
||||
// ungrouped_rows.push(RowPB::from(row_rev));
|
||||
self.default_group.add_row(row_rev.into());
|
||||
self.configuration.get_mut_default_group().add_row(row_rev.into());
|
||||
} else {
|
||||
for group_row in grouped_rows {
|
||||
if let Some(group) = self.configuration.get_mut_group(&group_row.group_id) {
|
||||
@ -164,30 +214,11 @@ where
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.default_group.add_row(row_rev.into());
|
||||
self.configuration.get_mut_default_group().add_row(row_rev.into());
|
||||
}
|
||||
}
|
||||
|
||||
// if !ungrouped_rows.is_empty() {
|
||||
// let default_group_rev = GroupRevision::default_group(gen_grid_group_id(), format!("No {}", field_rev.name));
|
||||
// let default_group = Group::new(
|
||||
// default_group_rev.id.clone(),
|
||||
// field_rev.id.clone(),
|
||||
// default_group_rev.name.clone(),
|
||||
// "".to_owned(),
|
||||
// );
|
||||
// }
|
||||
|
||||
tracing::Span::current().record(
|
||||
"group_result",
|
||||
&format!(
|
||||
"{}, default_group has {} rows",
|
||||
self.configuration,
|
||||
self.default_group.rows.len()
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
|
||||
tracing::Span::current().record("group_result", &format!("{},", self.configuration,).as_str());
|
||||
Ok(self.groups())
|
||||
}
|
||||
|
||||
@ -203,7 +234,12 @@ where
|
||||
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
|
||||
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev);
|
||||
let cell_data = cell_bytes.parser::<P>()?;
|
||||
let changesets = self.add_row_if_match(row_rev, &cell_data);
|
||||
let mut changesets = self.add_row_if_match(row_rev, &cell_data);
|
||||
let default_group_changeset = self.update_default_group(row_rev, &changesets);
|
||||
tracing::info!("default_group_changeset: {}", default_group_changeset);
|
||||
if !default_group_changeset.is_empty() {
|
||||
changesets.push(default_group_changeset);
|
||||
}
|
||||
Ok(changesets)
|
||||
} else {
|
||||
Ok(vec![])
|
||||
|
@ -15,18 +15,25 @@ pub fn add_row(
|
||||
row_rev: &RowRevision,
|
||||
) -> Option<GroupChangesetPB> {
|
||||
let mut changeset = GroupChangesetPB::new(group.id.clone());
|
||||
cell_data.select_options.iter().for_each(|option| {
|
||||
if option.id == group.id {
|
||||
if !group.contains_row(&row_rev.id) {
|
||||
let row_pb = RowPB::from(row_rev);
|
||||
changeset.inserted_rows.push(InsertedRowPB::new(row_pb.clone()));
|
||||
group.add_row(row_pb);
|
||||
}
|
||||
} else if group.contains_row(&row_rev.id) {
|
||||
if cell_data.select_options.is_empty() {
|
||||
if group.contains_row(&row_rev.id) {
|
||||
changeset.deleted_rows.push(row_rev.id.clone());
|
||||
group.remove_row(&row_rev.id);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
cell_data.select_options.iter().for_each(|option| {
|
||||
if option.id == group.id {
|
||||
if !group.contains_row(&row_rev.id) {
|
||||
let row_pb = RowPB::from(row_rev);
|
||||
changeset.inserted_rows.push(InsertedRowPB::new(row_pb.clone()));
|
||||
group.add_row(row_pb);
|
||||
}
|
||||
} else 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() {
|
||||
None
|
||||
|
@ -5,6 +5,7 @@ pub struct Group {
|
||||
pub id: String,
|
||||
pub field_id: String,
|
||||
pub name: String,
|
||||
pub is_default: bool,
|
||||
pub(crate) rows: Vec<RowPB>,
|
||||
|
||||
/// [content] is used to determine which group the cell belongs to.
|
||||
@ -16,6 +17,7 @@ impl Group {
|
||||
Self {
|
||||
id,
|
||||
field_id,
|
||||
is_default: false,
|
||||
name,
|
||||
rows: vec![],
|
||||
content,
|
||||
|
@ -2,7 +2,7 @@ use crate::grid::grid_editor::GridEditorTest;
|
||||
use flowy_grid::entities::{
|
||||
CreateRowParams, FieldChangesetParams, FieldType, GridLayout, GroupPB, MoveGroupParams, MoveGroupRowParams, RowPB,
|
||||
};
|
||||
use flowy_grid::services::cell::insert_select_option_cell;
|
||||
use flowy_grid::services::cell::{delete_select_option_cell, insert_select_option_cell};
|
||||
use flowy_grid_data_model::revision::RowChangeset;
|
||||
use std::time::Duration;
|
||||
use tokio::time::interval;
|
||||
@ -128,11 +128,22 @@ impl GridGroupTest {
|
||||
let field_id = from_group.field_id;
|
||||
let field_rev = self.editor.get_field_rev(&field_id).await.unwrap();
|
||||
let field_type: FieldType = field_rev.ty.into();
|
||||
let cell_rev = match field_type {
|
||||
FieldType::SingleSelect => insert_select_option_cell(to_group.group_id.clone(), &field_rev),
|
||||
FieldType::MultiSelect => insert_select_option_cell(to_group.group_id.clone(), &field_rev),
|
||||
_ => {
|
||||
panic!("Unsupported group field type");
|
||||
|
||||
let cell_rev = if to_group.is_default {
|
||||
match field_type {
|
||||
FieldType::SingleSelect => delete_select_option_cell(to_group.group_id.clone(), &field_rev),
|
||||
FieldType::MultiSelect => delete_select_option_cell(to_group.group_id.clone(), &field_rev),
|
||||
_ => {
|
||||
panic!("Unsupported group field type");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match field_type {
|
||||
FieldType::SingleSelect => insert_select_option_cell(to_group.group_id.clone(), &field_rev),
|
||||
FieldType::MultiSelect => insert_select_option_cell(to_group.group_id.clone(), &field_rev),
|
||||
_ => {
|
||||
panic!("Unsupported group field type");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -6,7 +6,7 @@ use flowy_grid::entities::FieldChangesetParams;
|
||||
async fn group_init_test() {
|
||||
let mut test = GridGroupTest::new().await;
|
||||
let scripts = vec![
|
||||
AssertGroupCount(3),
|
||||
AssertGroupCount(4),
|
||||
AssertGroupRowCount {
|
||||
group_index: 0,
|
||||
row_count: 2,
|
||||
@ -19,6 +19,10 @@ async fn group_init_test() {
|
||||
group_index: 2,
|
||||
row_count: 1,
|
||||
},
|
||||
AssertGroupRowCount {
|
||||
group_index: 3,
|
||||
row_count: 0,
|
||||
},
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
@ -294,6 +298,55 @@ async fn group_reorder_group_test() {
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn group_move_to_default_group_test() {
|
||||
let mut test = GridGroupTest::new().await;
|
||||
let scripts = vec![
|
||||
UpdateRow {
|
||||
from_group_index: 0,
|
||||
row_index: 0,
|
||||
to_group_index: 3,
|
||||
},
|
||||
AssertGroupRowCount {
|
||||
group_index: 0,
|
||||
row_count: 1,
|
||||
},
|
||||
AssertGroupRowCount {
|
||||
group_index: 3,
|
||||
row_count: 1,
|
||||
},
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn group_move_from_default_group_test() {
|
||||
let mut test = GridGroupTest::new().await;
|
||||
let scripts = vec![UpdateRow {
|
||||
from_group_index: 0,
|
||||
row_index: 0,
|
||||
to_group_index: 3,
|
||||
}];
|
||||
test.run_scripts(scripts).await;
|
||||
|
||||
let scripts = vec![
|
||||
UpdateRow {
|
||||
from_group_index: 3,
|
||||
row_index: 0,
|
||||
to_group_index: 0,
|
||||
},
|
||||
AssertGroupRowCount {
|
||||
group_index: 0,
|
||||
row_count: 2,
|
||||
},
|
||||
AssertGroupRowCount {
|
||||
group_index: 3,
|
||||
row_count: 0,
|
||||
},
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn group_move_group_test() {
|
||||
let mut test = GridGroupTest::new().await;
|
||||
|
Loading…
Reference in New Issue
Block a user