Skip to content

Commit 940289c

Browse files
committed
chore: add board no status column
1 parent 03a5756 commit 940289c

File tree

9 files changed

+212
-61
lines changed

9 files changed

+212
-61
lines changed

frontend/app_flowy/lib/plugins/board/presentation/board_page.dart

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import 'package:flowy_infra_ui/style_widget/text.dart';
1515
import 'package:flowy_infra_ui/widget/error_page.dart';
1616
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
1717
import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
18+
import 'package:flowy_sdk/protobuf/flowy-grid/group.pbserver.dart';
1819
import 'package:flutter/material.dart';
1920
import 'package:flutter_bloc/flutter_bloc.dart';
2021
import '../../grid/application/row/row_cache.dart';
@@ -154,7 +155,11 @@ class _BoardContentState extends State<BoardContent> {
154155
}
155156

156157
Widget _buildFooter(BuildContext context, AFBoardColumnData columnData) {
157-
return AppFlowyColumnFooter(
158+
final group = columnData.customData as GroupPB;
159+
if (group.isDefault) {
160+
return const SizedBox();
161+
} else {
162+
return AppFlowyColumnFooter(
158163
icon: SizedBox(
159164
height: 20,
160165
width: 20,
@@ -172,7 +177,9 @@ class _BoardContentState extends State<BoardContent> {
172177
margin: config.footerPadding,
173178
onAddButtonClick: () {
174179
context.read<BoardBloc>().add(BoardEvent.createRow(columnData.id));
175-
});
180+
},
181+
);
182+
}
176183
}
177184

178185
Widget _buildCard(

frontend/rust-lib/flowy-grid/src/entities/group_entities/group.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ pub struct GroupPB {
8181

8282
#[pb(index = 4)]
8383
pub rows: Vec<RowPB>,
84+
85+
#[pb(index = 5)]
86+
pub is_default: bool,
8487
}
8588

8689
impl std::convert::From<Group> for GroupPB {
@@ -90,6 +93,7 @@ impl std::convert::From<Group> for GroupPB {
9093
group_id: group.id,
9194
desc: group.name,
9295
rows: group.rows,
96+
is_default: group.is_default,
9397
}
9498
}
9599
}

frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,12 @@ pub fn insert_select_option_cell(option_id: String, field_rev: &FieldRevision) -
176176
CellRevision::new(data)
177177
}
178178

179+
pub fn delete_select_option_cell(option_id: String, field_rev: &FieldRevision) -> CellRevision {
180+
let cell_data = SelectOptionCellChangeset::from_delete(&option_id).to_str();
181+
let data = apply_cell_data_changeset(cell_data, None, field_rev).unwrap();
182+
CellRevision::new(data)
183+
}
184+
179185
/// If the cell data is not String type, it should impl this trait.
180186
/// Deserialize the String into cell specific data type.
181187
pub trait FromCellString {

frontend/rust-lib/flowy-grid/src/services/group/configuration.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ impl<T> std::fmt::Display for GenericGroupConfiguration<T> {
3131
self.groups_map.iter().for_each(|(_, group)| {
3232
let _ = f.write_fmt(format_args!("Group:{} has {} rows \n", group.id, group.rows.len()));
3333
});
34+
let _ = f.write_fmt(format_args!(
35+
"Default group has {} rows \n",
36+
self.default_group.rows.len()
37+
));
3438
Ok(())
3539
}
3640
}
@@ -41,6 +45,8 @@ pub struct GenericGroupConfiguration<C> {
4145
configuration_content: PhantomData<C>,
4246
field_rev: Arc<FieldRevision>,
4347
groups_map: IndexMap<String, Group>,
48+
/// default_group is used to store the rows that don't belong to any groups.
49+
default_group: Group,
4450
writer: Arc<dyn GroupConfigurationWriter>,
4551
}
4652

