mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: newly-created rows aren't being automatically sorted (#4661)
* fix: newly-created rows aren't being automatically sorted * chore: new database view collab notification and add tests
This commit is contained in:
parent
15c9a67028
commit
a6c6aa819c
@ -6,7 +6,7 @@ use crate::entities::{
|
||||
};
|
||||
use crate::notification::{send_notification, DatabaseNotification};
|
||||
use crate::services::filter::FilterResultNotification;
|
||||
use crate::services::sort::{ReorderAllRowsResult, ReorderSingleRowResult};
|
||||
use crate::services::sort::{InsertSortedRowResult, ReorderAllRowsResult, ReorderSingleRowResult};
|
||||
use async_stream::stream;
|
||||
use futures::stream::StreamExt;
|
||||
use tokio::sync::broadcast;
|
||||
@ -16,6 +16,7 @@ pub enum DatabaseViewChanged {
|
||||
FilterNotification(FilterResultNotification),
|
||||
ReorderAllRowsNotification(ReorderAllRowsResult),
|
||||
ReorderSingleRowNotification(ReorderSingleRowResult),
|
||||
InsertSortedRowNotification(InsertSortedRowResult),
|
||||
CalculationValueNotification(CalculationChangesetNotificationPB),
|
||||
}
|
||||
|
||||
@ -78,6 +79,7 @@ impl DatabaseViewChangedReceiverRunner {
|
||||
.payload(reorder_row)
|
||||
.send()
|
||||
},
|
||||
DatabaseViewChanged::InsertSortedRowNotification(_result) => {},
|
||||
DatabaseViewChanged::CalculationValueNotification(notification) => send_notification(
|
||||
¬ification.view_id,
|
||||
DatabaseNotification::DidUpdateCalculation,
|
||||
|
@ -161,7 +161,7 @@ impl DatabaseViewEditor {
|
||||
.payload(changes)
|
||||
.send();
|
||||
self
|
||||
.gen_view_tasks(row_detail.row.id.clone(), "".to_string())
|
||||
.gen_did_create_row_view_tasks(row_detail.row.id.clone())
|
||||
.await;
|
||||
}
|
||||
|
||||
@ -257,7 +257,7 @@ impl DatabaseViewEditor {
|
||||
// Each row update will trigger a calculations, filter and sort operation. We don't want
|
||||
// to block the main thread, so we spawn a new task to do the work.
|
||||
self
|
||||
.gen_view_tasks(row_detail.row.id.clone(), field_id)
|
||||
.gen_did_update_row_view_tasks(row_detail.row.id.clone(), field_id)
|
||||
.await;
|
||||
}
|
||||
|
||||
@ -1071,7 +1071,7 @@ impl DatabaseViewEditor {
|
||||
}
|
||||
}
|
||||
|
||||
async fn gen_view_tasks(&self, row_id: RowId, field_id: String) {
|
||||
async fn gen_did_update_row_view_tasks(&self, row_id: RowId, field_id: String) {
|
||||
let weak_filter_controller = Arc::downgrade(&self.filter_controller);
|
||||
let weak_sort_controller = Arc::downgrade(&self.sort_controller);
|
||||
let weak_calculations_controller = Arc::downgrade(&self.calculations_controller);
|
||||
@ -1095,4 +1095,13 @@ impl DatabaseViewEditor {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn gen_did_create_row_view_tasks(&self, row_id: RowId) {
|
||||
let weak_sort_controller = Arc::downgrade(&self.sort_controller);
|
||||
af_spawn(async move {
|
||||
if let Some(sort_controller) = weak_sort_controller.upgrade() {
|
||||
sort_controller.read().await.did_create_row(row_id).await;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,8 @@ use crate::services::field::{
|
||||
default_order, TimestampCellData, TimestampCellDataWrapper, TypeOptionCellExt,
|
||||
};
|
||||
use crate::services::sort::{
|
||||
ReorderAllRowsResult, ReorderSingleRowResult, Sort, SortChangeset, SortCondition,
|
||||
InsertSortedRowResult, ReorderAllRowsResult, ReorderSingleRowResult, Sort, SortChangeset,
|
||||
SortCondition,
|
||||
};
|
||||
|
||||
pub trait SortDelegate: Send + Sync {
|
||||
@ -93,6 +94,17 @@ impl SortController {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn did_create_row(&self, row_id: RowId) {
|
||||
if !self.sorts.is_empty() {
|
||||
self
|
||||
.gen_task(
|
||||
SortEvent::NewRowInserted(row_id),
|
||||
QualityOfService::Background,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
// #[tracing::instrument(name = "process_sort_task", level = "trace", skip_all, err)]
|
||||
pub async fn process(&mut self, predicate: &str) -> FlowyResult<()> {
|
||||
let event_type = SortEvent::from_str(predicate).unwrap();
|
||||
@ -118,6 +130,7 @@ impl SortController {
|
||||
},
|
||||
SortEvent::RowDidChanged(row_id) => {
|
||||
let old_row_index = self.row_index_cache.get(&row_id).cloned();
|
||||
|
||||
self.sort_rows(&mut row_details).await;
|
||||
let new_row_index = self.row_index_cache.get(&row_id).cloned();
|
||||
match (old_row_index, new_row_index) {
|
||||
@ -140,6 +153,26 @@ impl SortController {
|
||||
_ => tracing::trace!("The row index cache is outdated"),
|
||||
}
|
||||
},
|
||||
SortEvent::NewRowInserted(row_id) => {
|
||||
self.sort_rows(&mut row_details).await;
|
||||
let row_index = self.row_index_cache.get(&row_id).cloned();
|
||||
match row_index {
|
||||
Some(row_index) => {
|
||||
let notification = InsertSortedRowResult {
|
||||
row_id: row_id.clone(),
|
||||
view_id: self.view_id.clone(),
|
||||
index: row_index,
|
||||
};
|
||||
self.row_index_cache.insert(row_id, row_index);
|
||||
let _ = self
|
||||
.notifier
|
||||
.send(DatabaseViewChanged::InsertSortedRowNotification(
|
||||
notification,
|
||||
));
|
||||
},
|
||||
_ => tracing::trace!("The row index cache is outdated"),
|
||||
}
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -313,6 +346,7 @@ fn cmp_cell(
|
||||
enum SortEvent {
|
||||
SortDidChanged,
|
||||
RowDidChanged(RowId),
|
||||
NewRowInserted(RowId),
|
||||
DeleteAllSorts,
|
||||
}
|
||||
|
||||
|
@ -121,6 +121,13 @@ pub struct ReorderSingleRowResult {
|
||||
pub new_index: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct InsertSortedRowResult {
|
||||
pub view_id: String,
|
||||
pub row_id: RowId,
|
||||
pub index: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct SortChangeset {
|
||||
pub(crate) insert_sort: Option<Sort>,
|
||||
|
@ -36,6 +36,7 @@ pub enum SortScript {
|
||||
row_id: RowId,
|
||||
text: String,
|
||||
},
|
||||
AddNewRow,
|
||||
AssertSortChanged {
|
||||
old_row_orders: Vec<&'static str>,
|
||||
new_row_orders: Vec<&'static str>,
|
||||
@ -145,6 +146,28 @@ impl DatabaseSortTest {
|
||||
);
|
||||
self.update_text_cell(row_id, &text).await.unwrap();
|
||||
},
|
||||
SortScript::AddNewRow => {
|
||||
self.recv = Some(
|
||||
self
|
||||
.editor
|
||||
.subscribe_view_changed(&self.view_id)
|
||||
.await
|
||||
.unwrap(),
|
||||
);
|
||||
self
|
||||
.editor
|
||||
.create_row(
|
||||
&self.view_id,
|
||||
None,
|
||||
collab_database::rows::CreateRowParams {
|
||||
id: collab_database::database::gen_row_id(),
|
||||
timestamp: collab_database::database::timestamp(),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
},
|
||||
SortScript::AssertSortChanged {
|
||||
new_row_orders,
|
||||
old_row_orders,
|
||||
@ -195,6 +218,7 @@ async fn assert_sort_changed(
|
||||
old_row_orders.insert(changed.new_index, old);
|
||||
assert_eq!(old_row_orders, new_row_orders);
|
||||
},
|
||||
DatabaseViewChanged::InsertSortedRowNotification(_changed) => {},
|
||||
_ => {},
|
||||
}
|
||||
})
|
||||
|
@ -81,10 +81,36 @@ async fn sort_change_notification_by_update_text_test() {
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn sort_after_new_row_test() {
|
||||
let mut test = DatabaseSortTest::new().await;
|
||||
let checkbox_field = test.get_first_field(FieldType::Checkbox);
|
||||
let scripts = vec![
|
||||
AssertCellContentOrder {
|
||||
field_id: checkbox_field.id.clone(),
|
||||
orders: vec!["Yes", "Yes", "No", "No", "No", "Yes", ""],
|
||||
},
|
||||
InsertSort {
|
||||
field: checkbox_field.clone(),
|
||||
condition: SortCondition::Ascending,
|
||||
},
|
||||
AssertCellContentOrder {
|
||||
field_id: checkbox_field.id.clone(),
|
||||
orders: vec!["No", "No", "No", "", "Yes", "Yes", "Yes"],
|
||||
},
|
||||
AddNewRow {},
|
||||
AssertCellContentOrder {
|
||||
field_id: checkbox_field.id,
|
||||
orders: vec!["No", "No", "No", "", "", "Yes", "Yes", "Yes"],
|
||||
},
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn sort_text_by_ascending_and_delete_sort_test() {
|
||||
let mut test = DatabaseSortTest::new().await;
|
||||
let text_field = test.get_first_field(FieldType::RichText).clone();
|
||||
let text_field = test.get_first_field(FieldType::RichText);
|
||||
let scripts = vec![
|
||||
InsertSort {
|
||||
field: text_field.clone(),
|
||||
|
Loading…
Reference in New Issue
Block a user