add structure
This commit is contained in:
254
lib/reports/fixed_header.dart
Normal file
254
lib/reports/fixed_header.dart
Normal file
@@ -0,0 +1,254 @@
|
||||
import 'package:fcs/vo/report.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ReportsDataTable2 extends StatefulWidget {
|
||||
Report report;
|
||||
ReportsDataTable2({this.report});
|
||||
@override
|
||||
_ReportsDataTable2State createState() => _ReportsDataTable2State();
|
||||
}
|
||||
|
||||
class _ReportsDataTable2State extends State<ReportsDataTable2> {
|
||||
final _rowsCells = [
|
||||
[1, 8, 10, 8, 7],
|
||||
[2, 10, 9, 6, 6],
|
||||
[3, 4, 5, 7, 5],
|
||||
[4, 4, 1, 7, 8],
|
||||
[7, 8, 10, 8, 7],
|
||||
[10, 10, 9, 6, 6],
|
||||
[5, 4, 5, 7, 5],
|
||||
[9, 4, 1, 7, 8],
|
||||
[7, 8, 10, 8, 7],
|
||||
[10, 10, 9, 6, 6],
|
||||
[5, 4, 5, 7, 5],
|
||||
[9, 4, 1, 7, 8],
|
||||
[7, 8, 10, 8, 7],
|
||||
[10, 10, 9, 6, 6],
|
||||
[5, 4, 5, 7, 5],
|
||||
[9, 4, 1, 7, 8]
|
||||
];
|
||||
final _fixedColCells = [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14",
|
||||
"15",
|
||||
"16"
|
||||
];
|
||||
final _fixedRowCells = [
|
||||
"Math",
|
||||
"Informatics",
|
||||
"Geography",
|
||||
"Physics",
|
||||
"Biology"
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(),
|
||||
body: CustomDataTable(
|
||||
rowsCells: _rowsCells,
|
||||
fixedColCells: _fixedColCells,
|
||||
fixedRowCells: _fixedRowCells,
|
||||
cellBuilder: (data) {
|
||||
return Container(
|
||||
decoration:
|
||||
BoxDecoration(border: Border.all(color: Colors.grey[400])),
|
||||
alignment: Alignment.centerRight,
|
||||
child: Text('$data'));
|
||||
},
|
||||
fixedCornerCell: "",
|
||||
fixedColWidth: 20,
|
||||
cellWidth: 150,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CustomDataTable<T> extends StatefulWidget {
|
||||
final T fixedCornerCell;
|
||||
final List<T> fixedColCells;
|
||||
final List<T> fixedRowCells;
|
||||
final List<List<T>> rowsCells;
|
||||
final Widget Function(T data) cellBuilder;
|
||||
final double fixedColWidth;
|
||||
final double cellWidth;
|
||||
final double cellHeight;
|
||||
final double cellMargin;
|
||||
final double cellSpacing;
|
||||
|
||||
CustomDataTable({
|
||||
this.fixedCornerCell,
|
||||
this.fixedColCells,
|
||||
this.fixedRowCells,
|
||||
@required this.rowsCells,
|
||||
this.cellBuilder,
|
||||
this.fixedColWidth = 60.0,
|
||||
this.cellHeight = 56.0,
|
||||
this.cellWidth = 120.0,
|
||||
this.cellMargin = 0.0,
|
||||
this.cellSpacing = 0,
|
||||
});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => CustomDataTableState();
|
||||
}
|
||||
|
||||
class CustomDataTableState<T> extends State<CustomDataTable<T>> {
|
||||
final _columnController = ScrollController();
|
||||
final _rowController = ScrollController();
|
||||
final _subTableYController = ScrollController();
|
||||
final _subTableXController = ScrollController();
|
||||
|
||||
Widget _buildChild(double width, T data) => SizedBox(
|
||||
width: width, child: widget.cellBuilder?.call(data) ?? Text('$data'));
|
||||
|
||||
Widget _buildHeader(double width, T data) => SizedBox(
|
||||
width: width, child: Container(
|
||||
decoration:
|
||||
BoxDecoration(border: Border.all(color: Colors.grey[400])),
|
||||
alignment: Alignment.centerRight,
|
||||
child: Text('$data')));
|
||||
|
||||
Widget _buildFixedCol() => widget.fixedColCells == null
|
||||
? SizedBox.shrink()
|
||||
: Material(
|
||||
color: Colors.grey[300],
|
||||
child: DataTable(
|
||||
horizontalMargin: widget.cellMargin,
|
||||
columnSpacing: widget.cellSpacing,
|
||||
headingRowHeight: widget.cellHeight,
|
||||
dataRowHeight: widget.cellHeight,
|
||||
columns: [
|
||||
DataColumn(
|
||||
label: _buildChild(
|
||||
widget.fixedColWidth, widget.fixedColCells.first),
|
||||
numeric: true)
|
||||
],
|
||||
rows: widget.fixedColCells
|
||||
.sublist(widget.fixedRowCells == null ? 1 : 0)
|
||||
.map((c) => DataRow(
|
||||
cells: [DataCell(_buildChild(widget.fixedColWidth, c))]))
|
||||
.toList()),
|
||||
);
|
||||
|
||||
Widget _buildFixedRow() => widget.fixedRowCells == null
|
||||
? SizedBox.shrink()
|
||||
: Material(
|
||||
color: Colors.grey[300],
|
||||
child: Theme(
|
||||
data: Theme.of(context).copyWith(dividerColor: Colors.green),
|
||||
child: DataTable(
|
||||
horizontalMargin: widget.cellMargin,
|
||||
columnSpacing: widget.cellSpacing,
|
||||
headingRowHeight: widget.cellHeight,
|
||||
dataRowHeight: widget.cellHeight,
|
||||
columns: widget.fixedRowCells
|
||||
.map((c) =>
|
||||
DataColumn(label: _buildHeader(widget.cellWidth, c)))
|
||||
.toList(),
|
||||
rows: []),
|
||||
),
|
||||
);
|
||||
|
||||
Widget _buildSubTable() => Material(
|
||||
child: DataTable(
|
||||
horizontalMargin: widget.cellMargin,
|
||||
columnSpacing: widget.cellSpacing,
|
||||
headingRowHeight: widget.cellHeight,
|
||||
dataRowHeight: widget.cellHeight,
|
||||
// MyDataRowHeight: widget.cellHeight,
|
||||
columns: widget.rowsCells.first
|
||||
.map((c) => DataColumn(
|
||||
label: _buildChild(widget.cellWidth, c), numeric: true))
|
||||
.toList(),
|
||||
rows: widget.rowsCells
|
||||
.sublist(widget.fixedRowCells == null ? 1 : 0)
|
||||
.map((row) => DataRow(
|
||||
cells: row
|
||||
.map((c) => DataCell(_buildChild(widget.cellWidth, c)))
|
||||
.toList()))
|
||||
.toList()));
|
||||
|
||||
Widget _buildCornerCell() =>
|
||||
widget.fixedColCells == null || widget.fixedRowCells == null
|
||||
? SizedBox.shrink()
|
||||
: Material(
|
||||
color: Colors.grey[300],
|
||||
child: DataTable(
|
||||
horizontalMargin: widget.cellMargin,
|
||||
columnSpacing: widget.cellSpacing,
|
||||
headingRowHeight: widget.cellHeight,
|
||||
dataRowHeight: widget.cellHeight,
|
||||
columns: [
|
||||
DataColumn(
|
||||
label: _buildChild(
|
||||
widget.fixedColWidth, widget.fixedCornerCell))
|
||||
],
|
||||
rows: []),
|
||||
);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_subTableXController.addListener(() {
|
||||
_rowController.jumpTo(_subTableXController.position.pixels);
|
||||
});
|
||||
_subTableYController.addListener(() {
|
||||
_columnController.jumpTo(_subTableYController.position.pixels);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
SingleChildScrollView(
|
||||
controller: _columnController,
|
||||
scrollDirection: Axis.vertical,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
child: _buildFixedCol(),
|
||||
),
|
||||
Flexible(
|
||||
child: SingleChildScrollView(
|
||||
controller: _subTableXController,
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: SingleChildScrollView(
|
||||
controller: _subTableYController,
|
||||
scrollDirection: Axis.vertical,
|
||||
child: _buildSubTable(),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
_buildCornerCell(),
|
||||
Flexible(
|
||||
child: SingleChildScrollView(
|
||||
controller: _rowController,
|
||||
scrollDirection: Axis.horizontal,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
child: _buildFixedRow(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
203
lib/reports/report_field_list_page.dart
Normal file
203
lib/reports/report_field_list_page.dart
Normal file
@@ -0,0 +1,203 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/model/report_model.dart';
|
||||
import 'package:fcs/theme/theme.dart';
|
||||
import 'package:fcs/vo/report.dart';
|
||||
|
||||
class ReportFieldListPage extends StatefulWidget {
|
||||
ReportFieldListPage({
|
||||
this.id,
|
||||
this.fields,
|
||||
this.selectedDisplayFields,
|
||||
});
|
||||
|
||||
final String id;
|
||||
final List<Field> fields;
|
||||
final List selectedDisplayFields;
|
||||
|
||||
@override
|
||||
ReportFieldListPageState createState() => ReportFieldListPageState();
|
||||
}
|
||||
|
||||
class ReportFieldListPageState extends State<ReportFieldListPage> {
|
||||
List _tempSelectedDisplayFields = [];
|
||||
List<Field> _fields = [];
|
||||
List convertList = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_tempSelectedDisplayFields = widget.selectedDisplayFields;
|
||||
_fields = widget.fields;
|
||||
_fields.asMap().forEach((key, value) {
|
||||
_tempSelectedDisplayFields.asMap().forEach((key, name) {
|
||||
if (value.name == name) {
|
||||
convertList.add(value.name);
|
||||
}
|
||||
});
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ReportModel reportModel = Provider.of<ReportModel>(context);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: primaryColor,
|
||||
title: Text("Report Display Fields"),
|
||||
),
|
||||
body: WillPopScope(
|
||||
onWillPop: () {
|
||||
Navigator.pop(context, convertList);
|
||||
return new Future(() => false);
|
||||
},
|
||||
child: Card(
|
||||
elevation: 0.5,
|
||||
child: ListView.builder(
|
||||
itemCount: _fields.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final field = _fields[index].name;
|
||||
final fieldName = _fields[index].displayName;
|
||||
return CheckboxListTile(
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
title: Text(fieldName),
|
||||
secondary: Container(
|
||||
width: 150,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
(index != 0)
|
||||
? IconButton(
|
||||
icon: Icon(
|
||||
Icons.arrow_upward,
|
||||
color: primaryColor,
|
||||
size: 20.0,
|
||||
),
|
||||
onPressed: () {
|
||||
List<Field> temp = new List();
|
||||
if (index == 0) return;
|
||||
temp = _fields;
|
||||
var tempField;
|
||||
var tempField1;
|
||||
|
||||
tempField = temp[index];
|
||||
tempField1 = temp[index - 1];
|
||||
|
||||
temp[index] = tempField1;
|
||||
temp[index - 1] = tempField;
|
||||
|
||||
_fields = [];
|
||||
setState(() {
|
||||
_fields = temp;
|
||||
});
|
||||
|
||||
convertList = [];
|
||||
_fields.asMap().forEach((key, value) {
|
||||
_tempSelectedDisplayFields
|
||||
.asMap()
|
||||
.forEach((key, name) {
|
||||
if (value.name == name) {
|
||||
setState(() {
|
||||
convertList.add(value.name);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
reportModel.saveSelectedFieldsAndPosition(
|
||||
widget.id, _fields, convertList);
|
||||
},
|
||||
)
|
||||
: IconButton(
|
||||
icon: Icon(
|
||||
Icons.arrow_upward,
|
||||
size: 20.0,
|
||||
),
|
||||
disabledColor: Colors.grey,
|
||||
onPressed: null,
|
||||
),
|
||||
(index != _fields.length - 1)
|
||||
? IconButton(
|
||||
icon: Icon(
|
||||
Icons.arrow_downward,
|
||||
color: primaryColor,
|
||||
size: 20.0,
|
||||
),
|
||||
onPressed: () {
|
||||
List<Field> temp = new List();
|
||||
if (index == _fields.length - 1) return;
|
||||
temp = _fields;
|
||||
var tempField;
|
||||
var tempField1;
|
||||
|
||||
tempField = temp[index];
|
||||
tempField1 = temp[index + 1];
|
||||
|
||||
temp[index] = tempField1;
|
||||
temp[index + 1] = tempField;
|
||||
|
||||
_fields = [];
|
||||
setState(() {
|
||||
_fields = temp;
|
||||
});
|
||||
|
||||
_fields.asMap().forEach((key, value) {
|
||||
_tempSelectedDisplayFields
|
||||
.asMap()
|
||||
.forEach((key, name) {
|
||||
if (value.name == name) {
|
||||
setState(() {
|
||||
convertList.add(value.name);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
reportModel.saveSelectedFieldsAndPosition(
|
||||
widget.id, _fields, convertList);
|
||||
},
|
||||
)
|
||||
: IconButton(
|
||||
icon: Icon(
|
||||
Icons.arrow_downward,
|
||||
size: 20.0,
|
||||
),
|
||||
onPressed: null,
|
||||
disabledColor: Colors.grey,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
value: _tempSelectedDisplayFields.contains(field),
|
||||
onChanged: (bool value) {
|
||||
if (value) {
|
||||
if (!_tempSelectedDisplayFields.contains(field)) {
|
||||
setState(() {
|
||||
_tempSelectedDisplayFields.add(field);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (_tempSelectedDisplayFields.contains(field)) {
|
||||
setState(() {
|
||||
_tempSelectedDisplayFields
|
||||
.removeWhere((rfield) => rfield == field);
|
||||
});
|
||||
}
|
||||
}
|
||||
convertList = [];
|
||||
_fields.asMap().forEach((key, value) {
|
||||
_tempSelectedDisplayFields.asMap().forEach((key, name) {
|
||||
if (value.name == name) {
|
||||
setState(() {
|
||||
convertList.add(value.name);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
reportModel.saveSelectedFieldsAndPosition(
|
||||
widget.id, _fields, convertList);
|
||||
});
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
244
lib/reports/report_filter_list_page.dart
Normal file
244
lib/reports/report_filter_list_page.dart
Normal file
@@ -0,0 +1,244 @@
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/model/main_model.dart';
|
||||
import 'package:fcs/model/report_model.dart';
|
||||
import 'package:fcs/vo/popup_menu.dart';
|
||||
import 'package:fcs/vo/report.dart';
|
||||
import 'package:fcs/widget/localization/app_translations.dart';
|
||||
import 'package:fcs/widget/popupmenu.dart';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fcs/widget/progress.dart';
|
||||
|
||||
import '../theme/theme.dart';
|
||||
|
||||
class ReportFilterListPage extends StatefulWidget {
|
||||
final Report report;
|
||||
final ValueChanged onChangedData;
|
||||
ReportFilterListPage(this.report, this.onChangedData);
|
||||
|
||||
@override
|
||||
_ReportFilterListPageState createState() => _ReportFilterListPageState();
|
||||
}
|
||||
|
||||
class _ReportFilterListPageState extends State<ReportFilterListPage> {
|
||||
bool _isLoading = false;
|
||||
List<DisplayFilter> filters = [];
|
||||
List<TextEditingController> _textControllers = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (widget.report != null) {
|
||||
filters = widget.report.displayFilters;
|
||||
filters.asMap().forEach((key, filter) {
|
||||
if (filter.compare == '==') {
|
||||
_textControllers.add(TextEditingController());
|
||||
}
|
||||
if (filter.compare == '>=') {
|
||||
//From
|
||||
// _textControllers.add(TextEditingController());
|
||||
}
|
||||
if (filter.compare == '==') {
|
||||
//To
|
||||
// _textControllers.add(TextEditingController());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
List<Widget> showFilterList(
|
||||
BuildContext context, List<DisplayFilter> filterlist) {
|
||||
List<Widget> list = [];
|
||||
filterlist.asMap().forEach((key, filter) {
|
||||
if (filter.compare == '==') {
|
||||
list.add(
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
filter.displayName,
|
||||
),
|
||||
),
|
||||
);
|
||||
list.add(Container(
|
||||
padding: EdgeInsets.only(top: 7),
|
||||
child: TextFormField(
|
||||
controller: _textControllers[key],
|
||||
cursorColor: primaryColor,
|
||||
textAlign: TextAlign.left,
|
||||
decoration: InputDecoration(
|
||||
contentPadding: EdgeInsets.all(8.0),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12.0)),
|
||||
borderSide: BorderSide(color: Colors.grey[300], width: 2),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(10.0)),
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey[300],
|
||||
),
|
||||
),
|
||||
),
|
||||
)));
|
||||
list.add(SizedBox(height: 15));
|
||||
}
|
||||
if (filter.compare == '>=') {}
|
||||
if (filter.compare == '<=') {}
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ReportModel reportModel = Provider.of<ReportModel>(context);
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: primaryColor,
|
||||
title: Text("Report Filter"),
|
||||
),
|
||||
body: ListView(
|
||||
padding: EdgeInsets.only(top: 10, left: 5, right: 5),
|
||||
children: <Widget>[
|
||||
Card(
|
||||
elevation: 5.0,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 20, right: 20, top: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: showFilterList(context, this.filters))),
|
||||
SizedBox(height: 15),
|
||||
Container(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: RaisedButton(
|
||||
child: Text("Clear Filter"),
|
||||
onPressed: () {
|
||||
reportModel.getReportDataWithFilters(
|
||||
widget.report, []).then((data) {
|
||||
widget.onChangedData(data);
|
||||
Navigator.pop(context);
|
||||
});
|
||||
},
|
||||
color: primaryColor,
|
||||
textColor: Colors.white,
|
||||
// padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
||||
splashColor: Colors.grey,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: RaisedButton(
|
||||
child: Text("Save"),
|
||||
onPressed: () {
|
||||
List flist = [];
|
||||
filters.asMap().forEach((key, filter) {
|
||||
if (_textControllers[key].text != null ||
|
||||
_textControllers[key].text != '') {
|
||||
flist.add({
|
||||
"field": filter.name,
|
||||
"compare": filter.compare,
|
||||
"value": _textControllers[key].text
|
||||
});
|
||||
}
|
||||
});
|
||||
reportModel
|
||||
.getReportDataWithFilters(widget.report, flist)
|
||||
.then((data) {
|
||||
widget.onChangedData(data);
|
||||
Navigator.pop(context);
|
||||
});
|
||||
},
|
||||
color: primaryColor,
|
||||
textColor: Colors.white,
|
||||
// padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
||||
splashColor: Colors.grey,
|
||||
),
|
||||
)
|
||||
],
|
||||
))
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
// body: new Column(children: <Widget>[
|
||||
// Expanded(
|
||||
// child: Column(children: showFilterList(context, this.filters))),
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.start,
|
||||
// children: <Widget>[
|
||||
// // Expanded(
|
||||
// // flex: 1,
|
||||
// // child: RaisedButton(
|
||||
// // child: Text("Cancel"),
|
||||
// // onPressed: () {
|
||||
// // Navigator.pop(context);
|
||||
// // },
|
||||
// // color: primaryColor,
|
||||
// // textColor: Colors.white,
|
||||
// // // padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
||||
// // splashColor: Colors.grey,
|
||||
// // ),
|
||||
// // ),
|
||||
// RaisedButton(
|
||||
// child: Text("Clear Filter"),
|
||||
// onPressed: () {
|
||||
// reportModel.getReportDataWithFilters(
|
||||
// widget.report, []).then((data) {
|
||||
// widget.onChangedData(data);
|
||||
// Navigator.pop(context);
|
||||
// });
|
||||
// },
|
||||
// color: primaryColor,
|
||||
// textColor: Colors.white,
|
||||
// // padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
||||
// splashColor: Colors.grey,
|
||||
// ),
|
||||
// RaisedButton(
|
||||
// child: Text("Save"),
|
||||
// onPressed: () {
|
||||
// List flist = [];
|
||||
// filters.asMap().forEach((key, filter) {
|
||||
// print(
|
||||
// '_textControllers vlaue=> ${_textControllers[key].text}');
|
||||
// if (_textControllers[key].text != null ||
|
||||
// _textControllers[key].text != '') {
|
||||
// flist.add({
|
||||
// "field": filter.name,
|
||||
// "compare": filter.compare,
|
||||
// "value": _textControllers[key].text
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// reportModel
|
||||
// .getReportDataWithFilters(widget.report, flist)
|
||||
// .then((data) {
|
||||
// widget.onChangedData(data);
|
||||
// Navigator.pop(context);
|
||||
// });
|
||||
// },
|
||||
// color: primaryColor,
|
||||
// textColor: Colors.white,
|
||||
// // padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
||||
// splashColor: Colors.grey,
|
||||
// )
|
||||
// ])
|
||||
// ]),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
166
lib/reports/report_list.dart
Normal file
166
lib/reports/report_list.dart
Normal file
@@ -0,0 +1,166 @@
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/model/main_model.dart';
|
||||
import 'package:fcs/model/report_model.dart';
|
||||
import 'package:fcs/pages/report_user_list.dart';
|
||||
import 'package:fcs/reports/fixed_header.dart';
|
||||
import 'package:fcs/vo/popup_menu.dart';
|
||||
import 'package:fcs/vo/report.dart';
|
||||
import 'package:fcs/widget/localization/app_translations.dart';
|
||||
import 'package:fcs/widget/popupmenu.dart';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fcs/widget/progress.dart';
|
||||
|
||||
import '../theme/theme.dart';
|
||||
import 'reports_data_table.dart';
|
||||
|
||||
class ReportList extends StatefulWidget {
|
||||
@override
|
||||
_ReportListState createState() => _ReportListState();
|
||||
}
|
||||
|
||||
class _ReportListState extends State<ReportList> {
|
||||
bool _isLoading = false;
|
||||
Report _report = new Report();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ReportModel reportModel = Provider.of<ReportModel>(context);
|
||||
MainModel mainModel = Provider.of<MainModel>(context);
|
||||
|
||||
bool isOwnerAndAbove =
|
||||
mainModel.user != null && mainModel.user.isOwnerAndAbove();
|
||||
bool hasAdmin = mainModel.user != null && mainModel.user.hasAdmin();
|
||||
bool hasOwner = mainModel.user != null && mainModel.user.isOwner();
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: primaryColor,
|
||||
title: Text(AppTranslations.of(context).text("report.title")),
|
||||
// actions: <Widget>[
|
||||
// IconButton(
|
||||
// onPressed: () {
|
||||
// reportModel.addreport();
|
||||
// },
|
||||
// iconSize: 30,
|
||||
// icon: Icon(Icons.filter_list),
|
||||
// ),
|
||||
// ],
|
||||
),
|
||||
floatingActionButton: mainModel.isSysAdmin()
|
||||
? FloatingActionButton(
|
||||
backgroundColor: primaryColor,
|
||||
onPressed: () async {},
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: Colors.white,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
body: new ListView.builder(
|
||||
scrollDirection: Axis.vertical,
|
||||
padding: EdgeInsets.only(top: 15),
|
||||
shrinkWrap: true,
|
||||
itemCount: reportModel.reportList.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(left: 10, right: 10),
|
||||
child: Card(
|
||||
elevation: 10,
|
||||
color: Colors.white,
|
||||
child: Row(children: <Widget>[
|
||||
new Expanded(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (_) => ReportsDataTable(
|
||||
report: reportModel.reportList[index],
|
||||
)));
|
||||
},
|
||||
child: new Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: new Row(children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Image.asset(
|
||||
"assets/report.png",
|
||||
width: 40,
|
||||
height: 40,
|
||||
// color: primaryColor,
|
||||
),
|
||||
),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
reportModel.reportList[index].display == null
|
||||
? ""
|
||||
: reportModel.reportList[index].display,
|
||||
style: new TextStyle(
|
||||
fontSize: 17.0, color: Colors.black),
|
||||
),
|
||||
],
|
||||
),
|
||||
])),
|
||||
)),
|
||||
isOwnerAndAbove || hasAdmin
|
||||
? hasOwner || hasAdmin
|
||||
? PopupMenuButton<PopupMenu>(
|
||||
elevation: 3.2,
|
||||
tooltip: 'This is tooltip',
|
||||
onSelected: _select,
|
||||
itemBuilder: (BuildContext context) {
|
||||
this._report = reportModel.reportList[index];
|
||||
return reportUserPopup
|
||||
.map((PopupMenu choice) {
|
||||
return PopupMenuItem<PopupMenu>(
|
||||
value: choice,
|
||||
child: Text(choice.status),
|
||||
);
|
||||
}).toList();
|
||||
})
|
||||
: PopupMenuButton<PopupMenu>(
|
||||
elevation: 3.2,
|
||||
tooltip: 'This is tooltip',
|
||||
onSelected: _select,
|
||||
itemBuilder: (BuildContext context) {
|
||||
this._report = reportModel.reportList[index];
|
||||
return reportpopup.map((PopupMenu choice) {
|
||||
return PopupMenuItem<PopupMenu>(
|
||||
value: choice,
|
||||
child: Text(choice.status),
|
||||
);
|
||||
}).toList();
|
||||
})
|
||||
: Container()
|
||||
]),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _select(PopupMenu popupMenu) {
|
||||
if (popupMenu.index == 3) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ReportUserList(report: this._report)),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
380
lib/reports/reports_data_table.dart
Normal file
380
lib/reports/reports_data_table.dart
Normal file
@@ -0,0 +1,380 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:downloads_path_provider/downloads_path_provider.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_downloader/flutter_downloader.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:open_file/open_file.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fcs/model/language_model.dart';
|
||||
import 'package:fcs/model/report_model.dart';
|
||||
import 'package:fcs/pages/util.dart';
|
||||
import 'package:fcs/theme/theme.dart';
|
||||
import 'package:fcs/vo/report.dart';
|
||||
import 'package:fcs/widget/my_data_table.dart';
|
||||
import 'package:fcs/widget/progress.dart';
|
||||
|
||||
import 'report_field_list_page.dart';
|
||||
import 'report_filter_list_page.dart';
|
||||
|
||||
class ReportsDataTable extends StatefulWidget {
|
||||
final Report report;
|
||||
ReportsDataTable({this.report});
|
||||
@override
|
||||
_ReportsDataTableState createState() => _ReportsDataTableState();
|
||||
}
|
||||
|
||||
class _ReportsDataTableState extends State<ReportsDataTable> {
|
||||
Report report;
|
||||
int limit = 20;
|
||||
int offset = 0;
|
||||
final numberFormatter = new NumberFormat("#,###");
|
||||
var dateFormatter = new DateFormat('dd MMM yyyy\nhh:mm:ss a');
|
||||
|
||||
List _initialDisplayFields = [];
|
||||
List<Field> _initialFields = [];
|
||||
List _initialfieldList = [];
|
||||
|
||||
List<Field> displayFields = [];
|
||||
List dataList = [];
|
||||
List cellfields = [];
|
||||
List fieldList = [];
|
||||
bool sort;
|
||||
bool _isLoading;
|
||||
int sortColumnIndex = 1;
|
||||
bool _endOfData;
|
||||
TargetPlatform platform;
|
||||
bool _permissionReady;
|
||||
String _localPath;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_controller = ScrollController();
|
||||
_controller.addListener(_scrollListener);
|
||||
|
||||
super.initState();
|
||||
sort = false;
|
||||
_isLoading = true;
|
||||
_endOfData = false;
|
||||
_permissionReady = false;
|
||||
_load();
|
||||
}
|
||||
|
||||
_prepare() async {
|
||||
platform = Theme.of(context).platform;
|
||||
|
||||
_permissionReady = await _checkPermission();
|
||||
|
||||
_localPath = (await _findLocalPath()) + Platform.pathSeparator + 'Download';
|
||||
|
||||
final savedDir = Directory(_localPath);
|
||||
bool hasExisted = await savedDir.exists();
|
||||
if (!hasExisted) {
|
||||
savedDir.create();
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> _checkPermission() async {
|
||||
if (platform == TargetPlatform.android) {
|
||||
PermissionStatus permission = await PermissionHandler()
|
||||
.checkPermissionStatus(PermissionGroup.storage);
|
||||
if (permission != PermissionStatus.granted) {
|
||||
Map<PermissionGroup, PermissionStatus> permissions =
|
||||
await PermissionHandler()
|
||||
.requestPermissions([PermissionGroup.storage]);
|
||||
if (permissions[PermissionGroup.storage] == PermissionStatus.granted) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
_load() async {
|
||||
var reportModel = Provider.of<ReportModel>(context, listen: false);
|
||||
var data = await reportModel.getReport(widget.report.id);
|
||||
reportModel.getReport(widget.report.id).then((_report) {
|
||||
// var data = await reportModel.loadSelectedFieldsAndPosition(widget.report.id);
|
||||
reportModel.loadSelectedFieldsAndPosition(widget.report.id).then((value) {
|
||||
print("report value => $value");
|
||||
if (value != null) {
|
||||
_initialDisplayFields = value.fieldSelection;
|
||||
_initialFields = value.fieldPosition;
|
||||
} else {
|
||||
_initialDisplayFields = _report.displayFields;
|
||||
_initialFields = _report.fields;
|
||||
}
|
||||
|
||||
_initialDisplayFields.asMap().forEach((key, value) {
|
||||
_initialFields.asMap().forEach((key, fvalue) {
|
||||
if (value == fvalue.name) {
|
||||
displayFields.add(fvalue);
|
||||
if (fvalue.aggFun != '') {
|
||||
var convertField = fvalue.name + '_' + fvalue.aggFun;
|
||||
cellfields.add(convertField);
|
||||
}
|
||||
if (fvalue.aggFun == '') {
|
||||
cellfields.add(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
_initialfieldList.add(value);
|
||||
});
|
||||
});
|
||||
|
||||
setState(() {
|
||||
this.report = _report;
|
||||
});
|
||||
|
||||
_loadData();
|
||||
});
|
||||
}
|
||||
|
||||
_loadData() {
|
||||
var reportModel = Provider.of<ReportModel>(context, listen: false);
|
||||
reportModel.getReportData(report, limit, offset).then((value) {
|
||||
setState(() {
|
||||
if (value == null || value.length < limit) {
|
||||
_endOfData = true;
|
||||
}
|
||||
dataList.addAll(value);
|
||||
_isLoading = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ScrollController _controller;
|
||||
|
||||
_scrollListener() {
|
||||
if (_controller.offset >= _controller.position.maxScrollExtent &&
|
||||
!_controller.position.outOfRange) {
|
||||
setState(() {
|
||||
offset += limit;
|
||||
if (!_endOfData) _loadData();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildPopupMenu() {
|
||||
return PopupMenuButton(
|
||||
onSelected: (s) {
|
||||
if (s == 1) {
|
||||
// var reportModel = Provider.of<ReportModel>(context, listen: false);
|
||||
// reportModel.downloadReportData(report);
|
||||
_download();
|
||||
} else if (s == 2) {}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
value: 1,
|
||||
child: Text("Download"),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 2,
|
||||
child: Text("Clear setting"),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var reportModel = Provider.of<ReportModel>(context, listen: false);
|
||||
fieldList = _initialfieldList;
|
||||
print("report fieldList => $fieldList");
|
||||
print("report sortColumnIndex => $sortColumnIndex");
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
actions: <Widget>[
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (_) => ReportFilterListPage(report, (data) {
|
||||
dataList = [];
|
||||
setState(() {
|
||||
dataList = data;
|
||||
});
|
||||
})));
|
||||
},
|
||||
iconSize: 30,
|
||||
icon: Icon(Icons.filter_list),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
List flist = await Navigator.push<List>(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ReportFieldListPage(
|
||||
id: widget.report.id,
|
||||
fields: report.fields,
|
||||
selectedDisplayFields: fieldList,
|
||||
)),
|
||||
);
|
||||
|
||||
fieldList = [];
|
||||
cellfields = [];
|
||||
displayFields = [];
|
||||
setState(() {
|
||||
fieldList = flist;
|
||||
fieldList.asMap().forEach((key, value) {
|
||||
_initialFields.asMap().forEach((key, fvalue) {
|
||||
if (value == fvalue.name) {
|
||||
displayFields.add(fvalue);
|
||||
if (fvalue.aggFun != '') {
|
||||
var convertField = fvalue.name + '_' + fvalue.aggFun;
|
||||
cellfields.add(convertField);
|
||||
}
|
||||
if (fvalue.aggFun == '') {
|
||||
cellfields.add(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
iconSize: 30,
|
||||
icon: Icon(Icons.list),
|
||||
),
|
||||
_buildPopupMenu()
|
||||
],
|
||||
backgroundColor: primaryColor,
|
||||
title: Text(
|
||||
report == null ? "" : report.display,
|
||||
style: Provider.of<LanguageModel>(context).isEng
|
||||
? TextStyle(fontSize: 18)
|
||||
: TextStyle(fontSize: 18, fontFamily: 'MyanmarUnicode'),
|
||||
),
|
||||
),
|
||||
body: _isLoading
|
||||
? Container()
|
||||
: SingleChildScrollView(
|
||||
controller: _controller,
|
||||
scrollDirection: Axis.vertical,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: MyDataTable(
|
||||
columnSpacing: 10,
|
||||
sortAscending: this.sort,
|
||||
sortColumnIndex: this.sortColumnIndex,
|
||||
columns: getReportColumn(reportModel, this.displayFields),
|
||||
rows: getReportRow(this.dataList),
|
||||
oddLine: tableRowOdd,
|
||||
evenLine: tableRowEven,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
onSortColumn(ReportModel reportModel, int columnIndex, bool ascending,
|
||||
String fieldName) {
|
||||
if (columnIndex == this.sortColumnIndex) {
|
||||
if (ascending) {
|
||||
var str = fieldName + " " + "asc";
|
||||
List sorts = [];
|
||||
sorts.add(str);
|
||||
this.report.id = widget.report.id;
|
||||
this.report.sorts = sorts;
|
||||
reportModel.getReportData(report, this.limit, 0).then((value) {
|
||||
setState(() {
|
||||
dataList = value;
|
||||
_isLoading = false;
|
||||
this.offset = 0;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
var str = fieldName + " " + "desc";
|
||||
List sorts = [];
|
||||
sorts.add(str);
|
||||
this.report.id = widget.report.id;
|
||||
this.report.sorts = sorts;
|
||||
Provider.of<ReportModel>(context)
|
||||
.getReportData(report, this.limit, 0)
|
||||
.then((value) {
|
||||
setState(() {
|
||||
dataList = value;
|
||||
_isLoading = false;
|
||||
this.offset = 0;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<MyDataColumn> getReportColumn(
|
||||
ReportModel reportModel, List<Field> colList) {
|
||||
return colList.map((p) {
|
||||
var r = MyDataColumn(
|
||||
label: Text(
|
||||
p.displayName,
|
||||
style: TextStyle(
|
||||
fontSize: 16, color: Colors.black, fontWeight: FontWeight.bold),
|
||||
),
|
||||
onSort: (columnIndex, ascending) {
|
||||
setState(() {
|
||||
sort = !sort;
|
||||
sortColumnIndex = columnIndex;
|
||||
});
|
||||
onSortColumn(reportModel, columnIndex, ascending, p.name);
|
||||
},
|
||||
numeric:
|
||||
p.dataType == 'integer' || p.dataType == 'float' ? true : false,
|
||||
);
|
||||
return r;
|
||||
}).toList()
|
||||
..insert(0, MyDataColumn(label: Text("Sr")));
|
||||
}
|
||||
|
||||
List<MyDataRow> getReportRow(List rowList) {
|
||||
int index = 0;
|
||||
return rowList.map((p) {
|
||||
var r = MyDataRow(cells: getDataCell(p, this.cellfields, ++index));
|
||||
return r;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
Future<String> _findLocalPath() async {
|
||||
var platform = Theme.of(context).platform;
|
||||
final directory = platform == TargetPlatform.android
|
||||
? await getExternalStorageDirectory()
|
||||
: await getApplicationDocumentsDirectory();
|
||||
return directory.path;
|
||||
}
|
||||
|
||||
_download() async {
|
||||
await _prepare();
|
||||
|
||||
var reportModel = Provider.of<ReportModel>(context, listen: false);
|
||||
String payload = await reportModel.getEscapeJson(report);
|
||||
|
||||
print("downloader Path:$_localPath");
|
||||
String id = await FlutterDownloader.enqueue(
|
||||
url: "http://petrok.mokkon.com:8082/api/report-pdf/${report.object}",
|
||||
headers: {"payload": payload},
|
||||
savedDir: _localPath,
|
||||
showNotification: true,
|
||||
openFileFromNotification: true);
|
||||
}
|
||||
}
|
||||
|
||||
List<MyDataCell> getDataCell(data, List fields, int index) {
|
||||
return fields.map((field) {
|
||||
var cell = MyDataCell(Text(
|
||||
'${data[field] == null ? "" : data[field]}',
|
||||
));
|
||||
return cell;
|
||||
}).toList()
|
||||
..insert(0, MyDataCell(Text("$index")));
|
||||
}
|
||||
Reference in New Issue
Block a user