fetch user workspaces

This commit is contained in:
appflowy 2021-07-26 13:51:41 +08:00
parent 9a1f17d41c
commit 0191645d49
30 changed files with 968 additions and 83 deletions

View File

@ -40,9 +40,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
}
Stream<MenuState> _performActionOnCreateApp(CreateApp event) async* {
await iWorkspaceImpl
.createApp(name: event.name, desc: event.desc)
.then((result) async* {
iWorkspaceImpl.createApp(name: event.name, desc: event.desc).then((result) {
result.fold(
(app) => {},
(error) async* {

View File

@ -1 +1,60 @@
import 'package:app_flowy/workspace/domain/i_user.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/workspace_create.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:dartz/dartz.dart';
part 'menu_user_bloc.freezed.dart';
class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
final IUser iUserImpl;
MenuUserBloc(this.iUserImpl) : super(MenuUserState.initial(iUserImpl.user));
@override
Stream<MenuUserState> mapEventToState(MenuUserEvent event) async* {
yield* event.map(
initial: (_) async* {
// fetch workspaces
iUserImpl.fetchWorkspaces().then((result) {
result.fold(
(workspaces) async* {
yield state.copyWith(workspaces: some(workspaces));
},
(error) async* {
yield state.copyWith(successOrFailure: right(error.msg));
},
);
});
},
fetchWorkspaces: (_FetchWorkspaces value) async* {},
);
}
@override
Future<void> close() async {
super.close();
}
}
@freezed
class MenuUserEvent with _$MenuUserEvent {
const factory MenuUserEvent.initial() = _Initial;
const factory MenuUserEvent.fetchWorkspaces() = _FetchWorkspaces;
}
@freezed
class MenuUserState with _$MenuUserState {
const factory MenuUserState({
required UserDetail user,
required Option<List<Workspace>> workspaces,
required Either<Unit, String> successOrFailure,
}) = _MenuUserState;
factory MenuUserState.initial(UserDetail user) => MenuUserState(
user: user,
workspaces: none(),
successOrFailure: left(unit),
);
}

View File

@ -0,0 +1,432 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides
part of 'menu_user_bloc.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
/// @nodoc
class _$MenuUserEventTearOff {
const _$MenuUserEventTearOff();
_Initial initial() {
return const _Initial();
}
_FetchWorkspaces fetchWorkspaces() {
return const _FetchWorkspaces();
}
}
/// @nodoc
const $MenuUserEvent = _$MenuUserEventTearOff();
/// @nodoc
mixin _$MenuUserEvent {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() fetchWorkspaces,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? fetchWorkspaces,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_FetchWorkspaces value) fetchWorkspaces,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_FetchWorkspaces value)? fetchWorkspaces,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $MenuUserEventCopyWith<$Res> {
factory $MenuUserEventCopyWith(
MenuUserEvent value, $Res Function(MenuUserEvent) then) =
_$MenuUserEventCopyWithImpl<$Res>;
}
/// @nodoc
class _$MenuUserEventCopyWithImpl<$Res>
implements $MenuUserEventCopyWith<$Res> {
_$MenuUserEventCopyWithImpl(this._value, this._then);
final MenuUserEvent _value;
// ignore: unused_field
final $Res Function(MenuUserEvent) _then;
}
/// @nodoc
abstract class _$InitialCopyWith<$Res> {
factory _$InitialCopyWith(_Initial value, $Res Function(_Initial) then) =
__$InitialCopyWithImpl<$Res>;
}
/// @nodoc
class __$InitialCopyWithImpl<$Res> extends _$MenuUserEventCopyWithImpl<$Res>
implements _$InitialCopyWith<$Res> {
__$InitialCopyWithImpl(_Initial _value, $Res Function(_Initial) _then)
: super(_value, (v) => _then(v as _Initial));
@override
_Initial get _value => super._value as _Initial;
}
/// @nodoc
class _$_Initial implements _Initial {
const _$_Initial();
@override
String toString() {
return 'MenuUserEvent.initial()';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) || (other is _Initial);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() fetchWorkspaces,
}) {
return initial();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? fetchWorkspaces,
required TResult orElse(),
}) {
if (initial != null) {
return initial();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_FetchWorkspaces value) fetchWorkspaces,
}) {
return initial(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_FetchWorkspaces value)? fetchWorkspaces,
required TResult orElse(),
}) {
if (initial != null) {
return initial(this);
}
return orElse();
}
}
abstract class _Initial implements MenuUserEvent {
const factory _Initial() = _$_Initial;
}
/// @nodoc
abstract class _$FetchWorkspacesCopyWith<$Res> {
factory _$FetchWorkspacesCopyWith(
_FetchWorkspaces value, $Res Function(_FetchWorkspaces) then) =
__$FetchWorkspacesCopyWithImpl<$Res>;
}
/// @nodoc
class __$FetchWorkspacesCopyWithImpl<$Res>
extends _$MenuUserEventCopyWithImpl<$Res>
implements _$FetchWorkspacesCopyWith<$Res> {
__$FetchWorkspacesCopyWithImpl(
_FetchWorkspaces _value, $Res Function(_FetchWorkspaces) _then)
: super(_value, (v) => _then(v as _FetchWorkspaces));
@override
_FetchWorkspaces get _value => super._value as _FetchWorkspaces;
}
/// @nodoc
class _$_FetchWorkspaces implements _FetchWorkspaces {
const _$_FetchWorkspaces();
@override
String toString() {
return 'MenuUserEvent.fetchWorkspaces()';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) || (other is _FetchWorkspaces);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() fetchWorkspaces,
}) {
return fetchWorkspaces();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? fetchWorkspaces,
required TResult orElse(),
}) {
if (fetchWorkspaces != null) {
return fetchWorkspaces();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_FetchWorkspaces value) fetchWorkspaces,
}) {
return fetchWorkspaces(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_FetchWorkspaces value)? fetchWorkspaces,
required TResult orElse(),
}) {
if (fetchWorkspaces != null) {
return fetchWorkspaces(this);
}
return orElse();
}
}
abstract class _FetchWorkspaces implements MenuUserEvent {
const factory _FetchWorkspaces() = _$_FetchWorkspaces;
}
/// @nodoc
class _$MenuUserStateTearOff {
const _$MenuUserStateTearOff();
_MenuUserState call(
{required UserDetail user,
required Option<List<Workspace>> workspaces,
required Either<Unit, String> successOrFailure}) {
return _MenuUserState(
user: user,
workspaces: workspaces,
successOrFailure: successOrFailure,
);
}
}
/// @nodoc
const $MenuUserState = _$MenuUserStateTearOff();
/// @nodoc
mixin _$MenuUserState {
UserDetail get user => throw _privateConstructorUsedError;
Option<List<Workspace>> get workspaces => throw _privateConstructorUsedError;
Either<Unit, String> get successOrFailure =>
throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$MenuUserStateCopyWith<MenuUserState> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $MenuUserStateCopyWith<$Res> {
factory $MenuUserStateCopyWith(
MenuUserState value, $Res Function(MenuUserState) then) =
_$MenuUserStateCopyWithImpl<$Res>;
$Res call(
{UserDetail user,
Option<List<Workspace>> workspaces,
Either<Unit, String> successOrFailure});
}
/// @nodoc
class _$MenuUserStateCopyWithImpl<$Res>
implements $MenuUserStateCopyWith<$Res> {
_$MenuUserStateCopyWithImpl(this._value, this._then);
final MenuUserState _value;
// ignore: unused_field
final $Res Function(MenuUserState) _then;
@override
$Res call({
Object? user = freezed,
Object? workspaces = freezed,
Object? successOrFailure = freezed,
}) {
return _then(_value.copyWith(
user: user == freezed
? _value.user
: user // ignore: cast_nullable_to_non_nullable
as UserDetail,
workspaces: workspaces == freezed
? _value.workspaces
: workspaces // ignore: cast_nullable_to_non_nullable
as Option<List<Workspace>>,
successOrFailure: successOrFailure == freezed
? _value.successOrFailure
: successOrFailure // ignore: cast_nullable_to_non_nullable
as Either<Unit, String>,
));
}
}
/// @nodoc
abstract class _$MenuUserStateCopyWith<$Res>
implements $MenuUserStateCopyWith<$Res> {
factory _$MenuUserStateCopyWith(
_MenuUserState value, $Res Function(_MenuUserState) then) =
__$MenuUserStateCopyWithImpl<$Res>;
@override
$Res call(
{UserDetail user,
Option<List<Workspace>> workspaces,
Either<Unit, String> successOrFailure});
}
/// @nodoc
class __$MenuUserStateCopyWithImpl<$Res>
extends _$MenuUserStateCopyWithImpl<$Res>
implements _$MenuUserStateCopyWith<$Res> {
__$MenuUserStateCopyWithImpl(
_MenuUserState _value, $Res Function(_MenuUserState) _then)
: super(_value, (v) => _then(v as _MenuUserState));
@override
_MenuUserState get _value => super._value as _MenuUserState;
@override
$Res call({
Object? user = freezed,
Object? workspaces = freezed,
Object? successOrFailure = freezed,
}) {
return _then(_MenuUserState(
user: user == freezed
? _value.user
: user // ignore: cast_nullable_to_non_nullable
as UserDetail,
workspaces: workspaces == freezed
? _value.workspaces
: workspaces // ignore: cast_nullable_to_non_nullable
as Option<List<Workspace>>,
successOrFailure: successOrFailure == freezed
? _value.successOrFailure
: successOrFailure // ignore: cast_nullable_to_non_nullable
as Either<Unit, String>,
));
}
}
/// @nodoc
class _$_MenuUserState implements _MenuUserState {
const _$_MenuUserState(
{required this.user,
required this.workspaces,
required this.successOrFailure});
@override
final UserDetail user;
@override
final Option<List<Workspace>> workspaces;
@override
final Either<Unit, String> successOrFailure;
@override
String toString() {
return 'MenuUserState(user: $user, workspaces: $workspaces, successOrFailure: $successOrFailure)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other is _MenuUserState &&
(identical(other.user, user) ||
const DeepCollectionEquality().equals(other.user, user)) &&
(identical(other.workspaces, workspaces) ||
const DeepCollectionEquality()
.equals(other.workspaces, workspaces)) &&
(identical(other.successOrFailure, successOrFailure) ||
const DeepCollectionEquality()
.equals(other.successOrFailure, successOrFailure)));
}
@override
int get hashCode =>
runtimeType.hashCode ^
const DeepCollectionEquality().hash(user) ^
const DeepCollectionEquality().hash(workspaces) ^
const DeepCollectionEquality().hash(successOrFailure);
@JsonKey(ignore: true)
@override
_$MenuUserStateCopyWith<_MenuUserState> get copyWith =>
__$MenuUserStateCopyWithImpl<_MenuUserState>(this, _$identity);
}
abstract class _MenuUserState implements MenuUserState {
const factory _MenuUserState(
{required UserDetail user,
required Option<List<Workspace>> workspaces,
required Either<Unit, String> successOrFailure}) = _$_MenuUserState;
@override
UserDetail get user => throw _privateConstructorUsedError;
@override
Option<List<Workspace>> get workspaces => throw _privateConstructorUsedError;
@override
Either<Unit, String> get successOrFailure =>
throw _privateConstructorUsedError;
@override
@JsonKey(ignore: true)
_$MenuUserStateCopyWith<_MenuUserState> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@ -2,13 +2,17 @@ import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/workspace_create.pb.dart';
export 'package:flowy_sdk/protobuf/flowy-workspace/workspace_create.pb.dart';
export 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
export 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
export 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
abstract class IUser {
Future<Either<Unit, WorkspaceError>> deleteWorkspace(String workspaceId);
UserDetail get user;
Future<Either<UserDetail, UserError>> fetchUserDetail(String userId);
Future<Either<List<Workspace>, WorkspaceError>> fetchWorkspaces();
Future<Either<Unit, WorkspaceError>> deleteWorkspace(String workspaceId);
Future<Either<Unit, UserError>> signOut();
}

View File

@ -2,6 +2,7 @@ import 'package:app_flowy/workspace/application/app/app_bloc.dart';
import 'package:app_flowy/workspace/application/app/app_watch_bloc.dart';
import 'package:app_flowy/workspace/application/doc/doc_bloc.dart';
import 'package:app_flowy/workspace/application/menu/menu_bloc.dart';
import 'package:app_flowy/workspace/application/menu/menu_user_bloc.dart';
import 'package:app_flowy/workspace/application/menu/menu_watch.dart';
import 'package:app_flowy/workspace/application/view/doc_watch_bloc.dart';
import 'package:app_flowy/workspace/application/view/view_bloc.dart';
@ -53,12 +54,16 @@ class HomeDepsResolver {
getIt.registerFactoryParam<IUser, UserDetail, void>(
(user, _) => IUserImpl(repo: UserRepo(user: user)));
//Bloc
//Menu Bloc
getIt.registerFactoryParam<MenuBloc, UserDetail, void>(
(user, _) => MenuBloc(getIt<IWorkspace>(param1: user)));
getIt.registerFactoryParam<MenuWatchBloc, UserDetail, void>(
(user, _) => MenuWatchBloc(getIt<IWorkspaceWatch>(param1: user)));
getIt.registerFactoryParam<MenuUserBloc, UserDetail, void>(
(user, _) => MenuUserBloc(getIt<IUser>(param1: user)));
//
getIt.registerFactoryParam<AppBloc, String, void>(
(appId, _) => AppBloc(getIt<IApp>(param1: appId)));
getIt.registerFactoryParam<AppWatchBloc, String, void>(

View File

@ -13,8 +13,7 @@ class IUserImpl extends IUser {
@override
Future<Either<Unit, WorkspaceError>> deleteWorkspace(String workspaceId) {
// TODO: implement deleteWorkspace
throw UnimplementedError();
return repo.deleteWorkspace(workspaceId: workspaceId);
}
@override
@ -24,7 +23,14 @@ class IUserImpl extends IUser {
@override
Future<Either<Unit, UserError>> signOut() {
// TODO: implement signOut
throw UnimplementedError();
return repo.signOut();
}
@override
UserDetail get user => repo.user;
@override
Future<Either<List<Workspace>, WorkspaceError>> fetchWorkspaces() {
return repo.fetchWorkspaces();
}
}

View File

@ -2,6 +2,8 @@ import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/workspace_create.pb.dart';
class UserRepo {
final UserDetail user;
@ -13,4 +15,22 @@ class UserRepo {
{required String userId}) {
return UserEventGetStatus().send();
}
Future<Either<Unit, WorkspaceError>> deleteWorkspace(
{required String workspaceId}) {
throw UnimplementedError();
}
Future<Either<Unit, UserError>> signOut() {
return UserEventSignOut().send();
}
Future<Either<List<Workspace>, WorkspaceError>> fetchWorkspaces() {
return WorkspaceEventReadAllWorkspace().send().then((result) {
return result.fold(
(workspaces) => left(workspaces.items),
(r) => right(r),
);
});
}
}

View File

@ -31,7 +31,7 @@ class MenuList extends StatelessWidget {
separatorBuilder: (context, index) => const VSpace(10),
physics: const BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return menuItems[index].build(context);
return menuItems[index];
},
),
),

View File

@ -1,7 +1,10 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/application/menu/menu_user_bloc.dart';
import 'package:app_flowy/workspace/presentation/widgets/menu/menu_list.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class MenuUser extends MenuItem {
final UserDetail user;
@ -9,18 +12,54 @@ class MenuUser extends MenuItem {
@override
Widget build(BuildContext context) {
return Row(children: [
SizedBox(
width: 30,
height: 30,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: const Image(image: AssetImage('assets/images/avatar.jpg')),
),
return BlocProvider<MenuUserBloc>(
create: (context) =>
getIt<MenuUserBloc>(param1: user)..add(const MenuUserEvent.initial()),
child: BlocBuilder<MenuUserBloc, MenuUserState>(
builder: (context, state) => Row(children: [
_renderAvatar(context),
const HSpace(10),
_renderUserName(context),
const HSpace(10),
_renderDropButton(context),
]),
),
const HSpace(10),
const Text("nathan", style: TextStyle(fontSize: 18)),
]);
);
}
Widget _renderAvatar(BuildContext context) {
return SizedBox(
width: 30,
height: 30,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: const Image(image: AssetImage('assets/images/avatar.jpg')),
),
);
}
Widget _renderUserName(BuildContext context) {
String name = context.read<MenuUserBloc>().state.user.name;
if (name.isEmpty) {
name = context.read<MenuUserBloc>().state.user.email;
}
return Flexible(
child: Text(
name,
overflow: TextOverflow.fade,
softWrap: false,
style: const TextStyle(fontSize: 18),
),
);
}
Widget _renderDropButton(BuildContext context) {
return IconButton(
icon: const Icon(Icons.arrow_drop_down),
alignment: Alignment.center,
padding: EdgeInsets.zero,
onPressed: () {},
);
}
@override

View File

@ -118,6 +118,20 @@ class WorkspaceEventGetWorkspace {
}
}
class WorkspaceEventReadAllWorkspace {
WorkspaceEventReadAllWorkspace();
Future<Either<Workspaces, WorkspaceError>> send() {
final request = FFIRequest.create()
..event = WorkspaceEvent.ReadAllWorkspace.toString();
return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold(
(okBytes) => left(Workspaces.fromBuffer(okBytes)),
(errBytes) => right(WorkspaceError.fromBuffer(errBytes)),
));
}
}
class WorkspaceEventCreateApp {
CreateAppRequest request;
WorkspaceEventCreateApp(this.request);

View File

@ -13,6 +13,7 @@ class WorkspaceEvent extends $pb.ProtobufEnum {
static const WorkspaceEvent CreateWorkspace = WorkspaceEvent._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateWorkspace');
static const WorkspaceEvent GetCurWorkspace = WorkspaceEvent._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetCurWorkspace');
static const WorkspaceEvent GetWorkspace = WorkspaceEvent._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetWorkspace');
static const WorkspaceEvent ReadAllWorkspace = WorkspaceEvent._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadAllWorkspace');
static const WorkspaceEvent CreateApp = WorkspaceEvent._(101, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateApp');
static const WorkspaceEvent GetApp = WorkspaceEvent._(102, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetApp');
static const WorkspaceEvent CreateView = WorkspaceEvent._(201, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateView');
@ -23,6 +24,7 @@ class WorkspaceEvent extends $pb.ProtobufEnum {
CreateWorkspace,
GetCurWorkspace,
GetWorkspace,
ReadAllWorkspace,
CreateApp,
GetApp,
CreateView,

View File

@ -15,6 +15,7 @@ const WorkspaceEvent$json = const {
const {'1': 'CreateWorkspace', '2': 0},
const {'1': 'GetCurWorkspace', '2': 1},
const {'1': 'GetWorkspace', '2': 2},
const {'1': 'ReadAllWorkspace', '2': 3},
const {'1': 'CreateApp', '2': 101},
const {'1': 'GetApp', '2': 102},
const {'1': 'CreateView', '2': 201},
@ -24,4 +25,4 @@ const WorkspaceEvent$json = const {
};
/// Descriptor for `WorkspaceEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List workspaceEventDescriptor = $convert.base64Decode('Cg5Xb3Jrc3BhY2VFdmVudBITCg9DcmVhdGVXb3Jrc3BhY2UQABITCg9HZXRDdXJXb3Jrc3BhY2UQARIQCgxHZXRXb3Jrc3BhY2UQAhINCglDcmVhdGVBcHAQZRIKCgZHZXRBcHAQZhIPCgpDcmVhdGVWaWV3EMkBEg0KCFJlYWRWaWV3EMoBEg8KClVwZGF0ZVZpZXcQywE=');
final $typed_data.Uint8List workspaceEventDescriptor = $convert.base64Decode('Cg5Xb3Jrc3BhY2VFdmVudBITCg9DcmVhdGVXb3Jrc3BhY2UQABITCg9HZXRDdXJXb3Jrc3BhY2UQARIQCgxHZXRXb3Jrc3BhY2UQAhIUChBSZWFkQWxsV29ya3NwYWNlEAMSDQoJQ3JlYXRlQXBwEGUSCgoGR2V0QXBwEGYSDwoKQ3JlYXRlVmlldxDJARINCghSZWFkVmlldxDKARIPCgpVcGRhdGVWaWV3EMsB');

View File

@ -163,3 +163,44 @@ class Workspace extends $pb.GeneratedMessage {
$0.RepeatedApp ensureApps() => $_ensure(3);
}
class Workspaces extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Workspaces', createEmptyInstance: create)
..pc<Workspace>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: Workspace.create)
..hasRequiredFields = false
;
Workspaces._() : super();
factory Workspaces({
$core.Iterable<Workspace>? items,
}) {
final _result = create();
if (items != null) {
_result.items.addAll(items);
}
return _result;
}
factory Workspaces.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory Workspaces.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
Workspaces clone() => Workspaces()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
Workspaces copyWith(void Function(Workspaces) updates) => super.copyWith((message) => updates(message as Workspaces)) as Workspaces; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static Workspaces create() => Workspaces._();
Workspaces createEmptyInstance() => create();
static $pb.PbList<Workspaces> createRepeated() => $pb.PbList<Workspaces>();
@$core.pragma('dart2js:noInline')
static Workspaces getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Workspaces>(create);
static Workspaces? _defaultInstance;
@$pb.TagNumber(1)
$core.List<Workspace> get items => $_getList(0);
}

View File

@ -32,3 +32,13 @@ const Workspace$json = const {
/// Descriptor for `Workspace`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List workspaceDescriptor = $convert.base64Decode('CglXb3Jrc3BhY2USDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYxIgCgRhcHBzGAQgASgLMgwuUmVwZWF0ZWRBcHBSBGFwcHM=');
@$core.Deprecated('Use workspacesDescriptor instead')
const Workspaces$json = const {
'1': 'Workspaces',
'2': const [
const {'1': 'items', '3': 1, '4': 3, '5': 11, '6': '.Workspace', '10': 'items'},
],
};
/// Descriptor for `Workspaces`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List workspacesDescriptor = $convert.base64Decode('CgpXb3Jrc3BhY2VzEiAKBWl0ZW1zGAEgAygLMgouV29ya3NwYWNlUgVpdGVtcw==');

View File

@ -14,7 +14,7 @@ packages:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.1"
version: "1.7.2"
animations:
dependency: transitive
description:
@ -35,7 +35,7 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.6.1"
version: "2.7.0"
bloc:
dependency: transitive
description:
@ -119,7 +119,7 @@ packages:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.3.1"
checked_yaml:
dependency: transitive
description:
@ -456,7 +456,7 @@ packages:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
version: "1.7.0"
mime:
dependency: transitive
description:
@ -701,7 +701,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.0"
version: "0.4.1"
textstyle_extensions:
dependency: transitive
description:

View File

@ -33,6 +33,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
| "UpdateWorkspaceRequest"
| "CreateWorkspaceRequest"
| "Workspace"
| "Workspaces"
| "QueryWorkspaceRequest"
| "CurrentWorkspace"
| "UpdateViewRequest"

View File

@ -13,6 +13,14 @@ pub struct WorkspaceUserImpl {
}
impl WorkspaceUser for WorkspaceUserImpl {
fn user_id(&self) -> Result<String, WorkspaceError> {
self.user_session.get_user_id().map_err(|e| {
ErrorBuilder::new(WsErrCode::UserInternalError)
.error(e)
.build()
})
}
fn set_cur_workspace_id(
&self,
workspace_id: &str,

View File

@ -84,7 +84,7 @@ pub struct App {
pub views: RepeatedView,
}
#[derive(Debug, Default, ProtoBuf)]
#[derive(PartialEq, Debug, Default, ProtoBuf)]
pub struct RepeatedApp {
#[pb(index = 1)]
pub items: Vec<App>,

View File

@ -1,6 +1,7 @@
use crate::{
entities::{app::RepeatedApp, workspace::parser::*},
errors::*,
impl_def_and_def_mut,
};
use flowy_derive::ProtoBuf;
use std::convert::TryInto;
@ -36,7 +37,7 @@ impl TryInto<CreateWorkspaceParams> for CreateWorkspaceRequest {
}
}
#[derive(ProtoBuf, Default, Debug)]
#[derive(PartialEq, ProtoBuf, Default, Debug)]
pub struct Workspace {
#[pb(index = 1)]
pub id: String,
@ -50,3 +51,11 @@ pub struct Workspace {
#[pb(index = 4)]
pub apps: RepeatedApp,
}
#[derive(PartialEq, Debug, Default, ProtoBuf)]
pub struct Workspaces {
#[pb(index = 1)]
pub items: Vec<Workspace>,
}
impl_def_and_def_mut!(Workspaces, Workspace);

View File

@ -6,33 +6,37 @@ use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
pub enum WorkspaceEvent {
#[display(fmt = "CreateWorkspace")]
#[event(input = "CreateWorkspaceRequest", output = "Workspace")]
CreateWorkspace = 0,
CreateWorkspace = 0,
#[display(fmt = "GetCurWorkspace")]
#[event(output = "Workspace")]
GetCurWorkspace = 1,
GetCurWorkspace = 1,
#[display(fmt = "GetWorkspace")]
#[event(input = "QueryWorkspaceRequest", output = "Workspace")]
GetWorkspace = 2,
GetWorkspace = 2,
#[display(fmt = "ReadAllWorkspace")]
#[event(output = "Workspaces")]
ReadAllWorkspace = 3,
#[display(fmt = "CreateApp")]
#[event(input = "CreateAppRequest", output = "App")]
CreateApp = 101,
CreateApp = 101,
#[display(fmt = "GetApp")]
#[event(input = "QueryAppRequest", output = "App")]
GetApp = 102,
GetApp = 102,
#[display(fmt = "CreateView")]
#[event(input = "CreateViewRequest", output = "View")]
CreateView = 201,
CreateView = 201,
#[display(fmt = "ReadView")]
#[event(input = "QueryViewRequest", output = "View")]
ReadView = 202,
ReadView = 202,
#[display(fmt = "UpdateView")]
#[event(input = "UpdateViewRequest")]
UpdateView = 203,
UpdateView = 203,
}

View File

@ -40,3 +40,12 @@ pub async fn get_workspace(
response_ok(workspace)
}
#[tracing::instrument(name = "get_all_workspaces", skip(controller))]
pub async fn read_all_workspaces(
controller: Unit<Arc<WorkspaceController>>,
) -> ResponseResult<Workspaces, WorkspaceError> {
let workspaces = controller.read_workspaces_belong_to_user().await?;
response_ok(Workspaces { items: workspaces })
}

View File

@ -13,6 +13,7 @@ use std::sync::Arc;
pub trait WorkspaceDeps: WorkspaceUser + WorkspaceDatabase {}
pub trait WorkspaceUser: Send + Sync {
fn user_id(&self) -> Result<String, WorkspaceError>;
fn set_cur_workspace_id(&self, id: &str) -> DispatchFuture<Result<(), WorkspaceError>>;
fn get_cur_workspace(&self) -> DispatchFuture<Result<CurrentWorkspace, WorkspaceError>>;
}
@ -41,6 +42,7 @@ pub fn create(user: Arc<dyn WorkspaceUser>, database: Arc<dyn WorkspaceDatabase>
.data(workspace_controller)
.data(app_controller)
.data(view_controller)
.event(WorkspaceEvent::ReadAllWorkspace, read_all_workspaces)
.event(WorkspaceEvent::CreateWorkspace, create_workspace)
.event(WorkspaceEvent::GetCurWorkspace, get_cur_workspace)
.event(WorkspaceEvent::GetWorkspace, get_workspace)

View File

@ -28,6 +28,7 @@ pub enum WorkspaceEvent {
CreateWorkspace = 0,
GetCurWorkspace = 1,
GetWorkspace = 2,
ReadAllWorkspace = 3,
CreateApp = 101,
GetApp = 102,
CreateView = 201,
@ -45,6 +46,7 @@ impl ::protobuf::ProtobufEnum for WorkspaceEvent {
0 => ::std::option::Option::Some(WorkspaceEvent::CreateWorkspace),
1 => ::std::option::Option::Some(WorkspaceEvent::GetCurWorkspace),
2 => ::std::option::Option::Some(WorkspaceEvent::GetWorkspace),
3 => ::std::option::Option::Some(WorkspaceEvent::ReadAllWorkspace),
101 => ::std::option::Option::Some(WorkspaceEvent::CreateApp),
102 => ::std::option::Option::Some(WorkspaceEvent::GetApp),
201 => ::std::option::Option::Some(WorkspaceEvent::CreateView),
@ -59,6 +61,7 @@ impl ::protobuf::ProtobufEnum for WorkspaceEvent {
WorkspaceEvent::CreateWorkspace,
WorkspaceEvent::GetCurWorkspace,
WorkspaceEvent::GetWorkspace,
WorkspaceEvent::ReadAllWorkspace,
WorkspaceEvent::CreateApp,
WorkspaceEvent::GetApp,
WorkspaceEvent::CreateView,
@ -92,29 +95,32 @@ impl ::protobuf::reflect::ProtobufValue for WorkspaceEvent {
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x0bevent.proto*\x98\x01\n\x0eWorkspaceEvent\x12\x13\n\x0fCreateWorksp\
\n\x0bevent.proto*\xae\x01\n\x0eWorkspaceEvent\x12\x13\n\x0fCreateWorksp\
ace\x10\0\x12\x13\n\x0fGetCurWorkspace\x10\x01\x12\x10\n\x0cGetWorkspace\
\x10\x02\x12\r\n\tCreateApp\x10e\x12\n\n\x06GetApp\x10f\x12\x0f\n\nCreat\
eView\x10\xc9\x01\x12\r\n\x08ReadView\x10\xca\x01\x12\x0f\n\nUpdateView\
\x10\xcb\x01J\xf2\x02\n\x06\x12\x04\0\0\x0b\x01\n\x08\n\x01\x0c\x12\x03\
\0\0\x12\n\n\n\x02\x05\0\x12\x04\x02\0\x0b\x01\n\n\n\x03\x05\0\x01\x12\
\x03\x02\x05\x13\n\x0b\n\x04\x05\0\x02\0\x12\x03\x03\x04\x18\n\x0c\n\x05\
\x05\0\x02\0\x01\x12\x03\x03\x04\x13\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\
\x03\x16\x17\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x04\x04\x18\n\x0c\n\x05\
\x05\0\x02\x01\x01\x12\x03\x04\x04\x13\n\x0c\n\x05\x05\0\x02\x01\x02\x12\
\x03\x04\x16\x17\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x05\x04\x15\n\x0c\n\
\x05\x05\0\x02\x02\x01\x12\x03\x05\x04\x10\n\x0c\n\x05\x05\0\x02\x02\x02\
\x12\x03\x05\x13\x14\n\x0b\n\x04\x05\0\x02\x03\x12\x03\x06\x04\x14\n\x0c\
\n\x05\x05\0\x02\x03\x01\x12\x03\x06\x04\r\n\x0c\n\x05\x05\0\x02\x03\x02\
\x12\x03\x06\x10\x13\n\x0b\n\x04\x05\0\x02\x04\x12\x03\x07\x04\x11\n\x0c\
\n\x05\x05\0\x02\x04\x01\x12\x03\x07\x04\n\n\x0c\n\x05\x05\0\x02\x04\x02\
\x12\x03\x07\r\x10\n\x0b\n\x04\x05\0\x02\x05\x12\x03\x08\x04\x15\n\x0c\n\
\x05\x05\0\x02\x05\x01\x12\x03\x08\x04\x0e\n\x0c\n\x05\x05\0\x02\x05\x02\
\x12\x03\x08\x11\x14\n\x0b\n\x04\x05\0\x02\x06\x12\x03\t\x04\x13\n\x0c\n\
\x05\x05\0\x02\x06\x01\x12\x03\t\x04\x0c\n\x0c\n\x05\x05\0\x02\x06\x02\
\x12\x03\t\x0f\x12\n\x0b\n\x04\x05\0\x02\x07\x12\x03\n\x04\x15\n\x0c\n\
\x05\x05\0\x02\x07\x01\x12\x03\n\x04\x0e\n\x0c\n\x05\x05\0\x02\x07\x02\
\x12\x03\n\x11\x14b\x06proto3\
\x10\x02\x12\x14\n\x10ReadAllWorkspace\x10\x03\x12\r\n\tCreateApp\x10e\
\x12\n\n\x06GetApp\x10f\x12\x0f\n\nCreateView\x10\xc9\x01\x12\r\n\x08Rea\
dView\x10\xca\x01\x12\x0f\n\nUpdateView\x10\xcb\x01J\x9b\x03\n\x06\x12\
\x04\0\0\x0c\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x05\0\x12\x04\
\x02\0\x0c\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\x05\x13\n\x0b\n\x04\x05\0\
\x02\0\x12\x03\x03\x04\x18\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x03\x04\
\x13\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\x16\x17\n\x0b\n\x04\x05\0\
\x02\x01\x12\x03\x04\x04\x18\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x04\
\x04\x13\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x04\x16\x17\n\x0b\n\x04\
\x05\0\x02\x02\x12\x03\x05\x04\x15\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\
\x05\x04\x10\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\x05\x13\x14\n\x0b\n\
\x04\x05\0\x02\x03\x12\x03\x06\x04\x19\n\x0c\n\x05\x05\0\x02\x03\x01\x12\
\x03\x06\x04\x14\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\x06\x17\x18\n\x0b\
\n\x04\x05\0\x02\x04\x12\x03\x07\x04\x14\n\x0c\n\x05\x05\0\x02\x04\x01\
\x12\x03\x07\x04\r\n\x0c\n\x05\x05\0\x02\x04\x02\x12\x03\x07\x10\x13\n\
\x0b\n\x04\x05\0\x02\x05\x12\x03\x08\x04\x11\n\x0c\n\x05\x05\0\x02\x05\
\x01\x12\x03\x08\x04\n\n\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x08\r\x10\n\
\x0b\n\x04\x05\0\x02\x06\x12\x03\t\x04\x15\n\x0c\n\x05\x05\0\x02\x06\x01\
\x12\x03\t\x04\x0e\n\x0c\n\x05\x05\0\x02\x06\x02\x12\x03\t\x11\x14\n\x0b\
\n\x04\x05\0\x02\x07\x12\x03\n\x04\x13\n\x0c\n\x05\x05\0\x02\x07\x01\x12\
\x03\n\x04\x0c\n\x0c\n\x05\x05\0\x02\x07\x02\x12\x03\n\x0f\x12\n\x0b\n\
\x04\x05\0\x02\x08\x12\x03\x0b\x04\x15\n\x0c\n\x05\x05\0\x02\x08\x01\x12\
\x03\x0b\x04\x0e\n\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0b\x11\x14b\x06p\
roto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -524,33 +524,205 @@ impl ::protobuf::reflect::ProtobufValue for Workspace {
}
}
#[derive(PartialEq,Clone,Default)]
pub struct Workspaces {
// message fields
pub items: ::protobuf::RepeatedField<Workspace>,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a Workspaces {
fn default() -> &'a Workspaces {
<Workspaces as ::protobuf::Message>::default_instance()
}
}
impl Workspaces {
pub fn new() -> Workspaces {
::std::default::Default::default()
}
// repeated .Workspace items = 1;
pub fn get_items(&self) -> &[Workspace] {
&self.items
}
pub fn clear_items(&mut self) {
self.items.clear();
}
// Param is passed by value, moved
pub fn set_items(&mut self, v: ::protobuf::RepeatedField<Workspace>) {
self.items = v;
}
// Mutable pointer to the field.
pub fn mut_items(&mut self) -> &mut ::protobuf::RepeatedField<Workspace> {
&mut self.items
}
// Take field
pub fn take_items(&mut self) -> ::protobuf::RepeatedField<Workspace> {
::std::mem::replace(&mut self.items, ::protobuf::RepeatedField::new())
}
}
impl ::protobuf::Message for Workspaces {
fn is_initialized(&self) -> bool {
for v in &self.items {
if !v.is_initialized() {
return false;
}
};
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.items)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
for value in &self.items {
let len = value.compute_size();
my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
};
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
for v in &self.items {
os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?;
os.write_raw_varint32(v.get_cached_size())?;
v.write_to_with_cached_sizes(os)?;
};
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> Workspaces {
Workspaces::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<Workspace>>(
"items",
|m: &Workspaces| { &m.items },
|m: &mut Workspaces| { &mut m.items },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<Workspaces>(
"Workspaces",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static Workspaces {
static instance: ::protobuf::rt::LazyV2<Workspaces> = ::protobuf::rt::LazyV2::INIT;
instance.get(Workspaces::new)
}
}
impl ::protobuf::Clear for Workspaces {
fn clear(&mut self) {
self.items.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for Workspaces {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for Workspaces {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x16workspace_create.proto\x1a\x10app_create.proto\"@\n\x16CreateWorks\
paceRequest\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\x12\x12\n\x04d\
esc\x18\x02\x20\x01(\tR\x04desc\"e\n\tWorkspace\x12\x0e\n\x02id\x18\x01\
\x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\
\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12\x20\n\x04apps\x18\x04\x20\x01\
(\x0b2\x0c.RepeatedAppR\x04appsJ\x97\x03\n\x06\x12\x04\0\0\x0c\x01\n\x08\
\n\x01\x0c\x12\x03\0\0\x12\n\t\n\x02\x03\0\x12\x03\x01\0\x1a\n\n\n\x02\
\x04\0\x12\x04\x03\0\x06\x01\n\n\n\x03\x04\0\x01\x12\x03\x03\x08\x1e\n\
\x0b\n\x04\x04\0\x02\0\x12\x03\x04\x04\x14\n\x0c\n\x05\x04\0\x02\0\x05\
\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x04\x0b\x0f\n\x0c\
\n\x05\x04\0\x02\0\x03\x12\x03\x04\x12\x13\n\x0b\n\x04\x04\0\x02\x01\x12\
\x03\x05\x04\x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x05\x04\n\n\x0c\n\
\x05\x04\0\x02\x01\x01\x12\x03\x05\x0b\x0f\n\x0c\n\x05\x04\0\x02\x01\x03\
\x12\x03\x05\x12\x13\n\n\n\x02\x04\x01\x12\x04\x07\0\x0c\x01\n\n\n\x03\
\x04\x01\x01\x12\x03\x07\x08\x11\n\x0b\n\x04\x04\x01\x02\0\x12\x03\x08\
\x04\x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x08\x04\n\n\x0c\n\x05\x04\
\x01\x02\0\x01\x12\x03\x08\x0b\r\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\
\x08\x10\x11\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\t\x04\x14\n\x0c\n\x05\
\x04\x01\x02\x01\x05\x12\x03\t\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\
\x03\t\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\t\x12\x13\n\x0b\n\
\x04\x04\x01\x02\x02\x12\x03\n\x04\x14\n\x0c\n\x05\x04\x01\x02\x02\x05\
\x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\n\x0b\x0f\n\x0c\
\n\x05\x04\x01\x02\x02\x03\x12\x03\n\x12\x13\n\x0b\n\x04\x04\x01\x02\x03\
\x12\x03\x0b\x04\x19\n\x0c\n\x05\x04\x01\x02\x03\x06\x12\x03\x0b\x04\x0f\
\n\x0c\n\x05\x04\x01\x02\x03\x01\x12\x03\x0b\x10\x14\n\x0c\n\x05\x04\x01\
\x02\x03\x03\x12\x03\x0b\x17\x18b\x06proto3\
(\x0b2\x0c.RepeatedAppR\x04apps\".\n\nWorkspaces\x12\x20\n\x05items\x18\
\x01\x20\x03(\x0b2\n.WorkspaceR\x05itemsJ\xf4\x03\n\x06\x12\x04\0\0\x0f\
\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\t\n\x02\x03\0\x12\x03\x01\0\x1a\n\
\n\n\x02\x04\0\x12\x04\x03\0\x06\x01\n\n\n\x03\x04\0\x01\x12\x03\x03\x08\
\x1e\n\x0b\n\x04\x04\0\x02\0\x12\x03\x04\x04\x14\n\x0c\n\x05\x04\0\x02\0\
\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x04\x0b\x0f\n\
\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x04\x12\x13\n\x0b\n\x04\x04\0\x02\x01\
\x12\x03\x05\x04\x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x05\x04\n\n\
\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x05\x0b\x0f\n\x0c\n\x05\x04\0\x02\
\x01\x03\x12\x03\x05\x12\x13\n\n\n\x02\x04\x01\x12\x04\x07\0\x0c\x01\n\n\
\n\x03\x04\x01\x01\x12\x03\x07\x08\x11\n\x0b\n\x04\x04\x01\x02\0\x12\x03\
\x08\x04\x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x08\x04\n\n\x0c\n\x05\
\x04\x01\x02\0\x01\x12\x03\x08\x0b\r\n\x0c\n\x05\x04\x01\x02\0\x03\x12\
\x03\x08\x10\x11\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\t\x04\x14\n\x0c\n\
\x05\x04\x01\x02\x01\x05\x12\x03\t\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\
\x12\x03\t\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\t\x12\x13\n\
\x0b\n\x04\x04\x01\x02\x02\x12\x03\n\x04\x14\n\x0c\n\x05\x04\x01\x02\x02\
\x05\x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\n\x0b\x0f\n\
\x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\n\x12\x13\n\x0b\n\x04\x04\x01\x02\
\x03\x12\x03\x0b\x04\x19\n\x0c\n\x05\x04\x01\x02\x03\x06\x12\x03\x0b\x04\
\x0f\n\x0c\n\x05\x04\x01\x02\x03\x01\x12\x03\x0b\x10\x14\n\x0c\n\x05\x04\
\x01\x02\x03\x03\x12\x03\x0b\x17\x18\n\n\n\x02\x04\x02\x12\x04\r\0\x0f\
\x01\n\n\n\x03\x04\x02\x01\x12\x03\r\x08\x12\n\x0b\n\x04\x04\x02\x02\0\
\x12\x03\x0e\x04!\n\x0c\n\x05\x04\x02\x02\0\x04\x12\x03\x0e\x04\x0c\n\
\x0c\n\x05\x04\x02\x02\0\x06\x12\x03\x0e\r\x16\n\x0c\n\x05\x04\x02\x02\0\
\x01\x12\x03\x0e\x17\x1c\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x0e\x1f\
\x20b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -4,6 +4,7 @@ enum WorkspaceEvent {
CreateWorkspace = 0;
GetCurWorkspace = 1;
GetWorkspace = 2;
ReadAllWorkspace = 3;
CreateApp = 101;
GetApp = 102;
CreateView = 201;

View File

@ -11,3 +11,6 @@ message Workspace {
string desc = 3;
RepeatedApp apps = 4;
}
message Workspaces {
repeated Workspace items = 1;
}

View File

@ -33,7 +33,8 @@ impl WorkspaceController {
&self,
params: CreateWorkspaceParams,
) -> Result<Workspace, WorkspaceError> {
let workspace_table = WorkspaceTable::new(params);
let user_id = self.user.user_id()?;
let workspace_table = WorkspaceTable::new(params, &user_id);
let detail: Workspace = workspace_table.clone().into();
let _ = self.sql.create_workspace(workspace_table)?;
Ok(detail)
@ -69,6 +70,18 @@ impl WorkspaceController {
Ok(workspace_table.into())
}
pub async fn read_workspaces_belong_to_user(&self) -> Result<Vec<Workspace>, WorkspaceError> {
let user_id = self.user.user_id()?;
let workspace = self
.sql
.read_workspaces_belong_to_user(&user_id)?
.into_iter()
.map(|workspace_table| workspace_table.into())
.collect::<Vec<Workspace>>();
Ok(workspace)
}
pub async fn read_apps(&self, workspace_id: &str) -> Result<Vec<App>, WorkspaceError> {
let apps = self
.sql

View File

@ -61,4 +61,19 @@ impl WorkspaceSql {
Ok(apps)
}
pub(crate) fn read_workspaces_belong_to_user(
&self,
user_id: &str,
) -> Result<Vec<WorkspaceTable>, WorkspaceError> {
let conn = self.database.db_connection()?;
let workspaces = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let workspaces = dsl::workspace_table
.filter(workspace_table::user_id.eq(user_id))
.load::<WorkspaceTable>(&*(conn))?;
Ok(workspaces)
})?;
Ok(workspaces)
}
}

View File

@ -19,10 +19,11 @@ pub struct WorkspaceTable {
impl WorkspaceTable {
#[allow(dead_code)]
pub fn new(params: CreateWorkspaceParams) -> Self {
pub fn new(params: CreateWorkspaceParams, user_id: &str) -> Self {
let mut workspace = WorkspaceTable::default();
workspace.name = params.name;
workspace.desc = params.desc;
workspace.user_id = user_id.to_string();
workspace
}
}

View File

@ -1,6 +1,6 @@
use crate::helper::*;
use flowy_workspace::{
entities::workspace::{CreateWorkspaceRequest, QueryWorkspaceRequest, Workspace},
entities::workspace::{CreateWorkspaceRequest, QueryWorkspaceRequest, Workspace, Workspaces},
event::WorkspaceEvent::*,
prelude::*,
};
@ -18,6 +18,16 @@ fn workspace_get_success() {
dbg!(&workspace);
}
#[test]
fn workspace_read_all_success() {
let workspaces = SingleUserTestBuilder::new()
.event(ReadAllWorkspace)
.sync_send()
.parse::<Workspaces>();
dbg!(&workspaces);
}
#[test]
fn workspace_create_and_then_get_workspace_success() {
let workspace = create_workspace(