fix: group with not support field test (#1890)

This commit is contained in:
Nathan.fooo 2023-02-27 19:00:00 +08:00 committed by GitHub
parent bf8e36a08b
commit 4a81fed6e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 192 additions and 158 deletions

View File

@ -12,8 +12,8 @@
"type": "dart",
"preLaunchTask": "AF: Build Appflowy Core",
"env": {
"RUST_LOG": "trace",
// "RUST_LOG": "debug"
// "RUST_LOG": "trace",
"RUST_LOG": "debug"
},
"cwd": "${workspaceRoot}/appflowy_flutter"
},

View File

@ -18,7 +18,7 @@ on_error_task = "catch"
run_task = { name = ["restore-crate-type"] }
[env]
RUST_LOG = "debug"
RUST_LOG = "info"
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
CARGO_MAKE_CRATE_NAME = "dart-ffi"
@ -48,7 +48,6 @@ TAURI_BACKEND_SERVICE_PATH = "appflowy_tauri/src/services/backend"
# Test default config
TEST_CRATE_TYPE = "cdylib"
TEST_LIB_EXT = "dylib"
TEST_RUST_LOG = "info"
TEST_BUILD_FLAG = "debug"
TEST_COMPILE_TARGET = "x86_64-apple-darwin"

View File

@ -53,7 +53,7 @@ class DatabaseBackendService {
});
}
Future<Either<Unit, FlowyError>> closeGrid() {
Future<Either<Unit, FlowyError>> closeView() {
final request = ViewIdPB(value: viewId);
return FolderEventCloseView(request).send();
}

View File

@ -126,7 +126,7 @@ class BoardDataController {
Future<void> dispose() async {
await _viewCache.dispose();
await _databaseFFIService.closeGrid();
await _databaseFFIService.closeView();
await fieldController.dispose();
}

View File

@ -109,7 +109,7 @@ class CalendarDataController {
Future<void> dispose() async {
await _viewCache.dispose();
await _databaseBackendSvc.closeGrid();
await _databaseBackendSvc.closeView();
await fieldController.dispose();
}
}

View File

@ -77,7 +77,7 @@ class DatabaseController {
}
Future<void> dispose() async {
await _databaseBackendSvc.closeGrid();
await _databaseBackendSvc.closeView();
await fieldController.dispose();
}
}

View File

@ -22,7 +22,7 @@ void main() {
await boardResponseFuture();
});
group('Group with not support grouping field:', () {
group('Group with not support grouping field', () {
blocTest<FieldEditorBloc, FieldEditorState>(
"switch to text field",
build: () => editorBloc,

View File

@ -1225,6 +1225,8 @@ dependencies = [
"lib-ws",
"parking_lot",
"revision-model",
"serde",
"serde_json",
"tokio",
"tracing",
"user-model",

View File

@ -14,7 +14,7 @@ class CellIdentifier {
class CellBackendService {
static updateCell = async (cellId: CellIdentifier, data: string) => {
const payload = CellChangesetPB.fromObject({
database_id: cellId.viewId,
view_id: cellId.viewId,
field_id: cellId.fieldId,
row_id: cellId.rowId,
type_cell_data: data,
@ -24,7 +24,7 @@ class CellBackendService {
getCell = async (cellId: CellIdentifier) => {
const payload = CellIdPB.fromObject({
database_id: cellId.viewId,
view_id: cellId.viewId,
field_id: cellId.fieldId,
row_id: cellId.rowId,
});

View File

@ -39,7 +39,7 @@ export class DateCellDataPersistence extends CellDataPersistence<CalendarData> {
function _makeCellPath(cellIdentifier: CellIdentifier): CellIdPB {
return CellIdPB.fromObject({
database_id: cellIdentifier.viewId,
view_id: cellIdentifier.viewId,
field_id: cellIdentifier.fieldId,
row_id: cellIdentifier.rowId,
});

View File

@ -28,7 +28,7 @@ export class FieldBackendService {
visibility?: boolean;
width?: number;
}) => {
const payload = FieldChangesetPB.fromObject({ database_id: this.viewId, field_id: this.fieldId });
const payload = FieldChangesetPB.fromObject({ view_id: this.viewId, field_id: this.fieldId });
if (data.name !== undefined) {
payload.name = data.name;

View File

@ -3,8 +3,8 @@ import { ChangeNotifier } from '../../../../utils/change_notifier';
import { FieldInfo } from '../field/controller';
import { CellCache, CellCacheKey } from '../cell/cache';
import {
ViewRowsChangesetPB,
ViewRowsVisibilityChangesetPB,
RowsChangesetPB,
RowsVisibilityChangesetPB,
} from '../../../../../services/backend/models/flowy-database/view_entities';
import { CellIdentifier } from '../cell/backend_service';
import { ReorderSingleRowPB } from '../../../../../services/backend/models/flowy-database/sort_entities';
@ -49,13 +49,13 @@ export class RowCache {
});
};
applyRowsChanged = (changeset: ViewRowsChangesetPB) => {
applyRowsChanged = (changeset: RowsChangesetPB) => {
this._deleteRows(changeset.deleted_rows);
this._insertRows(changeset.inserted_rows);
this._updateRows(changeset.updated_rows);
};
applyRowsVisibility = (changeset: ViewRowsVisibilityChangesetPB) => {
applyRowsVisibility = (changeset: RowsVisibilityChangesetPB) => {
this._hideRows(changeset.invisible_rows);
this._displayRows(changeset.visible_rows);
};

View File

@ -5,15 +5,15 @@ import {
ReorderSingleRowPB,
} from '../../../../../services/backend/events/flowy-database';
import {
ViewRowsChangesetPB,
ViewRowsVisibilityChangesetPB,
RowsChangesetPB,
RowsVisibilityChangesetPB,
} from '../../../../../services/backend/models/flowy-database/view_entities';
import { FlowyError } from '../../../../../services/backend/models/flowy-error/errors';
import { ChangeNotifier } from '../../../../utils/change_notifier';
import { DatabaseNotificationObserver } from '../notifications/observer';
export type RowsVisibilityNotifyValue = Result<ViewRowsVisibilityChangesetPB, FlowyError>;
export type RowsNotifyValue = Result<ViewRowsChangesetPB, FlowyError>;
export type RowsVisibilityNotifyValue = Result<RowsVisibilityChangesetPB, FlowyError>;
export type RowsNotifyValue = Result<RowsChangesetPB, FlowyError>;
export type ReorderRowsNotifyValue = Result<string[], FlowyError>;
export type ReorderSingleRowNotifyValue = Result<ReorderSingleRowPB, FlowyError>;
@ -43,10 +43,10 @@ export class DatabaseViewRowsObserver {
parserHandler: (notification, payload) => {
switch (notification) {
case DatabaseNotification.DidUpdateViewRowsVisibility:
this._rowsVisibilityNotifier.notify(Ok(ViewRowsVisibilityChangesetPB.deserializeBinary(payload)));
this._rowsVisibilityNotifier.notify(Ok(RowsVisibilityChangesetPB.deserializeBinary(payload)));
break;
case DatabaseNotification.DidUpdateViewRows:
this._rowsNotifier.notify(Ok(ViewRowsChangesetPB.deserializeBinary(payload)));
this._rowsNotifier.notify(Ok(RowsChangesetPB.deserializeBinary(payload)));
break;
case DatabaseNotification.DidReorderRows:
this._reorderRowsNotifier.notify(Ok(ReorderAllRowsPB.deserializeBinary(payload).row_orders));

View File

@ -41,7 +41,6 @@ export class AppBackendService {
belong_to_id: this.appId,
name: params.name,
desc: params.desc || '',
data_format: params.dataFormatType,
layout: params.layoutType,
initial_data: encoder.encode(params.initialData || ''),
});

View File

@ -109,18 +109,18 @@ impl DatabaseRevisionPad {
&mut self,
field_id: &str,
) -> SyncResult<Option<DatabaseRevisionChangeset>> {
self.modify_database(|grid_meta| {
match grid_meta
self.modify_database(|database| {
match database
.fields
.iter()
.position(|field| field.id == field_id)
{
None => Ok(None),
Some(index) => {
if grid_meta.fields[index].is_primary {
if database.fields[index].is_primary {
Err(SyncError::can_not_delete_primary_field())
} else {
grid_meta.fields.remove(index);
database.fields.remove(index);
Ok(Some(()))
}
},

View File

@ -572,7 +572,7 @@ impl FieldType {
}
pub fn can_be_group(&self) -> bool {
self.is_select_option() || self.is_checkbox()
self.is_select_option() || self.is_checkbox() || self.is_url()
}
}

View File

@ -162,7 +162,7 @@ pub(crate) async fn delete_field_handler(
Ok(())
}
#[tracing::instrument(level = "trace", skip(data, manager), err)]
#[tracing::instrument(level = "debug", skip(data, manager), err)]
pub(crate) async fn switch_to_field_handler(
data: AFPluginData<UpdateFieldTypePayloadPB>,
manager: AFPluginState<Arc<DatabaseManager>>,

View File

@ -40,7 +40,7 @@ pub trait DatabaseUser: Send + Sync {
}
pub struct DatabaseManager {
database_editors: RwLock<HashMap<String, Arc<DatabaseEditor>>>,
editors_by_database_id: RwLock<HashMap<String, Arc<DatabaseEditor>>>,
database_user: Arc<dyn DatabaseUser>,
block_indexer: Arc<BlockRowIndexer>,
database_ref_indexer: Arc<DatabaseRefIndexer>,
@ -58,7 +58,7 @@ impl DatabaseManager {
task_scheduler: Arc<RwLock<TaskDispatcher>>,
database_db: Arc<dyn DatabaseDBConnection>,
) -> Self {
let database_editors = RwLock::new(HashMap::new());
let editors_by_database_id = RwLock::new(HashMap::new());
let kv_persistence = Arc::new(DatabaseKVPersistence::new(database_db.clone()));
let block_indexer = Arc::new(BlockRowIndexer::new(database_db.clone()));
let database_ref_indexer = Arc::new(DatabaseRefIndexer::new(database_db.clone()));
@ -68,7 +68,7 @@ impl DatabaseManager {
database_ref_indexer.clone(),
);
Self {
database_editors,
editors_by_database_id,
database_user,
kv_persistence,
block_indexer,
@ -141,7 +141,6 @@ impl DatabaseManager {
.await
}
#[tracing::instrument(level = "debug", skip_all, fields(view_id), err)]
pub async fn close_database_view<T: AsRef<str>>(&self, view_id: T) -> FlowyResult<()> {
let view_id = view_id.as_ref();
let database_info = self.database_ref_indexer.get_database_with_view(view_id)?;
@ -149,7 +148,7 @@ impl DatabaseManager {
let mut should_remove_editor = false;
if let Some(database_editor) = self
.database_editors
.editors_by_database_id
.write()
.await
.get(&database_info.database_id)
@ -162,8 +161,9 @@ impl DatabaseManager {
}
if should_remove_editor {
tracing::debug!("Close database base editor: {}", database_info.database_id);
self
.database_editors
.editors_by_database_id
.write()
.await
.remove(&database_info.database_id);
@ -173,15 +173,19 @@ impl DatabaseManager {
// #[tracing::instrument(level = "debug", skip(self), err)]
pub async fn get_database_editor(&self, view_id: &str) -> FlowyResult<Arc<DatabaseEditor>> {
let read_guard = self.database_editors.read().await;
let editor = read_guard.get(view_id);
match editor {
let database_info = self.database_ref_indexer.get_database_with_view(view_id)?;
let database_editor = self
.editors_by_database_id
.read()
.await
.get(&database_info.database_id)
.cloned();
match database_editor {
None => {
// Drop the read_guard ASAP in case of the following read/write lock
drop(read_guard);
self.open_database_view(view_id).await
},
Some(editor) => Ok(editor.clone()),
Some(editor) => Ok(editor),
}
}
@ -200,7 +204,7 @@ impl DatabaseManager {
database_id: &str,
view_id: &str,
) -> FlowyResult<Arc<DatabaseEditor>> {
if let Some(database_editor) = self.database_editors.read().await.get(database_id) {
if let Some(database_editor) = self.editors_by_database_id.read().await.get(database_id) {
let user_id = self.database_user.user_id()?;
let (view_pad, view_rev_manager) =
make_database_view_revision_pad(view_id, self.database_user.clone()).await?;
@ -217,10 +221,10 @@ impl DatabaseManager {
return Ok(database_editor.clone());
}
// Lock the database_editors
let mut database_editors = self.database_editors.write().await;
let mut editors_by_database_id = self.editors_by_database_id.write().await;
let db_pool = self.database_user.db_pool()?;
let editor = self.make_database_rev_editor(view_id, db_pool).await?;
database_editors.insert(database_id.to_string(), editor.clone());
editors_by_database_id.insert(database_id.to_string(), editor.clone());
Ok(editor)
}
@ -236,7 +240,7 @@ impl DatabaseManager {
make_database_view_revision_pad(view_id, user.clone()).await?;
let mut database_id = base_view_pad.database_id.clone();
tracing::debug!("Open database:{}", database_id);
tracing::debug!("Open database: {}", database_id);
if database_id.is_empty() {
// Before the database_id concept comes up, we used the view_id directly. So if
// the database_id is empty, which means we can used the view_id. After the version 0.1.1,

View File

@ -129,15 +129,14 @@ impl DatabaseBlockEditor {
if let Ok(pad) = self.pad.try_read() {
Ok(pad.get_row_rev(row_id))
} else {
tracing::error!("Required grid block read lock failed, retrying");
let retry = GetRowDataRetryAction {
row_id: row_id.to_owned(),
pad: self.pad.clone(),
};
match spawn_retry(3, 300, retry).await {
Ok(value) => Ok(value),
Err(err) => {
tracing::error!("Read row revision failed with: {}", err);
Err(_) => {
tracing::error!("Required database block read lock failed");
Ok(None)
},
}

View File

@ -116,7 +116,7 @@ impl DatabaseEditor {
self.database_views.open(view_editor).await
}
#[tracing::instrument(name = "close database editor view", level = "trace", skip_all)]
#[tracing::instrument(name = "Close database editor view", level = "debug", skip_all)]
pub async fn close_view_editor(&self, view_id: &str) {
self.rev_manager.generate_snapshot().await;
self.database_views.close(view_id).await;
@ -175,7 +175,7 @@ impl DatabaseEditor {
self
.database_views
.did_update_view_field_type_option(view_id, field_id, old_field_rev)
.did_update_field_type_option(view_id, field_id, old_field_rev)
.await?;
self.notify_did_update_database_field(field_id).await?;
Ok(())
@ -275,7 +275,7 @@ impl DatabaseEditor {
if is_changed {
match self
.database_views
.did_update_view_field_type_option(view_id, field_id, old_field_rev)
.did_update_field_type_option(view_id, field_id, old_field_rev)
.await
{
Ok(_) => {},
@ -600,7 +600,7 @@ impl DatabaseEditor {
field_id: &str,
) -> FlowyResult<Vec<RowSingleCellData>> {
let view_editor = self.database_views.get_view_editor(view_id).await?;
view_editor.get_cells_for_field(field_id).await
view_editor.v_get_cells_for_field(field_id).await
}
#[tracing::instrument(level = "trace", skip_all, err)]

View File

@ -222,20 +222,20 @@ impl DatabaseViewEditor {
.send();
}
pub async fn sort_rows(&self, rows: &mut Vec<Arc<RowRevision>>) {
pub async fn v_sort_rows(&self, rows: &mut Vec<Arc<RowRevision>>) {
self.sort_controller.write().await.sort_rows(rows).await
}
pub async fn filter_rows(&self, _block_id: &str, rows: &mut Vec<Arc<RowRevision>>) {
pub async fn v_filter_rows(&self, _block_id: &str, rows: &mut Vec<Arc<RowRevision>>) {
self.filter_controller.filter_row_revs(rows).await;
}
pub async fn duplicate_view_data(&self) -> FlowyResult<String> {
pub async fn v_duplicate_data(&self) -> FlowyResult<String> {
let json_str = self.pad.read().await.json_str()?;
Ok(json_str)
}
pub async fn will_create_view_row(&self, row_rev: &mut RowRevision, params: &CreateRowParams) {
pub async fn v_will_create_row(&self, row_rev: &mut RowRevision, params: &CreateRowParams) {
if params.group_id.is_none() {
return;
}
@ -248,7 +248,7 @@ impl DatabaseViewEditor {
.await;
}
pub async fn did_create_view_row(&self, row_pb: &RowPB, params: &CreateRowParams) {
pub async fn v_did_create_row(&self, row_pb: &RowPB, params: &CreateRowParams) {
// Send the group notification if the current view has groups
match params.group_id.as_ref() {
None => {},
@ -275,7 +275,7 @@ impl DatabaseViewEditor {
}
#[tracing::instrument(level = "trace", skip_all)]
pub async fn did_delete_view_row(&self, row_rev: &RowRevision) {
pub async fn v_did_delete_row(&self, row_rev: &RowRevision) {
// Send the group notification if the current view has groups;
let result = self
.mut_group_controller(|group_controller, field_rev| {
@ -291,7 +291,7 @@ impl DatabaseViewEditor {
}
}
pub async fn did_update_view_row(
pub async fn v_did_update_row(
&self,
old_row_rev: Option<Arc<RowRevision>>,
row_rev: &RowRevision,
@ -339,7 +339,7 @@ impl DatabaseViewEditor {
});
}
pub async fn move_view_group_row(
pub async fn v_move_group_row(
&self,
row_rev: &RowRevision,
row_changeset: &mut RowChangeset,
@ -377,7 +377,7 @@ impl DatabaseViewEditor {
}
/// Only call once after grid view editor initialized
#[tracing::instrument(level = "trace", skip(self))]
pub async fn load_view_groups(&self) -> FlowyResult<Vec<GroupPB>> {
pub async fn v_load_groups(&self) -> FlowyResult<Vec<GroupPB>> {
let groups = self
.group_controller
.read()
@ -391,7 +391,7 @@ impl DatabaseViewEditor {
}
#[tracing::instrument(level = "trace", skip(self), err)]
pub async fn move_view_group(&self, params: MoveGroupParams) -> FlowyResult<()> {
pub async fn v_move_group(&self, params: MoveGroupParams) -> FlowyResult<()> {
self
.group_controller
.write()
@ -430,7 +430,7 @@ impl DatabaseViewEditor {
/// Initialize new group when grouping by a new field
///
pub async fn initialize_new_group(&self, params: InsertGroupParams) -> FlowyResult<()> {
pub async fn v_initialize_new_group(&self, params: InsertGroupParams) -> FlowyResult<()> {
if let Some(field_rev) = self.delegate.get_field_rev(&params.field_id).await {
self
.modify(|pad| {
@ -445,13 +445,13 @@ impl DatabaseViewEditor {
.await?;
}
if self.group_controller.read().await.field_id() != params.field_id {
self.group_by_view_field(&params.field_id).await?;
self.v_update_group_setting(&params.field_id).await?;
self.notify_did_update_setting().await;
}
Ok(())
}
pub async fn delete_view_group(&self, params: DeleteGroupParams) -> FlowyResult<()> {
pub async fn v_delete_group(&self, params: DeleteGroupParams) -> FlowyResult<()> {
self
.modify(|pad| {
let changeset =
@ -461,18 +461,18 @@ impl DatabaseViewEditor {
.await
}
pub async fn get_view_setting(&self) -> DatabaseViewSettingPB {
pub async fn v_get_setting(&self) -> DatabaseViewSettingPB {
let field_revs = self.delegate.get_field_revs(None).await;
make_database_view_setting(&*self.pad.read().await, &field_revs)
}
pub async fn get_all_view_sorts(&self) -> Vec<Arc<SortRevision>> {
pub async fn v_get_all_sorts(&self) -> Vec<Arc<SortRevision>> {
let field_revs = self.delegate.get_field_revs(None).await;
self.pad.read().await.get_all_sorts(&field_revs)
}
#[tracing::instrument(level = "trace", skip(self), err)]
pub async fn insert_view_sort(&self, params: AlterSortParams) -> FlowyResult<SortRevision> {
pub async fn v_insert_sort(&self, params: AlterSortParams) -> FlowyResult<SortRevision> {
let sort_type = SortType::from(&params);
let is_exist = params.sort_id.is_some();
let sort_id = match params.sort_id {
@ -514,7 +514,7 @@ impl DatabaseViewEditor {
Ok(sort_rev)
}
pub async fn delete_view_sort(&self, params: DeleteSortParams) -> FlowyResult<()> {
pub async fn v_delete_sort(&self, params: DeleteSortParams) -> FlowyResult<()> {
let notification = self
.sort_controller
.write()
@ -537,8 +537,8 @@ impl DatabaseViewEditor {
Ok(())
}
pub async fn delete_all_view_sorts(&self) -> FlowyResult<()> {
let all_sorts = self.get_all_view_sorts().await;
pub async fn v_delete_all_sorts(&self) -> FlowyResult<()> {
let all_sorts = self.v_get_all_sorts().await;
self.sort_controller.write().await.delete_all_sorts().await;
self
.modify(|pad| {
@ -556,12 +556,12 @@ impl DatabaseViewEditor {
Ok(())
}
pub async fn get_all_view_filters(&self) -> Vec<Arc<FilterRevision>> {
pub async fn v_get_all_filters(&self) -> Vec<Arc<FilterRevision>> {
let field_revs = self.delegate.get_field_revs(None).await;
self.pad.read().await.get_all_filters(&field_revs)
}
pub async fn get_view_filters(&self, filter_type: &FilterType) -> Vec<Arc<FilterRevision>> {
pub async fn v_get_filters(&self, filter_type: &FilterType) -> Vec<Arc<FilterRevision>> {
let field_type_rev: FieldTypeRevision = filter_type.field_type.clone().into();
self
.pad
@ -571,7 +571,7 @@ impl DatabaseViewEditor {
}
#[tracing::instrument(level = "trace", skip(self), err)]
pub async fn insert_view_filter(&self, params: AlterFilterParams) -> FlowyResult<()> {
pub async fn v_insert_filter(&self, params: AlterFilterParams) -> FlowyResult<()> {
let filter_type = FilterType::from(&params);
let is_exist = params.filter_id.is_some();
let filter_id = match params.filter_id {
@ -624,7 +624,7 @@ impl DatabaseViewEditor {
}
#[tracing::instrument(level = "trace", skip(self), err)]
pub async fn delete_view_filter(&self, params: DeleteFilterParams) -> FlowyResult<()> {
pub async fn v_delete_filter(&self, params: DeleteFilterParams) -> FlowyResult<()> {
let filter_type = params.filter_type;
let changeset = self
.filter_controller
@ -649,7 +649,7 @@ impl DatabaseViewEditor {
}
/// Returns the current calendar settings
pub async fn get_calendar_settings(&self) -> FlowyResult<CalendarSettingsParams> {
pub async fn v_get_calendar_settings(&self) -> FlowyResult<CalendarSettingsParams> {
let settings = self
.pad
.read()
@ -660,7 +660,10 @@ impl DatabaseViewEditor {
}
/// Update the calendar settings and send the notification to refresh the UI
pub async fn update_calendar_settings(&self, params: CalendarSettingsParams) -> FlowyResult<()> {
pub async fn v_update_calendar_settings(
&self,
params: CalendarSettingsParams,
) -> FlowyResult<()> {
// Maybe it needs no send notification to refresh the UI
self
.modify(|pad| Ok(pad.update_layout_setting(&LayoutRevision::Calendar, &params)?))
@ -669,7 +672,7 @@ impl DatabaseViewEditor {
}
#[tracing::instrument(level = "trace", skip_all, err)]
pub async fn did_update_view_field_type_option(
pub async fn v_did_update_field_type_option(
&self,
field_id: &str,
old_field_rev: Option<Arc<FieldRevision>>,
@ -709,7 +712,7 @@ impl DatabaseViewEditor {
/// * `field_id`:
///
#[tracing::instrument(level = "debug", skip_all, err)]
pub async fn group_by_view_field(&self, field_id: &str) -> FlowyResult<()> {
pub async fn v_update_group_setting(&self, field_id: &str) -> FlowyResult<()> {
if let Some(field_rev) = self.delegate.get_field_rev(field_id).await {
let row_revs = self.delegate.get_row_revs(None).await;
let configuration_reader = GroupConfigurationReaderImpl {
@ -750,7 +753,7 @@ impl DatabaseViewEditor {
Ok(())
}
pub(crate) async fn get_cells_for_field(
pub(crate) async fn v_get_cells_for_field(
&self,
field_id: &str,
) -> FlowyResult<Vec<RowSingleCellData>> {
@ -758,7 +761,7 @@ impl DatabaseViewEditor {
}
async fn notify_did_update_setting(&self) {
let setting = self.get_view_setting().await;
let setting = self.v_get_setting().await;
send_notification(&self.view_id, DatabaseNotification::DidUpdateSettings)
.payload(setting)
.send();

View File

@ -84,8 +84,8 @@ impl DatabaseViews {
.get_row_revs(Some(vec![block_id.to_owned()]))
.await;
if let Ok(view_editor) = self.get_view_editor(view_id).await {
view_editor.filter_rows(block_id, &mut row_revs).await;
view_editor.sort_rows(&mut row_revs).await;
view_editor.v_filter_rows(block_id, &mut row_revs).await;
view_editor.v_sort_rows(&mut row_revs).await;
}
Ok(row_revs)
@ -93,21 +93,21 @@ impl DatabaseViews {
pub async fn duplicate_database_view(&self, view_id: &str) -> FlowyResult<String> {
let editor = self.get_view_editor(view_id).await?;
let view_data = editor.duplicate_view_data().await?;
let view_data = editor.v_duplicate_data().await?;
Ok(view_data)
}
/// When the row was created, we may need to modify the [RowRevision] according to the [CreateRowParams].
pub async fn will_create_row(&self, row_rev: &mut RowRevision, params: &CreateRowParams) {
for view_editor in self.view_editors.read().await.values() {
view_editor.will_create_view_row(row_rev, params).await;
view_editor.v_will_create_row(row_rev, params).await;
}
}
/// Notify the view that the row was created. For the moment, the view is just sending notifications.
pub async fn did_create_row(&self, row_pb: &RowPB, params: &CreateRowParams) {
for view_editor in self.view_editors.read().await.values() {
view_editor.did_create_view_row(row_pb, params).await;
view_editor.v_did_create_row(row_pb, params).await;
}
}
@ -120,7 +120,7 @@ impl DatabaseViews {
Some((_, row_rev)) => {
for view_editor in self.view_editors.read().await.values() {
view_editor
.did_update_view_row(old_row_rev.clone(), &row_rev)
.v_did_update_row(old_row_rev.clone(), &row_rev)
.await;
}
},
@ -129,24 +129,24 @@ impl DatabaseViews {
pub async fn group_by_field(&self, view_id: &str, field_id: &str) -> FlowyResult<()> {
let view_editor = self.get_view_editor(view_id).await?;
view_editor.group_by_view_field(field_id).await?;
view_editor.v_update_group_setting(field_id).await?;
Ok(())
}
pub async fn did_delete_row(&self, row_rev: Arc<RowRevision>) {
for view_editor in self.view_editors.read().await.values() {
view_editor.did_delete_view_row(&row_rev).await;
view_editor.v_did_delete_row(&row_rev).await;
}
}
pub async fn get_setting(&self, view_id: &str) -> FlowyResult<DatabaseViewSettingPB> {
let view_editor = self.get_view_editor(view_id).await?;
Ok(view_editor.get_view_setting().await)
Ok(view_editor.v_get_setting().await)
}
pub async fn get_all_filters(&self, view_id: &str) -> FlowyResult<Vec<Arc<FilterRevision>>> {
let view_editor = self.get_view_editor(view_id).await?;
Ok(view_editor.get_all_view_filters().await)
Ok(view_editor.v_get_all_filters().await)
}
pub async fn get_filters(
@ -155,58 +155,58 @@ impl DatabaseViews {
filter_id: &FilterType,
) -> FlowyResult<Vec<Arc<FilterRevision>>> {
let view_editor = self.get_view_editor(view_id).await?;
Ok(view_editor.get_view_filters(filter_id).await)
Ok(view_editor.v_get_filters(filter_id).await)
}
pub async fn create_or_update_filter(&self, params: AlterFilterParams) -> FlowyResult<()> {
let view_editor = self.get_view_editor(&params.view_id).await?;
view_editor.insert_view_filter(params).await
view_editor.v_insert_filter(params).await
}
pub async fn delete_filter(&self, params: DeleteFilterParams) -> FlowyResult<()> {
let view_editor = self.get_view_editor(&params.view_id).await?;
view_editor.delete_view_filter(params).await
view_editor.v_delete_filter(params).await
}
pub async fn get_all_sorts(&self, view_id: &str) -> FlowyResult<Vec<Arc<SortRevision>>> {
let view_editor = self.get_view_editor(view_id).await?;
Ok(view_editor.get_all_view_sorts().await)
Ok(view_editor.v_get_all_sorts().await)
}
pub async fn create_or_update_sort(&self, params: AlterSortParams) -> FlowyResult<SortRevision> {
let view_editor = self.get_view_editor(&params.view_id).await?;
view_editor.insert_view_sort(params).await
view_editor.v_insert_sort(params).await
}
pub async fn delete_all_sorts(&self, view_id: &str) -> FlowyResult<()> {
let view_editor = self.get_view_editor(view_id).await?;
view_editor.delete_all_view_sorts().await
view_editor.v_delete_all_sorts().await
}
pub async fn delete_sort(&self, params: DeleteSortParams) -> FlowyResult<()> {
let view_editor = self.get_view_editor(&params.view_id).await?;
view_editor.delete_view_sort(params).await
view_editor.v_delete_sort(params).await
}
pub async fn load_groups(&self, view_id: &str) -> FlowyResult<RepeatedGroupPB> {
let view_editor = self.get_view_editor(view_id).await?;
let groups = view_editor.load_view_groups().await?;
let groups = view_editor.v_load_groups().await?;
Ok(RepeatedGroupPB { items: groups })
}
pub async fn insert_or_update_group(&self, params: InsertGroupParams) -> FlowyResult<()> {
let view_editor = self.get_view_editor(&params.view_id).await?;
view_editor.initialize_new_group(params).await
view_editor.v_initialize_new_group(params).await
}
pub async fn delete_group(&self, params: DeleteGroupParams) -> FlowyResult<()> {
let view_editor = self.get_view_editor(&params.view_id).await?;
view_editor.delete_view_group(params).await
view_editor.v_delete_group(params).await
}
pub async fn move_group(&self, params: MoveGroupParams) -> FlowyResult<()> {
let view_editor = self.get_view_editor(&params.view_id).await?;
view_editor.move_view_group(params).await?;
view_editor.v_move_group(params).await?;
Ok(())
}
@ -224,7 +224,7 @@ impl DatabaseViews {
let mut row_changeset = RowChangeset::new(row_rev.id.clone());
let view_editor = self.get_view_editor(view_id).await?;
view_editor
.move_view_group_row(
.v_move_group_row(
&row_rev,
&mut row_changeset,
&to_group_id,
@ -246,20 +246,22 @@ impl DatabaseViews {
///
/// * `field_id`: the id of the field in current view
///
#[tracing::instrument(level = "trace", skip(self), err)]
pub async fn did_update_view_field_type_option(
#[tracing::instrument(level = "debug", skip(self, old_field_rev), err)]
pub async fn did_update_field_type_option(
&self,
view_id: &str,
field_id: &str,
old_field_rev: Option<Arc<FieldRevision>>,
) -> FlowyResult<()> {
let view_editor = self.get_view_editor(view_id).await?;
// If the id of the grouping field is equal to the updated field's id, then we need to
// update the group setting
if view_editor.group_id().await == field_id {
view_editor.group_by_view_field(field_id).await?;
view_editor.v_update_group_setting(field_id).await?;
}
view_editor
.did_update_view_field_type_option(field_id, old_field_rev)
.v_did_update_field_type_option(field_id, old_field_rev)
.await?;
Ok(())
}
@ -269,6 +271,7 @@ impl DatabaseViews {
if let Some(editor) = self.view_editors.read().await.get(view_id) {
return Ok(editor);
}
tracing::trace!("{:p} create view:{} editor", self, view_id);
let mut view_editors = self.view_editors.write().await;
let editor = Arc::new(self.make_view_editor(view_id).await?);

View File

@ -26,7 +26,17 @@ use std::sync::Arc;
/// * `configuration_reader`: a reader used to read the group configuration from disk
/// * `configuration_writer`: as writer used to write the group configuration to disk
///
#[tracing::instrument(level = "trace", skip_all, err)]
#[tracing::instrument(
level = "debug",
skip(
row_revs,
configuration_reader,
configuration_writer,
grouping_field_rev
),
fields(grouping_field_id=%grouping_field_rev.id, grouping_field_type)
err
)]
pub async fn make_group_controller<R, W>(
view_id: String,
grouping_field_rev: Arc<FieldRevision>,
@ -39,6 +49,7 @@ where
W: GroupConfigurationWriter,
{
let grouping_field_type: FieldType = grouping_field_rev.ty.into();
tracing::Span::current().record("grouping_field_type", &format!("{}", grouping_field_type));
let mut group_controller: Box<dyn GroupController>;
let configuration_reader = Arc::new(configuration_reader);
@ -99,17 +110,31 @@ where
Ok(group_controller)
}
#[tracing::instrument(level = "debug", skip_all)]
pub fn find_grouping_field(
field_revs: &[Arc<FieldRevision>],
_layout: &LayoutRevision,
) -> Option<Arc<FieldRevision>> {
field_revs
let mut groupable_field_revs = field_revs
.iter()
.find(|field_rev| {
.flat_map(|field_rev| {
let field_type: FieldType = field_rev.ty.into();
field_type.can_be_group()
match field_type.can_be_group() {
true => Some(field_rev.clone()),
false => None,
}
})
.cloned()
.collect::<Vec<Arc<FieldRevision>>>();
if groupable_field_revs.is_empty() {
// If there is not groupable fields then we use the primary field.
field_revs
.iter()
.find(|field_rev| field_rev.is_primary)
.cloned()
} else {
Some(groupable_field_revs.remove(0))
}
}
/// Returns a `default` group configuration for the [FieldRevision]

View File

@ -189,21 +189,21 @@ diesel::table! {
}
diesel::allow_tables_to_appear_in_same_query!(
app_table,
database_refs,
document_rev_snapshot,
document_rev_table,
folder_rev_snapshot,
grid_block_index_table,
grid_meta_rev_table,
grid_rev_snapshot,
grid_rev_table,
grid_view_rev_table,
kv_table,
rev_snapshot,
rev_table,
trash_table,
user_table,
view_table,
workspace_table,
app_table,
database_refs,
document_rev_snapshot,
document_rev_table,
folder_rev_snapshot,
grid_block_index_table,
grid_meta_rev_table,
grid_rev_snapshot,
grid_rev_table,
grid_view_rev_table,
kv_table,
rev_snapshot,
rev_table,
trash_table,
user_table,
view_table,
workspace_table,
);

View File

@ -189,22 +189,35 @@ script = [
]
script_runner = "@duckscript"
[tasks.build-test-lib]
[tasks.build_test_backend]
category = "Build"
dependencies = ["env_check"]
run_task = { name = [
"setup-test-crate-type",
"build-test-backend",
"compile_test_backend",
"copy-to-sandbox-folder",
"restore-test-crate-type",
] }
[tasks.build-test-backend]
mac_alias = "build-test-backend-default"
windows_alias = "build-test-backend-widnows"
linux_alias = "build-test-backend-default"
[tasks.compile_test_backend]
mac_alias = "compile_test_backend_default"
windows_alias = "compile_test_backend_widnows"
linux_alias = "compile_test_backend_default"
[tasks.build-test-backend-default]
[tasks.compile_test_backend_default]
private = true
script = [
"""
cd rust-lib/
rustup show
echo RUST_LOG=${RUST_LOG} cargo build --package=dart-ffi --target ${TEST_COMPILE_TARGET} --features "${FLUTTER_DESKTOP_FEATURES}"
RUST_LOG=${RUST_LOG} cargo build --package=dart-ffi --target ${TEST_COMPILE_TARGET} --features "${FLUTTER_DESKTOP_FEATURES}"
cd ../
""",
]
script_runner = "@shell"
[tasks.compile_test_backend_widnows]
private = true
script = [
"""
@ -217,19 +230,6 @@ script = [
]
script_runner = "@shell"
[tasks.build-test-backend-widnows]
private = true
script = [
"""
cd rust-lib/
rustup show
echo cargo build --package=dart-ffi --target ${TEST_COMPILE_TARGET} --features "${FLUTTER_DESKTOP_FEATURES}"
RUST_LOG=${TEST_RUST_LOG} cargo build --package=dart-ffi --target ${TEST_COMPILE_TARGET} --features "${FLUTTER_DESKTOP_FEATURES}"
cd ../
""",
]
script_runner = "@shell"
[tasks.copy-to-sandbox-folder]
mac_alias = "copy-to-sandbox-folder-default"
windows_alias = "copy-to-sandbox-folder-windows"

View File

@ -1,29 +1,29 @@
[tasks.dart_unit_test]
script = '''
cargo make --profile test-macos dart_unit_test_inner
cargo make --profile test-macos dart_unit_test_impl
'''
script_runner = "@shell"
[tasks.dart_unit_test.windows]
script = '''
cargo make --profile test-windows dart_unit_test_inner
cargo make --profile test-windows dart_unit_test_impl
'''
script_runner = "@shell"
[tasks.dart_unit_test.linux]
script = '''
cargo make --profile test-linux dart_unit_test_inner
cargo make --profile test-linux dart_unit_test_impl
'''
script_runner = "@shell"
[tasks.dart_unit_test_inner]
env = { RUST_LOG = "info", TEST_RUST_LOG = "info" }
dependencies = ["build-test-lib"]
[tasks.dart_unit_test_impl]
env = { RUST_LOG = "info" }
dependencies = ["build_test_backend"]
description = "Run flutter unit tests"
script = '''
cd appflowy_flutter
flutter test --dart-define=RUST_LOG=${TEST_RUST_LOG} -j, --concurrency=1
flutter test --dart-define=RUST_LOG=${RUST_LOG} -j, --concurrency=1
'''
[tasks.rust_unit_test]

View File

@ -115,7 +115,7 @@ pub struct FieldRevision {
#[serde(with = "indexmap::serde_seq")]
pub type_options: IndexMap<String, String>,
#[serde(default = "DEFAULT_IS_PRIMARY")]
#[serde(default = "DEFAULT_IS_PRIMARY_VALUE")]
pub is_primary: bool,
}
@ -125,7 +125,7 @@ impl AsRef<FieldRevision> for FieldRevision {
}
}
const DEFAULT_IS_PRIMARY: fn() -> bool = || false;
const DEFAULT_IS_PRIMARY_VALUE: fn() -> bool = || false;
impl FieldRevision {
pub fn new<T: Into<FieldTypeRevision>>(