@@ -55,6 +61,15 @@ where
5561
reader: Arc<dyn GroupConfigurationReader>,
5662
writer: Arc<dyn GroupConfigurationWriter>,
5763
) -> FlowyResult<Self> {
64+
let default_group_id = format!("{}_default_group", view_id);
65+
let default_group = Group {
66+
id: default_group_id,
67+
field_id: field_rev.id.clone(),
68+
name: format!("No {}", field_rev.name),
69+
is_default: true,
70+
rows: vec![],
71+
content: "".to_string(),
72+
};
5873
let configuration = match reader.get_group_configuration(field_rev.clone()).await {
5974
None => {
6075
let default_group_configuration = default_group_configuration(&field_rev);
@@ -71,6 +86,7 @@ where
7186
view_id,
7287
field_rev,
7388
groups_map: IndexMap::new(),
89+
default_group,
7490
writer,
7591
configuration,
7692
configuration_content: PhantomData,
@@ -82,7 +98,9 @@ where
8298
}
8399

84100
pub(crate) fn clone_groups(&self) -> Vec<Group> {
85-
self.groups_map.values().cloned().collect()
101+
let mut groups: Vec<Group> = self.groups_map.values().cloned().collect();
102+
groups.push(self.default_group.clone());
103+
groups
86104
}
87105

88106
pub(crate) fn merge_groups(&mut self, groups: Vec<Group>) -> FlowyResult<Option<GroupViewChangesetPB>> {
@@ -160,6 +178,10 @@ where
160178
self.groups_map.get_mut(group_id)
161179
}
162180

181+
pub(crate) fn get_mut_default_group(&mut self) -> &mut Group {
182+
&mut self.default_group
183+
}
184+
163185
pub(crate) fn move_group(&mut self, from_id: &str, to_id: &str) -> FlowyResult<()> {
164186
let from_index = self.groups_map.get_index_of(from_id);
165187
let to_index = self.groups_map.get_index_of(to_id);

frontend/rust-lib/flowy-grid/src/services/group/controller.rs

Lines changed: 81 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, RowPB};
1+
use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, InsertedRowPB, RowPB};
22
use crate::services::cell::{decode_any_cell_data, CellBytesParser};
33
use crate::services::group::action::GroupAction;
44
use crate::services::group::configuration::GenericGroupConfiguration;
@@ -11,8 +11,6 @@ use flowy_grid_data_model::revision::{
1111
use std::marker::PhantomData;
1212
use std::sync::Arc;
1313

14-
const DEFAULT_GROUP_ID: &str = "default_group";
15-
1614
// Each kind of group must implement this trait to provide custom group
1715
// operations. For example, insert cell data to the row_rev when creating
1816
// a new row.
@@ -72,8 +70,6 @@ pub struct GenericGroupController<C, T, G, P> {
7270
pub field_id: String,
7371
pub type_option: Option<T>,
7472
pub configuration: GenericGroupConfiguration<C>,
75-
/// default_group is used to store the rows that don't belong to any groups.
76-
default_group: Group,
7773
group_action_phantom: PhantomData<G>,
7874
cell_parser_phantom: PhantomData<P>,
7975
}
@@ -92,22 +88,85 @@ where
9288
let type_option = field_rev.get_type_option_entry::<T>(field_type_rev);
9389
let groups = G::generate_groups(&field_rev.id, &configuration, &type_option);
9490
let _ = configuration.merge_groups(groups)?;
95-
let default_group = Group::new(
96-
DEFAULT_GROUP_ID.to_owned(),
97-
field_rev.id.clone(),
98-
format!("No {}", field_rev.name),
99-
"".to_string(),
100-
);
10191

10292
Ok(Self {
10393
field_id: field_rev.id.clone(),
104-
default_group,
10594
type_option,
10695
configuration,
10796
group_action_phantom: PhantomData,
10897
cell_parser_phantom: PhantomData,
10998
})
11099
}
100+
101+
fn update_default_group(
102+
&mut self,
103+
row_rev: &RowRevision,
104+
other_group_changesets: &Vec<GroupChangesetPB>,
105+
) -> GroupChangesetPB {
106+
let default_group = self.configuration.get_mut_default_group();
107+
108+
// [other_group_inserted_row] contains all the inserted rows except the default group.
109+
let other_group_inserted_row = other_group_changesets
110+
.iter()
111+
.flat_map(|changeset| &changeset.inserted_rows)
112+
.collect::<Vec<&InsertedRowPB>>();
113+
114+
// Calculate the inserted_rows of the default_group
115+
let default_group_inserted_row = other_group_changesets
116+
.iter()
117+
.flat_map(|changeset| &changeset.deleted_rows)
118+
.cloned()
119+
.filter(|row_id| {
120+
// if the [other_group_inserted_row] contains the row_id of the row
121+
// which means the row should not move to the default group.
122+
other_group_inserted_row
123+
.iter()
124+
.find(|inserted_row| &inserted_row.row.id == row_id)
125+
.is_none()
126+
})
127+
.collect::<Vec<String>>();
128+
129+
let mut changeset = GroupChangesetPB::new(default_group.id.clone());
130+
if default_group_inserted_row.is_empty() == false {
131+
changeset.inserted_rows.push(InsertedRowPB::new(row_rev.into()));
132+
default_group.add_row(row_rev.into());
133+
}
134+
135+
// [other_group_delete_rows] contains all the deleted rows except the default group.
136+
let other_group_delete_rows: Vec<String> = other_group_changesets
137+
.iter()
138+
.flat_map(|changeset| &changeset.deleted_rows)
139+
.cloned()
140+
.collect();
141+
142+
let default_group_deleted_rows = other_group_changesets
143+
.iter()
144+
.flat_map(|changeset| &changeset.inserted_rows)
145+
.filter(|inserted_row| {
146+
// if the [other_group_delete_rows] contain the inserted_row, which means this row should move
147+
// out from the default_group.
148+
let inserted_row_id = &inserted_row.row.id;
149+
other_group_delete_rows
150+
.iter()
151+
.find(|row_id| inserted_row_id == row_id.clone())
152+
.is_none()
153+
})
154+
.collect::<Vec<&InsertedRowPB>>();
155+
156+
let mut deleted_row_ids = vec![];
157+
for row in &default_group.rows {
158+
if default_group_deleted_rows
159+
.iter()
160+
.find(|deleted_row| deleted_row.row.id == row.id)
161+
.is_some()
162+
{
163+
deleted_row_ids.push(row.id.clone());
164+
}
165+
}
166+
default_group.rows.retain(|row| !deleted_row_ids.contains(&row.id));
167+
changeset.deleted_rows.extend(deleted_row_ids);
168+
changeset
169+
}
111170
}
112171

