mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-08-17 21:31:31 +00:00
feat: use new api to get the workspace member role (#6783)
* chore: update to latest client api * chore: merge with main * chore: remove unneeded code * fix: sqlite migration * fix: cargo fmt * feat: use new api to get the member role --------- Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
This commit is contained in:
parent
dda3962249
commit
ee96a44fef
@ -15,8 +15,11 @@ part 'local_ai_on_boarding_bloc.freezed.dart';
|
||||
|
||||
class LocalAIOnBoardingBloc
|
||||
extends Bloc<LocalAIOnBoardingEvent, LocalAIOnBoardingState> {
|
||||
LocalAIOnBoardingBloc(this.userProfile, this.member, this.workspaceId)
|
||||
: super(const LocalAIOnBoardingState()) {
|
||||
LocalAIOnBoardingBloc(
|
||||
this.userProfile,
|
||||
this.currentWorkspaceMemberRole,
|
||||
this.workspaceId,
|
||||
) : super(const LocalAIOnBoardingState()) {
|
||||
_userService = UserBackendService(userId: userProfile.id);
|
||||
_successListenable = getIt<SubscriptionSuccessListenable>();
|
||||
_successListenable.addListener(_onPaymentSuccessful);
|
||||
@ -36,7 +39,7 @@ class LocalAIOnBoardingBloc
|
||||
}
|
||||
|
||||
final UserProfilePB userProfile;
|
||||
final WorkspaceMemberPB member;
|
||||
final AFRolePB? currentWorkspaceMemberRole;
|
||||
final String workspaceId;
|
||||
late final IUserBackendService _userService;
|
||||
late final SubscriptionSuccessListenable _successListenable;
|
||||
|
@ -14,13 +14,18 @@ class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> {
|
||||
SettingsAIBloc(
|
||||
this.userProfile,
|
||||
this.workspaceId,
|
||||
WorkspaceMemberPB? member,
|
||||
AFRolePB? currentWorkspaceMemberRole,
|
||||
) : _userListener = UserListener(userProfile: userProfile),
|
||||
_userService = UserBackendService(userId: userProfile.id),
|
||||
super(SettingsAIState(userProfile: userProfile, member: member)) {
|
||||
super(
|
||||
SettingsAIState(
|
||||
userProfile: userProfile,
|
||||
currentWorkspaceMemberRole: currentWorkspaceMemberRole,
|
||||
),
|
||||
) {
|
||||
_dispatch();
|
||||
|
||||
if (member == null) {
|
||||
if (currentWorkspaceMemberRole == null) {
|
||||
_userService.getWorkspaceMember().then((result) {
|
||||
result.fold(
|
||||
(member) {
|
||||
@ -85,7 +90,7 @@ class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> {
|
||||
);
|
||||
},
|
||||
refreshMember: (member) {
|
||||
emit(state.copyWith(member: member));
|
||||
emit(state.copyWith(currentWorkspaceMemberRole: member.role));
|
||||
},
|
||||
);
|
||||
});
|
||||
@ -152,7 +157,7 @@ class SettingsAIState with _$SettingsAIState {
|
||||
const factory SettingsAIState({
|
||||
required UserProfilePB userProfile,
|
||||
UseAISettingPB? aiSettings,
|
||||
WorkspaceMemberPB? member,
|
||||
AFRolePB? currentWorkspaceMemberRole,
|
||||
@Default(true) bool enableSearchIndexing,
|
||||
}) = _SettingsAIState;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ class SettingsDialogBloc
|
||||
extends Bloc<SettingsDialogEvent, SettingsDialogState> {
|
||||
SettingsDialogBloc(
|
||||
this.userProfile,
|
||||
this.workspaceMember, {
|
||||
this.currentWorkspaceMemberRole, {
|
||||
SettingsPage? initPage,
|
||||
}) : _userListener = UserListener(userProfile: userProfile),
|
||||
super(SettingsDialogState.initial(userProfile, initPage)) {
|
||||
@ -41,7 +41,7 @@ class SettingsDialogBloc
|
||||
}
|
||||
|
||||
final UserProfilePB userProfile;
|
||||
final WorkspaceMemberPB? workspaceMember;
|
||||
final AFRolePB? currentWorkspaceMemberRole;
|
||||
final UserListener _userListener;
|
||||
|
||||
@override
|
||||
@ -57,8 +57,10 @@ class SettingsDialogBloc
|
||||
initial: () async {
|
||||
_userListener.start(onProfileUpdated: _profileUpdated);
|
||||
|
||||
final isBillingEnabled =
|
||||
await _isBillingEnabled(userProfile, workspaceMember);
|
||||
final isBillingEnabled = await _isBillingEnabled(
|
||||
userProfile,
|
||||
currentWorkspaceMemberRole,
|
||||
);
|
||||
if (isBillingEnabled) {
|
||||
emit(state.copyWith(isBillingEnabled: true));
|
||||
}
|
||||
@ -86,7 +88,7 @@ class SettingsDialogBloc
|
||||
|
||||
Future<bool> _isBillingEnabled(
|
||||
UserProfilePB userProfile, [
|
||||
WorkspaceMemberPB? member,
|
||||
AFRolePB? currentWorkspaceMemberRole,
|
||||
]) async {
|
||||
if ([
|
||||
AuthenticatorPB.Local,
|
||||
@ -94,7 +96,8 @@ class SettingsDialogBloc
|
||||
return false;
|
||||
}
|
||||
|
||||
if (member == null || member.role != AFRolePB.Owner) {
|
||||
if (currentWorkspaceMemberRole == null ||
|
||||
currentWorkspaceMemberRole != AFRolePB.Owner) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -63,13 +63,6 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
|
||||
actionResult: null,
|
||||
),
|
||||
);
|
||||
|
||||
/// We wait with fetching the workspace member as it may take some time,
|
||||
/// to avoid blocking the UI from rendering (the sidebar).
|
||||
final workspaceMemberResult =
|
||||
await _userService.getWorkspaceMember();
|
||||
final workspaceMember = workspaceMemberResult.toNullable();
|
||||
emit(state.copyWith(currentWorkspaceMember: workspaceMember));
|
||||
},
|
||||
fetchWorkspaces: () async {
|
||||
final result = await _fetchWorkspaces();
|
||||
@ -238,14 +231,6 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
/// We wait with fetching the workspace member as it may take some time,
|
||||
/// to avoid blocking the UI from rendering (the sidebar).
|
||||
final workspaceMemberResult =
|
||||
await _userService.getWorkspaceMember();
|
||||
final workspaceMember = workspaceMemberResult.toNullable();
|
||||
|
||||
emit(state.copyWith(currentWorkspaceMember: workspaceMember));
|
||||
},
|
||||
renameWorkspace: (workspaceId, name) async {
|
||||
final result =
|
||||
@ -515,7 +500,6 @@ class UserWorkspaceState with _$UserWorkspaceState {
|
||||
const factory UserWorkspaceState({
|
||||
@Default(null) UserWorkspacePB? currentWorkspace,
|
||||
@Default([]) List<UserWorkspacePB> workspaces,
|
||||
@Default(null) WorkspaceMemberPB? currentWorkspaceMember,
|
||||
@Default(null) UserWorkspaceActionResult? actionResult,
|
||||
@Default(false) bool isCollabWorkspaceOn,
|
||||
}) = _UserWorkspaceState;
|
||||
@ -533,7 +517,6 @@ class UserWorkspaceState with _$UserWorkspaceState {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is UserWorkspaceState &&
|
||||
other.currentWorkspaceMember == currentWorkspaceMember &&
|
||||
other.currentWorkspace == currentWorkspace &&
|
||||
_deepCollectionEquality.equals(other.workspaces, workspaces) &&
|
||||
identical(other.actionResult, actionResult);
|
||||
|
@ -94,15 +94,15 @@ class SidebarToast extends StatelessWidget {
|
||||
}
|
||||
|
||||
final userWorkspaceBloc = context.read<UserWorkspaceBloc>();
|
||||
final member = userWorkspaceBloc.state.currentWorkspaceMember;
|
||||
if (member == null) {
|
||||
final role = userWorkspaceBloc.state.currentWorkspace?.role;
|
||||
if (role == null) {
|
||||
return Log.error(
|
||||
"Member is null. It should not happen. If you see this error, it's a bug",
|
||||
);
|
||||
}
|
||||
|
||||
// Only if the user is the workspace owner will we navigate to the plan page.
|
||||
if (member.role.isOwner) {
|
||||
if (role.isOwner) {
|
||||
showSettingsDialog(
|
||||
context,
|
||||
userProfile,
|
||||
|
@ -150,7 +150,7 @@ class SpaceMoreActionTypeWrapper extends CustomActionCell {
|
||||
final isOwner = context
|
||||
.read<UserWorkspaceBloc?>()
|
||||
?.state
|
||||
.currentWorkspaceMember
|
||||
.currentWorkspace
|
||||
?.role
|
||||
.isOwner ??
|
||||
false;
|
||||
|
@ -1,21 +1,20 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/shared/af_role_pb_extension.dart';
|
||||
import 'package:appflowy/shared/feature_flags.dart';
|
||||
import 'package:appflowy/workspace/application/settings/ai/local_ai_on_boarding_bloc.dart';
|
||||
import 'package:appflowy/workspace/application/settings/ai/settings_ai_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/pages/setting_ai_view/local_ai_setting.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/pages/setting_ai_view/model_selection.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/setting_appflowy_cloud.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/workspace/application/settings/ai/settings_ai_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_body.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/setting_appflowy_cloud.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class AIFeatureOnlySupportedWhenUsingAppFlowyCloud extends StatelessWidget {
|
||||
@ -39,19 +38,20 @@ class SettingsAIView extends StatelessWidget {
|
||||
const SettingsAIView({
|
||||
super.key,
|
||||
required this.userProfile,
|
||||
required this.member,
|
||||
required this.currentWorkspaceMemberRole,
|
||||
required this.workspaceId,
|
||||
});
|
||||
|
||||
final UserProfilePB userProfile;
|
||||
final WorkspaceMemberPB? member;
|
||||
final AFRolePB? currentWorkspaceMemberRole;
|
||||
final String workspaceId;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider<SettingsAIBloc>(
|
||||
create: (_) => SettingsAIBloc(userProfile, workspaceId, member)
|
||||
..add(const SettingsAIEvent.started()),
|
||||
create: (_) =>
|
||||
SettingsAIBloc(userProfile, workspaceId, currentWorkspaceMemberRole)
|
||||
..add(const SettingsAIEvent.started()),
|
||||
child: BlocBuilder<SettingsAIBloc, SettingsAIState>(
|
||||
builder: (context, state) {
|
||||
final children = <Widget>[
|
||||
@ -60,11 +60,11 @@ class SettingsAIView extends StatelessWidget {
|
||||
|
||||
children.add(const _AISearchToggle(value: false));
|
||||
|
||||
if (state.member != null) {
|
||||
if (state.currentWorkspaceMemberRole != null) {
|
||||
children.add(
|
||||
_LocalAIOnBoarding(
|
||||
userProfile: userProfile,
|
||||
member: state.member!,
|
||||
currentWorkspaceMemberRole: state.currentWorkspaceMemberRole!,
|
||||
workspaceId: workspaceId,
|
||||
),
|
||||
);
|
||||
@ -129,11 +129,11 @@ class _AISearchToggle extends StatelessWidget {
|
||||
class _LocalAIOnBoarding extends StatelessWidget {
|
||||
const _LocalAIOnBoarding({
|
||||
required this.userProfile,
|
||||
required this.member,
|
||||
required this.currentWorkspaceMemberRole,
|
||||
required this.workspaceId,
|
||||
});
|
||||
final UserProfilePB userProfile;
|
||||
final WorkspaceMemberPB member;
|
||||
final AFRolePB? currentWorkspaceMemberRole;
|
||||
final String workspaceId;
|
||||
|
||||
@override
|
||||
@ -142,16 +142,18 @@ class _LocalAIOnBoarding extends StatelessWidget {
|
||||
return BillingGateGuard(
|
||||
builder: (context) {
|
||||
return BlocProvider(
|
||||
create: (context) =>
|
||||
LocalAIOnBoardingBloc(userProfile, member, workspaceId)
|
||||
..add(const LocalAIOnBoardingEvent.started()),
|
||||
create: (context) => LocalAIOnBoardingBloc(
|
||||
userProfile,
|
||||
currentWorkspaceMemberRole,
|
||||
workspaceId,
|
||||
)..add(const LocalAIOnBoardingEvent.started()),
|
||||
child: BlocBuilder<LocalAIOnBoardingBloc, LocalAIOnBoardingState>(
|
||||
builder: (context, state) {
|
||||
// Show the local AI settings if the user has purchased the AI Local plan
|
||||
if (kDebugMode || state.isPurchaseAILocal) {
|
||||
return const LocalAISetting();
|
||||
} else {
|
||||
if (member.role.isOwner) {
|
||||
if (currentWorkspaceMemberRole?.isOwner ?? false) {
|
||||
// Show the upgrade to AI Local plan button if the user has not purchased the AI Local plan
|
||||
return _UpgradeToAILocalPlan(
|
||||
onTap: () {
|
||||
|
@ -1,7 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||
@ -45,6 +43,7 @@ import 'package:flowy_infra/theme.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
@ -52,11 +51,11 @@ class SettingsWorkspaceView extends StatelessWidget {
|
||||
const SettingsWorkspaceView({
|
||||
super.key,
|
||||
required this.userProfile,
|
||||
this.workspaceMember,
|
||||
this.currentWorkspaceMemberRole,
|
||||
});
|
||||
|
||||
final UserProfilePB userProfile;
|
||||
final WorkspaceMemberPB? workspaceMember;
|
||||
final AFRolePB? currentWorkspaceMemberRole;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -93,7 +92,11 @@ class SettingsWorkspaceView extends StatelessWidget {
|
||||
SettingsCategory(
|
||||
title: LocaleKeys.settings_workspacePage_workspaceName_title
|
||||
.tr(),
|
||||
children: [_WorkspaceNameSetting(member: workspaceMember)],
|
||||
children: [
|
||||
_WorkspaceNameSetting(
|
||||
currentWorkspaceMemberRole: currentWorkspaceMemberRole,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SettingsCategorySpacer(),
|
||||
SettingsCategory(
|
||||
@ -104,7 +107,7 @@ class SettingsWorkspaceView extends StatelessWidget {
|
||||
.tr(),
|
||||
children: [
|
||||
_WorkspaceIconSetting(
|
||||
enableEdit: workspaceMember?.role.isOwner ?? false,
|
||||
enableEdit: currentWorkspaceMemberRole?.isOwner ?? false,
|
||||
workspace: state.workspace,
|
||||
),
|
||||
],
|
||||
@ -185,14 +188,14 @@ class SettingsWorkspaceView extends StatelessWidget {
|
||||
fontWeight: FontWeight.w600,
|
||||
onPressed: () => showConfirmDialog(
|
||||
context: context,
|
||||
title: workspaceMember?.role.isOwner ?? false
|
||||
title: currentWorkspaceMemberRole?.isOwner ?? false
|
||||
? LocaleKeys
|
||||
.settings_workspacePage_deleteWorkspacePrompt_title
|
||||
.tr()
|
||||
: LocaleKeys
|
||||
.settings_workspacePage_leaveWorkspacePrompt_title
|
||||
.tr(),
|
||||
description: workspaceMember?.role.isOwner ?? false
|
||||
description: currentWorkspaceMemberRole?.isOwner ?? false
|
||||
? LocaleKeys
|
||||
.settings_workspacePage_deleteWorkspacePrompt_content
|
||||
.tr()
|
||||
@ -201,13 +204,13 @@ class SettingsWorkspaceView extends StatelessWidget {
|
||||
.tr(),
|
||||
style: ConfirmPopupStyle.cancelAndOk,
|
||||
onConfirm: () => context.read<WorkspaceSettingsBloc>().add(
|
||||
workspaceMember?.role.isOwner ?? false
|
||||
currentWorkspaceMemberRole?.isOwner ?? false
|
||||
? const WorkspaceSettingsEvent.deleteWorkspace()
|
||||
: const WorkspaceSettingsEvent.leaveWorkspace(),
|
||||
),
|
||||
),
|
||||
buttonType: SingleSettingsButtonType.danger,
|
||||
buttonLabel: workspaceMember?.role.isOwner ?? false
|
||||
buttonLabel: currentWorkspaceMemberRole?.isOwner ?? false
|
||||
? LocaleKeys
|
||||
.settings_workspacePage_manageWorkspace_deleteWorkspace
|
||||
.tr()
|
||||
@ -225,9 +228,11 @@ class SettingsWorkspaceView extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _WorkspaceNameSetting extends StatefulWidget {
|
||||
const _WorkspaceNameSetting({this.member});
|
||||
const _WorkspaceNameSetting({
|
||||
this.currentWorkspaceMemberRole,
|
||||
});
|
||||
|
||||
final WorkspaceMemberPB? member;
|
||||
final AFRolePB? currentWorkspaceMemberRole;
|
||||
|
||||
@override
|
||||
State<_WorkspaceNameSetting> createState() => _WorkspaceNameSettingState();
|
||||
@ -255,7 +260,8 @@ class _WorkspaceNameSettingState extends State<_WorkspaceNameSetting> {
|
||||
}
|
||||
},
|
||||
builder: (_, state) {
|
||||
if (widget.member == null || !widget.member!.role.isOwner) {
|
||||
if (widget.currentWorkspaceMemberRole == null ||
|
||||
!widget.currentWorkspaceMemberRole!.isOwner) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.5),
|
||||
child: FlowyText.regular(
|
||||
|
@ -109,7 +109,7 @@ class _HomePageButton extends StatelessWidget {
|
||||
final isOwner = context
|
||||
.watch<UserWorkspaceBloc>()
|
||||
.state
|
||||
.currentWorkspaceMember
|
||||
.currentWorkspace
|
||||
?.role
|
||||
.isOwner ??
|
||||
false;
|
||||
@ -227,7 +227,7 @@ class _FreePlanUpgradeButton extends StatelessWidget {
|
||||
final isOwner = context
|
||||
.watch<UserWorkspaceBloc>()
|
||||
.state
|
||||
.currentWorkspaceMember
|
||||
.currentWorkspace
|
||||
?.role
|
||||
.isOwner ??
|
||||
false;
|
||||
|
@ -82,7 +82,7 @@ class _DomainMoreActionState extends State<DomainMoreAction> {
|
||||
final isOwner = context
|
||||
.watch<UserWorkspaceBloc>()
|
||||
.state
|
||||
.currentWorkspaceMember
|
||||
.currentWorkspace
|
||||
?.role
|
||||
.isOwner ??
|
||||
false;
|
||||
|
@ -57,7 +57,7 @@ class SettingsDialog extends StatelessWidget {
|
||||
return BlocProvider<SettingsDialogBloc>(
|
||||
create: (context) => SettingsDialogBloc(
|
||||
user,
|
||||
context.read<UserWorkspaceBloc>().state.currentWorkspaceMember,
|
||||
context.read<UserWorkspaceBloc>().state.currentWorkspace?.role,
|
||||
initPage: initPage,
|
||||
)..add(const SettingsDialogEvent.initial()),
|
||||
child: BlocBuilder<SettingsDialogBloc, SettingsDialogState>(
|
||||
@ -80,10 +80,6 @@ class SettingsDialog extends StatelessWidget {
|
||||
currentPage:
|
||||
context.read<SettingsDialogBloc>().state.page,
|
||||
isBillingEnabled: state.isBillingEnabled,
|
||||
member: context
|
||||
.read<UserWorkspaceBloc>()
|
||||
.state
|
||||
.currentWorkspaceMember,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
@ -98,7 +94,8 @@ class SettingsDialog extends StatelessWidget {
|
||||
context
|
||||
.read<UserWorkspaceBloc>()
|
||||
.state
|
||||
.currentWorkspaceMember,
|
||||
.currentWorkspace
|
||||
?.role,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -114,7 +111,7 @@ class SettingsDialog extends StatelessWidget {
|
||||
String workspaceId,
|
||||
SettingsPage page,
|
||||
UserProfilePB user,
|
||||
WorkspaceMemberPB? member,
|
||||
AFRolePB? currentWorkspaceMemberRole,
|
||||
) {
|
||||
switch (page) {
|
||||
case SettingsPage.account:
|
||||
@ -126,7 +123,7 @@ class SettingsDialog extends StatelessWidget {
|
||||
case SettingsPage.workspace:
|
||||
return SettingsWorkspaceView(
|
||||
userProfile: user,
|
||||
workspaceMember: member,
|
||||
currentWorkspaceMemberRole: currentWorkspaceMemberRole,
|
||||
);
|
||||
case SettingsPage.manageData:
|
||||
return SettingsManageDataView(userProfile: user);
|
||||
@ -140,7 +137,7 @@ class SettingsDialog extends StatelessWidget {
|
||||
if (user.authenticator == AuthenticatorPB.AppFlowyCloud) {
|
||||
return SettingsAIView(
|
||||
userProfile: user,
|
||||
member: member,
|
||||
currentWorkspaceMemberRole: currentWorkspaceMemberRole,
|
||||
workspaceId: workspaceId,
|
||||
);
|
||||
} else {
|
||||
|
@ -16,14 +16,12 @@ class SettingsMenu extends StatelessWidget {
|
||||
required this.currentPage,
|
||||
required this.userProfile,
|
||||
required this.isBillingEnabled,
|
||||
this.member,
|
||||
});
|
||||
|
||||
final Function changeSelectedPage;
|
||||
final SettingsPage currentPage;
|
||||
final UserProfilePB userProfile;
|
||||
final bool isBillingEnabled;
|
||||
final WorkspaceMemberPB? member;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -11,4 +11,4 @@ flowy-error = { workspace = true }
|
||||
client-api = { workspace = true }
|
||||
bytes.workspace = true
|
||||
futures.workspace = true
|
||||
serde_json.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
@ -667,6 +667,7 @@ fn to_user_workspace(af_workspace: AFWorkspace) -> UserWorkspace {
|
||||
workspace_database_id: af_workspace.database_storage_id.to_string(),
|
||||
icon: af_workspace.icon,
|
||||
member_count: af_workspace.member_count.unwrap_or(0),
|
||||
role: af_workspace.role.map(|r| r.into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ impl UserCloudService for LocalServerUserAuthServiceImpl {
|
||||
let params = params.unbox_or_error::<SignUpParams>()?;
|
||||
let uid = ID_GEN.lock().await.next_id();
|
||||
let workspace_id = uuid::Uuid::new_v4().to_string();
|
||||
let user_workspace = UserWorkspace::new(&workspace_id, uid);
|
||||
let user_workspace = UserWorkspace::new_local(&workspace_id, uid);
|
||||
let user_name = if params.name.is_empty() {
|
||||
DEFAULT_USER_NAME()
|
||||
} else {
|
||||
@ -214,6 +214,7 @@ fn make_user_workspace() -> UserWorkspace {
|
||||
created_at: Default::default(),
|
||||
workspace_database_id: uuid::Uuid::new_v4().to_string(),
|
||||
icon: "".to_string(),
|
||||
member_count: 0,
|
||||
member_count: 1,
|
||||
role: None,
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
ALTER TABLE user_workspace_table DROP COLUMN role;
|
@ -0,0 +1 @@
|
||||
ALTER TABLE user_workspace_table ADD COLUMN role INT;
|
@ -102,6 +102,7 @@ diesel::table! {
|
||||
database_storage_id -> Text,
|
||||
icon -> Text,
|
||||
member_count -> BigInt,
|
||||
role -> Nullable<Integer>,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ use std::str::FromStr;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
pub use client_api::entity::billing_dto::RecurringInterval;
|
||||
use client_api::entity::AFRole;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use serde_repr::*;
|
||||
@ -145,10 +146,12 @@ pub struct UserWorkspace {
|
||||
pub icon: String,
|
||||
#[serde(default)]
|
||||
pub member_count: i64,
|
||||
#[serde(default)]
|
||||
pub role: Option<Role>,
|
||||
}
|
||||
|
||||
impl UserWorkspace {
|
||||
pub fn new(workspace_id: &str, _uid: i64) -> Self {
|
||||
pub fn new_local(workspace_id: &str, _uid: i64) -> Self {
|
||||
Self {
|
||||
id: workspace_id.to_string(),
|
||||
name: "".to_string(),
|
||||
@ -156,6 +159,7 @@ impl UserWorkspace {
|
||||
workspace_database_id: Uuid::new_v4().to_string(),
|
||||
icon: "".to_string(),
|
||||
member_count: 1,
|
||||
role: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -420,6 +424,16 @@ impl From<Role> for i32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AFRole> for Role {
|
||||
fn from(value: AFRole) -> Self {
|
||||
match value {
|
||||
AFRole::Owner => Role::Owner,
|
||||
AFRole::Member => Role::Member,
|
||||
AFRole::Guest => Role::Guest,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WorkspaceMember {
|
||||
pub email: String,
|
||||
pub role: Role,
|
||||
|
@ -75,7 +75,8 @@ impl<'de> Visitor<'de> for SessionVisitor {
|
||||
// For historical reasons, the database_storage_id is constructed by the user_id.
|
||||
workspace_database_id: STANDARD.encode(format!("{}:user:database", user_id)),
|
||||
icon: "".to_owned(),
|
||||
member_count: 0,
|
||||
member_count: 1,
|
||||
role: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ use crate::entities::{AIModelPB, AuthenticatorPB};
|
||||
use crate::errors::ErrorCode;
|
||||
|
||||
use super::parser::UserStabilityAIKey;
|
||||
use super::AFRolePB;
|
||||
|
||||
#[derive(Default, ProtoBuf)]
|
||||
pub struct UserTokenPB {
|
||||
@ -237,6 +238,9 @@ pub struct UserWorkspacePB {
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub member_count: i64,
|
||||
|
||||
#[pb(index = 6, one_of)]
|
||||
pub role: Option<AFRolePB>,
|
||||
}
|
||||
|
||||
impl From<UserWorkspace> for UserWorkspacePB {
|
||||
@ -247,6 +251,7 @@ impl From<UserWorkspace> for UserWorkspacePB {
|
||||
created_at_timestamp: value.created_at.timestamp(),
|
||||
icon: value.icon,
|
||||
member_count: value.member_count,
|
||||
role: value.role.map(AFRolePB::from),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ pub struct UpdateWorkspaceMemberPB {
|
||||
}
|
||||
|
||||
// Workspace Role
|
||||
#[derive(ProtoBuf_Enum, Clone, Default)]
|
||||
#[derive(Debug, ProtoBuf_Enum, Clone, Default)]
|
||||
pub enum AFRolePB {
|
||||
Owner = 0,
|
||||
Member = 1,
|
||||
|
@ -17,6 +17,7 @@ pub struct UserWorkspaceTable {
|
||||
pub database_storage_id: String,
|
||||
pub icon: String,
|
||||
pub member_count: i64,
|
||||
pub role: Option<i32>,
|
||||
}
|
||||
|
||||
pub fn get_user_workspace_op(workspace_id: &str, mut conn: DBConnection) -> Option<UserWorkspace> {
|
||||
@ -94,6 +95,7 @@ impl TryFrom<(i64, &UserWorkspace)> for UserWorkspaceTable {
|
||||
database_storage_id: value.1.workspace_database_id.clone(),
|
||||
icon: value.1.icon.clone(),
|
||||
member_count: value.1.member_count,
|
||||
role: value.1.role.clone().map(|v| v as i32),
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -110,6 +112,7 @@ impl From<UserWorkspaceTable> for UserWorkspace {
|
||||
workspace_database_id: value.database_storage_id,
|
||||
icon: value.icon,
|
||||
member_count: value.member_count,
|
||||
role: value.role.map(|v| v.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -730,6 +730,7 @@ pub fn save_all_user_workspaces(
|
||||
user_workspace_table::database_storage_id.eq(&user_workspace.database_storage_id),
|
||||
user_workspace_table::icon.eq(&user_workspace.icon),
|
||||
user_workspace_table::member_count.eq(&user_workspace.member_count),
|
||||
user_workspace_table::role.eq(&user_workspace.role),
|
||||
))
|
||||
.execute(conn)?;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user