Subscriptions
This commit is contained in:
parent
9dd186cfca
commit
ffc558903d
|
|
@ -129,9 +129,9 @@ part 'serializers.g.dart';
|
|||
TaxRateItemResponse,
|
||||
TaxRateListResponse,
|
||||
// STARTER: serializers - do not remove comment
|
||||
SubscriptionEntity,
|
||||
SubscriptionListResponse,
|
||||
SubscriptionItemResponse,
|
||||
SubscriptionEntity,
|
||||
SubscriptionListResponse,
|
||||
SubscriptionItemResponse,
|
||||
|
||||
TaskStatusEntity,
|
||||
TaskStatusListResponse,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import 'package:invoiceninja_flutter/data/models/models.dart';
|
|||
import 'package:invoiceninja_flutter/data/web_client.dart';
|
||||
|
||||
class SubscriptionRepository {
|
||||
|
||||
const SubscriptionRepository({
|
||||
this.webClient = const WebClient(),
|
||||
});
|
||||
|
|
@ -20,52 +19,53 @@ class SubscriptionRepository {
|
|||
final dynamic response = await webClient.get(
|
||||
'${credentials.url}/subscriptions/$entityId', credentials.token);
|
||||
|
||||
final SubscriptionItemResponse subscriptionResponse =
|
||||
serializers.deserializeWith(SubscriptionItemResponse.serializer, response);
|
||||
final SubscriptionItemResponse subscriptionResponse = serializers
|
||||
.deserializeWith(SubscriptionItemResponse.serializer, response);
|
||||
|
||||
return subscriptionResponse.data;
|
||||
}
|
||||
|
||||
Future<BuiltList<SubscriptionEntity>> loadList(Credentials credentials) async {
|
||||
Future<BuiltList<SubscriptionEntity>> loadList(
|
||||
Credentials credentials) async {
|
||||
final String url = credentials.url + '/subscriptions?';
|
||||
final dynamic response = await webClient.get(url, credentials.token);
|
||||
|
||||
final SubscriptionListResponse subscriptionResponse =
|
||||
serializers.deserializeWith(SubscriptionListResponse.serializer, response);
|
||||
final SubscriptionListResponse subscriptionResponse = serializers
|
||||
.deserializeWith(SubscriptionListResponse.serializer, response);
|
||||
|
||||
return subscriptionResponse.data;
|
||||
}
|
||||
|
||||
Future<List<SubscriptionEntity>> bulkAction(
|
||||
Credentials credentials, List<String> ids, EntityAction action) async {
|
||||
final url = credentials.url + '/subscriptions/bulk';
|
||||
final dynamic response = await webClient.post(url, credentials.token,
|
||||
data: json.encode({'ids': ids, 'action': action.toApiParam()}));
|
||||
Future<List<SubscriptionEntity>> bulkAction(
|
||||
Credentials credentials, List<String> ids, EntityAction action) async {
|
||||
final url = credentials.url + '/subscriptions/bulk';
|
||||
final dynamic response = await webClient.post(url, credentials.token,
|
||||
data: json.encode({'ids': ids, 'action': action.toApiParam()}));
|
||||
|
||||
final SubscriptionListResponse subscriptionResponse =
|
||||
serializers.deserializeWith(SubscriptionListResponse.serializer, response);
|
||||
|
||||
return subscriptionResponse.data.toList();
|
||||
}
|
||||
final SubscriptionListResponse subscriptionResponse = serializers
|
||||
.deserializeWith(SubscriptionListResponse.serializer, response);
|
||||
|
||||
return subscriptionResponse.data.toList();
|
||||
}
|
||||
|
||||
Future<SubscriptionEntity> saveData(
|
||||
Credentials credentials, SubscriptionEntity subscription) async {
|
||||
final data = serializers.serializeWith(SubscriptionEntity.serializer, subscription);
|
||||
final data =
|
||||
serializers.serializeWith(SubscriptionEntity.serializer, subscription);
|
||||
dynamic response;
|
||||
|
||||
if (subscription.isNew) {
|
||||
response = await webClient.post(
|
||||
credentials.url + '/subscriptions',
|
||||
credentials.token,
|
||||
credentials.url + '/subscriptions', credentials.token,
|
||||
data: json.encode(data));
|
||||
} else {
|
||||
final url = '${credentials.url}/subscriptions/${subscription.id}';
|
||||
response = await webClient.put(url, credentials.token, data: json.encode(data));
|
||||
response =
|
||||
await webClient.put(url, credentials.token, data: json.encode(data));
|
||||
}
|
||||
|
||||
final SubscriptionItemResponse subscriptionResponse =
|
||||
serializers.deserializeWith(SubscriptionItemResponse.serializer, response);
|
||||
final SubscriptionItemResponse subscriptionResponse = serializers
|
||||
.deserializeWith(SubscriptionItemResponse.serializer, response);
|
||||
|
||||
return subscriptionResponse.data;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,8 +69,7 @@ void main({bool isTesting = false}) async {
|
|||
..addAll(createStoreSettingsMiddleware())
|
||||
..addAll(createStoreReportsMiddleware())
|
||||
// STARTER: middleware - do not remove comment
|
||||
..addAll(createStoreSubscriptionsMiddleware())
|
||||
|
||||
..addAll(createStoreSubscriptionsMiddleware())
|
||||
..addAll(createStoreTaskStatusesMiddleware())
|
||||
..addAll(createStoreExpenseCategoriesMiddleware())
|
||||
..addAll(createStoreRecurringInvoicesMiddleware())
|
||||
|
|
|
|||
|
|
@ -343,9 +343,12 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
|
|||
QuoteEmailScreen.route: (context) => QuoteEmailScreen(),
|
||||
QuotePdfScreen.route: (context) => QuotePdfScreen(),
|
||||
// STARTER: routes - do not remove comment
|
||||
SubscriptionScreen.route: (context) => SubscriptionScreenBuilder(),
|
||||
SubscriptionViewScreen.route: (context) => SubscriptionViewScreen(),
|
||||
SubscriptionEditScreen.route: (context) => SubscriptionEditScreen(),
|
||||
SubscriptionScreen.route: (context) =>
|
||||
SubscriptionScreenBuilder(),
|
||||
SubscriptionViewScreen.route: (context) =>
|
||||
SubscriptionViewScreen(),
|
||||
SubscriptionEditScreen.route: (context) =>
|
||||
SubscriptionEditScreen(),
|
||||
|
||||
TaskStatusScreen.route: (context) =>
|
||||
TaskStatusScreenBuilder(),
|
||||
|
|
|
|||
|
|
@ -100,7 +100,9 @@ final lastErrorReducer = combineReducers<String>([
|
|||
return '${action.error}';
|
||||
}),
|
||||
// STARTER: errors - do not remove comment
|
||||
TypedReducer<String, LoadSubscriptionsFailure>((state, action) { return '${action.error}'; }),
|
||||
TypedReducer<String, LoadSubscriptionsFailure>((state, action) {
|
||||
return '${action.error}';
|
||||
}),
|
||||
|
||||
TypedReducer<String, LoadTaskStatusesFailure>((state, action) {
|
||||
return '${action.error}';
|
||||
|
|
|
|||
|
|
@ -51,7 +51,9 @@ import 'package:invoiceninja_flutter/ui/group/edit/group_edit_vm.dart';
|
|||
import 'package:invoiceninja_flutter/ui/product/edit/product_edit_vm.dart';
|
||||
|
||||
// STARTER: import - do not remove comment
|
||||
import 'package:invoiceninja_flutter/redux/subscription/subscription_state.dart';import 'package:invoiceninja_flutter/ui/subscription/edit/subscription_edit_vm.dart';import 'package:invoiceninja_flutter/redux/subscription/subscription_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/subscription/subscription_state.dart';
|
||||
import 'package:invoiceninja_flutter/ui/subscription/edit/subscription_edit_vm.dart';
|
||||
import 'package:invoiceninja_flutter/redux/subscription/subscription_selectors.dart';
|
||||
|
||||
import 'package:invoiceninja_flutter/redux/task_status/task_status_state.dart';
|
||||
import 'package:invoiceninja_flutter/ui/recurring_invoice/recurring_invoice_screen.dart';
|
||||
|
|
@ -275,8 +277,8 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
|
|||
case EntityType.invoice:
|
||||
return invoiceState.map;
|
||||
// STARTER: states switch map - do not remove comment
|
||||
case EntityType.subscription:
|
||||
return subscriptionState.map;
|
||||
case EntityType.subscription:
|
||||
return subscriptionState.map;
|
||||
|
||||
case EntityType.taskStatus:
|
||||
return taskStatusState.map;
|
||||
|
|
@ -349,8 +351,8 @@ return subscriptionState.map;
|
|||
case EntityType.invoice:
|
||||
return invoiceState.list;
|
||||
// STARTER: states switch list - do not remove comment
|
||||
case EntityType.subscription:
|
||||
return subscriptionState.list;
|
||||
case EntityType.subscription:
|
||||
return subscriptionState.list;
|
||||
|
||||
case EntityType.taskStatus:
|
||||
return taskStatusState.list;
|
||||
|
|
@ -414,8 +416,8 @@ return subscriptionState.list;
|
|||
case EntityType.invoice:
|
||||
return invoiceUIState;
|
||||
// STARTER: states switch - do not remove comment
|
||||
case EntityType.subscription:
|
||||
return subscriptionUIState;
|
||||
case EntityType.subscription:
|
||||
return subscriptionUIState;
|
||||
|
||||
case EntityType.taskStatus:
|
||||
return taskStatusUIState;
|
||||
|
|
@ -483,10 +485,10 @@ return subscriptionUIState;
|
|||
ListUIState get invoiceListState => uiState.invoiceUIState.listUIState;
|
||||
|
||||
// STARTER: state getters - do not remove comment
|
||||
SubscriptionState get subscriptionState => userCompanyState.subscriptionState;
|
||||
ListUIState get subscriptionListState => uiState.subscriptionUIState.listUIState;
|
||||
SubscriptionUIState get subscriptionUIState => uiState.subscriptionUIState;
|
||||
|
||||
SubscriptionState get subscriptionState => userCompanyState.subscriptionState;
|
||||
ListUIState get subscriptionListState =>
|
||||
uiState.subscriptionUIState.listUIState;
|
||||
SubscriptionUIState get subscriptionUIState => uiState.subscriptionUIState;
|
||||
|
||||
TaskStatusState get taskStatusState => userCompanyState.taskStatusState;
|
||||
|
||||
|
|
@ -644,7 +646,9 @@ SubscriptionUIState get subscriptionUIState => uiState.subscriptionUIState;
|
|||
case CreditEditScreen.route:
|
||||
return hasCreditChanges(creditUIState.editing, creditState.map);
|
||||
// STARTER: has changes - do not remove comment
|
||||
case SubscriptionEditScreen.route: return hasSubscriptionChanges(subscriptionUIState.editing, subscriptionState.map);
|
||||
case SubscriptionEditScreen.route:
|
||||
return hasSubscriptionChanges(
|
||||
subscriptionUIState.editing, subscriptionState.map);
|
||||
|
||||
case TaskStatusEditScreen.route:
|
||||
return hasTaskStatusChanges(
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ UserCompanyState companyReducer(UserCompanyState state, dynamic action) {
|
|||
..vendorState.replace(vendorsReducer(state.vendorState, action))
|
||||
..taskState.replace(tasksReducer(state.taskState, action))
|
||||
// STARTER: reducer - do not remove comment
|
||||
..subscriptionState.replace(subscriptionsReducer(state.subscriptionState, action))
|
||||
|
||||
..subscriptionState
|
||||
.replace(subscriptionsReducer(state.subscriptionState, action))
|
||||
..taskStatusState
|
||||
.replace(taskStatusesReducer(state.taskStatusState, action))
|
||||
..expenseCategoryState
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ abstract class UserCompanyState
|
|||
paymentState: PaymentState(),
|
||||
quoteState: QuoteState(),
|
||||
// STARTER: constructor - do not remove comment
|
||||
subscriptionState: SubscriptionState(),
|
||||
subscriptionState: SubscriptionState(),
|
||||
|
||||
taskStatusState: TaskStatusState(),
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ subscriptionState: SubscriptionState(),
|
|||
QuoteState get quoteState;
|
||||
|
||||
// STARTER: fields - do not remove comment
|
||||
SubscriptionState get subscriptionState;
|
||||
SubscriptionState get subscriptionState;
|
||||
|
||||
TaskStatusState get taskStatusState;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ import 'package:invoiceninja_flutter/utils/completers.dart';
|
|||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
||||
|
||||
class ViewSubscriptionList extends AbstractNavigatorAction implements PersistUI, StopLoading {
|
||||
class ViewSubscriptionList extends AbstractNavigatorAction
|
||||
implements PersistUI, StopLoading {
|
||||
ViewSubscriptionList({
|
||||
@required NavigatorState navigator,
|
||||
this.force = false,
|
||||
|
|
@ -120,7 +121,6 @@ class LoadSubscriptionsSuccess implements StopLoading {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
class SaveSubscriptionRequest implements StartSaving {
|
||||
SaveSubscriptionRequest({this.completer, this.subscription});
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ class AddSubscriptionSuccess implements StopSaving, PersistData, PersistUI {
|
|||
}
|
||||
|
||||
class SaveSubscriptionFailure implements StopSaving {
|
||||
SaveSubscriptionFailure (this.error);
|
||||
SaveSubscriptionFailure(this.error);
|
||||
|
||||
final Object error;
|
||||
}
|
||||
|
|
@ -203,7 +203,6 @@ class RestoreSubscriptionsFailure implements StopSaving {
|
|||
final List<SubscriptionEntity> subscriptions;
|
||||
}
|
||||
|
||||
|
||||
class FilterSubscriptions implements PersistUI {
|
||||
FilterSubscriptions(this.filter);
|
||||
|
||||
|
|
@ -274,7 +273,6 @@ class UpdateSubscriptionTab implements PersistUI {
|
|||
|
||||
void handleSubscriptionAction(
|
||||
BuildContext context, List<BaseEntity> subscriptions, EntityAction action) {
|
||||
|
||||
if (subscriptions.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -283,7 +281,8 @@ void handleSubscriptionAction(
|
|||
final state = store.state;
|
||||
final localization = AppLocalization.of(context);
|
||||
final subscription = subscriptions.first as SubscriptionEntity;
|
||||
final subscriptionIds = subscriptions.map((subscription) => subscription.id).toList();
|
||||
final subscriptionIds =
|
||||
subscriptions.map((subscription) => subscription.id).toList();
|
||||
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
|
|
@ -291,15 +290,18 @@ void handleSubscriptionAction(
|
|||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreSubscriptionsRequest(
|
||||
snackBarCompleter<Null>(context, localization.restoredSubscription), subscriptionIds));
|
||||
snackBarCompleter<Null>(context, localization.restoredSubscription),
|
||||
subscriptionIds));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveSubscriptionsRequest(
|
||||
snackBarCompleter<Null>(context, localization.archivedSubscription), subscriptionIds));
|
||||
snackBarCompleter<Null>(context, localization.archivedSubscription),
|
||||
subscriptionIds));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteSubscriptionsRequest(
|
||||
snackBarCompleter<Null>(context, localization.deletedSubscription), subscriptionIds));
|
||||
snackBarCompleter<Null>(context, localization.deletedSubscription),
|
||||
subscriptionIds));
|
||||
break;
|
||||
case EntityAction.toggleMultiselect:
|
||||
if (!store.state.subscriptionListState.isInMultiselect()) {
|
||||
|
|
@ -312,23 +314,21 @@ void handleSubscriptionAction(
|
|||
|
||||
for (final subscription in subscriptions) {
|
||||
if (!store.state.subscriptionListState.isSelected(subscription.id)) {
|
||||
store.dispatch(
|
||||
AddToSubscriptionMultiselect(entity: subscription));
|
||||
store.dispatch(AddToSubscriptionMultiselect(entity: subscription));
|
||||
} else {
|
||||
store.dispatch(
|
||||
RemoveFromSubscriptionMultiselect(entity: subscription));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EntityAction.more:
|
||||
showEntityActionsDialog(
|
||||
entities: [subscription],
|
||||
context: context,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
print('Error: unhandled action $action in subscription_actions');
|
||||
break;
|
||||
|
||||
case EntityAction.more:
|
||||
showEntityActionsDialog(
|
||||
entities: [subscription],
|
||||
context: context,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
print('Error: unhandled action $action in subscription_actions');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ List<Middleware<AppState>> createStoreSubscriptionsMiddleware([
|
|||
|
||||
Middleware<AppState> _editSubscription() {
|
||||
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||
|
||||
final action = dynamicAction as EditSubscription;
|
||||
|
||||
next(action);
|
||||
|
|
@ -49,22 +48,22 @@ Middleware<AppState> _editSubscription() {
|
|||
store.dispatch(UpdateCurrentRoute(SubscriptionEditScreen.route));
|
||||
|
||||
if (isMobile(action.context)) {
|
||||
action.navigator.pushNamed(SubscriptionEditScreen.route);
|
||||
action.navigator.pushNamed(SubscriptionEditScreen.route);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Middleware<AppState> _viewSubscription() {
|
||||
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) async {
|
||||
|
||||
final action = dynamicAction as ViewSubscription;
|
||||
return (Store<AppState> store, dynamic dynamicAction,
|
||||
NextDispatcher next) async {
|
||||
final action = dynamicAction as ViewSubscription;
|
||||
|
||||
next(action);
|
||||
|
||||
store.dispatch(UpdateCurrentRoute(SubscriptionViewScreen.route));
|
||||
|
||||
if (isMobile(action.context)) {
|
||||
Navigator.of(action.context).pushNamed(SubscriptionViewScreen.route);
|
||||
Navigator.of(action.context).pushNamed(SubscriptionViewScreen.route);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -91,11 +90,12 @@ Middleware<AppState> _viewSubscriptionList() {
|
|||
Middleware<AppState> _archiveSubscription(SubscriptionRepository repository) {
|
||||
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||
final action = dynamicAction as ArchiveSubscriptionsRequest;
|
||||
final prevSubscriptions =
|
||||
action.subscriptionIds.map((id) => store.state.subscriptionState.map[id]).toList();
|
||||
final prevSubscriptions = action.subscriptionIds
|
||||
.map((id) => store.state.subscriptionState.map[id])
|
||||
.toList();
|
||||
repository
|
||||
.bulkAction(
|
||||
store.state.credentials, action.subscriptionIds, EntityAction.archive)
|
||||
.bulkAction(store.state.credentials, action.subscriptionIds,
|
||||
EntityAction.archive)
|
||||
.then((List<SubscriptionEntity> subscriptions) {
|
||||
store.dispatch(ArchiveSubscriptionsSuccess(subscriptions));
|
||||
if (action.completer != null) {
|
||||
|
|
@ -116,11 +116,12 @@ Middleware<AppState> _archiveSubscription(SubscriptionRepository repository) {
|
|||
Middleware<AppState> _deleteSubscription(SubscriptionRepository repository) {
|
||||
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||
final action = dynamicAction as DeleteSubscriptionsRequest;
|
||||
final prevSubscriptions =
|
||||
action.subscriptionIds.map((id) => store.state.subscriptionState.map[id]).toList();
|
||||
final prevSubscriptions = action.subscriptionIds
|
||||
.map((id) => store.state.subscriptionState.map[id])
|
||||
.toList();
|
||||
repository
|
||||
.bulkAction(
|
||||
store.state.credentials, action.subscriptionIds, EntityAction.delete)
|
||||
.bulkAction(store.state.credentials, action.subscriptionIds,
|
||||
EntityAction.delete)
|
||||
.then((List<SubscriptionEntity> subscriptions) {
|
||||
store.dispatch(DeleteSubscriptionsSuccess(subscriptions));
|
||||
if (action.completer != null) {
|
||||
|
|
@ -141,11 +142,12 @@ Middleware<AppState> _deleteSubscription(SubscriptionRepository repository) {
|
|||
Middleware<AppState> _restoreSubscription(SubscriptionRepository repository) {
|
||||
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||
final action = dynamicAction as RestoreSubscriptionsRequest;
|
||||
final prevSubscriptions =
|
||||
action.subscriptionIds.map((id) => store.state.subscriptionState.map[id]).toList();
|
||||
final prevSubscriptions = action.subscriptionIds
|
||||
.map((id) => store.state.subscriptionState.map[id])
|
||||
.toList();
|
||||
repository
|
||||
.bulkAction(
|
||||
store.state.credentials, action.subscriptionIds, EntityAction.restore)
|
||||
.bulkAction(store.state.credentials, action.subscriptionIds,
|
||||
EntityAction.restore)
|
||||
.then((List<SubscriptionEntity> subscriptions) {
|
||||
store.dispatch(RestoreSubscriptionsSuccess(subscriptions));
|
||||
if (action.completer != null) {
|
||||
|
|
@ -167,8 +169,7 @@ Middleware<AppState> _saveSubscription(SubscriptionRepository repository) {
|
|||
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||
final action = dynamicAction as SaveSubscriptionRequest;
|
||||
repository
|
||||
.saveData(
|
||||
store.state.credentials, action.subscription)
|
||||
.saveData(store.state.credentials, action.subscription)
|
||||
.then((SubscriptionEntity subscription) {
|
||||
if (action.subscription.isNew) {
|
||||
store.dispatch(AddSubscriptionSuccess(subscription));
|
||||
|
|
@ -177,7 +178,6 @@ Middleware<AppState> _saveSubscription(SubscriptionRepository repository) {
|
|||
}
|
||||
|
||||
action.completer.complete(subscription);
|
||||
|
||||
}).catchError((Object error) {
|
||||
print(error);
|
||||
store.dispatch(SaveSubscriptionFailure(error));
|
||||
|
|
@ -190,10 +190,10 @@ Middleware<AppState> _saveSubscription(SubscriptionRepository repository) {
|
|||
|
||||
Middleware<AppState> _loadSubscription(SubscriptionRepository repository) {
|
||||
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||
final action = dynamicAction as LoadSubscription;
|
||||
final action = dynamicAction as LoadSubscription;
|
||||
final AppState state = store.state;
|
||||
|
||||
store.dispatch(LoadSubscriptionRequest());
|
||||
store.dispatch(LoadSubscriptionRequest());
|
||||
repository
|
||||
.loadItem(state.credentials, action.subscriptionId)
|
||||
.then((subscription) {
|
||||
|
|
@ -216,14 +216,11 @@ store.dispatch(LoadSubscriptionRequest());
|
|||
|
||||
Middleware<AppState> _loadSubscriptions(SubscriptionRepository repository) {
|
||||
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
|
||||
final action = dynamicAction as LoadSubscriptions;
|
||||
final action = dynamicAction as LoadSubscriptions;
|
||||
final AppState state = store.state;
|
||||
|
||||
|
||||
store.dispatch(LoadSubscriptionsRequest());
|
||||
repository
|
||||
.loadList(state.credentials)
|
||||
.then((data) {
|
||||
repository.loadList(state.credentials).then((data) {
|
||||
store.dispatch(LoadSubscriptionsSuccess(data));
|
||||
|
||||
if (action.completer != null) {
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@ EntityUIState subscriptionUIReducer(SubscriptionUIState state, dynamic action) {
|
|||
..listUIState.replace(subscriptionListReducer(state.listUIState, action))
|
||||
..editing.replace(editingReducer(state.editing, action))
|
||||
..selectedId = selectedIdReducer(state.selectedId, action)
|
||||
..tabIndex = tabIndexReducer(state.tabIndex, action)
|
||||
);
|
||||
..tabIndex = tabIndexReducer(state.tabIndex, action));
|
||||
}
|
||||
|
||||
final tabIndexReducer = combineReducers<int>([
|
||||
|
|
@ -36,55 +35,66 @@ Reducer<String> selectedIdReducer = combineReducers([
|
|||
(String selectedId, dynamic action) => action.subscriptionId),
|
||||
TypedReducer<String, AddSubscriptionSuccess>(
|
||||
(String selectedId, dynamic action) => action.subscription.id),
|
||||
TypedReducer<String, SelectCompany>((selectedId, action) => action.clearSelection ? '' : selectedId),
|
||||
TypedReducer<String, SelectCompany>(
|
||||
(selectedId, action) => action.clearSelection ? '' : selectedId),
|
||||
TypedReducer<String, ClearEntityFilter>((selectedId, action) => ''),
|
||||
TypedReducer<String, FilterByEntity>((selectedId, action) =>
|
||||
action
|
||||
.clearSelection
|
||||
? ''
|
||||
: action.entityType == EntityType.subscription ? action.entityId : selectedId),
|
||||
|
||||
TypedReducer<String, FilterByEntity>(
|
||||
(selectedId, action) => action.clearSelection
|
||||
? ''
|
||||
: action.entityType == EntityType.subscription
|
||||
? action.entityId
|
||||
: selectedId),
|
||||
]);
|
||||
|
||||
final editingReducer = combineReducers<SubscriptionEntity>([
|
||||
TypedReducer<SubscriptionEntity, SaveSubscriptionSuccess>(_updateEditing),
|
||||
TypedReducer<SubscriptionEntity, AddSubscriptionSuccess>(_updateEditing),
|
||||
TypedReducer<SubscriptionEntity, RestoreSubscriptionsSuccess>((subscriptions, action) {
|
||||
return action.subscriptions[0];
|
||||
}),
|
||||
TypedReducer<SubscriptionEntity, ArchiveSubscriptionsSuccess>((subscriptions, action) {
|
||||
return action.subscriptions[0];
|
||||
}),
|
||||
TypedReducer<SubscriptionEntity, DeleteSubscriptionsSuccess>((subscriptions, action) {
|
||||
return action.subscriptions[0];
|
||||
}),
|
||||
TypedReducer<SubscriptionEntity, RestoreSubscriptionsSuccess>(
|
||||
(subscriptions, action) {
|
||||
return action.subscriptions[0];
|
||||
}),
|
||||
TypedReducer<SubscriptionEntity, ArchiveSubscriptionsSuccess>(
|
||||
(subscriptions, action) {
|
||||
return action.subscriptions[0];
|
||||
}),
|
||||
TypedReducer<SubscriptionEntity, DeleteSubscriptionsSuccess>(
|
||||
(subscriptions, action) {
|
||||
return action.subscriptions[0];
|
||||
}),
|
||||
TypedReducer<SubscriptionEntity, EditSubscription>(_updateEditing),
|
||||
TypedReducer<SubscriptionEntity, UpdateSubscription>((subscription, action) {
|
||||
return action.subscription.rebuild((b) => b..isChanged = true);
|
||||
}),
|
||||
return action.subscription.rebuild((b) => b..isChanged = true);
|
||||
}),
|
||||
TypedReducer<SubscriptionEntity, DiscardChanges>(_clearEditing),
|
||||
]);
|
||||
|
||||
SubscriptionEntity _clearEditing(SubscriptionEntity subscription, dynamic action) {
|
||||
SubscriptionEntity _clearEditing(
|
||||
SubscriptionEntity subscription, dynamic action) {
|
||||
return SubscriptionEntity();
|
||||
}
|
||||
|
||||
SubscriptionEntity _updateEditing(SubscriptionEntity subscription, dynamic action) {
|
||||
SubscriptionEntity _updateEditing(
|
||||
SubscriptionEntity subscription, dynamic action) {
|
||||
return action.subscription;
|
||||
}
|
||||
|
||||
|
||||
final subscriptionListReducer = combineReducers<ListUIState>([
|
||||
TypedReducer<ListUIState, SortSubscriptions>(_sortSubscriptions),
|
||||
TypedReducer<ListUIState, FilterSubscriptionsByState>(_filterSubscriptionsByState),
|
||||
TypedReducer<ListUIState, FilterSubscriptionsByState>(
|
||||
_filterSubscriptionsByState),
|
||||
TypedReducer<ListUIState, FilterSubscriptions>(_filterSubscriptions),
|
||||
TypedReducer<ListUIState, FilterSubscriptionsByCustom1>(_filterSubscriptionsByCustom1),
|
||||
TypedReducer<ListUIState, FilterSubscriptionsByCustom2>(_filterSubscriptionsByCustom2),
|
||||
TypedReducer<ListUIState, StartSubscriptionMultiselect>(_startListMultiselect),
|
||||
TypedReducer<ListUIState, AddToSubscriptionMultiselect>(_addToListMultiselect),
|
||||
TypedReducer<ListUIState, FilterSubscriptionsByCustom1>(
|
||||
_filterSubscriptionsByCustom1),
|
||||
TypedReducer<ListUIState, FilterSubscriptionsByCustom2>(
|
||||
_filterSubscriptionsByCustom2),
|
||||
TypedReducer<ListUIState, StartSubscriptionMultiselect>(
|
||||
_startListMultiselect),
|
||||
TypedReducer<ListUIState, AddToSubscriptionMultiselect>(
|
||||
_addToListMultiselect),
|
||||
TypedReducer<ListUIState, RemoveFromSubscriptionMultiselect>(
|
||||
_removeFromListMultiselect),
|
||||
TypedReducer<ListUIState, ClearSubscriptionMultiselect>(_clearListMultiselect),
|
||||
TypedReducer<ListUIState, ClearSubscriptionMultiselect>(
|
||||
_clearListMultiselect),
|
||||
]);
|
||||
|
||||
ListUIState _filterSubscriptionsByCustom1(
|
||||
|
|
@ -93,7 +103,8 @@ ListUIState _filterSubscriptionsByCustom1(
|
|||
return subscriptionListState
|
||||
.rebuild((b) => b..custom1Filters.remove(action.value));
|
||||
} else {
|
||||
return subscriptionListState.rebuild((b) => b..custom1Filters.add(action.value));
|
||||
return subscriptionListState
|
||||
.rebuild((b) => b..custom1Filters.add(action.value));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -103,27 +114,33 @@ ListUIState _filterSubscriptionsByCustom2(
|
|||
return subscriptionListState
|
||||
.rebuild((b) => b..custom2Filters.remove(action.value));
|
||||
} else {
|
||||
return subscriptionListState.rebuild((b) => b..custom2Filters.add(action.value));
|
||||
return subscriptionListState
|
||||
.rebuild((b) => b..custom2Filters.add(action.value));
|
||||
}
|
||||
}
|
||||
|
||||
ListUIState _filterSubscriptionsByState(
|
||||
ListUIState subscriptionListState, FilterSubscriptionsByState action) {
|
||||
if (subscriptionListState.stateFilters.contains(action.state)) {
|
||||
return subscriptionListState.rebuild((b) => b..stateFilters.remove(action.state));
|
||||
return subscriptionListState
|
||||
.rebuild((b) => b..stateFilters.remove(action.state));
|
||||
} else {
|
||||
return subscriptionListState.rebuild((b) => b..stateFilters.add(action.state));
|
||||
return subscriptionListState
|
||||
.rebuild((b) => b..stateFilters.add(action.state));
|
||||
}
|
||||
}
|
||||
|
||||
ListUIState _filterSubscriptions(ListUIState subscriptionListState, FilterSubscriptions action) {
|
||||
return subscriptionListState.rebuild((b) => b..filter = action.filter
|
||||
..filterClearedAt = action.filter == null
|
||||
? DateTime.now().millisecondsSinceEpoch
|
||||
: subscriptionListState.filterClearedAt);
|
||||
ListUIState _filterSubscriptions(
|
||||
ListUIState subscriptionListState, FilterSubscriptions action) {
|
||||
return subscriptionListState.rebuild((b) => b
|
||||
..filter = action.filter
|
||||
..filterClearedAt = action.filter == null
|
||||
? DateTime.now().millisecondsSinceEpoch
|
||||
: subscriptionListState.filterClearedAt);
|
||||
}
|
||||
|
||||
ListUIState _sortSubscriptions(ListUIState subscriptionListState, SortSubscriptions action) {
|
||||
ListUIState _sortSubscriptions(
|
||||
ListUIState subscriptionListState, SortSubscriptions action) {
|
||||
return subscriptionListState.rebuild((b) => b
|
||||
..sortAscending = b.sortField != action.field || !b.sortAscending
|
||||
..sortField = action.field);
|
||||
|
|
@ -136,8 +153,7 @@ ListUIState _startListMultiselect(
|
|||
|
||||
ListUIState _addToListMultiselect(
|
||||
ListUIState productListState, AddToSubscriptionMultiselect action) {
|
||||
return productListState
|
||||
.rebuild((b) => b..selectedIds.add(action.entity.id));
|
||||
return productListState.rebuild((b) => b..selectedIds.add(action.entity.id));
|
||||
}
|
||||
|
||||
ListUIState _removeFromListMultiselect(
|
||||
|
|
@ -154,12 +170,17 @@ ListUIState _clearListMultiselect(
|
|||
final subscriptionsReducer = combineReducers<SubscriptionState>([
|
||||
TypedReducer<SubscriptionState, SaveSubscriptionSuccess>(_updateSubscription),
|
||||
TypedReducer<SubscriptionState, AddSubscriptionSuccess>(_addSubscription),
|
||||
TypedReducer<SubscriptionState, LoadSubscriptionsSuccess>(_setLoadedSubscriptions),
|
||||
TypedReducer<SubscriptionState, LoadSubscriptionSuccess>(_setLoadedSubscription),
|
||||
TypedReducer<SubscriptionState, LoadSubscriptionsSuccess>(
|
||||
_setLoadedSubscriptions),
|
||||
TypedReducer<SubscriptionState, LoadSubscriptionSuccess>(
|
||||
_setLoadedSubscription),
|
||||
TypedReducer<SubscriptionState, LoadCompanySuccess>(_setLoadedCompany),
|
||||
TypedReducer<SubscriptionState, ArchiveSubscriptionsSuccess>(_archiveSubscriptionSuccess),
|
||||
TypedReducer<SubscriptionState, DeleteSubscriptionsSuccess>(_deleteSubscriptionSuccess),
|
||||
TypedReducer<SubscriptionState, RestoreSubscriptionsSuccess>(_restoreSubscriptionSuccess),
|
||||
TypedReducer<SubscriptionState, ArchiveSubscriptionsSuccess>(
|
||||
_archiveSubscriptionSuccess),
|
||||
TypedReducer<SubscriptionState, DeleteSubscriptionsSuccess>(
|
||||
_deleteSubscriptionSuccess),
|
||||
TypedReducer<SubscriptionState, RestoreSubscriptionsSuccess>(
|
||||
_restoreSubscriptionSuccess),
|
||||
]);
|
||||
|
||||
SubscriptionState _archiveSubscriptionSuccess(
|
||||
|
|
@ -189,21 +210,23 @@ SubscriptionState _restoreSubscriptionSuccess(
|
|||
});
|
||||
}
|
||||
|
||||
SubscriptionState _addSubscription(SubscriptionState subscriptionState, AddSubscriptionSuccess action) {
|
||||
SubscriptionState _addSubscription(
|
||||
SubscriptionState subscriptionState, AddSubscriptionSuccess action) {
|
||||
return subscriptionState.rebuild((b) => b
|
||||
..map[action.subscription.id] = action.subscription
|
||||
..list.add(action.subscription.id));
|
||||
}
|
||||
|
||||
SubscriptionState _updateSubscription(SubscriptionState subscriptionState, SaveSubscriptionSuccess action) {
|
||||
return subscriptionState.rebuild((b) => b
|
||||
..map[action.subscription.id] = action.subscription);
|
||||
SubscriptionState _updateSubscription(
|
||||
SubscriptionState subscriptionState, SaveSubscriptionSuccess action) {
|
||||
return subscriptionState
|
||||
.rebuild((b) => b..map[action.subscription.id] = action.subscription);
|
||||
}
|
||||
|
||||
SubscriptionState _setLoadedSubscription(
|
||||
SubscriptionState subscriptionState, LoadSubscriptionSuccess action) {
|
||||
return subscriptionState.rebuild((b) => b
|
||||
..map[action.subscription.id] = action.subscription);
|
||||
return subscriptionState
|
||||
.rebuild((b) => b..map[action.subscription.id] = action.subscription);
|
||||
}
|
||||
|
||||
SubscriptionState _setLoadedSubscriptions(
|
||||
|
|
@ -211,7 +234,7 @@ SubscriptionState _setLoadedSubscriptions(
|
|||
subscriptionState.loadSubscriptions(action.subscriptions);
|
||||
|
||||
SubscriptionState _setLoadedCompany(
|
||||
SubscriptionState subscriptionState, LoadCompanySuccess action) {
|
||||
final company = action.userCompany.company;
|
||||
return subscriptionState.loadSubscriptions(company.subscriptions);
|
||||
SubscriptionState subscriptionState, LoadCompanySuccess action) {
|
||||
final company = action.userCompany.company;
|
||||
return subscriptionState.loadSubscriptions(company.subscriptions);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -329,7 +329,17 @@ Reducer<BuiltList<HistoryRecord>> historyReducer = combineReducers([
|
|||
_addToHistory(historyList,
|
||||
HistoryRecord(id: action.group.id, entityType: EntityType.group))),
|
||||
// STARTER: history - do not remove comment
|
||||
TypedReducer<BuiltList<HistoryRecord>, ViewSubscription>((historyList, action) => _addToHistory(historyList, HistoryRecord(id: action.subscriptionId, entityType: EntityType.subscription))),TypedReducer<BuiltList<HistoryRecord>, EditSubscription>((historyList, action) => _addToHistory(historyList, HistoryRecord(id: action.subscription.id, entityType: EntityType.subscription))),
|
||||
TypedReducer<BuiltList<HistoryRecord>, ViewSubscription>(
|
||||
(historyList, action) => _addToHistory(
|
||||
historyList,
|
||||
HistoryRecord(
|
||||
id: action.subscriptionId, entityType: EntityType.subscription))),
|
||||
TypedReducer<BuiltList<HistoryRecord>, EditSubscription>(
|
||||
(historyList, action) => _addToHistory(
|
||||
historyList,
|
||||
HistoryRecord(
|
||||
id: action.subscription.id,
|
||||
entityType: EntityType.subscription))),
|
||||
|
||||
TypedReducer<BuiltList<HistoryRecord>, ViewTaskStatus>(
|
||||
(historyList, action) => _addToHistory(
|
||||
|
|
|
|||
|
|
@ -88,8 +88,8 @@ UIState uiReducer(UIState state, dynamic action) {
|
|||
.replace(dashboardUIReducer(state.dashboardUIState, action))
|
||||
..reportsUIState.replace(reportsUIReducer(state.reportsUIState, action))
|
||||
// STARTER: reducer - do not remove comment
|
||||
..subscriptionUIState.replace(subscriptionUIReducer(state.subscriptionUIState, action))
|
||||
|
||||
..subscriptionUIState
|
||||
.replace(subscriptionUIReducer(state.subscriptionUIState, action))
|
||||
..taskStatusUIState
|
||||
.replace(taskStatusUIReducer(state.taskStatusUIState, action))
|
||||
..expenseCategoryUIState
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
|
|||
clientUIState: ClientUIState(),
|
||||
invoiceUIState: InvoiceUIState(),
|
||||
// STARTER: constructor - do not remove comment
|
||||
subscriptionUIState: SubscriptionUIState(),
|
||||
subscriptionUIState: SubscriptionUIState(),
|
||||
|
||||
taskStatusUIState: TaskStatusUIState(),
|
||||
expenseCategoryUIState: ExpenseCategoryUIState(),
|
||||
|
|
@ -112,7 +112,7 @@ subscriptionUIState: SubscriptionUIState(),
|
|||
InvoiceUIState get invoiceUIState;
|
||||
|
||||
// STARTER: properties - do not remove comment
|
||||
SubscriptionUIState get subscriptionUIState;
|
||||
SubscriptionUIState get subscriptionUIState;
|
||||
|
||||
TaskStatusUIState get taskStatusUIState;
|
||||
|
||||
|
|
|
|||
|
|
@ -386,13 +386,6 @@ class MenuDrawer extends StatelessWidget {
|
|||
iconTooltip: localization.newExpense,
|
||||
),
|
||||
// STARTER: menu - do not remove comment
|
||||
DrawerTile(
|
||||
company: company,
|
||||
entityType: EntityType.subscription,
|
||||
icon: getEntityIcon(EntityType.subscription),
|
||||
title: localization.subscriptions,
|
||||
),
|
||||
|
||||
DrawerTile(
|
||||
company: company,
|
||||
icon: getEntityIcon(EntityType.reports),
|
||||
|
|
|
|||
|
|
@ -115,8 +115,7 @@ class LoginVM {
|
|||
}) async {
|
||||
try {
|
||||
await GoogleOAuth.signOut();
|
||||
final signedIn = await GoogleOAuth.signIn(
|
||||
(idToken, accessToken) {
|
||||
final signedIn = await GoogleOAuth.signIn((idToken, accessToken) {
|
||||
if (idToken.isEmpty || accessToken.isEmpty) {
|
||||
GoogleOAuth.signOut();
|
||||
completer.completeError(
|
||||
|
|
|
|||
|
|
@ -63,26 +63,31 @@ class SubscriptionEditVM {
|
|||
onChanged: (SubscriptionEntity subscription) {
|
||||
store.dispatch(UpdateSubscription(subscription));
|
||||
},
|
||||
onCancelPressed: (BuildContext context) {
|
||||
createEntity(context: context, entity: SubscriptionEntity(), force: true);
|
||||
},
|
||||
onCancelPressed: (BuildContext context) {
|
||||
createEntity(
|
||||
context: context, entity: SubscriptionEntity(), force: true);
|
||||
},
|
||||
onSavePressed: (BuildContext context) {
|
||||
final localization = AppLocalization.of(context);
|
||||
final Completer<SubscriptionEntity> completer = new Completer<SubscriptionEntity>();
|
||||
store.dispatch(SaveSubscriptionRequest(completer: completer, subscription: subscription));
|
||||
final Completer<SubscriptionEntity> completer =
|
||||
new Completer<SubscriptionEntity>();
|
||||
store.dispatch(SaveSubscriptionRequest(
|
||||
completer: completer, subscription: subscription));
|
||||
return completer.future.then((savedSubscription) {
|
||||
showToast(subscription.isNew
|
||||
? localization.createdSubscription
|
||||
: localization.updatedSubscription);
|
||||
? localization.createdSubscription
|
||||
: localization.updatedSubscription);
|
||||
if (isMobile(context)) {
|
||||
store.dispatch(UpdateCurrentRoute(SubscriptionViewScreen.route));
|
||||
if (subscription.isNew) {
|
||||
Navigator.of(context).pushReplacementNamed(SubscriptionViewScreen.route);
|
||||
} else {
|
||||
Navigator.of(context).pop(savedSubscription);
|
||||
}
|
||||
store.dispatch(UpdateCurrentRoute(SubscriptionViewScreen.route));
|
||||
if (subscription.isNew) {
|
||||
Navigator.of(context)
|
||||
.pushReplacementNamed(SubscriptionViewScreen.route);
|
||||
} else {
|
||||
Navigator.of(context).pop(savedSubscription);
|
||||
}
|
||||
} else {
|
||||
viewEntity(context: context, entity: savedSubscription, force: true);
|
||||
viewEntity(
|
||||
context: context, entity: savedSubscription, force: true);
|
||||
}
|
||||
}).catchError((Object error) {
|
||||
showDialog<ErrorDialog>(
|
||||
|
|
|
|||
|
|
@ -3,11 +3,8 @@ import 'package:invoiceninja_flutter/data/models/models.dart';
|
|||
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
|
||||
|
||||
class SubscriptionPresenter extends EntityPresenter {
|
||||
|
||||
static List<String> getDefaultTableFields(UserCompanyEntity userCompany) {
|
||||
return [
|
||||
|
||||
];
|
||||
return [];
|
||||
}
|
||||
|
||||
static List<String> getAllTableFields(UserCompanyEntity userCompany) {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,10 @@ import 'package:invoiceninja_flutter/ui/subscription/view/subscription_view.dart
|
|||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
|
||||
class SubscriptionViewScreen extends StatelessWidget {
|
||||
const SubscriptionViewScreen({Key key, this.isFilter = false,}) : super(key: key);
|
||||
const SubscriptionViewScreen({
|
||||
Key key,
|
||||
this.isFilter = false,
|
||||
}) : super(key: key);
|
||||
static const String route = '/subscription/view';
|
||||
final bool isFilter;
|
||||
|
||||
|
|
@ -34,7 +37,6 @@ class SubscriptionViewScreen extends StatelessWidget {
|
|||
}
|
||||
|
||||
class SubscriptionViewVM {
|
||||
|
||||
SubscriptionViewVM({
|
||||
@required this.state,
|
||||
@required this.subscription,
|
||||
|
|
@ -48,27 +50,29 @@ class SubscriptionViewVM {
|
|||
|
||||
factory SubscriptionViewVM.fromStore(Store<AppState> store) {
|
||||
final state = store.state;
|
||||
final subscription = state.subscriptionState.map[state.subscriptionUIState.selectedId] ??
|
||||
SubscriptionEntity(id: state.subscriptionUIState.selectedId);
|
||||
final subscription =
|
||||
state.subscriptionState.map[state.subscriptionUIState.selectedId] ??
|
||||
SubscriptionEntity(id: state.subscriptionUIState.selectedId);
|
||||
|
||||
Future<Null> _handleRefresh(BuildContext context) {
|
||||
final completer = snackBarCompleter<Null>(
|
||||
context, AppLocalization.of(context).refreshComplete);
|
||||
store.dispatch(LoadSubscription(completer: completer, subscriptionId: subscription.id));
|
||||
store.dispatch(LoadSubscription(
|
||||
completer: completer, subscriptionId: subscription.id));
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
return SubscriptionViewVM(
|
||||
state: state,
|
||||
company: state.company,
|
||||
isSaving: state.isSaving,
|
||||
isLoading: state.isLoading,
|
||||
isDirty: subscription.isNew,
|
||||
subscription: subscription,
|
||||
onRefreshed: (context) => _handleRefresh(context),
|
||||
state: state,
|
||||
company: state.company,
|
||||
isSaving: state.isSaving,
|
||||
isLoading: state.isLoading,
|
||||
isDirty: subscription.isNew,
|
||||
subscription: subscription,
|
||||
onRefreshed: (context) => _handleRefresh(context),
|
||||
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||
handleEntitiesActions(context, [subscription], action, autoPop: true),
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
final AppState state;
|
||||
|
|
|
|||
Loading…
Reference in New Issue