mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: add open ai key to database (#1852)
* feat: add open ai key to database * chore: refactor code
This commit is contained in:
parent
7207e35349
commit
72e155f5b9
@ -191,6 +191,12 @@
|
||||
"create": "Create",
|
||||
"folderPath": "Path to store your folder",
|
||||
"locationCannotBeEmpty": "Path cannot be empty"
|
||||
},
|
||||
"user": {
|
||||
"name": "Name",
|
||||
"icon": "Icon",
|
||||
"selectAnIcon": "Select an icon",
|
||||
"pleaseInputYourOpenAIKey": "please input your OpenAI key"
|
||||
}
|
||||
},
|
||||
"grid": {
|
||||
|
@ -21,6 +21,7 @@ class UserService {
|
||||
String? password,
|
||||
String? email,
|
||||
String? iconUrl,
|
||||
String? openAIKey,
|
||||
}) {
|
||||
var payload = UpdateUserProfilePayloadPB.create()..id = userId;
|
||||
|
||||
@ -40,6 +41,10 @@ class UserService {
|
||||
payload.iconUrl = iconUrl;
|
||||
}
|
||||
|
||||
if (openAIKey != null) {
|
||||
payload.openaiKey = openAIKey;
|
||||
}
|
||||
|
||||
return UserEventUpdateUserProfile(payload).send();
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,14 @@ class SettingsUserViewBloc extends Bloc<SettingsUserEvent, SettingsUserState> {
|
||||
);
|
||||
});
|
||||
},
|
||||
updateUserOpenaiKey: (openAIKey) {
|
||||
_userService.updateUserProfile(openAIKey: openAIKey).then((result) {
|
||||
result.fold(
|
||||
(l) => null,
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -73,6 +81,8 @@ class SettingsUserEvent with _$SettingsUserEvent {
|
||||
const factory SettingsUserEvent.updateUserName(String name) = _UpdateUserName;
|
||||
const factory SettingsUserEvent.updateUserIcon(String iconUrl) =
|
||||
_UpdateUserIcon;
|
||||
const factory SettingsUserEvent.updateUserOpenaiKey(String openAIKey) =
|
||||
_UpdateUserOpenaiKey;
|
||||
const factory SettingsUserEvent.didReceiveUserProfile(
|
||||
UserProfilePB newUserProfile) = _DidReceiveUserProfile;
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
|
||||
import 'package:flowy_infra/image.dart';
|
||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
@ -28,7 +30,9 @@ class SettingsUserView extends StatelessWidget {
|
||||
children: [
|
||||
_renderUserNameInput(context),
|
||||
const VSpace(20),
|
||||
_renderCurrentIcon(context)
|
||||
_renderCurrentIcon(context),
|
||||
const VSpace(20),
|
||||
_renderCurrentOpenaiKey(context)
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -49,6 +53,12 @@ class SettingsUserView extends StatelessWidget {
|
||||
}
|
||||
return _CurrentIcon(iconUrl);
|
||||
}
|
||||
|
||||
Widget _renderCurrentOpenaiKey(BuildContext context) {
|
||||
String openAIKey =
|
||||
context.read<SettingsUserViewBloc>().state.userProfile.openaiKey;
|
||||
return _OpenaiKeyInput(openAIKey);
|
||||
}
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
@ -62,15 +72,41 @@ class UserNameInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextField(
|
||||
controller: TextEditingController()..text = name,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Name',
|
||||
),
|
||||
onSubmitted: (val) {
|
||||
context
|
||||
.read<SettingsUserViewBloc>()
|
||||
.add(SettingsUserEvent.updateUserName(val));
|
||||
});
|
||||
controller: TextEditingController()..text = name,
|
||||
decoration: InputDecoration(
|
||||
labelText: LocaleKeys.settings_user_name.tr(),
|
||||
),
|
||||
onSubmitted: (val) {
|
||||
context
|
||||
.read<SettingsUserViewBloc>()
|
||||
.add(SettingsUserEvent.updateUserName(val));
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _OpenaiKeyInput extends StatelessWidget {
|
||||
final String openAIKey;
|
||||
const _OpenaiKeyInput(
|
||||
this.openAIKey, {
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextField(
|
||||
controller: TextEditingController()..text = openAIKey,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Openai Key',
|
||||
hintText: LocaleKeys.settings_user_pleaseInputYourOpenAIKey.tr(),
|
||||
),
|
||||
onSubmitted: (val) {
|
||||
// TODO: validate key
|
||||
context
|
||||
.read<SettingsUserViewBloc>()
|
||||
.add(SettingsUserEvent.updateUserOpenaiKey(val));
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,7 +132,7 @@ class _CurrentIcon extends StatelessWidget {
|
||||
builder: (BuildContext context) {
|
||||
return SimpleDialog(
|
||||
title: FlowyText.medium(
|
||||
'Select an Icon',
|
||||
LocaleKeys.settings_user_selectAnIcon.tr(),
|
||||
fontSize: FontSizes.s16,
|
||||
),
|
||||
children: <Widget>[
|
||||
@ -112,11 +148,11 @@ class _CurrentIcon extends StatelessWidget {
|
||||
},
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
const Align(
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Text(
|
||||
"Icon",
|
||||
style: TextStyle(color: Colors.grey),
|
||||
LocaleKeys.settings_user_icon.tr(),
|
||||
style: const TextStyle(color: Colors.grey),
|
||||
)),
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
|
@ -0,0 +1 @@
|
||||
ALTER TABLE user_table DROP COLUMN openai_key;
|
@ -0,0 +1 @@
|
||||
ALTER TABLE user_table ADD COLUMN openai_key TEXT NOT NULL DEFAULT '';
|
@ -146,6 +146,7 @@ diesel::table! {
|
||||
email -> Text,
|
||||
workspace -> Text,
|
||||
icon_url -> Text,
|
||||
openai_key -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,8 @@ use crate::errors::ErrorCode;
|
||||
use flowy_derive::ProtoBuf;
|
||||
use std::convert::TryInto;
|
||||
use user_model::{
|
||||
UpdateUserProfileParams, UserEmail, UserIcon, UserId, UserName, UserPassword, UserProfile,
|
||||
UpdateUserProfileParams, UserEmail, UserIcon, UserId, UserName, UserOpenaiKey, UserPassword,
|
||||
UserProfile,
|
||||
};
|
||||
|
||||
#[derive(Default, ProtoBuf)]
|
||||
@ -33,6 +34,9 @@ pub struct UserProfilePB {
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub icon_url: String,
|
||||
|
||||
#[pb(index = 6)]
|
||||
pub openai_key: String,
|
||||
}
|
||||
|
||||
impl std::convert::From<UserProfile> for UserProfilePB {
|
||||
@ -43,6 +47,7 @@ impl std::convert::From<UserProfile> for UserProfilePB {
|
||||
name: user_profile.name,
|
||||
token: user_profile.token,
|
||||
icon_url: user_profile.icon_url,
|
||||
openai_key: user_profile.openai_key,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -63,6 +68,9 @@ pub struct UpdateUserProfilePayloadPB {
|
||||
|
||||
#[pb(index = 5, one_of)]
|
||||
pub icon_url: Option<String>,
|
||||
|
||||
#[pb(index = 6, one_of)]
|
||||
pub openai_key: Option<String>,
|
||||
}
|
||||
|
||||
impl UpdateUserProfilePayloadPB {
|
||||
@ -92,6 +100,11 @@ impl UpdateUserProfilePayloadPB {
|
||||
self.icon_url = Some(icon_url.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn openai_key(mut self, openai_key: &str) -> Self {
|
||||
self.openai_key = Some(openai_key.to_owned());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl TryInto<UpdateUserProfileParams> for UpdateUserProfilePayloadPB {
|
||||
@ -120,12 +133,18 @@ impl TryInto<UpdateUserProfileParams> for UpdateUserProfilePayloadPB {
|
||||
Some(icon_url) => Some(UserIcon::parse(icon_url)?.0),
|
||||
};
|
||||
|
||||
let openai_key = match self.openai_key {
|
||||
None => None,
|
||||
Some(openai_key) => Some(UserOpenaiKey::parse(openai_key)?.0),
|
||||
};
|
||||
|
||||
Ok(UpdateUserProfileParams {
|
||||
id,
|
||||
name,
|
||||
email,
|
||||
password,
|
||||
icon_url,
|
||||
openai_key,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ pub struct UserTable {
|
||||
pub(crate) email: String,
|
||||
pub(crate) workspace: String, // deprecated
|
||||
pub(crate) icon_url: String,
|
||||
pub(crate) openai_key: String,
|
||||
}
|
||||
|
||||
impl UserTable {
|
||||
@ -95,6 +96,7 @@ impl UserTable {
|
||||
token,
|
||||
icon_url: "".to_owned(),
|
||||
workspace: "".to_owned(),
|
||||
openai_key: "".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,6 +126,7 @@ impl std::convert::From<UserTable> for UserProfile {
|
||||
name: table.name,
|
||||
token: table.token,
|
||||
icon_url: table.icon_url,
|
||||
openai_key: table.openai_key,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -136,6 +139,7 @@ pub struct UserTableChangeset {
|
||||
pub name: Option<String>,
|
||||
pub email: Option<String>,
|
||||
pub icon_url: Option<String>,
|
||||
pub openai_key: Option<String>,
|
||||
}
|
||||
|
||||
impl UserTableChangeset {
|
||||
@ -146,6 +150,7 @@ impl UserTableChangeset {
|
||||
name: params.name,
|
||||
email: params.email,
|
||||
icon_url: params.icon_url,
|
||||
openai_key: params.openai_key,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ pub struct UserProfile {
|
||||
pub name: String,
|
||||
pub token: String,
|
||||
pub icon_url: String,
|
||||
pub openai_key: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Clone, Debug)]
|
||||
@ -51,6 +52,7 @@ pub struct UpdateUserProfileParams {
|
||||
pub email: Option<String>,
|
||||
pub password: Option<String>,
|
||||
pub icon_url: Option<String>,
|
||||
pub openai_key: Option<String>,
|
||||
}
|
||||
|
||||
impl UpdateUserProfileParams {
|
||||
@ -61,6 +63,7 @@ impl UpdateUserProfileParams {
|
||||
email: None,
|
||||
password: None,
|
||||
icon_url: None,
|
||||
openai_key: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,4 +86,9 @@ impl UpdateUserProfileParams {
|
||||
self.icon_url = Some(icon_url.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn openai_key(mut self, openai_key: &str) -> Self {
|
||||
self.openai_key = Some(openai_key.to_owned());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ mod user_email;
|
||||
mod user_icon;
|
||||
mod user_id;
|
||||
mod user_name;
|
||||
mod user_openai_key;
|
||||
mod user_password;
|
||||
mod user_workspace;
|
||||
|
||||
@ -10,5 +11,6 @@ pub use user_email::*;
|
||||
pub use user_icon::*;
|
||||
pub use user_id::*;
|
||||
pub use user_name::*;
|
||||
pub use user_openai_key::*;
|
||||
pub use user_password::*;
|
||||
pub use user_workspace::*;
|
||||
|
16
shared-lib/user-model/src/parser/user_openai_key.rs
Normal file
16
shared-lib/user-model/src/parser/user_openai_key.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use crate::errors::UserErrorCode;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UserOpenaiKey(pub String);
|
||||
|
||||
impl UserOpenaiKey {
|
||||
pub fn parse(s: String) -> Result<UserOpenaiKey, UserErrorCode> {
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for UserOpenaiKey {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user