mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: add sub data type
This commit is contained in:
parent
2b745bc41a
commit
ad3e2f5725
@ -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:dartz/dartz.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-folder/view.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
|
||||
@ -55,15 +56,6 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||
didReceiveGridUpdate: (GridPB 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) {
|
||||
if (!isClosed) {
|
||||
add(BoardEvent.didReceiveRowUpdate(rowInfos, reason));
|
||||
_buildColumnItems(rowInfos);
|
||||
}
|
||||
},
|
||||
onFieldsChanged: (fields) {
|
||||
if (!isClosed) {
|
||||
_buildColumns(fields);
|
||||
add(BoardEvent.didReceiveFieldUpdate(fields));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _buildColumnItems(List<GridRowInfo> rowInfos) {
|
||||
for (final rowInfo in rowInfos) {}
|
||||
}
|
||||
|
||||
void _buildColumns(UnmodifiableListView<GridFieldPB> fields) {
|
||||
for (final field in fields) {
|
||||
if (field.fieldType == FieldType.SingleSelect) {
|
||||
@ -127,7 +122,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||
|
||||
boardDataController.addColumns(columns);
|
||||
},
|
||||
onError: (err) {},
|
||||
onError: (err) => Log.error(err),
|
||||
);
|
||||
}
|
||||
|
||||
@ -148,14 +143,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||
class BoardEvent with _$BoardEvent {
|
||||
const factory BoardEvent.initial() = InitialGrid;
|
||||
const factory BoardEvent.createRow() = _CreateRow;
|
||||
const factory BoardEvent.didReceiveRowUpdate(
|
||||
List<GridRowInfo> rows,
|
||||
GridRowChangeReason listState,
|
||||
) = _DidReceiveRowUpdate;
|
||||
const factory BoardEvent.didReceiveFieldUpdate(
|
||||
UnmodifiableListView<GridFieldPB> fields,
|
||||
) = _DidReceiveFieldUpdate;
|
||||
|
||||
const factory BoardEvent.groupByField(GridFieldPB field) = _GroupByField;
|
||||
const factory BoardEvent.didReceiveGridUpdate(
|
||||
GridPB grid,
|
||||
) = _DidReceiveGridUpdate;
|
||||
@ -166,19 +154,17 @@ class BoardState with _$BoardState {
|
||||
const factory BoardState({
|
||||
required String gridId,
|
||||
required Option<GridPB> grid,
|
||||
required GridFieldEquatable fields,
|
||||
required Option<GridFieldPB> groupField,
|
||||
required List<GridRowInfo> rowInfos,
|
||||
required GridLoadingState loadingState,
|
||||
required GridRowChangeReason reason,
|
||||
}) = _BoardState;
|
||||
|
||||
factory BoardState.initial(String gridId) => BoardState(
|
||||
fields: GridFieldEquatable(UnmodifiableListView([])),
|
||||
rowInfos: [],
|
||||
groupField: none(),
|
||||
grid: none(),
|
||||
gridId: gridId,
|
||||
loadingState: const _Loading(),
|
||||
reason: const InitialListState(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,10 @@ class BoardPluginBuilder implements PluginBuilder {
|
||||
PluginType get pluginType => DefaultPlugin.board.type();
|
||||
|
||||
@override
|
||||
ViewDataType get dataType => ViewDataType.Grid;
|
||||
ViewDataTypePB get dataType => ViewDataTypePB.Database;
|
||||
|
||||
@override
|
||||
SubViewDataTypePB get subDataType => SubViewDataTypePB.Board;
|
||||
}
|
||||
|
||||
class BoardPluginConfig implements PluginConfig {
|
||||
|
@ -1,15 +1,17 @@
|
||||
// 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:flowy_infra_ui/widget/error_page.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../application/board_bloc.dart';
|
||||
import 'card.dart';
|
||||
|
||||
class BoardPage extends StatelessWidget {
|
||||
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
|
||||
Widget build(BuildContext context) {
|
||||
@ -53,12 +55,7 @@ class BoardContent extends StatelessWidget {
|
||||
dataController: context.read<BoardBloc>().boardDataController,
|
||||
headerBuilder: _buildHeader,
|
||||
footBuilder: _buildFooter,
|
||||
cardBuilder: (context, item) {
|
||||
return AppFlowyColumnItemCard(
|
||||
key: ObjectKey(item),
|
||||
child: _buildCard(item),
|
||||
);
|
||||
},
|
||||
cardBuilder: _buildCard,
|
||||
columnConstraints: const BoxConstraints.tightFor(width: 240),
|
||||
config: BoardConfig(
|
||||
columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
||||
@ -90,42 +87,12 @@ class BoardContent extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCard(ColumnItem item) {
|
||||
if (item is TextItem) {
|
||||
return Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Padding(
|
||||
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();
|
||||
Widget _buildCard(BuildContext context, ColumnItem item) {
|
||||
final rowInfo = item as GridRowInfo;
|
||||
return AppFlowyColumnItemCard(
|
||||
key: ObjectKey(item),
|
||||
child: BoardCard(rowInfo: rowInfo),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
13
frontend/app_flowy/lib/plugins/board/presentation/card.dart
Normal file
13
frontend/app_flowy/lib/plugins/board/presentation/card.dart
Normal 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'));
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
library docuemnt_plugin;
|
||||
library document_plugin;
|
||||
|
||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||
import 'package:app_flowy/startup/plugin/plugin.dart';
|
||||
@ -42,10 +42,10 @@ class DocumentPluginBuilder extends PluginBuilder {
|
||||
String get menuName => LocaleKeys.document_menuName.tr();
|
||||
|
||||
@override
|
||||
PluginType get pluginType => DefaultPlugin.quill.type();
|
||||
PluginType get pluginType => DefaultPlugin.editor.type();
|
||||
|
||||
@override
|
||||
ViewDataType get dataType => ViewDataType.TextBlock;
|
||||
ViewDataTypePB get dataType => ViewDataTypePB.TextBlock;
|
||||
}
|
||||
|
||||
class DocumentPlugin implements Plugin {
|
||||
|
@ -25,7 +25,10 @@ class GridPluginBuilder implements PluginBuilder {
|
||||
PluginType get pluginType => DefaultPlugin.grid.type();
|
||||
|
||||
@override
|
||||
ViewDataType get dataType => ViewDataType.Grid;
|
||||
ViewDataTypePB get dataType => ViewDataTypePB.Database;
|
||||
|
||||
@override
|
||||
SubViewDataTypePB? get subDataType => SubViewDataTypePB.Grid;
|
||||
}
|
||||
|
||||
class GridPluginConfig implements PluginConfig {
|
||||
|
@ -10,7 +10,7 @@ import 'package:flutter/widgets.dart';
|
||||
export "./src/sandbox.dart";
|
||||
|
||||
enum DefaultPlugin {
|
||||
quill,
|
||||
editor,
|
||||
blank,
|
||||
trash,
|
||||
grid,
|
||||
@ -20,7 +20,7 @@ enum DefaultPlugin {
|
||||
extension FlowyDefaultPluginExt on DefaultPlugin {
|
||||
int type() {
|
||||
switch (this) {
|
||||
case DefaultPlugin.quill:
|
||||
case DefaultPlugin.editor:
|
||||
return 0;
|
||||
case DefaultPlugin.blank:
|
||||
return 1;
|
||||
@ -35,7 +35,6 @@ extension FlowyDefaultPluginExt on DefaultPlugin {
|
||||
}
|
||||
|
||||
typedef PluginType = int;
|
||||
typedef PluginDataType = ViewDataType;
|
||||
typedef PluginId = String;
|
||||
|
||||
abstract class Plugin {
|
||||
@ -55,7 +54,9 @@ abstract class PluginBuilder {
|
||||
|
||||
PluginType get pluginType;
|
||||
|
||||
ViewDataType get dataType => ViewDataType.TextBlock;
|
||||
ViewDataTypePB get dataType => ViewDataTypePB.TextBlock;
|
||||
|
||||
SubViewDataTypePB? get subDataType => null;
|
||||
}
|
||||
|
||||
abstract class PluginConfig {
|
||||
|
@ -86,6 +86,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
|
||||
desc: value.desc,
|
||||
dataType: value.dataType,
|
||||
pluginType: value.pluginType,
|
||||
subDataType: value.subDataType,
|
||||
);
|
||||
viewOrFailed.fold(
|
||||
(view) => emit(state.copyWith(
|
||||
@ -138,7 +139,8 @@ class AppEvent with _$AppEvent {
|
||||
const factory AppEvent.createView(
|
||||
String name,
|
||||
String desc,
|
||||
PluginDataType dataType,
|
||||
ViewDataTypePB dataType,
|
||||
SubViewDataTypePB? subDataType,
|
||||
PluginType pluginType,
|
||||
) = CreateView;
|
||||
const factory AppEvent.delete() = Delete;
|
||||
|
@ -24,16 +24,21 @@ class AppService {
|
||||
required String appId,
|
||||
required String name,
|
||||
required String desc,
|
||||
required PluginDataType dataType,
|
||||
required ViewDataTypePB dataType,
|
||||
required PluginType pluginType,
|
||||
SubViewDataTypePB? subDataType,
|
||||
}) {
|
||||
final payload = CreateViewPayloadPB.create()
|
||||
var payload = CreateViewPayloadPB.create()
|
||||
..belongToId = appId
|
||||
..name = name
|
||||
..desc = desc
|
||||
..dataType = dataType
|
||||
..pluginType = pluginType;
|
||||
|
||||
if (subDataType != null) {
|
||||
payload.subDataType = subDataType;
|
||||
}
|
||||
|
||||
return FolderEventCreateView(payload).send();
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,9 @@ class MenuAppHeader extends StatelessWidget {
|
||||
height: MenuAppSizes.headerHeight,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
ExpandableController.of(context, rebuildOnChange: false, required: true)?.toggle();
|
||||
ExpandableController.of(context,
|
||||
rebuildOnChange: false, required: true)
|
||||
?.toggle();
|
||||
},
|
||||
child: ExpandableIcon(
|
||||
theme: ExpandableThemeData(
|
||||
@ -68,18 +70,23 @@ class MenuAppHeader extends StatelessWidget {
|
||||
Widget _renderTitle(BuildContext context, AppTheme theme) {
|
||||
return Expanded(
|
||||
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) {
|
||||
final expandableController = ExpandableController.of(context, rebuildOnChange: false, required: true)!;
|
||||
final expandableController = ExpandableController.of(context,
|
||||
rebuildOnChange: false, required: true)!;
|
||||
if (!expandableController.expanded) {
|
||||
expandableController.toggle();
|
||||
}
|
||||
},
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () => ExpandableController.of(context, rebuildOnChange: false, required: true)?.toggle(),
|
||||
onTap: () => ExpandableController.of(context,
|
||||
rebuildOnChange: false, required: true)
|
||||
?.toggle(),
|
||||
onSecondaryTap: () {
|
||||
final actionList = AppDisclosureActionSheet(onSelected: (action) => _handleAction(context, action));
|
||||
final actionList = AppDisclosureActionSheet(
|
||||
onSelected: (action) => _handleAction(context, action));
|
||||
actionList.show(
|
||||
context,
|
||||
anchorDirection: AnchorDirection.bottomWithCenterAligned,
|
||||
@ -107,6 +114,7 @@ class MenuAppHeader extends StatelessWidget {
|
||||
LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||
"",
|
||||
pluginBuilder.dataType,
|
||||
pluginBuilder.subDataType,
|
||||
pluginBuilder.pluginType,
|
||||
));
|
||||
},
|
||||
|
@ -22,7 +22,7 @@ pub struct ViewPB {
|
||||
pub name: String,
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub data_type: ViewDataType,
|
||||
pub data_type: ViewDataTypePB,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub modified_time: i64,
|
||||
@ -49,31 +49,37 @@ impl std::convert::From<ViewRevision> for ViewPB {
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)]
|
||||
pub enum ViewDataType {
|
||||
pub enum ViewDataTypePB {
|
||||
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 {
|
||||
ViewDataTypeRevision::default().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<ViewDataTypeRevision> for ViewDataType {
|
||||
impl std::convert::From<ViewDataTypeRevision> for ViewDataTypePB {
|
||||
fn from(rev: ViewDataTypeRevision) -> Self {
|
||||
match rev {
|
||||
ViewDataTypeRevision::TextBlock => ViewDataType::TextBlock,
|
||||
ViewDataTypeRevision::Grid => ViewDataType::Grid,
|
||||
ViewDataTypeRevision::TextBlock => ViewDataTypePB::TextBlock,
|
||||
ViewDataTypeRevision::Database => ViewDataTypePB::Database,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<ViewDataType> for ViewDataTypeRevision {
|
||||
fn from(ty: ViewDataType) -> Self {
|
||||
impl std::convert::From<ViewDataTypePB> for ViewDataTypeRevision {
|
||||
fn from(ty: ViewDataTypePB) -> Self {
|
||||
match ty {
|
||||
ViewDataType::TextBlock => ViewDataTypeRevision::TextBlock,
|
||||
ViewDataType::Grid => ViewDataTypeRevision::Grid,
|
||||
ViewDataTypePB::TextBlock => ViewDataTypeRevision::TextBlock,
|
||||
ViewDataTypePB::Database => ViewDataTypeRevision::Database,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -113,12 +119,15 @@ pub struct CreateViewPayloadPB {
|
||||
pub thumbnail: Option<String>,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub data_type: ViewDataType,
|
||||
pub data_type: ViewDataTypePB,
|
||||
|
||||
#[pb(index = 6)]
|
||||
pub plugin_type: i32,
|
||||
#[pb(index = 6, one_of)]
|
||||
pub sub_data_type: Option<SubViewDataTypePB>,
|
||||
|
||||
#[pb(index = 7)]
|
||||
pub plugin_type: i32,
|
||||
|
||||
#[pb(index = 8)]
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
@ -128,7 +137,8 @@ pub struct CreateViewParams {
|
||||
pub name: String,
|
||||
pub desc: String,
|
||||
pub thumbnail: String,
|
||||
pub data_type: ViewDataType,
|
||||
pub data_type: ViewDataTypePB,
|
||||
pub sub_data_type: Option<SubViewDataTypePB>,
|
||||
pub view_id: String,
|
||||
pub data: Vec<u8>,
|
||||
pub plugin_type: i32,
|
||||
@ -151,6 +161,7 @@ impl TryInto<CreateViewParams> for CreateViewPayloadPB {
|
||||
name,
|
||||
desc: self.desc,
|
||||
data_type: self.data_type,
|
||||
sub_data_type: self.sub_data_type,
|
||||
thumbnail,
|
||||
view_id,
|
||||
data: self.data,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::entities::{RepeatedViewPB, ViewDataType};
|
||||
use crate::entities::{RepeatedViewPB, ViewDataTypePB};
|
||||
use flowy_derive::ProtoBuf;
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
@ -16,7 +16,7 @@ pub struct ViewInfoPB {
|
||||
pub desc: String,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub data_type: ViewDataType,
|
||||
pub data_type: ViewDataTypePB,
|
||||
|
||||
#[pb(index = 6)]
|
||||
pub belongings: RepeatedViewPB,
|
||||
|
@ -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::{
|
||||
dart_notification::{send_dart_notification, FolderNotification},
|
||||
@ -221,7 +222,7 @@ impl DefaultFolderBuilder {
|
||||
};
|
||||
let _ = view_controller.set_latest_view(&view.id);
|
||||
let _ = view_controller
|
||||
.create_view(&view.id, ViewDataType::TextBlock, Bytes::from(view_data))
|
||||
.create_view(&view.id, ViewDataTypePB::TextBlock, Bytes::from(view_data))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
@ -256,7 +257,12 @@ pub trait ViewDataProcessor {
|
||||
|
||||
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(
|
||||
&self,
|
||||
@ -265,7 +271,7 @@ pub trait ViewDataProcessor {
|
||||
data: Vec<u8>,
|
||||
) -> 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>>>;
|
||||
|
@ -88,7 +88,7 @@ impl ViewTable {
|
||||
pub fn new(view_rev: ViewRevision) -> Self {
|
||||
let data_type = match view_rev.data_type {
|
||||
ViewDataTypeRevision::TextBlock => SqlViewDataType::Block,
|
||||
ViewDataTypeRevision::Grid => SqlViewDataType::Grid,
|
||||
ViewDataTypeRevision::Database => SqlViewDataType::Grid,
|
||||
};
|
||||
|
||||
ViewTable {
|
||||
@ -111,7 +111,7 @@ impl std::convert::From<ViewTable> for ViewRevision {
|
||||
fn from(table: ViewTable) -> Self {
|
||||
let data_type = match table.view_type {
|
||||
SqlViewDataType::Block => ViewDataTypeRevision::TextBlock,
|
||||
SqlViewDataType::Grid => ViewDataTypeRevision::Grid,
|
||||
SqlViewDataType::Grid => ViewDataTypeRevision::Database,
|
||||
};
|
||||
|
||||
ViewRevision {
|
||||
|
@ -1,5 +1,5 @@
|
||||
pub use crate::entities::view::ViewDataType;
|
||||
use crate::entities::ViewInfoPB;
|
||||
pub use crate::entities::view::ViewDataTypePB;
|
||||
use crate::entities::{SubViewDataTypePB, ViewInfoPB};
|
||||
use crate::manager::{ViewDataProcessor, ViewDataProcessorMap};
|
||||
use crate::{
|
||||
dart_notification::{send_dart_notification, FolderNotification},
|
||||
@ -61,7 +61,9 @@ impl ViewController {
|
||||
let processor = self.get_data_processor(params.data_type.clone())?;
|
||||
let user_id = self.user.user_id()?;
|
||||
if params.data.is_empty() {
|
||||
let view_data = processor.create_default_view(&user_id, ¶ms.view_id).await?;
|
||||
let view_data = processor
|
||||
.create_default_view(&user_id, ¶ms.view_id, params.sub_data_type.clone())
|
||||
.await?;
|
||||
params.data = view_data.to_vec();
|
||||
} else {
|
||||
let delta_data = processor
|
||||
@ -81,7 +83,7 @@ impl ViewController {
|
||||
pub(crate) async fn create_view(
|
||||
&self,
|
||||
view_id: &str,
|
||||
data_type: ViewDataType,
|
||||
data_type: ViewDataTypePB,
|
||||
delta_data: Bytes,
|
||||
) -> Result<(), FlowyError> {
|
||||
if delta_data.is_empty() {
|
||||
@ -217,6 +219,7 @@ impl ViewController {
|
||||
desc: view_rev.desc,
|
||||
thumbnail: view_rev.thumbnail,
|
||||
data_type: view_rev.data_type.into(),
|
||||
sub_data_type: None,
|
||||
data: delta_bytes.to_vec(),
|
||||
view_id: gen_view_id(),
|
||||
plugin_type: view_rev.plugin_type,
|
||||
@ -364,7 +367,7 @@ impl ViewController {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_data_processor<T: Into<ViewDataType>>(
|
||||
fn get_data_processor<T: Into<ViewDataTypePB>>(
|
||||
&self,
|
||||
data_type: T,
|
||||
) -> FlowyResult<Arc<dyn ViewDataProcessor + Send + Sync>> {
|
||||
@ -452,7 +455,7 @@ async fn handle_trash_event(
|
||||
|
||||
fn get_data_processor(
|
||||
data_processors: ViewDataProcessorMap,
|
||||
data_type: &ViewDataType,
|
||||
data_type: &ViewDataTypePB,
|
||||
) -> FlowyResult<Arc<dyn ViewDataProcessor + Send + Sync>> {
|
||||
match data_processors.get(data_type) {
|
||||
None => Err(FlowyError::internal().context(format!(
|
||||
|
@ -1,5 +1,5 @@
|
||||
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_revision::disk::RevisionState;
|
||||
@ -134,12 +134,12 @@ async fn app_create_with_view() {
|
||||
CreateView {
|
||||
name: "View A".to_owned(),
|
||||
desc: "View A description".to_owned(),
|
||||
data_type: ViewDataType::TextBlock,
|
||||
data_type: ViewDataTypePB::TextBlock,
|
||||
},
|
||||
CreateView {
|
||||
name: "Grid".to_owned(),
|
||||
desc: "Grid description".to_owned(),
|
||||
data_type: ViewDataType::Grid,
|
||||
data_type: ViewDataTypePB::Database,
|
||||
},
|
||||
ReadApp(app.id),
|
||||
])
|
||||
@ -198,12 +198,12 @@ async fn view_delete_all() {
|
||||
CreateView {
|
||||
name: "View A".to_owned(),
|
||||
desc: "View A description".to_owned(),
|
||||
data_type: ViewDataType::TextBlock,
|
||||
data_type: ViewDataTypePB::TextBlock,
|
||||
},
|
||||
CreateView {
|
||||
name: "Grid".to_owned(),
|
||||
desc: "Grid description".to_owned(),
|
||||
data_type: ViewDataType::Grid,
|
||||
data_type: ViewDataTypePB::Database,
|
||||
},
|
||||
ReadApp(app.id.clone()),
|
||||
])
|
||||
@ -231,7 +231,7 @@ async fn view_delete_all_permanent() {
|
||||
CreateView {
|
||||
name: "View A".to_owned(),
|
||||
desc: "View A description".to_owned(),
|
||||
data_type: ViewDataType::TextBlock,
|
||||
data_type: ViewDataTypePB::TextBlock,
|
||||
},
|
||||
ReadApp(app.id.clone()),
|
||||
])
|
||||
@ -330,7 +330,7 @@ async fn folder_sync_revision_with_new_view() {
|
||||
CreateView {
|
||||
name: view_name.clone(),
|
||||
desc: view_desc.clone(),
|
||||
data_type: ViewDataType::TextBlock,
|
||||
data_type: ViewDataTypePB::TextBlock,
|
||||
},
|
||||
AssertCurrentRevId(3),
|
||||
AssertNextSyncRevId(Some(3)),
|
||||
|
@ -9,7 +9,7 @@ use flowy_folder::entities::{
|
||||
use flowy_folder::entities::{
|
||||
app::{AppPB, RepeatedAppPB},
|
||||
trash::TrashPB,
|
||||
view::{RepeatedViewPB, ViewDataType, ViewPB},
|
||||
view::{RepeatedViewPB, ViewDataTypePB, ViewPB},
|
||||
workspace::WorkspacePB,
|
||||
};
|
||||
use flowy_folder::event_map::FolderEvent::*;
|
||||
@ -51,7 +51,7 @@ pub enum FolderScript {
|
||||
CreateView {
|
||||
name: String,
|
||||
desc: String,
|
||||
data_type: ViewDataType,
|
||||
data_type: ViewDataTypePB,
|
||||
},
|
||||
AssertView(ViewPB),
|
||||
ReadView(String),
|
||||
@ -98,7 +98,7 @@ impl FolderTest {
|
||||
&app.id,
|
||||
"Folder View",
|
||||
"Folder test view",
|
||||
ViewDataType::TextBlock,
|
||||
ViewDataTypePB::TextBlock,
|
||||
)
|
||||
.await;
|
||||
app.belongings = RepeatedViewPB {
|
||||
@ -346,7 +346,13 @@ pub async fn delete_app(sdk: &FlowySDKTest, app_id: &str) {
|
||||
.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 {
|
||||
belong_to_id: app_id.to_string(),
|
||||
name: name.to_string(),
|
||||
|
@ -82,7 +82,7 @@ impl_into_box_type_option_builder!(SingleSelectTypeOptionBuilder);
|
||||
impl_builder_from_json_str_and_from_bytes!(SingleSelectTypeOptionBuilder, SingleSelectTypeOptionPB);
|
||||
|
||||
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
|
||||
}
|
||||
@ -113,9 +113,9 @@ mod tests {
|
||||
let facebook_option = SelectOptionPB::new("Facebook");
|
||||
let twitter_option = SelectOptionPB::new("Twitter");
|
||||
let single_select = SingleSelectTypeOptionBuilder::default()
|
||||
.option(google_option.clone())
|
||||
.option(facebook_option.clone())
|
||||
.option(twitter_option);
|
||||
.add_option(google_option.clone())
|
||||
.add_option(facebook_option.clone())
|
||||
.add_option(twitter_option);
|
||||
|
||||
let field_rev = FieldBuilder::new(single_select)
|
||||
.name("Platform")
|
||||
|
@ -133,7 +133,7 @@ mod tests {
|
||||
// Single select
|
||||
let done_option = SelectOptionPB::new("Done");
|
||||
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();
|
||||
|
||||
assert_eq!(
|
||||
|
@ -272,7 +272,7 @@ impl GridRevisionEditor {
|
||||
let block_id = self.block_id().await?;
|
||||
|
||||
// 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);
|
||||
|
||||
// insert the row
|
||||
|
@ -7,12 +7,13 @@ use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct RowRevisionBuilder<'a> {
|
||||
block_id: String,
|
||||
field_rev_map: HashMap<&'a String, Arc<FieldRevision>>,
|
||||
payload: CreateRowRevisionPayload,
|
||||
}
|
||||
|
||||
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
|
||||
.iter()
|
||||
.map(|field| (&field.id, field.clone()))
|
||||
@ -25,7 +26,13 @@ impl<'a> RowRevisionBuilder<'a> {
|
||||
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<()> {
|
||||
@ -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()) {
|
||||
None => {
|
||||
let msg = format!("Invalid field_id: {}", field_id);
|
||||
Err(FlowyError::internal().context(msg))
|
||||
tracing::warn!("Invalid field_id: {}", field_id);
|
||||
self
|
||||
}
|
||||
Some(field_rev) => {
|
||||
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);
|
||||
self.payload.cell_by_field_id.insert(field_id.to_owned(), cell);
|
||||
Ok(())
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -71,10 +78,10 @@ impl<'a> RowRevisionBuilder<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self, block_id: &str) -> RowRevision {
|
||||
pub fn build(self) -> RowRevision {
|
||||
RowRevision {
|
||||
id: self.payload.row_id,
|
||||
block_id: block_id.to_owned(),
|
||||
block_id: self.block_id,
|
||||
cells: self.payload.cell_by_field_id,
|
||||
height: self.payload.height,
|
||||
visibility: self.payload.visibility,
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::entities::FieldType;
|
||||
use crate::services::field::*;
|
||||
use crate::services::row::RowRevisionBuilder;
|
||||
use flowy_grid_data_model::revision::BuildGridContext;
|
||||
use flowy_sync::client_grid::GridBuilder;
|
||||
|
||||
@ -30,3 +31,47 @@ pub fn make_default_grid() -> BuildGridContext {
|
||||
grid_builder.add_empty_row();
|
||||
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()
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ pub struct GridRowTestBuilder<'a> {
|
||||
impl<'a> GridRowTestBuilder<'a> {
|
||||
pub fn new(block_id: &str, field_revs: &'a [Arc<FieldRevision>]) -> Self {
|
||||
assert_eq!(field_revs.len(), FieldType::COUNT);
|
||||
let inner_builder = RowRevisionBuilder::new(field_revs);
|
||||
let inner_builder = RowRevisionBuilder::new(block_id, field_revs);
|
||||
Self {
|
||||
block_id: block_id.to_owned(),
|
||||
field_revs,
|
||||
@ -77,8 +77,7 @@ impl<'a> GridRowTestBuilder<'a> {
|
||||
let type_option = SingleSelectTypeOptionPB::from(&single_select_field);
|
||||
let option = f(type_option.options);
|
||||
self.inner_builder
|
||||
.insert_select_option_cell(&single_select_field.id, option.id)
|
||||
.unwrap();
|
||||
.insert_select_option_cell(&single_select_field.id, option.id);
|
||||
|
||||
single_select_field.id.clone()
|
||||
}
|
||||
@ -96,8 +95,7 @@ impl<'a> GridRowTestBuilder<'a> {
|
||||
.collect::<Vec<_>>()
|
||||
.join(SELECTION_IDS_SEPARATOR);
|
||||
self.inner_builder
|
||||
.insert_select_option_cell(&multi_select_field.id, ops_ids)
|
||||
.unwrap();
|
||||
.insert_select_option_cell(&multi_select_field.id, ops_ids);
|
||||
|
||||
multi_select_field.id.clone()
|
||||
}
|
||||
@ -115,7 +113,7 @@ impl<'a> GridRowTestBuilder<'a> {
|
||||
}
|
||||
|
||||
pub fn build(self) -> RowRevision {
|
||||
self.inner_builder.build(&self.block_id)
|
||||
self.inner_builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
let single_select = SingleSelectTypeOptionBuilder::default()
|
||||
.option(SelectOptionPB::new("Done"))
|
||||
.option(SelectOptionPB::new("Progress"));
|
||||
.add_option(SelectOptionPB::new("Done"))
|
||||
.add_option(SelectOptionPB::new("Progress"));
|
||||
|
||||
let field_rev = FieldBuilder::new(single_select).name("Name").visibility(true).build();
|
||||
let cloned_field_rev = field_rev.clone();
|
||||
|
@ -138,9 +138,9 @@ fn make_test_grid() -> BuildGridContext {
|
||||
FieldType::SingleSelect => {
|
||||
// Single Select
|
||||
let single_select = SingleSelectTypeOptionBuilder::default()
|
||||
.option(SelectOptionPB::new(COMPLETED))
|
||||
.option(SelectOptionPB::new(PLANNED))
|
||||
.option(SelectOptionPB::new(PAUSED));
|
||||
.add_option(SelectOptionPB::new(COMPLETED))
|
||||
.add_option(SelectOptionPB::new(PLANNED))
|
||||
.add_option(SelectOptionPB::new(PAUSED));
|
||||
let single_select_field = FieldBuilder::new(single_select).name("Status").visibility(true).build();
|
||||
grid_builder.add_field(single_select_field);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use bytes::Bytes;
|
||||
use flowy_database::ConnectionPool;
|
||||
use flowy_folder::entities::ViewDataType;
|
||||
use flowy_folder::entities::{SubViewDataTypePB, ViewDataTypePB};
|
||||
use flowy_folder::manager::{ViewDataProcessor, ViewDataProcessorMap};
|
||||
use flowy_folder::{
|
||||
errors::{internal_error, FlowyError},
|
||||
@ -8,7 +8,7 @@ use flowy_folder::{
|
||||
manager::FolderManager,
|
||||
};
|
||||
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_net::ClientServerConfiguration;
|
||||
use flowy_net::{
|
||||
@ -66,7 +66,7 @@ fn make_view_data_processor(
|
||||
text_block_manager: Arc<TextBlockManager>,
|
||||
grid_manager: Arc<GridManager>,
|
||||
) -> 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);
|
||||
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 view_id = view_id.to_string();
|
||||
let manager = self.0.clone();
|
||||
@ -203,8 +208,8 @@ impl ViewDataProcessor for TextBlockViewDataProcessor {
|
||||
FutureResult::new(async move { Ok(Bytes::from(data)) })
|
||||
}
|
||||
|
||||
fn data_type(&self) -> ViewDataType {
|
||||
ViewDataType::TextBlock
|
||||
fn data_type(&self) -> ViewDataTypePB {
|
||||
ViewDataTypePB::TextBlock
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,8 +257,16 @@ impl ViewDataProcessor for GridViewDataProcessor {
|
||||
})
|
||||
}
|
||||
|
||||
fn create_default_view(&self, user_id: &str, view_id: &str) -> FutureResult<Bytes, FlowyError> {
|
||||
let build_context = make_default_grid();
|
||||
fn create_default_view(
|
||||
&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 view_id = view_id.to_string();
|
||||
let grid_manager = self.0.clone();
|
||||
@ -278,7 +291,7 @@ impl ViewDataProcessor for GridViewDataProcessor {
|
||||
})
|
||||
}
|
||||
|
||||
fn data_type(&self) -> ViewDataType {
|
||||
ViewDataType::Grid
|
||||
fn data_type(&self) -> ViewDataTypePB {
|
||||
ViewDataTypePB::Database
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ pub struct ViewTest {
|
||||
|
||||
impl ViewTest {
|
||||
#[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;
|
||||
open_workspace(sdk, &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 {
|
||||
Self::new(sdk, ViewDataType::Grid, data).await
|
||||
Self::new(sdk, ViewDataTypePB::Database, data).await
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
belong_to_id: app_id.to_string(),
|
||||
name: "View A".to_string(),
|
||||
|
@ -53,7 +53,7 @@ impl std::convert::From<ViewRevision> for TrashRevision {
|
||||
#[repr(u8)]
|
||||
pub enum ViewDataTypeRevision {
|
||||
TextBlock = 0,
|
||||
Grid = 1,
|
||||
Database = 1,
|
||||
}
|
||||
|
||||
impl std::default::Default for ViewDataTypeRevision {
|
||||
|
Loading…
Reference in New Issue
Block a user