diff --git a/lib/redux/app/app_reducer.dart b/lib/redux/app/app_reducer.dart index 10f645b30..21399b8b8 100644 --- a/lib/redux/app/app_reducer.dart +++ b/lib/redux/app/app_reducer.dart @@ -1,3 +1,4 @@ +import 'package:invoiceninja/redux/app/ui_reducer.dart'; import 'package:invoiceninja/redux/auth/auth_actions.dart'; import 'package:redux/redux.dart'; import 'package:invoiceninja/redux/app/app_state.dart'; @@ -26,6 +27,7 @@ AppState appReducer(AppState state, action) { ? companyReducer(state.companyState4, action) : state.companyState4) ..companyState5.replace(state.selectedCompanyIndex == 5 ? companyReducer(state.companyState5, action) : state.companyState5) + ..uiState.replace(uiReducer(state.uiState, action)) ); } diff --git a/lib/redux/app/app_state.dart b/lib/redux/app/app_state.dart index 11d47e4d9..890ad247b 100644 --- a/lib/redux/app/app_state.dart +++ b/lib/redux/app/app_state.dart @@ -1,4 +1,6 @@ import 'package:invoiceninja/data/models/models.dart'; +import 'package:invoiceninja/redux/app/ui_state.dart'; +import 'package:invoiceninja/redux/app/entity_ui_state.dart'; import 'package:invoiceninja/redux/auth/auth_state.dart'; import 'package:invoiceninja/redux/company/company_state.dart'; import 'package:invoiceninja/redux/product/product_state.dart'; @@ -17,6 +19,7 @@ abstract class AppState implements Built { CompanyState get companyState3; CompanyState get companyState4; CompanyState get companyState5; + UIState get uiState; factory AppState() { return _$AppState._( @@ -28,6 +31,7 @@ abstract class AppState implements Built { companyState3: CompanyState(), companyState4: CompanyState(), companyState5: CompanyState(), + uiState: UIState(), ); } @@ -56,11 +60,16 @@ abstract class AppState implements Built { return this.selectedCompanyState().company; } + DashboardState dashboardState() { + return this.selectedCompanyState().dashboardState; + } + ProductState productState() { return this.selectedCompanyState().productState; } - DashboardState dashboardState() { - return this.selectedCompanyState().dashboardState; + EntityUIState productUIState() { + return this.uiState.productUIState; } + } \ No newline at end of file diff --git a/lib/redux/app/app_state.g.dart b/lib/redux/app/app_state.g.dart index 43f633dbf..8abf93015 100644 --- a/lib/redux/app/app_state.g.dart +++ b/lib/redux/app/app_state.g.dart @@ -50,6 +50,9 @@ class _$AppStateSerializer implements StructuredSerializer { 'companyState5', serializers.serialize(object.companyState5, specifiedType: const FullType(CompanyState)), + 'uiState', + serializers.serialize(object.uiState, + specifiedType: const FullType(UIState)), ]; return result; @@ -98,6 +101,10 @@ class _$AppStateSerializer implements StructuredSerializer { result.companyState5.replace(serializers.deserialize(value, specifiedType: const FullType(CompanyState)) as CompanyState); break; + case 'uiState': + result.uiState.replace(serializers.deserialize(value, + specifiedType: const FullType(UIState)) as UIState); + break; } } @@ -122,6 +129,8 @@ class _$AppState extends AppState { final CompanyState companyState4; @override final CompanyState companyState5; + @override + final UIState uiState; factory _$AppState([void updates(AppStateBuilder b)]) => (new AppStateBuilder()..update(updates)).build(); @@ -134,7 +143,8 @@ class _$AppState extends AppState { this.companyState2, this.companyState3, this.companyState4, - this.companyState5}) + this.companyState5, + this.uiState}) : super._() { if (isLoading == null) throw new BuiltValueNullFieldError('AppState', 'isLoading'); @@ -152,6 +162,8 @@ class _$AppState extends AppState { throw new BuiltValueNullFieldError('AppState', 'companyState4'); if (companyState5 == null) throw new BuiltValueNullFieldError('AppState', 'companyState5'); + if (uiState == null) + throw new BuiltValueNullFieldError('AppState', 'uiState'); } @override @@ -172,7 +184,8 @@ class _$AppState extends AppState { companyState2 == other.companyState2 && companyState3 == other.companyState3 && companyState4 == other.companyState4 && - companyState5 == other.companyState5; + companyState5 == other.companyState5 && + uiState == other.uiState; } @override @@ -182,13 +195,17 @@ class _$AppState extends AppState { $jc( $jc( $jc( - $jc($jc($jc(0, isLoading.hashCode), authState.hashCode), - selectedCompanyIndex.hashCode), - companyState1.hashCode), - companyState2.hashCode), - companyState3.hashCode), - companyState4.hashCode), - companyState5.hashCode)); + $jc( + $jc( + $jc($jc(0, isLoading.hashCode), + authState.hashCode), + selectedCompanyIndex.hashCode), + companyState1.hashCode), + companyState2.hashCode), + companyState3.hashCode), + companyState4.hashCode), + companyState5.hashCode), + uiState.hashCode)); } @override @@ -201,7 +218,8 @@ class _$AppState extends AppState { ..add('companyState2', companyState2) ..add('companyState3', companyState3) ..add('companyState4', companyState4) - ..add('companyState5', companyState5)) + ..add('companyState5', companyState5) + ..add('uiState', uiState)) .toString(); } } @@ -253,6 +271,10 @@ class AppStateBuilder implements Builder { set companyState5(CompanyStateBuilder companyState5) => _$this._companyState5 = companyState5; + UIStateBuilder _uiState; + UIStateBuilder get uiState => _$this._uiState ??= new UIStateBuilder(); + set uiState(UIStateBuilder uiState) => _$this._uiState = uiState; + AppStateBuilder(); AppStateBuilder get _$this { @@ -265,6 +287,7 @@ class AppStateBuilder implements Builder { _companyState3 = _$v.companyState3?.toBuilder(); _companyState4 = _$v.companyState4?.toBuilder(); _companyState5 = _$v.companyState5?.toBuilder(); + _uiState = _$v.uiState?.toBuilder(); _$v = null; } return this; @@ -294,7 +317,8 @@ class AppStateBuilder implements Builder { companyState2: companyState2.build(), companyState3: companyState3.build(), companyState4: companyState4.build(), - companyState5: companyState5.build()); + companyState5: companyState5.build(), + uiState: uiState.build()); } catch (_) { String _$failedField; try { @@ -311,6 +335,8 @@ class AppStateBuilder implements Builder { companyState4.build(); _$failedField = 'companyState5'; companyState5.build(); + _$failedField = 'uiState'; + uiState.build(); } catch (e) { throw new BuiltValueNestedFieldError( 'AppState', _$failedField, e.toString()); diff --git a/lib/redux/app/entity_ui_state.dart b/lib/redux/app/entity_ui_state.dart new file mode 100644 index 000000000..73d2af749 --- /dev/null +++ b/lib/redux/app/entity_ui_state.dart @@ -0,0 +1,13 @@ +import 'package:built_value/built_value.dart'; +import 'package:built_value/serializer.dart'; + +part 'entity_ui_state.g.dart'; + +abstract class EntityUIState implements Built { + + String get sortField; + + EntityUIState._(); + factory EntityUIState([updates(EntityUIStateBuilder b)]) = _$EntityUIState; + static Serializer get serializer => _$entityUIStateSerializer; +} \ No newline at end of file diff --git a/lib/redux/app/entity_ui_state.g.dart b/lib/redux/app/entity_ui_state.g.dart new file mode 100644 index 000000000..057dd4f0a --- /dev/null +++ b/lib/redux/app/entity_ui_state.g.dart @@ -0,0 +1,134 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'entity_ui_state.dart'; + +// ************************************************************************** +// Generator: BuiltValueGenerator +// ************************************************************************** + +// ignore_for_file: always_put_control_body_on_new_line +// ignore_for_file: annotate_overrides +// ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_returning_this +// ignore_for_file: omit_local_variable_types +// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: sort_constructors_first + +Serializer _$entityUIStateSerializer = + new _$EntityUIStateSerializer(); + +class _$EntityUIStateSerializer implements StructuredSerializer { + @override + final Iterable types = const [EntityUIState, _$EntityUIState]; + @override + final String wireName = 'EntityUIState'; + + @override + Iterable serialize(Serializers serializers, EntityUIState object, + {FullType specifiedType: FullType.unspecified}) { + final result = [ + 'sortField', + serializers.serialize(object.sortField, + specifiedType: const FullType(String)), + ]; + + return result; + } + + @override + EntityUIState deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType: FullType.unspecified}) { + final result = new EntityUIStateBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current as String; + iterator.moveNext(); + final dynamic value = iterator.current; + switch (key) { + case 'sortField': + result.sortField = serializers.deserialize(value, + specifiedType: const FullType(String)) as String; + break; + } + } + + return result.build(); + } +} + +class _$EntityUIState extends EntityUIState { + @override + final String sortField; + + factory _$EntityUIState([void updates(EntityUIStateBuilder b)]) => + (new EntityUIStateBuilder()..update(updates)).build(); + + _$EntityUIState._({this.sortField}) : super._() { + if (sortField == null) + throw new BuiltValueNullFieldError('EntityUIState', 'sortField'); + } + + @override + EntityUIState rebuild(void updates(EntityUIStateBuilder b)) => + (toBuilder()..update(updates)).build(); + + @override + EntityUIStateBuilder toBuilder() => new EntityUIStateBuilder()..replace(this); + + @override + bool operator ==(dynamic other) { + if (identical(other, this)) return true; + if (other is! EntityUIState) return false; + return sortField == other.sortField; + } + + @override + int get hashCode { + return $jf($jc(0, sortField.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('EntityUIState') + ..add('sortField', sortField)) + .toString(); + } +} + +class EntityUIStateBuilder + implements Builder { + _$EntityUIState _$v; + + String _sortField; + String get sortField => _$this._sortField; + set sortField(String sortField) => _$this._sortField = sortField; + + EntityUIStateBuilder(); + + EntityUIStateBuilder get _$this { + if (_$v != null) { + _sortField = _$v.sortField; + _$v = null; + } + return this; + } + + @override + void replace(EntityUIState other) { + if (other == null) throw new ArgumentError.notNull('other'); + _$v = other as _$EntityUIState; + } + + @override + void update(void updates(EntityUIStateBuilder b)) { + if (updates != null) updates(this); + } + + @override + _$EntityUIState build() { + final _$result = _$v ?? new _$EntityUIState._(sortField: sortField); + replace(_$result); + return _$result; + } +} diff --git a/lib/redux/app/ui_reducer.dart b/lib/redux/app/ui_reducer.dart new file mode 100644 index 000000000..daa0e76b9 --- /dev/null +++ b/lib/redux/app/ui_reducer.dart @@ -0,0 +1,9 @@ +import 'package:invoiceninja/redux/app/ui_state.dart'; +import 'package:invoiceninja/redux/product/product_reducer.dart'; + +UIState uiReducer(UIState state, action) { + + return state.rebuild((b) => b + ..productUIState.replace(productUIReducer(state.productUIState, action)) + ); +} \ No newline at end of file diff --git a/lib/redux/app/ui_state.dart b/lib/redux/app/ui_state.dart new file mode 100644 index 000000000..527ba8b34 --- /dev/null +++ b/lib/redux/app/ui_state.dart @@ -0,0 +1,21 @@ +import 'package:built_value/built_value.dart'; +import 'package:built_value/serializer.dart'; +import 'package:invoiceninja/redux/app/entity_ui_state.dart'; + +part 'ui_state.g.dart'; + +abstract class UIState implements Built { + + EntityUIState get productUIState; + + factory UIState() { + return _$UIState._( + productUIState: EntityUIState(), + ); + } + + UIState._(); + //factory UIState([updates(UIStateBuilder b)]) = _$UIState; + static Serializer get serializer => _$uIStateSerializer; +} + diff --git a/lib/redux/app/ui_state.g.dart b/lib/redux/app/ui_state.g.dart new file mode 100644 index 000000000..879d654f3 --- /dev/null +++ b/lib/redux/app/ui_state.g.dart @@ -0,0 +1,147 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'ui_state.dart'; + +// ************************************************************************** +// Generator: BuiltValueGenerator +// ************************************************************************** + +// ignore_for_file: always_put_control_body_on_new_line +// ignore_for_file: annotate_overrides +// ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_returning_this +// ignore_for_file: omit_local_variable_types +// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: sort_constructors_first + +Serializer _$uIStateSerializer = new _$UIStateSerializer(); + +class _$UIStateSerializer implements StructuredSerializer { + @override + final Iterable types = const [UIState, _$UIState]; + @override + final String wireName = 'UIState'; + + @override + Iterable serialize(Serializers serializers, UIState object, + {FullType specifiedType: FullType.unspecified}) { + final result = [ + 'productUIState', + serializers.serialize(object.productUIState, + specifiedType: const FullType(EntityUIState)), + ]; + + return result; + } + + @override + UIState deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType: FullType.unspecified}) { + final result = new UIStateBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current as String; + iterator.moveNext(); + final dynamic value = iterator.current; + switch (key) { + case 'productUIState': + result.productUIState.replace(serializers.deserialize(value, + specifiedType: const FullType(EntityUIState)) as EntityUIState); + break; + } + } + + return result.build(); + } +} + +class _$UIState extends UIState { + @override + final EntityUIState productUIState; + + factory _$UIState([void updates(UIStateBuilder b)]) => + (new UIStateBuilder()..update(updates)).build(); + + _$UIState._({this.productUIState}) : super._() { + if (productUIState == null) + throw new BuiltValueNullFieldError('UIState', 'productUIState'); + } + + @override + UIState rebuild(void updates(UIStateBuilder b)) => + (toBuilder()..update(updates)).build(); + + @override + UIStateBuilder toBuilder() => new UIStateBuilder()..replace(this); + + @override + bool operator ==(dynamic other) { + if (identical(other, this)) return true; + if (other is! UIState) return false; + return productUIState == other.productUIState; + } + + @override + int get hashCode { + return $jf($jc(0, productUIState.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('UIState') + ..add('productUIState', productUIState)) + .toString(); + } +} + +class UIStateBuilder implements Builder { + _$UIState _$v; + + EntityUIStateBuilder _productUIState; + EntityUIStateBuilder get productUIState => + _$this._productUIState ??= new EntityUIStateBuilder(); + set productUIState(EntityUIStateBuilder productUIState) => + _$this._productUIState = productUIState; + + UIStateBuilder(); + + UIStateBuilder get _$this { + if (_$v != null) { + _productUIState = _$v.productUIState?.toBuilder(); + _$v = null; + } + return this; + } + + @override + void replace(UIState other) { + if (other == null) throw new ArgumentError.notNull('other'); + _$v = other as _$UIState; + } + + @override + void update(void updates(UIStateBuilder b)) { + if (updates != null) updates(this); + } + + @override + _$UIState build() { + _$UIState _$result; + try { + _$result = _$v ?? new _$UIState._(productUIState: productUIState.build()); + } catch (_) { + String _$failedField; + try { + _$failedField = 'productUIState'; + productUIState.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'UIState', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} diff --git a/lib/redux/product/product_actions.dart b/lib/redux/product/product_actions.dart index 71219e0d7..d40a70a6e 100644 --- a/lib/redux/product/product_actions.dart +++ b/lib/redux/product/product_actions.dart @@ -11,7 +11,6 @@ class LoadProductsAction { class ProductsNotLoadedAction { final dynamic error; - ProductsNotLoadedAction(this.error); @override @@ -22,7 +21,6 @@ class ProductsNotLoadedAction { class ProductsLoadedAction { final BuiltList products; - ProductsLoadedAction(this.products); @override @@ -33,14 +31,12 @@ class ProductsLoadedAction { class SelectProductAction { final ProductEntity product; - SelectProductAction(this.product); } class SaveProductRequest { final Completer completer; final ProductEntity product; - SaveProductRequest(this.completer, this.product); } @@ -71,7 +67,6 @@ class DeleteProductFailure {} class RestoreProductRequest { final Completer completer; final int productId; - RestoreProductRequest(this.completer, this.productId); } class RestoreProductSuccess {} @@ -79,12 +74,15 @@ class RestoreProductFailure {} class AddProductSuccess { final ProductEntity product; - AddProductSuccess(this.product); } class SaveProductFailure { final String error; - SaveProductFailure (this.error); +} + +class SortProducts { + final String field; + SortProducts(this.field); } \ No newline at end of file diff --git a/lib/redux/product/product_reducer.dart b/lib/redux/product/product_reducer.dart index 65333c363..c53a5b0cd 100644 --- a/lib/redux/product/product_reducer.dart +++ b/lib/redux/product/product_reducer.dart @@ -1,7 +1,18 @@ +import 'package:invoiceninja/redux/app/entity_ui_state.dart'; import 'package:redux/redux.dart'; import 'package:invoiceninja/redux/product/product_actions.dart'; import 'package:invoiceninja/redux/product/product_state.dart'; +final productUIReducer = combineReducers([ + TypedReducer(_sortProducts), +]); + +EntityUIState _sortProducts(EntityUIState productUIState, SortProducts action) { + return productUIState.rebuild((b) => b + ..sortField = action.field + ); +} + final productsReducer = combineReducers([ /* TypedReducer, AddProductAction>(_addProduct), diff --git a/lib/ui/app/action_popup_menu.dart b/lib/ui/app/action_popup_menu.dart index 3da940591..a498d951c 100644 --- a/lib/ui/app/action_popup_menu.dart +++ b/lib/ui/app/action_popup_menu.dart @@ -66,9 +66,12 @@ class ActionMenuButton extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: sortFields.map((sortField) { return RadioListTile( + dense: true, title: Text(sortField.label), - groupValue: 'sort', - onChanged: (String) {}, + groupValue: ActionMenuButtonType.sort, + onChanged: (value) { + print('value changed: ' + value); + }, value: sortField.field, ); }).toList()),