chore: add sub data type

This commit is contained in:
appflowy 2022-08-10 17:59:28 +08:00
parent 2b745bc41a
commit ad3e2f5725
29 changed files with 243 additions and 166 deletions

View File

@ -6,6 +6,7 @@ import 'package:app_flowy/plugins/grid/presentation/widgets/header/type_option/b
import 'package:appflowy_board/appflowy_board.dart'; import 'package:appflowy_board/appflowy_board.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
@ -55,15 +56,6 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
didReceiveGridUpdate: (GridPB grid) { didReceiveGridUpdate: (GridPB grid) {
emit(state.copyWith(grid: Some(grid))); emit(state.copyWith(grid: Some(grid)));
}, },
didReceiveFieldUpdate: (UnmodifiableListView<GridFieldPB> fields) {
emit(state.copyWith(fields: GridFieldEquatable(fields)));
},
didReceiveRowUpdate: (
List<GridRowInfo> newRowInfos,
GridRowChangeReason reason,
) {
emit(state.copyWith(rowInfos: newRowInfos, reason: reason));
},
); );
}, },
); );
@ -89,18 +81,21 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
}, },
onRowsChanged: (rowInfos, reason) { onRowsChanged: (rowInfos, reason) {
if (!isClosed) { if (!isClosed) {
add(BoardEvent.didReceiveRowUpdate(rowInfos, reason)); _buildColumnItems(rowInfos);
} }
}, },
onFieldsChanged: (fields) { onFieldsChanged: (fields) {
if (!isClosed) { if (!isClosed) {
_buildColumns(fields); _buildColumns(fields);
add(BoardEvent.didReceiveFieldUpdate(fields));
} }
}, },
); );
} }
void _buildColumnItems(List<GridRowInfo> rowInfos) {
for (final rowInfo in rowInfos) {}
}
void _buildColumns(UnmodifiableListView<GridFieldPB> fields) { void _buildColumns(UnmodifiableListView<GridFieldPB> fields) {
for (final field in fields) { for (final field in fields) {
if (field.fieldType == FieldType.SingleSelect) { if (field.fieldType == FieldType.SingleSelect) {
@ -127,7 +122,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
boardDataController.addColumns(columns); boardDataController.addColumns(columns);
}, },
onError: (err) {}, onError: (err) => Log.error(err),
); );
} }
@ -148,14 +143,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
class BoardEvent with _$BoardEvent { class BoardEvent with _$BoardEvent {
const factory BoardEvent.initial() = InitialGrid; const factory BoardEvent.initial() = InitialGrid;
const factory BoardEvent.createRow() = _CreateRow; const factory BoardEvent.createRow() = _CreateRow;
const factory BoardEvent.didReceiveRowUpdate( const factory BoardEvent.groupByField(GridFieldPB field) = _GroupByField;
List<GridRowInfo> rows,
GridRowChangeReason listState,
) = _DidReceiveRowUpdate;
const factory BoardEvent.didReceiveFieldUpdate(
UnmodifiableListView<GridFieldPB> fields,
) = _DidReceiveFieldUpdate;
const factory BoardEvent.didReceiveGridUpdate( const factory BoardEvent.didReceiveGridUpdate(
GridPB grid, GridPB grid,
) = _DidReceiveGridUpdate; ) = _DidReceiveGridUpdate;
@ -166,19 +154,17 @@ class BoardState with _$BoardState {
const factory BoardState({ const factory BoardState({
required String gridId, required String gridId,
required Option<GridPB> grid, required Option<GridPB> grid,
required GridFieldEquatable fields, required Option<GridFieldPB> groupField,
required List<GridRowInfo> rowInfos, required List<GridRowInfo> rowInfos,
required GridLoadingState loadingState, required GridLoadingState loadingState,
required GridRowChangeReason reason,
}) = _BoardState; }) = _BoardState;
factory BoardState.initial(String gridId) => BoardState( factory BoardState.initial(String gridId) => BoardState(
fields: GridFieldEquatable(UnmodifiableListView([])),
rowInfos: [], rowInfos: [],
groupField: none(),
grid: none(), grid: none(),
gridId: gridId, gridId: gridId,
loadingState: const _Loading(), loadingState: const _Loading(),
reason: const InitialListState(),
); );
} }

View File

@ -23,7 +23,10 @@ class BoardPluginBuilder implements PluginBuilder {
PluginType get pluginType => DefaultPlugin.board.type(); PluginType get pluginType => DefaultPlugin.board.type();
@override @override
ViewDataType get dataType => ViewDataType.Grid; ViewDataTypePB get dataType => ViewDataTypePB.Database;
@override
SubViewDataTypePB get subDataType => SubViewDataTypePB.Board;
} }
class BoardPluginConfig implements PluginConfig { class BoardPluginConfig implements PluginConfig {

View File

@ -1,15 +1,17 @@
// ignore_for_file: unused_field // ignore_for_file: unused_field
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
import 'package:appflowy_board/appflowy_board.dart'; import 'package:appflowy_board/appflowy_board.dart';
import 'package:flowy_infra_ui/widget/error_page.dart'; import 'package:flowy_infra_ui/widget/error_page.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import '../application/board_bloc.dart'; import '../application/board_bloc.dart';
import 'card.dart';
class BoardPage extends StatelessWidget { class BoardPage extends StatelessWidget {
final ViewPB view; final ViewPB view;
const BoardPage({required this.view, Key? key}) : super(key: key); BoardPage({required this.view, Key? key}) : super(key: ValueKey(view.id));
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -53,12 +55,7 @@ class BoardContent extends StatelessWidget {
dataController: context.read<BoardBloc>().boardDataController, dataController: context.read<BoardBloc>().boardDataController,
headerBuilder: _buildHeader, headerBuilder: _buildHeader,
footBuilder: _buildFooter, footBuilder: _buildFooter,
cardBuilder: (context, item) { cardBuilder: _buildCard,
return AppFlowyColumnItemCard(
key: ObjectKey(item),
child: _buildCard(item),
);
},
columnConstraints: const BoxConstraints.tightFor(width: 240), columnConstraints: const BoxConstraints.tightFor(width: 240),
config: BoardConfig( config: BoardConfig(
columnBackgroundColor: HexColor.fromHex('#F7F8FC'), columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
@ -90,43 +87,13 @@ class BoardContent extends StatelessWidget {
); );
} }
Widget _buildCard(ColumnItem item) { Widget _buildCard(BuildContext context, ColumnItem item) {
if (item is TextItem) { final rowInfo = item as GridRowInfo;
return Align( return AppFlowyColumnItemCard(
alignment: Alignment.centerLeft, key: ObjectKey(item),
child: Padding( child: BoardCard(rowInfo: rowInfo),
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Text(item.s),
),
); );
} }
if (item is RichTextItem) {
return Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
item.title,
style: const TextStyle(fontSize: 14),
textAlign: TextAlign.left,
),
const SizedBox(height: 10),
Text(
item.subtitle,
style: const TextStyle(fontSize: 12, color: Colors.grey),
)
],
),
),
);
}
throw UnimplementedError();
}
} }
extension HexColor on Color { extension HexColor on Color {

View File

@ -0,0 +1,13 @@
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
import 'package:flutter/material.dart';
class BoardCard extends StatelessWidget {
final GridRowInfo rowInfo;
const BoardCard({required this.rowInfo, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(child: Text('1234'));
}
}

View File

@ -1,4 +1,4 @@
library docuemnt_plugin; library document_plugin;
import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:app_flowy/startup/plugin/plugin.dart'; import 'package:app_flowy/startup/plugin/plugin.dart';
@ -42,10 +42,10 @@ class DocumentPluginBuilder extends PluginBuilder {
String get menuName => LocaleKeys.document_menuName.tr(); String get menuName => LocaleKeys.document_menuName.tr();
@override @override
PluginType get pluginType => DefaultPlugin.quill.type(); PluginType get pluginType => DefaultPlugin.editor.type();
@override @override
ViewDataType get dataType => ViewDataType.TextBlock; ViewDataTypePB get dataType => ViewDataTypePB.TextBlock;
} }
class DocumentPlugin implements Plugin { class DocumentPlugin implements Plugin {

View File

@ -25,7 +25,10 @@ class GridPluginBuilder implements PluginBuilder {
PluginType get pluginType => DefaultPlugin.grid.type(); PluginType get pluginType => DefaultPlugin.grid.type();
@override @override
ViewDataType get dataType => ViewDataType.Grid; ViewDataTypePB get dataType => ViewDataTypePB.Database;
@override
SubViewDataTypePB? get subDataType => SubViewDataTypePB.Grid;
} }
class GridPluginConfig implements PluginConfig { class GridPluginConfig implements PluginConfig {

View File

@ -10,7 +10,7 @@ import 'package:flutter/widgets.dart';
export "./src/sandbox.dart"; export "./src/sandbox.dart";
enum DefaultPlugin { enum DefaultPlugin {
quill, editor,
blank, blank,
trash, trash,
grid, grid,
@ -20,7 +20,7 @@ enum DefaultPlugin {
extension FlowyDefaultPluginExt on DefaultPlugin { extension FlowyDefaultPluginExt on DefaultPlugin {
int type() { int type() {
switch (this) { switch (this) {
case DefaultPlugin.quill: case DefaultPlugin.editor:
return 0; return 0;
case DefaultPlugin.blank: case DefaultPlugin.blank:
return 1; return 1;
@ -35,7 +35,6 @@ extension FlowyDefaultPluginExt on DefaultPlugin {
} }
typedef PluginType = int; typedef PluginType = int;
typedef PluginDataType = ViewDataType;
typedef PluginId = String; typedef PluginId = String;
abstract class Plugin { abstract class Plugin {
@ -55,7 +54,9 @@ abstract class PluginBuilder {
PluginType get pluginType; PluginType get pluginType;
ViewDataType get dataType => ViewDataType.TextBlock; ViewDataTypePB get dataType => ViewDataTypePB.TextBlock;
SubViewDataTypePB? get subDataType => null;
} }
abstract class PluginConfig { abstract class PluginConfig {

View File

@ -86,6 +86,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
desc: value.desc, desc: value.desc,
dataType: value.dataType, dataType: value.dataType,
pluginType: value.pluginType, pluginType: value.pluginType,
subDataType: value.subDataType,
); );
viewOrFailed.fold( viewOrFailed.fold(
(view) => emit(state.copyWith( (view) => emit(state.copyWith(
@ -138,7 +139,8 @@ class AppEvent with _$AppEvent {
const factory AppEvent.createView( const factory AppEvent.createView(
String name, String name,
String desc, String desc,
PluginDataType dataType, ViewDataTypePB dataType,
SubViewDataTypePB? subDataType,
PluginType pluginType, PluginType pluginType,
) = CreateView; ) = CreateView;
const factory AppEvent.delete() = Delete; const factory AppEvent.delete() = Delete;

View File

@ -24,16 +24,21 @@ class AppService {
required String appId, required String appId,
required String name, required String name,
required String desc, required String desc,
required PluginDataType dataType, required ViewDataTypePB dataType,
required PluginType pluginType, required PluginType pluginType,
SubViewDataTypePB? subDataType,
}) { }) {
final payload = CreateViewPayloadPB.create() var payload = CreateViewPayloadPB.create()
..belongToId = appId ..belongToId = appId
..name = name ..name = name
..desc = desc ..desc = desc
..dataType = dataType ..dataType = dataType
..pluginType = pluginType; ..pluginType = pluginType;
if (subDataType != null) {
payload.subDataType = subDataType;
}
return FolderEventCreateView(payload).send(); return FolderEventCreateView(payload).send();
} }

View File

@ -49,7 +49,9 @@ class MenuAppHeader extends StatelessWidget {
height: MenuAppSizes.headerHeight, height: MenuAppSizes.headerHeight,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
ExpandableController.of(context, rebuildOnChange: false, required: true)?.toggle(); ExpandableController.of(context,
rebuildOnChange: false, required: true)
?.toggle();
}, },
child: ExpandableIcon( child: ExpandableIcon(
theme: ExpandableThemeData( theme: ExpandableThemeData(
@ -68,18 +70,23 @@ class MenuAppHeader extends StatelessWidget {
Widget _renderTitle(BuildContext context, AppTheme theme) { Widget _renderTitle(BuildContext context, AppTheme theme) {
return Expanded( return Expanded(
child: BlocListener<AppBloc, AppState>( child: BlocListener<AppBloc, AppState>(
listenWhen: (p, c) => (p.latestCreatedView == null && c.latestCreatedView != null), listenWhen: (p, c) =>
(p.latestCreatedView == null && c.latestCreatedView != null),
listener: (context, state) { listener: (context, state) {
final expandableController = ExpandableController.of(context, rebuildOnChange: false, required: true)!; final expandableController = ExpandableController.of(context,
rebuildOnChange: false, required: true)!;
if (!expandableController.expanded) { if (!expandableController.expanded) {
expandableController.toggle(); expandableController.toggle();
} }
}, },
child: GestureDetector( child: GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () => ExpandableController.of(context, rebuildOnChange: false, required: true)?.toggle(), onTap: () => ExpandableController.of(context,
rebuildOnChange: false, required: true)
?.toggle(),
onSecondaryTap: () { onSecondaryTap: () {
final actionList = AppDisclosureActionSheet(onSelected: (action) => _handleAction(context, action)); final actionList = AppDisclosureActionSheet(
onSelected: (action) => _handleAction(context, action));
actionList.show( actionList.show(
context, context,
anchorDirection: AnchorDirection.bottomWithCenterAligned, anchorDirection: AnchorDirection.bottomWithCenterAligned,
@ -107,6 +114,7 @@ class MenuAppHeader extends StatelessWidget {
LocaleKeys.menuAppHeader_defaultNewPageName.tr(), LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
"", "",
pluginBuilder.dataType, pluginBuilder.dataType,
pluginBuilder.subDataType,
pluginBuilder.pluginType, pluginBuilder.pluginType,
)); ));
}, },

View File

@ -22,7 +22,7 @@ pub struct ViewPB {
pub name: String, pub name: String,
#[pb(index = 4)] #[pb(index = 4)]
pub data_type: ViewDataType, pub data_type: ViewDataTypePB,
#[pb(index = 5)] #[pb(index = 5)]
pub modified_time: i64, pub modified_time: i64,
@ -49,31 +49,37 @@ impl std::convert::From<ViewRevision> for ViewPB {
} }
#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)] #[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)]
pub enum ViewDataType { pub enum ViewDataTypePB {
TextBlock = 0, TextBlock = 0,
Grid = 1, Database = 1,
} }
impl std::default::Default for ViewDataType { #[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)]
pub enum SubViewDataTypePB {
Grid = 0,
Board = 1,
}
impl std::default::Default for ViewDataTypePB {
fn default() -> Self { fn default() -> Self {
ViewDataTypeRevision::default().into() ViewDataTypeRevision::default().into()
} }
} }
impl std::convert::From<ViewDataTypeRevision> for ViewDataType { impl std::convert::From<ViewDataTypeRevision> for ViewDataTypePB {
fn from(rev: ViewDataTypeRevision) -> Self { fn from(rev: ViewDataTypeRevision) -> Self {
match rev { match rev {
ViewDataTypeRevision::TextBlock => ViewDataType::TextBlock, ViewDataTypeRevision::TextBlock => ViewDataTypePB::TextBlock,
ViewDataTypeRevision::Grid => ViewDataType::Grid, ViewDataTypeRevision::Database => ViewDataTypePB::Database,
} }
} }
} }
impl std::convert::From<ViewDataType> for ViewDataTypeRevision { impl std::convert::From<ViewDataTypePB> for ViewDataTypeRevision {
fn from(ty: ViewDataType) -> Self { fn from(ty: ViewDataTypePB) -> Self {
match ty { match ty {
ViewDataType::TextBlock => ViewDataTypeRevision::TextBlock, ViewDataTypePB::TextBlock => ViewDataTypeRevision::TextBlock,
ViewDataType::Grid => ViewDataTypeRevision::Grid, ViewDataTypePB::Database => ViewDataTypeRevision::Database,
} }
} }
} }
@ -113,12 +119,15 @@ pub struct CreateViewPayloadPB {
pub thumbnail: Option<String>, pub thumbnail: Option<String>,
#[pb(index = 5)] #[pb(index = 5)]
pub data_type: ViewDataType, pub data_type: ViewDataTypePB,
#[pb(index = 6)] #[pb(index = 6, one_of)]
pub plugin_type: i32, pub sub_data_type: Option<SubViewDataTypePB>,
#[pb(index = 7)] #[pb(index = 7)]
pub plugin_type: i32,
#[pb(index = 8)]
pub data: Vec<u8>, pub data: Vec<u8>,
} }
@ -128,7 +137,8 @@ pub struct CreateViewParams {
pub name: String, pub name: String,
pub desc: String, pub desc: String,
pub thumbnail: String, pub thumbnail: String,
pub data_type: ViewDataType, pub data_type: ViewDataTypePB,
pub sub_data_type: Option<SubViewDataTypePB>,
pub view_id: String, pub view_id: String,
pub data: Vec<u8>, pub data: Vec<u8>,
pub plugin_type: i32, pub plugin_type: i32,
@ -151,6 +161,7 @@ impl TryInto<CreateViewParams> for CreateViewPayloadPB {
name, name,
desc: self.desc, desc: self.desc,
data_type: self.data_type, data_type: self.data_type,
sub_data_type: self.sub_data_type,
thumbnail, thumbnail,
view_id, view_id,
data: self.data, data: self.data,

View File

@ -1,4 +1,4 @@
use crate::entities::{RepeatedViewPB, ViewDataType}; use crate::entities::{RepeatedViewPB, ViewDataTypePB};
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
@ -16,7 +16,7 @@ pub struct ViewInfoPB {
pub desc: String, pub desc: String,
#[pb(index = 5)] #[pb(index = 5)]
pub data_type: ViewDataType, pub data_type: ViewDataTypePB,
#[pb(index = 6)] #[pb(index = 6)]
pub belongings: RepeatedViewPB, pub belongings: RepeatedViewPB,

View File

@ -1,4 +1,5 @@
use crate::entities::view::ViewDataType; use crate::entities::view::ViewDataTypePB;
use crate::entities::SubViewDataTypePB;
use crate::services::folder_editor::FolderRevisionCompactor; use crate::services::folder_editor::FolderRevisionCompactor;
use crate::{ use crate::{
dart_notification::{send_dart_notification, FolderNotification}, dart_notification::{send_dart_notification, FolderNotification},
@ -221,7 +222,7 @@ impl DefaultFolderBuilder {
}; };
let _ = view_controller.set_latest_view(&view.id); let _ = view_controller.set_latest_view(&view.id);
let _ = view_controller let _ = view_controller
.create_view(&view.id, ViewDataType::TextBlock, Bytes::from(view_data)) .create_view(&view.id, ViewDataTypePB::TextBlock, Bytes::from(view_data))
.await?; .await?;
} }
} }
@ -256,7 +257,12 @@ pub trait ViewDataProcessor {
fn get_delta_data(&self, view_id: &str) -> FutureResult<Bytes, FlowyError>; fn get_delta_data(&self, view_id: &str) -> FutureResult<Bytes, FlowyError>;
fn create_default_view(&self, user_id: &str, view_id: &str) -> FutureResult<Bytes, FlowyError>; fn create_default_view(
&self,
user_id: &str,
view_id: &str,
sub_data_type: Option<SubViewDataTypePB>,
) -> FutureResult<Bytes, FlowyError>;
fn create_view_from_delta_data( fn create_view_from_delta_data(
&self, &self,
@ -265,7 +271,7 @@ pub trait ViewDataProcessor {
data: Vec<u8>, data: Vec<u8>,
) -> FutureResult<Bytes, FlowyError>; ) -> FutureResult<Bytes, FlowyError>;
fn data_type(&self) -> ViewDataType; fn data_type(&self) -> ViewDataTypePB;
} }
pub type ViewDataProcessorMap = Arc<HashMap<ViewDataType, Arc<dyn ViewDataProcessor + Send + Sync>>>; pub type ViewDataProcessorMap = Arc<HashMap<ViewDataTypePB, Arc<dyn ViewDataProcessor + Send + Sync>>>;

View File

@ -88,7 +88,7 @@ impl ViewTable {
pub fn new(view_rev: ViewRevision) -> Self { pub fn new(view_rev: ViewRevision) -> Self {
let data_type = match view_rev.data_type { let data_type = match view_rev.data_type {
ViewDataTypeRevision::TextBlock => SqlViewDataType::Block, ViewDataTypeRevision::TextBlock => SqlViewDataType::Block,
ViewDataTypeRevision::Grid => SqlViewDataType::Grid, ViewDataTypeRevision::Database => SqlViewDataType::Grid,
}; };
ViewTable { ViewTable {
@ -111,7 +111,7 @@ impl std::convert::From<ViewTable> for ViewRevision {
fn from(table: ViewTable) -> Self { fn from(table: ViewTable) -> Self {
let data_type = match table.view_type { let data_type = match table.view_type {
SqlViewDataType::Block => ViewDataTypeRevision::TextBlock, SqlViewDataType::Block => ViewDataTypeRevision::TextBlock,
SqlViewDataType::Grid => ViewDataTypeRevision::Grid, SqlViewDataType::Grid => ViewDataTypeRevision::Database,
}; };
ViewRevision { ViewRevision {

View File

@ -1,5 +1,5 @@
pub use crate::entities::view::ViewDataType; pub use crate::entities::view::ViewDataTypePB;
use crate::entities::ViewInfoPB; use crate::entities::{SubViewDataTypePB, ViewInfoPB};
use crate::manager::{ViewDataProcessor, ViewDataProcessorMap}; use crate::manager::{ViewDataProcessor, ViewDataProcessorMap};
use crate::{ use crate::{
dart_notification::{send_dart_notification, FolderNotification}, dart_notification::{send_dart_notification, FolderNotification},
@ -61,7 +61,9 @@ impl ViewController {
let processor = self.get_data_processor(params.data_type.clone())?; let processor = self.get_data_processor(params.data_type.clone())?;
let user_id = self.user.user_id()?; let user_id = self.user.user_id()?;
if params.data.is_empty() { if params.data.is_empty() {
let view_data = processor.create_default_view(&user_id, &params.view_id).await?; let view_data = processor
.create_default_view(&user_id, &params.view_id, params.sub_data_type.clone())
.await?;
params.data = view_data.to_vec(); params.data = view_data.to_vec();
} else { } else {
let delta_data = processor let delta_data = processor
@ -81,7 +83,7 @@ impl ViewController {
pub(crate) async fn create_view( pub(crate) async fn create_view(
&self, &self,
view_id: &str, view_id: &str,
data_type: ViewDataType, data_type: ViewDataTypePB,
delta_data: Bytes, delta_data: Bytes,
) -> Result<(), FlowyError> { ) -> Result<(), FlowyError> {
if delta_data.is_empty() { if delta_data.is_empty() {
@ -217,6 +219,7 @@ impl ViewController {
desc: view_rev.desc, desc: view_rev.desc,
thumbnail: view_rev.thumbnail, thumbnail: view_rev.thumbnail,
data_type: view_rev.data_type.into(), data_type: view_rev.data_type.into(),
sub_data_type: None,
data: delta_bytes.to_vec(), data: delta_bytes.to_vec(),
view_id: gen_view_id(), view_id: gen_view_id(),
plugin_type: view_rev.plugin_type, plugin_type: view_rev.plugin_type,
@ -364,7 +367,7 @@ impl ViewController {
} }
#[inline] #[inline]
fn get_data_processor<T: Into<ViewDataType>>( fn get_data_processor<T: Into<ViewDataTypePB>>(
&self, &self,
data_type: T, data_type: T,
) -> FlowyResult<Arc<dyn ViewDataProcessor + Send + Sync>> { ) -> FlowyResult<Arc<dyn ViewDataProcessor + Send + Sync>> {
@ -452,7 +455,7 @@ async fn handle_trash_event(
fn get_data_processor( fn get_data_processor(
data_processors: ViewDataProcessorMap, data_processors: ViewDataProcessorMap,
data_type: &ViewDataType, data_type: &ViewDataTypePB,
) -> FlowyResult<Arc<dyn ViewDataProcessor + Send + Sync>> { ) -> FlowyResult<Arc<dyn ViewDataProcessor + Send + Sync>> {
match data_processors.get(data_type) { match data_processors.get(data_type) {
None => Err(FlowyError::internal().context(format!( None => Err(FlowyError::internal().context(format!(

View File

@ -1,5 +1,5 @@
use crate::script::{invalid_workspace_name_test_case, FolderScript::*, FolderTest}; use crate::script::{invalid_workspace_name_test_case, FolderScript::*, FolderTest};
use flowy_folder::entities::view::ViewDataType; use flowy_folder::entities::view::ViewDataTypePB;
use flowy_folder::entities::workspace::CreateWorkspacePayloadPB; use flowy_folder::entities::workspace::CreateWorkspacePayloadPB;
use flowy_revision::disk::RevisionState; use flowy_revision::disk::RevisionState;
@ -134,12 +134,12 @@ async fn app_create_with_view() {
CreateView { CreateView {
name: "View A".to_owned(), name: "View A".to_owned(),
desc: "View A description".to_owned(), desc: "View A description".to_owned(),
data_type: ViewDataType::TextBlock, data_type: ViewDataTypePB::TextBlock,
}, },
CreateView { CreateView {
name: "Grid".to_owned(), name: "Grid".to_owned(),
desc: "Grid description".to_owned(), desc: "Grid description".to_owned(),
data_type: ViewDataType::Grid, data_type: ViewDataTypePB::Database,
}, },
ReadApp(app.id), ReadApp(app.id),
]) ])
@ -198,12 +198,12 @@ async fn view_delete_all() {
CreateView { CreateView {
name: "View A".to_owned(), name: "View A".to_owned(),
desc: "View A description".to_owned(), desc: "View A description".to_owned(),
data_type: ViewDataType::TextBlock, data_type: ViewDataTypePB::TextBlock,
}, },
CreateView { CreateView {
name: "Grid".to_owned(), name: "Grid".to_owned(),
desc: "Grid description".to_owned(), desc: "Grid description".to_owned(),
data_type: ViewDataType::Grid, data_type: ViewDataTypePB::Database,
}, },
ReadApp(app.id.clone()), ReadApp(app.id.clone()),
]) ])
@ -231,7 +231,7 @@ async fn view_delete_all_permanent() {
CreateView { CreateView {
name: "View A".to_owned(), name: "View A".to_owned(),
desc: "View A description".to_owned(), desc: "View A description".to_owned(),
data_type: ViewDataType::TextBlock, data_type: ViewDataTypePB::TextBlock,
}, },
ReadApp(app.id.clone()), ReadApp(app.id.clone()),
]) ])
@ -330,7 +330,7 @@ async fn folder_sync_revision_with_new_view() {
CreateView { CreateView {
name: view_name.clone(), name: view_name.clone(),
desc: view_desc.clone(), desc: view_desc.clone(),
data_type: ViewDataType::TextBlock, data_type: ViewDataTypePB::TextBlock,
}, },
AssertCurrentRevId(3), AssertCurrentRevId(3),
AssertNextSyncRevId(Some(3)), AssertNextSyncRevId(Some(3)),

View File

@ -9,7 +9,7 @@ use flowy_folder::entities::{
use flowy_folder::entities::{ use flowy_folder::entities::{
app::{AppPB, RepeatedAppPB}, app::{AppPB, RepeatedAppPB},
trash::TrashPB, trash::TrashPB,
view::{RepeatedViewPB, ViewDataType, ViewPB}, view::{RepeatedViewPB, ViewDataTypePB, ViewPB},
workspace::WorkspacePB, workspace::WorkspacePB,
}; };
use flowy_folder::event_map::FolderEvent::*; use flowy_folder::event_map::FolderEvent::*;
@ -51,7 +51,7 @@ pub enum FolderScript {
CreateView { CreateView {
name: String, name: String,
desc: String, desc: String,
data_type: ViewDataType, data_type: ViewDataTypePB,
}, },
AssertView(ViewPB), AssertView(ViewPB),
ReadView(String), ReadView(String),
@ -98,7 +98,7 @@ impl FolderTest {
&app.id, &app.id,
"Folder View", "Folder View",
"Folder test view", "Folder test view",
ViewDataType::TextBlock, ViewDataTypePB::TextBlock,
) )
.await; .await;
app.belongings = RepeatedViewPB { app.belongings = RepeatedViewPB {
@ -346,7 +346,13 @@ pub async fn delete_app(sdk: &FlowySDKTest, app_id: &str) {
.await; .await;
} }
pub async fn create_view(sdk: &FlowySDKTest, app_id: &str, name: &str, desc: &str, data_type: ViewDataType) -> ViewPB { pub async fn create_view(
sdk: &FlowySDKTest,
app_id: &str,
name: &str,
desc: &str,
data_type: ViewDataTypePB,
) -> ViewPB {
let request = CreateViewPayloadPB { let request = CreateViewPayloadPB {
belong_to_id: app_id.to_string(), belong_to_id: app_id.to_string(),
name: name.to_string(), name: name.to_string(),

View File

@ -82,7 +82,7 @@ impl_into_box_type_option_builder!(SingleSelectTypeOptionBuilder);
impl_builder_from_json_str_and_from_bytes!(SingleSelectTypeOptionBuilder, SingleSelectTypeOptionPB); impl_builder_from_json_str_and_from_bytes!(SingleSelectTypeOptionBuilder, SingleSelectTypeOptionPB);
impl SingleSelectTypeOptionBuilder { impl SingleSelectTypeOptionBuilder {
pub fn option(mut self, opt: SelectOptionPB) -> Self { pub fn add_option(mut self, opt: SelectOptionPB) -> Self {
self.0.options.push(opt); self.0.options.push(opt);
self self
} }
@ -113,9 +113,9 @@ mod tests {
let facebook_option = SelectOptionPB::new("Facebook"); let facebook_option = SelectOptionPB::new("Facebook");
let twitter_option = SelectOptionPB::new("Twitter"); let twitter_option = SelectOptionPB::new("Twitter");
let single_select = SingleSelectTypeOptionBuilder::default() let single_select = SingleSelectTypeOptionBuilder::default()
.option(google_option.clone()) .add_option(google_option.clone())
.option(facebook_option.clone()) .add_option(facebook_option.clone())
.option(twitter_option); .add_option(twitter_option);
let field_rev = FieldBuilder::new(single_select) let field_rev = FieldBuilder::new(single_select)
.name("Platform") .name("Platform")

View File

@ -133,7 +133,7 @@ mod tests {
// Single select // Single select
let done_option = SelectOptionPB::new("Done"); let done_option = SelectOptionPB::new("Done");
let done_option_id = done_option.id.clone(); let done_option_id = done_option.id.clone();
let single_select = SingleSelectTypeOptionBuilder::default().option(done_option.clone()); let single_select = SingleSelectTypeOptionBuilder::default().add_option(done_option.clone());
let single_select_field_rev = FieldBuilder::new(single_select).build(); let single_select_field_rev = FieldBuilder::new(single_select).build();
assert_eq!( assert_eq!(

View File

@ -272,7 +272,7 @@ impl GridRevisionEditor {
let block_id = self.block_id().await?; let block_id = self.block_id().await?;
// insert empty row below the row whose id is upper_row_id // insert empty row below the row whose id is upper_row_id
let row_rev = RowRevisionBuilder::new(&field_revs).build(&block_id); let row_rev = RowRevisionBuilder::new(&block_id, &field_revs).build();
let row_order = GridRowPB::from(&row_rev); let row_order = GridRowPB::from(&row_rev);
// insert the row // insert the row

View File

@ -7,12 +7,13 @@ use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
pub struct RowRevisionBuilder<'a> { pub struct RowRevisionBuilder<'a> {
block_id: String,
field_rev_map: HashMap<&'a String, Arc<FieldRevision>>, field_rev_map: HashMap<&'a String, Arc<FieldRevision>>,
payload: CreateRowRevisionPayload, payload: CreateRowRevisionPayload,
} }
impl<'a> RowRevisionBuilder<'a> { impl<'a> RowRevisionBuilder<'a> {
pub fn new(fields: &'a [Arc<FieldRevision>]) -> Self { pub fn new(block_id: &str, fields: &'a [Arc<FieldRevision>]) -> Self {
let field_rev_map = fields let field_rev_map = fields
.iter() .iter()
.map(|field| (&field.id, field.clone())) .map(|field| (&field.id, field.clone()))
@ -25,7 +26,13 @@ impl<'a> RowRevisionBuilder<'a> {
visibility: true, visibility: true,
}; };
Self { field_rev_map, payload } let block_id = block_id.to_string();
Self {
block_id,
field_rev_map,
payload,
}
} }
pub fn insert_cell(&mut self, field_id: &str, data: String) -> FlowyResult<()> { pub fn insert_cell(&mut self, field_id: &str, data: String) -> FlowyResult<()> {
@ -43,18 +50,18 @@ impl<'a> RowRevisionBuilder<'a> {
} }
} }
pub fn insert_select_option_cell(&mut self, field_id: &str, data: String) -> FlowyResult<()> { pub fn insert_select_option_cell(mut self, field_id: &str, data: String) -> Self {
match self.field_rev_map.get(&field_id.to_owned()) { match self.field_rev_map.get(&field_id.to_owned()) {
None => { None => {
let msg = format!("Invalid field_id: {}", field_id); tracing::warn!("Invalid field_id: {}", field_id);
Err(FlowyError::internal().context(msg)) self
} }
Some(field_rev) => { Some(field_rev) => {
let cell_data = SelectOptionCellChangeset::from_insert(&data).to_str(); let cell_data = SelectOptionCellChangeset::from_insert(&data).to_str();
let data = apply_cell_data_changeset(cell_data, None, field_rev)?; let data = apply_cell_data_changeset(cell_data, None, field_rev).unwrap();
let cell = CellRevision::new(data); let cell = CellRevision::new(data);
self.payload.cell_by_field_id.insert(field_id.to_owned(), cell); self.payload.cell_by_field_id.insert(field_id.to_owned(), cell);
Ok(()) self
} }
} }
} }
@ -71,10 +78,10 @@ impl<'a> RowRevisionBuilder<'a> {
self self
} }
pub fn build(self, block_id: &str) -> RowRevision { pub fn build(self) -> RowRevision {
RowRevision { RowRevision {
id: self.payload.row_id, id: self.payload.row_id,
block_id: block_id.to_owned(), block_id: self.block_id,
cells: self.payload.cell_by_field_id, cells: self.payload.cell_by_field_id,
height: self.payload.height, height: self.payload.height,
visibility: self.payload.visibility, visibility: self.payload.visibility,

View File

@ -1,5 +1,6 @@
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::services::field::*; use crate::services::field::*;
use crate::services::row::RowRevisionBuilder;
use flowy_grid_data_model::revision::BuildGridContext; use flowy_grid_data_model::revision::BuildGridContext;
use flowy_sync::client_grid::GridBuilder; use flowy_sync::client_grid::GridBuilder;
@ -30,3 +31,47 @@ pub fn make_default_grid() -> BuildGridContext {
grid_builder.add_empty_row(); grid_builder.add_empty_row();
grid_builder.build() grid_builder.build()
} }
pub fn make_default_board() -> BuildGridContext {
let mut grid_builder = GridBuilder::new();
// text
let text_field = FieldBuilder::new(RichTextTypeOptionBuilder::default())
.name("Name")
.visibility(true)
.primary(true)
.build();
grid_builder.add_field(text_field);
// single select
let in_progress_option = SelectOptionPB::new("In progress");
let not_started_option = SelectOptionPB::new("Not started");
let done_option = SelectOptionPB::new("Done");
let single_select = SingleSelectTypeOptionBuilder::default()
.add_option(not_started_option.clone())
.add_option(in_progress_option.clone())
.add_option(done_option.clone());
let single_select_field = FieldBuilder::new(single_select).name("Status").visibility(true).build();
let single_select_field_id = single_select_field.id.clone();
grid_builder.add_field(single_select_field);
let field_revs = grid_builder.field_revs();
let block_id = grid_builder.block_id();
// rows
let row_1 = RowRevisionBuilder::new(block_id, field_revs)
.insert_select_option_cell(&single_select_field_id, not_started_option.id.clone())
.build();
grid_builder.add_row(row_1);
let row_2 = RowRevisionBuilder::new(block_id, field_revs)
.insert_select_option_cell(&single_select_field_id, not_started_option.id.clone())
.build();
grid_builder.add_row(row_2);
let row_3 = RowRevisionBuilder::new(block_id, field_revs)
.insert_select_option_cell(&single_select_field_id, not_started_option.id.clone())
.build();
grid_builder.add_row(row_3);
grid_builder.build()
}

View File

@ -18,7 +18,7 @@ pub struct GridRowTestBuilder<'a> {
impl<'a> GridRowTestBuilder<'a> { impl<'a> GridRowTestBuilder<'a> {
pub fn new(block_id: &str, field_revs: &'a [Arc<FieldRevision>]) -> Self { pub fn new(block_id: &str, field_revs: &'a [Arc<FieldRevision>]) -> Self {
assert_eq!(field_revs.len(), FieldType::COUNT); assert_eq!(field_revs.len(), FieldType::COUNT);
let inner_builder = RowRevisionBuilder::new(field_revs); let inner_builder = RowRevisionBuilder::new(block_id, field_revs);
Self { Self {
block_id: block_id.to_owned(), block_id: block_id.to_owned(),
field_revs, field_revs,
@ -77,8 +77,7 @@ impl<'a> GridRowTestBuilder<'a> {
let type_option = SingleSelectTypeOptionPB::from(&single_select_field); let type_option = SingleSelectTypeOptionPB::from(&single_select_field);
let option = f(type_option.options); let option = f(type_option.options);
self.inner_builder self.inner_builder
.insert_select_option_cell(&single_select_field.id, option.id) .insert_select_option_cell(&single_select_field.id, option.id);
.unwrap();
single_select_field.id.clone() single_select_field.id.clone()
} }
@ -96,8 +95,7 @@ impl<'a> GridRowTestBuilder<'a> {
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(SELECTION_IDS_SEPARATOR); .join(SELECTION_IDS_SEPARATOR);
self.inner_builder self.inner_builder
.insert_select_option_cell(&multi_select_field.id, ops_ids) .insert_select_option_cell(&multi_select_field.id, ops_ids);
.unwrap();
multi_select_field.id.clone() multi_select_field.id.clone()
} }
@ -115,7 +113,7 @@ impl<'a> GridRowTestBuilder<'a> {
} }
pub fn build(self) -> RowRevision { pub fn build(self) -> RowRevision {
self.inner_builder.build(&self.block_id) self.inner_builder.build()
} }
} }

View File

@ -39,8 +39,8 @@ pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) {
pub fn create_single_select_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) { pub fn create_single_select_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) {
let single_select = SingleSelectTypeOptionBuilder::default() let single_select = SingleSelectTypeOptionBuilder::default()
.option(SelectOptionPB::new("Done")) .add_option(SelectOptionPB::new("Done"))
.option(SelectOptionPB::new("Progress")); .add_option(SelectOptionPB::new("Progress"));
let field_rev = FieldBuilder::new(single_select).name("Name").visibility(true).build(); let field_rev = FieldBuilder::new(single_select).name("Name").visibility(true).build();
let cloned_field_rev = field_rev.clone(); let cloned_field_rev = field_rev.clone();

View File

@ -138,9 +138,9 @@ fn make_test_grid() -> BuildGridContext {
FieldType::SingleSelect => { FieldType::SingleSelect => {
// Single Select // Single Select
let single_select = SingleSelectTypeOptionBuilder::default() let single_select = SingleSelectTypeOptionBuilder::default()
.option(SelectOptionPB::new(COMPLETED)) .add_option(SelectOptionPB::new(COMPLETED))
.option(SelectOptionPB::new(PLANNED)) .add_option(SelectOptionPB::new(PLANNED))
.option(SelectOptionPB::new(PAUSED)); .add_option(SelectOptionPB::new(PAUSED));
let single_select_field = FieldBuilder::new(single_select).name("Status").visibility(true).build(); let single_select_field = FieldBuilder::new(single_select).name("Status").visibility(true).build();
grid_builder.add_field(single_select_field); grid_builder.add_field(single_select_field);
} }

View File

@ -1,6 +1,6 @@
use bytes::Bytes; use bytes::Bytes;
use flowy_database::ConnectionPool; use flowy_database::ConnectionPool;
use flowy_folder::entities::ViewDataType; use flowy_folder::entities::{SubViewDataTypePB, ViewDataTypePB};
use flowy_folder::manager::{ViewDataProcessor, ViewDataProcessorMap}; use flowy_folder::manager::{ViewDataProcessor, ViewDataProcessorMap};
use flowy_folder::{ use flowy_folder::{
errors::{internal_error, FlowyError}, errors::{internal_error, FlowyError},
@ -8,7 +8,7 @@ use flowy_folder::{
manager::FolderManager, manager::FolderManager,
}; };
use flowy_grid::manager::{make_grid_view_data, GridManager}; use flowy_grid::manager::{make_grid_view_data, GridManager};
use flowy_grid::util::make_default_grid; use flowy_grid::util::{make_default_board, make_default_grid};
use flowy_grid_data_model::revision::BuildGridContext; use flowy_grid_data_model::revision::BuildGridContext;
use flowy_net::ClientServerConfiguration; use flowy_net::ClientServerConfiguration;
use flowy_net::{ use flowy_net::{
@ -66,7 +66,7 @@ fn make_view_data_processor(
text_block_manager: Arc<TextBlockManager>, text_block_manager: Arc<TextBlockManager>,
grid_manager: Arc<GridManager>, grid_manager: Arc<GridManager>,
) -> ViewDataProcessorMap { ) -> ViewDataProcessorMap {
let mut map: HashMap<ViewDataType, Arc<dyn ViewDataProcessor + Send + Sync>> = HashMap::new(); let mut map: HashMap<ViewDataTypePB, Arc<dyn ViewDataProcessor + Send + Sync>> = HashMap::new();
let block_data_impl = TextBlockViewDataProcessor(text_block_manager); let block_data_impl = TextBlockViewDataProcessor(text_block_manager);
map.insert(block_data_impl.data_type(), Arc::new(block_data_impl)); map.insert(block_data_impl.data_type(), Arc::new(block_data_impl));
@ -180,7 +180,12 @@ impl ViewDataProcessor for TextBlockViewDataProcessor {
}) })
} }
fn create_default_view(&self, user_id: &str, view_id: &str) -> FutureResult<Bytes, FlowyError> { fn create_default_view(
&self,
user_id: &str,
view_id: &str,
_sub_data_type: Option<SubViewDataTypePB>,
) -> FutureResult<Bytes, FlowyError> {
let user_id = user_id.to_string(); let user_id = user_id.to_string();
let view_id = view_id.to_string(); let view_id = view_id.to_string();
let manager = self.0.clone(); let manager = self.0.clone();
@ -203,8 +208,8 @@ impl ViewDataProcessor for TextBlockViewDataProcessor {
FutureResult::new(async move { Ok(Bytes::from(data)) }) FutureResult::new(async move { Ok(Bytes::from(data)) })
} }
fn data_type(&self) -> ViewDataType { fn data_type(&self) -> ViewDataTypePB {
ViewDataType::TextBlock ViewDataTypePB::TextBlock
} }
} }
@ -252,8 +257,16 @@ impl ViewDataProcessor for GridViewDataProcessor {
}) })
} }
fn create_default_view(&self, user_id: &str, view_id: &str) -> FutureResult<Bytes, FlowyError> { fn create_default_view(
let build_context = make_default_grid(); &self,
user_id: &str,
view_id: &str,
sub_data_type: Option<SubViewDataTypePB>,
) -> FutureResult<Bytes, FlowyError> {
let build_context = match sub_data_type.unwrap() {
SubViewDataTypePB::Grid => make_default_grid(),
SubViewDataTypePB::Board => make_default_board(),
};
let user_id = user_id.to_string(); let user_id = user_id.to_string();
let view_id = view_id.to_string(); let view_id = view_id.to_string();
let grid_manager = self.0.clone(); let grid_manager = self.0.clone();
@ -278,7 +291,7 @@ impl ViewDataProcessor for GridViewDataProcessor {
}) })
} }
fn data_type(&self) -> ViewDataType { fn data_type(&self) -> ViewDataTypePB {
ViewDataType::Grid ViewDataTypePB::Database
} }
} }

View File

@ -25,7 +25,7 @@ pub struct ViewTest {
impl ViewTest { impl ViewTest {
#[allow(dead_code)] #[allow(dead_code)]
pub async fn new(sdk: &FlowySDKTest, data_type: ViewDataType, data: Vec<u8>) -> Self { pub async fn new(sdk: &FlowySDKTest, data_type: ViewDataTypePB, data: Vec<u8>) -> Self {
let workspace = create_workspace(sdk, "Workspace", "").await; let workspace = create_workspace(sdk, "Workspace", "").await;
open_workspace(sdk, &workspace.id).await; open_workspace(sdk, &workspace.id).await;
let app = create_app(sdk, "App", "AppFlowy GitHub Project", &workspace.id).await; let app = create_app(sdk, "App", "AppFlowy GitHub Project", &workspace.id).await;
@ -39,11 +39,11 @@ impl ViewTest {
} }
pub async fn new_grid_view(sdk: &FlowySDKTest, data: Vec<u8>) -> Self { pub async fn new_grid_view(sdk: &FlowySDKTest, data: Vec<u8>) -> Self {
Self::new(sdk, ViewDataType::Grid, data).await Self::new(sdk, ViewDataTypePB::Database, data).await
} }
pub async fn new_text_block_view(sdk: &FlowySDKTest) -> Self { pub async fn new_text_block_view(sdk: &FlowySDKTest) -> Self {
Self::new(sdk, ViewDataType::TextBlock, vec![]).await Self::new(sdk, ViewDataTypePB::TextBlock, vec![]).await
} }
} }
@ -90,7 +90,7 @@ async fn create_app(sdk: &FlowySDKTest, name: &str, desc: &str, workspace_id: &s
app app
} }
async fn create_view(sdk: &FlowySDKTest, app_id: &str, data_type: ViewDataType, data: Vec<u8>) -> ViewPB { async fn create_view(sdk: &FlowySDKTest, app_id: &str, data_type: ViewDataTypePB, data: Vec<u8>) -> ViewPB {
let request = CreateViewPayloadPB { let request = CreateViewPayloadPB {
belong_to_id: app_id.to_string(), belong_to_id: app_id.to_string(),
name: "View A".to_string(), name: "View A".to_string(),

View File

@ -53,7 +53,7 @@ impl std::convert::From<ViewRevision> for TrashRevision {
#[repr(u8)] #[repr(u8)]
pub enum ViewDataTypeRevision { pub enum ViewDataTypeRevision {
TextBlock = 0, TextBlock = 0,
Grid = 1, Database = 1,
} }
impl std::default::Default for ViewDataTypeRevision { impl std::default::Default for ViewDataTypeRevision {