Merge branch 'release/0.0.5' into merge/release_005

This commit is contained in:
appflowy 2022-09-07 14:22:23 +08:00
commit 4f97133183
20 changed files with 292 additions and 237 deletions

View File

@ -99,7 +99,6 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
));
},
endEditRow: (rowId) {
assert(state.editingRow.isSome());
state.editingRow.fold(() => null, (editingRow) {
assert(editingRow.row.id == rowId);
emit(state.copyWith(editingRow: none()));

View File

@ -7,20 +7,20 @@ import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
import 'card_data_controller.dart';
part 'card_bloc.freezed.dart';
class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
final String fieldId;
final String groupFieldId;
final RowFFIService _rowService;
final CardDataController _dataController;
BoardCardBloc({
required this.fieldId,
required this.groupFieldId,
required String gridId,
required CardDataController dataController,
required bool isEditing,
}) : _rowService = RowFFIService(
gridId: gridId,
blockId: dataController.rowPB.blockId,
@ -29,7 +29,8 @@ class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
super(
BoardCardState.initial(
dataController.rowPB,
_makeCells(fieldId, dataController.loadData()),
_makeCells(groupFieldId, dataController.loadData()),
isEditing,
),
) {
on<BoardCardEvent>(
@ -44,6 +45,9 @@ class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
changeReason: reason,
));
},
setIsEditing: (bool isEditing) {
emit(state.copyWith(isEditing: isEditing));
},
);
},
);
@ -69,7 +73,7 @@ class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
_dataController.addListener(
onRowChanged: (cellMap, reason) {
if (!isClosed) {
final cells = _makeCells(fieldId, cellMap);
final cells = _makeCells(groupFieldId, cellMap);
add(BoardCardEvent.didReceiveCells(cells, reason));
}
},
@ -77,22 +81,24 @@ class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
}
}
UnmodifiableListView<BoardCellEquatable> _makeCells(
String fieldId, GridCellMap originalCellMap) {
List<BoardCellEquatable> _makeCells(
String groupFieldId, GridCellMap originalCellMap) {
List<BoardCellEquatable> cells = [];
for (final entry in originalCellMap.entries) {
if (entry.value.fieldId != fieldId) {
// Filter out the cell if it's fieldId equal to the groupFieldId
if (entry.value.fieldId != groupFieldId) {
cells.add(BoardCellEquatable(entry.value));
}
}
return UnmodifiableListView(cells);
return cells;
}
@freezed
class BoardCardEvent with _$BoardCardEvent {
const factory BoardCardEvent.initial() = _InitialRow;
const factory BoardCardEvent.setIsEditing(bool isEditing) = _IsEditing;
const factory BoardCardEvent.didReceiveCells(
UnmodifiableListView<BoardCellEquatable> cells,
List<BoardCellEquatable> cells,
RowsChangedReason reason,
) = _DidReceiveCells;
}
@ -101,15 +107,20 @@ class BoardCardEvent with _$BoardCardEvent {
class BoardCardState with _$BoardCardState {
const factory BoardCardState({
required RowPB rowPB,
required UnmodifiableListView<BoardCellEquatable> cells,
required List<BoardCellEquatable> cells,
required bool isEditing,
RowsChangedReason? changeReason,
}) = _BoardCardState;
factory BoardCardState.initial(
RowPB rowPB, UnmodifiableListView<BoardCellEquatable> cells) =>
RowPB rowPB,
List<BoardCellEquatable> cells,
bool isEditing,
) =>
BoardCardState(
rowPB: rowPB,
cells: cells,
isEditing: isEditing,
);
}
@ -119,10 +130,12 @@ class BoardCellEquatable extends Equatable {
const BoardCellEquatable(this.identifier);
@override
List<Object?> get props => [
identifier.fieldContext.id,
identifier.fieldContext.fieldType,
identifier.fieldContext.visibility,
identifier.fieldContext.width,
];
List<Object?> get props {
return [
identifier.fieldContext.id,
identifier.fieldContext.fieldType,
identifier.fieldContext.visibility,
identifier.fieldContext.width,
];
}
}

View File

@ -64,6 +64,7 @@ class BoardContent extends StatefulWidget {
class _BoardContentState extends State<BoardContent> {
late AppFlowyBoardScrollController scrollManager;
final Map<String, ValueKey> cardKeysCache = {};
final config = AppFlowyBoardConfig(
groupBackgroundColor: HexColor.fromHex('#F7F8FC'),
@ -83,6 +84,7 @@ class _BoardContentState extends State<BoardContent> {
buildWhen: (previous, current) => previous.groupIds != current.groupIds,
builder: (context, state) {
final column = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [const _ToolbarBlocAdaptor(), _buildBoard(context)],
);
@ -240,8 +242,15 @@ class _BoardContentState extends State<BoardContent> {
},
);
ValueKey? key = cardKeysCache[columnItem.id];
if (key == null) {
final newKey = ValueKey(columnItem.id);
cardKeysCache[columnItem.id] = newKey;
key = newKey;
}
return AppFlowyGroupCard(
key: ValueKey(columnItem.id),
key: key,
margin: config.cardPadding,
decoration: _makeBoxDecoration(context),
child: BoardCard(

View File

@ -1,47 +1,74 @@
import 'package:app_flowy/plugins/grid/application/prelude.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:flutter/material.dart';
abstract class FocusableBoardCell {
set becomeFocus(bool isFocus);
}
class EditableCellNotifier {
final Notifier becomeFirstResponder = Notifier();
final ValueNotifier<bool> isCellEditing;
final Notifier resignFirstResponder = Notifier();
EditableCellNotifier({bool isEditing = false})
: isCellEditing = ValueNotifier(isEditing);
EditableCellNotifier();
void dispose() {
isCellEditing.dispose();
}
}
class EditableRowNotifier {
final Map<EditableCellId, EditableCellNotifier> _cells = {};
final ValueNotifier<bool> isEditing;
EditableRowNotifier({required bool isEditing})
: isEditing = ValueNotifier(isEditing);
void insertCell(
GridCellIdentifier cellIdentifier,
EditableCellNotifier notifier,
) {
assert(
_cells.values.isEmpty,
'Only one cell can receive the notification',
);
final id = EditableCellId.from(cellIdentifier);
_cells[id]?.dispose();
notifier.isCellEditing.addListener(() {
isEditing.value = notifier.isCellEditing.value;
});
_cells[EditableCellId.from(cellIdentifier)] = notifier;
}
void becomeFirstResponder() {
for (final notifier in _cells.values) {
notifier.becomeFirstResponder.notify();
}
if (_cells.values.isEmpty) return;
assert(
_cells.values.length == 1,
'Only one cell can receive the notification',
);
_cells.values.first.isCellEditing.value = true;
}
void resignFirstResponder() {
for (final notifier in _cells.values) {
notifier.resignFirstResponder.notify();
}
if (_cells.values.isEmpty) return;
assert(
_cells.values.length == 1,
'Only one cell can receive the notification',
);
_cells.values.first.isCellEditing.value = false;
}
void clear() {
for (final notifier in _cells.values) {
notifier.dispose();
}
_cells.clear();
}
void dispose() {
for (final notifier in _cells.values) {
notifier.resignFirstResponder.notify();
notifier.dispose();
}
_cells.clear();

View File

@ -5,6 +5,8 @@ import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'define.dart';
class BoardDateCell extends StatefulWidget {
final String groupId;
final GridCellControllerBuilder cellControllerBuilder;
@ -44,10 +46,15 @@ class _BoardDateCellState extends State<BoardDateCell> {
} else {
return Align(
alignment: Alignment.centerLeft,
child: FlowyText.regular(
state.dateStr,
fontSize: 13,
color: context.read<AppTheme>().shader3,
child: Padding(
padding: EdgeInsets.symmetric(
vertical: BoardSizes.cardCellVPadding,
),
child: FlowyText.regular(
state.dateStr,
fontSize: 13,
color: context.read<AppTheme>().shader3,
),
),
);
}

View File

@ -4,6 +4,8 @@ import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'define.dart';
class BoardNumberCell extends StatefulWidget {
final String groupId;
final GridCellControllerBuilder cellControllerBuilder;
@ -43,9 +45,14 @@ class _BoardNumberCellState extends State<BoardNumberCell> {
} else {
return Align(
alignment: Alignment.centerLeft,
child: FlowyText.medium(
state.content,
fontSize: 14,
child: Padding(
padding: EdgeInsets.symmetric(
vertical: BoardSizes.cardCellVPadding,
),
child: FlowyText.medium(
state.content,
fontSize: 14,
),
),
);
}

View File

@ -56,23 +56,23 @@ class _BoardSelectOptionCellState extends State<BoardSelectOptionCell> {
(option) => SelectOptionTag.fromOption(
context: context,
option: option,
onSelected: () {
SelectOptionCellEditor.show(
context: context,
cellController: widget.cellControllerBuilder.build()
as GridSelectOptionCellController,
);
},
),
)
.toList();
return IntrinsicHeight(
child: Stack(
alignment: AlignmentDirectional.center,
fit: StackFit.expand,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 6),
child: Wrap(spacing: 4, runSpacing: 2, children: children),
),
_SelectOptionDialog(
controller: widget.cellControllerBuilder.build(),
),
],
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 6),
child: SizedBox.expand(
child: Wrap(spacing: 4, runSpacing: 2, children: children),
),
),
);
}
@ -98,12 +98,13 @@ class _SelectOptionDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
return InkWell(onTap: () {
SelectOptionCellEditor.show(
context,
_controller,
() {},
);
});
return SizedBox(
child: InkWell(onTap: () {
SelectOptionCellEditor.show(
context: context,
cellController: _controller,
);
}),
);
}
}

View File

@ -9,7 +9,6 @@ import 'define.dart';
class BoardTextCell extends StatefulWidget with EditableCell {
final String groupId;
final bool isFocus;
@override
final EditableCellNotifier? editableNotifier;
final GridCellControllerBuilder cellControllerBuilder;
@ -18,7 +17,6 @@ class BoardTextCell extends StatefulWidget with EditableCell {
required this.groupId,
required this.cellControllerBuilder,
this.editableNotifier,
this.isFocus = false,
Key? key,
}) : super(key: key);
@ -39,40 +37,42 @@ class _BoardTextCellState extends State<BoardTextCell> {
_cellBloc = BoardTextCellBloc(cellController: cellController)
..add(const BoardTextCellEvent.initial());
_controller = TextEditingController(text: _cellBloc.state.content);
focusWhenInit = widget.isFocus;
if (widget.isFocus) {
focusWhenInit = widget.editableNotifier?.isCellEditing.value ?? false;
if (focusWhenInit) {
focusNode.requestFocus();
}
focusNode.addListener(() {
if (!focusNode.hasFocus) {
focusWhenInit = false;
widget.editableNotifier?.isCellEditing.value = false;
_cellBloc.add(const BoardTextCellEvent.enableEdit(false));
if (focusWhenInit) {
setState(() {
focusWhenInit = false;
});
}
}
});
widget.editableNotifier?.becomeFirstResponder.addListener(() {
if (!mounted) return;
WidgetsBinding.instance.addPostFrameCallback((_) {
focusNode.requestFocus();
});
_cellBloc.add(const BoardTextCellEvent.enableEdit(true));
});
widget.editableNotifier?.resignFirstResponder.addListener(() {
if (!mounted) return;
_cellBloc.add(const BoardTextCellEvent.enableEdit(false));
});
_bindEditableNotifier();
super.initState();
}
void _bindEditableNotifier() {
widget.editableNotifier?.isCellEditing.addListener(() {
if (!mounted) return;
final isEditing = widget.editableNotifier?.isCellEditing.value ?? false;
if (isEditing) {
WidgetsBinding.instance.addPostFrameCallback((_) {
focusNode.requestFocus();
});
}
_cellBloc.add(BoardTextCellEvent.enableEdit(isEditing));
});
}
@override
void didUpdateWidget(covariant BoardTextCell oldWidget) {
_bindEditableNotifier();
super.didUpdateWidget(oldWidget);
}
@override
Widget build(BuildContext context) {
return BlocProvider.value(
@ -84,6 +84,15 @@ class _BoardTextCellState extends State<BoardTextCell> {
}
},
child: BlocBuilder<BoardTextCellBloc, BoardTextCellState>(
buildWhen: (previous, current) {
if (previous.content != current.content &&
_controller.text == current.content &&
current.enableEdit) {
return false;
}
return previous != current;
},
builder: (context, state) {
if (state.content.isEmpty &&
state.enableEdit == false &&
@ -127,24 +136,26 @@ class _BoardTextCellState extends State<BoardTextCell> {
}
Widget _buildTextField() {
return TextField(
controller: _controller,
focusNode: focusNode,
onChanged: (value) => focusChanged(),
onEditingComplete: () => focusNode.unfocus(),
maxLines: 1,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
fontFamily: 'Mulish',
),
decoration: InputDecoration(
// Magic number 4 makes the textField take up the same space as FlowyText
contentPadding: EdgeInsets.symmetric(
vertical: BoardSizes.cardCellVPadding + 4,
return IntrinsicHeight(
child: TextField(
controller: _controller,
focusNode: focusNode,
onChanged: (value) => focusChanged(),
onEditingComplete: () => focusNode.unfocus(),
maxLines: null,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
fontFamily: 'Mulish',
),
decoration: InputDecoration(
// Magic number 4 makes the textField take up the same space as FlowyText
contentPadding: EdgeInsets.symmetric(
vertical: BoardSizes.cardCellVPadding + 4,
),
border: InputBorder.none,
isDense: true,
),
border: InputBorder.none,
isDense: true,
),
);
}

View File

@ -4,6 +4,8 @@ import 'package:flowy_infra/theme.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'define.dart';
class BoardUrlCell extends StatefulWidget {
final String groupId;
final GridCellControllerBuilder cellControllerBuilder;
@ -43,14 +45,19 @@ class _BoardUrlCellState extends State<BoardUrlCell> {
} else {
return Align(
alignment: Alignment.centerLeft,
child: RichText(
textAlign: TextAlign.left,
text: TextSpan(
text: state.content,
style: TextStyle(
color: theme.main2,
fontSize: 14,
decoration: TextDecoration.underline,
child: Padding(
padding: EdgeInsets.symmetric(
vertical: BoardSizes.cardCellVPadding,
),
child: RichText(
textAlign: TextAlign.left,
text: TextSpan(
text: state.content,
style: TextStyle(
color: theme.main2,
fontSize: 14,
decoration: TextDecoration.underline,
),
),
),
),

View File

@ -5,6 +5,7 @@ import 'package:app_flowy/plugins/grid/presentation/widgets/row/row_action_sheet
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/flowy_infra_ui_web.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'board_cell.dart';
@ -41,12 +42,19 @@ class _BoardCardState extends State<BoardCard> {
@override
void initState() {
rowNotifier = EditableRowNotifier();
rowNotifier = EditableRowNotifier(isEditing: widget.isEditing);
_cardBloc = BoardCardBloc(
gridId: widget.gridId,
fieldId: widget.fieldId,
groupFieldId: widget.fieldId,
dataController: widget.dataController,
isEditing: widget.isEditing,
)..add(const BoardCardEvent.initial());
rowNotifier.isEditing.addListener(() {
if (!mounted) return;
_cardBloc.add(BoardCardEvent.setIsEditing(rowNotifier.isEditing.value));
});
super.initState();
}
@ -56,10 +64,15 @@ class _BoardCardState extends State<BoardCard> {
value: _cardBloc,
child: BlocBuilder<BoardCardBloc, BoardCardState>(
buildWhen: (previous, current) {
return previous.cells.length != current.cells.length;
if (previous.cells.length != current.cells.length ||
previous.isEditing != current.isEditing) {
return true;
}
return !listEquals(previous.cells, current.cells);
},
builder: (context, state) {
return BoardCardContainer(
buildAccessoryWhen: () => state.isEditing == false,
accessoryBuilder: (context) {
return [
_CardEditOption(
@ -92,17 +105,24 @@ class _BoardCardState extends State<BoardCard> {
rowNotifier.clear();
cells.asMap().forEach(
(int index, GridCellIdentifier cellId) {
final cellNotifier = EditableCellNotifier();
EditableCellNotifier cellNotifier;
if (index == 0) {
// Only use the first cell to receive user's input when click the edit
// button
cellNotifier = EditableCellNotifier(
isEditing: rowNotifier.isEditing.value,
);
rowNotifier.insertCell(cellId, cellNotifier);
} else {
cellNotifier = EditableCellNotifier();
}
Widget child = widget.cellBuilder.buildCell(
widget.groupId,
cellId,
index == 0 ? widget.isEditing : false,
cellNotifier,
);
if (index == 0) {
rowNotifier.insertCell(cellId, cellNotifier);
}
child = Padding(
key: cellId.key(),
padding: const EdgeInsets.only(left: 4, right: 4),

View File

@ -23,7 +23,6 @@ class BoardCellBuilder {
Widget buildCell(
String groupId,
GridCellIdentifier cellId,
bool isEditing,
EditableCellNotifier cellNotifier,
) {
final cellControllerBuilder = GridCellControllerBuilder(
@ -69,7 +68,6 @@ class BoardCellBuilder {
return BoardTextCell(
groupId: groupId,
cellControllerBuilder: cellControllerBuilder,
isFocus: isEditing,
editableNotifier: cellNotifier,
key: key,
);

View File

@ -7,11 +7,13 @@ import 'package:styled_widget/styled_widget.dart';
class BoardCardContainer extends StatelessWidget {
final Widget child;
final CardAccessoryBuilder? accessoryBuilder;
final bool Function()? buildAccessoryWhen;
final void Function(BuildContext) onTap;
const BoardCardContainer({
required this.child,
required this.onTap,
this.accessoryBuilder,
this.buildAccessoryWhen,
Key? key,
}) : super(key: key);
@ -22,7 +24,12 @@ class BoardCardContainer extends StatelessWidget {
child: Consumer<_CardContainerNotifier>(
builder: (context, notifier, _) {
Widget container = Center(child: child);
if (accessoryBuilder != null) {
bool shouldBuildAccessory = true;
if (buildAccessoryWhen != null) {
shouldBuildAccessory = buildAccessoryWhen!.call();
}
if (accessoryBuilder != null && shouldBuildAccessory) {
final accessories = accessoryBuilder!(context);
if (accessories.isNotEmpty) {
container = _CardEnterRegion(

View File

@ -46,7 +46,8 @@ class _DateCellState extends GridCellState<GridDateCell> {
@override
void initState() {
_popover = PopoverController();
final cellController = widget.cellControllerBuilder.build();
final cellController =
widget.cellControllerBuilder.build() as GridDateCellController;
_cellBloc = getIt<DateCellBloc>(param1: cellController)
..add(const DateCellEvent.initial());
super.initState();

View File

@ -27,13 +27,13 @@ const double _editorPannelWidth = 300;
class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
final GridSelectOptionCellController cellController;
final VoidCallback onDismissed;
final VoidCallback? onDismissed;
static double editorPanelWidth = 300;
const SelectOptionCellEditor({
required this.cellController,
required this.onDismissed,
this.onDismissed,
Key? key,
}) : super(key: key);
@ -61,14 +61,14 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
);
}
static void show(
BuildContext context,
GridSelectOptionCellController cellContext,
VoidCallback onDismissed,
) {
static void show({
required BuildContext context,
required GridSelectOptionCellController cellController,
VoidCallback? onDismissed,
}) {
SelectOptionCellEditor.remove(context);
final editor = SelectOptionCellEditor(
cellController: cellContext,
cellController: cellController,
onDismissed: onDismissed,
);
@ -97,7 +97,7 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
bool asBarrier() => true;
@override
void didRemove() => onDismissed();
void didRemove() => onDismissed?.call();
}
class _OptionList extends StatelessWidget {

View File

@ -25,7 +25,7 @@ class AppFlowyGroupFooter extends StatefulWidget {
class _AppFlowyGroupFooterState extends State<AppFlowyGroupFooter> {
@override
Widget build(BuildContext context) {
return GestureDetector(
return InkWell(
onTap: widget.onAddButtonClick,
child: SizedBox(
height: widget.height,

View File

@ -8,7 +8,9 @@ pub trait GroupAction: Send + Sync {
fn default_cell_rev(&self) -> Option<CellRevision> {
None
}
fn use_default_group(&self) -> bool {
true
}
fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool;
fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB>;
fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB>;

View File

@ -97,11 +97,8 @@ where
self.groups_map.values().collect()
}
/// Returns the all the groups that contain the default group.
pub(crate) fn clone_groups(&self) -> Vec<Group> {
let mut groups: Vec<Group> = self.groups_map.values().cloned().collect();
groups.push(self.default_group.clone());
groups
pub(crate) fn default_group(&self) -> &Group {
&self.default_group
}
/// Iterate mut the groups. The default group will be the last one that get mutated.

View File

@ -182,7 +182,13 @@ where
}
fn groups(&self) -> Vec<Group> {
self.group_ctx.clone_groups()
if self.use_default_group() {
let mut groups: Vec<Group> = self.group_ctx.concrete_groups().into_iter().cloned().collect();
groups.push(self.group_ctx.default_group().clone());
groups
} else {
self.group_ctx.concrete_groups().into_iter().cloned().collect()
}
}
fn get_group(&self, group_id: &str) -> Option<(usize, Group)> {
@ -243,7 +249,7 @@ where
let cell_data = cell_bytes.parser::<P>()?;
let mut changesets = self.add_row_if_match(row_rev, &cell_data);
let default_group_changeset = self.update_default_group(row_rev, &changesets);
tracing::info!("default_group_changeset: {}", default_group_changeset);
tracing::trace!("default_group_changeset: {}", default_group_changeset);
if !default_group_changeset.is_empty() {
changesets.push(default_group_changeset);
}

View File

@ -27,6 +27,10 @@ impl GroupAction for CheckboxGroupController {
Some(CellRevision::new(UNCHECK.to_string()))
}
fn use_default_group(&self) -> bool {
false
}
fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool {
if cell_data.is_check() {
content == CHECK

View File

@ -3,7 +3,6 @@ use crate::services::field::*;
use crate::services::row::RowRevisionBuilder;
use flowy_grid_data_model::revision::BuildGridContext;
use flowy_sync::client_grid::GridBuilder;
use lib_infra::util::timestamp;
pub fn make_default_grid() -> BuildGridContext {
let mut grid_builder = GridBuilder::new();
@ -59,6 +58,45 @@ pub fn make_default_board() -> BuildGridContext {
let single_select_field_id = single_select_field.id.clone();
grid_builder.add_field(single_select_field);
for i in 0..3 {
let mut row_builder = RowRevisionBuilder::new(grid_builder.block_id(), grid_builder.field_revs());
row_builder.insert_select_option_cell(&single_select_field_id, to_do_option.id.clone());
let data = format!("Card {}", i + 1);
row_builder.insert_text_cell(&text_field_id, data);
let row = row_builder.build();
grid_builder.add_row(row);
}
grid_builder.build()
}
#[allow(dead_code)]
pub fn make_default_board_2() -> BuildGridContext {
let mut grid_builder = GridBuilder::new();
// text
let text_field = FieldBuilder::new(RichTextTypeOptionBuilder::default())
.name("Description")
.visibility(true)
.primary(true)
.build();
let text_field_id = text_field.id.clone();
grid_builder.add_field(text_field);
// single select
let to_do_option = SelectOptionPB::with_color("To Do", SelectOptionColorPB::Purple);
let doing_option = SelectOptionPB::with_color("Doing", SelectOptionColorPB::Orange);
let done_option = SelectOptionPB::with_color("Done", SelectOptionColorPB::Yellow);
let single_select_type_option = SingleSelectTypeOptionBuilder::default()
.add_option(to_do_option.clone())
.add_option(doing_option.clone())
.add_option(done_option.clone());
let single_select_field = FieldBuilder::new(single_select_type_option)
.name("Status")
.visibility(true)
.build();
let single_select_field_id = single_select_field.id.clone();
grid_builder.add_field(single_select_field);
// MultiSelect
let work_option = SelectOptionPB::with_color("Work", SelectOptionColorPB::Aqua);
let travel_option = SelectOptionPB::with_color("Travel", SelectOptionColorPB::Green);
@ -152,102 +190,3 @@ pub fn make_default_board() -> BuildGridContext {
grid_builder.build()
}
#[allow(dead_code)]
pub fn make_default_board2() -> BuildGridContext {
let mut grid_builder = GridBuilder::new();
// text
let text_field = FieldBuilder::new(RichTextTypeOptionBuilder::default())
.name("Name")
.visibility(true)
.primary(true)
.build();
let text_field_id = text_field.id.clone();
grid_builder.add_field(text_field);
// date
let date_type_option = DateTypeOptionBuilder::default();
let date_field = FieldBuilder::new(date_type_option)
.name("Date")
.visibility(true)
.build();
let date_field_id = date_field.id.clone();
let timestamp = timestamp();
grid_builder.add_field(date_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_type_option = SingleSelectTypeOptionBuilder::default()
.add_option(not_started_option.clone())
.add_option(in_progress_option)
.add_option(done_option);
let single_select_field = FieldBuilder::new(single_select_type_option)
.name("Status")
.visibility(true)
.build();
let single_select_field_id = single_select_field.id.clone();
grid_builder.add_field(single_select_field);
// MultiSelect
let apple_option = SelectOptionPB::new("Apple");
let banana_option = SelectOptionPB::new("Banana");
let pear_option = SelectOptionPB::new("Pear");
let multi_select_type_option = MultiSelectTypeOptionBuilder::default()
.add_option(banana_option.clone())
.add_option(apple_option.clone())
.add_option(pear_option);
let multi_select_field = FieldBuilder::new(multi_select_type_option)
.name("Fruit")
.visibility(true)
.build();
let multi_select_field_id = multi_select_field.id.clone();
grid_builder.add_field(multi_select_field);
// Number
let number_type_option = NumberTypeOptionBuilder::default().set_format(NumberFormat::USD);
let number_field = FieldBuilder::new(number_type_option)
.name("Price")
.visibility(true)
.build();
let number_field_id = number_field.id.clone();
grid_builder.add_field(number_field);
// Checkbox
let checkbox_type_option = CheckboxTypeOptionBuilder::default();
let checkbox_field = FieldBuilder::new(checkbox_type_option).name("Reimbursement").build();
let checkbox_field_id = checkbox_field.id.clone();
grid_builder.add_field(checkbox_field);
// Url
let url_type_option = URLTypeOptionBuilder::default();
let url_field = FieldBuilder::new(url_type_option).name("Shop Link").build();
let url_field_id = url_field.id.clone();
grid_builder.add_field(url_field);
// Insert rows
for i in 0..10 {
// insert single select
let mut row_builder = RowRevisionBuilder::new(grid_builder.block_id(), grid_builder.field_revs());
row_builder.insert_select_option_cell(&single_select_field_id, not_started_option.id.clone());
// insert multi select
row_builder.insert_select_option_cell(&multi_select_field_id, apple_option.id.clone());
row_builder.insert_select_option_cell(&multi_select_field_id, banana_option.id.clone());
// insert text
row_builder.insert_text_cell(&text_field_id, format!("Card {}", i));
// insert date
row_builder.insert_date_cell(&date_field_id, timestamp);
// number
row_builder.insert_number_cell(&number_field_id, i);
// checkbox
row_builder.insert_checkbox_cell(&checkbox_field_id, i % 2 == 0);
// url
row_builder.insert_url_cell(&url_field_id, "https://appflowy.io".to_string());
let row = row_builder.build();
grid_builder.add_row(row);
}
grid_builder.build()
}