113172
impl<C, T, G, P> GroupControllerSharedOperation for GenericGroupController<C, T, G, P>
@@ -124,11 +183,7 @@ where
124183
}
125184

126185
fn groups(&self) -> Vec<Group> {
127-
let mut groups = self.configuration.clone_groups();
128-
if self.default_group.is_empty() == false {
129-
groups.insert(0, self.default_group.clone());
130-
}
131-
groups
186+
self.configuration.clone_groups()
132187
}
133188

134189
fn get_group(&self, group_id: &str) -> Option<(usize, Group)> {
@@ -138,7 +193,6 @@ where
138193

139194
#[tracing::instrument(level = "trace", skip_all, fields(row_count=%row_revs.len(), group_result))]
140195
fn fill_groups(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<Vec<Group>> {
141-
// let mut ungrouped_rows = vec![];
142196
for row_rev in row_revs {
143197
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
144198
let mut grouped_rows: Vec<GroupedRow> = vec![];
@@ -154,8 +208,7 @@ where
154208
}
155209

156210
if grouped_rows.is_empty() {
157-
// ungrouped_rows.push(RowPB::from(row_rev));
158-
self.default_group.add_row(row_rev.into());
211+
self.configuration.get_mut_default_group().add_row(row_rev.into());
159212
} else {
160213
for group_row in grouped_rows {
161214
if let Some(group) = self.configuration.get_mut_group(&group_row.group_id) {
@@ -164,30 +217,11 @@ where
164217
}
165218
}
166219
} else {
167-
self.default_group.add_row(row_rev.into());
220+
self.configuration.get_mut_default_group().add_row(row_rev.into());
168221
}
169222
}
170223

171-
// if !ungrouped_rows.is_empty() {
172-
// let default_group_rev = GroupRevision::default_group(gen_grid_group_id(), format!("No {}", field_rev.name));
173-
// let default_group = Group::new(
174-
// default_group_rev.id.clone(),
175-
// field_rev.id.clone(),
176-
// default_group_rev.name.clone(),
177-
// "".to_owned(),
178-
// );
179-
// }
180-
181-
tracing::Span::current().record(
182-
"group_result",
183-
&format!(
184-
"{}, default_group has {} rows",
185-
self.configuration,
186-
self.default_group.rows.len()
187-
)
188-
.as_str(),
189-
);
190-
224+
tracing::Span::current().record("group_result", &format!("{},", self.configuration,).as_str());
191225
Ok(self.groups())
192226
}
193227

@@ -203,7 +237,12 @@ where
203237
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
204238
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev);
205239
let cell_data = cell_bytes.parser::<P>()?;
206-
let changesets = self.add_row_if_match(row_rev, &cell_data);
240+
let mut changesets = self.add_row_if_match(row_rev, &cell_data);
241+
let default_group_changeset = self.update_default_group(row_rev, &changesets);
242+
tracing::info!("default_group_changeset: {}", default_group_changeset);
243+
if !default_group_changeset.is_empty() {
244+
changesets.push(default_group_changeset);
245+
}
207246
Ok(changesets)
208247
} else {
209248
Ok(vec![])

frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,25 @@ pub fn add_row(
1515
row_rev: &RowRevision,
1616
) -> Option<GroupChangesetPB> {
1717
let mut changeset = GroupChangesetPB::new(group.id.clone());
18-
cell_data.select_options.iter().for_each(|option| {
19-
if option.id == group.id {
20-
if !group.contains_row(&row_rev.id) {
21-
let row_pb = RowPB::from(row_rev);
22-
changeset.inserted_rows.push(InsertedRowPB::new(row_pb.clone()));
23-
group.add_row(row_pb);
24-
}
25-
} else if group.contains_row(&row_rev.id) {
18+
if cell_data.select_options.is_empty() {
19+
if group.contains_row(&row_rev.id) {
2620
changeset.deleted_rows.push(row_rev.id.clone());
2721
group.remove_row(&row_rev.id);
2822
}
29-
});
23+
} else {
24+
cell_data.select_options.iter().for_each(|option| {
25+
if option.id == group.id {
26+
if !group.contains_row(&row_rev.id) {
27+
let row_pb = RowPB::from(row_rev);
28+
changeset.inserted_rows.push(InsertedRowPB::new(row_pb.clone()));
29+
group.add_row(row_pb);
30+
}
31+
} else if group.contains_row(&row_rev.id) {
32+
changeset.deleted_rows.push(row_rev.id.clone());
33+
group.remove_row(&row_rev.id);
34+
}
35+
});
36+
}
3037

3138
if changeset.is_empty() {
3239
None

frontend/rust-lib/flowy-grid/src/services/group/entities.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub struct Group {
55
pub id: String,
66
pub field_id: String,
77
pub name: String,
8+
pub is_default: bool,
89
pub(crate) rows: Vec<RowPB>,
910

1011
/// [content] is used to determine which group the cell belongs to.
@@ -16,6 +17,7 @@ impl Group {
1617
Self {
1718
id,
1819
field_id,
20+
is_default: false,
1921
name,
2022
rows: vec![],
2123
content,

0 commit comments

Comments
 (0)