diff --git a/lib/data/models/serializers.dart b/lib/data/models/serializers.dart index 1debb30df..9ebb78aec 100644 --- a/lib/data/models/serializers.dart +++ b/lib/data/models/serializers.dart @@ -119,6 +119,7 @@ part 'serializers.g.dart'; GatewayEntity, GatewayTokenListResponse, GatewayTokenItemResponse, + UserCompanyItemResponse, ]) final Serializers serializers = diff --git a/lib/data/models/serializers.g.dart b/lib/data/models/serializers.g.dart index c1d08eea4..ce19e8dbe 100644 --- a/lib/data/models/serializers.g.dart +++ b/lib/data/models/serializers.g.dart @@ -141,6 +141,7 @@ Serializers _$serializers = (new Serializers().toBuilder() ..add(TokenEntity.serializer) ..add(UIState.serializer) ..add(UserCompanyEntity.serializer) + ..add(UserCompanyItemResponse.serializer) ..add(UserCompanyState.serializer) ..add(UserEntity.serializer) ..add(UserItemResponse.serializer) diff --git a/lib/data/models/user_model.dart b/lib/data/models/user_model.dart index 1c1bed21b..5bf89ffa7 100644 --- a/lib/data/models/user_model.dart +++ b/lib/data/models/user_model.dart @@ -35,6 +35,19 @@ abstract class UserItemResponse _$userItemResponseSerializer; } +abstract class UserCompanyItemResponse + implements Built { + factory UserCompanyItemResponse([void updates(UserCompanyItemResponseBuilder b)]) = + _$UserCompanyItemResponse; + + UserCompanyItemResponse._(); + + UserCompanyEntity get data; + + static Serializer get serializer => + _$userCompanyItemResponseSerializer; +} + class UserFields { static const String firstName = 'first_name'; static const String lastName = 'last_name'; diff --git a/lib/data/models/user_model.g.dart b/lib/data/models/user_model.g.dart index 9d26d10ab..a1c8dbeb6 100644 --- a/lib/data/models/user_model.g.dart +++ b/lib/data/models/user_model.g.dart @@ -10,6 +10,8 @@ Serializer _$userListResponseSerializer = new _$UserListResponseSerializer(); Serializer _$userItemResponseSerializer = new _$UserItemResponseSerializer(); +Serializer _$userCompanyItemResponseSerializer = + new _$UserCompanyItemResponseSerializer(); Serializer _$userEntitySerializer = new _$UserEntitySerializer(); class _$UserListResponseSerializer @@ -99,6 +101,53 @@ class _$UserItemResponseSerializer } } +class _$UserCompanyItemResponseSerializer + implements StructuredSerializer { + @override + final Iterable types = const [ + UserCompanyItemResponse, + _$UserCompanyItemResponse + ]; + @override + final String wireName = 'UserCompanyItemResponse'; + + @override + Iterable serialize( + Serializers serializers, UserCompanyItemResponse object, + {FullType specifiedType = FullType.unspecified}) { + final result = [ + 'data', + serializers.serialize(object.data, + specifiedType: const FullType(UserCompanyEntity)), + ]; + + return result; + } + + @override + UserCompanyItemResponse deserialize( + Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = new UserCompanyItemResponseBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current as String; + iterator.moveNext(); + final dynamic value = iterator.current; + switch (key) { + case 'data': + result.data.replace(serializers.deserialize(value, + specifiedType: const FullType(UserCompanyEntity)) + as UserCompanyEntity); + break; + } + } + + return result.build(); + } +} + class _$UserEntitySerializer implements StructuredSerializer { @override final Iterable types = const [UserEntity, _$UserEntity]; @@ -475,6 +524,102 @@ class UserItemResponseBuilder } } +class _$UserCompanyItemResponse extends UserCompanyItemResponse { + @override + final UserCompanyEntity data; + + factory _$UserCompanyItemResponse( + [void Function(UserCompanyItemResponseBuilder) updates]) => + (new UserCompanyItemResponseBuilder()..update(updates)).build(); + + _$UserCompanyItemResponse._({this.data}) : super._() { + if (data == null) { + throw new BuiltValueNullFieldError('UserCompanyItemResponse', 'data'); + } + } + + @override + UserCompanyItemResponse rebuild( + void Function(UserCompanyItemResponseBuilder) updates) => + (toBuilder()..update(updates)).build(); + + @override + UserCompanyItemResponseBuilder toBuilder() => + new UserCompanyItemResponseBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is UserCompanyItemResponse && data == other.data; + } + + @override + int get hashCode { + return $jf($jc(0, data.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('UserCompanyItemResponse') + ..add('data', data)) + .toString(); + } +} + +class UserCompanyItemResponseBuilder + implements + Builder { + _$UserCompanyItemResponse _$v; + + UserCompanyEntityBuilder _data; + UserCompanyEntityBuilder get data => + _$this._data ??= new UserCompanyEntityBuilder(); + set data(UserCompanyEntityBuilder data) => _$this._data = data; + + UserCompanyItemResponseBuilder(); + + UserCompanyItemResponseBuilder get _$this { + if (_$v != null) { + _data = _$v.data?.toBuilder(); + _$v = null; + } + return this; + } + + @override + void replace(UserCompanyItemResponse other) { + if (other == null) { + throw new ArgumentError.notNull('other'); + } + _$v = other as _$UserCompanyItemResponse; + } + + @override + void update(void Function(UserCompanyItemResponseBuilder) updates) { + if (updates != null) updates(this); + } + + @override + _$UserCompanyItemResponse build() { + _$UserCompanyItemResponse _$result; + try { + _$result = _$v ?? new _$UserCompanyItemResponse._(data: data.build()); + } catch (_) { + String _$failedField; + try { + _$failedField = 'data'; + data.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'UserCompanyItemResponse', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} + class _$UserEntity extends UserEntity { @override final String firstName; diff --git a/lib/data/repositories/settings_repository.dart b/lib/data/repositories/settings_repository.dart index 45a2b193d..5b4ee7a5c 100644 --- a/lib/data/repositories/settings_repository.dart +++ b/lib/data/repositories/settings_repository.dart @@ -30,7 +30,7 @@ class SettingsRepository { return companyResponse.data; } - Future saveUser( + Future saveAuthUser( Credentials credentials, UserEntity user, String password) async { final data = serializers.serializeWith(UserEntity.serializer, user); dynamic response; @@ -44,7 +44,25 @@ class SettingsRepository { ); final UserItemResponse userResponse = - serializers.deserializeWith(UserItemResponse.serializer, response); + serializers.deserializeWith(UserItemResponse.serializer, response); + + return userResponse.data; + } + + Future saveUserSettings( + Credentials credentials, UserEntity user) async { + final data = serializers.serializeWith(UserEntity.serializer, user); + dynamic response; + + final url = credentials.url + '/company_users/${user.id}'; + response = await webClient.put( + url, + credentials.token, + data: json.encode(data), + ); + + final UserCompanyItemResponse userResponse = + serializers.deserializeWith(UserCompanyItemResponse.serializer, response); return userResponse.data; } diff --git a/lib/redux/company/company_reducer.dart b/lib/redux/company/company_reducer.dart index 338e65ce7..9b17e2eb2 100644 --- a/lib/redux/company/company_reducer.dart +++ b/lib/redux/company/company_reducer.dart @@ -81,10 +81,14 @@ Reducer userCompanyEntityReducer = combineReducers([ ); } }), - TypedReducer( - (userCompany, action) => userCompany.rebuild((b) => b + TypedReducer((userCompany, action) => + userCompany.rebuild((b) => b ..user.replace(action.user) ..settings.replace(action.user.userCompany.settings))), + TypedReducer( + (userCompany, action) => userCompany.rebuild((b) => b + ..user.userCompany.settings.replace(userCompany.settings) + ..settings.replace(action.userCompany.settings))), ]); UserCompanyEntity loadCompanySuccessReducer( diff --git a/lib/redux/reports/reports_reducer.dart b/lib/redux/reports/reports_reducer.dart index 575cdf10c..21685f908 100644 --- a/lib/redux/reports/reports_reducer.dart +++ b/lib/redux/reports/reports_reducer.dart @@ -4,7 +4,7 @@ import 'package:invoiceninja_flutter/redux/reports/reports_state.dart'; import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart'; ReportsUIState reportsUIReducer(ReportsUIState state, dynamic action) { - if (action is SaveUserSettingsSuccess) { + if (action is SaveAuthUserSuccess) { return state.rebuild((b) => b ..group = '' ..subgroup = '' diff --git a/lib/redux/settings/settings_actions.dart b/lib/redux/settings/settings_actions.dart index 10f630a67..f5f1c6f59 100644 --- a/lib/redux/settings/settings_actions.dart +++ b/lib/redux/settings/settings_actions.dart @@ -61,6 +61,28 @@ class SaveUserSettingsRequest implements StartSaving { SaveUserSettingsRequest({ @required this.completer, @required this.user, + }); + + final Completer completer; + final UserEntity user; +} + +class SaveUserSettingsSuccess implements StopSaving, PersistData, PersistUI { + SaveUserSettingsSuccess(this.userCompany); + + final UserCompanyEntity userCompany; +} + +class SaveUserSettingsFailure implements StopSaving { + SaveUserSettingsFailure(this.error); + + final Object error; +} + +class SaveAuthUserRequest implements StartSaving { + SaveAuthUserRequest({ + @required this.completer, + @required this.user, this.password, }); @@ -69,14 +91,14 @@ class SaveUserSettingsRequest implements StartSaving { final String password; } -class SaveUserSettingsSuccess implements StopSaving, PersistData, PersistUI { - SaveUserSettingsSuccess(this.user); +class SaveAuthUserSuccess implements StopSaving, PersistData, PersistUI { + SaveAuthUserSuccess(this.user); final UserEntity user; } -class SaveUserSettingsFailure implements StopSaving { - SaveUserSettingsFailure(this.error); +class SaveAuthUserFailure implements StopSaving { + SaveAuthUserFailure(this.error); final Object error; } diff --git a/lib/redux/settings/settings_middleware.dart b/lib/redux/settings/settings_middleware.dart index 11aa8cd88..97c44c843 100644 --- a/lib/redux/settings/settings_middleware.dart +++ b/lib/redux/settings/settings_middleware.dart @@ -22,13 +22,15 @@ List> createStoreSettingsMiddleware([ ]) { final viewSettings = _viewSettings(); final saveCompany = _saveCompany(repository); - final saveUser = _saveUser(repository); + final saveAuthUser = _saveAuthUser(repository); + final saveSettings = _saveSettings(repository); final uploadLogo = _uploadLogo(repository); return [ TypedMiddleware(viewSettings), TypedMiddleware(saveCompany), - TypedMiddleware(saveUser), + TypedMiddleware(saveAuthUser), + TypedMiddleware(saveSettings), TypedMiddleware(uploadLogo), ]; } @@ -84,15 +86,34 @@ Middleware _saveCompany(SettingsRepository settingsRepository) { }; } -Middleware _saveUser(SettingsRepository settingsRepository) { +Middleware _saveAuthUser(SettingsRepository settingsRepository) { + return (Store store, dynamic dynamicAction, NextDispatcher next) { + final action = dynamicAction as SaveAuthUserRequest; + + settingsRepository + .saveAuthUser(store.state.credentials, action.user, action.password) + .then((user) { + store.dispatch(SaveAuthUserSuccess(user)); + store.dispatch(UserVerifiedPassword()); + action.completer.complete(); + }).catchError((Object error) { + print(error); + store.dispatch(SaveAuthUserFailure(error)); + action.completer.completeError(error); + }); + + next(action); + }; +} + +Middleware _saveSettings(SettingsRepository settingsRepository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as SaveUserSettingsRequest; settingsRepository - .saveUser(store.state.credentials, action.user, action.password) - .then((user) { - store.dispatch(SaveUserSettingsSuccess(user)); - store.dispatch(UserVerifiedPassword()); + .saveUserSettings(store.state.credentials, action.user) + .then((userCompany) { + store.dispatch(SaveUserSettingsSuccess(userCompany)); action.completer.complete(); }).catchError((Object error) { print(error); diff --git a/lib/redux/ui/pref_reducer.dart b/lib/redux/ui/pref_reducer.dart index 7aaf74429..aa2b48770 100644 --- a/lib/redux/ui/pref_reducer.dart +++ b/lib/redux/ui/pref_reducer.dart @@ -261,7 +261,7 @@ Reducer settingsUIReducer = combineReducers([ ..origClient.replace(action.client) ..isChanged = false); }), - TypedReducer( + TypedReducer( (state, action) { return state.rebuild((b) => b ..user.replace(action.user) diff --git a/lib/redux/ui/ui_reducer.dart b/lib/redux/ui/ui_reducer.dart index 97d98511b..707a57c15 100644 --- a/lib/redux/ui/ui_reducer.dart +++ b/lib/redux/ui/ui_reducer.dart @@ -172,7 +172,7 @@ Reducer settingsUIReducer = combineReducers([ ..origClient.replace(action.client) ..isChanged = false); }), - TypedReducer((state, action) { + TypedReducer((state, action) { return state.rebuild((b) => b ..user.replace(action.user) ..origUser.replace(action.user) diff --git a/lib/ui/reports/reports_screen_vm.dart b/lib/ui/reports/reports_screen_vm.dart index 8c80ac7e8..3fa008194 100644 --- a/lib/ui/reports/reports_screen_vm.dart +++ b/lib/ui/reports/reports_screen_vm.dart @@ -31,7 +31,7 @@ import 'package:redux/redux.dart'; import 'expense_report.dart'; import 'reports_screen.dart'; import 'package:invoiceninja_flutter/utils/web_stub.dart' -if (dart.library.html) 'package:invoiceninja_flutter/utils/web.dart'; + if (dart.library.html) 'package:invoiceninja_flutter/utils/web.dart'; class ReportsScreenBuilder extends StatelessWidget { const ReportsScreenBuilder({Key key}) : super(key: key); @@ -225,26 +225,12 @@ class ReportsScreenVM { .rebuild((b) => b..userCompany.settings.replace(settings)); final completer = snackBarCompleter( context, AppLocalization.of(context).savedSettings); - if (state.authState.hasRecentlyEnteredPassword) { - store.dispatch( - SaveUserSettingsRequest( - completer: completer, - user: user, - ), - ); - } else { - passwordCallback( - context: context, - callback: (password) { - store.dispatch( - SaveUserSettingsRequest( - completer: completer, - user: user, - password: password, - ), - ); - }); - } + store.dispatch( + SaveUserSettingsRequest( + completer: completer, + user: user, + ), + ); }, onSettingsChanged: ({ String report, diff --git a/lib/ui/settings/user_details_vm.dart b/lib/ui/settings/user_details_vm.dart index 9a8e332dc..baeba1337 100644 --- a/lib/ui/settings/user_details_vm.dart +++ b/lib/ui/settings/user_details_vm.dart @@ -52,7 +52,7 @@ class UserDetailsVM { }); if (state.authState.hasRecentlyEnteredPassword) { store.dispatch( - SaveUserSettingsRequest( + SaveAuthUserRequest( completer: completer, user: state.uiState.settingsUIState.user, ), @@ -62,7 +62,7 @@ class UserDetailsVM { context: context, callback: (password) { store.dispatch( - SaveUserSettingsRequest( + SaveAuthUserRequest( completer: completer, user: state.uiState.settingsUIState.user, password: password,