Handle invalid credentails
This commit is contained in:
parent
9e5e260eb1
commit
5b255b1745
|
|
@ -2,15 +2,30 @@ import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
part 'entities.g.dart';
|
part 'entities.g.dart';
|
||||||
|
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
class ErrorResponse extends Object with _$ErrorResponseSerializerMixin {
|
||||||
|
|
||||||
|
final String message;
|
||||||
|
|
||||||
|
ErrorResponse(
|
||||||
|
this.message,
|
||||||
|
);
|
||||||
|
|
||||||
|
factory ErrorResponse.fromJson(Map<String, dynamic> json) => _$ErrorResponseFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class BaseListResponse extends Object with _$BaseListResponseSerializerMixin {
|
class BaseListResponse extends Object with _$BaseListResponseSerializerMixin {
|
||||||
//final String message;
|
|
||||||
|
|
||||||
@JsonKey(name: "data")
|
@JsonKey(name: "data")
|
||||||
final List<dynamic> data;
|
final List<dynamic> data;
|
||||||
|
final ErrorResponse error;
|
||||||
|
|
||||||
BaseListResponse(
|
BaseListResponse(
|
||||||
this.data,
|
this.data,
|
||||||
|
this.error,
|
||||||
);
|
);
|
||||||
|
|
||||||
factory BaseListResponse.fromJson(Map<String, dynamic> json) => _$BaseListResponseFromJson(json);
|
factory BaseListResponse.fromJson(Map<String, dynamic> json) => _$BaseListResponseFromJson(json);
|
||||||
|
|
@ -22,9 +37,11 @@ class BaseItemResponse extends Object with _$BaseItemResponseSerializerMixin {
|
||||||
|
|
||||||
@JsonKey(name: "data")
|
@JsonKey(name: "data")
|
||||||
final dynamic data;
|
final dynamic data;
|
||||||
|
final ErrorResponse error;
|
||||||
|
|
||||||
BaseItemResponse(
|
BaseItemResponse(
|
||||||
this.data,
|
this.data,
|
||||||
|
this.error,
|
||||||
);
|
);
|
||||||
|
|
||||||
factory BaseItemResponse.fromJson(Map<String, dynamic> json) => _$BaseItemResponseFromJson(json);
|
factory BaseItemResponse.fromJson(Map<String, dynamic> json) => _$BaseItemResponseFromJson(json);
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,42 @@ part of 'entities.dart';
|
||||||
// Generator: JsonSerializableGenerator
|
// Generator: JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
ErrorResponse _$ErrorResponseFromJson(Map<String, dynamic> json) =>
|
||||||
|
new ErrorResponse(json['message'] as String);
|
||||||
|
|
||||||
|
abstract class _$ErrorResponseSerializerMixin {
|
||||||
|
String get message;
|
||||||
|
Map<String, dynamic> toJson() => <String, dynamic>{'message': message};
|
||||||
|
}
|
||||||
|
|
||||||
BaseListResponse _$BaseListResponseFromJson(Map<String, dynamic> json) =>
|
BaseListResponse _$BaseListResponseFromJson(Map<String, dynamic> json) =>
|
||||||
new BaseListResponse(json['data'] as List);
|
new BaseListResponse(
|
||||||
|
json['data'] as List,
|
||||||
|
json['error'] == null
|
||||||
|
? null
|
||||||
|
: new ErrorResponse.fromJson(
|
||||||
|
json['error'] as Map<String, dynamic>));
|
||||||
|
|
||||||
abstract class _$BaseListResponseSerializerMixin {
|
abstract class _$BaseListResponseSerializerMixin {
|
||||||
List<dynamic> get data;
|
List<dynamic> get data;
|
||||||
Map<String, dynamic> toJson() => <String, dynamic>{'data': data};
|
ErrorResponse get error;
|
||||||
|
Map<String, dynamic> toJson() =>
|
||||||
|
<String, dynamic>{'data': data, 'error': error};
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseItemResponse _$BaseItemResponseFromJson(Map<String, dynamic> json) =>
|
BaseItemResponse _$BaseItemResponseFromJson(Map<String, dynamic> json) =>
|
||||||
new BaseItemResponse(json['data']);
|
new BaseItemResponse(
|
||||||
|
json['data'],
|
||||||
|
json['error'] == null
|
||||||
|
? null
|
||||||
|
: new ErrorResponse.fromJson(
|
||||||
|
json['error'] as Map<String, dynamic>));
|
||||||
|
|
||||||
abstract class _$BaseItemResponseSerializerMixin {
|
abstract class _$BaseItemResponseSerializerMixin {
|
||||||
dynamic get data;
|
dynamic get data;
|
||||||
Map<String, dynamic> toJson() => <String, dynamic>{'data': data};
|
ErrorResponse get error;
|
||||||
|
Map<String, dynamic> toJson() =>
|
||||||
|
<String, dynamic>{'data': data, 'error': error};
|
||||||
}
|
}
|
||||||
|
|
||||||
CompanyEntity _$CompanyEntityFromJson(Map<String, dynamic> json) =>
|
CompanyEntity _$CompanyEntityFromJson(Map<String, dynamic> json) =>
|
||||||
|
|
|
||||||
|
|
@ -35,26 +35,35 @@ class WebClient {
|
||||||
|
|
||||||
Future<dynamic> fetchItem(String url, String token) async {
|
Future<dynamic> fetchItem(String url, String token) async {
|
||||||
final http.Response response = await sendGetRequest(url, token);
|
final http.Response response = await sendGetRequest(url, token);
|
||||||
return BaseItemResponse
|
final result = BaseItemResponse.fromJson(json.decode(response.body));
|
||||||
.fromJson(json.decode(response.body))
|
|
||||||
.data;
|
if (result.error.message != null) {
|
||||||
|
throw(result.error.message);
|
||||||
|
} else {
|
||||||
|
return result.data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<List<dynamic>> fetchList(String url, String token) async {
|
Future<List<dynamic>> fetchList(String url, String token) async {
|
||||||
final http.Response response = await sendGetRequest(url, token);
|
final http.Response response = await sendGetRequest(url, token);
|
||||||
return BaseListResponse
|
final result = BaseListResponse.fromJson(json.decode(response.body));
|
||||||
.fromJson(json.decode(response.body))
|
|
||||||
.data
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (result.error.message != null) {
|
||||||
|
throw(result.error.message);
|
||||||
|
} else {
|
||||||
|
return result.data.toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<dynamic>> postList(String url, String token, var data) async {
|
Future<List<dynamic>> postList(String url, String token, var data) async {
|
||||||
final http.Response response = await sendPostRequest(url, token, data);
|
final http.Response response = await sendPostRequest(url, token, data);
|
||||||
return BaseListResponse
|
final result = BaseListResponse.fromJson(json.decode(response.body));
|
||||||
.fromJson(json.decode(response.body))
|
|
||||||
.data
|
if (result.error.message != null) {
|
||||||
.toList();
|
throw(result.error.message);
|
||||||
|
} else {
|
||||||
|
return result.data.toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import 'package:invoiceninja/redux/app/app_state.dart';
|
||||||
import 'package:invoiceninja/data/models/models.dart';
|
import 'package:invoiceninja/data/models/models.dart';
|
||||||
|
|
||||||
class UserLoginRequest {
|
class UserLoginRequest {
|
||||||
final dynamic context;
|
final BuildContext context;
|
||||||
final String email;
|
final String email;
|
||||||
final String password;
|
final String password;
|
||||||
final String url;
|
final String url;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
import 'package:invoiceninja/redux/auth/auth_actions.dart';
|
import 'package:invoiceninja/redux/auth/auth_actions.dart';
|
||||||
|
|
@ -53,8 +54,18 @@ Middleware<AppState> _createLoginRequest(AuthRepository repository) {
|
||||||
|
|
||||||
Navigator.of(action.context).pushNamed(AppRoutes.dashboard);
|
Navigator.of(action.context).pushNamed(AppRoutes.dashboard);
|
||||||
}
|
}
|
||||||
).catchError((error) => store.dispatch(UserLoginFailure(error)));
|
).catchError((error) {
|
||||||
|
store.dispatch(UserLoginFailure(null));
|
||||||
|
|
||||||
|
final snackBar = new SnackBar(
|
||||||
|
duration: Duration(seconds: 3),
|
||||||
|
content: new Text('Error: ' + error.toString()),
|
||||||
|
);
|
||||||
|
|
||||||
|
Scaffold.of(action.context).showSnackBar(snackBar);
|
||||||
|
});
|
||||||
|
|
||||||
next(action);
|
next(action);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,22 +47,24 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return StoreConnector<AppState, dynamic>(
|
|
||||||
converter: (Store<AppState> store) {
|
|
||||||
return (BuildContext context, String email, String password, String url) {
|
|
||||||
store.dispatch(UserLoginRequest(context, email, password, url));
|
|
||||||
};
|
|
||||||
}, builder: (BuildContext context, loginAction) {
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Form(
|
body: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: ListView(
|
child:
|
||||||
|
StoreConnector<AppState, dynamic>(converter: (Store<AppState> store) {
|
||||||
|
return (BuildContext context, String email, String password,
|
||||||
|
String url) {
|
||||||
|
store.dispatch(UserLoginRequest(context, email, password, url));
|
||||||
|
};
|
||||||
|
}, builder: (BuildContext context, loginAction) {
|
||||||
|
return ListView(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
padding: EdgeInsets.only(left: 24.0, right: 24.0, top: 40.0),
|
padding: EdgeInsets.only(left: 24.0, right: 24.0, top: 40.0),
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 20.0, bottom: 20.0),
|
padding: EdgeInsets.only(top: 20.0, bottom: 20.0),
|
||||||
child: new Image.asset('assets/images/logo.png', width: 100.0, height: 100.0),
|
child: new Image.asset('assets/images/logo.png',
|
||||||
|
width: 100.0, height: 100.0),
|
||||||
),
|
),
|
||||||
TextFormField(
|
TextFormField(
|
||||||
controller: _emailTextController,
|
controller: _emailTextController,
|
||||||
|
|
@ -83,8 +85,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||||
TextFormField(
|
TextFormField(
|
||||||
controller: _urlTextController,
|
controller: _urlTextController,
|
||||||
decoration: InputDecoration(labelText: 'URL'),
|
decoration: InputDecoration(labelText: 'URL'),
|
||||||
validator: (val) =>
|
validator: (val) => val.isEmpty ? 'Please enter your URL.' : null,
|
||||||
val.isEmpty ? 'Please enter your URL.' : null,
|
|
||||||
onSaved: (val) => _url = val,
|
onSaved: (val) => _url = val,
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
|
|
@ -101,15 +102,13 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||||
//Navigator.of(context).pushNamed(HomeScreen.tag);
|
//Navigator.of(context).pushNamed(HomeScreen.tag);
|
||||||
},
|
},
|
||||||
color: Colors.lightBlueAccent,
|
color: Colors.lightBlueAccent,
|
||||||
child:
|
child: Text('LOGIN', style: TextStyle(color: Colors.white)),
|
||||||
Text('LOGIN', style: TextStyle(color: Colors.white)),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
});
|
}),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue