diff --git a/lib/Components/Buttons/rounded_button.dart b/lib/Components/Buttons/rounded_button.dart new file mode 100644 index 0000000..011e314 --- /dev/null +++ b/lib/Components/Buttons/rounded_button.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:tablet_app/constants.dart'; + +class RoundedButton extends StatelessWidget { + final String text; + final Function press; + final Color color, textColor; + final double fontSize; + + const RoundedButton({ + Key key, + this.text, + this.press, + this.color = kMainRed, + this.textColor = Colors.white, + this.fontSize + }) : super(key: key); + + @override + Widget build(BuildContext context) { + Size size = MediaQuery.of(context).size; + return FlatButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(35.0), + //side: BorderSide(color: kSubTitleColor) + ), + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 25), + color: color, + onPressed: () => { + press() + }, + child: Text( + text, + style: new TextStyle(color: textColor, fontSize: fontSize, fontWeight: FontWeight.w400), + ), + ); + } +} \ No newline at end of file diff --git a/lib/Components/rounded_input_field.dart b/lib/Components/rounded_input_field.dart new file mode 100644 index 0000000..8b1f335 --- /dev/null +++ b/lib/Components/rounded_input_field.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:tablet_app/Components/text_field_container.dart'; +import 'package:tablet_app/constants.dart'; + +class RoundedInputField extends StatelessWidget { + final String hintText; + final IconData icon; + final ValueChanged onChanged; + final String initialValue; + final Color color, textColor, iconColor; + final int maxLength; + const RoundedInputField({ + Key key, + this.hintText, + this.initialValue, + this.icon, + this.color = kBackgroundGrey, + this.textColor = kMainGrey, + this.iconColor = kMainRed, + this.onChanged, + this.maxLength, // 50 + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return TextFieldContainer( + color: color, + child: TextFormField ( + onChanged: onChanged, + initialValue: initialValue, + cursorColor: textColor, + maxLength: maxLength, + style: TextStyle(fontSize: 20, color: textColor), + decoration: InputDecoration( + icon: icon != null ? Icon( + icon, + color: iconColor, + ): null, + hintText: hintText, + hintStyle: TextStyle(fontSize: 20.0, color: textColor), + border: InputBorder.none, + ) + ), + ); + } +} diff --git a/lib/Components/text_field_container.dart b/lib/Components/text_field_container.dart new file mode 100644 index 0000000..3f929b7 --- /dev/null +++ b/lib/Components/text_field_container.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:tablet_app/constants.dart'; + +class TextFieldContainer extends StatelessWidget { + final Widget child; + final Color color; + const TextFieldContainer({ + Key key, + this.child, + this.color = kBackgroundGrey, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + Size size = MediaQuery.of(context).size; + return Container( + margin: EdgeInsets.symmetric(vertical: 10), + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 5), + width: size.width * 0.8, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(29), + ), + child: child, + ); + } +} \ No newline at end of file diff --git a/lib/Helpers/DatabaseHelper.dart b/lib/Helpers/DatabaseHelper.dart new file mode 100644 index 0000000..10a0667 --- /dev/null +++ b/lib/Helpers/DatabaseHelper.dart @@ -0,0 +1,108 @@ +import 'dart:convert'; + +import 'package:managerapi/api.dart'; +import 'package:path/path.dart'; +import 'package:sqflite/sqflite.dart'; +import 'package:tablet_app/Models/tabletContext.dart'; + +class DatabaseHelper { + static final _databaseName = "tablet_database.db"; + static final _databaseVersion = 1; + + static final table = 'tabletAppContext'; + + static final columnId = 'id'; + static final columnDeviceId = 'deviceId'; + static final columnHost = 'host'; + static final columnConfiguration = 'configuration'; + static final columnLanguage = 'language'; + + DatabaseHelper._privateConstructor(); + static final DatabaseHelper instance = DatabaseHelper._privateConstructor(); + + static Database _database; + Future get database async { + if (_database != null) return _database; + _database = await _initDatabase(); + return _database; + } + + _initDatabase() async { + String path = join(await getDatabasesPath(), _databaseName); + return await openDatabase(path, + version: _databaseVersion, onCreate: _onCreate); + } + + // SQL code to create the database table + Future _onCreate(Database db, int version) async { + await db.execute(''' + CREATE TABLE $table ( + $columnId TEXT NOT NULL PRIMARY KEY, + $columnDeviceId TEXT NOT NULL, + $columnHost TEXT NOT NULL, + $columnConfiguration TEXT, + $columnLanguage TEXT NOT NULL + ) + '''); + } + + Future insert(TabletAppContext tabletAppContext) async { + Database db = await instance.database; + + var res = await db.insert(table, tabletAppContext.toMap()); + return res; + } + + Future update(TabletAppContext tabletAppContext) async { + // Get a reference to the database. + final db = await instance.database; + + await db.update( + 'tabletAppContext', + tabletAppContext.toMap(), + where: "id = ?", + whereArgs: ["1234"], // + ); + } + + Future>> queryAllRows() async { + Database db = await instance.database; + var res = await db.query(table, orderBy: "$columnId DESC"); + return res; + } + + Future delete(String email) async { + Database db = await instance.database; + return await db.delete(table, where: '$columnId = ?', whereArgs: [email]); + } + + Future clearTable() async { + Database db = await instance.database; + return await db.rawQuery("DELETE FROM $table"); + } + + Future getData() async { + TabletAppContext tabletAppContext; + + await DatabaseHelper.instance.queryAllRows().then((value) { + value.forEach((element) { + print("DB - CONTEXT --- "); + + // Configuration is store in SQLite in JSON Format + var configuration = element['configuration'] == null ? null: ConfigurationDTO.fromJson(jsonDecode(element['configuration'])); + + tabletAppContext = TabletAppContext( + id: element["id"], + deviceId: element["deviceId"], + host: element["host"], + configuration: configuration, + language: element["language"] + ); + }); + }).catchError((error) { + print(error); + }); + + return tabletAppContext; + } +} \ No newline at end of file diff --git a/lib/Models/map-marker.dart b/lib/Models/map-marker.dart index da441df..b8102c3 100644 --- a/lib/Models/map-marker.dart +++ b/lib/Models/map-marker.dart @@ -1,21 +1,28 @@ +import 'package:managerapi/api.dart'; + class MapMarker { int id; String title; String description; - String image; + List images; String latitude; String longitude; - MapMarker({this.id, this.title, this.description, this.image, this.latitude, this.longitude}); + MapMarker({this.id, this.title, this.description, this.images, this.latitude, this.longitude}); factory MapMarker.fromJson(Map json) { return new MapMarker( id: json['id'] as int, title: json['title'] as String, description: json['description'] as String, - image: json['image'] as String, + images: json['image'] as List, latitude: json['latitude'] as String, longitude: json['longitude'] as String, ); } + + @override + String toString() { + return 'MapMarker{id: $id, title: $title, description: $description, images: $images, latitude: $latitude, longitude: $longitude}'; + } } \ No newline at end of file diff --git a/lib/Models/tabletContext.dart b/lib/Models/tabletContext.dart index 3f5e98d..3de32c4 100644 --- a/lib/Models/tabletContext.dart +++ b/lib/Models/tabletContext.dart @@ -1,17 +1,42 @@ import 'package:flutter/material.dart'; import 'package:managerapi/api.dart'; import 'package:tablet_app/client.dart'; +import 'dart:convert'; class TabletAppContext with ChangeNotifier{ Client clientAPI; + String id; + String host; ConfigurationDTO configuration; String language; - TabletAppContext(); + String deviceId; + + TabletAppContext({this.id, this.deviceId, this.host, this.configuration, this.language}); + + Map toMap() { + return { + 'id': id, + 'deviceId': deviceId, + 'host': host, + 'configuration': configuration == null ? null : jsonEncode(configuration.toJson()), + 'language': language + }; + } + + factory TabletAppContext.fromJson(Map json) { + return new TabletAppContext( + id: json['id'] as String, + deviceId: json['deviceId'] as String, + host: json['host'] as String, + configuration: json['configuration'] == null ? null : ConfigurationDTO.fromJson(json['configuration']), + language: json['language'] as String + ); + } // Implement toString to make it easier to see information about @override String toString() { - return 'TabletAppContext{selectedConfiguration: $configuration, language: $language}'; + return 'TabletAppContext{id: $id, deviceId: $deviceId, selectedConfiguration: $configuration, language: $language, host: $host}'; } } \ No newline at end of file diff --git a/lib/Screens/Configuration/config_view.dart b/lib/Screens/Configuration/config_view.dart new file mode 100644 index 0000000..9e5e58b --- /dev/null +++ b/lib/Screens/Configuration/config_view.dart @@ -0,0 +1,293 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:managerapi/api.dart'; +import 'package:provider/provider.dart'; +import 'package:tablet_app/Components/Buttons/rounded_button.dart'; +import 'package:tablet_app/Components/loading.dart'; +import 'package:tablet_app/Components/rounded_input_field.dart'; +import 'package:tablet_app/Helpers/DatabaseHelper.dart'; +import 'package:tablet_app/Models/map-marker.dart'; +import 'package:tablet_app/Models/tabletContext.dart'; +import 'package:tablet_app/Screens/MainView/dropDown_configuration.dart'; +import 'package:tablet_app/Screens/MainView/main_view.dart'; +import 'package:tablet_app/app_context.dart'; +import 'package:tablet_app/client.dart'; +import 'package:tablet_app/constants.dart'; +import 'package:auto_size_text/auto_size_text.dart'; +import 'dart:io'; + +import 'package:unique_identifier/unique_identifier.dart'; + + +class ConfigViewWidget extends StatefulWidget { + ConfigViewWidget(); + + @override + _ConfigViewWidget createState() => _ConfigViewWidget(); +} + +class _ConfigViewWidget extends State { + Size sizeScreen = new Size(1080.0, 1920.0); // Tablet resolution + String url = "http://192.168.31.96"; //DEV "http://192.168.31.96" + bool configOk = false; + + @override + Widget build(BuildContext context) { + final appContext = Provider.of(context); + SystemChrome.setEnabledSystemUIOverlays([]); + Size size = MediaQuery.of(context).size; + return Scaffold( + body: Container( + height: size.height, + width: size.width, + color: kBackgroundGrey, + child: Center( + child: Container( + height: size.height * 0.85, + width: size.width * 0.9, + child: configOk ? FutureBuilder( + future: getConfigurations(appContext), + builder: (context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return Center( + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(29), + color: kBackgroundLight, + ), + height: size.height*0.3, + width: size.width*0.3, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.only(left: 15, right: 15, top: 15, bottom: 5), + child: Text( + "Choisir une configuration", + style: new TextStyle( + fontSize: 25 + ), + ), + ), + DropDownConfig( + configurations: snapshot.data, + onChange: (ConfigurationDTO configurationOut) async { + // CREATE DEVICE REQUEST + createDevice(configurationOut, appContext); + + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute( + builder: (context) { + return MainViewWidget(); + }, + ), + (Route route) => false // For pushAndRemoveUntil + ); + }, + ), + ], + ), + ), + ); + } else if (snapshot.connectionState == ConnectionState.none) { + return Text("No data"); + } else { + return Center( + child: Container( + height: size.height * 0.2, + child: Loading() + ) + ); + } + } + ) : Center( + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(29), + color: kBackgroundLight, + ), + height: size.height*0.3, + width: size.width*0.3, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + "Entrer l'url du manager", + style: new TextStyle( + fontSize: 25 + ), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 50, right: 50), + child: RoundedInputField( + hintText: "URL", + onChanged: (value) { + setState(() { + url = value; + }); + }, + icon: Icons.language + ), + ), + RoundedButton( + text: "OK", + fontSize: 25, + press: () async { + var client = Client(url); + var isOk = await isValidApi(client); + if (isOk) { + Fluttertoast.showToast( + msg: "Connecté au manager", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.BOTTOM, + timeInSecForIosWeb: 1, + backgroundColor: Colors.lightGreen, + textColor: Colors.white, + fontSize: 16.0 + ); + setState(() { + TabletAppContext tabletAppContext = new TabletAppContext(); + tabletAppContext.host = url; + tabletAppContext.clientAPI = client; + appContext.setContext(tabletAppContext); + + configOk = true; + }); + } else { + Fluttertoast.showToast( + msg: "L'url ne correspond pas à un manager", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.BOTTOM, + timeInSecForIosWeb: 1, + backgroundColor: Colors.redAccent, + textColor: Colors.white, + fontSize: 16.0 + ); + } + }, + ) + ], + ), + ), + ), + ), + ), + ) + ); + } + + Future createDevice(ConfigurationDTO configurationDTO, dynamic appContext) async { + TabletAppContext tabletAppContext = appContext.getContext(); + DeviceDetailDTO newDevice = new DeviceDetailDTO(); + newDevice.configurationId = configurationDTO.id; + newDevice.configuration = configurationDTO.label; + newDevice.connected = true; + newDevice.identifier = await UniqueIdentifier.serial; + newDevice.ipAddressWLAN = await getIP(true); + newDevice.ipAddressETH = await getIP(false); + newDevice.name = newDevice.ipAddressWLAN; + + print(newDevice); + + DeviceDetailDTO device = await tabletAppContext.clientAPI.deviceApi.deviceCreate(newDevice); + + if (device != null) { + // STORE IT LOCALLY !! + TabletAppContext tabletAppContext = appContext.getContext(); + tabletAppContext.id = device.identifier; + tabletAppContext.deviceId = device.id; + tabletAppContext.host = url; + tabletAppContext.language = "FR"; // By Default + tabletAppContext.configuration = configurationDTO; + appContext.setContext(tabletAppContext); + + // STORE IT LOCALLY (SQLite) + await DatabaseHelper.instance.insert(tabletAppContext); + + Fluttertoast.showToast( + msg: "La tablette a bien été créée", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.BOTTOM, + timeInSecForIosWeb: 1, + backgroundColor: Colors.lightGreen, + textColor: Colors.white, + fontSize: 16.0 + ); + } else { + Fluttertoast.showToast( + msg: "Une erreur est survenue lors de la création de la tablette", + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.BOTTOM, + timeInSecForIosWeb: 1, + backgroundColor: Colors.deepOrangeAccent, + textColor: Colors.white, + fontSize: 16.0 + ); + } + } + + isValidApi(Client client) async { + print("TEST URL"); + try { + var configs = await client.configurationApi.configurationGet(); + return configs != null; + } catch (ex) { + return false; + } + } +} + +Future getIP(bool isWLAN) async { + for (var interface in await NetworkInterface.list()) { + print('== Interface: ${interface.name} =='); + if (interface.name == "wlan0" && isWLAN) { + // wifi + return interface.addresses.first.address; + } + if (interface.name == "eth0" && !isWLAN) { + // wired + return interface.addresses.first.address; + } + } + return null; +} + +boxDecoration(SectionDTO section) { + return BoxDecoration( + color: kBackgroundLight, + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(30.0), + image: new DecorationImage( + fit: BoxFit.cover, + colorFilter: new ColorFilter.mode(Colors.black.withOpacity(0.6), BlendMode.dstATop), + image: new NetworkImage( + section.imageSource, + ), + ), + boxShadow: [ + BoxShadow( + color: kBackgroundSecondGrey, + spreadRadius: 0.5, + blurRadius: 5, + offset: Offset(0, 1.5), // changes position of shadow + ), + ], + ); +} + +Future> getConfigurations(dynamic appContext) async { + List configurations = await appContext.getContext().clientAPI.configurationApi.configurationGet(); + print("number of configurations " + configurations.length.toString()); + configurations.forEach((element) { + print(element); + }); + return configurations; +} \ No newline at end of file diff --git a/lib/Components/MainView/dropDown_configuration.dart b/lib/Screens/MainView/dropDown_configuration.dart similarity index 100% rename from lib/Components/MainView/dropDown_configuration.dart rename to lib/Screens/MainView/dropDown_configuration.dart diff --git a/lib/Components/MainView/language_selection.dart b/lib/Screens/MainView/language_selection.dart similarity index 100% rename from lib/Components/MainView/language_selection.dart rename to lib/Screens/MainView/language_selection.dart diff --git a/lib/Components/MainView/main_view.dart b/lib/Screens/MainView/main_view.dart similarity index 58% rename from lib/Components/MainView/main_view.dart rename to lib/Screens/MainView/main_view.dart index db597ed..8e65036 100644 --- a/lib/Components/MainView/main_view.dart +++ b/lib/Screens/MainView/main_view.dart @@ -1,14 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; -import 'package:fluttertoast/fluttertoast.dart'; import 'package:managerapi/api.dart'; import 'package:provider/provider.dart'; -import 'package:tablet_app/Components/MainView/dropDown_configuration.dart'; -import 'package:tablet_app/Components/Map/map_context.dart'; -import 'package:tablet_app/Components/Map/map_view.dart'; import 'package:tablet_app/Components/loading.dart'; -import 'package:tablet_app/Components/webView.dart'; +import 'package:tablet_app/Screens/Map/map_context.dart'; +import 'package:tablet_app/Screens/Map/map_view.dart'; +import 'file:///C:/Users/Thomas%20Fransolet/Documents/Documents/Perso/MuseeDeLaFraise/tablet-app/lib/Screens/webView.dart'; import 'package:tablet_app/Models/map-marker.dart'; import 'package:tablet_app/Models/tabletContext.dart'; import 'package:tablet_app/app_context.dart'; @@ -46,7 +44,7 @@ class _MainViewWidget extends State { longitude: null, title: '', description: '')), - child: MapViewWidget() /*FutureBuilder( + child: MapViewWidget(section: sectionSelected) /*FutureBuilder( future: _url, builder: (BuildContext context, AsyncSnapshot snapshot) => snapshot.hasData ? WebViewWidget(url: snapshot.data,) @@ -161,7 +159,6 @@ class _MainViewWidget extends State { ), ), ), - ); } else { return Scaffold( @@ -182,62 +179,7 @@ class _MainViewWidget extends State { print('helloo test'); if (snapshot.connectionState == ConnectionState.done) { if (snapshot.data == null) { - //return Text("NO CONFIGURATION"); - return FutureBuilder( - future: getConfigurations(appContext), - builder: (context, AsyncSnapshot snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - return Center( - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(29), - color: kBackgroundLight, - ), - height: size.height*0.3, - width: size.width*0.3, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(15.0), - child: Text( - "Choisir une configuration", - style: new TextStyle( - fontSize: 25 - ), - ), - ), - DropDownConfig( - configurations: snapshot.data, - onChange: (ConfigurationDTO configurationOut) { - setState(() { - // TODO STORE IT LOCALLY !! + CREATE DEVICE REQUEST - - TabletAppContext tabletAppContext = appContext.getContext(); - tabletAppContext.configuration = configurationOut; - appContext.setContext(tabletAppContext); - - createDevice(configurationOut, appContext); - }); - }, - ), - ], - ), - ), - ); - } else if (snapshot.connectionState == ConnectionState.none) { - return Text("No data"); - } else { - return Center( - child: Container( - height: size.height * 0.2, - child: Loading() - ) - ); - } - } - ); + return Text("ERROR CALL 0498/07.95.35"); } else { return GridView.builder( @@ -307,81 +249,12 @@ class _MainViewWidget extends State { Future> getSections(dynamic appContext) async { TabletAppContext tabletAppContext = await appContext.getContext(); + print("GET SECTIONS"); print(tabletAppContext.toString()); List sections = await tabletAppContext.clientAPI.sectionApi.sectionGetFromConfiguration(tabletAppContext.configuration.id); print(sections); return sections; - /*print('in future'); - final response = await http.get('https://jsonplaceholder.typicode.com/posts/1'); - - if (response.statusCode == 200) { - // If the call to the server was successful, parse the JSON. - return [ - new Section(id: 0, title: "TEST Map", description: "Ceci est l'essai d'une carte", image: "https://www.novo-monde.com/app/uploads/2017/11/novo-map-banner-3.jpg", category: 0), - new Section(id: 0, title: "TEST Site web", description: "Ceci est l'essai d'un site web", image: "https://static.wixstatic.com/media/38e2f4_4c1714f38942446e99c1e736726e4465~mv2.jpg/v1/fill/w_892,h_564,al_c,q_85,usm_0.66_1.00_0.01/38e2f4_4c1714f38942446e99c1e736726e4465~mv2.webp", category: 1), - new Section(id: 0, title: "TEST 2", description: "fsfsdf", image: "https://static.wixstatic.com/media/38e2f4_4c1714f38942446e99c1e736726e4465~mv2.jpg/v1/fill/w_892,h_564,al_c,q_85,usm_0.66_1.00_0.01/38e2f4_4c1714f38942446e99c1e736726e4465~mv2.webp", category: 2), - new Section(id: 0, title: "TEST 3", description: "fsfsdf", image: "https://static.wixstatic.com/media/38e2f4_4c1714f38942446e99c1e736726e4465~mv2.jpg/v1/fill/w_892,h_564,al_c,q_85,usm_0.66_1.00_0.01/38e2f4_4c1714f38942446e99c1e736726e4465~mv2.webp", category: 0), - new Section(id: 0, title: "TEST 4", description: "fsfsdf", image: "https://static.wixstatic.com/media/38e2f4_4c1714f38942446e99c1e736726e4465~mv2.jpg/v1/fill/w_892,h_564,al_c,q_85,usm_0.66_1.00_0.01/38e2f4_4c1714f38942446e99c1e736726e4465~mv2.webp", category: 0), - new Section(id: 0, title: "TEST 5", description: "fsfsdf", image: "https://static.wixstatic.com/media/38e2f4_4c1714f38942446e99c1e736726e4465~mv2.jpg/v1/fill/w_892,h_564,al_c,q_85,usm_0.66_1.00_0.01/38e2f4_4c1714f38942446e99c1e736726e4465~mv2.webp", category: 0), - new Section(id: 0, title: "TEST 6", description: "fsfsdf", image: "https://static.wixstatic.com/media/38e2f4_4c1714f38942446e99c1e736726e4465~mv2.jpg/v1/fill/w_892,h_564,al_c,q_85,usm_0.66_1.00_0.01/38e2f4_4c1714f38942446e99c1e736726e4465~mv2.webp", category: 0), - ]; - } else { - // If that call was not successful, throw an error. - throw Exception('Failed to load post'); - }*/ - } - - Future createDevice(ConfigurationDTO configurationDTO, dynamic appContext) async { - TabletAppContext tabletAppContext = appContext.getContext(); - DeviceDetailDTO newDevice = new DeviceDetailDTO(); - newDevice.configurationId = configurationDTO.id; - newDevice.configuration = configurationDTO.label; - newDevice.connected = true; - newDevice.ipAddressWLAN = await getIP(true); - newDevice.ipAddressETH = await getIP(false); - - print(newDevice); - - DeviceDetailDTO device = await tabletAppContext.clientAPI.deviceApi.deviceCreate(newDevice); - - if (device != null) { - Fluttertoast.showToast( - msg: "La tablette a bien été créée", - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - timeInSecForIosWeb: 1, - backgroundColor: Colors.lightGreen, - textColor: Colors.white, - fontSize: 16.0 - ); - } else { - Fluttertoast.showToast( - msg: "Une erreur est survenue lors de la création de la tablette", - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - timeInSecForIosWeb: 1, - backgroundColor: Colors.deepOrangeAccent, - textColor: Colors.white, - fontSize: 16.0 - ); - } - } -} - -Future getIP(bool isWLAN) async { - for (var interface in await NetworkInterface.list()) { - print('== Interface: ${interface.name} =='); - if (interface.name == "wlan0" && isWLAN) { - // wifi - return interface.addresses.first.address; - } - if (interface.name == "eth0" && !isWLAN) { - // wired - return interface.addresses.first.address; - } - } - return null; } boxDecoration(SectionDTO section) { @@ -405,13 +278,4 @@ boxDecoration(SectionDTO section) { ), ], ); -} - -Future> getConfigurations(dynamic appContext) async { - List configurations = await appContext.getContext().clientAPI.configurationApi.configurationGet(); - print("number of configurations " + configurations.length.toString()); - configurations.forEach((element) { - print(element); - }); - return configurations; } \ No newline at end of file diff --git a/lib/Components/Map/map_context.dart b/lib/Screens/Map/map_context.dart similarity index 100% rename from lib/Components/Map/map_context.dart rename to lib/Screens/Map/map_context.dart diff --git a/lib/Components/Map/map_view.dart b/lib/Screens/Map/map_view.dart similarity index 51% rename from lib/Components/Map/map_view.dart rename to lib/Screens/Map/map_view.dart index 13741d3..8431137 100644 --- a/lib/Components/Map/map_view.dart +++ b/lib/Screens/Map/map_view.dart @@ -1,30 +1,35 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:managerapi/api.dart'; import 'package:provider/provider.dart'; -import 'package:tablet_app/Components/Map/marker_view.dart'; +import 'package:tablet_app/Components/loading.dart'; import 'package:tablet_app/Models/map-marker.dart'; import 'dart:ui' as ui; import 'package:flutter/widgets.dart'; +import 'package:tablet_app/Screens/Map/marker_view.dart'; +import '../../app_context.dart'; import 'map_context.dart'; Set markers = {}; List markersList = List(); class MapViewWidget extends StatefulWidget { - MapViewWidget(); + final SectionDTO section; + MapViewWidget({Key key, this.section}) : super(key: key); @override _MapViewWidget createState() => _MapViewWidget(); } class _MapViewWidget extends State { - + MapDTO mapDTO; Completer _controller = Completer(); - + Uint8List selectedMarkerIcon; Future getBytesFromAsset(String path, int width) async { ByteData data = await rootBundle.load(path); @@ -36,48 +41,25 @@ class _MapViewWidget extends State { .asUint8List(); } - void getMarkers(mapContext) async { + Set getMarkers(appContext, mapContext) { /*final Uint8List userMarkerIcon = await getBytesFromAsset('assets/normalMarker.png', 75); */ - final Uint8List selectedMarkerIcon = await getBytesFromAsset('assets/images/strawberry.png', 50); - markers = {}; - // TODO Call manager to fetch saved markers - - markersList.add(MapMarker( - id: 1, - title: "La Grande Poste", - description: "The Algiers central post office is an office building for postal services located at Alger Centre municipality in Algiers, Algeria", - image: "https://www.dzbreaking.com/wp-content/uploads/2018/03/2000.png", - latitude: "36.752887", - longitude: "3.042048" - )); - markersList.add(MapMarker( - id: 2, - title: "Mosquee Ketchaoua", - description: "The Ketchaoua Mosque is a mosque in Algiers, the capital of Algeria. It was built during the Ottoman rule in the 17th century and is located at the foot of the Casbah, which is a UNESCO World Heritage Site", - image: "https://ttnotes.com/images/makam-echahid-algiers.jpg", - latitude: "36.7850", - longitude: "3.0608" - )); - markersList.add(MapMarker( - id: 3, - title: "The shrine of the martyr", - description: "The Maqam Echahid is a concrete monument commemorating the Algerian war for independence. The monument was opened in 1982 on the 20th anniversary of Algeria's independence", - image: "https://www.airfrance.co.uk/GB/common/common/img/tbaf/news/ALG/la-mosquee-ketchaoua-l-histoire-avec-un-grand-h/ALG-la-mosquee-ketchaoua-l-histoire-avec-un-grand-h-2_1-1024x512.jpg", - latitude: "36.7456", - longitude: "3.0698" - )); - markersList.add(MapMarker( - id: 4, - title: "Musée de la fraise", - description: "Musée de la fraise wépion", - image: "https://www.airfrance.co.uk/GB/common/common/img/tbaf/news/ALG/la-mosquee-ketchaoua-l-histoire-avec-un-grand-h/ALG-la-mosquee-ketchaoua-l-histoire-avec-un-grand-h-2_1-1024x512.jpg", - latitude: "50.416639", - longitude: "4.879169" - )); + mapDTO.points.forEach((point) { + var mapMarker = new MapMarker( + id: point.id, + title: point.title.firstWhere((translation) => translation.language == appContext.getContext().language).value, + description: point.description.firstWhere((translation) => translation.language == appContext.getContext().language).value, + longitude: point.longitude, + latitude: point.latitude, + images: point.images + ); + print("MAP MARKERRRR ---------------------------------------------------"); + print(mapMarker.toString()); + markersList.add(mapMarker); + }); markersList.forEach((element) { if (element.latitude != null && element.longitude != null) { @@ -107,11 +89,16 @@ class _MapViewWidget extends State { infoWindow: InfoWindow(title: element.title))); } }); + + return markers; } @override void initState() { - print(markers); + print(widget.section.data); + mapDTO = MapDTO.fromJson(jsonDecode(widget.section.data)); + print(mapDTO); + super.initState(); } @@ -121,11 +108,6 @@ class _MapViewWidget extends State { super.dispose(); } - static final CameraPosition _kGooglePlex = CameraPosition( - target: LatLng(50.416639, 4.879169), - zoom: 18, - ); - /*static final CameraPosition _kLake = CameraPosition( bearing: 192.8334901395799, target: LatLng(37.43296265331129, -122.08832357078792), @@ -135,29 +117,47 @@ class _MapViewWidget extends State { @override Widget build(BuildContext context) { final mapContext = Provider.of(context); - getMarkers(mapContext); + final appContext = Provider.of(context); return Stack( children: [ - GoogleMap( - mapType: MapType.hybrid, - mapToolbarEnabled: false, - initialCameraPosition: _kGooglePlex, - onMapCreated: (GoogleMapController controller) { - _controller.complete(controller); - }, - markers: markers, - onTap: (LatLng location) { - setState(() { - print(location); - mapContext.setSelectedMarker( - new MapMarker( - title: '', - description: '', - longitude: null, - latitude: null - )); - }); - }, + FutureBuilder( + future: getByteIcon(), + builder: (context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return GoogleMap( + //mapType: mapDTO.mapType, // TODO mapDTO.mapType, + mapToolbarEnabled: false, + initialCameraPosition: CameraPosition( + target: LatLng(50.416639, 4.879169), + zoom: mapDTO.zoom != null ? mapDTO.zoom.toDouble() : 18, + ), + onMapCreated: (GoogleMapController controller) { + _controller.complete(controller); + }, + markers: getMarkers(appContext, mapContext), + onTap: (LatLng location) { + /*setState(() { + print(location); + mapContext.setSelectedMarker( + new MapMarker( + title: '', + description: '', + longitude: null, + latitude: null + )); + });*/ + }, + ); + } else if (snapshot.connectionState == ConnectionState.none) { + return Text("No data"); + } else { + return Center( + child: Container( + child: Loading() + ) + ); + } + } ), MarkerViewWidget() ] @@ -169,6 +169,10 @@ class _MapViewWidget extends State { ); } + getByteIcon() async { + selectedMarkerIcon = await getBytesFromAsset('assets/images/strawberry.png', 50); + } + /*Future _goToTheLake() async { final GoogleMapController controller = await _controller.future; controller.animateCamera(CameraUpdate.newCameraPosition(_kLake)); diff --git a/lib/Components/Map/marker_view.dart b/lib/Screens/Map/marker_view.dart similarity index 98% rename from lib/Components/Map/marker_view.dart rename to lib/Screens/Map/marker_view.dart index ad17302..1ec8f6f 100644 --- a/lib/Components/Map/marker_view.dart +++ b/lib/Screens/Map/marker_view.dart @@ -1,10 +1,10 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:tablet_app/Components/Map/map_context.dart'; import 'package:tablet_app/Models/map-marker.dart'; import '../../constants.dart'; +import 'map_context.dart'; class MarkerViewWidget extends StatefulWidget { MarkerViewWidget(); diff --git a/lib/Components/Previous/previous_view.dart b/lib/Screens/Previous/previous_view.dart similarity index 99% rename from lib/Components/Previous/previous_view.dart rename to lib/Screens/Previous/previous_view.dart index eccee6b..95a1aac 100644 --- a/lib/Components/Previous/previous_view.dart +++ b/lib/Screens/Previous/previous_view.dart @@ -3,9 +3,9 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; -import 'package:tablet_app/Components/Map/map_context.dart'; -import 'package:tablet_app/Components/Map/map_view.dart'; import 'package:tablet_app/Models/map-marker.dart'; +import 'package:tablet_app/Screens/Map/map_context.dart'; +import 'package:tablet_app/Screens/Map/map_view.dart'; import 'package:webview_flutter/webview_flutter.dart'; import '../../constants.dart'; diff --git a/lib/Components/custom_clipper.dart b/lib/Screens/custom_clipper.dart similarity index 100% rename from lib/Components/custom_clipper.dart rename to lib/Screens/custom_clipper.dart diff --git a/lib/Components/webView.dart b/lib/Screens/webView.dart similarity index 100% rename from lib/Components/webView.dart rename to lib/Screens/webView.dart diff --git a/lib/client.dart b/lib/client.dart index 84b5974..26477d5 100644 --- a/lib/client.dart +++ b/lib/client.dart @@ -23,9 +23,9 @@ class Client { DeviceApi _deviceApi; DeviceApi get deviceApi => _deviceApi; - Client() { + Client(String path) { _apiClient = ApiClient( - basePath: "http://192.168.31.96"); + basePath: path); // "http://192.168.31.96" //basePath: "https://localhost:44339"); _authenticationApi = AuthenticationApi(_apiClient); _userApi = UserApi(_apiClient); diff --git a/lib/main.dart b/lib/main.dart index b61a5c1..527789b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,71 +1,67 @@ import 'package:flutter/material.dart'; import 'package:managerapi/api.dart'; import 'package:provider/provider.dart'; -import 'package:tablet_app/Components/MainView/main_view.dart'; import 'package:tablet_app/client.dart'; - -import 'Components/Previous/previous_view.dart'; +import 'Helpers/DatabaseHelper.dart'; import 'Models/tabletContext.dart'; +import 'Screens/Configuration/config_view.dart'; +import 'Screens/MainView/main_view.dart'; +import 'Screens/Previous/previous_view.dart'; import 'app_context.dart'; import 'constants.dart'; -void main() { +void main() async { + WidgetsFlutterBinding.ensureInitialized(); String initialRoute; + TabletAppContext localContext = new TabletAppContext(); + bool isConfig = false; - initialRoute = '/main'; + localContext = await DatabaseHelper.instance.getData(); + + if(localContext != null) { + print("we've got an local db !"); + localContext.clientAPI = new Client(localContext.host); + isConfig = localContext.configuration != null; + print(localContext); + // Get config from manager + DeviceDetailDTO device = await localContext.clientAPI.deviceApi.deviceGetDetail(localContext.deviceId); + localContext.configuration.id = device.configurationId; + + } else { + print("NO LOCAL DB !"); + } + + initialRoute = isConfig ? '/main' : '/config'; final MyApp myApp = MyApp( initialRoute: initialRoute, - //context: localContext, + tabletAppContext: localContext, ); - runApp(myApp); } class MyApp extends StatefulWidget { final String initialRoute; final TabletAppContext tabletAppContext; - final clientAPI = Client(); - - //final Context context; MyApp({this.initialRoute, this.tabletAppContext}); - // This widget is the root of your application. @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State { - Client clientAPI = new Client(); - TabletAppContext tabletAppContext; @override void initState() { - if (widget.tabletAppContext == null) { - tabletAppContext = new TabletAppContext(); - // store user info locally - tabletAppContext.clientAPI = clientAPI; - tabletAppContext.language = "FR"; - - //appContext.setContext(tabletAppContext); - - /*List sections = await clientAPI.sectionApi.sectionGetFromConfiguration("60b1257a2939c9163c3f0921"); - print("number of sections " + sections.length.toString()); - sections.forEach((element) { - print(element); - });*/ - - } else { - tabletAppContext = widget.tabletAppContext; - } + //tabletAppContext = widget.tabletAppContext; super.initState(); } @override Widget build(BuildContext context) { return ChangeNotifierProvider( - create: (_) => AppContext(tabletAppContext), + create: (_) => AppContext(widget.tabletAppContext), child: MaterialApp( debugShowCheckedModeBanner: false, title: 'Tablet App Demo', @@ -83,7 +79,8 @@ class _MyAppState extends State { ), routes: { '/previous': (context) => PreviousViewWidget(title: 'Tablet App Demo Home Page'), - '/main': (context) => MainViewWidget() + '/main': (context) => MainViewWidget(), + '/config': (context) => ConfigViewWidget(), } ), ); diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index cf98146..66dd8a8 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -7,6 +7,8 @@ import FlutterMacOS import Foundation +import sqflite func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) } diff --git a/manager_api/.openapi-generator/FILES b/manager_api/.openapi-generator/FILES index 1e85bb0..5271cf2 100644 --- a/manager_api/.openapi-generator/FILES +++ b/manager_api/.openapi-generator/FILES @@ -13,7 +13,7 @@ doc/ImageDTO.md doc/ImageGeoPoint.md doc/LoginDTO.md doc/MapDTO.md -doc/MapType.md +doc/MapTypeApp.md doc/MenuDTO.md doc/ResourceApi.md doc/ResourceDTO.md @@ -55,7 +55,7 @@ lib/model/image_dto.dart lib/model/image_geo_point.dart lib/model/login_dto.dart lib/model/map_dto.dart -lib/model/map_type.dart +lib/model/map_type_app.dart lib/model/menu_dto.dart lib/model/resource_detail_dto.dart lib/model/resource_dto.dart @@ -70,3 +70,4 @@ lib/model/user_detail_dto.dart lib/model/video_dto.dart lib/model/web_dto.dart pubspec.yaml +test/map_type_app_test.dart diff --git a/manager_api/README.md b/manager_api/README.md index ab85a8a..61935fe 100644 --- a/manager_api/README.md +++ b/manager_api/README.md @@ -116,7 +116,7 @@ Class | Method | HTTP request | Description - [ImageGeoPoint](doc\/ImageGeoPoint.md) - [LoginDTO](doc\/LoginDTO.md) - [MapDTO](doc\/MapDTO.md) - - [MapType](doc\/MapType.md) + - [MapTypeApp](doc\/MapTypeApp.md) - [MenuDTO](doc\/MenuDTO.md) - [ResourceDTO](doc\/ResourceDTO.md) - [ResourceDetailDTO](doc\/ResourceDetailDTO.md) diff --git a/manager_api/doc/DeviceDTO.md b/manager_api/doc/DeviceDTO.md index 0004f9f..62df565 100644 --- a/manager_api/doc/DeviceDTO.md +++ b/manager_api/doc/DeviceDTO.md @@ -9,6 +9,7 @@ import 'package:managerapi/api.dart'; Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **id** | **String** | | [optional] +**identifier** | **String** | | [optional] **name** | **String** | | [optional] **ipAddressWLAN** | **String** | | [optional] **ipAddressETH** | **String** | | [optional] @@ -16,6 +17,7 @@ Name | Type | Description | Notes **configuration** | **String** | | [optional] **connected** | **bool** | | [optional] **dateCreation** | [**DateTime**](DateTime.md) | | [optional] +**dateUpdate** | [**DateTime**](DateTime.md) | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/manager_api/doc/DeviceDetailDTO.md b/manager_api/doc/DeviceDetailDTO.md index fa40fcd..4968995 100644 --- a/manager_api/doc/DeviceDetailDTO.md +++ b/manager_api/doc/DeviceDetailDTO.md @@ -9,6 +9,7 @@ import 'package:managerapi/api.dart'; Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **id** | **String** | | [optional] +**identifier** | **String** | | [optional] **name** | **String** | | [optional] **ipAddressWLAN** | **String** | | [optional] **ipAddressETH** | **String** | | [optional] @@ -16,6 +17,7 @@ Name | Type | Description | Notes **configuration** | **String** | | [optional] **connected** | **bool** | | [optional] **dateCreation** | [**DateTime**](DateTime.md) | | [optional] +**dateUpdate** | [**DateTime**](DateTime.md) | | [optional] **connectionLevel** | **String** | | [optional] **lastConnectionLevel** | [**DateTime**](DateTime.md) | | [optional] **batteryLevel** | **String** | | [optional] diff --git a/manager_api/doc/MapDTO.md b/manager_api/doc/MapDTO.md index 107bd50..656bd08 100644 --- a/manager_api/doc/MapDTO.md +++ b/manager_api/doc/MapDTO.md @@ -9,7 +9,7 @@ import 'package:managerapi/api.dart'; Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **zoom** | **int** | | [optional] -**mapType** | [**MapType**](MapType.md) | | [optional] +**mapType** | [**MapTypeApp**](MapTypeApp.md) | | [optional] **points** | [**List**](GeoPointDTO.md) | | [optional] [default to const []] **iconResourceId** | **String** | | [optional] **iconSource** | **String** | | [optional] diff --git a/manager_api/doc/MapTypeApp.md b/manager_api/doc/MapTypeApp.md new file mode 100644 index 0000000..4d1d1a4 --- /dev/null +++ b/manager_api/doc/MapTypeApp.md @@ -0,0 +1,14 @@ +# managerapi.model.MapTypeApp + +## Load the model package +```dart +import 'package:managerapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/manager_api/lib/api.dart b/manager_api/lib/api.dart index a984d28..ae74ca1 100644 --- a/manager_api/lib/api.dart +++ b/manager_api/lib/api.dart @@ -43,7 +43,7 @@ part 'model/image_dto.dart'; part 'model/image_geo_point.dart'; part 'model/login_dto.dart'; part 'model/map_dto.dart'; -part 'model/map_type.dart'; +part 'model/map_type_app.dart'; part 'model/menu_dto.dart'; part 'model/resource_dto.dart'; part 'model/resource_detail_dto.dart'; diff --git a/manager_api/lib/api_client.dart b/manager_api/lib/api_client.dart index 86c28f2..b2e9dc9 100644 --- a/manager_api/lib/api_client.dart +++ b/manager_api/lib/api_client.dart @@ -174,8 +174,8 @@ class ApiClient { return LoginDTO.fromJson(value); case 'MapDTO': return MapDTO.fromJson(value); - case 'MapType': - return MapTypeTypeTransformer().decode(value); + case 'MapTypeApp': + return MapTypeAppTypeTransformer().decode(value); case 'MenuDTO': return MenuDTO.fromJson(value); diff --git a/manager_api/lib/api_helper.dart b/manager_api/lib/api_helper.dart index 563f194..1f73cef 100644 --- a/manager_api/lib/api_helper.dart +++ b/manager_api/lib/api_helper.dart @@ -58,8 +58,8 @@ String parameterToString(dynamic value) { if (value is DateTime) { return value.toUtc().toIso8601String(); } - if (value is MapType) { - return MapTypeTypeTransformer().encode(value).toString(); + if (value is MapTypeApp) { + return MapTypeAppTypeTransformer().encode(value).toString(); } if (value is ResourceType) { return ResourceTypeTypeTransformer().encode(value).toString(); diff --git a/manager_api/lib/model/device_detail_dto.dart b/manager_api/lib/model/device_detail_dto.dart index f936a30..f8b686c 100644 --- a/manager_api/lib/model/device_detail_dto.dart +++ b/manager_api/lib/model/device_detail_dto.dart @@ -13,6 +13,7 @@ class DeviceDetailDTO { /// Returns a new [DeviceDetailDTO] instance. DeviceDetailDTO({ this.id, + this.identifier, this.name, this.ipAddressWLAN, this.ipAddressETH, @@ -20,6 +21,7 @@ class DeviceDetailDTO { this.configuration, this.connected, this.dateCreation, + this.dateUpdate, this.connectionLevel, this.lastConnectionLevel, this.batteryLevel, @@ -28,6 +30,8 @@ class DeviceDetailDTO { String id; + String identifier; + String name; String ipAddressWLAN; @@ -42,6 +46,8 @@ class DeviceDetailDTO { DateTime dateCreation; + DateTime dateUpdate; + String connectionLevel; DateTime lastConnectionLevel; @@ -53,6 +59,7 @@ class DeviceDetailDTO { @override bool operator ==(Object other) => identical(this, other) || other is DeviceDetailDTO && other.id == id && + other.identifier == identifier && other.name == name && other.ipAddressWLAN == ipAddressWLAN && other.ipAddressETH == ipAddressETH && @@ -60,6 +67,7 @@ class DeviceDetailDTO { other.configuration == configuration && other.connected == connected && other.dateCreation == dateCreation && + other.dateUpdate == dateUpdate && other.connectionLevel == connectionLevel && other.lastConnectionLevel == lastConnectionLevel && other.batteryLevel == batteryLevel && @@ -68,6 +76,7 @@ class DeviceDetailDTO { @override int get hashCode => (id == null ? 0 : id.hashCode) + + (identifier == null ? 0 : identifier.hashCode) + (name == null ? 0 : name.hashCode) + (ipAddressWLAN == null ? 0 : ipAddressWLAN.hashCode) + (ipAddressETH == null ? 0 : ipAddressETH.hashCode) + @@ -75,19 +84,23 @@ class DeviceDetailDTO { (configuration == null ? 0 : configuration.hashCode) + (connected == null ? 0 : connected.hashCode) + (dateCreation == null ? 0 : dateCreation.hashCode) + + (dateUpdate == null ? 0 : dateUpdate.hashCode) + (connectionLevel == null ? 0 : connectionLevel.hashCode) + (lastConnectionLevel == null ? 0 : lastConnectionLevel.hashCode) + (batteryLevel == null ? 0 : batteryLevel.hashCode) + (lastBatteryLevel == null ? 0 : lastBatteryLevel.hashCode); @override - String toString() => 'DeviceDetailDTO[id=$id, name=$name, ipAddressWLAN=$ipAddressWLAN, ipAddressETH=$ipAddressETH, configurationId=$configurationId, configuration=$configuration, connected=$connected, dateCreation=$dateCreation, connectionLevel=$connectionLevel, lastConnectionLevel=$lastConnectionLevel, batteryLevel=$batteryLevel, lastBatteryLevel=$lastBatteryLevel]'; + String toString() => 'DeviceDetailDTO[id=$id, identifier=$identifier, name=$name, ipAddressWLAN=$ipAddressWLAN, ipAddressETH=$ipAddressETH, configurationId=$configurationId, configuration=$configuration, connected=$connected, dateCreation=$dateCreation, dateUpdate=$dateUpdate, connectionLevel=$connectionLevel, lastConnectionLevel=$lastConnectionLevel, batteryLevel=$batteryLevel, lastBatteryLevel=$lastBatteryLevel]'; Map toJson() { final json = {}; if (id != null) { json[r'id'] = id; } + if (identifier != null) { + json[r'identifier'] = identifier; + } if (name != null) { json[r'name'] = name; } @@ -109,6 +122,9 @@ class DeviceDetailDTO { if (dateCreation != null) { json[r'dateCreation'] = dateCreation.toUtc().toIso8601String(); } + if (dateUpdate != null) { + json[r'dateUpdate'] = dateUpdate.toUtc().toIso8601String(); + } if (connectionLevel != null) { json[r'connectionLevel'] = connectionLevel; } @@ -130,6 +146,7 @@ class DeviceDetailDTO { ? null : DeviceDetailDTO( id: json[r'id'], + identifier: json[r'identifier'], name: json[r'name'], ipAddressWLAN: json[r'ipAddressWLAN'], ipAddressETH: json[r'ipAddressETH'], @@ -139,6 +156,9 @@ class DeviceDetailDTO { dateCreation: json[r'dateCreation'] == null ? null : DateTime.parse(json[r'dateCreation']), + dateUpdate: json[r'dateUpdate'] == null + ? null + : DateTime.parse(json[r'dateUpdate']), connectionLevel: json[r'connectionLevel'], lastConnectionLevel: json[r'lastConnectionLevel'] == null ? null diff --git a/manager_api/lib/model/device_dto.dart b/manager_api/lib/model/device_dto.dart index ff51a82..19a5677 100644 --- a/manager_api/lib/model/device_dto.dart +++ b/manager_api/lib/model/device_dto.dart @@ -13,6 +13,7 @@ class DeviceDTO { /// Returns a new [DeviceDTO] instance. DeviceDTO({ this.id, + this.identifier, this.name, this.ipAddressWLAN, this.ipAddressETH, @@ -20,10 +21,13 @@ class DeviceDTO { this.configuration, this.connected, this.dateCreation, + this.dateUpdate, }); String id; + String identifier; + String name; String ipAddressWLAN; @@ -38,36 +42,45 @@ class DeviceDTO { DateTime dateCreation; + DateTime dateUpdate; + @override bool operator ==(Object other) => identical(this, other) || other is DeviceDTO && other.id == id && + other.identifier == identifier && other.name == name && other.ipAddressWLAN == ipAddressWLAN && other.ipAddressETH == ipAddressETH && other.configurationId == configurationId && other.configuration == configuration && other.connected == connected && - other.dateCreation == dateCreation; + other.dateCreation == dateCreation && + other.dateUpdate == dateUpdate; @override int get hashCode => (id == null ? 0 : id.hashCode) + + (identifier == null ? 0 : identifier.hashCode) + (name == null ? 0 : name.hashCode) + (ipAddressWLAN == null ? 0 : ipAddressWLAN.hashCode) + (ipAddressETH == null ? 0 : ipAddressETH.hashCode) + (configurationId == null ? 0 : configurationId.hashCode) + (configuration == null ? 0 : configuration.hashCode) + (connected == null ? 0 : connected.hashCode) + - (dateCreation == null ? 0 : dateCreation.hashCode); + (dateCreation == null ? 0 : dateCreation.hashCode) + + (dateUpdate == null ? 0 : dateUpdate.hashCode); @override - String toString() => 'DeviceDTO[id=$id, name=$name, ipAddressWLAN=$ipAddressWLAN, ipAddressETH=$ipAddressETH, configurationId=$configurationId, configuration=$configuration, connected=$connected, dateCreation=$dateCreation]'; + String toString() => 'DeviceDTO[id=$id, identifier=$identifier, name=$name, ipAddressWLAN=$ipAddressWLAN, ipAddressETH=$ipAddressETH, configurationId=$configurationId, configuration=$configuration, connected=$connected, dateCreation=$dateCreation, dateUpdate=$dateUpdate]'; Map toJson() { final json = {}; if (id != null) { json[r'id'] = id; } + if (identifier != null) { + json[r'identifier'] = identifier; + } if (name != null) { json[r'name'] = name; } @@ -89,6 +102,9 @@ class DeviceDTO { if (dateCreation != null) { json[r'dateCreation'] = dateCreation.toUtc().toIso8601String(); } + if (dateUpdate != null) { + json[r'dateUpdate'] = dateUpdate.toUtc().toIso8601String(); + } return json; } @@ -98,6 +114,7 @@ class DeviceDTO { ? null : DeviceDTO( id: json[r'id'], + identifier: json[r'identifier'], name: json[r'name'], ipAddressWLAN: json[r'ipAddressWLAN'], ipAddressETH: json[r'ipAddressETH'], @@ -107,6 +124,9 @@ class DeviceDTO { dateCreation: json[r'dateCreation'] == null ? null : DateTime.parse(json[r'dateCreation']), + dateUpdate: json[r'dateUpdate'] == null + ? null + : DateTime.parse(json[r'dateUpdate']), ); static List listFromJson(List json, {bool emptyIsNull, bool growable,}) => diff --git a/manager_api/lib/model/map_dto.dart b/manager_api/lib/model/map_dto.dart index 40c624c..f8e229d 100644 --- a/manager_api/lib/model/map_dto.dart +++ b/manager_api/lib/model/map_dto.dart @@ -21,7 +21,7 @@ class MapDTO { int zoom; - MapType mapType; + MapTypeApp mapType; List points; @@ -74,7 +74,7 @@ class MapDTO { ? null : MapDTO( zoom: json[r'zoom'], - mapType: MapType.fromJson(json[r'mapType']), + mapType: MapTypeApp.fromJson(json[r'mapType']), points: GeoPointDTO.listFromJson(json[r'points']), iconResourceId: json[r'iconResourceId'], iconSource: json[r'iconSource'], diff --git a/manager_api/lib/model/map_type_app.dart b/manager_api/lib/model/map_type_app.dart new file mode 100644 index 0000000..893968e --- /dev/null +++ b/manager_api/lib/model/map_type_app.dart @@ -0,0 +1,85 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.0 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + + +class MapTypeApp { + /// Instantiate a new enum with the provided [value]. + const MapTypeApp._(this.value); + + /// The underlying value of this enum member. + final String value; + + @override + String toString() => value; + + String toJson() => value; + + static const none = MapTypeApp._(r'none'); + static const normal = MapTypeApp._(r'normal'); + static const satellite = MapTypeApp._(r'satellite'); + static const terrain = MapTypeApp._(r'terrain'); + static const hybrid = MapTypeApp._(r'hybrid'); + + /// List of all possible values in this [enum][MapTypeApp]. + static const values = [ + none, + normal, + satellite, + terrain, + hybrid, + ]; + + static MapTypeApp fromJson(dynamic value) => + MapTypeAppTypeTransformer().decode(value); + + static List listFromJson(List json, {bool emptyIsNull, bool growable,}) => + json == null || json.isEmpty + ? true == emptyIsNull ? null : [] + : json + .map((value) => MapTypeApp.fromJson(value)) + .toList(growable: true == growable); +} + +/// Transformation class that can [encode] an instance of [MapTypeApp] to String, +/// and [decode] dynamic data back to [MapTypeApp]. +class MapTypeAppTypeTransformer { + const MapTypeAppTypeTransformer._(); + + factory MapTypeAppTypeTransformer() => _instance ??= MapTypeAppTypeTransformer._(); + + String encode(MapTypeApp data) => data.value; + + /// Decodes a [dynamic value][data] to a MapTypeApp. + /// + /// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully, + /// then null is returned. However, if [allowNull] is false and the [dynamic value][data] + /// cannot be decoded successfully, then an [UnimplementedError] is thrown. + /// + /// The [allowNull] is very handy when an API changes and a new enum value is added or removed, + /// and users are still using an old app with the old code. + MapTypeApp decode(dynamic data, {bool allowNull}) { + switch (data) { + case r'none': return MapTypeApp.none; + case r'normal': return MapTypeApp.normal; + case r'satellite': return MapTypeApp.satellite; + case r'terrain': return MapTypeApp.terrain; + case r'hybrid': return MapTypeApp.hybrid; + default: + if (allowNull == false) { + throw ArgumentError('Unknown enum value to decode: $data'); + } + } + return null; + } + + /// Singleton [MapTypeAppTypeTransformer] instance. + static MapTypeAppTypeTransformer _instance; +} diff --git a/manager_api/swagger.yaml b/manager_api/swagger.yaml index adc429b..a28aa3b 100644 --- a/manager_api/swagger.yaml +++ b/manager_api/swagger.yaml @@ -1298,6 +1298,9 @@ components: id: type: string nullable: true + identifier: + type: string + nullable: true name: type: string nullable: true @@ -1318,6 +1321,9 @@ components: dateCreation: type: string format: date-time + dateUpdate: + type: string + format: date-time DeviceDetailDTO: allOf: - $ref: '#/components/schemas/DeviceDTO' @@ -1460,7 +1466,7 @@ components: type: integer format: int32 mapType: - $ref: '#/components/schemas/MapType' + $ref: '#/components/schemas/MapTypeApp' points: type: array nullable: true @@ -1472,7 +1478,7 @@ components: iconSource: type: string nullable: true - MapType: + MapTypeApp: type: string description: '' x-enumNames: diff --git a/manager_api/test/map_type_app_test.dart b/manager_api/test/map_type_app_test.dart new file mode 100644 index 0000000..4145313 --- /dev/null +++ b/manager_api/test/map_type_app_test.dart @@ -0,0 +1,20 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.0 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: lines_longer_than_80_chars + +import 'package:managerapi/api.dart'; +import 'package:test/test.dart'; + +// tests for MapTypeApp +void main() { + + group('test MapTypeApp', () { + + }); + +} diff --git a/pubspec.lock b/pubspec.lock index 31a5cc1..ce526dd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -210,6 +210,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.1" + sqflite: + dependency: "direct main" + description: + name: sqflite + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0+3" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0+2" stack_trace: dependency: transitive description: @@ -238,6 +252,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.0" + synchronized: + dependency: transitive + description: + name: synchronized + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" term_glyph: dependency: transitive description: @@ -259,6 +280,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0" + unique_identifier: + dependency: "direct main" + description: + name: unique_identifier + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.3" vector_math: dependency: transitive description: @@ -272,7 +300,7 @@ packages: name: webview_flutter url: "https://pub.dartlang.org" source: hosted - version: "2.0.9" + version: "2.0.10" sdks: dart: ">=2.12.0 <3.0.0" flutter: ">=2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 47a5d1b..e77ba5f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -23,6 +23,7 @@ environment: dependencies: flutter: sdk: flutter + sqflite: webview_flutter: ^2.0.2 google_maps_flutter: ^2.0.1 flare_flutter: ^3.0.1 @@ -30,6 +31,7 @@ dependencies: http: ^0.12.2 auto_size_text: ^2.1.0 fluttertoast: + unique_identifier: ^0.0.3 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons.