diff --git a/assets/awi_logo.png b/assets/awi_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6246037121002e6e99ead4898b08ef1f9f79d890 Binary files /dev/null and b/assets/awi_logo.png differ diff --git a/lib/configuration.dart b/lib/configuration.dart index 8007b44a9f42c242ab122607a067170463a9d3bb..0ea45e20d503886c0c3e5d8bff314846e56f3fa7 100644 --- a/lib/configuration.dart +++ b/lib/configuration.dart @@ -7,7 +7,7 @@ import 'datamodel.dart'; Future<List<Device>> updateDevices(int collectionId) async { debugPrint("Start HTTP GET Collection Devices. Collection Id: " + collectionId.toString()); - String url = 'https://sensor.awi.de/rest/sensors/collections/getItemsOfCollection/' + collectionId.toString(); + String url = 'https://sandbox.sensor.awi.de/rest/sensors/collections/getItemsOfCollection/' + collectionId.toString(); // Get Access to local device and current event store. EventStoreInstance eventsStore = EventStoreInstance(); @@ -46,7 +46,7 @@ Future<List<Collection>> fetchCollections() async { List<Collection> collectionList = []; final response = await http - .get(Uri.parse('https://sensor.awi.de/rest/sensors/collections/getAllCollections?pointInTime=2018-07-03T12%3A30%3A55.389Z')); + .get(Uri.parse('https://sandbox.sensor.awi.de/rest/sensors/collections/getAllCollections?pointInTime=2018-07-03T12%3A30%3A55.389Z')); if (response.statusCode == 200) { return (json.decode(response.body) as List) @@ -84,8 +84,6 @@ class _MyHomePageState extends State<Configuration> { Widget build(BuildContext context) { final ConfigurationStoreInstance configuration = ConfigurationStoreInstance(); - //final CollectionStoreInstance collections = CollectionStoreInstance(); - //final CollectionCurrentInstance activeCollection = CollectionCurrentInstance(); return Scaffold( appBar: AppBar( diff --git a/lib/datamodel.dart b/lib/datamodel.dart index 7c8aa4d2c08585142325b12f7a83dae3c2c29378..cc65b9b66475b4e85f5629cbd638168e82487e84 100644 --- a/lib/datamodel.dart +++ b/lib/datamodel.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:shared_preferences/shared_preferences.dart'; @@ -107,15 +109,37 @@ class EventType{ } } +class SensorLogin{ + String mail; + String password; + String token; + + SensorLogin( + this.mail, + this.password, + this.token //REST API access Token + ); + + String toJsonString() { + return '{ "username": $mail, "authPassword": $password }'; + } + + Map<String, dynamic> toJson() => { + "username": mail, + "authPassword": password + }; +} + + // Storage classes // ConfigurationStoreBase for Collection, devices, event types, login information // EventStoreBase for created event information. abstract class ConfigurationStoreBase { List<Collection> collections = []; Collection currentCollection = Collection(id: -1, description: '', collectionName: ''); - List<Device> devices = []; List<EventType> eventTypes = []; + SensorLogin loginInformation = SensorLogin('', '', ''); Collection getCollectionFromName(String name) { for (var collection in collections) { @@ -149,6 +173,7 @@ abstract class ConfigurationStoreBase { devices = []; eventTypes = []; currentCollection = Collection(id: -1, description: '', collectionName: ''); + loginInformation = SensorLogin('', '', ''); } } diff --git a/lib/login.dart b/lib/login.dart index c3c9588f4d86c6ca505f0f16fbba44fd938b44d7..ad4ec370c8b928eb19dd5b9080986ba38111b78b 100644 --- a/lib/login.dart +++ b/lib/login.dart @@ -1,5 +1,46 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'datamodel.dart'; +import 'dart:convert'; +import 'package:http/http.dart' as http; + +Future<int> login() async { + // Get Access to local configuration store. Token must be stored there! + ConfigurationStoreInstance configuration = ConfigurationStoreInstance(); + + String url = 'https://sandbox.sensor.awi.de/rest/sensors/contacts/login'; + debugPrint("Start login to : " + url); + + final String body = jsonEncode(configuration.loginInformation); + debugPrint(body); + + final response = await http.post(Uri.parse(url), + body: body, + headers: { + 'Accept' : 'application/json', + 'Content-Type' : 'application/x-www-form-urlencoded' + }, + encoding: Encoding.getByName("utf-8") + ); + + + if (response.statusCode == 200) { + debugPrint('Login success'); + //TODO store token + + } else { + debugPrint('Header: ' + response.headers.toString()); + debugPrint('Body: ' + response.body.toString()); + debugPrint('StatusCode: ' + response.statusCode.toString()); + throw Exception('Failed to login'); + + + } + + return 0; +} + + class LoginPage extends StatefulWidget{ static String tag = 'login-page'; @@ -13,38 +54,46 @@ class _LoginPageState extends State<LoginPage> { @override Widget build(BuildContext context){ - const logo = Hero( - tag: 'blabla', - child: CircleAvatar( - backgroundColor: Colors.transparent, - radius: 48.0, - child: Text('LOGIN'), - ) - ); + final ConfigurationStoreInstance configuration = ConfigurationStoreInstance(); - final email = TextFormField( - keyboardType: TextInputType.emailAddress, - autofocus: false, - initialValue: '', - decoration: InputDecoration( - hintText: 'sensor e-mail address', - contentPadding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(32.0) + var logo = Hero( + tag: 'blabla', + child: CircleAvatar( + backgroundColor: Colors.transparent, + radius: 48.0, + child: Image.asset('assets/awi_logo.png'), ) - ) ); - final password = TextFormField( + final email = TextFormField( + keyboardType: TextInputType.emailAddress, autofocus: false, - initialValue: '', + initialValue: configuration.loginInformation.mail, decoration: InputDecoration( - hintText: 'sensor password', + hintText: 'sensor e-mail address', contentPadding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), border: OutlineInputBorder( borderRadius: BorderRadius.circular(32.0) ) - ) + ), + onChanged: (value) { + configuration.loginInformation.mail = value; + }, + ); + + final password = TextFormField( + autofocus: false, + initialValue: configuration.loginInformation.password, + decoration: InputDecoration( + hintText: 'sensor password', + contentPadding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(32.0) + ) + ), + onChanged: (value){ + configuration.loginInformation.password = value; + }, ); @@ -54,19 +103,23 @@ class _LoginPageState extends State<LoginPage> { borderRadius: BorderRadius.circular(30.0), shadowColor: Colors.lightBlueAccent.shade100, elevation: 5.0, - child: MaterialButton( - minWidth: 200.0, - height: 42.0, - onPressed: (){ - - }, - color: Colors.lightBlueAccent, - child: const Text('Log In', style: TextStyle(color: Colors.white)), - ), + child: MaterialButton( + minWidth: 200.0, + height: 42.0, + onPressed: (){ + login(); + //Navigator.pop(context); // Go back to previous widget + + //Return to previous widget if successfully logged in. Store x-auth-token. + //Display login error if login not possible. + }, + color: Colors.lightBlueAccent, + child: const Text('Log In', style: TextStyle(color: Colors.white)), + ), ), ); - final forgotLabel = FlatButton( + final forgotLabel = TextButton( onPressed: () { }, child: const Text('Forgot password?', style: TextStyle(color: Colors.black54), @@ -74,25 +127,25 @@ class _LoginPageState extends State<LoginPage> { ); return Scaffold( - backgroundColor: Colors.white, - body: Center( - child: ListView( - shrinkWrap: true, - padding: const EdgeInsets.only(left: 24.0, right: 24.0), - children: <Widget>[ - logo, - const SizedBox(height: 48.0), - email, - const SizedBox(height: 8.0), - password, - const SizedBox(height: 24.0), - loginButton, - forgotLabel - - - ], + backgroundColor: Colors.white, + body: Center( + child: ListView( + shrinkWrap: true, + padding: const EdgeInsets.only(left: 24.0, right: 24.0), + children: <Widget>[ + logo, + const SizedBox(height: 48.0), + email, + const SizedBox(height: 8.0), + password, + const SizedBox(height: 24.0), + loginButton, + forgotLabel //TODO: launch https://data.awi.de/auth/ + + + ], + ) ) - ) ); } } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 48eacfebc5489d2e1a093d524123fcb657939143..74c9d15dc7acc9d031d196fded72bde769042496 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -17,7 +17,8 @@ void main() { events.reset(); configuration.reset(); - + configuration.loginInformation.mail = 'admin'; // Sandbox.sensor.de admin account + configuration.loginInformation.password ='adminadmin'; // Add some dummy devices // TODO: load from shared preferences. diff --git a/lib/viewevents.dart b/lib/viewevents.dart index b9435c9ef49e0feb7b452020e8e3117ad8bd6a7c..2e1988f591eba8c4b13d53c27019d63b513037af 100644 --- a/lib/viewevents.dart +++ b/lib/viewevents.dart @@ -160,7 +160,7 @@ class ViewEvents extends StatelessWidget { icon: null, label: const Text('Upload'), onPressed: () { - // Provide + // Login }, ), ], diff --git a/pubspec.yaml b/pubspec.yaml index 6fcb55b4bdda4feb84eb553c3e1f11216efe76c1..75a049dd672103a0d9fe6d19a48c357062315101 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -62,7 +62,8 @@ flutter: uses-material-design: true # To add assets to your application, add an assets section, like this: - # assets: + assets: + - assets/awi_logo.png # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg