Subscriptions

This commit is contained in:
Hillel Coren 2021-03-24 20:23:43 +02:00
parent f5d3486dac
commit 7ecdb6c6a5
28 changed files with 166 additions and 149 deletions

View File

@ -517,7 +517,7 @@ abstract class CompanyEntity extends Object
..passwordTimeout = 30 * 60 * 1000
..oauthPasswordRequired = false
..invoiceTaskDatelog = true
..subscriptions = BuiltList<SubscriptionEntity>();
..subscriptions.replace(BuiltList<SubscriptionEntity>());
static Serializer<CompanyEntity> get serializer => _$companyEntitySerializer;
}

View File

@ -8,6 +8,7 @@ export 'package:invoiceninja_flutter/data/models/company_model.dart';
export 'package:invoiceninja_flutter/data/models/credit_model.dart';
export 'package:invoiceninja_flutter/data/models/tax_rate_model.dart';
export 'package:invoiceninja_flutter/data/models/document_model.dart';
export 'package:invoiceninja_flutter/data/models/settings_model.dart';
export 'package:invoiceninja_flutter/data/models/entities.dart';
export 'package:invoiceninja_flutter/data/models/expense_model.dart';
export 'package:invoiceninja_flutter/data/models/subscription_model.dart';

View File

@ -46,7 +46,8 @@ abstract class SubscriptionItemResponse
}
class SubscriptionFields {
// STARTER: fields - do not remove comment
static const String createdAt = 'created_at';
static const String updatedAt = 'updated_at';
}
abstract class SubscriptionEntity extends Object

View File

@ -47,7 +47,6 @@ List<String> filteredClientsSelector(
ListUIState clientListState,
BuiltMap<String, UserEntity> userMap,
StaticState staticState) {
final filterEntityId = selectionState.filterEntityId;
final filterEntityType = selectionState.filterEntityType;

View File

@ -6,6 +6,7 @@ import 'package:invoiceninja_flutter/data/models/client_model.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/group_model.dart';
import 'package:invoiceninja_flutter/data/models/settings_model.dart';
import 'package:invoiceninja_flutter/data/models/user_model.dart';
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
import 'package:invoiceninja_flutter/redux/auth/auth_actions.dart';

View File

@ -1,4 +1,5 @@
import 'package:invoiceninja_flutter/data/models/subscription_model.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/static/static_state.dart';
import 'package:memoize/memoize.dart';
import 'package:built_collection/built_collection.dart';
@ -6,13 +7,16 @@ import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
var memoizedDropdownSubscriptionList = memo5(
(BuiltMap<String, SubscriptionEntity> subscriptionMap, BuiltList<String> subscriptionList,
StaticState staticState,
BuiltMap<String, UserEntity> userMap,
(BuiltMap<String, SubscriptionEntity> subscriptionMap,
BuiltList<String> subscriptionList,
StaticState staticState,
BuiltMap<String, UserEntity> userMap,
String clientId) =>
dropdownSubscriptionsSelector(subscriptionMap, subscriptionList, staticState, userMap, clientId));
dropdownSubscriptionsSelector(
subscriptionMap, subscriptionList, staticState, userMap, clientId));
List<String> dropdownSubscriptionsSelector(BuiltMap<String, SubscriptionEntity> subscriptionMap,
List<String> dropdownSubscriptionsSelector(
BuiltMap<String, SubscriptionEntity> subscriptionMap,
BuiltList<String> subscriptionList,
StaticState staticState,
BuiltMap<String, UserEntity> userMap,
@ -30,64 +34,60 @@ List<String> dropdownSubscriptionsSelector(BuiltMap<String, SubscriptionEntity>
list.sort((subscriptionAId, subscriptionBId) {
final subscriptionA = subscriptionMap[subscriptionAId];
final subscriptionB = subscriptionMap[subscriptionBId];
return subscriptionA.compareTo(subscriptionB, SubscriptionFields.name, true);
return subscriptionA.compareTo(
subscriptionB, SubscriptionFields.createdAt, true);
});
return list;
}
var memoizedFilteredSubscriptionList = memo7((
String filterEntityId,
EntityType filterEntityType,
var memoizedFilteredSubscriptionList = memo4((SelectionState selectionState,
BuiltMap<String, SubscriptionEntity> subscriptionMap,
BuiltList<String> subscriptionList,
StaticState staticState,
BuiltMap<String, UserEntity> userMap,
ListUIState subscriptionListState) =>
filteredSubscriptionsSelector(filterEntityId, filterEntityType, subscriptionMap, subscriptionList, staticState, userMap, subscriptionListState));
filteredSubscriptionsSelector(
selectionState,
subscriptionMap,
subscriptionList,
subscriptionListState,
));
List<String> filteredSubscriptionsSelector(
String filterEntityId,
EntityType filterEntityType,
SelectionState selectionState,
BuiltMap<String, SubscriptionEntity> subscriptionMap,
BuiltList<String> subscriptionList,
StaticState staticState,
BuiltMap<String, UserEntity> userMap,
ListUIState subscriptionListState) {
final filterEntityId = selectionState.filterEntityId;
final filterEntityType = selectionState.filterEntityType;
final list = subscriptionList.where((subscriptionId) {
final subscription = subscriptionMap[subscriptionId];
if (subscription.id == selectionState.selectedId) {
return true;
}
if (filterEntityId != null && subscription.id != filterEntityId) {
return false;
} else {
}
} else {}
if (!subscription.matchesStates(subscriptionListState.stateFilters)) {
return false;
}
if (subscriptionListState.custom1Filters.isNotEmpty &&
!subscriptionListState.custom1Filters.contains(subscription.customValue1)) {
return false;
}
if (subscriptionListState.custom2Filters.isNotEmpty &&
!subscriptionListState.custom2Filters.contains(subscription.customValue2)) {
return false;
}
return subscription.matchesFilter(subscriptionListState.filter);
}).toList();
list.sort((subscriptionAId, subscriptionBId) {
return subscriptionMap[subscriptionAId].compareTo(
subscription: subscriptionMap[subscriptionBId],
sortField: subscriptionListState.sortField,
sortAscending: subscriptionListState.sortAscending,
);
final subscriptionA = subscriptionMap[subscriptionAId];
final subscriptionB = subscriptionMap[subscriptionBId];
return subscriptionA.compareTo(subscriptionB,
subscriptionListState.sortField, subscriptionListState.sortAscending);
});
return list;
}
bool hasSubscriptionChanges(
SubscriptionEntity subscription, BuiltMap<String, SubscriptionEntity> subscriptionMap) =>
subscription.isNew ? subscription.isChanged : subscription != subscriptionMap[subscription.id];
bool hasSubscriptionChanges(SubscriptionEntity subscription,
BuiltMap<String, SubscriptionEntity> subscriptionMap) =>
subscription.isNew
? subscription.isChanged
: subscription != subscriptionMap[subscription.id];

View File

@ -9,8 +9,8 @@ import 'package:invoiceninja_flutter/data/models/models.dart';
part 'subscription_state.g.dart';
abstract class SubscriptionState implements Built<SubscriptionState, SubscriptionStateBuilder> {
abstract class SubscriptionState
implements Built<SubscriptionState, SubscriptionStateBuilder> {
factory SubscriptionState() {
return _$SubscriptionState._(
map: BuiltMap<String, SubscriptionEntity>(),
@ -46,15 +46,16 @@ abstract class SubscriptionState implements Built<SubscriptionState, Subscriptio
..list.replace((map.keys.toList() + list.toList()).toSet().toList()));
}
static Serializer<SubscriptionState> get serializer => _$subscriptionStateSerializer;
static Serializer<SubscriptionState> get serializer =>
_$subscriptionStateSerializer;
}
abstract class SubscriptionUIState extends Object with EntityUIState implements Built<SubscriptionUIState, SubscriptionUIStateBuilder> {
abstract class SubscriptionUIState extends Object
with EntityUIState
implements Built<SubscriptionUIState, SubscriptionUIStateBuilder> {
factory SubscriptionUIState() {
return _$SubscriptionUIState._(
listUIState: ListUIState(SubscriptionFields.name),
listUIState: ListUIState(SubscriptionFields.createdAt),
editing: SubscriptionEntity(),
selectedId: '',
tabIndex: 0,
@ -63,7 +64,7 @@ abstract class SubscriptionUIState extends Object with EntityUIState implements
SubscriptionUIState._();
@override
@memoized
@memoized
int get hashCode;
@nullable
@ -75,5 +76,6 @@ abstract class SubscriptionUIState extends Object with EntityUIState implements
@override
String get editingId => editing.id;
static Serializer<SubscriptionUIState> get serializer => _$subscriptionUIStateSerializer;
static Serializer<SubscriptionUIState> get serializer =>
_$subscriptionUIStateSerializer;
}

View File

@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/invoice_model.dart';
import 'package:invoiceninja_flutter/data/models/settings_model.dart';
import 'package:invoiceninja_flutter/redux/invoice/invoice_selectors.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/app/forms/app_dropdown_button.dart';

View File

@ -6,6 +6,7 @@ import 'package:invoiceninja_flutter/data/models/client_model.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/group_model.dart';
import 'package:invoiceninja_flutter/data/models/settings_model.dart';
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
import 'package:invoiceninja_flutter/redux/company/company_actions.dart';
import 'package:invoiceninja_flutter/redux/group/group_actions.dart';

View File

@ -11,6 +11,7 @@ import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/document_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/group_model.dart';
import 'package:invoiceninja_flutter/data/models/settings_model.dart';
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
import 'package:invoiceninja_flutter/redux/company/company_actions.dart';

View File

@ -6,6 +6,7 @@ import 'package:invoiceninja_flutter/data/models/client_model.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/group_model.dart';
import 'package:invoiceninja_flutter/data/models/settings_model.dart';
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
import 'package:invoiceninja_flutter/redux/company/company_actions.dart';
import 'package:invoiceninja_flutter/redux/group/group_actions.dart';

View File

@ -6,6 +6,7 @@ import 'package:invoiceninja_flutter/data/models/client_model.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/group_model.dart';
import 'package:invoiceninja_flutter/data/models/settings_model.dart';
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
import 'package:invoiceninja_flutter/redux/company/company_actions.dart';
import 'package:invoiceninja_flutter/redux/group/group_actions.dart';

View File

@ -8,6 +8,7 @@ import 'package:invoiceninja_flutter/data/models/client_model.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/group_model.dart';
import 'package:invoiceninja_flutter/data/models/settings_model.dart';
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
import 'package:invoiceninja_flutter/redux/company/company_actions.dart';

View File

@ -1,6 +1,7 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/settings_model.dart';
import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/app/forms/app_dropdown_button.dart';

View File

@ -6,6 +6,7 @@ import 'package:invoiceninja_flutter/data/models/client_model.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/group_model.dart';
import 'package:invoiceninja_flutter/data/models/settings_model.dart';
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
import 'package:invoiceninja_flutter/redux/company/company_actions.dart';
import 'package:invoiceninja_flutter/redux/group/group_actions.dart';

View File

@ -6,6 +6,7 @@ import 'package:invoiceninja_flutter/data/models/client_model.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/group_model.dart';
import 'package:invoiceninja_flutter/data/models/settings_model.dart';
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
import 'package:invoiceninja_flutter/redux/company/company_actions.dart';
import 'package:invoiceninja_flutter/redux/group/group_actions.dart';

View File

@ -3,6 +3,7 @@ import 'package:flutter/widgets.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/settings_model.dart';
import 'package:invoiceninja_flutter/redux/company/company_actions.dart';
import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart';
import 'package:invoiceninja_flutter/ui/settings/tax_settings.dart';

View File

@ -6,6 +6,7 @@ import 'package:invoiceninja_flutter/data/models/client_model.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/group_model.dart';
import 'package:invoiceninja_flutter/data/models/settings_model.dart';
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
import 'package:invoiceninja_flutter/redux/company/company_actions.dart';
import 'package:invoiceninja_flutter/redux/group/group_actions.dart';

View File

@ -1,7 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/settings_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/app/forms/app_dropdown_button.dart';

View File

@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/ui/app/edit_scaffold.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/app/scrollable_listview.dart';
import 'package:invoiceninja_flutter/ui/subscription/edit/subscription_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
@ -19,30 +20,27 @@ class SubscriptionEdit extends StatefulWidget {
}
class _SubscriptionEditState extends State<SubscriptionEdit> {
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>(debugLabel: '_subscriptionEdit');
static final GlobalKey<FormState> _formKey =
GlobalKey<FormState>(debugLabel: '_subscriptionEdit');
final _debouncer = Debouncer();
// STARTER: controllers - do not remove comment
final _subscriptionsController = TextEditingController();
final _subscriptionsController = TextEditingController();
List<TextEditingController> _controllers = [];
@override
void didChangeDependencies() {
_controllers = [
// STARTER: array - do not remove comment
_subscriptionsController,
_subscriptionsController,
];
_controllers.forEach((controller) => controller.removeListener(_onChanged));
final subscription = widget.viewModel.subscription;
// STARTER: read value - do not remove comment
_subscriptionsController.text = subscription.subscriptions;
//_subscriptionsController.text = subscription.subscriptions;
_controllers.forEach((controller) => controller.addListener(_onChanged));
@ -61,15 +59,13 @@ _subscriptionsController.text = subscription.subscriptions;
void _onChanged() {
_debouncer.run(() {
final subscription = widget.viewModel.subscription.rebuild((b) => b
// STARTER: set value - do not remove comment
..subscriptions = _subscriptionsController.text.trim()
);
if (subscription != widget.viewModel.subscription) {
final subscription = widget.viewModel.subscription.rebuild((b) => b
// STARTER: set value - do not remove comment
//..subscriptions = _subscriptionsController.text.trim()
);
if (subscription != widget.viewModel.subscription) {
widget.viewModel.onChanged(subscription);
}
}
});
}
@ -80,46 +76,45 @@ _subscriptionsController.text = subscription.subscriptions;
final subscription = viewModel.subscription;
return EditScaffold(
title: subscription.isNew ? localization.newSubscription : localization.editSubscription,
title: subscription.isNew
? localization.newSubscription
: localization.editSubscription,
onCancelPressed: (context) => viewModel.onCancelPressed(context),
onSavePressed: (context) {
final bool isValid = _formKey.currentState.validate();
onSavePressed: (context) {
final bool isValid = _formKey.currentState.validate();
/*
/*
setState(() {
_autoValidate = !isValid;
});
*/
if (!isValid) {
return;
}
if (!isValid) {
return;
}
viewModel.onSavePressed(context);
viewModel.onSavePressed(context);
},
body:Form(
key: _formKey,
child: Builder(builder: (BuildContext context) {
return ScrollableListView(
children: <Widget>[
FormCard(
children: <Widget>[
// STARTER: widgets - do not remove comment
TextFormField(
controller: _subscriptionsController,
autocorrect: false,
decoration: InputDecoration(
labelText: 'Subscriptions',
),
),
],
),
],
);
})
),
body: Form(
key: _formKey,
child: Builder(builder: (BuildContext context) {
return ScrollableListView(
children: <Widget>[
FormCard(
children: <Widget>[
// STARTER: widgets - do not remove comment
TextFormField(
controller: _subscriptionsController,
autocorrect: false,
decoration: InputDecoration(
labelText: 'Subscriptions',
),
),
],
),
],
);
})),
);
}
}

View File

@ -47,7 +47,9 @@ class SubscriptionListItem extends StatelessWidget {
userCompany: state.userCompany,
entity: subscription,
isSelected: subscription.id ==
(uiState.isEditing ? subscriptionUIState.editing.id : subscriptionUIState.selectedId),
(uiState.isEditing
? subscriptionUIState.editing.id
: subscriptionUIState.selectedId),
child: ListTile(
onTap: () => onTap != null
? onTap()
@ -73,7 +75,7 @@ class SubscriptionListItem extends StatelessWidget {
children: <Widget>[
Expanded(
child: Text(
subscription.name,
subscription.id,
style: Theme.of(context).textTheme.headline6,
),
),

View File

@ -47,7 +47,8 @@ class SubscriptionListBuilder extends StatelessWidget {
user: viewModel.state.user,
filter: viewModel.filter,
subscription: subscription,
isChecked: isInMultiselect && listState.isSelected(subscription.id),
isChecked:
isInMultiselect && listState.isSelected(subscription.id),
);
});
},
@ -85,23 +86,27 @@ class SubscriptionListVM {
final state = store.state;
return SubscriptionListVM(
state: state,
userCompany: state.userCompany,
listState: state.subscriptionListState,
subscriptionList: memoizedFilteredSubscriptionList(state.subscriptionState.map,
state.subscriptionState.list, state.subscriptionListState),
subscriptionMap: state.subscriptionState.map,
isLoading: state.isLoading,
filter: state.subscriptionUIState.listUIState.filter,
onEntityAction:
(BuildContext context, List<BaseEntity> subscriptions, EntityAction action) =>
state: state,
userCompany: state.userCompany,
listState: state.subscriptionListState,
subscriptionList: memoizedFilteredSubscriptionList(
state.getUISelection(EntityType.subscription),
state.subscriptionState.map,
state.subscriptionState.list,
state.subscriptionListState,
),
subscriptionMap: state.subscriptionState.map,
isLoading: state.isLoading,
filter: state.subscriptionUIState.listUIState.filter,
onEntityAction: (BuildContext context, List<BaseEntity> subscriptions,
EntityAction action) =>
handleSubscriptionAction(context, subscriptions, action),
onRefreshed: (context) => _handleRefresh(context),
tableColumns:
state.userCompany.settings.getTableColumns(EntityType.subscription) ??
SubscriptionPresenter.getDefaultTableFields(state.userCompany),
onSortColumn: (field) => store.dispatch(SortSubscriptions(field)),
onClearMultielsect: () => store.dispatch(ClearSubscriptionMultiselect()),
onRefreshed: (context) => _handleRefresh(context),
tableColumns:
state.userCompany.settings.getTableColumns(EntityType.subscription) ??
SubscriptionPresenter.getDefaultTableFields(state.userCompany),
onSortColumn: (field) => store.dispatch(SortSubscriptions(field)),
onClearMultielsect: () => store.dispatch(ClearSubscriptionMultiselect()),
);
}
@ -117,4 +122,4 @@ class SubscriptionListVM {
final List<String> tableColumns;
final Function(String) onSortColumn;
final Function onClearMultielsect;
}
}

View File

@ -34,7 +34,8 @@ class SubscriptionScreen extends StatelessWidget {
return ListScaffold(
entityType: EntityType.subscription,
onHamburgerLongPress: () => store.dispatch(StartSubscriptionMultiselect()),
onHamburgerLongPress: () =>
store.dispatch(StartSubscriptionMultiselect()),
appBarTitle: ListFilter(
entityIds: viewModel.subscriptionList,
filter: state.subscriptionListState.filter,
@ -46,13 +47,13 @@ class SubscriptionScreen extends StatelessWidget {
bottomNavigationBar: AppBottomBar(
entityType: EntityType.subscription,
tableColumns: SubscriptionPresenter.getAllTableFields(userCompany),
defaultTableColumns: SubscriptionPresenter.getDefaultTableFields(userCompany),
defaultTableColumns:
SubscriptionPresenter.getDefaultTableFields(userCompany),
onSelectedSortField: (value) {
store.dispatch(SortSubscriptions(value));
},
sortFields: [
SubscriptionFields.name,
SubscriptionFields.balance,
SubscriptionFields.createdAt,
SubscriptionFields.updatedAt,
],
onSelectedState: (EntityState state, value) {
@ -65,14 +66,6 @@ class SubscriptionScreen extends StatelessWidget {
store.dispatch(StartSubscriptionMultiselect());
}
},
customValues1: company.getCustomFieldValues(CustomFieldType.subscription1,
excludeBlank: true),
customValues2: company.getCustomFieldValues(CustomFieldType.subscription2,
excludeBlank: true),
customValues3: company.getCustomFieldValues(CustomFieldType.subscription3,
excludeBlank: true),
customValues4: company.getCustomFieldValues(CustomFieldType.subscription4,
excludeBlank: true),
onSelectedCustom1: (value) =>
store.dispatch(FilterSubscriptionsByCustom1(value)),
onSelectedCustom2: (value) =>
@ -82,7 +75,8 @@ class SubscriptionScreen extends StatelessWidget {
onSelectedCustom4: (value) =>
store.dispatch(FilterSubscriptionsByCustom4(value)),
),
floatingActionButton: state.prefState.isMenuFloated && userCompany.canCreate(EntityType.subscription)
floatingActionButton: state.prefState.isMenuFloated &&
userCompany.canCreate(EntityType.subscription)
? FloatingActionButton(
heroTag: 'subscription_fab',
backgroundColor: Theme.of(context).primaryColorDark,

View File

@ -47,8 +47,12 @@ class SubscriptionScreenVM {
return SubscriptionScreenVM(
subscriptionMap: state.subscriptionState.map,
subscriptionList: memoizedFilteredSubscriptionList(state.subscriptionState.map,
state.subscriptionState.list, state.subscriptionListState),
subscriptionList: memoizedFilteredSubscriptionList(
state.getUISelection(EntityType.subscription),
state.subscriptionState.map,
state.subscriptionState.list,
state.subscriptionListState,
),
userCompany: state.userCompany,
isInMultiselect: state.subscriptionListState.isInMultiselect(),
onEntityAction: (BuildContext context, List<BaseEntity> subscriptions,

View File

@ -1,10 +1,10 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/ui/app/scrollable_listview.dart';
import 'package:invoiceninja_flutter/ui/subscription/view/subscription_view_vm.dart';
import 'package:invoiceninja_flutter/ui/app/view_scaffold.dart';
class SubscriptionView extends StatefulWidget {
const SubscriptionView({
Key key,
@required this.viewModel,
@ -28,8 +28,7 @@ class _SubscriptionViewState extends State<SubscriptionView> {
isFilter: widget.isFilter,
entity: subscription,
body: ScrollableListView(
children: <Widget>[
],
children: <Widget>[],
),
);
}

View File

@ -1,5 +1,6 @@
import 'package:invoiceninja_flutter/data/models/stub_model.dart';
import 'package:invoiceninja_flutter/redux/static/static_state.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:memoize/memoize.dart';
import 'package:built_collection/built_collection.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
@ -36,9 +37,8 @@ List<String> dropdownStubsSelector(BuiltMap<String, StubEntity> stubMap,
return list;
}
var memoizedFilteredStubList = memo7((
String filterEntityId,
EntityType filterEntityType,
var memoizedFilteredStubList = memo6((
SelectionState selectionState,
BuiltMap<String, StubEntity> stubMap,
BuiltList<String> stubList,
StaticState staticState,
@ -47,13 +47,16 @@ var memoizedFilteredStubList = memo7((
filteredStubsSelector(filterEntityId, filterEntityType, stubMap, stubList, staticState, userMap, stubListState));
List<String> filteredStubsSelector(
String filterEntityId,
EntityType filterEntityType,
SelectionState selectionState,
BuiltMap<String, StubEntity> stubMap,
BuiltList<String> stubList,
StaticState staticState,
BuiltMap<String, UserEntity> userMap,
ListUIState stubListState) {
final filterEntityId = selectionState.filterEntityId;
final filterEntityType = selectionState.filterEntityType;
final list = stubList.where((stubId) {
final stub = stubMap[stubId];
if (filterEntityId != null && stub.id != filterEntityId) {
@ -77,11 +80,10 @@ List<String> filteredStubsSelector(
}).toList();
list.sort((stubAId, stubBId) {
return stubMap[stubAId].compareTo(
stub: stubMap[stubBId],
sortField: stubListState.sortField,
sortAscending: stubListState.sortAscending,
);
final stubA = stubMap[stubAId];
final stubB = stubMap[stubBId];
return clientA.compareTo(stubB, stubListState.sortField,
stubListState.sortAscending, userMap, staticState);
});

View File

@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/stub/edit/stub_edit_vm.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/ui/app/scrollable_listview.dart';
class StubEdit extends StatefulWidget {
const StubEdit({

View File

@ -1,5 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/ui/app/scrollable_listview.dart';
import 'package:invoiceninja_flutter/ui/stub/view/stub_view_vm.dart';
import 'package:invoiceninja_flutter/ui/app/view_scaffold.dart';