mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: add documentation
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
||||||
|
@ -8,7 +8,7 @@ import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
|||||||
import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option_entities.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option_entities.pb.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
||||||
|
@ -4,7 +4,7 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_servic
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:flowy_sdk/log.dart';
|
import 'package:flowy_sdk/log.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import 'package:flowy_sdk/dispatch/dispatch.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-grid/cell_entities.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
|
||||||
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_service.dart';
|
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_service.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
import 'cell_service/cell_service.dart';
|
import 'cell_service/cell_service.dart';
|
||||||
|
|
||||||
class SelectOptionService {
|
class SelectOptionService {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
@ -6,8 +6,10 @@ import 'package:protobuf/protobuf.dart';
|
|||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
part 'edit_select_option_bloc.freezed.dart';
|
part 'edit_select_option_bloc.freezed.dart';
|
||||||
|
|
||||||
class EditSelectOptionBloc extends Bloc<EditSelectOptionEvent, EditSelectOptionState> {
|
class EditSelectOptionBloc
|
||||||
EditSelectOptionBloc({required SelectOptionPB option}) : super(EditSelectOptionState.initial(option)) {
|
extends Bloc<EditSelectOptionEvent, EditSelectOptionState> {
|
||||||
|
EditSelectOptionBloc({required SelectOptionPB option})
|
||||||
|
: super(EditSelectOptionState.initial(option)) {
|
||||||
on<EditSelectOptionEvent>(
|
on<EditSelectOptionEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
event.map(
|
event.map(
|
||||||
@ -48,7 +50,8 @@ class EditSelectOptionBloc extends Bloc<EditSelectOptionEvent, EditSelectOptionS
|
|||||||
@freezed
|
@freezed
|
||||||
class EditSelectOptionEvent with _$EditSelectOptionEvent {
|
class EditSelectOptionEvent with _$EditSelectOptionEvent {
|
||||||
const factory EditSelectOptionEvent.updateName(String name) = _UpdateName;
|
const factory EditSelectOptionEvent.updateName(String name) = _UpdateName;
|
||||||
const factory EditSelectOptionEvent.updateColor(SelectOptionColorPB color) = _UpdateColor;
|
const factory EditSelectOptionEvent.updateColor(SelectOptionColorPB color) =
|
||||||
|
_UpdateColor;
|
||||||
const factory EditSelectOptionEvent.delete() = _Delete;
|
const factory EditSelectOptionEvent.delete() = _Delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +62,8 @@ class EditSelectOptionState with _$EditSelectOptionState {
|
|||||||
required Option<bool> deleted,
|
required Option<bool> deleted,
|
||||||
}) = _EditSelectOptionState;
|
}) = _EditSelectOptionState;
|
||||||
|
|
||||||
factory EditSelectOptionState.initial(SelectOptionPB option) => EditSelectOptionState(
|
factory EditSelectOptionState.initial(SelectOptionPB option) =>
|
||||||
|
EditSelectOptionState(
|
||||||
option: option,
|
option: option,
|
||||||
deleted: none(),
|
deleted: none(),
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'package:flowy_sdk/log.dart';
|
import 'package:flowy_sdk/log.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/multi_select_type_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/multi_select_type_option.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'select_option_type_option_bloc.dart';
|
import 'select_option_type_option_bloc.dart';
|
||||||
import 'type_option_context.dart';
|
import 'type_option_context.dart';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import 'package:flowy_sdk/log.dart';
|
import 'package:flowy_sdk/log.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/single_select_type_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/single_select_type_option.pb.dart';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:protobuf/protobuf.dart';
|
import 'package:protobuf/protobuf.dart';
|
||||||
|
@ -2,7 +2,7 @@ import 'package:dartz/dartz.dart';
|
|||||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
import 'package:flowy_sdk/dispatch/dispatch.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-grid/cell_entities.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
|
|
||||||
class TypeOptionFFIService {
|
class TypeOptionFFIService {
|
||||||
final String gridId;
|
final String gridId;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||||
|
@ -7,7 +7,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
|||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
// ignore: unused_import
|
// ignore: unused_import
|
||||||
import 'package:flowy_sdk/log.dart';
|
import 'package:flowy_sdk/log.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.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';
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
|||||||
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.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 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
@ -2,7 +2,7 @@ import 'dart:collection';
|
|||||||
|
|
||||||
import 'package:flowy_infra/size.dart';
|
import 'package:flowy_infra/size.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||||
|
@ -6,7 +6,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
|||||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.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 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
@ -6,7 +6,7 @@ import 'package:flowy_infra_ui/style_widget/button.dart';
|
|||||||
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.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 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
@ -2,7 +2,7 @@ use crate::entities::*;
|
|||||||
use crate::manager::GridManager;
|
use crate::manager::GridManager;
|
||||||
use crate::services::cell::AnyCellData;
|
use crate::services::cell::AnyCellData;
|
||||||
use crate::services::field::{
|
use crate::services::field::{
|
||||||
default_type_option_builder_from_type, select_option_operation, type_option_builder_from_json_str,
|
default_type_option_builder_from_type, select_type_option_from_field_rev, type_option_builder_from_json_str,
|
||||||
DateChangesetParams, DateChangesetPayloadPB, SelectOptionCellChangeset, SelectOptionCellChangesetParams,
|
DateChangesetParams, DateChangesetPayloadPB, SelectOptionCellChangeset, SelectOptionCellChangesetParams,
|
||||||
SelectOptionCellChangesetPayloadPB, SelectOptionCellDataPB, SelectOptionChangeset, SelectOptionChangesetPayloadPB,
|
SelectOptionCellChangesetPayloadPB, SelectOptionCellDataPB, SelectOptionChangeset, SelectOptionChangesetPayloadPB,
|
||||||
SelectOptionPB,
|
SelectOptionPB,
|
||||||
@ -321,7 +321,7 @@ pub(crate) async fn new_select_option_handler(
|
|||||||
match editor.get_field_rev(¶ms.field_id).await {
|
match editor.get_field_rev(¶ms.field_id).await {
|
||||||
None => Err(ErrorCode::InvalidData.into()),
|
None => Err(ErrorCode::InvalidData.into()),
|
||||||
Some(field_rev) => {
|
Some(field_rev) => {
|
||||||
let type_option = select_option_operation(&field_rev)?;
|
let type_option = select_type_option_from_field_rev(&field_rev)?;
|
||||||
let select_option = type_option.create_option(¶ms.option_name);
|
let select_option = type_option.create_option(¶ms.option_name);
|
||||||
data_result(select_option)
|
data_result(select_option)
|
||||||
}
|
}
|
||||||
@ -338,7 +338,7 @@ pub(crate) async fn update_select_option_handler(
|
|||||||
|
|
||||||
let _ = editor
|
let _ = editor
|
||||||
.modify_field_rev(&changeset.cell_identifier.field_id, |field_rev| {
|
.modify_field_rev(&changeset.cell_identifier.field_id, |field_rev| {
|
||||||
let mut type_option = select_option_operation(field_rev)?;
|
let mut type_option = select_type_option_from_field_rev(field_rev)?;
|
||||||
let mut cell_content_changeset = None;
|
let mut cell_content_changeset = None;
|
||||||
let mut is_changed = None;
|
let mut is_changed = None;
|
||||||
|
|
||||||
@ -400,7 +400,7 @@ pub(crate) async fn get_select_option_handler(
|
|||||||
Some(field_rev) => {
|
Some(field_rev) => {
|
||||||
//
|
//
|
||||||
let cell_rev = editor.get_cell_rev(¶ms.row_id, ¶ms.field_id).await?;
|
let cell_rev = editor.get_cell_rev(¶ms.row_id, ¶ms.field_id).await?;
|
||||||
let type_option = select_option_operation(&field_rev)?;
|
let type_option = select_type_option_from_field_rev(&field_rev)?;
|
||||||
let any_cell_data: AnyCellData = match cell_rev {
|
let any_cell_data: AnyCellData = match cell_rev {
|
||||||
None => AnyCellData {
|
None => AnyCellData {
|
||||||
data: "".to_string(),
|
data: "".to_string(),
|
||||||
@ -408,8 +408,8 @@ pub(crate) async fn get_select_option_handler(
|
|||||||
},
|
},
|
||||||
Some(cell_rev) => cell_rev.try_into()?,
|
Some(cell_rev) => cell_rev.try_into()?,
|
||||||
};
|
};
|
||||||
let option_context = type_option.selected_select_option(any_cell_data.into());
|
let selected_options = type_option.get_selected_options(any_cell_data.into());
|
||||||
data_result(option_context)
|
data_result(selected_options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,30 @@ pub trait CellGroupOperation {
|
|||||||
|
|
||||||
/// Return object that describes the cell.
|
/// Return object that describes the cell.
|
||||||
pub trait CellDisplayable<CD> {
|
pub trait CellDisplayable<CD> {
|
||||||
/// Serialize the cell data into `CellBytes` that will be posted to `Dart` side
|
/// Serialize the cell data into `CellBytes` that will be posted to the `Dart` side. Using the
|
||||||
|
/// corresponding protobuf struct implement in `Dart` to deserialize the data.
|
||||||
///
|
///
|
||||||
/// Using `utf8` to encode the cell data if the cell data using `String` as its data container.
|
/// Using `utf8` to encode the cell data if the cell data use `String` as its data container.
|
||||||
/// Using `protobuf` to encode the cell data if the cell data using `Protobuf struct` as its data container.
|
/// Using `protobuf` to encode the cell data if the cell data use `Protobuf struct` as its data container.
|
||||||
|
///
|
||||||
|
/// When switching the field type of the `FieldRevision` to another field type. The `field_type`
|
||||||
|
/// of the `FieldRevision` is not equal to the `decoded_field_type`. The cell data is need to do
|
||||||
|
/// some custom transformation.
|
||||||
|
///
|
||||||
|
/// For example, the current field type of the `FieldRevision` is a checkbox. When switching the field
|
||||||
|
/// type from the checkbox to single select, the `TypeOptionBuilder`'s transform method gets called.
|
||||||
|
/// It will create two new options,`Yes` and `No`, if they don't exist. But the cell data didn't change,
|
||||||
|
/// because we can't iterate all the rows to transform the cell data that can be parsed by the current
|
||||||
|
/// field type. One approach is to transform the cell data when it get read. For the moment,
|
||||||
|
/// the cell data is a string, `Yes` or `No`. It needs to compare with the option's name, if match
|
||||||
|
/// return the id of the option. Otherwise, return a default value of `CellBytes`.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `cell_data`: the generic annotation `CD` represents as the deserialize data type of the cell.
|
||||||
|
/// * `decoded_field_type`: the field type of the cell_data when doing serialization
|
||||||
|
///
|
||||||
|
/// returns: Result<CellBytes, FlowyError>
|
||||||
///
|
///
|
||||||
fn displayed_cell_bytes(
|
fn displayed_cell_bytes(
|
||||||
&self,
|
&self,
|
||||||
@ -35,10 +55,10 @@ pub trait CellDisplayable<CD> {
|
|||||||
/// The cell data is not readable which means it can't display the cell data directly to user.
|
/// The cell data is not readable which means it can't display the cell data directly to user.
|
||||||
/// For example,
|
/// For example,
|
||||||
/// 1. the cell data is timestamp if its field type is FieldType::Date that is not readable.
|
/// 1. the cell data is timestamp if its field type is FieldType::Date that is not readable.
|
||||||
/// it needs to be parsed as the date string.
|
/// It needs to be parsed as the date string.
|
||||||
///
|
///
|
||||||
/// 2. the cell data is a commas separated id if its field type if FieldType::MultiSelect that is not readable.
|
/// 2. the cell data is a commas separated id if its field type if FieldType::MultiSelect that is not readable.
|
||||||
/// it needs to be parsed as a commas separated option name.
|
/// It needs to be parsed as a commas separated option name.
|
||||||
///
|
///
|
||||||
fn displayed_cell_string(
|
fn displayed_cell_string(
|
||||||
&self,
|
&self,
|
||||||
@ -48,16 +68,19 @@ pub trait CellDisplayable<CD> {
|
|||||||
) -> FlowyResult<String>;
|
) -> FlowyResult<String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CD: Short for CellData. This type is the type return by apply_changeset function.
|
|
||||||
// CS: Short for Changeset. Parse the string into specific Changeset type.
|
|
||||||
pub trait CellDataOperation<CD, CS> {
|
pub trait CellDataOperation<CD, CS> {
|
||||||
/// Decode the cell data into `CD` that is certain type of data.
|
/// The generic annotation `CD` represents as the deserialize data type of the cell data.
|
||||||
|
/// The Serialize/Deserialize struct of the cell is base on the field type of the cell.
|
||||||
///
|
///
|
||||||
/// Each `CD` type represents as a specific field type data. For example:
|
/// For example:
|
||||||
/// FieldType::URL => URLCellData
|
/// FieldType::URL => URLCellData
|
||||||
/// FieldType::Date=> DateCellData
|
/// FieldType::Date=> DateCellData
|
||||||
///
|
///
|
||||||
/// `decoded_field_type`: the field type of the cell data
|
/// Each cell data is a opaque data, it needs to deserialized to a concrete data struct
|
||||||
|
///
|
||||||
|
/// `cell_data`: the opaque data of the cell.
|
||||||
|
/// `decoded_field_type`: the field type of the cell data when doing serialization
|
||||||
|
/// `field_rev`: the field of the cell data
|
||||||
///
|
///
|
||||||
/// Returns the error if the cell data can't be parsed into `CD`.
|
/// Returns the error if the cell data can't be parsed into `CD`.
|
||||||
///
|
///
|
||||||
@ -68,9 +91,12 @@ pub trait CellDataOperation<CD, CS> {
|
|||||||
field_rev: &FieldRevision,
|
field_rev: &FieldRevision,
|
||||||
) -> FlowyResult<CellBytes>;
|
) -> FlowyResult<CellBytes>;
|
||||||
|
|
||||||
/// The changeset is able to parse into the specific data if CS impl the FromCellChangeset trait.
|
/// The changeset is able to parse into the concrete data struct if CS implements
|
||||||
|
/// the `FromCellChangeset` trait.
|
||||||
|
///
|
||||||
/// For example:
|
/// For example:
|
||||||
/// SelectOptionCellChangeset,DateCellChangeset. etc.
|
/// SelectOptionCellChangeset,DateCellChangeset. etc.
|
||||||
|
///
|
||||||
fn apply_changeset(&self, changeset: CellDataChangeset<CS>, cell_rev: Option<CellRevision>) -> FlowyResult<String>;
|
fn apply_changeset(&self, changeset: CellDataChangeset<CS>, cell_rev: Option<CellRevision>) -> FlowyResult<String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,10 @@ use bytes::Bytes;
|
|||||||
use flowy_grid_data_model::revision::TypeOptionDataSerializer;
|
use flowy_grid_data_model::revision::TypeOptionDataSerializer;
|
||||||
|
|
||||||
pub trait TypeOptionBuilder {
|
pub trait TypeOptionBuilder {
|
||||||
|
/// Returns the type of the type-option data
|
||||||
fn field_type(&self) -> FieldType;
|
fn field_type(&self) -> FieldType;
|
||||||
|
|
||||||
|
/// Returns a serializer that can be used to serialize the type-option data
|
||||||
fn serializer(&self) -> &dyn TypeOptionDataSerializer;
|
fn serializer(&self) -> &dyn TypeOptionDataSerializer;
|
||||||
|
|
||||||
/// Transform the data from passed-in type-option to current type-option
|
/// Transform the data from passed-in type-option to current type-option
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
mod multi_select_type_option;
|
mod multi_select_type_option;
|
||||||
mod select_option;
|
mod select_type_option;
|
||||||
mod single_select_type_option;
|
mod single_select_type_option;
|
||||||
|
|
||||||
pub use multi_select_type_option::*;
|
pub use multi_select_type_option::*;
|
||||||
pub use select_option::*;
|
pub use select_type_option::*;
|
||||||
pub use single_select_type_option::*;
|
pub use single_select_type_option::*;
|
||||||
|
@ -3,8 +3,8 @@ use crate::impl_type_option;
|
|||||||
use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable};
|
use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable};
|
||||||
use crate::services::field::type_options::util::get_cell_data;
|
use crate::services::field::type_options::util::get_cell_data;
|
||||||
use crate::services::field::{
|
use crate::services::field::{
|
||||||
make_selected_select_options, BoxTypeOptionBuilder, SelectOptionCellChangeset, SelectOptionCellDataPB,
|
BoxTypeOptionBuilder, SelectOptionCellChangeset, SelectOptionIds, SelectOptionPB, SelectTypeOptionSharedAction,
|
||||||
SelectOptionColorPB, SelectOptionIds, SelectOptionOperation, SelectOptionPB, TypeOptionBuilder, CHECK, UNCHECK,
|
TypeOptionBuilder,
|
||||||
};
|
};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_derive::ProtoBuf;
|
use flowy_derive::ProtoBuf;
|
||||||
@ -25,13 +25,9 @@ pub struct MultiSelectTypeOptionPB {
|
|||||||
}
|
}
|
||||||
impl_type_option!(MultiSelectTypeOptionPB, FieldType::MultiSelect);
|
impl_type_option!(MultiSelectTypeOptionPB, FieldType::MultiSelect);
|
||||||
|
|
||||||
impl SelectOptionOperation for MultiSelectTypeOptionPB {
|
impl SelectTypeOptionSharedAction for MultiSelectTypeOptionPB {
|
||||||
fn selected_select_option(&self, cell_data: CellData<SelectOptionIds>) -> SelectOptionCellDataPB {
|
fn number_of_max_options(&self) -> Option<usize> {
|
||||||
let select_options = make_selected_select_options(cell_data, &self.options);
|
None
|
||||||
SelectOptionCellDataPB {
|
|
||||||
options: self.options.clone(),
|
|
||||||
select_options,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn options(&self) -> &Vec<SelectOptionPB> {
|
fn options(&self) -> &Vec<SelectOptionPB> {
|
||||||
@ -113,23 +109,8 @@ impl TypeOptionBuilder for MultiSelectTypeOptionBuilder {
|
|||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transform(&mut self, field_type: &FieldType, _type_option_data: String) {
|
fn transform(&mut self, field_type: &FieldType, type_option_data: String) {
|
||||||
match field_type {
|
self.0.transform_type_option(field_type, type_option_data);
|
||||||
FieldType::Checkbox => {
|
|
||||||
//Add Yes and No options if it's not exist.
|
|
||||||
if !self.0.options.iter().any(|option| option.name == CHECK) {
|
|
||||||
let check_option = SelectOptionPB::with_color(CHECK, SelectOptionColorPB::Green);
|
|
||||||
self.0.options.push(check_option);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !self.0.options.iter().any(|option| option.name == UNCHECK) {
|
|
||||||
let uncheck_option = SelectOptionPB::with_color(UNCHECK, SelectOptionColorPB::Yellow);
|
|
||||||
self.0.options.push(uncheck_option);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FieldType::SingleSelect => {}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -154,6 +135,8 @@ mod tests {
|
|||||||
debug_assert_eq!(multi_select.0.options.len(), 2);
|
debug_assert_eq!(multi_select.0.options.len(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn multi_select_insert_multi_option_test() {
|
fn multi_select_insert_multi_option_test() {
|
||||||
let google = SelectOptionPB::new("Google");
|
let google = SelectOptionPB::new("Google");
|
||||||
|
@ -2,7 +2,7 @@ use crate::entities::{CellChangesetPB, FieldType, GridCellIdPB, GridCellIdParams
|
|||||||
use crate::services::cell::{
|
use crate::services::cell::{
|
||||||
CellBytes, CellBytesParser, CellData, CellDataIsEmpty, CellDisplayable, FromCellChangeset, FromCellString,
|
CellBytes, CellBytesParser, CellData, CellDataIsEmpty, CellDisplayable, FromCellChangeset, FromCellString,
|
||||||
};
|
};
|
||||||
use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB};
|
use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB, CHECK, UNCHECK};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||||
use flowy_error::{internal_error, ErrorCode, FlowyResult};
|
use flowy_error::{internal_error, ErrorCode, FlowyResult};
|
||||||
@ -64,10 +64,7 @@ impl std::default::Default for SelectOptionColorPB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_selected_select_options(
|
pub fn make_selected_options(cell_data: CellData<SelectOptionIds>, options: &[SelectOptionPB]) -> Vec<SelectOptionPB> {
|
||||||
cell_data: CellData<SelectOptionIds>,
|
|
||||||
options: &[SelectOptionPB],
|
|
||||||
) -> Vec<SelectOptionPB> {
|
|
||||||
if let Ok(ids) = cell_data.try_into_inner() {
|
if let Ok(ids) = cell_data.try_into_inner() {
|
||||||
ids.iter()
|
ids.iter()
|
||||||
.flat_map(|option_id| options.iter().find(|option| &option.id == option_id).cloned())
|
.flat_map(|option_id| options.iter().find(|option| &option.id == option_id).cloned())
|
||||||
@ -76,8 +73,11 @@ pub fn make_selected_select_options(
|
|||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Defines the shared actions used by SingleSelect or Multi-Select.
|
||||||
|
pub trait SelectTypeOptionSharedAction: TypeOptionDataSerializer + Send + Sync {
|
||||||
|
/// Returns `None` means there is no limited
|
||||||
|
fn number_of_max_options(&self) -> Option<usize>;
|
||||||
|
|
||||||
pub trait SelectOptionOperation: TypeOptionDataSerializer + Send + Sync {
|
|
||||||
/// Insert the `SelectOptionPB` into corresponding type option.
|
/// Insert the `SelectOptionPB` into corresponding type option.
|
||||||
fn insert_option(&mut self, new_option: SelectOptionPB) {
|
fn insert_option(&mut self, new_option: SelectOptionPB) {
|
||||||
let options = self.mut_options();
|
let options = self.mut_options();
|
||||||
@ -104,7 +104,60 @@ pub trait SelectOptionOperation: TypeOptionDataSerializer + Send + Sync {
|
|||||||
SelectOptionPB::with_color(name, color)
|
SelectOptionPB::with_color(name, color)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn selected_select_option(&self, cell_data: CellData<SelectOptionIds>) -> SelectOptionCellDataPB;
|
/// Return a list of options that are selected by user
|
||||||
|
fn get_selected_options(&self, cell_data: CellData<SelectOptionIds>) -> SelectOptionCellDataPB {
|
||||||
|
let mut select_options = make_selected_options(cell_data, self.options());
|
||||||
|
match self.number_of_max_options() {
|
||||||
|
None => {}
|
||||||
|
Some(number_of_max_options) => {
|
||||||
|
select_options.truncate(number_of_max_options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SelectOptionCellDataPB {
|
||||||
|
options: self.options().clone(),
|
||||||
|
select_options,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn transform_type_option(&mut self, field_type: &FieldType, _type_option_data: String) {
|
||||||
|
match field_type {
|
||||||
|
FieldType::Checkbox => {
|
||||||
|
//add Yes and No options if it's not exist.
|
||||||
|
if !self.options().iter().any(|option| option.name == CHECK) {
|
||||||
|
let check_option = SelectOptionPB::with_color(CHECK, SelectOptionColorPB::Green);
|
||||||
|
self.mut_options().push(check_option);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.options().iter().any(|option| option.name == UNCHECK) {
|
||||||
|
let uncheck_option = SelectOptionPB::with_color(UNCHECK, SelectOptionColorPB::Yellow);
|
||||||
|
self.mut_options().push(uncheck_option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FieldType::MultiSelect => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn transform_cell_data(
|
||||||
|
&self,
|
||||||
|
cell_data: CellData<SelectOptionIds>,
|
||||||
|
decoded_field_type: &FieldType,
|
||||||
|
_field_rev: &FieldRevision,
|
||||||
|
) -> FlowyResult<CellBytes> {
|
||||||
|
match decoded_field_type {
|
||||||
|
FieldType::SingleSelect | FieldType::MultiSelect => {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
FieldType::Checkbox => {
|
||||||
|
// transform the cell data to the option id
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Ok(CellBytes::default());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CellBytes::from(self.get_selected_options(cell_data))
|
||||||
|
}
|
||||||
|
|
||||||
fn options(&self) -> &Vec<SelectOptionPB>;
|
fn options(&self) -> &Vec<SelectOptionPB>;
|
||||||
|
|
||||||
@ -113,19 +166,15 @@ pub trait SelectOptionOperation: TypeOptionDataSerializer + Send + Sync {
|
|||||||
|
|
||||||
impl<T> CellDisplayable<SelectOptionIds> for T
|
impl<T> CellDisplayable<SelectOptionIds> for T
|
||||||
where
|
where
|
||||||
T: SelectOptionOperation,
|
T: SelectTypeOptionSharedAction,
|
||||||
{
|
{
|
||||||
fn displayed_cell_bytes(
|
fn displayed_cell_bytes(
|
||||||
&self,
|
&self,
|
||||||
cell_data: CellData<SelectOptionIds>,
|
cell_data: CellData<SelectOptionIds>,
|
||||||
decoded_field_type: &FieldType,
|
decoded_field_type: &FieldType,
|
||||||
_field_rev: &FieldRevision,
|
field_rev: &FieldRevision,
|
||||||
) -> FlowyResult<CellBytes> {
|
) -> FlowyResult<CellBytes> {
|
||||||
if !decoded_field_type.is_select_option() {
|
self.transform_cell_data(cell_data, decoded_field_type, field_rev)
|
||||||
return Ok(CellBytes::default());
|
|
||||||
}
|
|
||||||
|
|
||||||
CellBytes::from(self.selected_select_option(cell_data))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn displayed_cell_string(
|
fn displayed_cell_string(
|
||||||
@ -135,7 +184,7 @@ where
|
|||||||
_field_rev: &FieldRevision,
|
_field_rev: &FieldRevision,
|
||||||
) -> FlowyResult<String> {
|
) -> FlowyResult<String> {
|
||||||
Ok(self
|
Ok(self
|
||||||
.selected_select_option(cell_data)
|
.get_selected_options(cell_data)
|
||||||
.select_options
|
.select_options
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|option| option.name)
|
.map(|option| option.name)
|
||||||
@ -144,7 +193,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_option_operation(field_rev: &FieldRevision) -> FlowyResult<Box<dyn SelectOptionOperation>> {
|
pub fn select_type_option_from_field_rev(
|
||||||
|
field_rev: &FieldRevision,
|
||||||
|
) -> FlowyResult<Box<dyn SelectTypeOptionSharedAction>> {
|
||||||
let field_type: FieldType = field_rev.ty.into();
|
let field_type: FieldType = field_rev.ty.into();
|
||||||
match &field_type {
|
match &field_type {
|
||||||
FieldType::SingleSelect => {
|
FieldType::SingleSelect => {
|
@ -1,11 +1,10 @@
|
|||||||
use crate::entities::FieldType;
|
use crate::entities::FieldType;
|
||||||
use crate::impl_type_option;
|
use crate::impl_type_option;
|
||||||
use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable};
|
use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable};
|
||||||
use crate::services::field::{
|
|
||||||
make_selected_select_options, SelectOptionCellChangeset, SelectOptionCellDataPB, SelectOptionColorPB,
|
|
||||||
SelectOptionIds, SelectOptionOperation, SelectOptionPB, CHECK, UNCHECK,
|
|
||||||
};
|
|
||||||
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
|
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
|
||||||
|
use crate::services::field::{
|
||||||
|
SelectOptionCellChangeset, SelectOptionIds, SelectOptionPB, SelectTypeOptionSharedAction,
|
||||||
|
};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_derive::ProtoBuf;
|
use flowy_derive::ProtoBuf;
|
||||||
use flowy_error::{FlowyError, FlowyResult};
|
use flowy_error::{FlowyError, FlowyResult};
|
||||||
@ -25,15 +24,9 @@ pub struct SingleSelectTypeOptionPB {
|
|||||||
}
|
}
|
||||||
impl_type_option!(SingleSelectTypeOptionPB, FieldType::SingleSelect);
|
impl_type_option!(SingleSelectTypeOptionPB, FieldType::SingleSelect);
|
||||||
|
|
||||||
impl SelectOptionOperation for SingleSelectTypeOptionPB {
|
impl SelectTypeOptionSharedAction for SingleSelectTypeOptionPB {
|
||||||
fn selected_select_option(&self, cell_data: CellData<SelectOptionIds>) -> SelectOptionCellDataPB {
|
fn number_of_max_options(&self) -> Option<usize> {
|
||||||
let mut select_options = make_selected_select_options(cell_data, &self.options);
|
Some(1)
|
||||||
// only keep option in single select
|
|
||||||
select_options.truncate(1);
|
|
||||||
SelectOptionCellDataPB {
|
|
||||||
options: self.options.clone(),
|
|
||||||
select_options,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn options(&self) -> &Vec<SelectOptionPB> {
|
fn options(&self) -> &Vec<SelectOptionPB> {
|
||||||
@ -102,23 +95,8 @@ impl TypeOptionBuilder for SingleSelectTypeOptionBuilder {
|
|||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transform(&mut self, field_type: &FieldType, _type_option_data: String) {
|
fn transform(&mut self, field_type: &FieldType, type_option_data: String) {
|
||||||
match field_type {
|
self.0.transform_type_option(field_type, type_option_data);
|
||||||
FieldType::Checkbox => {
|
|
||||||
//add Yes and No options if it's not exist.
|
|
||||||
if !self.0.options.iter().any(|option| option.name == CHECK) {
|
|
||||||
let check_option = SelectOptionPB::with_color(CHECK, SelectOptionColorPB::Green);
|
|
||||||
self.0.options.push(check_option);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !self.0.options.iter().any(|option| option.name == UNCHECK) {
|
|
||||||
let uncheck_option = SelectOptionPB::with_color(UNCHECK, SelectOptionColorPB::Yellow);
|
|
||||||
self.0.options.push(uncheck_option);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FieldType::MultiSelect => {}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use crate::entities::{SelectOptionCondition, SelectOptionFilterConfigurationPB};
|
use crate::entities::{SelectOptionCondition, SelectOptionFilterConfigurationPB};
|
||||||
use crate::services::cell::{AnyCellData, CellFilterOperation};
|
use crate::services::cell::{AnyCellData, CellFilterOperation};
|
||||||
use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB};
|
use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB};
|
||||||
use crate::services::field::{SelectOptionOperation, SelectedSelectOptions};
|
use crate::services::field::{SelectTypeOptionSharedAction, SelectedSelectOptions};
|
||||||
use flowy_error::FlowyResult;
|
use flowy_error::FlowyResult;
|
||||||
|
|
||||||
impl SelectOptionFilterConfigurationPB {
|
impl SelectOptionFilterConfigurationPB {
|
||||||
@ -49,7 +49,7 @@ impl CellFilterOperation<SelectOptionFilterConfigurationPB> for MultiSelectTypeO
|
|||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
let selected_options = SelectedSelectOptions::from(self.selected_select_option(any_cell_data.into()));
|
let selected_options = SelectedSelectOptions::from(self.get_selected_options(any_cell_data.into()));
|
||||||
Ok(filter.is_visible(&selected_options))
|
Ok(filter.is_visible(&selected_options))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ impl CellFilterOperation<SelectOptionFilterConfigurationPB> for SingleSelectType
|
|||||||
if !any_cell_data.is_single_select() {
|
if !any_cell_data.is_single_select() {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
let selected_options = SelectedSelectOptions::from(self.selected_select_option(any_cell_data.into()));
|
let selected_options = SelectedSelectOptions::from(self.get_selected_options(any_cell_data.into()));
|
||||||
Ok(filter.is_visible(&selected_options))
|
Ok(filter.is_visible(&selected_options))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use flowy_grid::entities::{
|
|||||||
};
|
};
|
||||||
use flowy_grid::services::cell::{delete_select_option_cell, insert_select_option_cell};
|
use flowy_grid::services::cell::{delete_select_option_cell, insert_select_option_cell};
|
||||||
use flowy_grid::services::field::{
|
use flowy_grid::services::field::{
|
||||||
edit_single_select_type_option, SelectOptionOperation, SelectOptionPB, SingleSelectTypeOptionPB,
|
edit_single_select_type_option, SelectOptionPB, SelectTypeOptionSharedAction, SingleSelectTypeOptionPB,
|
||||||
};
|
};
|
||||||
use flowy_grid_data_model::revision::{FieldRevision, RowChangeset};
|
use flowy_grid_data_model::revision::{FieldRevision, RowChangeset};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
Reference in New Issue
Block a user