mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: fix unit test
This commit is contained in:
parent
c6edd1a6da
commit
afc563d781
@ -2,7 +2,7 @@ part of 'cell_service.dart';
|
||||
|
||||
typedef GridCellContext = _GridCellContext<Cell, String>;
|
||||
typedef GridSelectOptionCellContext = _GridCellContext<SelectOptionCellData, String>;
|
||||
typedef GridDateCellContext = _GridCellContext<DateCellData, DateCellPersistenceData>;
|
||||
typedef GridDateCellContext = _GridCellContext<DateCellData, DateCalData>;
|
||||
|
||||
class GridCellContextBuilder {
|
||||
final GridCellCache _cellCache;
|
||||
|
@ -31,23 +31,26 @@ class CellDataPersistence implements _GridCellDataPersistence<String> {
|
||||
}
|
||||
|
||||
@freezed
|
||||
class DateCellPersistenceData with _$DateCellPersistenceData {
|
||||
const factory DateCellPersistenceData({required DateTime date, String? time}) = _DateCellPersistenceData;
|
||||
class DateCalData with _$DateCalData {
|
||||
const factory DateCalData({required DateTime date, String? time}) = _DateCellPersistenceData;
|
||||
}
|
||||
|
||||
class DateCellDataPersistence implements _GridCellDataPersistence<DateCellPersistenceData> {
|
||||
class DateCellDataPersistence implements _GridCellDataPersistence<DateCalData> {
|
||||
final GridCell gridCell;
|
||||
DateCellDataPersistence({
|
||||
required this.gridCell,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<Option<FlowyError>> save(DateCellPersistenceData data) {
|
||||
Future<Option<FlowyError>> save(DateCalData data) {
|
||||
var payload = DateChangesetPayload.create()..cellIdentifier = _cellIdentifier(gridCell);
|
||||
|
||||
final date = (data.date.millisecondsSinceEpoch ~/ 1000).toString();
|
||||
payload.date = date;
|
||||
payload.time = data.time ?? "";
|
||||
|
||||
if (data.time != null) {
|
||||
payload.time = data.time!;
|
||||
}
|
||||
|
||||
return GridEventUpdateDateCell(payload).send().then((result) {
|
||||
return result.fold(
|
||||
|
@ -9,7 +9,7 @@ import 'dart:async';
|
||||
import 'cell_service/cell_service.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:protobuf/protobuf.dart';
|
||||
// import 'package:fixnum/fixnum.dart' as $fixnum;
|
||||
import 'package:fixnum/fixnum.dart' as $fixnum;
|
||||
part 'date_cal_bloc.freezed.dart';
|
||||
|
||||
class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
|
||||
@ -34,7 +34,11 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
|
||||
setFocusedDay: (focusedDay) {
|
||||
emit(state.copyWith(focusedDay: focusedDay));
|
||||
},
|
||||
didReceiveCellUpdate: (value) {},
|
||||
didReceiveCellUpdate: (DateCellData cellData) {
|
||||
final dateData = dateDataFromCellData(cellData);
|
||||
final time = dateData.foldRight("", (dateData, previous) => dateData.time);
|
||||
emit(state.copyWith(dateData: dateData, time: time));
|
||||
},
|
||||
setIncludeTime: (includeTime) async {
|
||||
await _updateTypeOption(emit, includeTime: includeTime);
|
||||
},
|
||||
@ -53,11 +57,8 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
|
||||
}
|
||||
|
||||
Future<void> _updateDateData(Emitter<DateCalState> emit, {DateTime? date, String? time}) {
|
||||
final DateCellPersistenceData newDateData = state.dateData.fold(
|
||||
() {
|
||||
var newDateData = DateCellPersistenceData(date: date ?? DateTime.now());
|
||||
return newDateData.copyWith(time: time);
|
||||
},
|
||||
final DateCalData newDateData = state.dateData.fold(
|
||||
() => DateCalData(date: date ?? DateTime.now(), time: time),
|
||||
(dateData) {
|
||||
var newDateData = dateData;
|
||||
if (date != null && !isSameDay(newDateData.date, date)) {
|
||||
@ -74,7 +75,7 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
|
||||
return _saveDateData(emit, newDateData);
|
||||
}
|
||||
|
||||
Future<void> _saveDateData(Emitter<DateCalState> emit, DateCellPersistenceData newDateData) async {
|
||||
Future<void> _saveDateData(Emitter<DateCalState> emit, DateCalData newDateData) async {
|
||||
if (state.dateData == Some(newDateData)) {
|
||||
return;
|
||||
}
|
||||
@ -173,31 +174,48 @@ class DateCalState with _$DateCalState {
|
||||
required DateTypeOption dateTypeOption,
|
||||
required CalendarFormat format,
|
||||
required DateTime focusedDay,
|
||||
required String time,
|
||||
required Option<String> timeFormatError,
|
||||
required Option<DateCellPersistenceData> dateData,
|
||||
required Option<DateCalData> dateData,
|
||||
required String? time,
|
||||
}) = _DateCalState;
|
||||
|
||||
factory DateCalState.initial(
|
||||
DateTypeOption dateTypeOption,
|
||||
DateCellData? cellData,
|
||||
) {
|
||||
Option<DateCellPersistenceData> dateData = none();
|
||||
final time = cellData?.time ?? "";
|
||||
if (cellData != null) {
|
||||
// final timestamp = $fixnum.Int64.parseInt(cellData.timestamp).toInt();
|
||||
final timestamp = cellData.timestamp * 1000;
|
||||
final selectedDay = DateTime.fromMillisecondsSinceEpoch(timestamp.toInt());
|
||||
dateData = Some(DateCellPersistenceData(date: selectedDay, time: time));
|
||||
}
|
||||
|
||||
Option<DateCalData> dateData = dateDataFromCellData(cellData);
|
||||
final time = dateData.foldRight("", (dateData, previous) => dateData.time);
|
||||
return DateCalState(
|
||||
dateTypeOption: dateTypeOption,
|
||||
format: CalendarFormat.month,
|
||||
focusedDay: DateTime.now(),
|
||||
dateData: dateData,
|
||||
time: time,
|
||||
dateData: dateData,
|
||||
timeFormatError: none(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Option<DateCalData> dateDataFromCellData(DateCellData? cellData) {
|
||||
String? time = timeFromCellData(cellData);
|
||||
Option<DateCalData> dateData = none();
|
||||
if (cellData != null) {
|
||||
final timestamp = cellData.timestamp * 1000;
|
||||
final date = DateTime.fromMillisecondsSinceEpoch(timestamp.toInt());
|
||||
dateData = Some(DateCalData(date: date, time: time));
|
||||
}
|
||||
return dateData;
|
||||
}
|
||||
|
||||
$fixnum.Int64 timestampFromDateTime(DateTime dateTime) {
|
||||
final timestamp = (dateTime.millisecondsSinceEpoch ~/ 1000);
|
||||
return $fixnum.Int64(timestamp);
|
||||
}
|
||||
|
||||
String? timeFromCellData(DateCellData? cellData) {
|
||||
String? time;
|
||||
if (cellData?.hasTime() ?? false) {
|
||||
time = cellData?.time;
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
@ -254,7 +254,11 @@ class _TimeTextFieldState extends State<_TimeTextField> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return BlocBuilder<DateCalBloc, DateCalState>(
|
||||
return BlocConsumer<DateCalBloc, DateCalState>(
|
||||
listener: (context, state) {
|
||||
_controller.text = state.time ?? "";
|
||||
},
|
||||
listenWhen: (p, c) => p.time != c.time,
|
||||
builder: (context, state) {
|
||||
if (state.dateTypeOption.includeTime) {
|
||||
return Padding(
|
||||
|
@ -289,7 +289,7 @@ pub(crate) async fn get_date_cell_data_handler(
|
||||
Some(field_meta) => {
|
||||
let cell_meta = editor.get_cell_meta(¶ms.row_id, ¶ms.field_id).await?;
|
||||
let type_option = DateTypeOption::from(&field_meta);
|
||||
let date_cell_data = type_option.date_cell_data(&cell_meta)?;
|
||||
let date_cell_data = type_option.make_date_cell_data(&cell_meta)?;
|
||||
data_result(date_cell_data)
|
||||
}
|
||||
}
|
||||
|
@ -5,14 +5,12 @@ use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellD
|
||||
use bytes::Bytes;
|
||||
use chrono::format::strftime::StrftimeItems;
|
||||
use chrono::NaiveDateTime;
|
||||
use diesel::types::Time;
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
use flowy_error::{internal_error, ErrorCode, FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::entities::{
|
||||
CellChangeset, CellMeta, FieldMeta, FieldType, TypeOptionDataDeserializer, TypeOptionDataEntry,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::Add;
|
||||
use std::str::FromStr;
|
||||
use strum_macros::EnumIter;
|
||||
|
||||
@ -79,7 +77,7 @@ impl DateTypeOption {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn date_cell_data(&self, cell_meta: &Option<CellMeta>) -> FlowyResult<DateCellData> {
|
||||
pub fn make_date_cell_data(&self, cell_meta: &Option<CellMeta>) -> FlowyResult<DateCellData> {
|
||||
if cell_meta.is_none() {
|
||||
return Ok(DateCellData::default());
|
||||
}
|
||||
@ -112,27 +110,28 @@ impl DateTypeOption {
|
||||
utc: &chrono::DateTime<chrono::Utc>,
|
||||
time: &Option<String>,
|
||||
) -> FlowyResult<i64> {
|
||||
let mut date_str = format!(
|
||||
"{}",
|
||||
utc.format_with_items(StrftimeItems::new(self.date_format.format_str()))
|
||||
);
|
||||
|
||||
if let Some(time_str) = time.as_ref() {
|
||||
if !time_str.is_empty() {
|
||||
date_str = date_str.add(&time_str);
|
||||
}
|
||||
}
|
||||
let fmt = self.date_fmt(time);
|
||||
match NaiveDateTime::parse_from_str(&date_str, &fmt) {
|
||||
Ok(native) => {
|
||||
let utc = self.utc_date_time_from_native(native);
|
||||
Ok(utc.timestamp())
|
||||
}
|
||||
Err(_e) => {
|
||||
let msg = format!("Parse {} with format: {} failed", date_str, fmt);
|
||||
Err(FlowyError::new(ErrorCode::InvalidDateTimeFormat, &msg))
|
||||
let date_str = format!(
|
||||
"{}{}",
|
||||
utc.format_with_items(StrftimeItems::new(self.date_format.format_str())),
|
||||
&time_str
|
||||
);
|
||||
|
||||
return match NaiveDateTime::parse_from_str(&date_str, &self.date_fmt(time)) {
|
||||
Ok(native) => {
|
||||
let utc = self.utc_date_time_from_native(native);
|
||||
Ok(utc.timestamp())
|
||||
}
|
||||
Err(_e) => {
|
||||
let msg = format!("Parse {} failed", date_str);
|
||||
Err(FlowyError::new(ErrorCode::InvalidDateTimeFormat, &msg))
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(utc.timestamp());
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,7 +169,7 @@ impl CellDataOperation for DateTypeOption {
|
||||
let timestamp = self.timestamp_from_utc_with_time(&utc, &time)?;
|
||||
DateCellDataSerde::new(timestamp, time, &self.time_format)
|
||||
}
|
||||
_ => DateCellDataSerde::from_timestamp(date_timestamp, &self.time_format),
|
||||
_ => DateCellDataSerde::from_timestamp(date_timestamp, Some(default_time_str(&self.time_format))),
|
||||
},
|
||||
};
|
||||
|
||||
@ -312,11 +311,8 @@ impl DateCellDataSerde {
|
||||
}
|
||||
}
|
||||
|
||||
fn from_timestamp(timestamp: i64, time_format: &TimeFormat) -> Self {
|
||||
Self {
|
||||
timestamp,
|
||||
time: Some(default_time_str(time_format)),
|
||||
}
|
||||
pub(crate) fn from_timestamp(timestamp: i64, time: Option<String>) -> Self {
|
||||
Self { timestamp, time }
|
||||
}
|
||||
|
||||
fn to_string(self) -> String {
|
||||
@ -614,11 +610,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn data(s: i64) -> String {
|
||||
let json = serde_json::to_string(&DateCellDataSerde {
|
||||
timestamp: s,
|
||||
time: None,
|
||||
})
|
||||
.unwrap();
|
||||
let json = serde_json::to_string(&DateCellDataSerde::from_timestamp(s, None)).unwrap();
|
||||
TypeOptionCellData::new(&json, FieldType::DateTime).json()
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,8 @@ mod tests {
|
||||
|
||||
// date
|
||||
let date_time_field_meta = FieldBuilder::from_field_type(&FieldType::DateTime).build();
|
||||
let data = TypeOptionCellData::new("1647251762", FieldType::DateTime).json();
|
||||
let json = serde_json::to_string(&DateCellDataSerde::from_timestamp(1647251762, None)).unwrap();
|
||||
let data = TypeOptionCellData::new(&json, FieldType::DateTime).json();
|
||||
assert_eq!(
|
||||
type_option.decode_cell_data(data, &date_time_field_meta).content,
|
||||
"Mar 14,2022".to_owned()
|
||||
|
@ -2,8 +2,8 @@ use crate::grid::script::EditorScript::*;
|
||||
use crate::grid::script::*;
|
||||
use chrono::NaiveDateTime;
|
||||
use flowy_grid::services::field::{
|
||||
MultiSelectTypeOption, SelectOption, SelectOptionCellContentChangeset, SingleSelectTypeOption,
|
||||
SELECTION_IDS_SEPARATOR,
|
||||
DateCellContentChangeset, MultiSelectTypeOption, SelectOption, SelectOptionCellContentChangeset,
|
||||
SingleSelectTypeOption, SELECTION_IDS_SEPARATOR,
|
||||
};
|
||||
use flowy_grid::services::row::{decode_cell_data, CreateRowMetaBuilder};
|
||||
use flowy_grid_data_model::entities::{
|
||||
@ -240,7 +240,9 @@ async fn grid_row_add_cells_test() {
|
||||
builder.add_cell(&field.id, "18,443".to_owned()).unwrap();
|
||||
}
|
||||
FieldType::DateTime => {
|
||||
builder.add_cell(&field.id, "1647251762".to_owned()).unwrap();
|
||||
builder
|
||||
.add_cell(&field.id, make_date_cell_string("1647251762"))
|
||||
.unwrap();
|
||||
}
|
||||
FieldType::SingleSelect => {
|
||||
let type_option = SingleSelectTypeOption::from(field);
|
||||
@ -278,10 +280,11 @@ async fn grid_row_add_date_cell_test() {
|
||||
date_field = Some(field.clone());
|
||||
NaiveDateTime::from_timestamp(123, 0);
|
||||
// The data should not be empty
|
||||
assert!(builder.add_cell(&field.id, "".to_owned()).is_err());
|
||||
|
||||
assert!(builder.add_cell(&field.id, "123".to_owned()).is_ok());
|
||||
assert!(builder.add_cell(&field.id, format!("{}", timestamp)).is_ok());
|
||||
assert!(builder.add_cell(&field.id, "".to_string()).is_err());
|
||||
assert!(builder.add_cell(&field.id, make_date_cell_string("123")).is_ok());
|
||||
assert!(builder
|
||||
.add_cell(&field.id, make_date_cell_string(×tamp.to_string()))
|
||||
.is_ok());
|
||||
}
|
||||
}
|
||||
let context = builder.build();
|
||||
@ -315,7 +318,7 @@ async fn grid_cell_update() {
|
||||
let data = match field_meta.field_type {
|
||||
FieldType::RichText => "".to_string(),
|
||||
FieldType::Number => "123".to_string(),
|
||||
FieldType::DateTime => "123".to_string(),
|
||||
FieldType::DateTime => make_date_cell_string("123"),
|
||||
FieldType::SingleSelect => {
|
||||
let type_option = SingleSelectTypeOption::from(field_meta);
|
||||
SelectOptionCellContentChangeset::from_insert(&type_option.options.first().unwrap().id).to_str()
|
||||
@ -363,3 +366,11 @@ async fn grid_cell_update() {
|
||||
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
fn make_date_cell_string(s: &str) -> String {
|
||||
serde_json::to_string(&DateCellContentChangeset {
|
||||
date: Some(s.to_string()),
|
||||
time: None,
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user