Newer
Older
import 'package:flutter/material.dart';
import 'datamodel.dart';
import 'sensorconnector.dart';
import 'package:getwidget/getwidget.dart';
class ViewEvents extends StatefulWidget {
const ViewEvents({Key? key}) : super(key: key);
@override
_ViewEvents createState() => _ViewEvents();
}
final EventStoreInstance _events = EventStoreInstance();
String _status = '';
TextStyle _statusStyle = const TextStyle(color: Colors.black);

Maximilian Betz
committed
String _appBarText = '';
int _selectedRow = -1;
String _pendingEventCnt = '';
String _syncedEventCnt = '';
bool _cancelSync = false; //Flag to cancel sync process
bool _currentlySyncing = false; // State flag to indicate if sync is ongoing
Widget _buildSyncDialog(BuildContext context) {
SensorConnector sensorConnector = SensorConnector();
String startButtonText = '';
String closeButtonText = '';
if (_currentlySyncing == true){
startButtonText = 'Syncing';
closeButtonText = 'Cancel';
}else{
startButtonText = 'Start';
closeButtonText = 'Close';
}
return WillPopScope(
onWillPop: () async => false,
child: AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const Text('Syncing Events...'),
const SizedBox(height: 15.0),
GFProgressBar(
percentage: 0.7, //Get percentage from global variable here
backgroundColor : Colors.black12,
progressBarColor: Colors.blue,
),
const SizedBox(height: 5.0),
Text(_syncedEventCnt + ' / ' + _pendingEventCnt),
//TODO: show text XX pending events. count down
],
),
actions: <Widget>[
TextButton(
onPressed: () {
if(_currentlySyncing == false){
syncEvents(); //Initiate sync
}
child: Text(startButtonText), //Change text to Syncing... during Sync process.
),
TextButton(
onPressed: () {
// Depending on state. Cancel or close. TODO: implement statemachine.
if(_currentlySyncing){
_cancelSync = true; // Set flag so that async tasks stops syncing
}else{
Navigator.of(context).pop(); // Close widget only if sync has stopped.
}
child: Text(closeButtonText), // Change to Cancel during Sync process.

Maximilian Betz
committed
final EventStoreInstance event = EventStoreInstance();
int pendingEvents = 0;
if (event.showAllEvents == false) {
_appBarText = 'Pending Events';
//Get only pending events
_localEvents = await database.getPendingEvents();
pendingEvents = _localEvents.length;
}else {
_appBarText = 'All Events';
_localEvents = await database.getEvents();
pendingEvents = await database.getPendingEventCnt();
}
_status = pendingEvents.toString() + ' event(s) pending';
_statusStyle = const TextStyle(color: Colors.black);

Maximilian Betz
committed
setState(() {}); //Got events from database, so update UI
@override
void initState() {
super.initState();
@override
void dispose() async {
/*Async update current configuration to shared preferences*/
final EventStoreInstance event = EventStoreInstance();
event.storeToSharedPrefs();
super.dispose();
}
final ConfigurationStoreInstance configuration = ConfigurationStoreInstance();
SensorConnector connection = SensorConnector();
List<Event> events = await database.getPendingEvents();
int syncCounter = events.length;
_pendingEventCnt = syncCounter.toString();
debugPrint('Pending Events');
for (var event in events){
debugPrint(event.toString());
}
if(syncCounter > 0) {
try {
String? token = await connection.getAuthToken(
configuration.loginInformation.mail,
configuration.loginInformation.password);
var index = 0;
for (var event in events) {
if(_cancelSync == true){
_currentlySyncing = false;
debugPrint('Sync process canceled');
return;
}
_currentlySyncing = true;
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 to export only once
database.updateEvent(event); //Update Event as exported in SQL Database
await fetchEventsFromDb(); //update view list //TODO: this is bad for the sync performance!
setState(() {});
} else {
throw Exception('Sync for ' + event.urn + 'failed');
_status = 'export success';
_statusStyle = const TextStyle(color: Colors.green);
_syncedEventCnt = index.toString();
String errorText = e.toString();
errorText = errorText.substring(10, errorText.length); //Remove 'Exception' from string.
_status = errorText;
_statusStyle = const TextStyle(color: Colors.red);
debugPrint('No PENDING event(s)');
@override
Widget build(BuildContext context) {

Maximilian Betz
committed
final EventStoreInstance event = EventStoreInstance();
return Scaffold(
appBar: AppBar(

Maximilian Betz
committed
actions: <Widget>[
Text(_appBarText, style: const TextStyle(fontStyle: FontStyle.italic),),
Switch( //Enable showing all or only pending events. Default is to show only pending events
value: event.showAllEvents,
onChanged: (value) {
event.showAllEvents = value;
fetchEventsFromDb();
setState(() {});
}),
],
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) 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),
),
//for (var event in _localEvents)
for (var i = 0; i < _localEvents.length; i++)
selected: i == _selectedRow,
onLongPress: () {
debugPrint("Selected Row: " + i.toString());
//TODO: open widget to edit the rows event values. Provide "cancel" and "update" functionality
//TODO: display "Exported Events are read only, Edit via Sensor.awi.de" when trying to edit.
debugPrint(_localEvents[i].toString());
//Navigator.pushNamed(context, '/second', arguments: {'event': _localEvents[i]},);
// TODO: create an edit widget. As Add Event, GNSS editing always enabled, No GNSS switch, Now Button?
/* //How to get the argument.
@override
Widget build(BuildContext context) {
final arguments = (ModalRoute.of(context)?.settings.arguments ?? <String, dynamic>{}) as Map;
print(arguments['exampleArgument']);
return Scaffold(...);
}
*/
},
//DataCell(Text(_localEvents[i].urnId.toString())),
DataCell(Text('('+_localEvents[i].urnId.toString()+') ' + _localEvents[i].urn)),
Text(_localEvents[i].label),
DataCell(Text(_localEvents[i].type)),
DataCell(Text(_localEvents[i].description)),

Maximilian Betz
committed
//Do not show microseconds
DataCell(Text(_localEvents[i].startDate.substring(0, 19) + 'Z')),
DataCell(Text(_localEvents[i].endDate.substring(0, 19) + 'Z')),
DataCell(Text(_localEvents[i].latitude)),
DataCell(Text(_localEvents[i].longitude)),
DataCell(Text(_localEvents[i].elevation == '' ? '' : double.parse(_localEvents[i].elevation).toStringAsFixed(2))),
DataCell(Text(_localEvents[i].status)),
bottomNavigationBar: Container(
margin: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const SizedBox(width: 1),
Text(_status, style: _statusStyle),
FloatingActionButton.extended(
heroTag: null,
tooltip: 'Upload Events',
icon: null,
label: const Text('Sync'),
onPressed: () {
//showDialog(
// barrierDismissible: false,
// context: context,
// builder: (BuildContext context) => _buildSyncDialog(context),
//);
],
),