import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; import 'datamodel.dart'; import 'package:http/http.dart' as http; import 'sensorconnector.dart'; class ViewEvents extends StatefulWidget { const ViewEvents({Key? key}) : super(key: key); @override _ViewEvents createState() => _ViewEvents(); } class _ViewEvents extends State<ViewEvents> { // Get singleton to access locally stored events: EventStoreInstance _events = EventStoreInstance(); String _sync_status = ''; //TODO: add exception handling and display exceptions to user. @override void initState() { _sync_status = _events.getPendingEventCount().toString() + ' event(s) pending'; super.initState(); //TODO: Query all events from database everytime this widget is opened. Remove local event storage instance! } Future<void> syncEvents() async { final ConfigurationStoreInstance configuration = ConfigurationStoreInstance(); SensorConnector connection = SensorConnector(); int syncCounter = _events.getPendingEventCount();; //For displaying progress during event upload if(syncCounter > 0) { try { String? token = await connection.getAuthToken( configuration.loginInformation.mail, configuration.loginInformation.password); if (token != null) { debugPrint('Number of Events: ' + _events.events.length.toString()); debugPrint('Number of Pending Events: ' + syncCounter.toString()); var index = 0; for (var event in _events.events) { if (event.status == 'PENDING') { //TODO: only query events which are 'PENDING' from database. debugPrint('Idx: ' + index.toString() + ' ' + event.toSensorJson().toString()); index++; if (await connection.putEvent(event, token) == true) { //Event has been posted to Sensor. syncCounter--; debugPrint( 'put success, remaining events: ' + syncCounter.toString()); event.status = 'EXPORTED'; //Update event export only once //TODO: move to database and update event based in primary row id. setState(() {}); } else { throw Exception('Sync for ' + event.urn + 'failed'); } } } _sync_status = 'export success'; } } on SocketException catch (e) { debugPrint('Exception: $e'); _sync_status = 'No connection'; setState(() {}); } catch (e) { debugPrint('Exception: $e'); _sync_status = '$e'; setState(() {}); } }else{ debugPrint('Nothing to export'); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("View & Sync"), ), body: Container( margin: const EdgeInsets.symmetric(horizontal: 5.0), child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: SingleChildScrollView( scrollDirection: Axis.vertical, child: DataTable( columns: const <DataColumn>[ DataColumn( label: Text( 'Id', style: TextStyle(fontStyle: FontStyle.italic), ), ), DataColumn( label: Text( 'URN', style: TextStyle(fontStyle: FontStyle.italic), ), ), DataColumn( label: Text( 'Label', style: TextStyle(fontStyle: FontStyle.italic), ), ), DataColumn( label: Text( 'Type', style: TextStyle(fontStyle: FontStyle.italic), ), ), DataColumn( label: Text( 'Description', style: TextStyle(fontStyle: FontStyle.italic), ), ), DataColumn( label: Text( 'StartDate', style: TextStyle(fontStyle: FontStyle.italic), ), ), DataColumn( label: Text( 'EndDate', style: TextStyle(fontStyle: FontStyle.italic), ), ), DataColumn( label: Text( 'Latitude', style: TextStyle(fontStyle: FontStyle.italic), ), ), DataColumn( label: Text( 'Longitude', style: TextStyle(fontStyle: FontStyle.italic), ), ), DataColumn( label: Text( 'Elevation', style: TextStyle(fontStyle: FontStyle.italic), ), ), DataColumn( label: Text( 'Status', style: TextStyle(fontStyle: FontStyle.italic), ), ), ], rows: <DataRow>[ for (var event in _events.events) DataRow( cells: <DataCell>[ DataCell(Text(event.id.toString())), DataCell(Text(event.urn)), DataCell( TextFormField( readOnly: true, initialValue: event.label, onFieldSubmitted: (val) { event.label = val; //Update Database }, ), ), DataCell(Text(event.type)), DataCell( TextFormField( readOnly: true, initialValue: event.description, onFieldSubmitted: (val) { event.description = val; //Update Database }, ), ), DataCell(Text(event.startDate)), DataCell(Text(event.endDate)), DataCell( TextFormField( readOnly: true, initialValue: event.latitude, onFieldSubmitted: (val) { event.latitude = val; //Update Database }, ), ), DataCell( TextFormField( readOnly: true, initialValue: event.longitude, onFieldSubmitted: (val) { event.longitude = val; //Update Database }, ), ), DataCell( TextFormField( readOnly: true, initialValue: event.elevation, onFieldSubmitted: (val) { event.elevation = val; //Update Database }, ), ), DataCell( TextFormField( readOnly: true, controller: TextEditingController( //Required to update field here text: event.status, ), onFieldSubmitted: (val) { event.status = val; //Update Database }, ), ), ], ), ], ), ), ), ), bottomNavigationBar: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ const SizedBox(width: 10), Text(_sync_status), const SizedBox(width: 50), Container( margin: const EdgeInsets.symmetric(vertical: 10.0), child: FloatingActionButton.extended( heroTag: null, tooltip: 'Upload Events', icon: null, label: const Text('Sync'), onPressed: () { debugPrint(_events.getEventDump()); syncEvents(); }, ), ), const SizedBox(width: 5.0), ], ), ); } } //TODO: allow editing fields here. Check validation of input value!