mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: migrate cloud document when the document content is not sync to … (#4108)
* fix: migrate cloud document when the document content is not sync to local * chore: clippy
This commit is contained in:
parent
4837d7f7fe
commit
d86431dfbc
@ -131,7 +131,7 @@ async fn hide_group_event_test() {
|
||||
|
||||
let groups = test.get_groups(&board_view.id).await;
|
||||
assert_eq!(groups.len(), 4);
|
||||
assert_eq!(groups[0].is_visible, false);
|
||||
assert!(!groups[0].is_visible);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -4,7 +4,7 @@ use flowy_core::DEFAULT_NAME;
|
||||
use crate::util::unzip_history_user_db;
|
||||
|
||||
#[tokio::test]
|
||||
async fn migrate_historical_empty_document_test() {
|
||||
async fn collab_db_restore_test() {
|
||||
let (cleaner, user_db_path) = unzip_history_user_db(
|
||||
"./tests/user/migration_test/history_user_db",
|
||||
"038_collab_db_corrupt_restore",
|
||||
|
@ -220,7 +220,7 @@ impl TryInto<CreateFieldParams> for CreateFieldPayloadPB {
|
||||
CreateFieldPosition::Before => {
|
||||
let field_id = self
|
||||
.target_field_id
|
||||
.ok_or_else(|| ErrorCode::InvalidParams)?;
|
||||
.ok_or(ErrorCode::InvalidParams)?;
|
||||
let field_id = NotEmptyStr::parse(field_id)
|
||||
.map_err(|_| ErrorCode::InvalidParams)?
|
||||
.0;
|
||||
@ -229,7 +229,7 @@ impl TryInto<CreateFieldParams> for CreateFieldPayloadPB {
|
||||
CreateFieldPosition::After => {
|
||||
let field_id = self
|
||||
.target_field_id
|
||||
.ok_or_else(|| ErrorCode::InvalidParams)?;
|
||||
.ok_or(ErrorCode::InvalidParams)?;
|
||||
let field_id = NotEmptyStr::parse(field_id)
|
||||
.map_err(|_| ErrorCode::InvalidParams)?
|
||||
.0;
|
||||
@ -564,7 +564,7 @@ pub enum FieldType {
|
||||
|
||||
impl Display for FieldType {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let value: i64 = self.clone().into();
|
||||
let value: i64 = (*self).into();
|
||||
f.write_fmt(format_args!("{}", value))
|
||||
}
|
||||
}
|
||||
@ -577,13 +577,13 @@ impl AsRef<FieldType> for FieldType {
|
||||
|
||||
impl From<&FieldType> for FieldType {
|
||||
fn from(field_type: &FieldType) -> Self {
|
||||
field_type.clone()
|
||||
*field_type
|
||||
}
|
||||
}
|
||||
|
||||
impl FieldType {
|
||||
pub fn value(&self) -> i64 {
|
||||
self.clone().into()
|
||||
(*self).into()
|
||||
}
|
||||
|
||||
pub fn default_name(&self) -> String {
|
||||
@ -666,7 +666,7 @@ impl From<FieldType> for i64 {
|
||||
|
||||
impl From<&FieldType> for i64 {
|
||||
fn from(ty: &FieldType) -> Self {
|
||||
i64::from(ty.clone())
|
||||
i64::from(*ty)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ impl std::convert::From<&Filter> for FilterPB {
|
||||
Self {
|
||||
id: filter.id.clone(),
|
||||
field_id: filter.field_id.clone(),
|
||||
field_type: filter.field_type.clone(),
|
||||
field_type: filter.field_type,
|
||||
data: bytes.to_vec(),
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ impl std::convert::From<&Sort> for SortPB {
|
||||
Self {
|
||||
id: sort.id.clone(),
|
||||
field_id: sort.field_id.clone(),
|
||||
field_type: sort.field_type.clone(),
|
||||
field_type: sort.field_type,
|
||||
condition: sort.condition.into(),
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ impl TypeCellData {
|
||||
pub fn from_field_type(field_type: &FieldType) -> TypeCellData {
|
||||
Self {
|
||||
cell_str: "".to_string(),
|
||||
field_type: field_type.clone(),
|
||||
field_type: *field_type,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,7 +346,7 @@ impl DatabaseEditor {
|
||||
}
|
||||
|
||||
let old_field_type = FieldType::from(field.field_type);
|
||||
let old_type_option = field.get_any_type_option(old_field_type.clone());
|
||||
let old_type_option = field.get_any_type_option(old_field_type);
|
||||
let new_type_option = field
|
||||
.get_any_type_option(new_field_type)
|
||||
.unwrap_or_else(|| default_type_option_data_from_type(new_field_type));
|
||||
@ -464,7 +464,7 @@ impl DatabaseEditor {
|
||||
field.map(|field| {
|
||||
let field_type = FieldType::from(field.field_type);
|
||||
let type_option = field
|
||||
.get_any_type_option(field_type.clone())
|
||||
.get_any_type_option(field_type)
|
||||
.unwrap_or_else(|| default_type_option_data_from_type(&field_type));
|
||||
(field, type_option_to_pb(type_option, &field_type))
|
||||
})
|
||||
@ -1265,7 +1265,7 @@ impl DatabaseViewOperation for DatabaseViewOperationImpl {
|
||||
let (_, field) = self.database.lock().create_field_with_mut(
|
||||
view_id,
|
||||
name.to_string(),
|
||||
field_type.clone().into(),
|
||||
field_type.into(),
|
||||
&OrderObjectPosition::default(),
|
||||
|field| {
|
||||
field
|
||||
|
@ -139,7 +139,7 @@ impl DatabaseLayoutDepsResolver {
|
||||
Field::new(
|
||||
field_id,
|
||||
"Date".to_string(),
|
||||
field_type.clone().into(),
|
||||
field_type.into(),
|
||||
false,
|
||||
)
|
||||
.with_type_option_data(field_type, default_date_type_option.into())
|
||||
@ -152,7 +152,7 @@ impl DatabaseLayoutDepsResolver {
|
||||
Field::new(
|
||||
field_id,
|
||||
"Status".to_string(),
|
||||
field_type.clone().into(),
|
||||
field_type.into(),
|
||||
false,
|
||||
)
|
||||
.with_type_option_data(field_type, default_select_type_option.into())
|
||||
|
@ -118,7 +118,7 @@ pub(crate) async fn get_cell_for_row(
|
||||
Some(RowSingleCellData {
|
||||
row_id: row_cell.row_id.clone(),
|
||||
field_id: field.id.clone(),
|
||||
field_type: field_type.clone(),
|
||||
field_type,
|
||||
cell_data,
|
||||
})
|
||||
}
|
||||
@ -143,7 +143,7 @@ pub(crate) async fn get_cells_for_field(
|
||||
RowSingleCellData {
|
||||
row_id: row_cell.row_id.clone(),
|
||||
field_id: field.id.clone(),
|
||||
field_type: field_type.clone(),
|
||||
field_type,
|
||||
cell_data,
|
||||
}
|
||||
})
|
||||
|
@ -12,7 +12,7 @@ impl FieldBuilder {
|
||||
let mut field = Field::new(
|
||||
gen_field_id(),
|
||||
"".to_string(),
|
||||
field_type.clone().into(),
|
||||
field_type.into(),
|
||||
false,
|
||||
);
|
||||
field.width = 150;
|
||||
|
@ -12,7 +12,7 @@ mod tests {
|
||||
fn checkout_box_description_test() {
|
||||
let type_option = CheckboxTypeOption::default();
|
||||
let field_type = FieldType::Checkbox;
|
||||
let field_rev = FieldBuilder::from_field_type(field_type.clone()).build();
|
||||
let field_rev = FieldBuilder::from_field_type(field_type).build();
|
||||
|
||||
// the checkout value will be checked if the value is "1", "true" or "yes"
|
||||
assert_checkbox(&type_option, "1", CHECK, &field_type, &field_rev);
|
||||
|
@ -12,7 +12,7 @@ mod tests {
|
||||
fn number_type_option_input_test() {
|
||||
let type_option = NumberTypeOption::default();
|
||||
let field_type = FieldType::Number;
|
||||
let field = FieldBuilder::from_field_type(field_type.clone()).build();
|
||||
let field = FieldBuilder::from_field_type(field_type).build();
|
||||
|
||||
// Input is empty String
|
||||
assert_number(&type_option, "", "", &field_type, &field);
|
||||
@ -31,7 +31,7 @@ mod tests {
|
||||
let field_type = FieldType::Number;
|
||||
let mut type_option = NumberTypeOption::new();
|
||||
type_option.format = NumberFormat::USD;
|
||||
let field = FieldBuilder::new(field_type.clone(), type_option.clone()).build();
|
||||
let field = FieldBuilder::new(field_type, type_option.clone()).build();
|
||||
|
||||
assert_number(&type_option, "", "", &field_type, &field);
|
||||
assert_number(&type_option, "abc", "", &field_type, &field);
|
||||
@ -49,7 +49,7 @@ mod tests {
|
||||
let field_type = FieldType::Number;
|
||||
let mut type_option = NumberTypeOption::new();
|
||||
type_option.format = NumberFormat::USD;
|
||||
let field = FieldBuilder::new(field_type.clone(), type_option.clone()).build();
|
||||
let field = FieldBuilder::new(field_type, type_option.clone()).build();
|
||||
|
||||
assert_number(
|
||||
&type_option,
|
||||
@ -71,7 +71,7 @@ mod tests {
|
||||
let field_type = FieldType::Number;
|
||||
let mut type_option = NumberTypeOption::new();
|
||||
type_option.format = NumberFormat::USD;
|
||||
let field = FieldBuilder::new(field_type.clone(), type_option.clone()).build();
|
||||
let field = FieldBuilder::new(field_type, type_option.clone()).build();
|
||||
|
||||
assert_number(&type_option, "€0.2", "$0.2", &field_type, &field);
|
||||
assert_number(&type_option, "-€0.2", "-$0.2", &field_type, &field);
|
||||
@ -85,7 +85,7 @@ mod tests {
|
||||
let field_type = FieldType::Number;
|
||||
let mut type_option = NumberTypeOption::new();
|
||||
type_option.format = NumberFormat::EUR;
|
||||
let field = FieldBuilder::new(field_type.clone(), type_option.clone()).build();
|
||||
let field = FieldBuilder::new(field_type, type_option.clone()).build();
|
||||
|
||||
assert_number(&type_option, "0.2", "€0,2", &field_type, &field);
|
||||
assert_number(&type_option, "1000", "€1.000", &field_type, &field);
|
||||
|
@ -12,7 +12,7 @@ mod tests {
|
||||
#[test]
|
||||
fn date_type_to_text_type() {
|
||||
let field_type = FieldType::DateTime;
|
||||
let field = FieldBuilder::new(field_type.clone(), DateTypeOption::test()).build();
|
||||
let field = FieldBuilder::new(field_type, DateTypeOption::test()).build();
|
||||
|
||||
assert_eq!(
|
||||
stringify_cell_data(
|
||||
@ -77,7 +77,7 @@ mod tests {
|
||||
options: vec![done_option.clone()],
|
||||
disable_color: false,
|
||||
};
|
||||
let field = FieldBuilder::new(field_type.clone(), single_select).build();
|
||||
let field = FieldBuilder::new(field_type, single_select).build();
|
||||
|
||||
assert_eq!(
|
||||
stringify_cell_data(
|
||||
@ -107,7 +107,7 @@ mod tests {
|
||||
let france_option_id = france.id;
|
||||
let argentina_option_id = argentina.id;
|
||||
|
||||
let field_rev = FieldBuilder::new(field_type.clone(), multi_select).build();
|
||||
let field_rev = FieldBuilder::new(field_type, multi_select).build();
|
||||
|
||||
assert_eq!(
|
||||
stringify_cell_data(
|
||||
|
@ -272,7 +272,7 @@ pub fn default_type_option_data_from_type(field_type: &FieldType) -> TypeOptionD
|
||||
FieldType::Number => NumberTypeOption::default().into(),
|
||||
FieldType::DateTime => DateTypeOption::default().into(),
|
||||
FieldType::LastEditedTime | FieldType::CreatedTime => TimestampTypeOption {
|
||||
field_type: field_type.clone(),
|
||||
field_type: *field_type,
|
||||
date_format: DateFormat::Friendly,
|
||||
time_format: TimeFormat::TwelveHour,
|
||||
include_time: true,
|
||||
|
@ -78,7 +78,7 @@ struct CellDataCacheKey(u64);
|
||||
impl CellDataCacheKey {
|
||||
pub fn new(field_rev: &Field, decoded_field_type: FieldType, cell: &Cell) -> Self {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
if let Some(type_option_data) = field_rev.get_any_type_option(&decoded_field_type) {
|
||||
if let Some(type_option_data) = field_rev.get_any_type_option(decoded_field_type) {
|
||||
type_option_data.hash(&mut hasher);
|
||||
}
|
||||
hasher.write(field_rev.id.as_bytes());
|
||||
@ -141,7 +141,7 @@ where
|
||||
decoded_field_type: &FieldType,
|
||||
field: &Field,
|
||||
) -> FlowyResult<<Self as TypeOption>::CellData> {
|
||||
let key = CellDataCacheKey::new(field, decoded_field_type.clone(), cell);
|
||||
let key = CellDataCacheKey::new(field, *decoded_field_type, cell);
|
||||
if let Some(cell_data_cache) = self.cell_data_cache.as_ref() {
|
||||
let read_guard = cell_data_cache.read();
|
||||
if let Some(cell_data) = read_guard.get(key.as_ref()).cloned() {
|
||||
|
@ -117,7 +117,7 @@ impl std::convert::From<&Filter> for FilterType {
|
||||
Self {
|
||||
filter_id: filter.id.clone(),
|
||||
field_id: filter.field_id.clone(),
|
||||
field_type: filter.field_type.clone(),
|
||||
field_type: filter.field_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -127,7 +127,7 @@ impl std::convert::From<&FilterPB> for FilterType {
|
||||
Self {
|
||||
filter_id: filter.id.clone(),
|
||||
field_id: filter.field_id.clone(),
|
||||
field_type: filter.field_type.clone(),
|
||||
field_type: filter.field_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ fn default_field(field_str: String, is_primary: bool) -> Field {
|
||||
Field::new(
|
||||
gen_field_id(),
|
||||
field_str,
|
||||
field_type.clone().into(),
|
||||
field_type.into(),
|
||||
is_primary,
|
||||
)
|
||||
.with_type_option_data(field_type, type_option_data)
|
||||
|
@ -240,7 +240,7 @@ fn cmp_row(
|
||||
fields: &[Arc<Field>],
|
||||
cell_data_cache: &CellCache,
|
||||
) -> Ordering {
|
||||
let field_type = sort.field_type.clone();
|
||||
let field_type = sort.field_type;
|
||||
match fields
|
||||
.iter()
|
||||
.find(|field_rev| field_rev.id == sort.field_id)
|
||||
|
@ -109,7 +109,7 @@ impl From<&Sort> for SortType {
|
||||
Self {
|
||||
sort_id: data.id.clone(),
|
||||
field_id: data.field_id.clone(),
|
||||
field_type: data.field_type.clone(),
|
||||
field_type: data.field_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ impl DatabaseEditorTest {
|
||||
|
||||
pub fn get_multi_select_type_option(&self, field_id: &str) -> Vec<SelectOption> {
|
||||
let field_type = FieldType::MultiSelect;
|
||||
let field = self.get_field(field_id, field_type.clone());
|
||||
let field = self.get_field(field_id, field_type);
|
||||
let type_option = field
|
||||
.get_type_option::<MultiSelectTypeOption>(field_type)
|
||||
.unwrap();
|
||||
@ -156,7 +156,7 @@ impl DatabaseEditorTest {
|
||||
|
||||
pub fn get_single_select_type_option(&self, field_id: &str) -> SingleSelectTypeOption {
|
||||
let field_type = FieldType::SingleSelect;
|
||||
let field = self.get_field(field_id, field_type.clone());
|
||||
let field = self.get_field(field_id, field_type);
|
||||
field
|
||||
.get_type_option::<SingleSelectTypeOption>(field_type)
|
||||
.unwrap()
|
||||
@ -165,7 +165,7 @@ impl DatabaseEditorTest {
|
||||
#[allow(dead_code)]
|
||||
pub fn get_checklist_type_option(&self, field_id: &str) -> ChecklistTypeOption {
|
||||
let field_type = FieldType::Checklist;
|
||||
let field = self.get_field(field_id, field_type.clone());
|
||||
let field = self.get_field(field_id, field_type);
|
||||
field
|
||||
.get_type_option::<ChecklistTypeOption>(field_type)
|
||||
.unwrap()
|
||||
@ -174,7 +174,7 @@ impl DatabaseEditorTest {
|
||||
#[allow(dead_code)]
|
||||
pub fn get_checkbox_type_option(&self, field_id: &str) -> CheckboxTypeOption {
|
||||
let field_type = FieldType::Checkbox;
|
||||
let field = self.get_field(field_id, field_type.clone());
|
||||
let field = self.get_field(field_id, field_type);
|
||||
field
|
||||
.get_type_option::<CheckboxTypeOption>(field_type)
|
||||
.unwrap()
|
||||
|
@ -1,5 +1,6 @@
|
||||
use collab_database::fields::Field;
|
||||
use collab_database::views::OrderObjectPosition;
|
||||
|
||||
use flowy_database2::entities::{CreateFieldParams, FieldType};
|
||||
use flowy_database2::services::field::{
|
||||
type_option_to_pb, DateCellChangeset, DateFormat, DateTypeOption, FieldBuilder,
|
||||
@ -9,7 +10,7 @@ use flowy_database2::services::field::{
|
||||
pub fn create_text_field(grid_id: &str) -> (CreateFieldParams, Field) {
|
||||
let field_type = FieldType::RichText;
|
||||
let type_option = RichTextTypeOption::default();
|
||||
let text_field = FieldBuilder::new(field_type.clone(), type_option.clone())
|
||||
let text_field = FieldBuilder::new(field_type, type_option.clone())
|
||||
.name("Name")
|
||||
.visibility(true)
|
||||
.primary(true)
|
||||
@ -31,7 +32,7 @@ pub fn create_single_select_field(grid_id: &str) -> (CreateFieldParams, Field) {
|
||||
let mut type_option = SingleSelectTypeOption::default();
|
||||
type_option.options.push(SelectOption::new("Done"));
|
||||
type_option.options.push(SelectOption::new("Progress"));
|
||||
let single_select_field = FieldBuilder::new(field_type.clone(), type_option.clone())
|
||||
let single_select_field = FieldBuilder::new(field_type, type_option.clone())
|
||||
.name("Name")
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -76,17 +77,15 @@ pub fn create_timestamp_field(grid_id: &str, field_type: FieldType) -> (CreateFi
|
||||
date_format: DateFormat::US,
|
||||
time_format: TimeFormat::TwentyFourHour,
|
||||
include_time: true,
|
||||
field_type: field_type.clone(),
|
||||
field_type,
|
||||
};
|
||||
|
||||
let field: Field = match field_type {
|
||||
FieldType::LastEditedTime => {
|
||||
FieldBuilder::new(field_type.clone(), timestamp_type_option.clone())
|
||||
.name("Updated At")
|
||||
.visibility(true)
|
||||
.build()
|
||||
},
|
||||
FieldType::CreatedTime => FieldBuilder::new(field_type.clone(), timestamp_type_option.clone())
|
||||
FieldType::LastEditedTime => FieldBuilder::new(field_type, timestamp_type_option.clone())
|
||||
.name("Updated At")
|
||||
.visibility(true)
|
||||
.build(),
|
||||
FieldType::CreatedTime => FieldBuilder::new(field_type, timestamp_type_option.clone())
|
||||
.name("Created At")
|
||||
.visibility(true)
|
||||
.build(),
|
||||
|
@ -1,7 +1,5 @@
|
||||
use collab_database::database::{gen_database_id, gen_database_view_id, gen_row_id, DatabaseData};
|
||||
use collab_database::views::{DatabaseLayout, DatabaseView, LayoutSetting, LayoutSettings};
|
||||
use flowy_database2::services::field_settings::default_field_settings_for_fields;
|
||||
use flowy_database2::services::setting::BoardLayoutSetting;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use flowy_database2::entities::FieldType;
|
||||
@ -10,6 +8,8 @@ use flowy_database2::services::field::{
|
||||
DateFormat, DateTypeOption, FieldBuilder, MultiSelectTypeOption, SelectOption, SelectOptionColor,
|
||||
SingleSelectTypeOption, TimeFormat, TimestampTypeOption,
|
||||
};
|
||||
use flowy_database2::services::field_settings::default_field_settings_for_fields;
|
||||
use flowy_database2::services::setting::BoardLayoutSetting;
|
||||
|
||||
use crate::database::database_editor::TestRowBuilder;
|
||||
use crate::database::mock_data::{COMPLETED, FACEBOOK, GOOGLE, PAUSED, PLANNED, TWITTER};
|
||||
@ -22,7 +22,7 @@ pub fn make_test_board() -> DatabaseData {
|
||||
for field_type in FieldType::iter() {
|
||||
match field_type {
|
||||
FieldType::RichText => {
|
||||
let text_field = FieldBuilder::from_field_type(field_type.clone())
|
||||
let text_field = FieldBuilder::from_field_type(field_type)
|
||||
.name("Name")
|
||||
.visibility(true)
|
||||
.primary(true)
|
||||
@ -31,7 +31,7 @@ pub fn make_test_board() -> DatabaseData {
|
||||
},
|
||||
FieldType::Number => {
|
||||
// Number
|
||||
let number_field = FieldBuilder::from_field_type(field_type.clone())
|
||||
let number_field = FieldBuilder::from_field_type(field_type)
|
||||
.name("Price")
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -45,7 +45,7 @@ pub fn make_test_board() -> DatabaseData {
|
||||
timezone_id: "Etc/UTC".to_owned(),
|
||||
};
|
||||
let name = "Time";
|
||||
let date_field = FieldBuilder::new(field_type.clone(), date_type_option)
|
||||
let date_field = FieldBuilder::new(field_type, date_type_option)
|
||||
.name(name)
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -57,14 +57,14 @@ pub fn make_test_board() -> DatabaseData {
|
||||
date_format: DateFormat::US,
|
||||
time_format: TimeFormat::TwentyFourHour,
|
||||
include_time: true,
|
||||
field_type: field_type.clone(),
|
||||
field_type,
|
||||
};
|
||||
let name = match field_type {
|
||||
FieldType::LastEditedTime => "Last Modified",
|
||||
FieldType::CreatedTime => "Created At",
|
||||
_ => "",
|
||||
};
|
||||
let date_field = FieldBuilder::new(field_type.clone(), date_type_option)
|
||||
let date_field = FieldBuilder::new(field_type, date_type_option)
|
||||
.name(name)
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -79,7 +79,7 @@ pub fn make_test_board() -> DatabaseData {
|
||||
single_select_type_option
|
||||
.options
|
||||
.extend(vec![option1, option2, option3]);
|
||||
let single_select_field = FieldBuilder::new(field_type.clone(), single_select_type_option)
|
||||
let single_select_field = FieldBuilder::new(field_type, single_select_type_option)
|
||||
.name("Status")
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -92,7 +92,7 @@ pub fn make_test_board() -> DatabaseData {
|
||||
let option3 = SelectOption::with_color(TWITTER, SelectOptionColor::Yellow);
|
||||
let mut type_option = MultiSelectTypeOption::default();
|
||||
type_option.options.extend(vec![option1, option2, option3]);
|
||||
let multi_select_field = FieldBuilder::new(field_type.clone(), type_option)
|
||||
let multi_select_field = FieldBuilder::new(field_type, type_option)
|
||||
.name("Platform")
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -100,7 +100,7 @@ pub fn make_test_board() -> DatabaseData {
|
||||
},
|
||||
FieldType::Checkbox => {
|
||||
// Checkbox
|
||||
let checkbox_field = FieldBuilder::from_field_type(field_type.clone())
|
||||
let checkbox_field = FieldBuilder::from_field_type(field_type)
|
||||
.name("is urgent")
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -108,7 +108,7 @@ pub fn make_test_board() -> DatabaseData {
|
||||
},
|
||||
FieldType::URL => {
|
||||
// URL
|
||||
let url = FieldBuilder::from_field_type(field_type.clone())
|
||||
let url = FieldBuilder::from_field_type(field_type)
|
||||
.name("link")
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -120,7 +120,7 @@ pub fn make_test_board() -> DatabaseData {
|
||||
// let option3 = SelectOption::with_color(THIRD_THING, SelectOptionColor::Yellow);
|
||||
let type_option = ChecklistTypeOption::default();
|
||||
// type_option.options.extend(vec![option1, option2, option3]);
|
||||
let checklist_field = FieldBuilder::new(field_type.clone(), type_option)
|
||||
let checklist_field = FieldBuilder::new(field_type, type_option)
|
||||
.name("TODO")
|
||||
.visibility(true)
|
||||
.build();
|
||||
|
@ -1,6 +1,5 @@
|
||||
use collab_database::database::{gen_database_id, gen_database_view_id, gen_row_id, DatabaseData};
|
||||
use collab_database::views::{DatabaseLayout, DatabaseView};
|
||||
use flowy_database2::services::field_settings::default_field_settings_for_fields;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use flowy_database2::entities::FieldType;
|
||||
@ -9,6 +8,7 @@ use flowy_database2::services::field::{
|
||||
DateFormat, DateTypeOption, FieldBuilder, MultiSelectTypeOption, NumberFormat, NumberTypeOption,
|
||||
SelectOption, SelectOptionColor, SingleSelectTypeOption, TimeFormat, TimestampTypeOption,
|
||||
};
|
||||
use flowy_database2::services::field_settings::default_field_settings_for_fields;
|
||||
|
||||
use crate::database::database_editor::TestRowBuilder;
|
||||
use crate::database::mock_data::{COMPLETED, FACEBOOK, GOOGLE, PAUSED, PLANNED, TWITTER};
|
||||
@ -21,7 +21,7 @@ pub fn make_test_grid() -> DatabaseData {
|
||||
for field_type in FieldType::iter() {
|
||||
match field_type {
|
||||
FieldType::RichText => {
|
||||
let text_field = FieldBuilder::from_field_type(field_type.clone())
|
||||
let text_field = FieldBuilder::from_field_type(field_type)
|
||||
.name("Name")
|
||||
.visibility(true)
|
||||
.primary(true)
|
||||
@ -33,7 +33,7 @@ pub fn make_test_grid() -> DatabaseData {
|
||||
let mut type_option = NumberTypeOption::default();
|
||||
type_option.set_format(NumberFormat::USD);
|
||||
|
||||
let number_field = FieldBuilder::new(field_type.clone(), type_option)
|
||||
let number_field = FieldBuilder::new(field_type, type_option)
|
||||
.name("Price")
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -47,7 +47,7 @@ pub fn make_test_grid() -> DatabaseData {
|
||||
timezone_id: "Etc/UTC".to_owned(),
|
||||
};
|
||||
let name = "Time";
|
||||
let date_field = FieldBuilder::new(field_type.clone(), date_type_option)
|
||||
let date_field = FieldBuilder::new(field_type, date_type_option)
|
||||
.name(name)
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -59,14 +59,14 @@ pub fn make_test_grid() -> DatabaseData {
|
||||
date_format: DateFormat::US,
|
||||
time_format: TimeFormat::TwentyFourHour,
|
||||
include_time: true,
|
||||
field_type: field_type.clone(),
|
||||
field_type,
|
||||
};
|
||||
let name = match field_type {
|
||||
FieldType::LastEditedTime => "Last Modified",
|
||||
FieldType::CreatedTime => "Created At",
|
||||
_ => "",
|
||||
};
|
||||
let timestamp_field = FieldBuilder::new(field_type.clone(), timestamp_type_option)
|
||||
let timestamp_field = FieldBuilder::new(field_type, timestamp_type_option)
|
||||
.name(name)
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -81,7 +81,7 @@ pub fn make_test_grid() -> DatabaseData {
|
||||
single_select_type_option
|
||||
.options
|
||||
.extend(vec![option1, option2, option3]);
|
||||
let single_select_field = FieldBuilder::new(field_type.clone(), single_select_type_option)
|
||||
let single_select_field = FieldBuilder::new(field_type, single_select_type_option)
|
||||
.name("Status")
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -94,7 +94,7 @@ pub fn make_test_grid() -> DatabaseData {
|
||||
let option3 = SelectOption::with_color(TWITTER, SelectOptionColor::Yellow);
|
||||
let mut type_option = MultiSelectTypeOption::default();
|
||||
type_option.options.extend(vec![option1, option2, option3]);
|
||||
let multi_select_field = FieldBuilder::new(field_type.clone(), type_option)
|
||||
let multi_select_field = FieldBuilder::new(field_type, type_option)
|
||||
.name("Platform")
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -102,7 +102,7 @@ pub fn make_test_grid() -> DatabaseData {
|
||||
},
|
||||
FieldType::Checkbox => {
|
||||
// Checkbox
|
||||
let checkbox_field = FieldBuilder::from_field_type(field_type.clone())
|
||||
let checkbox_field = FieldBuilder::from_field_type(field_type)
|
||||
.name("is urgent")
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -110,7 +110,7 @@ pub fn make_test_grid() -> DatabaseData {
|
||||
},
|
||||
FieldType::URL => {
|
||||
// URL
|
||||
let url = FieldBuilder::from_field_type(field_type.clone())
|
||||
let url = FieldBuilder::from_field_type(field_type)
|
||||
.name("link")
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -122,7 +122,7 @@ pub fn make_test_grid() -> DatabaseData {
|
||||
// let option3 = SelectOption::with_color(THIRD_THING, SelectOptionColor::Yellow);
|
||||
let type_option = ChecklistTypeOption::default();
|
||||
// type_option.options.extend(vec![option1, option2, option3]);
|
||||
let checklist_field = FieldBuilder::new(field_type.clone(), type_option)
|
||||
let checklist_field = FieldBuilder::new(field_type, type_option)
|
||||
.name("TODO")
|
||||
.visibility(true)
|
||||
.build();
|
||||
@ -274,7 +274,7 @@ pub fn make_no_date_test_grid() -> DatabaseData {
|
||||
for field_type in FieldType::iter() {
|
||||
match field_type {
|
||||
FieldType::RichText => {
|
||||
let text_field = FieldBuilder::from_field_type(field_type.clone())
|
||||
let text_field = FieldBuilder::from_field_type(field_type)
|
||||
.name("Name")
|
||||
.visibility(true)
|
||||
.primary(true)
|
||||
@ -286,7 +286,7 @@ pub fn make_no_date_test_grid() -> DatabaseData {
|
||||
let mut type_option = NumberTypeOption::default();
|
||||
type_option.set_format(NumberFormat::USD);
|
||||
|
||||
let number_field = FieldBuilder::new(field_type.clone(), type_option)
|
||||
let number_field = FieldBuilder::new(field_type, type_option)
|
||||
.name("Price")
|
||||
.visibility(true)
|
||||
.build();
|
||||
|
@ -234,7 +234,8 @@ impl UserManager {
|
||||
Box::new(HistoricalEmptyDocumentMigration),
|
||||
Box::new(FavoriteV1AndWorkspaceArrayMigration),
|
||||
];
|
||||
match UserLocalDataMigration::new(session.clone(), collab_db, sqlite_pool).run(migrations)
|
||||
match UserLocalDataMigration::new(session.clone(), collab_db, sqlite_pool)
|
||||
.run(migrations, ¤t_authenticator)
|
||||
{
|
||||
Ok(applied_migrations) => {
|
||||
if !applied_migrations.is_empty() {
|
||||
|
@ -9,6 +9,7 @@ use tracing::{event, instrument};
|
||||
|
||||
use collab_integrate::{PersistenceError, RocksCollabDB, YrsDocAction};
|
||||
use flowy_error::{internal_error, FlowyError, FlowyResult};
|
||||
use flowy_user_deps::entities::Authenticator;
|
||||
|
||||
use crate::migrations::migration::UserDataMigration;
|
||||
use crate::migrations::util::load_collab;
|
||||
@ -23,7 +24,18 @@ impl UserDataMigration for HistoricalEmptyDocumentMigration {
|
||||
}
|
||||
|
||||
#[instrument(name = "HistoricalEmptyDocumentMigration", skip_all, err)]
|
||||
fn run(&self, session: &Session, collab_db: &Arc<RocksCollabDB>) -> FlowyResult<()> {
|
||||
fn run(
|
||||
&self,
|
||||
session: &Session,
|
||||
collab_db: &Arc<RocksCollabDB>,
|
||||
authenticator: &Authenticator,
|
||||
) -> FlowyResult<()> {
|
||||
// - The `empty document` struct has already undergone refactoring prior to the launch of the AppFlowy cloud version.
|
||||
// - Consequently, if a user is utilizing the AppFlowy cloud version, there is no need to perform any migration for the `empty document` struct.
|
||||
// - This migration step is only necessary for users who are transitioning from a local version of AppFlowy to the cloud version.
|
||||
if !matches!(authenticator, Authenticator::Local) {
|
||||
return Ok(());
|
||||
}
|
||||
let write_txn = collab_db.write_txn();
|
||||
let origin = CollabOrigin::Client(CollabClient::new(session.user_id, "phantom"));
|
||||
let folder_collab = match load_collab(session.user_id, &write_txn, &session.user_workspace.id) {
|
||||
@ -37,7 +49,7 @@ impl UserDataMigration for HistoricalEmptyDocumentMigration {
|
||||
// For historical reasons, the first level documents are empty. So migrate them by inserting
|
||||
// the default document data.
|
||||
for view in migration_views {
|
||||
if let Err(_) = migrate_empty_document(&write_txn, &origin, &view, session.user_id) {
|
||||
if migrate_empty_document(&write_txn, &origin, &view, session.user_id).is_err() {
|
||||
event!(
|
||||
tracing::Level::ERROR,
|
||||
"Failed to migrate document {}",
|
||||
@ -46,7 +58,6 @@ impl UserDataMigration for HistoricalEmptyDocumentMigration {
|
||||
}
|
||||
}
|
||||
|
||||
event!(tracing::Level::INFO, "Save all migrated documents");
|
||||
write_txn.commit_transaction().map_err(internal_error)?;
|
||||
Ok(())
|
||||
}
|
||||
@ -62,6 +73,7 @@ where
|
||||
W: YrsDocAction<'a>,
|
||||
PersistenceError: From<W::Error>,
|
||||
{
|
||||
// If the document is not exist, we don't need to migrate it.
|
||||
if load_collab(user_id, write_txn, &view.id).is_err() {
|
||||
let collab = Arc::new(MutexCollab::new(origin.clone(), &view.id, vec![]));
|
||||
let document = Document::create_with_data(collab, default_document_data())?;
|
||||
|
@ -7,6 +7,7 @@ use collab_integrate::RocksCollabDB;
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_sqlite::schema::user_data_migration_records;
|
||||
use flowy_sqlite::ConnectionPool;
|
||||
use flowy_user_deps::entities::Authenticator;
|
||||
|
||||
use crate::services::entities::Session;
|
||||
|
||||
@ -42,7 +43,11 @@ impl UserLocalDataMigration {
|
||||
///
|
||||
/// * `migrations` - A vector of boxed dynamic `UserDataMigration` objects representing the migrations to be applied.
|
||||
///
|
||||
pub fn run(self, migrations: Vec<Box<dyn UserDataMigration>>) -> FlowyResult<Vec<String>> {
|
||||
pub fn run(
|
||||
self,
|
||||
migrations: Vec<Box<dyn UserDataMigration>>,
|
||||
authenticator: &Authenticator,
|
||||
) -> FlowyResult<Vec<String>> {
|
||||
let mut applied_migrations = vec![];
|
||||
let conn = self.sqlite_pool.get()?;
|
||||
let record = get_all_records(&conn)?;
|
||||
@ -54,7 +59,7 @@ impl UserLocalDataMigration {
|
||||
{
|
||||
let migration_name = migration.name().to_string();
|
||||
if !duplicated_names.contains(&migration_name) {
|
||||
migration.run(&self.session, &self.collab_db)?;
|
||||
migration.run(&self.session, &self.collab_db, authenticator)?;
|
||||
applied_migrations.push(migration.name().to_string());
|
||||
save_record(&conn, &migration_name);
|
||||
duplicated_names.push(migration_name);
|
||||
@ -70,7 +75,12 @@ impl UserLocalDataMigration {
|
||||
pub trait UserDataMigration {
|
||||
/// Migration with the same name will be skipped
|
||||
fn name(&self) -> &str;
|
||||
fn run(&self, user: &Session, collab_db: &Arc<RocksCollabDB>) -> FlowyResult<()>;
|
||||
fn run(
|
||||
&self,
|
||||
user: &Session,
|
||||
collab_db: &Arc<RocksCollabDB>,
|
||||
authenticator: &Authenticator,
|
||||
) -> FlowyResult<()>;
|
||||
}
|
||||
|
||||
fn save_record(conn: &SqliteConnection, migration_name: &str) {
|
||||
|
@ -5,6 +5,7 @@ use tracing::instrument;
|
||||
|
||||
use collab_integrate::{RocksCollabDB, YrsDocAction};
|
||||
use flowy_error::{internal_error, FlowyResult};
|
||||
use flowy_user_deps::entities::Authenticator;
|
||||
|
||||
use crate::migrations::migration::UserDataMigration;
|
||||
use crate::migrations::util::load_collab;
|
||||
@ -21,7 +22,19 @@ impl UserDataMigration for FavoriteV1AndWorkspaceArrayMigration {
|
||||
}
|
||||
|
||||
#[instrument(name = "FavoriteV1AndWorkspaceArrayMigration", skip_all, err)]
|
||||
fn run(&self, session: &Session, collab_db: &Arc<RocksCollabDB>) -> FlowyResult<()> {
|
||||
fn run(
|
||||
&self,
|
||||
session: &Session,
|
||||
collab_db: &Arc<RocksCollabDB>,
|
||||
authenticator: &Authenticator,
|
||||
) -> FlowyResult<()> {
|
||||
// Note on `favorite` Struct Refactoring and Migration:
|
||||
// - The `favorite` struct has already undergone refactoring prior to the launch of the AppFlowy cloud version.
|
||||
// - Consequently, if a user is utilizing the AppFlowy cloud version, there is no need to perform any migration for the `favorite` struct.
|
||||
// - This migration step is only necessary for users who are transitioning from a local version of AppFlowy to the cloud version.
|
||||
if !matches!(authenticator, Authenticator::Local) {
|
||||
return Ok(());
|
||||
}
|
||||
let write_txn = collab_db.write_txn();
|
||||
if let Ok(collab) = load_collab(session.user_id, &write_txn, &session.user_workspace.id) {
|
||||
let folder = Folder::open(session.user_id, collab, None)?;
|
||||
|
Loading…
Reference in New Issue
Block a user