diff --git a/lib/settings/login.dart b/lib/settings/login.dart index e298604d..7447d93e 100644 --- a/lib/settings/login.dart +++ b/lib/settings/login.dart @@ -29,7 +29,7 @@ class _InvenTreeLoginSettingsState extends State { final GlobalKey _formKey = new GlobalKey(); - final _addProfileKey = new GlobalKey(); + final GlobalKey _addProfileKey = new GlobalKey(); final SharedPreferences _preferences; @@ -45,8 +45,21 @@ class _InvenTreeLoginSettingsState extends State { _password = _preferences.getString('password') ?? ''; } + void _reload() async { + + profiles = await UserProfileDBManager().getAllProfiles(); + + setState(() { + }); + } + void _createProfile(BuildContext context) { + var _name; + var _server; + var _username; + var _password; + showFormDialog( context, I18N.of(context).profileAdd, @@ -61,7 +74,19 @@ class _InvenTreeLoginSettingsState extends State { FlatButton( child: Text(I18N.of(context).save), onPressed: () { - // TODO + if (_addProfileKey.currentState.validate()) { + _addProfileKey.currentState.save(); + + // TODO - create the new profile... + UserProfile profile = UserProfile( + name: _name, + server: _server, + username: _username, + password: _password + ); + + _addProfile(profile); + } } ) ], @@ -69,21 +94,40 @@ class _InvenTreeLoginSettingsState extends State { StringField( label: I18N.of(context).name, initial: "profile", + onSaved: (value) => _name = value, + validator: _validateProfileName, ), StringField( label: "Server", initial: "http://127.0.0.1:8000", + hint: "http[s]://:", + validator: _validateServer, + onSaved: (value) => _server = value, ), StringField( label: "Username", + onSaved: (value) => _username = value, + validator: _validateUsername, ), StringField( - label: "Password" + label: "Password", + onSaved: (value) => _password = value, + validator: _validatePassword, ) ] ); } + String _validateProfileName(String value) { + + if (value.isEmpty) { + return 'Profile name cannot be empty'; + } + + // TODO: Check if a profile already exists with ths name + + return null; + } String _validateServer(String value) { @@ -95,6 +139,8 @@ class _InvenTreeLoginSettingsState extends State { return 'Server must start with http[s]'; } + // TODO: URL validator + return null; } @@ -118,20 +164,46 @@ class _InvenTreeLoginSettingsState extends State { if (_formKey.currentState.validate()) { _formKey.currentState.save(); + // TODO await InvenTreePreferences().saveLoginDetails(context, _server, _username, _password); } } + void _selectProfile(UserProfile profile) async { + + // Mark currently selected profile as unselected + final selected = await UserProfileDBManager().getSelectedProfile(); + + selected.selected = false; + + await UserProfileDBManager().updateProfile(selected); + + profile.selected = true; + + await UserProfileDBManager().updateProfile(profile); + + _reload(); + } + void _deleteProfile(UserProfile profile) async { await UserProfileDBManager().deleteProfile(profile); - // Reload profiles - profiles = await UserProfileDBManager().getAllProfiles(); + // Close the dialog + Navigator.of(context).pop(); - setState(() { - }); + _reload(); + } + + void _addProfile(UserProfile profile) async { + + await UserProfileDBManager().addProfile(profile); + + // Dismiss the create dialog + Navigator.of(context).pop(); + + _reload(); } @override @@ -146,9 +218,11 @@ class _InvenTreeLoginSettingsState extends State { UserProfile profile = profiles[idx]; children.add(ListTile( - title: Text(profile.name), + title: Text( + profile.name, + ), subtitle: Text(profile.server), - trailing: FaIcon(FontAwesomeIcons.checkCircle), + trailing: profile.selected ? FaIcon(FontAwesomeIcons.checkCircle) : null, onLongPress: () { showDialog( context: context, @@ -159,7 +233,7 @@ class _InvenTreeLoginSettingsState extends State { SimpleDialogOption( onPressed: () { Navigator.of(context).pop(); - // TODO - Mark profile as selected + _selectProfile(profile); }, child: Text(I18N.of(context).profileSelect), ), diff --git a/lib/user_profile.dart b/lib/user_profile.dart index 72553094..ba70f075 100644 --- a/lib/user_profile.dart +++ b/lib/user_profile.dart @@ -12,7 +12,8 @@ class UserProfile { this.name, this.server, this.username, - this.password + this.password, + this.selected, }); // ID of the profile @@ -30,6 +31,8 @@ class UserProfile { // Password String password; + bool selected = false; + // User ID (will be provided by the server on log-in) int user_id; @@ -39,6 +42,7 @@ class UserProfile { server: json['server'], username: json['username'], password: json['password'], + selected: json['selected'] ?? false, ); Map toJson() => { @@ -46,6 +50,7 @@ class UserProfile { "server": server, "username": username, "password": password, + "selected": selected, }; @override @@ -89,7 +94,7 @@ class UserProfileDBManager { final finder = Finder(filter: Filter.byKey(profile.key)); await _folder.update(await _db, profile.toJson(), finder: finder); - print("Updated user profile <%{profile.key}> - '${profile.name}"); + print("Updated user profile <${profile.key}> - '${profile.name}"); } Future deleteProfile(UserProfile profile) async { @@ -99,13 +104,65 @@ class UserProfileDBManager { print("Deleted user profile <${profile.key}> - '${profile.name}'"); } + Future getSelectedProfile() async { + /* + * Return the currently selected profile. + * + * If multiple profiles are selected, + * mark all but the first as unselected + * + * If no profile is currently selected, + * then force the first profile to be selected. + */ + + final selected_finder = Finder(filter: Filter.equals("selected", true)); + + final selected_profiles = await _folder.find(await _db, finder: selected_finder); + + if (selected_profiles.length == 1) { + // A single profile is selected + return UserProfile.fromJson(selected_profiles[0].key, selected_profiles[0].value); + } else if (selected_profiles.length > 1) { + // Multiple selected profiles - de-select others + for (int idx = 1; idx < selected_profiles.length; idx++) { + UserProfile profile = UserProfile.fromJson(selected_profiles[idx].key, selected_profiles[idx].value); + + profile.selected = false; + updateProfile(profile); + } + + // And return the first profile + return UserProfile.fromJson(selected_profiles[0].key, selected_profiles[0].value); + } else { + // No profiles selected! + + final all_profiles = await getAllProfiles(); + + if (all_profiles.length == 0) { + // No profiles available + return null; + } else { + UserProfile prf = all_profiles[0]; + prf.selected = true; + updateProfile(prf); + + // Return the selected profile + return prf; + } + } + } + Future getProfile(String name) async { + + print("Looking for user profile '${name}'"); + // Lookup profile by name (or return null if does not exist) final finder = Finder(filter: Filter.equals("name", name)); final profiles = await _folder.find(await _db, finder: finder); if (profiles.length == 0) { + print("No matching profiles found"); return null; }