Add new settings route

This commit is contained in:
Hillel Coren 2020-02-28 16:31:20 +02:00
parent 8d61720eaa
commit 309d49f4a0
13 changed files with 252 additions and 41 deletions

View File

@ -119,6 +119,7 @@ part 'serializers.g.dart';
GatewayEntity,
GatewayTokenListResponse,
GatewayTokenItemResponse,
UserCompanyItemResponse,
])
final Serializers serializers =

View File

@ -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)

View File

@ -35,6 +35,19 @@ abstract class UserItemResponse
_$userItemResponseSerializer;
}
abstract class UserCompanyItemResponse
implements Built<UserCompanyItemResponse, UserCompanyItemResponseBuilder> {
factory UserCompanyItemResponse([void updates(UserCompanyItemResponseBuilder b)]) =
_$UserCompanyItemResponse;
UserCompanyItemResponse._();
UserCompanyEntity get data;
static Serializer<UserCompanyItemResponse> get serializer =>
_$userCompanyItemResponseSerializer;
}
class UserFields {
static const String firstName = 'first_name';
static const String lastName = 'last_name';

View File

@ -10,6 +10,8 @@ Serializer<UserListResponse> _$userListResponseSerializer =
new _$UserListResponseSerializer();
Serializer<UserItemResponse> _$userItemResponseSerializer =
new _$UserItemResponseSerializer();
Serializer<UserCompanyItemResponse> _$userCompanyItemResponseSerializer =
new _$UserCompanyItemResponseSerializer();
Serializer<UserEntity> _$userEntitySerializer = new _$UserEntitySerializer();
class _$UserListResponseSerializer
@ -99,6 +101,53 @@ class _$UserItemResponseSerializer
}
}
class _$UserCompanyItemResponseSerializer
implements StructuredSerializer<UserCompanyItemResponse> {
@override
final Iterable<Type> types = const [
UserCompanyItemResponse,
_$UserCompanyItemResponse
];
@override
final String wireName = 'UserCompanyItemResponse';
@override
Iterable<Object> serialize(
Serializers serializers, UserCompanyItemResponse object,
{FullType specifiedType = FullType.unspecified}) {
final result = <Object>[
'data',
serializers.serialize(object.data,
specifiedType: const FullType(UserCompanyEntity)),
];
return result;
}
@override
UserCompanyItemResponse deserialize(
Serializers serializers, Iterable<Object> 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<UserEntity> {
@override
final Iterable<Type> 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, UserCompanyItemResponseBuilder> {
_$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;

View File

@ -30,7 +30,7 @@ class SettingsRepository {
return companyResponse.data;
}
Future<UserEntity> saveUser(
Future<UserEntity> saveAuthUser(
Credentials credentials, UserEntity user, String password) async {
final data = serializers.serializeWith(UserEntity.serializer, user);
dynamic response;
@ -49,6 +49,24 @@ class SettingsRepository {
return userResponse.data;
}
Future<UserCompanyEntity> 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;
}
Future<BaseEntity> uploadLogo(Credentials credentials, String entityId,
String path, EntityType type) async {
final route = type == EntityType.company

View File

@ -81,10 +81,14 @@ Reducer<UserCompanyEntity> userCompanyEntityReducer = combineReducers([
);
}
}),
TypedReducer<UserCompanyEntity, SaveUserSettingsSuccess>(
(userCompany, action) => userCompany.rebuild((b) => b
TypedReducer<UserCompanyEntity, SaveAuthUserSuccess>((userCompany, action) =>
userCompany.rebuild((b) => b
..user.replace(action.user)
..settings.replace(action.user.userCompany.settings))),
TypedReducer<UserCompanyEntity, SaveUserSettingsSuccess>(
(userCompany, action) => userCompany.rebuild((b) => b
..user.userCompany.settings.replace(userCompany.settings)
..settings.replace(action.userCompany.settings))),
]);
UserCompanyEntity loadCompanySuccessReducer(

View File

@ -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 = ''

View File

@ -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;
}

View File

@ -22,13 +22,15 @@ List<Middleware<AppState>> 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<AppState, ViewSettings>(viewSettings),
TypedMiddleware<AppState, SaveCompanyRequest>(saveCompany),
TypedMiddleware<AppState, SaveUserSettingsRequest>(saveUser),
TypedMiddleware<AppState, SaveAuthUserRequest>(saveAuthUser),
TypedMiddleware<AppState, SaveUserSettingsRequest>(saveSettings),
TypedMiddleware<AppState, UploadLogoRequest>(uploadLogo),
];
}
@ -84,15 +86,34 @@ Middleware<AppState> _saveCompany(SettingsRepository settingsRepository) {
};
}
Middleware<AppState> _saveUser(SettingsRepository settingsRepository) {
Middleware<AppState> _saveAuthUser(SettingsRepository settingsRepository) {
return (Store<AppState> 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<AppState> _saveSettings(SettingsRepository settingsRepository) {
return (Store<AppState> 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);

View File

@ -261,7 +261,7 @@ Reducer<SettingsUIState> settingsUIReducer = combineReducers([
..origClient.replace(action.client)
..isChanged = false);
}),
TypedReducer<SettingsUIState, prefix0.SaveUserSettingsSuccess>(
TypedReducer<SettingsUIState, prefix0.SaveAuthUserSuccess>(
(state, action) {
return state.rebuild((b) => b
..user.replace(action.user)

View File

@ -172,7 +172,7 @@ Reducer<SettingsUIState> settingsUIReducer = combineReducers([
..origClient.replace(action.client)
..isChanged = false);
}),
TypedReducer<SettingsUIState, SaveUserSettingsSuccess>((state, action) {
TypedReducer<SettingsUIState, SaveAuthUserSuccess>((state, action) {
return state.rebuild((b) => b
..user.replace(action.user)
..origUser.replace(action.user)

View File

@ -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<Null>(
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,
),
);
});
}
},
onSettingsChanged: ({
String report,

View File

@ -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,