frontend/frontend-flutter/lib/screens/settings.dart (441 lines of code) (raw):
import 'dart:convert';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_settings_ui/flutter_settings_ui.dart';
import 'package:flutter/material.dart';
import '../services/display_stepper/display_stepper_cubit.dart';
import '../utils/TextToDocParameter.dart';
import 'package:flutter/services.dart';
class Settings extends StatefulWidget {
Settings(FirebaseFirestore this.db, {Key? key}) : super(key: key);
bool useFeedback = false;
bool useColorMode = false;
bool useDashboards = false;
bool useReports = false;
bool useExpertMode = false;
bool useLog = false;
bool useAnonymizedMode = false;
static bool isLoadConfig = false;
static bool isUseFeedback = false;
static bool isUseColorMode = false;
static bool isUseDashboards = false;
static bool isUseReports = false;
static bool isExpert = false;
static bool isUseLog = false;
static bool isAnonymizedMode = false;
FirebaseFirestore db;
@override
State<Settings> createState() => SettingsState();
}
class SettingsState extends State<Settings> {
@override
Widget build(BuildContext context) {
print("Settings : build() : START");
print("Settings : build() : widget.db = ${widget.db}");
return Scaffold(
appBar: AppBar(
title: Text('Open data QnA',
style:
TextStyle(fontWeight: FontWeight.bold, color: Colors.purple)),
centerTitle: false,
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context, Settings.isExpert);
},
),
actions: [
Padding(
padding: const EdgeInsets.only(right: 100),
child: IconButton(
icon: Image.asset('assets/images/cymbal_logo.png'),
onPressed: () {
;
},
),
),
],
),
body: SettingsList(
sections: [
SettingsSection(
title: Text('General',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
tiles: [
SettingsTile.switchTile(
initialValue: TextToDocParameter.isLoadConfig,
onToggle: (value) {
setState(() {
//Settings.isLoadConfig = value;
TextToDocParameter.isLoadConfig = value;
print(
"Settings : build() : TextToDocParameter.isLoadConfig = ${TextToDocParameter.isLoadConfig}");
importFrontEndCfgFile();
});
},
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Image.asset(
'assets/images/config_frontend.png',
height: 70,
width: 70,
fit: BoxFit.cover,
),
Container(width: 20),
Text('Upload frontend config file'),
],
),
description: Text("Set required app's parameters"),
),
SettingsTile.switchTile(
initialValue: widget.useFeedback,
onToggle: (value) {
setState(() {
//useFeedback = value;
});
},
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Image.asset(
'assets/images/feedback.png',
height: 70,
width: 70,
fit: BoxFit.cover,
),
Container(width: 20),
Text('Feedback (not implemented yet)'),
],
),
description: Text('Send feedback on generated answers'),
),
SettingsTile.switchTile(
initialValue: widget.useColorMode,
onToggle: (value) {
setState(() {
//useColorMode = value;
});
},
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Image.asset(
'assets/images/color_mode.png',
height: 70,
width: 70,
fit: BoxFit.cover,
),
Container(width: 20),
Text('Enable dark mode (not implemented yet)'),
],
)),
SettingsTile.switchTile(
initialValue: TextToDocParameter.anonymized_data,//Settings.isAnonymizedMode,
onToggle: (value) {
setState(() {
//Settings.isAnonymizedMode = value;
TextToDocParameter.anonymized_data = value;
//print("Settings : build() : widget.useExpertMode = ${widget.useExpertMode}");
print(
"Settings : build() : TextToDocParameter.anonymized_data = ${TextToDocParameter.anonymized_data}");
updateFrontEndFlutterCfg(parameter: "anonymized_data", value: value);
});
},
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Image.asset(
'assets/images/anonymized.jpeg',
height: 70,
width: 70,
fit: BoxFit.cover,
),
Container(width: 20),
Text('Enable anonymization of data'),
],
)),
],
),
SettingsSection(
title: Text('Statistics',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
tiles: [
SettingsTile.switchTile(
initialValue: widget.useDashboards,
onToggle: (value) {
setState(() {
//useDashboards = value;
});
},
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Image.asset(
'assets/images/statistics.png',
height: 70,
width: 70,
fit: BoxFit.cover,
),
Container(width: 20),
Text('Dashboards (not implemented yet)'),
],
),
description: Text('Get visibility on activities'),
),
SettingsTile.switchTile(
initialValue: widget.useReports,
onToggle: (value) {
setState(() {
//useReports = value;
});
},
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Image.asset(
'assets/images/reports.png',
height: 70,
width: 70,
fit: BoxFit.cover,
),
Container(width: 20),
Text('Reports (not implemented yet)'),
],
),
description: Text('Export activity reports in pdf'),
),
],
),
SettingsSection(
title: Text('Troubleshooting',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
tiles: [
SettingsTile.switchTile(
initialValue: TextToDocParameter.expert_mode,//Settings.isExpert,
onToggle: (value) {
setState(() {
//widget.useExpertMode = value;
//Settings.isExpert = value;
TextToDocParameter.expert_mode = value;
//Config.isExpert = value;
//print("Settings : build() : widget.useExpertMode = ${widget.useExpertMode}");
print(
"Settings : build() : TextToDocParameter.expert_mode = ${TextToDocParameter.expert_mode}");
BlocProvider.of<DisplayStepperCubit>(context).displayStepper(value);
});
updateFrontEndFlutterCfg(parameter: "expert_mode", value: value);
},
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Image.asset(
'assets/images/troubleshooting.png',
height: 70,
width: 70,
fit: BoxFit.cover,
),
Container(width: 20),
Text('Expert mode'),
],
),
description: Text(
'Get workflow details and internal technical informations'),
),
SettingsTile.switchTile(
initialValue: widget.useLog,
onToggle: (value) {
setState(() {
//useLog = value;
});
},
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Image.asset(
'assets/images/logs.png',
height: 70,
width: 70,
fit: BoxFit.cover,
),
Container(width: 20),
Text('Enable logs (not implemented yet)'),
],
),
description: Text('Generate logs for troubleshooting'),
),
],
),
],
),
);
}
void importFrontEndCfgFile() async {
print('Settings: importFrontEndCfgFile() : START');
List<List<dynamic>>? rowsAsListOfValues;
final filePickerResult = await FilePicker.platform.pickFiles(
allowMultiple: false,
allowedExtensions: ['json'],
type: FileType.custom,
dialogTitle: "Import Frontend json Config File",
);
if (filePickerResult != null) {
print(
'Settings: importFrontEndCfgFile() : fileName = ${filePickerResult.files.single.name}');
print(
'Settings: importFrontEndCfgFile() : size = ${filePickerResult.files.single.size}');
//print('Settings: importFrontEndCfgFile() : path = ${filePickerResult.files.single.path}');
Uint8List fileBytes = filePickerResult.files.single.bytes!;
String fileContent = utf8.decode(fileBytes);
print('Settings: importFrontEndCfgFile() : fileContent = ${fileContent}');
var cfg = jsonDecode(fileContent);
print('Settings: importFrontEndCfgFile() : cfg = ${cfg}');
if (cfg != null) {
setState(() {
TextToDocParameter.isLoadConfig = false;
TextToDocParameter.anonymized_data = cfg["anonymized_data"];
TextToDocParameter.expert_mode = cfg["expert_mode"];
TextToDocParameter.endpoint_opendataqnq = cfg["endpoint_opendataqnq"];
TextToDocParameter.firestore_database_id = cfg["firestore_database_id"];
TextToDocParameter.firebase_app_name = cfg["firebase_app_name"];
TextToDocParameter.firestore_history_collection = cfg["firestore_history_collection"];
TextToDocParameter.firestore_cfg_collection = cfg["firestore_cfg_collection"];
TextToDocParameter.imported_questions = cfg["imported_questions"];
});
if (TextToDocParameter.anonymized_data != null &&
TextToDocParameter.expert_mode != null &&
TextToDocParameter.endpoint_opendataqnq != null &&
TextToDocParameter.firestore_database_id != null &&
TextToDocParameter.firebase_app_name != null &&
TextToDocParameter.firestore_history_collection != null &&
TextToDocParameter.firestore_cfg_collection != null &&
TextToDocParameter.imported_questions != null
) {
print('Settings: importFrontEndCfgFile() : Trying to update front_end_flutter_cfg');
try {
widget.db
.collection("${TextToDocParameter.firestore_cfg_collection}")
.doc('${TextToDocParameter.userID}')
.set({
"endpoint_opendataqnq":
"${TextToDocParameter.endpoint_opendataqnq}",
"firestore_database_id":
"${TextToDocParameter.firestore_database_id}",
"expert_mode": TextToDocParameter.expert_mode,
"anonymized_data": TextToDocParameter.anonymized_data,
"firebase_app_name": "${TextToDocParameter.firebase_app_name}",
"firestore_history_collection": "${TextToDocParameter.firestore_history_collection}",
"firestore_cfg_collection": "${TextToDocParameter.firestore_cfg_collection}",
"imported_questions": "${TextToDocParameter.imported_questions}"
});
showSuccessfulUploadMsg();
} catch (e) {
print('Settings: importFrontEndCfgFile() : EXCEPTION : ${e}');
displayCfgUploadErrorMsg();
}
} else {
print('Settings: importFrontEndCfgFile() : some fields if cfg are null, could not update firestore_cfg_collection');
displayCfgUploadErrorMsg();
}
}
}
}
void showSuccessfulUploadMsg() {
showDialog(
context: context,//navigatorKey.currentContext!,
builder: (BuildContext context) {
return AlertDialog(
title: Row( // Use a Row to align the icon and title
children: [
Icon(Icons.info, color: Colors.blueAccent),
SizedBox(width: 8), // Add some spacing
Text('Information'),
],
),
content: Text('The json configuration file has been\nuploaded successfully to Firestore.'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(); // Close the dialog
},
child: Text('OK'),
),
],
);
},
);
}
void displayCfgUploadErrorMsg() {
showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return AlertDialog(
title: Row( // Use a Row to align the icon and title
children: [
Icon(Icons.warning, color: Colors.red),
SizedBox(width: 8), // Add some spacing
Text('Alert'),
],
),
content: SelectableText.rich(
TextSpan(
children: [
TextSpan(text: "Please check you have uploaded a config_frontend.json\n" +
"file similar as the one below:\n\n"),
TextSpan(text: "{\n", style: TextStyle(color: Colors.black),),
TextSpan(text:'"endpoint_opendataqnq": ', style: TextStyle(color: Colors.blueAccent),),
TextSpan(text:'"<URI of the backend endpoint>",\n', style: TextStyle(color: Colors.green),),
TextSpan(text:'"firestore_database_id": ', style: TextStyle(color: Colors.blueAccent),),
TextSpan(text:'"opendataqna-session-logs",\n', style: TextStyle(color: Colors.green),),
TextSpan(text:'"firestore_history_collection": ', style: TextStyle(color: Colors.blueAccent),),
TextSpan(text:'"session_logs",\n', style: TextStyle(color: Colors.green),),
TextSpan(text:'"firestore_cfg_collection": ', style: TextStyle(color: Colors.blueAccent),),
TextSpan(text:'"front_end_flutter_cfg",\n', style: TextStyle(color: Colors.green),),
TextSpan(text:'"expert_mode": ', style: TextStyle(color: Colors.blueAccent),),
TextSpan(text:'<true|false>,\n', style: TextStyle(color: Colors.red),),
TextSpan(text:'"anonymized_data": ', style: TextStyle(color: Colors.blueAccent),),
TextSpan(text:'<true|false>,\n', style: TextStyle(color: Colors.red),),
TextSpan(text:'"firebase_app_name": ', style: TextStyle(color: Colors.blueAccent),),
TextSpan(text:'"opendataqna"\n', style: TextStyle(color: Colors.green),),
TextSpan(text:'}', style: TextStyle(color: Colors.black),),
],
),
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(); // Close the dialog
},
child: Text('OK'),
),
],
);
},
);
}
void updateFrontEndFlutterCfg({required String parameter, required bool value}) {
print("Settings : updateFrontEndFlutterCfg() : START");
print("Settings : updateFrontEndFlutterCfg() : widget.db = ${widget.db}");
print("Settings : updateFrontEndFlutterCfg() : parameter = ${parameter}");
print("Settings : updateFrontEndFlutterCfg() : value = ${value}");
print(
'Settings: updateFrontEndFlutterCfg() : TextToDocParameter.firestore_cfg_collection = ${TextToDocParameter.firestore_cfg_collection}');
print(
'Settings: updateFrontEndFlutterCfg() : TextToDocParameter.userID = ${TextToDocParameter.userID}');
//update the document in front_end_flutter_cfg collection corresponding to the user_id to refelect the chnage of the TextToDocParameter.expert_mode parameter
try {
widget.db!
.collection("${TextToDocParameter.firestore_cfg_collection}")
.doc('${TextToDocParameter.userID}')
.set(
{"$parameter": value},
SetOptions(merge: true));
print(
'Settings: updateFrontEndFlutterCfg() : update firestore_history_collection.expert_mode successfully: parameter = $parameter : value = $value');
} catch (e) {
print(
'Settings: updateFrontEndFlutterCfg() : update firestore_history_collection.expert_mode : EXCEPTION : $e');
}
}
}
class Config {
static bool isUseFeedback = false;
static bool isUseColorMode = false;
static bool isUseDashboards = false;
static bool isUseReports = false;
static bool isExpert = false;
static bool isUseLog = false;
static bool isAnonymizedMode = false;
@override
String toString() {
return isExpert.toString();
}
}