Add scrollbars to tables
This commit is contained in:
parent
7c54561161
commit
ae1b5bb63a
|
|
@ -8,6 +8,7 @@ import 'package:flutter/material.dart' hide DataRow, DataCell, DataColumn;
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/gestures.dart' show DragStartBehavior;
|
import 'package:flutter/gestures.dart' show DragStartBehavior;
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/app_scrollbar.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/tables/app_data_table.dart';
|
import 'package:invoiceninja_flutter/ui/app/tables/app_data_table.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/tables/app_data_table_source.dart';
|
import 'package:invoiceninja_flutter/ui/app/tables/app_data_table_source.dart';
|
||||||
|
|
||||||
|
|
@ -223,11 +224,13 @@ class AppPaginatedDataTableState extends State<AppPaginatedDataTable> {
|
||||||
int _firstRowIndex;
|
int _firstRowIndex;
|
||||||
int _rowCount;
|
int _rowCount;
|
||||||
bool _rowCountApproximate;
|
bool _rowCountApproximate;
|
||||||
|
ScrollController _controller;
|
||||||
final Map<int, DataRow> _rows = <int, DataRow>{};
|
final Map<int, DataRow> _rows = <int, DataRow>{};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_controller = ScrollController();
|
||||||
_firstRowIndex = PageStorage.of(context)?.readState(context) as int ??
|
_firstRowIndex = PageStorage.of(context)?.readState(context) as int ??
|
||||||
widget.initialFirstRowIndex ??
|
widget.initialFirstRowIndex ??
|
||||||
0;
|
0;
|
||||||
|
|
@ -247,6 +250,7 @@ class AppPaginatedDataTableState extends State<AppPaginatedDataTable> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
widget.source.removeListener(_handleDataSourceChanged);
|
widget.source.removeListener(_handleDataSourceChanged);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
@ -470,23 +474,27 @@ class AppPaginatedDataTableState extends State<AppPaginatedDataTable> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
*/
|
*/
|
||||||
SingleChildScrollView(
|
Scrollbar(
|
||||||
scrollDirection: Axis.horizontal,
|
controller: _controller,
|
||||||
dragStartBehavior: widget.dragStartBehavior,
|
child: SingleChildScrollView(
|
||||||
child: ConstrainedBox(
|
controller: _controller,
|
||||||
constraints: BoxConstraints(minWidth: constraints.minWidth),
|
scrollDirection: Axis.horizontal,
|
||||||
child: AppDataTable(
|
dragStartBehavior: widget.dragStartBehavior,
|
||||||
key: _tableKey,
|
child: ConstrainedBox(
|
||||||
columns: widget.columns,
|
constraints: BoxConstraints(minWidth: constraints.minWidth),
|
||||||
sortColumnIndex: widget.sortColumnIndex,
|
child: AppDataTable(
|
||||||
sortAscending: widget.sortAscending,
|
key: _tableKey,
|
||||||
onSelectAll: widget.onSelectAll,
|
columns: widget.columns,
|
||||||
dataRowHeight: widget.dataRowHeight,
|
sortColumnIndex: widget.sortColumnIndex,
|
||||||
headingRowHeight: widget.headingRowHeight,
|
sortAscending: widget.sortAscending,
|
||||||
horizontalMargin: widget.horizontalMargin,
|
onSelectAll: widget.onSelectAll,
|
||||||
columnSpacing: widget.columnSpacing,
|
dataRowHeight: widget.dataRowHeight,
|
||||||
showCheckboxColumn: widget.showCheckboxColumn,
|
headingRowHeight: widget.headingRowHeight,
|
||||||
rows: _getRows(_firstRowIndex, widget.rowsPerPage),
|
horizontalMargin: widget.horizontalMargin,
|
||||||
|
columnSpacing: widget.columnSpacing,
|
||||||
|
showCheckboxColumn: widget.showCheckboxColumn,
|
||||||
|
rows: _getRows(_firstRowIndex, widget.rowsPerPage),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
|
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/app_border.dart';
|
import 'package:invoiceninja_flutter/ui/app/app_border.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/app_scrollbar.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/forms/save_cancel_buttons.dart';
|
import 'package:invoiceninja_flutter/ui/app/forms/save_cancel_buttons.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/help_text.dart';
|
import 'package:invoiceninja_flutter/ui/app/help_text.dart';
|
||||||
|
|
@ -60,11 +61,14 @@ class _EntityListState extends State<EntityList> {
|
||||||
EntityDataTableSource dataTableSource;
|
EntityDataTableSource dataTableSource;
|
||||||
|
|
||||||
int _firstRowIndex = 0;
|
int _firstRowIndex = 0;
|
||||||
|
ScrollController _controller;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
_controller = ScrollController();
|
||||||
|
|
||||||
final entityType = widget.entityType;
|
final entityType = widget.entityType;
|
||||||
final state = widget.state;
|
final state = widget.state;
|
||||||
final entityList = widget.entityList;
|
final entityList = widget.entityList;
|
||||||
|
|
@ -107,6 +111,12 @@ class _EntityListState extends State<EntityList> {
|
||||||
dataTableSource.notifyListeners();
|
dataTableSource.notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final store = StoreProvider.of<AppState>(context);
|
final store = StoreProvider.of<AppState>(context);
|
||||||
|
|
@ -229,74 +239,79 @@ class _EntityListState extends State<EntityList> {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SingleChildScrollView(
|
child: AppScrollbar(
|
||||||
child: Padding(
|
controller: _controller,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
child: SingleChildScrollView(
|
||||||
child: AppPaginatedDataTable(
|
controller: _controller,
|
||||||
onSelectAll: (value) {
|
child: Padding(
|
||||||
final startIndex =
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
min(_firstRowIndex, entityList.length - 1);
|
child: AppPaginatedDataTable(
|
||||||
final endIndex =
|
onSelectAll: (value) {
|
||||||
min(_firstRowIndex + rowsPerPage, entityList.length);
|
final startIndex =
|
||||||
final entities = entityList
|
min(_firstRowIndex, entityList.length - 1);
|
||||||
.sublist(startIndex, endIndex)
|
final endIndex = min(
|
||||||
.map<BaseEntity>(
|
_firstRowIndex + rowsPerPage, entityList.length);
|
||||||
(String entityId) => entityMap[entityId])
|
final entities = entityList
|
||||||
.where((invoice) =>
|
.sublist(startIndex, endIndex)
|
||||||
value != listUIState.isSelected(invoice.id))
|
.map<BaseEntity>(
|
||||||
.toList();
|
(String entityId) => entityMap[entityId])
|
||||||
handleEntitiesActions(
|
.where((invoice) =>
|
||||||
entities, EntityAction.toggleMultiselect);
|
value != listUIState.isSelected(invoice.id))
|
||||||
},
|
.toList();
|
||||||
columns: [
|
handleEntitiesActions(
|
||||||
if (!isInMultiselect) DataColumn(label: SizedBox()),
|
entities, EntityAction.toggleMultiselect);
|
||||||
...widget.tableColumns.map((field) {
|
},
|
||||||
String label =
|
columns: [
|
||||||
AppLocalization.of(context).lookup(field);
|
if (!isInMultiselect) DataColumn(label: SizedBox()),
|
||||||
if (field.startsWith('custom')) {
|
...widget.tableColumns.map((field) {
|
||||||
final key = field.replaceFirst(
|
String label =
|
||||||
'custom', entityType.snakeCase);
|
AppLocalization.of(context).lookup(field);
|
||||||
label = state.company.getCustomFieldLabel(key);
|
if (field.startsWith('custom')) {
|
||||||
}
|
final key = field.replaceFirst(
|
||||||
var maxWidth = kTableColumnWidthMax;
|
'custom', entityType.snakeCase);
|
||||||
var minWidth = kTableColumnWidthMin;
|
label = state.company.getCustomFieldLabel(key);
|
||||||
if (field == ProductFields.description) {
|
}
|
||||||
maxWidth *= 5;
|
var maxWidth = kTableColumnWidthMax;
|
||||||
minWidth *= 5;
|
var minWidth = kTableColumnWidthMin;
|
||||||
}
|
if (field == ProductFields.description) {
|
||||||
return DataColumn(
|
maxWidth *= 5;
|
||||||
label: Container(
|
minWidth *= 5;
|
||||||
constraints: BoxConstraints(
|
}
|
||||||
minWidth: minWidth,
|
return DataColumn(
|
||||||
maxWidth: maxWidth,
|
label: Container(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
minWidth: minWidth,
|
||||||
|
maxWidth: maxWidth,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
label,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: Text(
|
onSort: (int columnIndex, bool ascending) {
|
||||||
label,
|
widget.onSortColumn(field);
|
||||||
overflow: TextOverflow.ellipsis,
|
});
|
||||||
),
|
}),
|
||||||
),
|
],
|
||||||
onSort: (int columnIndex, bool ascending) {
|
source: dataTableSource,
|
||||||
widget.onSortColumn(field);
|
sortColumnIndex: widget.tableColumns
|
||||||
});
|
.contains(listUIState.sortField)
|
||||||
}),
|
? widget.tableColumns.indexOf(listUIState.sortField)
|
||||||
],
|
: 0,
|
||||||
source: dataTableSource,
|
sortAscending: listUIState.sortAscending,
|
||||||
sortColumnIndex:
|
rowsPerPage: state.prefState.rowsPerPage,
|
||||||
widget.tableColumns.contains(listUIState.sortField)
|
onPageChanged: (row) => _firstRowIndex = row,
|
||||||
? widget.tableColumns.indexOf(listUIState.sortField)
|
initialFirstRowIndex: _firstRowIndex,
|
||||||
: 0,
|
availableRowsPerPage: [
|
||||||
sortAscending: listUIState.sortAscending,
|
10,
|
||||||
rowsPerPage: state.prefState.rowsPerPage,
|
25,
|
||||||
onPageChanged: (row) => _firstRowIndex = row,
|
50,
|
||||||
initialFirstRowIndex: _firstRowIndex,
|
],
|
||||||
availableRowsPerPage: [
|
onRowsPerPageChanged: (value) {
|
||||||
10,
|
store.dispatch(
|
||||||
25,
|
UpdateUserPreferences(rowsPerPage: value));
|
||||||
50,
|
},
|
||||||
],
|
),
|
||||||
onRowsPerPageChanged: (value) {
|
|
||||||
store.dispatch(UpdateUserPreferences(rowsPerPage: value));
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue