Custom filters

This commit is contained in:
Hillel Coren 2018-08-17 15:58:21 -07:00
parent 37dda74dfa
commit 5eddfadee2
6 changed files with 166 additions and 33 deletions

View File

@ -254,18 +254,22 @@ abstract class CompanyEntity
} }
} }
List<String> getCustomFieldValues(String field) { List<String> getCustomFieldValues(String field, {bool excludeBlank = false}) {
final values = customFields[field]; final values = customFields[field];
if (values == null || !values.contains('|')) { if (values == null || !values.contains('|')) {
return []; return [];
} else { } else {
return values.split('|').last.split(','); final data = values.split('|').last.split(',');
if (excludeBlank) {
return data.where((data) => data.isNotEmpty).toList();
} else {
return data;
}
} }
} }
//UserEntity get user => userMap[userId];
static Serializer<CompanyEntity> get serializer => _$companyEntitySerializer; static Serializer<CompanyEntity> get serializer => _$companyEntitySerializer;
} }

View File

@ -222,6 +222,12 @@ Serializers _$serializers = (new Serializers().toBuilder()
..addBuilderFactory( ..addBuilderFactory(
const FullType(BuiltList, const [const FullType(EntityStatus)]), const FullType(BuiltList, const [const FullType(EntityStatus)]),
() => new ListBuilder<EntityStatus>()) () => new ListBuilder<EntityStatus>())
..addBuilderFactory(
const FullType(BuiltList, const [const FullType(String)]),
() => new ListBuilder<String>())
..addBuilderFactory(
const FullType(BuiltList, const [const FullType(String)]),
() => new ListBuilder<String>())
..addBuilderFactory( ..addBuilderFactory(
const FullType( const FullType(
BuiltList, const [const FullType(ExpenseCategoryEntity)]), BuiltList, const [const FullType(ExpenseCategoryEntity)]),
@ -320,9 +326,7 @@ Serializers _$serializers = (new Serializers().toBuilder()
const FullType(BuiltMap, const FullType(BuiltMap,
const [const FullType(int), const FullType(DateFormatEntity)]), const [const FullType(int), const FullType(DateFormatEntity)]),
() => new MapBuilder<int, DateFormatEntity>()) () => new MapBuilder<int, DateFormatEntity>())
..addBuilderFactory( ..addBuilderFactory(const FullType(BuiltMap, const [const FullType(int), const FullType(DatetimeFormatEntity)]), () => new MapBuilder<int, DatetimeFormatEntity>())
const FullType(BuiltMap, const [const FullType(int), const FullType(DatetimeFormatEntity)]),
() => new MapBuilder<int, DatetimeFormatEntity>())
..addBuilderFactory(const FullType(BuiltMap, const [const FullType(int), const FullType(LanguageEntity)]), () => new MapBuilder<int, LanguageEntity>()) ..addBuilderFactory(const FullType(BuiltMap, const [const FullType(int), const FullType(LanguageEntity)]), () => new MapBuilder<int, LanguageEntity>())
..addBuilderFactory(const FullType(BuiltMap, const [const FullType(int), const FullType(PaymentTypeEntity)]), () => new MapBuilder<int, PaymentTypeEntity>()) ..addBuilderFactory(const FullType(BuiltMap, const [const FullType(int), const FullType(PaymentTypeEntity)]), () => new MapBuilder<int, PaymentTypeEntity>())
..addBuilderFactory(const FullType(BuiltMap, const [const FullType(int), const FullType(CountryEntity)]), () => new MapBuilder<int, CountryEntity>()) ..addBuilderFactory(const FullType(BuiltMap, const [const FullType(int), const FullType(CountryEntity)]), () => new MapBuilder<int, CountryEntity>())

View File

@ -15,6 +15,8 @@ abstract class ListUIState implements Built<ListUIState, ListUIStateBuilder> {
EntityState.active, EntityState.active,
]), ]),
statusFilters: BuiltList<EntityStatus>(), statusFilters: BuiltList<EntityStatus>(),
custom1Filters: BuiltList<String>(),
custom2Filters: BuiltList<String>(),
); );
} }
ListUIState._(); ListUIState._();
@ -29,6 +31,8 @@ abstract class ListUIState implements Built<ListUIState, ListUIStateBuilder> {
bool get sortAscending; bool get sortAscending;
BuiltList<EntityState> get stateFilters; BuiltList<EntityState> get stateFilters;
BuiltList<EntityStatus> get statusFilters; BuiltList<EntityStatus> get statusFilters;
BuiltList<String> get custom1Filters;
BuiltList<String> get custom2Filters;
bool get hasCustomStateFilters => stateFilters.length != 1 || stateFilters.first != EntityState.active; bool get hasCustomStateFilters => stateFilters.length != 1 || stateFilters.first != EntityState.active;
bool get hasCustomStatusFilters => statusFilters.isNotEmpty; bool get hasCustomStatusFilters => statusFilters.isNotEmpty;

View File

@ -42,6 +42,14 @@ class _$ListUIStateSerializer implements StructuredSerializer<ListUIState> {
serializers.serialize(object.statusFilters, serializers.serialize(object.statusFilters,
specifiedType: specifiedType:
const FullType(BuiltList, const [const FullType(EntityStatus)])), const FullType(BuiltList, const [const FullType(EntityStatus)])),
'custom1Filters',
serializers.serialize(object.custom1Filters,
specifiedType:
const FullType(BuiltList, const [const FullType(String)])),
'custom2Filters',
serializers.serialize(object.custom2Filters,
specifiedType:
const FullType(BuiltList, const [const FullType(String)])),
]; ];
if (object.filter != null) { if (object.filter != null) {
result result
@ -98,6 +106,18 @@ class _$ListUIStateSerializer implements StructuredSerializer<ListUIState> {
BuiltList, const [const FullType(EntityStatus)])) BuiltList, const [const FullType(EntityStatus)]))
as BuiltList); as BuiltList);
break; break;
case 'custom1Filters':
result.custom1Filters.replace(serializers.deserialize(value,
specifiedType:
const FullType(BuiltList, const [const FullType(String)]))
as BuiltList);
break;
case 'custom2Filters':
result.custom2Filters.replace(serializers.deserialize(value,
specifiedType:
const FullType(BuiltList, const [const FullType(String)]))
as BuiltList);
break;
} }
} }
@ -118,6 +138,10 @@ class _$ListUIState extends ListUIState {
final BuiltList<EntityState> stateFilters; final BuiltList<EntityState> stateFilters;
@override @override
final BuiltList<EntityStatus> statusFilters; final BuiltList<EntityStatus> statusFilters;
@override
final BuiltList<String> custom1Filters;
@override
final BuiltList<String> custom2Filters;
factory _$ListUIState([void updates(ListUIStateBuilder b)]) => factory _$ListUIState([void updates(ListUIStateBuilder b)]) =>
(new ListUIStateBuilder()..update(updates)).build(); (new ListUIStateBuilder()..update(updates)).build();
@ -128,7 +152,9 @@ class _$ListUIState extends ListUIState {
this.sortField, this.sortField,
this.sortAscending, this.sortAscending,
this.stateFilters, this.stateFilters,
this.statusFilters}) this.statusFilters,
this.custom1Filters,
this.custom2Filters})
: super._() { : super._() {
if (sortField == null) if (sortField == null)
throw new BuiltValueNullFieldError('ListUIState', 'sortField'); throw new BuiltValueNullFieldError('ListUIState', 'sortField');
@ -138,6 +164,10 @@ class _$ListUIState extends ListUIState {
throw new BuiltValueNullFieldError('ListUIState', 'stateFilters'); throw new BuiltValueNullFieldError('ListUIState', 'stateFilters');
if (statusFilters == null) if (statusFilters == null)
throw new BuiltValueNullFieldError('ListUIState', 'statusFilters'); throw new BuiltValueNullFieldError('ListUIState', 'statusFilters');
if (custom1Filters == null)
throw new BuiltValueNullFieldError('ListUIState', 'custom1Filters');
if (custom2Filters == null)
throw new BuiltValueNullFieldError('ListUIState', 'custom2Filters');
} }
@override @override
@ -156,7 +186,9 @@ class _$ListUIState extends ListUIState {
sortField == other.sortField && sortField == other.sortField &&
sortAscending == other.sortAscending && sortAscending == other.sortAscending &&
stateFilters == other.stateFilters && stateFilters == other.stateFilters &&
statusFilters == other.statusFilters; statusFilters == other.statusFilters &&
custom1Filters == other.custom1Filters &&
custom2Filters == other.custom2Filters;
} }
@override @override
@ -164,11 +196,17 @@ class _$ListUIState extends ListUIState {
return $jf($jc( return $jf($jc(
$jc( $jc(
$jc( $jc(
$jc($jc($jc(0, filter.hashCode), filterClientId.hashCode), $jc(
sortField.hashCode), $jc(
sortAscending.hashCode), $jc(
stateFilters.hashCode), $jc($jc(0, filter.hashCode),
statusFilters.hashCode)); filterClientId.hashCode),
sortField.hashCode),
sortAscending.hashCode),
stateFilters.hashCode),
statusFilters.hashCode),
custom1Filters.hashCode),
custom2Filters.hashCode));
} }
@override @override
@ -179,7 +217,9 @@ class _$ListUIState extends ListUIState {
..add('sortField', sortField) ..add('sortField', sortField)
..add('sortAscending', sortAscending) ..add('sortAscending', sortAscending)
..add('stateFilters', stateFilters) ..add('stateFilters', stateFilters)
..add('statusFilters', statusFilters)) ..add('statusFilters', statusFilters)
..add('custom1Filters', custom1Filters)
..add('custom2Filters', custom2Filters))
.toString(); .toString();
} }
} }
@ -217,6 +257,18 @@ class ListUIStateBuilder implements Builder<ListUIState, ListUIStateBuilder> {
set statusFilters(ListBuilder<EntityStatus> statusFilters) => set statusFilters(ListBuilder<EntityStatus> statusFilters) =>
_$this._statusFilters = statusFilters; _$this._statusFilters = statusFilters;
ListBuilder<String> _custom1Filters;
ListBuilder<String> get custom1Filters =>
_$this._custom1Filters ??= new ListBuilder<String>();
set custom1Filters(ListBuilder<String> custom1Filters) =>
_$this._custom1Filters = custom1Filters;
ListBuilder<String> _custom2Filters;
ListBuilder<String> get custom2Filters =>
_$this._custom2Filters ??= new ListBuilder<String>();
set custom2Filters(ListBuilder<String> custom2Filters) =>
_$this._custom2Filters = custom2Filters;
ListUIStateBuilder(); ListUIStateBuilder();
ListUIStateBuilder get _$this { ListUIStateBuilder get _$this {
@ -227,6 +279,8 @@ class ListUIStateBuilder implements Builder<ListUIState, ListUIStateBuilder> {
_sortAscending = _$v.sortAscending; _sortAscending = _$v.sortAscending;
_stateFilters = _$v.stateFilters?.toBuilder(); _stateFilters = _$v.stateFilters?.toBuilder();
_statusFilters = _$v.statusFilters?.toBuilder(); _statusFilters = _$v.statusFilters?.toBuilder();
_custom1Filters = _$v.custom1Filters?.toBuilder();
_custom2Filters = _$v.custom2Filters?.toBuilder();
_$v = null; _$v = null;
} }
return this; return this;
@ -254,7 +308,9 @@ class ListUIStateBuilder implements Builder<ListUIState, ListUIStateBuilder> {
sortField: sortField, sortField: sortField,
sortAscending: sortAscending, sortAscending: sortAscending,
stateFilters: stateFilters.build(), stateFilters: stateFilters.build(),
statusFilters: statusFilters.build()); statusFilters: statusFilters.build(),
custom1Filters: custom1Filters.build(),
custom2Filters: custom2Filters.build());
} catch (_) { } catch (_) {
String _$failedField; String _$failedField;
try { try {
@ -262,6 +318,10 @@ class ListUIStateBuilder implements Builder<ListUIState, ListUIStateBuilder> {
stateFilters.build(); stateFilters.build();
_$failedField = 'statusFilters'; _$failedField = 'statusFilters';
statusFilters.build(); statusFilters.build();
_$failedField = 'custom1Filters';
custom1Filters.build();
_$failedField = 'custom2Filters';
custom2Filters.build();
} catch (e) { } catch (e) {
throw new BuiltValueNestedFieldError( throw new BuiltValueNestedFieldError(
'ListUIState', _$failedField, e.toString()); 'ListUIState', _$failedField, e.toString());

View File

@ -14,14 +14,18 @@ class AppBottomBar extends StatefulWidget {
final Function(String) onSelectedSortField; final Function(String) onSelectedSortField;
final Function(EntityState, bool) onSelectedState; final Function(EntityState, bool) onSelectedState;
final Function(EntityStatus, bool) onSelectedStatus; final Function(EntityStatus, bool) onSelectedStatus;
final List<String> customValues1;
final List<String> customValues2;
const AppBottomBar({ const AppBottomBar({
this.sortFields, this.sortFields,
this.onSelectedSortField, this.onSelectedSortField,
this.entityType, this.entityType,
this.onSelectedState, this.onSelectedState,
this.statuses,
this.onSelectedStatus, this.onSelectedStatus,
this.statuses = const [],
this.customValues1 = const [],
this.customValues2 = const [],
}); });
@override @override
@ -32,9 +36,12 @@ class _AppBottomBarState extends State<AppBottomBar> {
PersistentBottomSheetController _sortController; PersistentBottomSheetController _sortController;
PersistentBottomSheetController _filterStateController; PersistentBottomSheetController _filterStateController;
PersistentBottomSheetController _filterStatusController; PersistentBottomSheetController _filterStatusController;
PersistentBottomSheetController _filterCustom1Controller;
PersistentBottomSheetController _filterCustom2Controller;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final _showFilterStateSheet = () { final _showFilterStateSheet = () {
if (_filterStateController != null) { if (_filterStateController != null) {
_filterStateController.close(); _filterStateController.close();
@ -44,7 +51,6 @@ class _AppBottomBarState extends State<AppBottomBar> {
_filterStateController = _filterStateController =
Scaffold.of(context).showBottomSheet<StoreConnector>((context) { Scaffold.of(context).showBottomSheet<StoreConnector>((context) {
return StoreConnector<AppState, BuiltList<EntityState>>( return StoreConnector<AppState, BuiltList<EntityState>>(
//distinct: true,
converter: (Store<AppState> store) => converter: (Store<AppState> store) =>
store.state.getListState(widget.entityType).stateFilters, store.state.getListState(widget.entityType).stateFilters,
builder: (BuildContext context, stateFilters) { builder: (BuildContext context, stateFilters) {
@ -165,6 +171,47 @@ class _AppBottomBarState extends State<AppBottomBar> {
}); });
}; };
final _showFilterCustom1Sheet = () {
if (_filterCustom1Controller != null) {
_filterCustom1Controller.close();
return;
}
_filterCustom1Controller =
Scaffold.of(context).showBottomSheet<StoreConnector>((context) {
return StoreConnector<AppState, BuiltList<String>>(
converter: (Store<AppState> store) =>
store.state.getListState(widget.entityType).custom1Filters,
builder: (BuildContext context, customFilters) {
return Container(
color: Theme.of(context).backgroundColor,
child: Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
Column(
children: widget.customValues1.map<Widget>((customField) {
return CheckboxListTile(
key: Key(customField.toString()),
title: Text(customField),
controlAffinity: ListTileControlAffinity.leading,
value: customFilters.contains(customField),
activeColor: Theme.of(context).accentColor,
dense: true,
onChanged: (value) {
//widget.onSelectedState(customField, value);
},
);
}).toList(),
),
]),
);
},
);
});
_filterCustom1Controller.closed.whenComplete(() {
_filterCustom1Controller = null;
});
};
return StoreBuilder(builder: (BuildContext context, Store<AppState> store) { return StoreBuilder(builder: (BuildContext context, Store<AppState> store) {
return BottomAppBar( return BottomAppBar(
shape: CircularNotchedRectangle(), shape: CircularNotchedRectangle(),
@ -185,19 +232,28 @@ class _AppBottomBarState extends State<AppBottomBar> {
? Theme.of(context).accentColor ? Theme.of(context).accentColor
: null, : null,
), ),
Opacity( widget.statuses.isNotEmpty ? IconButton(
opacity: widget.statuses == null ? 0.0 : 1.0, tooltip: AppLocalization.of(context).filter,
child: IconButton( icon: Icon(Icons.filter),
tooltip: AppLocalization.of(context).filter, onPressed: _showFilterStatusSheet,
icon: Icon(Icons.filter), color: store.state
onPressed: _showFilterStatusSheet, .getListState(widget.entityType)
color: store.state .hasCustomStatusFilters
.getListState(widget.entityType) ? Theme.of(context).accentColor
.hasCustomStatusFilters : null,
? Theme.of(context).accentColor ) : SizedBox(width: 0.0),
: null, widget.customValues1.isNotEmpty ? IconButton(
), tooltip: AppLocalization.of(context).filter,
), icon: Icon(Icons.looks_one),
onPressed: _showFilterCustom1Sheet,
/*
color: store.state
.getListState(widget.entityType)
.hasCustomStatusFilters
? Theme.of(context).accentColor
: null,
*/
) : SizedBox(width: 0.0)
], ],
), ),
); );

View File

@ -17,7 +17,8 @@ class ProductScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final store = StoreProvider.of<AppState>(context); final store = StoreProvider.of<AppState>(context);
final user = store.state.user; final company = store.state.selectedCompany;
final user = company.user;
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);
return Scaffold( return Scaffold(
@ -41,6 +42,10 @@ class ProductScreen extends StatelessWidget {
body: ProductListBuilder(), body: ProductListBuilder(),
bottomNavigationBar: AppBottomBar( bottomNavigationBar: AppBottomBar(
entityType: EntityType.product, entityType: EntityType.product,
customValues1: company.getCustomFieldValues(CustomFieldType.product1,
excludeBlank: true),
customValues2: company.getCustomFieldValues(CustomFieldType.product2,
excludeBlank: true),
onSelectedSortField: (value) { onSelectedSortField: (value) {
store.dispatch(SortProducts(value)); store.dispatch(SortProducts(value));
}, },