Compare commits

...
Author SHA1 Message Date
nathan 87e7c18185 chore: ai tag 2024-06-17 21:07:39 +08:00
nathan fba6106787 Merge branch 'main' into ai_tag_feature 2024-06-13 15:23:56 +08:00
nathan d7fae6fa73 chore: update client api 2024-06-13 15:14:41 +08:00
nathan 805cbcb518 chore: integrate ai tag 2024-06-13 14:55:58 +08:00
41 changed files with 713 additions and 120 deletions

No files matched your search

@@ -0,0 +1,111 @@
import 'dart:async';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/field/field_info.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'tag_cell_bloc.freezed.dart';
class TagCellBloc extends Bloc<TagCellEvent, TagCellState> {
TagCellBloc({
required this.cellController,
}) : super(TagCellState.initial(cellController)) {
_dispatch();
_startListening();
}
final TagCellController cellController;
void Function()? _onCellChangedFn;
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
cellController.removeListener(
onCellChanged: _onCellChangedFn!,
onFieldChanged: _onFieldChangedListener,
);
}
await cellController.dispose();
return super.close();
}
void _dispatch() {
on<TagCellEvent>(
(event, emit) async {
await event.when(
didReceiveCellUpdate: (cellData) {
emit(
state.copyWith(content: cellData ?? ""),
);
},
didUpdateField: (fieldInfo) {
final wrap = fieldInfo.wrapCellContent;
if (wrap != null) {
emit(state.copyWith(wrap: wrap));
}
},
updateCell: (text) async {
if (state.content != text) {
emit(state.copyWith(content: text));
await cellController.saveCellData(text);
// If the input content is "abc" that can't parsered as number then the data stored in the backend will be an empty string.
// So for every cell data that will be formatted in the backend.
// It needs to get the formatted data after saving.
add(
TagCellEvent.didReceiveCellUpdate(
cellController.getCellData() ?? "",
),
);
}
},
);
},
);
}
void _startListening() {
_onCellChangedFn = cellController.addListener(
onCellChanged: (cellContent) {
if (!isClosed) {
add(
TagCellEvent.didReceiveCellUpdate(cellContent ?? ""),
);
}
},
onFieldChanged: _onFieldChangedListener,
);
}
void _onFieldChangedListener(FieldInfo fieldInfo) {
if (!isClosed) {
add(TagCellEvent.didUpdateField(fieldInfo));
}
}
}
@freezed
class TagCellEvent with _$TagCellEvent {
const factory TagCellEvent.didReceiveCellUpdate(String? cellContent) =
_DidReceiveCellUpdate;
const factory TagCellEvent.didUpdateField(FieldInfo fieldInfo) =
_DidUpdateField;
const factory TagCellEvent.updateCell(String text) = _UpdateCell;
}
@freezed
class TagCellState with _$TagCellState {
const factory TagCellState({
required String content,
required bool wrap,
}) = _TagCellState;
factory TagCellState.initial(TagCellController cellController) {
final wrap = cellController.fieldInfo.wrapCellContent;
return TagCellState(
content: cellController.getCellData() ?? "",
wrap: wrap ?? true,
);
}
}
@@ -18,6 +18,7 @@ typedef RelationCellController = CellController<RelationCellDataPB, String>;
typedef SummaryCellController = CellController<String, String>;
typedef TimeCellController = CellController<TimeCellDataPB, String>;
typedef TranslateCellController = CellController<String, String>;
typedef TagCellController = CellController<String, String>;
CellController makeCellController(
DatabaseController databaseController,
@@ -0,0 +1,62 @@
import 'package:appflowy/plugins/database/application/cell/bloc/tag_cell.bloc.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'card_cell.dart';
class TagCardCellStyle extends CardCellStyle {
const TagCardCellStyle({
required super.padding,
required this.textStyle,
});
final TextStyle textStyle;
}
class TagCardCell extends CardCell<TagCardCellStyle> {
const TagCardCell({
super.key,
required super.style,
required this.databaseController,
required this.cellContext,
});
final DatabaseController databaseController;
final CellContext cellContext;
@override
State<TagCardCell> createState() => _TagCellState();
}
class _TagCellState extends State<TagCardCell> {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) {
return TagCellBloc(
cellController: makeCellController(
widget.databaseController,
widget.cellContext,
).as(),
);
},
child: BlocBuilder<TagCellBloc, TagCellState>(
buildWhen: (previous, current) => previous.content != current.content,
builder: (context, state) {
if (state.content.isEmpty) {
return const SizedBox.shrink();
}
return Container(
alignment: AlignmentDirectional.centerStart,
padding: widget.style.padding,
child: Text(state.content, style: widget.style.textStyle),
);
},
),
);
}
}
@@ -1,3 +1,5 @@
import 'package:appflowy/plugins/database/widgets/cell/card_cell_skeleton/tag_card_cell.dart';
import 'package:appflowy/plugins/database/widgets/cell/card_cell_skeleton/translate_card_cell.dart';
import 'package:flutter/material.dart';
import 'package:appflowy/plugins/database/widgets/cell/card_cell_skeleton/summary_card_cell.dart';
@@ -89,7 +91,11 @@ CardCellStyleMap mobileBoardCardCellStyleMap(BuildContext context) {
padding: padding,
textStyle: textStyle,
),
FieldType.Translate: SummaryCardCellStyle(
FieldType.Translate: TranslateCardCellStyle(
padding: padding,
textStyle: textStyle,
),
FieldType.Tag: TagCardCellStyle(
padding: padding,
textStyle: textStyle,
),
@@ -24,6 +24,7 @@ const List<FieldType> _supportedFieldTypes = [
FieldType.Summary,
FieldType.Time,
FieldType.Translate,
FieldType.Tag,
];
class FieldTypeList extends StatelessWidget with FlowyOverlayDelegate {
@@ -1,7 +1,6 @@
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:appflowy/plugins/database/widgets/field/type_option_editor/translate.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
@@ -18,6 +17,7 @@ import 'summary.dart';
import 'time.dart';
import 'timestamp.dart';
import 'url.dart';
import 'tag.dart';
typedef TypeOptionDataCallback = void Function(Uint8List typeOptionData);
@@ -38,6 +38,7 @@ abstract class TypeOptionEditorFactory {
FieldType.Summary => const SummaryTypeOptionEditorFactory(),
FieldType.Time => const TimeTypeOptionEditorFactory(),
FieldType.Translate => const TranslateTypeOptionEditorFactory(),
FieldType.Tag => const TagTypeOptionEditorFactory(),
_ => throw UnimplementedError(),
};
}
@@ -0,0 +1,19 @@
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:flutter/material.dart';
import 'builder.dart';
class TagTypeOptionEditorFactory implements TypeOptionEditorFactory {
const TagTypeOptionEditorFactory();
@override
Widget? build({
required BuildContext context,
required String viewId,
required FieldPB field,
required PopoverMutex popoverMutex,
required TypeOptionDataCallback onTypeOptionUpdated,
}) =>
null;
}
@@ -24,6 +24,7 @@ extension FieldTypeExtension on FieldType {
FieldType.Summary => LocaleKeys.grid_field_summaryFieldName.tr(),
FieldType.Time => LocaleKeys.grid_field_timeFieldName.tr(),
FieldType.Translate => LocaleKeys.grid_field_translateFieldName.tr(),
FieldType.Tag => LocaleKeys.grid_field_tagFieldName.tr(),
_ => throw UnimplementedError(),
};
@@ -42,12 +43,14 @@ extension FieldTypeExtension on FieldType {
FieldType.Summary => FlowySvgs.ai_summary_s,
FieldType.Time => FlowySvgs.timer_start_s,
FieldType.Translate => FlowySvgs.ai_translate_s,
FieldType.Tag => FlowySvgs.ai_tag_s,
_ => throw UnimplementedError(),
};
FlowySvgData? get rightIcon => switch (this) {
FieldType.Summary => FlowySvgs.ai_indicator_s,
FieldType.Translate => FlowySvgs.ai_indicator_s,
FieldType.Tag => FlowySvgs.ai_indicator_s,
_ => null,
};
@@ -66,6 +69,7 @@ extension FieldTypeExtension on FieldType {
FieldType.Summary => const Color(0xFFBECCFF),
FieldType.Time => const Color(0xFFFDEDA7),
FieldType.Translate => const Color(0xFFBECCFF),
FieldType.Tag => const Color(0xFFBECCFF),
_ => throw UnimplementedError(),
};
@@ -85,6 +89,7 @@ extension FieldTypeExtension on FieldType {
FieldType.Summary => const Color(0xFF6859A7),
FieldType.Time => const Color(0xFFFDEDA7),
FieldType.Translate => const Color(0xFF6859A7),
FieldType.Tag => const Color(0xFF6859A7),
_ => throw UnimplementedError(),
};
}
+14 -29
View File
@@ -172,7 +172,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"bincode",
@@ -192,7 +192,7 @@ dependencies = [
[[package]]
name = "appflowy-ai-client"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"bytes",
@@ -203,20 +203,6 @@ dependencies = [
"thiserror",
]
[[package]]
name = "appflowy-cloud-billing-client"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud-Billing-Client?rev=9f9c2d1ad180987a31d18c6c067a56a5fa1f6da6#9f9c2d1ad180987a31d18c6c067a56a5fa1f6da6"
dependencies = [
"client-api",
"reqwest",
"serde",
"serde_json",
"shared-entity",
"tokio",
"yrs",
]
[[package]]
name = "appflowy_tauri"
version = "0.0.0"
@@ -786,7 +772,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"again",
"anyhow",
@@ -833,7 +819,7 @@ dependencies = [
[[package]]
name = "client-websocket"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"futures-channel",
"futures-util",
@@ -1073,7 +1059,7 @@ dependencies = [
[[package]]
name = "collab-rt-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"bincode",
@@ -1098,7 +1084,7 @@ dependencies = [
[[package]]
name = "collab-rt-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"async-trait",
@@ -1344,7 +1330,7 @@ dependencies = [
"cssparser-macros",
"dtoa-short",
"itoa 1.0.6",
"phf 0.11.2",
"phf 0.8.0",
"smallvec",
]
@@ -1455,7 +1441,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"app-error",
@@ -2262,7 +2248,6 @@ name = "flowy-server"
version = "0.1.0"
dependencies = [
"anyhow",
"appflowy-cloud-billing-client",
"bytes",
"chrono",
"client-api",
@@ -2876,7 +2861,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"futures-util",
@@ -2893,7 +2878,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"app-error",
@@ -3325,7 +3310,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"reqwest",
@@ -4830,7 +4815,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2"
dependencies = [
"bytes",
"heck 0.4.1",
"itertools 0.11.0",
"itertools 0.10.5",
"log",
"multimap",
"once_cell",
@@ -4851,7 +4836,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e"
dependencies = [
"anyhow",
"itertools 0.11.0",
"itertools 0.10.5",
"proc-macro2",
"quote",
"syn 2.0.47",
@@ -5815,7 +5800,7 @@ dependencies = [
[[package]]
name = "shared-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"app-error",
+1 -1
View File
@@ -52,7 +52,7 @@ collab-user = { version = "0.2" }
# Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9d3d28ad8937712cc688c20be7c0ee6e4d14a168" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "44ffc45c50e7fe362bd3f5ab4c7452e045d6b358" }
[dependencies]
serde_json.workspace = true
+13 -42
View File
@@ -216,7 +216,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"bincode",
@@ -236,7 +236,7 @@ dependencies = [
[[package]]
name = "appflowy-ai-client"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"bytes",
@@ -247,20 +247,6 @@ dependencies = [
"thiserror",
]
[[package]]
name = "appflowy-cloud-billing-client"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud-Billing-Client?rev=9f9c2d1ad180987a31d18c6c067a56a5fa1f6da6#9f9c2d1ad180987a31d18c6c067a56a5fa1f6da6"
dependencies = [
"client-api",
"reqwest",
"serde",
"serde_json",
"shared-entity",
"tokio",
"yrs",
]
[[package]]
name = "arc-swap"
version = "1.7.1"
@@ -576,7 +562,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"again",
"anyhow",
@@ -623,7 +609,7 @@ dependencies = [
[[package]]
name = "client-websocket"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"futures-channel",
"futures-util",
@@ -801,7 +787,7 @@ dependencies = [
[[package]]
name = "collab-rt-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"bincode",
@@ -826,7 +812,7 @@ dependencies = [
[[package]]
name = "collab-rt-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"async-trait",
@@ -995,7 +981,7 @@ dependencies = [
"cssparser-macros",
"dtoa-short",
"itoa",
"phf 0.11.2",
"phf 0.8.0",
"smallvec",
]
@@ -1040,7 +1026,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"app-error",
@@ -1546,7 +1532,6 @@ name = "flowy-server"
version = "0.1.0"
dependencies = [
"anyhow",
"appflowy-cloud-billing-client",
"bytes",
"chrono",
"client-api",
@@ -1901,7 +1886,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"futures-util",
@@ -1918,7 +1903,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"app-error",
@@ -2219,7 +2204,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"reqwest",
@@ -2936,7 +2921,7 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
dependencies = [
"phf_macros 0.8.0",
"phf_macros",
"phf_shared 0.8.0",
"proc-macro-hack",
]
@@ -2956,7 +2941,6 @@ version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
dependencies = [
"phf_macros 0.11.2",
"phf_shared 0.11.2",
]
@@ -3024,19 +3008,6 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "phf_macros"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
dependencies = [
"phf_generator 0.11.2",
"phf_shared 0.11.2",
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "phf_shared"
version = "0.8.0"
@@ -3921,7 +3892,7 @@ dependencies = [
[[package]]
name = "shared-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"app-error",
+1 -1
View File
@@ -55,7 +55,7 @@ yrs = "0.18.8"
# Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9d3d28ad8937712cc688c20be7c0ee6e4d14a168" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "44ffc45c50e7fe362bd3f5ab4c7452e045d6b358" }
[profile.dev]
opt-level = 0
+16 -15
View File
@@ -163,7 +163,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"bincode",
@@ -183,7 +183,7 @@ dependencies = [
[[package]]
name = "appflowy-ai-client"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"bytes",
@@ -746,7 +746,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"again",
"anyhow",
@@ -793,7 +793,7 @@ dependencies = [
[[package]]
name = "client-websocket"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"futures-channel",
"futures-util",
@@ -1042,7 +1042,7 @@ dependencies = [
[[package]]
name = "collab-rt-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"bincode",
@@ -1067,7 +1067,7 @@ dependencies = [
[[package]]
name = "collab-rt-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"async-trait",
@@ -1428,7 +1428,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"app-error",
@@ -2248,6 +2248,7 @@ dependencies = [
"flowy-codegen",
"flowy-derive",
"flowy-error",
"flowy-folder",
"flowy-notification",
"flowy-search-pub",
"flowy-sqlite",
@@ -2934,7 +2935,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"futures-util",
@@ -2951,7 +2952,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"app-error",
@@ -3388,7 +3389,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"reqwest",
@@ -5894,7 +5895,7 @@ dependencies = [
[[package]]
name = "shared-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ff4384fbd07a4b7394a9af8c9159cd65715d3471#ff4384fbd07a4b7394a9af8c9159cd65715d3471"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"app-error",
@@ -6873,9 +6874,9 @@ checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8"
[[package]]
name = "tokio"
version = "1.36.0"
version = "1.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
dependencies = [
"backtrace",
"bytes",
@@ -6893,9 +6894,9 @@ dependencies = [
[[package]]
name = "tokio-macros"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
dependencies = [
"proc-macro2",
"quote",
@@ -52,7 +52,7 @@ collab-user = { version = "0.2" }
# Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9d3d28ad8937712cc688c20be7c0ee6e4d14a168" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "44ffc45c50e7fe362bd3f5ab4c7452e045d6b358" }
[dependencies]
serde_json.workspace = true
+1
View File
@@ -1013,6 +1013,7 @@
"summaryFieldName": "AI Summary",
"timeFieldName": "Time",
"translateFieldName": "AI Translate",
"tagFieldName": "AI Tags",
"translateTo": "Translate to",
"numberFormat": "Number format",
"dateFormat": "Date format",
+29 -15
View File
@@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9d3d28ad8937712cc688c20be7c0ee6e4d14a168#9d3d28ad8937712cc688c20be7c0ee6e4d14a168"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"bincode",
@@ -183,7 +183,7 @@ dependencies = [
[[package]]
name = "appflowy-ai-client"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9d3d28ad8937712cc688c20be7c0ee6e4d14a168#9d3d28ad8937712cc688c20be7c0ee6e4d14a168"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"bytes",
@@ -664,7 +664,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9d3d28ad8937712cc688c20be7c0ee6e4d14a168#9d3d28ad8937712cc688c20be7c0ee6e4d14a168"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"again",
"anyhow",
@@ -711,7 +711,7 @@ dependencies = [
[[package]]
name = "client-websocket"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9d3d28ad8937712cc688c20be7c0ee6e4d14a168#9d3d28ad8937712cc688c20be7c0ee6e4d14a168"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"futures-channel",
"futures-util",
@@ -920,7 +920,7 @@ dependencies = [
[[package]]
name = "collab-rt-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9d3d28ad8937712cc688c20be7c0ee6e4d14a168#9d3d28ad8937712cc688c20be7c0ee6e4d14a168"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"bincode",
@@ -945,7 +945,7 @@ dependencies = [
[[package]]
name = "collab-rt-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9d3d28ad8937712cc688c20be7c0ee6e4d14a168#9d3d28ad8937712cc688c20be7c0ee6e4d14a168"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"async-trait",
@@ -1165,7 +1165,7 @@ dependencies = [
"cssparser-macros",
"dtoa-short",
"itoa",
"phf 0.8.0",
"phf 0.11.2",
"smallvec",
]
@@ -1265,7 +1265,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9d3d28ad8937712cc688c20be7c0ee6e4d14a168#9d3d28ad8937712cc688c20be7c0ee6e4d14a168"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"app-error",
@@ -2531,7 +2531,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9d3d28ad8937712cc688c20be7c0ee6e4d14a168#9d3d28ad8937712cc688c20be7c0ee6e4d14a168"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"futures-util",
@@ -2548,7 +2548,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9d3d28ad8937712cc688c20be7c0ee6e4d14a168#9d3d28ad8937712cc688c20be7c0ee6e4d14a168"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"app-error",
@@ -2913,7 +2913,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9d3d28ad8937712cc688c20be7c0ee6e4d14a168#9d3d28ad8937712cc688c20be7c0ee6e4d14a168"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"reqwest",
@@ -3789,7 +3789,7 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
dependencies = [
"phf_macros",
"phf_macros 0.8.0",
"phf_shared 0.8.0",
"proc-macro-hack",
]
@@ -3809,6 +3809,7 @@ version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
dependencies = [
"phf_macros 0.11.2",
"phf_shared 0.11.2",
]
@@ -3876,6 +3877,19 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "phf_macros"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
dependencies = [
"phf_generator 0.11.2",
"phf_shared 0.11.2",
"proc-macro2",
"quote",
"syn 2.0.47",
]
[[package]]
name = "phf_shared"
version = "0.8.0"
@@ -4079,7 +4093,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2"
dependencies = [
"bytes",
"heck 0.4.1",
"itertools 0.10.5",
"itertools 0.11.0",
"log",
"multimap",
"once_cell",
@@ -4100,7 +4114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e"
dependencies = [
"anyhow",
"itertools 0.10.5",
"itertools 0.11.0",
"proc-macro2",
"quote",
"syn 2.0.47",
@@ -4997,7 +5011,7 @@ dependencies = [
[[package]]
name = "shared-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9d3d28ad8937712cc688c20be7c0ee6e4d14a168#9d3d28ad8937712cc688c20be7c0ee6e4d14a168"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=44ffc45c50e7fe362bd3f5ab4c7452e045d6b358#44ffc45c50e7fe362bd3f5ab4c7452e045d6b358"
dependencies = [
"anyhow",
"app-error",
+1 -1
View File
@@ -94,7 +94,7 @@ yrs = "0.18.8"
# Run the script.add_workspace_members:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9d3d28ad8937712cc688c20be7c0ee6e4d14a168" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "44ffc45c50e7fe362bd3f5ab4c7452e045d6b358" }
[profile.dev]
opt-level = 1
@@ -6,6 +6,7 @@ use collab_database::fields::Field;
use collab_database::rows::Row;
use flowy_database2::entities::FieldType;
use flowy_database2::services::field::summary_type_option::summary::SummarizationTypeOption;
use flowy_database2::services::field::tag_type_option::tag::TagTypeOption;
use flowy_database2::services::field::translate_type_option::translate::TranslateTypeOption;
use flowy_database2::services::field::{
FieldBuilder, NumberFormat, NumberTypeOption, SelectOption, SelectOptionColor,
@@ -63,6 +64,7 @@ fn create_fields() -> Vec<Field> {
FieldType::SingleSelect => fields.push(create_single_select_field("Status")),
FieldType::Summary => fields.push(create_summary_field("AI summary")),
FieldType::Translate => fields.push(create_translate_field("AI Translate")),
FieldType::Tag => fields.push(create_tag_field("AI Tag")),
_ => {},
}
}
@@ -137,3 +139,11 @@ fn create_translate_field(name: &str) -> Field {
.name(name)
.build()
}
#[allow(dead_code)]
fn create_tag_field(name: &str) -> Field {
let type_option = TagTypeOption::default();
FieldBuilder::new(FieldType::Tag, type_option)
.name(name)
.build()
}
@@ -5,7 +5,7 @@ use std::sync::Arc;
use anyhow::Error;
use client_api::collab_sync::{SinkConfig, SyncObject, SyncPlugin};
use client_api::entity::ai_dto::RepeatedRelatedQuestion;
use client_api::entity::ai_dto::{RepeatedRelatedQuestion, TagRowResponse};
use client_api::entity::ChatMessageType;
use collab::core::origin::{CollabClient, CollabOrigin};
@@ -23,7 +23,7 @@ use flowy_chat_pub::cloud::{
StreamAnswer,
};
use flowy_database_pub::cloud::{
CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent,
CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent, TagRowContent,
TranslateRowContent, TranslateRowResponse,
};
use flowy_document::deps::DocumentData;
@@ -313,6 +313,21 @@ impl DatabaseCloudService for ServerProvider {
.await
})
}
fn tag_database_row(
&self,
workspace_id: &str,
tag_row: TagRowContent,
) -> FutureResult<TagRowResponse, Error> {
let workspace_id = workspace_id.to_string();
let server = self.get_server();
FutureResult::new(async move {
server?
.database_service()
.tag_database_row(&workspace_id, tag_row)
.await
})
}
}
impl DocumentCloudService for ServerProvider {
@@ -1,5 +1,7 @@
use anyhow::Error;
pub use client_api::entity::ai_dto::{TranslateItem, TranslateRowResponse};
pub use client_api::entity::ai_dto::{
TagItem, TagRowData, TagRowResponse, TranslateItem, TranslateRowResponse,
};
use collab::core::collab::DataSource;
use collab_entity::CollabType;
use lib_infra::future::FutureResult;
@@ -8,6 +10,8 @@ use std::collections::HashMap;
pub type CollabDocStateByOid = HashMap<String, DataSource>;
pub type SummaryRowContent = HashMap<String, String>;
pub type TranslateRowContent = Vec<TranslateItem>;
pub type TagRowContent = TagRowData;
/// A trait for database cloud service.
/// Each kind of server should implement this trait. Check out the [AppFlowyServerProvider] of
/// [flowy-server] crate for more information.
@@ -48,6 +52,12 @@ pub trait DatabaseCloudService: Send + Sync {
translate_row: TranslateRowContent,
language: &str,
) -> FutureResult<TranslateRowResponse, Error>;
fn tag_database_row(
&self,
workspace_id: &str,
tag_row: TagRowContent,
) -> FutureResult<TagRowResponse, Error>;
}
pub struct DatabaseSnapshot {
@@ -451,6 +451,7 @@ pub enum FieldType {
Summary = 11,
Translate = 12,
Time = 13,
Tag = 14,
}
impl Display for FieldType {
@@ -492,13 +493,17 @@ impl FieldType {
FieldType::Relation => "Relation",
FieldType::Summary => "Summarize",
FieldType::Translate => "Translate",
FieldType::Tag => "Tag",
FieldType::Time => "Time",
};
s.to_string()
}
pub fn is_ai_field(&self) -> bool {
matches!(self, FieldType::Summary | FieldType::Translate)
matches!(
self,
FieldType::Summary | FieldType::Translate | FieldType::Tag
)
}
pub fn is_number(&self) -> bool {
@@ -117,6 +117,10 @@ impl From<&Filter> for FilterPB {
.cloned::<TextFilterPB>()
.unwrap()
.try_into(),
FieldType::Tag => condition_and_content
.cloned::<TextFilterPB>()
.unwrap()
.try_into(),
};
Self {
@@ -170,6 +174,9 @@ impl TryFrom<FilterDataPB> for FilterInner {
FieldType::Translate => {
BoxAny::new(TextFilterPB::try_from(bytes).map_err(|_| ErrorCode::ProtobufSerde)?)
},
FieldType::Tag => {
BoxAny::new(TextFilterPB::try_from(bytes).map_err(|_| ErrorCode::ProtobufSerde)?)
},
};
Ok(Self::Data {
@@ -18,6 +18,7 @@ macro_rules! impl_into_field_type {
11 => FieldType::Summary,
12 => FieldType::Translate,
13 => FieldType::Time,
14 => FieldType::Tag,
_ => {
tracing::error!("🔴Can't parse FieldType from value: {}", ty);
FieldType::RichText
@@ -5,6 +5,7 @@ mod number_entities;
mod relation_entities;
mod select_option_entities;
mod summary_entities;
mod tag_entities;
mod text_entities;
mod time_entities;
mod timestamp_entities;
@@ -18,6 +19,7 @@ pub use number_entities::*;
pub use relation_entities::*;
pub use select_option_entities::*;
pub use summary_entities::*;
pub use tag_entities::*;
pub use text_entities::*;
pub use time_entities::*;
pub use timestamp_entities::*;
@@ -0,0 +1,53 @@
use crate::entities::TranslateTypeOptionPB;
use crate::services::field::tag_type_option::tag::{TagOption, TagTypeOption};
use flowy_derive::ProtoBuf;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, ProtoBuf)]
pub struct TagTypeOptionPB {
#[pb(index = 1)]
pub tags: Vec<TagItemPB>,
}
#[derive(ProtoBuf, Debug, Clone, Default)]
pub struct TagItemPB {
#[pb(index = 1)]
color: String,
#[pb(index = 2)]
text: String,
}
impl From<TagOption> for TagItemPB {
fn from(value: TagOption) -> Self {
Self {
color: value.color,
text: value.text,
}
}
}
impl From<TagItemPB> for TagOption {
fn from(value: TagItemPB) -> Self {
Self {
color: value.color,
text: value.text,
}
}
}
impl From<TagTypeOption> for TagTypeOptionPB {
fn from(value: TagTypeOption) -> Self {
Self {
tags: value.tags.into_iter().map(TagItemPB::from).collect(),
}
}
}
impl From<TagTypeOptionPB> for TagTypeOption {
fn from(value: TagTypeOptionPB) -> Self {
Self {
tags: value.tags.into_iter().map(TagOption::from).collect(),
}
}
}
@@ -18,7 +18,8 @@ use tracing::{event, instrument, trace};
use collab_integrate::collab_builder::{AppFlowyCollabBuilder, CollabBuilderConfig};
use collab_integrate::{CollabKVAction, CollabKVDB, CollabPersistenceConfig};
use flowy_database_pub::cloud::{
DatabaseCloudService, SummaryRowContent, TranslateItem, TranslateRowContent,
DatabaseCloudService, SummaryRowContent, TagItem, TagRowContent, TranslateItem,
TranslateRowContent,
};
use flowy_error::{internal_error, FlowyError, FlowyResult};
use lib_infra::box_any::BoxAny;
@@ -28,6 +29,7 @@ use crate::entities::{DatabaseLayoutPB, DatabaseSnapshotPB, FieldType};
use crate::services::cell::stringify_cell;
use crate::services::database::DatabaseEditor;
use crate::services::database_view::DatabaseLayoutDepsResolver;
use crate::services::field::tag_type_option::tag::{TagOption, TagTypeOption};
use crate::services::field::translate_type_option::translate::TranslateTypeOption;
use crate::services::field_settings::default_field_settings_by_layout_map;
@@ -506,7 +508,6 @@ impl DatabaseManager {
}
}
// Call the cloud service to summarize the row.
trace!(
"[AI]:translate to {}, content:{:?}",
language,
@@ -539,6 +540,59 @@ impl DatabaseManager {
Ok(())
}
#[instrument(level = "debug", skip_all)]
pub async fn tag_row(&self, view_id: String, row_id: RowId, field_id: String) -> FlowyResult<()> {
let database = self.get_database_with_view_id(&view_id).await?;
let mut tag_row = TagRowContent {
existing_tags: vec![],
items: vec![],
num_tags: 5,
};
if let Some(row) = database.get_row(&view_id, &row_id) {
let fields = database.get_fields(&view_id, None);
for field in fields {
if field.id != field_id {
if FieldType::from(field.field_type).is_ai_field() {
continue;
}
if let Some(cell) = row.cells.get(&field.id) {
tag_row.items.push(TagItem {
title: field.name.clone(),
content: stringify_cell(cell, &field),
})
}
} else {
tag_row.existing_tags.extend(
field
.type_options
.get(&FieldType::Tag.to_string())
.cloned()
.map(TagTypeOption::from)
.unwrap_or_default()
.tags
.into_iter()
.map(|tag| tag.text)
.collect::<Vec<String>>(),
)
}
}
}
let response = self
.cloud_service
.tag_database_row(&self.user.workspace_id()?, tag_row)
.await?;
// Format the response items into a single string
let content = response.tags.join(", ");
trace!("[AI]:tag row response: {}", content);
database
.update_cell_with_changeset(&view_id, &row_id, &field_id, BoxAny::new(content))
.await?;
Ok(())
}
/// Only expose this method for testing
#[cfg(debug_assertions)]
pub fn get_cloud_service(&self) -> &Arc<dyn DatabaseCloudService> {
@@ -265,6 +265,9 @@ impl<'a> CellBuilder<'a> {
FieldType::Translate => {
cells.insert(field_id, insert_text_cell(cell_str, field));
},
FieldType::Tag => {
cells.insert(field_id, insert_text_cell(cell_str, field));
},
}
}
}
@@ -5,6 +5,7 @@ pub mod number_type_option;
pub mod relation_type_option;
pub mod selection_type_option;
pub mod summary_type_option;
pub mod tag_type_option;
pub mod text_type_option;
pub mod time_type_option;
pub mod timestamp_type_option;
@@ -0,0 +1,2 @@
pub mod tag;
pub mod tag_entities;
@@ -0,0 +1,132 @@
use crate::entities::TextFilterPB;
use crate::services::cell::{CellDataChangeset, CellDataDecoder};
use crate::services::field::type_options::tag_type_option::tag_entities::TagCellData;
use crate::services::field::type_options::util::ProtobufStr;
use crate::services::field::{
TypeOption, TypeOptionCellData, TypeOptionCellDataCompare, TypeOptionCellDataFilter,
TypeOptionCellDataSerde, TypeOptionTransform,
};
use crate::services::sort::SortCondition;
use collab::core::any_map::{AnyMap, AnyMapExtension};
use collab_database::fields::{TypeOptionData, TypeOptionDataBuilder};
use collab_database::rows::Cell;
use flowy_error::FlowyResult;
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
#[derive(Debug, Clone, Default)]
pub struct TagTypeOption {
pub tags: Vec<TagOption>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct TagOption {
pub color: String,
pub text: String,
}
impl From<AnyMap> for TagOption {
fn from(value: AnyMap) -> Self {
let color = value.get_str_value("color").unwrap_or_default();
let text = value.get_str_value("text").unwrap_or_default();
Self { color, text }
}
}
impl From<TagOption> for AnyMap {
fn from(value: TagOption) -> Self {
let mut map = AnyMap::new();
map.insert_str_value("color", value.color);
map.insert_str_value("text", value.text);
map
}
}
impl From<TypeOptionData> for TagTypeOption {
fn from(value: TypeOptionData) -> Self {
let tags = value.get_array("tags");
Self { tags }
}
}
impl From<TagTypeOption> for TypeOptionData {
fn from(value: TagTypeOption) -> Self {
TypeOptionDataBuilder::new()
.insert_maps("tags", value.tags)
.build()
}
}
impl TypeOption for TagTypeOption {
type CellData = TagCellData;
type CellChangeset = String;
type CellProtobufType = ProtobufStr;
type CellFilter = TextFilterPB;
}
impl CellDataChangeset for TagTypeOption {
fn apply_changeset(
&self,
changeset: String,
_cell: Option<Cell>,
) -> FlowyResult<(Cell, TagCellData)> {
let cell_data = TagCellData(changeset);
Ok((cell_data.clone().into(), cell_data))
}
}
impl TypeOptionCellDataFilter for TagTypeOption {
fn apply_filter(
&self,
filter: &<Self as TypeOption>::CellFilter,
cell_data: &<Self as TypeOption>::CellData,
) -> bool {
filter.is_visible(cell_data)
}
}
impl TypeOptionCellDataCompare for TagTypeOption {
fn apply_cmp(
&self,
cell_data: &<Self as TypeOption>::CellData,
other_cell_data: &<Self as TypeOption>::CellData,
sort_condition: SortCondition,
) -> Ordering {
match (cell_data.is_cell_empty(), other_cell_data.is_cell_empty()) {
(true, true) => Ordering::Equal,
(true, false) => Ordering::Greater,
(false, true) => Ordering::Less,
(false, false) => {
let order = cell_data.0.cmp(&other_cell_data.0);
sort_condition.evaluate_order(order)
},
}
}
}
impl CellDataDecoder for TagTypeOption {
fn decode_cell(&self, cell: &Cell) -> FlowyResult<TagCellData> {
Ok(TagCellData::from(cell))
}
fn stringify_cell_data(&self, cell_data: TagCellData) -> String {
cell_data.to_string()
}
fn numeric_cell(&self, _cell: &Cell) -> Option<f64> {
None
}
}
impl TypeOptionTransform for TagTypeOption {}
impl TypeOptionCellDataSerde for TagTypeOption {
fn protobuf_encode(
&self,
cell_data: <Self as TypeOption>::CellData,
) -> <Self as TypeOption>::CellProtobufType {
ProtobufStr::from(cell_data.0)
}
fn parse_cell(&self, cell: &Cell) -> FlowyResult<<Self as TypeOption>::CellData> {
Ok(TagCellData::from(cell))
}
}
@@ -0,0 +1,46 @@
use crate::entities::FieldType;
use crate::services::field::{TypeOptionCellData, CELL_DATA};
use collab::core::any_map::AnyMapExtension;
use collab_database::rows::{new_cell_builder, Cell};
#[derive(Default, Debug, Clone)]
pub struct TagCellData(pub String);
impl std::ops::Deref for TagCellData {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl TypeOptionCellData for TagCellData {
fn is_cell_empty(&self) -> bool {
self.0.is_empty()
}
}
impl From<&Cell> for TagCellData {
fn from(cell: &Cell) -> Self {
Self(cell.get_str_value(CELL_DATA).unwrap_or_default())
}
}
impl From<TagCellData> for Cell {
fn from(data: TagCellData) -> Self {
new_cell_builder(FieldType::Tag)
.insert_str_value(CELL_DATA, data.0)
.build()
}
}
impl ToString for TagCellData {
fn to_string(&self) -> String {
self.0.clone()
}
}
impl AsRef<str> for TagCellData {
fn as_ref(&self) -> &str {
&self.0
}
}
@@ -82,7 +82,8 @@ impl CellDataDecoder for RichTextTypeOption {
| FieldType::URL
| FieldType::Summary
| FieldType::Translate
| FieldType::Time => Some(StringCellData::from(stringify_cell(cell, field))),
| FieldType::Time
| FieldType::Tag => Some(StringCellData::from(stringify_cell(cell, field))),
FieldType::Checklist
| FieldType::LastEditedTime
| FieldType::CreatedTime
@@ -11,12 +11,13 @@ use flowy_error::FlowyResult;
use crate::entities::{
CheckboxTypeOptionPB, ChecklistTypeOptionPB, DateTypeOptionPB, FieldType,
MultiSelectTypeOptionPB, NumberTypeOptionPB, RelationTypeOptionPB, RichTextTypeOptionPB,
SingleSelectTypeOptionPB, SummarizationTypeOptionPB, TimeTypeOptionPB, TimestampTypeOptionPB,
TranslateTypeOptionPB, URLTypeOptionPB,
SingleSelectTypeOptionPB, SummarizationTypeOptionPB, TagTypeOptionPB, TimeTypeOptionPB,
TimestampTypeOptionPB, TranslateTypeOptionPB, URLTypeOptionPB,
};
use crate::services::cell::CellDataDecoder;
use crate::services::field::checklist_type_option::ChecklistTypeOption;
use crate::services::field::summary_type_option::summary::SummarizationTypeOption;
use crate::services::field::tag_type_option::tag::TagTypeOption;
use crate::services::field::translate_type_option::translate::TranslateTypeOption;
use crate::services::field::{
CheckboxTypeOption, DateTypeOption, MultiSelectTypeOption, NumberTypeOption, RelationTypeOption,
@@ -191,6 +192,7 @@ pub fn type_option_data_from_pb<T: Into<Bytes>>(
FieldType::Translate => {
TranslateTypeOptionPB::try_from(bytes).map(|pb| TranslateTypeOption::from(pb).into())
},
FieldType::Tag => TagTypeOptionPB::try_from(bytes).map(|pb| TagTypeOption::from(pb).into()),
}
}
@@ -268,6 +270,10 @@ pub fn type_option_to_pb(type_option: TypeOptionData, field_type: &FieldType) ->
.try_into()
.unwrap()
},
FieldType::Tag => {
let tag_type_option: TagTypeOption = type_option.into();
TagTypeOptionPB::from(tag_type_option).try_into().unwrap()
},
}
}
@@ -289,6 +295,7 @@ pub fn default_type_option_data_from_type(field_type: FieldType) -> TypeOptionDa
FieldType::Relation => RelationTypeOption::default().into(),
FieldType::Summary => SummarizationTypeOption::default().into(),
FieldType::Translate => TranslateTypeOption::default().into(),
FieldType::Tag => TagTypeOption::default().into(),
FieldType::Time => TimeTypeOption.into(),
}
}
@@ -11,6 +11,7 @@ use lib_infra::box_any::BoxAny;
use crate::entities::FieldType;
use crate::services::cell::{CellCache, CellDataChangeset, CellDataDecoder, CellProtobufBlob};
use crate::services::field::summary_type_option::summary::SummarizationTypeOption;
use crate::services::field::tag_type_option::tag::TagTypeOption;
use crate::services::field::translate_type_option::translate::TranslateTypeOption;
use crate::services::field::{
CheckboxTypeOption, ChecklistTypeOption, DateTypeOption, MultiSelectTypeOption, NumberTypeOption,
@@ -470,6 +471,18 @@ impl<'a> TypeOptionCellExt<'a> {
self.cell_data_cache.clone(),
)
}),
FieldType::Tag => {
self
.field
.get_type_option::<TagTypeOption>(field_type)
.map(|type_option| {
TypeOptionCellDataHandlerImpl::new_with_boxed(
type_option,
field_type,
self.cell_data_cache.clone(),
)
})
},
}
}
@@ -579,6 +592,9 @@ fn get_type_option_transform_handler(
FieldType::Translate => {
Box::new(TranslateTypeOption::from(type_option_data)) as Box<dyn TypeOptionTransformHandler>
},
FieldType::Tag => {
Box::new(TagTypeOption::from(type_option_data)) as Box<dyn TypeOptionTransformHandler>
},
}
}
@@ -284,6 +284,7 @@ impl FilterInner {
FieldType::Summary => BoxAny::new(TextFilterPB::parse(condition as u8, content)),
FieldType::Translate => BoxAny::new(TextFilterPB::parse(condition as u8, content)),
FieldType::Time => BoxAny::new(TimeFilterPB::parse(condition as u8, content)),
FieldType::Tag => BoxAny::new(TextFilterPB::parse(condition as u8, content)),
};
FilterInner::Data {
@@ -378,6 +379,10 @@ impl<'a> From<&'a Filter> for FilterMap {
let filter = condition_and_content.cloned::<TextFilterPB>()?;
(filter.condition as u8, filter.content)
},
FieldType::Tag => {
let filter = condition_and_content.cloned::<TextFilterPB>()?;
(filter.condition as u8, filter.content)
},
};
Some((condition, content))
};
@@ -141,6 +141,7 @@ pub fn make_test_board() -> DatabaseData {
fields.push(time_field);
},
FieldType::Translate => {},
FieldType::Tag => {},
}
}
@@ -6,6 +6,7 @@ use crate::database::mock_data::{COMPLETED, FACEBOOK, GOOGLE, PAUSED, PLANNED, T
use event_integration_test::database_event::TestRowBuilder;
use flowy_database2::entities::FieldType;
use flowy_database2::services::field::summary_type_option::summary::SummarizationTypeOption;
use flowy_database2::services::field::tag_type_option::tag::TagTypeOption;
use flowy_database2::services::field::translate_type_option::translate::TranslateTypeOption;
use flowy_database2::services::field::{
ChecklistTypeOption, DateFormat, DateTypeOption, FieldBuilder, MultiSelectTypeOption,
@@ -150,6 +151,13 @@ pub fn make_test_grid() -> DatabaseData {
.build();
fields.push(translate_field);
},
FieldType::Tag => {
let type_option = TagTypeOption { tags: vec![] };
let translate_field = FieldBuilder::new(field_type, type_option)
.name("AI Tag")
.build();
fields.push(translate_field);
},
}
}
@@ -85,6 +85,7 @@ async fn export_and_then_import_meta_csv_test() {
FieldType::Summary => {},
FieldType::Time => {},
FieldType::Translate => {},
FieldType::Tag => {},
}
} else {
panic!(
@@ -170,6 +171,7 @@ async fn history_database_import_test() {
FieldType::Summary => {},
FieldType::Time => {},
FieldType::Translate => {},
FieldType::Tag => {},
}
} else {
panic!(
@@ -1,6 +1,7 @@
use anyhow::Error;
use client_api::entity::ai_dto::{
SummarizeRowData, SummarizeRowParams, TranslateRowData, TranslateRowParams,
SummarizeRowData, SummarizeRowParams, TagRowData, TagRowParams, TagRowResponse, TranslateRowData,
TranslateRowParams,
};
use client_api::entity::QueryCollabResult::{Failed, Success};
use client_api::entity::{QueryCollab, QueryCollabParams};
@@ -13,7 +14,7 @@ use std::sync::Arc;
use tracing::{error, instrument};
use flowy_database_pub::cloud::{
CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent,
CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent, TagRowContent,
TranslateRowContent, TranslateRowResponse,
};
use lib_infra::future::FutureResult;
@@ -164,4 +165,19 @@ where
Ok(data)
})
}
fn tag_database_row(
&self,
workspace_id: &str,
tag_row: TagRowContent,
) -> FutureResult<TagRowResponse, Error> {
let workspace_id = workspace_id.to_string();
let try_get_client = self.inner.try_get_client();
FutureResult::new(async move {
let data = tag_row;
let params = TagRowParams { workspace_id, data };
let data = try_get_client?.tag_row(params).await?;
Ok(data)
})
}
}
@@ -1,11 +1,12 @@
use anyhow::Error;
use client_api::entity::ai_dto::TagRowResponse;
use collab::preclude::Collab;
use collab_entity::define::{DATABASE, DATABASE_ROW_DATA, WORKSPACE_DATABASES};
use collab_entity::CollabType;
use yrs::{Any, MapPrelim};
use flowy_database_pub::cloud::{
CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent,
CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent, TagRowContent,
TranslateRowContent, TranslateRowResponse,
};
use lib_infra::future::FutureResult;
@@ -96,4 +97,12 @@ impl DatabaseCloudService for LocalServerDatabaseCloudServiceImpl {
// TODO(lucas): local ai
FutureResult::new(async move { Ok(TranslateRowResponse::default()) })
}
fn tag_database_row(
&self,
workspace_id: &str,
tag_row: TagRowContent,
) -> FutureResult<TagRowResponse, Error> {
FutureResult::new(async move { Ok(TagRowResponse::default()) })
}
}
@@ -1,9 +1,10 @@
use anyhow::Error;
use client_api::entity::ai_dto::TagRowResponse;
use collab_entity::CollabType;
use tokio::sync::oneshot::channel;
use flowy_database_pub::cloud::{
CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent,
CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent, TagRowContent,
TranslateRowContent, TranslateRowResponse,
};
use lib_dispatch::prelude::af_spawn;
@@ -115,4 +116,12 @@ where
) -> FutureResult<TranslateRowResponse, Error> {
FutureResult::new(async move { Ok(TranslateRowResponse::default()) })
}
fn tag_database_row(
&self,
workspace_id: &str,
tag_row: TagRowContent,
) -> FutureResult<TagRowResponse, Error> {
FutureResult::new(async move { Ok(TagRowResponse::default()) })
}
}