Merge pull request #97 from gincos/develop

Refactor modules to use /bulk and ListFilterMessage
This commit is contained in:
Hillel Coren 2019-10-30 21:04:37 +02:00 committed by GitHub
commit 6d5d255dc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 593 additions and 391 deletions

View File

@ -60,7 +60,7 @@ class ClientRepository {
if (action != null) { if (action != null) {
url += '&action=' + action.toString(); url += '&action=' + action.toString();
} }
response = await webClient.put(url, credentials.token, response = await webClient.post(url, credentials.token,
data: json.encode([ids])); data: json.encode([ids]));
break; break;
default: default:

View File

@ -44,6 +44,32 @@ class InvoiceRepository {
return invoiceResponse.data; return invoiceResponse.data;
} }
Future<List<InvoiceEntity>> bulkAction(
Credentials credentials, List<String> ids, EntityAction action) async {
dynamic response;
switch (action) {
case EntityAction.restore:
case EntityAction.archive:
case EntityAction.delete:
var url = credentials.url + '/invoices/bulk?include=activities';
if (action != null) {
url += '&action=' + action.toString();
}
response = await webClient.post(url, credentials.token,
data: json.encode([ids]));
break;
default:
// Might have other actions in the future
break;
}
final InvoiceListResponse invoiceResponse =
serializers.deserializeWith(InvoiceListResponse.serializer, response);
return invoiceResponse.data.toList();
}
Future<InvoiceEntity> saveData(Credentials credentials, InvoiceEntity invoice, Future<InvoiceEntity> saveData(Credentials credentials, InvoiceEntity invoice,
[EntityAction action]) async { [EntityAction action]) async {
final data = serializers.serializeWith(InvoiceEntity.serializer, invoice); final data = serializers.serializeWith(InvoiceEntity.serializer, invoice);

View File

@ -31,6 +31,32 @@ class PaymentRepository {
return paymentResponse.data; return paymentResponse.data;
} }
Future<List<PaymentEntity>> bulkAction(
Credentials credentials, List<String> ids, EntityAction action) async {
dynamic response;
switch (action) {
case EntityAction.restore:
case EntityAction.archive:
case EntityAction.delete:
var url = credentials.url + '/payments/bulk?include=activities';
if (action != null) {
url += '&action=' + action.toString();
}
response = await webClient.post(url, credentials.token,
data: json.encode([ids]));
break;
default:
// Might have other actions in the future
break;
}
final PaymentListResponse paymentResponse =
serializers.deserializeWith(PaymentListResponse.serializer, response);
return paymentResponse.data.toList();
}
Future<PaymentEntity> saveData(Credentials credentials, PaymentEntity payment, Future<PaymentEntity> saveData(Credentials credentials, PaymentEntity payment,
{EntityAction action, bool sendEmail = false}) async { {EntityAction action, bool sendEmail = false}) async {
final data = serializers.serializeWith(PaymentEntity.serializer, payment); final data = serializers.serializeWith(PaymentEntity.serializer, payment);

View File

@ -31,6 +31,32 @@ class ProductRepository {
return productResponse.data; return productResponse.data;
} }
Future<List<ProductEntity>> bulkAction(
Credentials credentials, List<String> ids, EntityAction action) async {
dynamic response;
switch (action) {
case EntityAction.restore:
case EntityAction.archive:
case EntityAction.delete:
var url = credentials.url + '/products/bulk?include=activities';
if (action != null) {
url += '&action=' + action.toString();
}
response = await webClient.post(url, credentials.token,
data: json.encode([ids]));
break;
default:
// Might have other actions in the future
break;
}
final ProductListResponse productResponse =
serializers.deserializeWith(ProductListResponse.serializer, response);
return productResponse.data.toList();
}
Future<ProductEntity> saveData(Credentials credentials, ProductEntity product, Future<ProductEntity> saveData(Credentials credentials, ProductEntity product,
[EntityAction action]) async { [EntityAction action]) async {
final data = serializers.serializeWith(ProductEntity.serializer, product); final data = serializers.serializeWith(ProductEntity.serializer, product);

View File

@ -44,6 +44,32 @@ class QuoteRepository {
return quoteResponse.data; return quoteResponse.data;
} }
Future<List<InvoiceEntity>> bulkAction(
Credentials credentials, List<String> ids, EntityAction action) async {
dynamic response;
switch (action) {
case EntityAction.restore:
case EntityAction.archive:
case EntityAction.delete:
var url = credentials.url + '/quotes/bulk?include=activities';
if (action != null) {
url += '&action=' + action.toString();
}
response = await webClient.post(url, credentials.token,
data: json.encode([ids]));
break;
default:
// Might have other actions in the future
break;
}
final InvoiceListResponse invoiceResponse =
serializers.deserializeWith(InvoiceListResponse.serializer, response);
return invoiceResponse.data.toList();
}
Future<InvoiceEntity> saveData(Credentials credentials, InvoiceEntity quote, Future<InvoiceEntity> saveData(Credentials credentials, InvoiceEntity quote,
[EntityAction action]) async { [EntityAction action]) async {
final data = serializers.serializeWith(InvoiceEntity.serializer, quote); final data = serializers.serializeWith(InvoiceEntity.serializer, quote);

View File

@ -214,60 +214,60 @@ class MarkSentInvoiceFailure implements StopSaving {
} }
class ArchiveInvoiceRequest implements StartSaving { class ArchiveInvoiceRequest implements StartSaving {
ArchiveInvoiceRequest(this.completer, this.invoiceId); ArchiveInvoiceRequest(this.completer, this.invoiceIds);
final Completer completer; final Completer completer;
final String invoiceId; final List<String> invoiceIds;
} }
class ArchiveInvoiceSuccess implements StopSaving, PersistData { class ArchiveInvoiceSuccess implements StopSaving, PersistData {
ArchiveInvoiceSuccess(this.invoice); ArchiveInvoiceSuccess(this.invoices);
final InvoiceEntity invoice; final List<InvoiceEntity> invoices;
} }
class ArchiveInvoiceFailure implements StopSaving { class ArchiveInvoiceFailure implements StopSaving {
ArchiveInvoiceFailure(this.invoice); ArchiveInvoiceFailure(this.invoices);
final InvoiceEntity invoice; final List<InvoiceEntity> invoices;
} }
class DeleteInvoiceRequest implements StartSaving { class DeleteInvoiceRequest implements StartSaving {
DeleteInvoiceRequest(this.completer, this.invoiceId); DeleteInvoiceRequest(this.completer, this.invoiceIds);
final Completer completer; final Completer completer;
final String invoiceId; final List<String> invoiceIds;
} }
class DeleteInvoiceSuccess implements StopSaving, PersistData { class DeleteInvoiceSuccess implements StopSaving, PersistData {
DeleteInvoiceSuccess(this.invoice); DeleteInvoiceSuccess(this.invoices);
final InvoiceEntity invoice; final List<InvoiceEntity> invoices;
} }
class DeleteInvoiceFailure implements StopSaving { class DeleteInvoiceFailure implements StopSaving {
DeleteInvoiceFailure(this.invoice); DeleteInvoiceFailure(this.invoices);
final InvoiceEntity invoice; final List<InvoiceEntity> invoices;
} }
class RestoreInvoiceRequest implements StartSaving { class RestoreInvoiceRequest implements StartSaving {
RestoreInvoiceRequest(this.completer, this.invoiceId); RestoreInvoiceRequest(this.completer, this.invoiceIds);
final Completer completer; final Completer completer;
final String invoiceId; final List<String> invoiceIds;
} }
class RestoreInvoiceSuccess implements StopSaving, PersistData { class RestoreInvoiceSuccess implements StopSaving, PersistData {
RestoreInvoiceSuccess(this.invoice); RestoreInvoiceSuccess(this.invoices);
final InvoiceEntity invoice; final List<InvoiceEntity> invoices;
} }
class RestoreInvoiceFailure implements StopSaving { class RestoreInvoiceFailure implements StopSaving {
RestoreInvoiceFailure(this.invoice); RestoreInvoiceFailure(this.invoices);
final InvoiceEntity invoice; final List<InvoiceEntity> invoices;
} }
class FilterInvoices { class FilterInvoices {
@ -336,6 +336,7 @@ void handleInvoiceAction(BuildContext context, List<BaseEntity> invoices,
final CompanyEntity company = state.selectedCompany; final CompanyEntity company = state.selectedCompany;
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);
final invoice = invoices.first as InvoiceEntity; final invoice = invoices.first as InvoiceEntity;
final invoiceIds = invoices.map((invoice) => invoice.id).toList();
switch (action) { switch (action) {
case EntityAction.edit: case EntityAction.edit:
@ -375,16 +376,16 @@ void handleInvoiceAction(BuildContext context, List<BaseEntity> invoices,
case EntityAction.restore: case EntityAction.restore:
store.dispatch(RestoreInvoiceRequest( store.dispatch(RestoreInvoiceRequest(
snackBarCompleter(context, localization.restoredInvoice), snackBarCompleter(context, localization.restoredInvoice),
invoice.id)); invoiceIds));
break; break;
case EntityAction.archive: case EntityAction.archive:
store.dispatch(ArchiveInvoiceRequest( store.dispatch(ArchiveInvoiceRequest(
snackBarCompleter(context, localization.archivedInvoice), snackBarCompleter(context, localization.archivedInvoice),
invoice.id)); invoiceIds));
break; break;
case EntityAction.delete: case EntityAction.delete:
store.dispatch(DeleteInvoiceRequest( store.dispatch(DeleteInvoiceRequest(
snackBarCompleter(context, localization.deletedInvoice), invoice.id)); snackBarCompleter(context, localization.deletedInvoice), invoiceIds));
break; break;
case EntityAction.toggleMultiselect: case EntityAction.toggleMultiselect:
if (!store.state.invoiceListState.isInMultiselect()) { if (!store.state.invoiceListState.isInMultiselect()) {

View File

@ -137,17 +137,20 @@ Middleware<AppState> _showEmailInvoice() {
Middleware<AppState> _archiveInvoice(InvoiceRepository repository) { Middleware<AppState> _archiveInvoice(InvoiceRepository repository) {
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) { return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
final action = dynamicAction as ArchiveInvoiceRequest; final action = dynamicAction as ArchiveInvoiceRequest;
final origInvoice = store.state.invoiceState.map[action.invoiceId];
repository repository
.saveData(store.state.credentials, origInvoice, EntityAction.archive) .bulkAction(
.then((InvoiceEntity invoice) { store.state.credentials, action.invoiceIds, EntityAction.archive)
store.dispatch(ArchiveInvoiceSuccess(invoice)); .then((List<InvoiceEntity> invoices) {
store.dispatch(ArchiveInvoiceSuccess(invoices));
if (action.completer != null) { if (action.completer != null) {
action.completer.complete(null); action.completer.complete(null);
} }
}).catchError((Object error) { }).catchError((Object error) {
print(error); print(error);
store.dispatch(ArchiveInvoiceFailure(origInvoice)); final invoices = action.invoiceIds
.map((id) => store.state.invoiceState.map[id])
.toList();
store.dispatch(ArchiveInvoiceFailure(invoices));
if (action.completer != null) { if (action.completer != null) {
action.completer.completeError(error); action.completer.completeError(error);
} }
@ -160,18 +163,21 @@ Middleware<AppState> _archiveInvoice(InvoiceRepository repository) {
Middleware<AppState> _deleteInvoice(InvoiceRepository repository) { Middleware<AppState> _deleteInvoice(InvoiceRepository repository) {
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) { return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
final action = dynamicAction as DeleteInvoiceRequest; final action = dynamicAction as DeleteInvoiceRequest;
final origInvoice = store.state.invoiceState.map[action.invoiceId];
repository repository
.saveData(store.state.credentials, origInvoice, EntityAction.delete) .bulkAction(
.then((InvoiceEntity invoice) { store.state.credentials, action.invoiceIds, EntityAction.delete)
store.dispatch(DeleteInvoiceSuccess(invoice)); .then((List<InvoiceEntity> invoices) {
store.dispatch(LoadClient(clientId: invoice.clientId)); store.dispatch(DeleteInvoiceSuccess(invoices));
store.dispatch(LoadClient(clientId: invoices.first.clientId));
if (action.completer != null) { if (action.completer != null) {
action.completer.complete(null); action.completer.complete(null);
} }
}).catchError((Object error) { }).catchError((Object error) {
print(error); print(error);
store.dispatch(DeleteInvoiceFailure(origInvoice)); final invoices = action.invoiceIds
.map((id) => store.state.invoiceState.map[id])
.toList();
store.dispatch(DeleteInvoiceFailure(invoices));
if (action.completer != null) { if (action.completer != null) {
action.completer.completeError(error); action.completer.completeError(error);
} }
@ -184,18 +190,21 @@ Middleware<AppState> _deleteInvoice(InvoiceRepository repository) {
Middleware<AppState> _restoreInvoice(InvoiceRepository repository) { Middleware<AppState> _restoreInvoice(InvoiceRepository repository) {
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) { return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
final action = dynamicAction as RestoreInvoiceRequest; final action = dynamicAction as RestoreInvoiceRequest;
final origInvoice = store.state.invoiceState.map[action.invoiceId];
repository repository
.saveData(store.state.credentials, origInvoice, EntityAction.restore) .bulkAction(
.then((InvoiceEntity invoice) { store.state.credentials, action.invoiceIds, EntityAction.restore)
store.dispatch(RestoreInvoiceSuccess(invoice)); .then((List<InvoiceEntity> invoices) {
store.dispatch(LoadClient(clientId: invoice.clientId)); store.dispatch(RestoreInvoiceSuccess(invoices));
store.dispatch(LoadClient(clientId: invoices.first.clientId));
if (action.completer != null) { if (action.completer != null) {
action.completer.complete(null); action.completer.complete(null);
} }
}).catchError((Object error) { }).catchError((Object error) {
print(error); print(error);
store.dispatch(RestoreInvoiceFailure(origInvoice)); final invoices = action.invoiceIds
.map((id) => store.state.invoiceState.map[id])
.toList();
store.dispatch(RestoreInvoiceFailure(invoices));
if (action.completer != null) { if (action.completer != null) {
action.completer.completeError(error); action.completer.completeError(error);
} }

View File

@ -28,10 +28,10 @@ InvoiceItemEntity editInvoiceItem(
} }
Reducer<String> dropdownFilterReducer = combineReducers([ Reducer<String> dropdownFilterReducer = combineReducers([
TypedReducer<String, FilterInvoiceDropdown>(filterClientDropdownReducer), TypedReducer<String, FilterInvoiceDropdown>(filterInvoiceDropdownReducer),
]); ]);
String filterClientDropdownReducer( String filterInvoiceDropdownReducer(
String dropdownFilter, FilterInvoiceDropdown action) { String dropdownFilter, FilterInvoiceDropdown action) {
return action.filter; return action.filter;
} }
@ -64,7 +64,7 @@ final editingReducer = combineReducers<InvoiceEntity>([
TypedReducer<InvoiceEntity, DiscardChanges>(_clearEditing), TypedReducer<InvoiceEntity, DiscardChanges>(_clearEditing),
]); ]);
InvoiceEntity _clearEditing(InvoiceEntity client, dynamic action) { InvoiceEntity _clearEditing(InvoiceEntity invoice, dynamic action) {
return InvoiceEntity(); return InvoiceEntity();
} }
@ -228,75 +228,104 @@ InvoiceState _markSentInvoiceSuccess(
InvoiceState _archiveInvoiceRequest( InvoiceState _archiveInvoiceRequest(
InvoiceState invoiceState, ArchiveInvoiceRequest action) { InvoiceState invoiceState, ArchiveInvoiceRequest action) {
final invoice = invoiceState.map[action.invoiceId] final invoices = action.invoiceIds.map((id) => invoiceState.map[id]).toList();
.rebuild((b) => b..archivedAt = DateTime.now().millisecondsSinceEpoch);
return invoiceState.rebuild((b) => b..map[action.invoiceId] = invoice); for (int i = 0; i < invoices.length; i++) {
invoices[i] = invoices[i]
.rebuild((b) => b..archivedAt = DateTime.now().millisecondsSinceEpoch);
}
return invoiceState.rebuild((b) {
for (final invoice in invoices) {
b.map[invoice.id] = invoice;
}
});
} }
InvoiceState _archiveInvoiceSuccess( InvoiceState _archiveInvoiceSuccess(
InvoiceState invoiceState, ArchiveInvoiceSuccess action) { InvoiceState invoiceState, ArchiveInvoiceSuccess action) {
return invoiceState return invoiceState.rebuild((b) {
.rebuild((b) => b..map[action.invoice.id] = action.invoice); for (final invoice in action.invoices) {
b.map[invoice.id] = invoice;
}
});
} }
InvoiceState _archiveInvoiceFailure( InvoiceState _archiveInvoiceFailure(
InvoiceState invoiceState, ArchiveInvoiceFailure action) { InvoiceState invoiceState, ArchiveInvoiceFailure action) {
return invoiceState return invoiceState.rebuild((b) {
.rebuild((b) => b..map[action.invoice.id] = action.invoice); for (final invoice in action.invoices) {
b.map[invoice.id] = invoice;
}
});
} }
InvoiceState _deleteInvoiceRequest( InvoiceState _deleteInvoiceRequest(
InvoiceState invoiceState, DeleteInvoiceRequest action) { InvoiceState invoiceState, DeleteInvoiceRequest action) {
if (!invoiceState.map.containsKey(action.invoiceId)) { final invoices = action.invoiceIds.map((id) => invoiceState.map[id]).toList();
return invoiceState;
for (int i = 0; i < invoices.length; i++) {
invoices[i] = invoices[i].rebuild((b) => b
..archivedAt = DateTime.now().millisecondsSinceEpoch
..isDeleted = true);
} }
return invoiceState.rebuild((b) {
final invoice = invoiceState.map[action.invoiceId].rebuild((b) => b for (final invoice in invoices) {
..archivedAt = DateTime.now().millisecondsSinceEpoch b.map[invoice.id] = invoice;
..isDeleted = true); }
});
return invoiceState.rebuild((b) => b..map[action.invoiceId] = invoice);
} }
InvoiceState _deleteInvoiceSuccess( InvoiceState _deleteInvoiceSuccess(
InvoiceState invoiceState, DeleteInvoiceSuccess action) { InvoiceState invoiceState, DeleteInvoiceSuccess action) {
if (!invoiceState.map.containsKey(action.invoice.id)) { return invoiceState.rebuild((b) {
return invoiceState; for (final invoice in action.invoices) {
} b.map[invoice.id] = invoice;
}
return invoiceState });
.rebuild((b) => b..map[action.invoice.id] = action.invoice);
} }
InvoiceState _deleteInvoiceFailure( InvoiceState _deleteInvoiceFailure(
InvoiceState invoiceState, DeleteInvoiceFailure action) { InvoiceState invoiceState, DeleteInvoiceFailure action) {
if (!invoiceState.map.containsKey(action.invoice.id)) { return invoiceState.rebuild((b) {
return invoiceState; for (final invoice in action.invoices) {
} b.map[invoice.id] = invoice;
}
return invoiceState });
.rebuild((b) => b..map[action.invoice.id] = action.invoice);
} }
InvoiceState _restoreInvoiceRequest( InvoiceState _restoreInvoiceRequest(
InvoiceState invoiceState, RestoreInvoiceRequest action) { InvoiceState invoiceState, RestoreInvoiceRequest action) {
final invoice = invoiceState.map[action.invoiceId].rebuild((b) => b final invoices = action.invoiceIds.map((id) => invoiceState.map[id]).toList();
..archivedAt = null
..isDeleted = false); for (int i = 0; i < invoices.length; i++) {
return invoiceState.rebuild((b) => b..map[action.invoiceId] = invoice); invoices[i] = invoices[i].rebuild((b) => b
..archivedAt = null
..isDeleted = false);
}
return invoiceState.rebuild((b) {
for (final invoice in invoices) {
b.map[invoice.id] = invoice;
}
});
} }
InvoiceState _restoreInvoiceSuccess( InvoiceState _restoreInvoiceSuccess(
InvoiceState invoiceState, RestoreInvoiceSuccess action) { InvoiceState invoiceState, RestoreInvoiceSuccess action) {
return invoiceState return invoiceState.rebuild((b) {
.rebuild((b) => b..map[action.invoice.id] = action.invoice); for (final invoice in action.invoices) {
b.map[invoice.id] = invoice;
}
});
} }
InvoiceState _restoreInvoiceFailure( InvoiceState _restoreInvoiceFailure(
InvoiceState invoiceState, RestoreInvoiceFailure action) { InvoiceState invoiceState, RestoreInvoiceFailure action) {
return invoiceState return invoiceState.rebuild((b) {
.rebuild((b) => b..map[action.invoice.id] = action.invoice); for (final invoice in action.invoices) {
b.map[invoice.id] = invoice;
}
});
} }
InvoiceState _addInvoice(InvoiceState invoiceState, AddInvoiceSuccess action) { InvoiceState _addInvoice(InvoiceState invoiceState, AddInvoiceSuccess action) {

View File

@ -143,60 +143,60 @@ class SavePaymentFailure implements StopSaving {
} }
class ArchivePaymentRequest implements StartSaving { class ArchivePaymentRequest implements StartSaving {
ArchivePaymentRequest(this.completer, this.paymentId); ArchivePaymentRequest(this.completer, this.paymentIds);
final Completer completer; final Completer completer;
final String paymentId; final List<String> paymentIds;
} }
class ArchivePaymentSuccess implements StopSaving, PersistData { class ArchivePaymentSuccess implements StopSaving, PersistData {
ArchivePaymentSuccess(this.payment); ArchivePaymentSuccess(this.payments);
final PaymentEntity payment; final List<PaymentEntity> payments;
} }
class ArchivePaymentFailure implements StopSaving { class ArchivePaymentFailure implements StopSaving {
ArchivePaymentFailure(this.payment); ArchivePaymentFailure(this.payments);
final PaymentEntity payment; final List<PaymentEntity> payments;
} }
class DeletePaymentRequest implements StartSaving { class DeletePaymentRequest implements StartSaving {
DeletePaymentRequest(this.completer, this.paymentId); DeletePaymentRequest(this.completer, this.paymentIds);
final Completer completer; final Completer completer;
final String paymentId; final List<String> paymentIds;
} }
class DeletePaymentSuccess implements StopSaving, PersistData { class DeletePaymentSuccess implements StopSaving, PersistData {
DeletePaymentSuccess(this.payment); DeletePaymentSuccess(this.payments);
final PaymentEntity payment; final List<PaymentEntity> payments;
} }
class DeletePaymentFailure implements StopSaving { class DeletePaymentFailure implements StopSaving {
DeletePaymentFailure(this.payment); DeletePaymentFailure(this.payments);
final PaymentEntity payment; final List<PaymentEntity> payments;
} }
class RestorePaymentRequest implements StartSaving { class RestorePaymentRequest implements StartSaving {
RestorePaymentRequest(this.completer, this.paymentId); RestorePaymentRequest(this.completer, this.paymentIds);
final Completer completer; final Completer completer;
final String paymentId; final List<String> paymentIds;
} }
class RestorePaymentSuccess implements StopSaving, PersistData { class RestorePaymentSuccess implements StopSaving, PersistData {
RestorePaymentSuccess(this.payment); RestorePaymentSuccess(this.payments);
final PaymentEntity payment; final List<PaymentEntity> payments;
} }
class RestorePaymentFailure implements StopSaving { class RestorePaymentFailure implements StopSaving {
RestorePaymentFailure(this.payment); RestorePaymentFailure(this.payments);
final PaymentEntity payment; final List<PaymentEntity> payments;
} }
class EmailPaymentRequest implements StartSaving { class EmailPaymentRequest implements StartSaving {
@ -265,6 +265,7 @@ void handlePaymentAction(
final store = StoreProvider.of<AppState>(context); final store = StoreProvider.of<AppState>(context);
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);
final paymentIds = payments.map((payment) => payment.id).toList();
final payment = payments.first; final payment = payments.first;
switch (action) { switch (action) {
@ -278,16 +279,16 @@ void handlePaymentAction(
case EntityAction.restore: case EntityAction.restore:
store.dispatch(RestorePaymentRequest( store.dispatch(RestorePaymentRequest(
snackBarCompleter(context, localization.restoredPayment), snackBarCompleter(context, localization.restoredPayment),
payment.id)); paymentIds));
break; break;
case EntityAction.archive: case EntityAction.archive:
store.dispatch(ArchivePaymentRequest( store.dispatch(ArchivePaymentRequest(
snackBarCompleter(context, localization.archivedPayment), snackBarCompleter(context, localization.archivedPayment),
payment.id)); paymentIds));
break; break;
case EntityAction.delete: case EntityAction.delete:
store.dispatch(DeletePaymentRequest( store.dispatch(DeletePaymentRequest(
snackBarCompleter(context, localization.deletedPayment), payment.id)); snackBarCompleter(context, localization.deletedPayment), paymentIds));
break; break;
case EntityAction.toggleMultiselect: case EntityAction.toggleMultiselect:
if (!store.state.paymentListState.isInMultiselect()) { if (!store.state.paymentListState.isInMultiselect()) {

View File

@ -111,18 +111,20 @@ Middleware<AppState> _viewPaymentList() {
Middleware<AppState> _archivePayment(PaymentRepository repository) { Middleware<AppState> _archivePayment(PaymentRepository repository) {
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) { return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
final action = dynamicAction as ArchivePaymentRequest; final action = dynamicAction as ArchivePaymentRequest;
final origPayment = store.state.paymentState.map[action.paymentId];
repository repository
.saveData(store.state.credentials, origPayment, .bulkAction(
action: EntityAction.archive) store.state.credentials, action.paymentIds, EntityAction.archive)
.then((PaymentEntity payment) { .then((List<PaymentEntity> payments) {
store.dispatch(ArchivePaymentSuccess(payment)); store.dispatch(ArchivePaymentSuccess(payments));
if (action.completer != null) { if (action.completer != null) {
action.completer.complete(null); action.completer.complete(null);
} }
}).catchError((Object error) { }).catchError((Object error) {
print(error); print(error);
store.dispatch(ArchivePaymentFailure(origPayment)); final payments = action.paymentIds
.map((id) => store.state.paymentState.map[id])
.toList();
store.dispatch(ArchivePaymentFailure(payments));
if (action.completer != null) { if (action.completer != null) {
action.completer.completeError(error); action.completer.completeError(error);
} }
@ -135,19 +137,21 @@ Middleware<AppState> _archivePayment(PaymentRepository repository) {
Middleware<AppState> _deletePayment(PaymentRepository repository) { Middleware<AppState> _deletePayment(PaymentRepository repository) {
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) { return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
final action = dynamicAction as DeletePaymentRequest; final action = dynamicAction as DeletePaymentRequest;
final origPayment = store.state.paymentState.map[action.paymentId];
repository repository
.saveData(store.state.credentials, origPayment, .bulkAction(
action: EntityAction.delete) store.state.credentials, action.paymentIds, EntityAction.delete)
.then((PaymentEntity payment) { .then((List<PaymentEntity> payments) {
store.dispatch(DeletePaymentSuccess(payment)); store.dispatch(DeletePaymentSuccess(payments));
store.dispatch(LoadInvoice(invoiceId: payment.invoiceId)); store.dispatch(LoadInvoice(invoiceId: payments.first.invoiceId));
if (action.completer != null) { if (action.completer != null) {
action.completer.complete(null); action.completer.complete(null);
} }
}).catchError((Object error) { }).catchError((Object error) {
print(error); print(error);
store.dispatch(DeletePaymentFailure(origPayment)); final payments = action.paymentIds
.map((id) => store.state.paymentState.map[id])
.toList();
store.dispatch(DeletePaymentFailure(payments));
if (action.completer != null) { if (action.completer != null) {
action.completer.completeError(error); action.completer.completeError(error);
} }
@ -160,19 +164,21 @@ Middleware<AppState> _deletePayment(PaymentRepository repository) {
Middleware<AppState> _restorePayment(PaymentRepository repository) { Middleware<AppState> _restorePayment(PaymentRepository repository) {
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) { return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
final action = dynamicAction as RestorePaymentRequest; final action = dynamicAction as RestorePaymentRequest;
final origPayment = store.state.paymentState.map[action.paymentId];
repository repository
.saveData(store.state.credentials, origPayment, .bulkAction(
action: EntityAction.restore) store.state.credentials, action.paymentIds, EntityAction.restore)
.then((PaymentEntity payment) { .then((List<PaymentEntity> payments) {
store.dispatch(RestorePaymentSuccess(payment)); store.dispatch(RestorePaymentSuccess(payments));
store.dispatch(LoadInvoice(invoiceId: payment.invoiceId)); store.dispatch(LoadInvoice(invoiceId: payments.first.invoiceId));
if (action.completer != null) { if (action.completer != null) {
action.completer.complete(null); action.completer.complete(null);
} }
}).catchError((Object error) { }).catchError((Object error) {
print(error); print(error);
store.dispatch(RestorePaymentFailure(origPayment)); final payments = action.paymentIds
.map((id) => store.state.paymentState.map[id])
.toList();
store.dispatch(RestorePaymentFailure(payments));
if (action.completer != null) { if (action.completer != null) {
action.completer.completeError(error); action.completer.completeError(error);
} }

View File

@ -150,63 +150,103 @@ final paymentsReducer = combineReducers<PaymentState>([
PaymentState _archivePaymentRequest( PaymentState _archivePaymentRequest(
PaymentState paymentState, ArchivePaymentRequest action) { PaymentState paymentState, ArchivePaymentRequest action) {
final payment = paymentState.map[action.paymentId] final payments = action.paymentIds.map((id) => paymentState.map[id]).toList();
.rebuild((b) => b..archivedAt = DateTime.now().millisecondsSinceEpoch);
return paymentState.rebuild((b) => b..map[action.paymentId] = payment); for (int i = 0; i < payments.length; i++) {
payments[i] = payments[i]
.rebuild((b) => b..archivedAt = DateTime.now().millisecondsSinceEpoch);
}
return paymentState.rebuild((b) {
for (final payment in payments) {
b.map[payment.id] = payment;
}
});
} }
PaymentState _archivePaymentSuccess( PaymentState _archivePaymentSuccess(
PaymentState paymentState, ArchivePaymentSuccess action) { PaymentState paymentState, ArchivePaymentSuccess action) {
return paymentState return paymentState.rebuild((b) {
.rebuild((b) => b..map[action.payment.id] = action.payment); for (final payment in action.payments) {
b.map[payment.id] = payment;
}
});
} }
PaymentState _archivePaymentFailure( PaymentState _archivePaymentFailure(
PaymentState paymentState, ArchivePaymentFailure action) { PaymentState paymentState, ArchivePaymentFailure action) {
return paymentState return paymentState.rebuild((b) {
.rebuild((b) => b..map[action.payment.id] = action.payment); for (final payment in action.payments) {
b.map[payment.id] = payment;
}
});
} }
PaymentState _deletePaymentRequest( PaymentState _deletePaymentRequest(
PaymentState paymentState, DeletePaymentRequest action) { PaymentState paymentState, DeletePaymentRequest action) {
final payment = paymentState.map[action.paymentId].rebuild((b) => b final payments = action.paymentIds.map((id) => paymentState.map[id]).toList();
..archivedAt = DateTime.now().millisecondsSinceEpoch
..isDeleted = true);
return paymentState.rebuild((b) => b..map[action.paymentId] = payment); for (int i = 0; i < payments.length; i++) {
payments[i] = payments[i].rebuild((b) => b
..archivedAt = DateTime.now().millisecondsSinceEpoch
..isDeleted = true);
}
return paymentState.rebuild((b) {
for (final payment in payments) {
b.map[payment.id] = payment;
}
});
} }
PaymentState _deletePaymentSuccess( PaymentState _deletePaymentSuccess(
PaymentState paymentState, DeletePaymentSuccess action) { PaymentState paymentState, DeletePaymentSuccess action) {
return paymentState return paymentState.rebuild((b) {
.rebuild((b) => b..map[action.payment.id] = action.payment); for (final payment in action.payments) {
b.map[payment.id] = payment;
}
});
} }
PaymentState _deletePaymentFailure( PaymentState _deletePaymentFailure(
PaymentState paymentState, DeletePaymentFailure action) { PaymentState paymentState, DeletePaymentFailure action) {
return paymentState return paymentState.rebuild((b) {
.rebuild((b) => b..map[action.payment.id] = action.payment); for (final payment in action.payments) {
b.map[payment.id] = payment;
}
});
} }
PaymentState _restorePaymentRequest( PaymentState _restorePaymentRequest(
PaymentState paymentState, RestorePaymentRequest action) { PaymentState paymentState, RestorePaymentRequest action) {
final payment = paymentState.map[action.paymentId].rebuild((b) => b final payments = action.paymentIds.map((id) => paymentState.map[id]).toList();
..archivedAt = null
..isDeleted = false); for (int i = 0; i < payments.length; i++) {
return paymentState.rebuild((b) => b..map[action.paymentId] = payment); payments[i] = payments[i].rebuild((b) => b
..archivedAt = null
..isDeleted = false);
}
return paymentState.rebuild((b) {
for (final payment in payments) {
b.map[payment.id] = payment;
}
});
} }
PaymentState _restorePaymentSuccess( PaymentState _restorePaymentSuccess(
PaymentState paymentState, RestorePaymentSuccess action) { PaymentState paymentState, RestorePaymentSuccess action) {
return paymentState return paymentState.rebuild((b) {
.rebuild((b) => b..map[action.payment.id] = action.payment); for (final payment in action.payments) {
b.map[payment.id] = payment;
}
});
} }
PaymentState _restorePaymentFailure( PaymentState _restorePaymentFailure(
PaymentState paymentState, RestorePaymentFailure action) { PaymentState paymentState, RestorePaymentFailure action) {
return paymentState return paymentState.rebuild((b) {
.rebuild((b) => b..map[action.payment.id] = action.payment); for (final payment in action.payments) {
b.map[payment.id] = payment;
}
});
} }
PaymentState _addPayment(PaymentState paymentState, AddPaymentSuccess action) { PaymentState _addPayment(PaymentState paymentState, AddPaymentSuccess action) {

View File

@ -103,60 +103,60 @@ class SaveProductFailure implements StopSaving {
} }
class ArchiveProductRequest implements StartSaving { class ArchiveProductRequest implements StartSaving {
ArchiveProductRequest(this.completer, this.productId); ArchiveProductRequest(this.completer, this.productIds);
final Completer completer; final Completer completer;
final String productId; final List<String> productIds;
} }
class ArchiveProductSuccess implements StopSaving, PersistData { class ArchiveProductSuccess implements StopSaving, PersistData {
ArchiveProductSuccess(this.product); ArchiveProductSuccess(this.products);
final ProductEntity product; final List<ProductEntity> products;
} }
class ArchiveProductFailure implements StopSaving { class ArchiveProductFailure implements StopSaving {
ArchiveProductFailure(this.product); ArchiveProductFailure(this.products);
final ProductEntity product; final List<ProductEntity> products;
} }
class DeleteProductRequest implements StartSaving { class DeleteProductRequest implements StartSaving {
DeleteProductRequest(this.completer, this.productId); DeleteProductRequest(this.completer, this.productIds);
final Completer completer; final Completer completer;
final String productId; final List<String> productIds;
} }
class DeleteProductSuccess implements StopSaving, PersistData { class DeleteProductSuccess implements StopSaving, PersistData {
DeleteProductSuccess(this.product); DeleteProductSuccess(this.products);
final ProductEntity product; final List<ProductEntity> products;
} }
class DeleteProductFailure implements StopSaving { class DeleteProductFailure implements StopSaving {
DeleteProductFailure(this.product); DeleteProductFailure(this.products);
final ProductEntity product; final List<ProductEntity> products;
} }
class RestoreProductRequest implements StartSaving { class RestoreProductRequest implements StartSaving {
RestoreProductRequest(this.completer, this.productId); RestoreProductRequest(this.completer, this.productIds);
final Completer completer; final Completer completer;
final String productId; final List<String> productIds;
} }
class RestoreProductSuccess implements StopSaving, PersistData { class RestoreProductSuccess implements StopSaving, PersistData {
RestoreProductSuccess(this.product); RestoreProductSuccess(this.products);
final ProductEntity product; final List<ProductEntity> products;
} }
class RestoreProductFailure implements StopSaving { class RestoreProductFailure implements StopSaving {
RestoreProductFailure(this.product); RestoreProductFailure(this.products);
final ProductEntity product; final List<ProductEntity> products;
} }
class FilterProducts { class FilterProducts {
@ -209,6 +209,7 @@ void handleProductAction(
final store = StoreProvider.of<AppState>(context); final store = StoreProvider.of<AppState>(context);
final state = store.state; final state = store.state;
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);
final productIds = products.map((product) => product.id).toList();
final product = products.first; final product = products.first;
switch (action) { switch (action) {
@ -230,16 +231,16 @@ void handleProductAction(
case EntityAction.restore: case EntityAction.restore:
store.dispatch(RestoreProductRequest( store.dispatch(RestoreProductRequest(
snackBarCompleter(context, localization.restoredProduct), snackBarCompleter(context, localization.restoredProduct),
product.id)); productIds));
break; break;
case EntityAction.archive: case EntityAction.archive:
store.dispatch(ArchiveProductRequest( store.dispatch(ArchiveProductRequest(
snackBarCompleter(context, localization.archivedProduct), snackBarCompleter(context, localization.archivedProduct),
product.id)); productIds));
break; break;
case EntityAction.delete: case EntityAction.delete:
store.dispatch(DeleteProductRequest( store.dispatch(DeleteProductRequest(
snackBarCompleter(context, localization.deletedProduct), product.id)); snackBarCompleter(context, localization.deletedProduct), productIds));
break; break;
case EntityAction.toggleMultiselect: case EntityAction.toggleMultiselect:
if (!store.state.productListState.isInMultiselect()) { if (!store.state.productListState.isInMultiselect()) {

View File

@ -103,17 +103,20 @@ Middleware<AppState> _viewProductList() {
Middleware<AppState> _archiveProduct(ProductRepository repository) { Middleware<AppState> _archiveProduct(ProductRepository repository) {
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) { return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
final action = dynamicAction as ArchiveProductRequest; final action = dynamicAction as ArchiveProductRequest;
final origProduct = store.state.productState.map[action.productId];
repository repository
.saveData(store.state.credentials, origProduct, EntityAction.archive) .bulkAction(
.then((ProductEntity product) { store.state.credentials, action.productIds, EntityAction.archive)
store.dispatch(ArchiveProductSuccess(product)); .then((List<ProductEntity> products) {
store.dispatch(ArchiveProductSuccess(products));
if (action.completer != null) { if (action.completer != null) {
action.completer.complete(null); action.completer.complete(null);
} }
}).catchError((dynamic error) { }).catchError((dynamic error) {
print(error); print(error);
store.dispatch(ArchiveProductFailure(origProduct)); final products = action.productIds
.map((id) => store.state.productState.map[id])
.toList();
store.dispatch(ArchiveProductFailure(products));
if (action.completer != null) { if (action.completer != null) {
action.completer.completeError(error); action.completer.completeError(error);
} }
@ -126,17 +129,20 @@ Middleware<AppState> _archiveProduct(ProductRepository repository) {
Middleware<AppState> _deleteProduct(ProductRepository repository) { Middleware<AppState> _deleteProduct(ProductRepository repository) {
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) { return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
final action = dynamicAction as DeleteProductRequest; final action = dynamicAction as DeleteProductRequest;
final origProduct = store.state.productState.map[action.productId];
repository repository
.saveData(store.state.credentials, origProduct, EntityAction.delete) .bulkAction(
.then((ProductEntity product) { store.state.credentials, action.productIds, EntityAction.delete)
store.dispatch(DeleteProductSuccess(product)); .then((List<ProductEntity> products) {
store.dispatch(DeleteProductSuccess(products));
if (action.completer != null) { if (action.completer != null) {
action.completer.complete(null); action.completer.complete(null);
} }
}).catchError((Object error) { }).catchError((Object error) {
print(error); print(error);
store.dispatch(DeleteProductFailure(origProduct)); final products = action.productIds
.map((id) => store.state.productState.map[id])
.toList();
store.dispatch(DeleteProductFailure(products));
if (action.completer != null) { if (action.completer != null) {
action.completer.completeError(error); action.completer.completeError(error);
} }
@ -149,17 +155,20 @@ Middleware<AppState> _deleteProduct(ProductRepository repository) {
Middleware<AppState> _restoreProduct(ProductRepository repository) { Middleware<AppState> _restoreProduct(ProductRepository repository) {
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) { return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
final action = dynamicAction as RestoreProductRequest; final action = dynamicAction as RestoreProductRequest;
final origProduct = store.state.productState.map[action.productId];
repository repository
.saveData(store.state.credentials, origProduct, EntityAction.restore) .bulkAction(
.then((ProductEntity product) { store.state.credentials, action.productIds, EntityAction.restore)
store.dispatch(RestoreProductSuccess(product)); .then((List<ProductEntity> products) {
store.dispatch(RestoreProductSuccess(products));
if (action.completer != null) { if (action.completer != null) {
action.completer.complete(null); action.completer.complete(null);
} }
}).catchError((Object error) { }).catchError((Object error) {
print(error); print(error);
store.dispatch(RestoreProductFailure(origProduct)); final products = action.productIds
.map((id) => store.state.productState.map[id])
.toList();
store.dispatch(RestoreProductFailure(products));
if (action.completer != null) { if (action.completer != null) {
action.completer.completeError(error); action.completer.completeError(error);
} }

View File

@ -16,10 +16,10 @@ EntityUIState productUIReducer(ProductUIState state, dynamic action) {
} }
Reducer<String> dropdownFilterReducer = combineReducers([ Reducer<String> dropdownFilterReducer = combineReducers([
TypedReducer<String, FilterProductDropdown>(filterClientDropdownReducer), TypedReducer<String, FilterProductDropdown>(filterProductDropdownReducer),
]); ]);
String filterClientDropdownReducer( String filterProductDropdownReducer(
String dropdownFilter, FilterProductDropdown action) { String dropdownFilter, FilterProductDropdown action) {
return action.filter; return action.filter;
} }
@ -38,11 +38,11 @@ final editingReducer = combineReducers<ProductEntity>([
TypedReducer<ProductEntity, DiscardChanges>(_clearEditing), TypedReducer<ProductEntity, DiscardChanges>(_clearEditing),
]); ]);
ProductEntity _clearEditing(ProductEntity client, dynamic action) { ProductEntity _clearEditing(ProductEntity product, dynamic action) {
return ProductEntity(); return ProductEntity();
} }
ProductEntity _updateEditing(ProductEntity client, dynamic action) { ProductEntity _updateEditing(ProductEntity product, dynamic action) {
return action.product; return action.product;
} }
@ -148,63 +148,103 @@ final productsReducer = combineReducers<ProductState>([
ProductState _archiveProductRequest( ProductState _archiveProductRequest(
ProductState productState, ArchiveProductRequest action) { ProductState productState, ArchiveProductRequest action) {
final product = productState.map[action.productId] final products = action.productIds.map((id) => productState.map[id]).toList();
.rebuild((b) => b..archivedAt = DateTime.now().millisecondsSinceEpoch);
return productState.rebuild((b) => b..map[action.productId] = product); for (int i = 0; i < products.length; i++) {
products[i] = products[i]
.rebuild((b) => b..archivedAt = DateTime.now().millisecondsSinceEpoch);
}
return productState.rebuild((b) {
for (final product in products) {
b.map[product.id] = product;
}
});
} }
ProductState _archiveProductSuccess( ProductState _archiveProductSuccess(
ProductState productState, ArchiveProductSuccess action) { ProductState productState, ArchiveProductSuccess action) {
return productState return productState.rebuild((b) {
.rebuild((b) => b..map[action.product.id] = action.product); for (final product in action.products) {
b.map[product.id] = product;
}
});
} }
ProductState _archiveProductFailure( ProductState _archiveProductFailure(
ProductState productState, ArchiveProductFailure action) { ProductState productState, ArchiveProductFailure action) {
return productState return productState.rebuild((b) {
.rebuild((b) => b..map[action.product.id] = action.product); for (final product in action.products) {
b.map[product.id] = product;
}
});
} }
ProductState _deleteProductRequest( ProductState _deleteProductRequest(
ProductState productState, DeleteProductRequest action) { ProductState productState, DeleteProductRequest action) {
final product = productState.map[action.productId].rebuild((b) => b final products = action.productIds.map((id) => productState.map[id]).toList();
..archivedAt = DateTime.now().millisecondsSinceEpoch
..isDeleted = true);
return productState.rebuild((b) => b..map[action.productId] = product); for (int i = 0; i < products.length; i++) {
products[i] = products[i].rebuild((b) => b
..archivedAt = DateTime.now().millisecondsSinceEpoch
..isDeleted = true);
}
return productState.rebuild((b) {
for (final product in products) {
b.map[product.id] = product;
}
});
} }
ProductState _deleteProductSuccess( ProductState _deleteProductSuccess(
ProductState productState, DeleteProductSuccess action) { ProductState productState, DeleteProductSuccess action) {
return productState return productState.rebuild((b) {
.rebuild((b) => b..map[action.product.id] = action.product); for (final product in action.products) {
b.map[product.id] = product;
}
});
} }
ProductState _deleteProductFailure( ProductState _deleteProductFailure(
ProductState productState, DeleteProductFailure action) { ProductState productState, DeleteProductFailure action) {
return productState return productState.rebuild((b) {
.rebuild((b) => b..map[action.product.id] = action.product); for (final product in action.products) {
b.map[product.id] = product;
}
});
} }
ProductState _restoreProductRequest( ProductState _restoreProductRequest(
ProductState productState, RestoreProductRequest action) { ProductState productState, RestoreProductRequest action) {
final product = productState.map[action.productId].rebuild((b) => b final products = action.productIds.map((id) => productState.map[id]).toList();
..archivedAt = null
..isDeleted = false); for (int i = 0; i < products.length; i++) {
return productState.rebuild((b) => b..map[action.productId] = product); products[i] = products[i].rebuild((b) => b
..archivedAt = null
..isDeleted = false);
}
return productState.rebuild((b) {
for (final product in products) {
b.map[product.id] = product;
}
});
} }
ProductState _restoreProductSuccess( ProductState _restoreProductSuccess(
ProductState productState, RestoreProductSuccess action) { ProductState productState, RestoreProductSuccess action) {
return productState return productState.rebuild((b) {
.rebuild((b) => b..map[action.product.id] = action.product); for (final product in action.products) {
b.map[product.id] = product;
}
});
} }
ProductState _restoreProductFailure( ProductState _restoreProductFailure(
ProductState productState, RestoreProductFailure action) { ProductState productState, RestoreProductFailure action) {
return productState return productState.rebuild((b) {
.rebuild((b) => b..map[action.product.id] = action.product); for (final product in action.products) {
b.map[product.id] = product;
}
});
} }
ProductState _addProduct(ProductState productState, AddProductSuccess action) { ProductState _addProduct(ProductState productState, AddProductSuccess action) {

View File

@ -214,60 +214,63 @@ class MarkSentQuoteFailure implements StopSaving {
} }
class ArchiveQuoteRequest implements StartSaving { class ArchiveQuoteRequest implements StartSaving {
ArchiveQuoteRequest(this.completer, this.quoteId); ArchiveQuoteRequest(this.completer, this.quoteIds);
final Completer completer; final Completer completer;
final String quoteId;
final List<String> quoteIds;
} }
class ArchiveQuoteSuccess implements StopSaving, PersistData { class ArchiveQuoteSuccess implements StopSaving, PersistData {
ArchiveQuoteSuccess(this.quote); ArchiveQuoteSuccess(this.quotes);
final InvoiceEntity quote; final List<InvoiceEntity> quotes;
} }
class ArchiveQuoteFailure implements StopSaving { class ArchiveQuoteFailure implements StopSaving {
ArchiveQuoteFailure(this.quote); ArchiveQuoteFailure(this.quotes);
final InvoiceEntity quote; final List<InvoiceEntity> quotes;
} }
class DeleteQuoteRequest implements StartSaving { class DeleteQuoteRequest implements StartSaving {
DeleteQuoteRequest(this.completer, this.quoteId); DeleteQuoteRequest(this.completer, this.quoteIds);
final Completer completer; final Completer completer;
final String quoteId;
final List<String> quoteIds;
} }
class DeleteQuoteSuccess implements StopSaving, PersistData { class DeleteQuoteSuccess implements StopSaving, PersistData {
DeleteQuoteSuccess(this.quote); DeleteQuoteSuccess(this.quotes);
final InvoiceEntity quote; final List<InvoiceEntity> quotes;
} }
class DeleteQuoteFailure implements StopSaving { class DeleteQuoteFailure implements StopSaving {
DeleteQuoteFailure(this.quote); DeleteQuoteFailure(this.quotes);
final InvoiceEntity quote; final List<InvoiceEntity> quotes;
} }
class RestoreQuoteRequest implements StartSaving { class RestoreQuoteRequest implements StartSaving {
RestoreQuoteRequest(this.completer, this.quoteId); RestoreQuoteRequest(this.completer, this.quoteIds);
final Completer completer; final Completer completer;
final String quoteId;
final List<String> quoteIds;
} }
class RestoreQuoteSuccess implements StopSaving, PersistData { class RestoreQuoteSuccess implements StopSaving, PersistData {
RestoreQuoteSuccess(this.quote); RestoreQuoteSuccess(this.quotes);
final InvoiceEntity quote; final List<InvoiceEntity> quotes;
} }
class RestoreQuoteFailure implements StopSaving { class RestoreQuoteFailure implements StopSaving {
RestoreQuoteFailure(this.quote); RestoreQuoteFailure(this.quotes);
final InvoiceEntity quote; final List<InvoiceEntity> quotes;
} }
class FilterQuotes { class FilterQuotes {
@ -354,6 +357,7 @@ Future handleQuoteAction(
final store = StoreProvider.of<AppState>(context); final store = StoreProvider.of<AppState>(context);
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);
final quote = quotes.first as InvoiceEntity; final quote = quotes.first as InvoiceEntity;
final quoteIds = quotes.map((quote) => quote.id).toList();
switch (action) { switch (action) {
case EntityAction.edit: case EntityAction.edit:
@ -399,15 +403,15 @@ Future handleQuoteAction(
break; break;
case EntityAction.restore: case EntityAction.restore:
store.dispatch(RestoreQuoteRequest( store.dispatch(RestoreQuoteRequest(
snackBarCompleter(context, localization.restoredQuote), quote.id)); snackBarCompleter(context, localization.restoredQuote), quoteIds));
break; break;
case EntityAction.archive: case EntityAction.archive:
store.dispatch(ArchiveQuoteRequest( store.dispatch(ArchiveQuoteRequest(
snackBarCompleter(context, localization.archivedQuote), quote.id)); snackBarCompleter(context, localization.archivedQuote), quoteIds));
break; break;
case EntityAction.delete: case EntityAction.delete:
store.dispatch(DeleteQuoteRequest( store.dispatch(DeleteQuoteRequest(
snackBarCompleter(context, localization.deletedQuote), quote.id)); snackBarCompleter(context, localization.deletedQuote), quoteIds));
break; break;
case EntityAction.toggleMultiselect: case EntityAction.toggleMultiselect:
if (!store.state.quoteListState.isInMultiselect()) { if (!store.state.quoteListState.isInMultiselect()) {

View File

@ -136,17 +136,19 @@ Middleware<AppState> _showEmailQuote() {
Middleware<AppState> _archiveQuote(QuoteRepository repository) { Middleware<AppState> _archiveQuote(QuoteRepository repository) {
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) { return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
final action = dynamicAction as ArchiveQuoteRequest; final action = dynamicAction as ArchiveQuoteRequest;
final origQuote = store.state.quoteState.map[action.quoteId];
repository repository
.saveData(store.state.credentials, origQuote, EntityAction.archive) .bulkAction(
.then((InvoiceEntity quote) { store.state.credentials, action.quoteIds, EntityAction.archive)
store.dispatch(ArchiveQuoteSuccess(quote)); .then((List<InvoiceEntity> quotes) {
store.dispatch(ArchiveQuoteSuccess(quotes));
if (action.completer != null) { if (action.completer != null) {
action.completer.complete(null); action.completer.complete(null);
} }
}).catchError((Object error) { }).catchError((Object error) {
print(error); print(error);
store.dispatch(ArchiveQuoteFailure(origQuote)); final quotes =
action.quoteIds.map((id) => store.state.quoteState.map[id]).toList();
store.dispatch(ArchiveQuoteFailure(quotes));
if (action.completer != null) { if (action.completer != null) {
action.completer.completeError(error); action.completer.completeError(error);
} }
@ -159,17 +161,20 @@ Middleware<AppState> _archiveQuote(QuoteRepository repository) {
Middleware<AppState> _deleteQuote(QuoteRepository repository) { Middleware<AppState> _deleteQuote(QuoteRepository repository) {
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) { return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
final action = dynamicAction as DeleteQuoteRequest; final action = dynamicAction as DeleteQuoteRequest;
final origQuote = store.state.quoteState.map[action.quoteId];
repository repository
.saveData(store.state.credentials, origQuote, EntityAction.delete) .bulkAction(
.then((InvoiceEntity quote) { store.state.credentials, action.quoteIds, EntityAction.delete)
store.dispatch(DeleteQuoteSuccess(quote)); .then((List<InvoiceEntity> quotes) {
store.dispatch(DeleteQuoteSuccess(quotes));
if (action.completer != null) { if (action.completer != null) {
action.completer.complete(null); action.completer.complete(null);
} }
}).catchError((Object error) { }).catchError((Object error) {
print(error); print(error);
store.dispatch(DeleteQuoteFailure(origQuote)); final quotes =
action.quoteIds.map((id) => store.state.quoteState.map[id]).toList();
store.dispatch(DeleteQuoteFailure(quotes));
if (action.completer != null) { if (action.completer != null) {
action.completer.completeError(error); action.completer.completeError(error);
} }
@ -182,17 +187,20 @@ Middleware<AppState> _deleteQuote(QuoteRepository repository) {
Middleware<AppState> _restoreQuote(QuoteRepository repository) { Middleware<AppState> _restoreQuote(QuoteRepository repository) {
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) { return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
final action = dynamicAction as RestoreQuoteRequest; final action = dynamicAction as RestoreQuoteRequest;
final origQuote = store.state.quoteState.map[action.quoteId];
repository repository
.saveData(store.state.credentials, origQuote, EntityAction.restore) .bulkAction(
.then((InvoiceEntity quote) { store.state.credentials, action.quoteIds, EntityAction.restore)
store.dispatch(RestoreQuoteSuccess(quote)); .then((List<InvoiceEntity> quotes) {
store.dispatch(RestoreQuoteSuccess(quotes));
if (action.completer != null) { if (action.completer != null) {
action.completer.complete(null); action.completer.complete(null);
} }
}).catchError((Object error) { }).catchError((Object error) {
print(error); print(error);
store.dispatch(RestoreQuoteFailure(origQuote)); final quotes =
action.quoteIds.map((id) => store.state.quoteState.map[id]).toList();
store.dispatch(RestoreQuoteFailure(quotes));
if (action.completer != null) { if (action.completer != null) {
action.completer.completeError(error); action.completer.completeError(error);
} }

View File

@ -27,10 +27,10 @@ InvoiceItemEntity editQuoteItem(InvoiceItemEntity quoteItem, dynamic action) {
} }
Reducer<String> dropdownFilterReducer = combineReducers([ Reducer<String> dropdownFilterReducer = combineReducers([
TypedReducer<String, FilterQuoteDropdown>(filterClientDropdownReducer), TypedReducer<String, FilterQuoteDropdown>(filterquoteDropdownReducer),
]); ]);
String filterClientDropdownReducer( String filterquoteDropdownReducer(
String dropdownFilter, FilterQuoteDropdown action) { String dropdownFilter, FilterQuoteDropdown action) {
return action.filter; return action.filter;
} }
@ -62,7 +62,7 @@ final editingReducer = combineReducers<InvoiceEntity>([
TypedReducer<InvoiceEntity, DiscardChanges>(_clearEditing), TypedReducer<InvoiceEntity, DiscardChanges>(_clearEditing),
]); ]);
InvoiceEntity _clearEditing(InvoiceEntity client, dynamic action) { InvoiceEntity _clearEditing(InvoiceEntity quote, dynamic action) {
return InvoiceEntity(); return InvoiceEntity();
} }
@ -213,65 +213,103 @@ QuoteState _markSentQuoteSuccess(
QuoteState _archiveQuoteRequest( QuoteState _archiveQuoteRequest(
QuoteState quoteState, ArchiveQuoteRequest action) { QuoteState quoteState, ArchiveQuoteRequest action) {
final quote = quoteState.map[action.quoteId] final quotes = action.quoteIds.map((id) => quoteState.map[id]).toList();
.rebuild((b) => b..archivedAt = DateTime.now().millisecondsSinceEpoch);
return quoteState.rebuild((b) => b..map[action.quoteId] = quote); for (int i = 0; i < quotes.length; i++) {
quotes[i] = quotes[i]
.rebuild((b) => b..archivedAt = DateTime.now().millisecondsSinceEpoch);
}
return quoteState.rebuild((b) {
for (final quote in quotes) {
b.map[quote.id] = quote;
}
});
} }
QuoteState _archiveQuoteSuccess( QuoteState _archiveQuoteSuccess(
QuoteState quoteState, ArchiveQuoteSuccess action) { QuoteState quoteState, ArchiveQuoteSuccess action) {
return quoteState.rebuild((b) => b..map[action.quote.id] = action.quote); return quoteState.rebuild((b) {
for (final quote in action.quotes) {
b.map[quote.id] = quote;
}
});
} }
QuoteState _archiveQuoteFailure( QuoteState _archiveQuoteFailure(
QuoteState quoteState, ArchiveQuoteFailure action) { QuoteState quoteState, ArchiveQuoteFailure action) {
return quoteState.rebuild((b) => b..map[action.quote.id] = action.quote); return quoteState.rebuild((b) {
for (final quote in action.quotes) {
b.map[quote.id] = quote;
}
});
} }
QuoteState _deleteQuoteRequest( QuoteState _deleteQuoteRequest(
QuoteState quoteState, DeleteQuoteRequest action) { QuoteState quoteState, DeleteQuoteRequest action) {
if (!quoteState.map.containsKey(action.quoteId)) { final quotes = action.quoteIds.map((id) => quoteState.map[id]).toList();
return quoteState;
for (int i = 0; i < quotes.length; i++) {
quotes[i] = quotes[i].rebuild((b) => b
..archivedAt = DateTime.now().millisecondsSinceEpoch
..isDeleted = true);
} }
return quoteState.rebuild((b) {
final quote = quoteState.map[action.quoteId].rebuild((b) => b for (final quote in quotes) {
..archivedAt = DateTime.now().millisecondsSinceEpoch b.map[quote.id] = quote;
..isDeleted = true); }
});
return quoteState.rebuild((b) => b..map[action.quoteId] = quote);
} }
QuoteState _deleteQuoteSuccess( QuoteState _deleteQuoteSuccess(
QuoteState quoteState, DeleteQuoteSuccess action) { QuoteState quoteState, DeleteQuoteSuccess action) {
if (!quoteState.map.containsKey(action.quote.id)) { return quoteState.rebuild((b) {
return quoteState; for (final quote in action.quotes) {
} b.map[quote.id] = quote;
}
return quoteState.rebuild((b) => b..map[action.quote.id] = action.quote); });
} }
QuoteState _deleteQuoteFailure( QuoteState _deleteQuoteFailure(
QuoteState quoteState, DeleteQuoteFailure action) { QuoteState quoteState, DeleteQuoteFailure action) {
return quoteState.rebuild((b) => b..map[action.quote.id] = action.quote); return quoteState.rebuild((b) {
for (final quote in action.quotes) {
b.map[quote.id] = quote;
}
});
} }
QuoteState _restoreQuoteRequest( QuoteState _restoreQuoteRequest(
QuoteState quoteState, RestoreQuoteRequest action) { QuoteState quoteState, RestoreQuoteRequest action) {
final quote = quoteState.map[action.quoteId].rebuild((b) => b final quotes = action.quoteIds.map((id) => quoteState.map[id]).toList();
..archivedAt = null
..isDeleted = false); for (int i = 0; i < quotes.length; i++) {
return quoteState.rebuild((b) => b..map[action.quoteId] = quote); quotes[i] = quotes[i].rebuild((b) => b
..archivedAt = null
..isDeleted = false);
}
return quoteState.rebuild((b) {
for (final quote in quotes) {
b.map[quote.id] = quote;
}
});
} }
QuoteState _restoreQuoteSuccess( QuoteState _restoreQuoteSuccess(
QuoteState quoteState, RestoreQuoteSuccess action) { QuoteState quoteState, RestoreQuoteSuccess action) {
return quoteState.rebuild((b) => b..map[action.quote.id] = action.quote); return quoteState.rebuild((b) {
for (final quote in action.quotes) {
b.map[quote.id] = quote;
}
});
} }
QuoteState _restoreQuoteFailure( QuoteState _restoreQuoteFailure(
QuoteState quoteState, RestoreQuoteFailure action) { QuoteState quoteState, RestoreQuoteFailure action) {
return quoteState.rebuild((b) => b..map[action.quote.id] = action.quote); return quoteState.rebuild((b) {
for (final quote in action.quotes) {
b.map[quote.id] = quote;
}
});
} }
QuoteState _convertQuoteSuccess( QuoteState _convertQuoteSuccess(

View File

@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/redux/document/document_selectors.dart';
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart'; import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
import 'package:invoiceninja_flutter/ui/app/help_text.dart'; import 'package:invoiceninja_flutter/ui/app/help_text.dart';
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart'; import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
import 'package:invoiceninja_flutter/ui/app/lists/list_filter.dart';
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart'; import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
import 'package:invoiceninja_flutter/ui/invoice/invoice_list_item.dart'; import 'package:invoiceninja_flutter/ui/invoice/invoice_list_item.dart';
import 'package:invoiceninja_flutter/ui/invoice/invoice_list_vm.dart'; import 'package:invoiceninja_flutter/ui/invoice/invoice_list_vm.dart';
@ -33,36 +34,13 @@ class InvoiceList extends StatelessWidget {
return Column( return Column(
children: <Widget>[ children: <Widget>[
filteredClient != null if (filteredClient != null)
? Material( ListFilterMessage(
color: Colors.orangeAccent, title:
elevation: 6.0, '${localization.filteredByGroup}: ${filteredClient.listDisplayName}',
child: InkWell( onPressed: viewModel.onViewEntityFilterPressed,
onTap: () => viewModel.onViewEntityFilterPressed(context), onClearPressed: viewModel.onClearEntityFilterPressed,
child: Row( ),
children: <Widget>[
SizedBox(width: 18.0),
Expanded(
child: Text(
'${localization.filteredByClient}: ${filteredClient.listDisplayName}',
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
),
),
),
IconButton(
icon: Icon(
Icons.close,
color: Colors.white,
),
onPressed: () => viewModel.onClearEntityFilterPressed(),
)
],
),
),
)
: Container(),
Expanded( Expanded(
child: !viewModel.isLoaded child: !viewModel.isLoaded
? (viewModel.isLoading ? LoadingIndicator() : SizedBox()) ? (viewModel.isLoading ? LoadingIndicator() : SizedBox())

View File

@ -7,6 +7,7 @@ import 'package:invoiceninja_flutter/redux/payment/payment_selectors.dart';
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart'; import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
import 'package:invoiceninja_flutter/ui/app/help_text.dart'; import 'package:invoiceninja_flutter/ui/app/help_text.dart';
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart'; import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
import 'package:invoiceninja_flutter/ui/app/lists/list_filter.dart';
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart'; import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
import 'package:invoiceninja_flutter/ui/payment/payment_list_item.dart'; import 'package:invoiceninja_flutter/ui/payment/payment_list_item.dart';
import 'package:invoiceninja_flutter/ui/payment/payment_list_vm.dart'; import 'package:invoiceninja_flutter/ui/payment/payment_list_vm.dart';
@ -49,36 +50,13 @@ class PaymentList extends StatelessWidget {
return Column( return Column(
children: <Widget>[ children: <Widget>[
filteredEntity != null if (filteredEntity != null)
? Material( ListFilterMessage(
color: Colors.orangeAccent, title:
elevation: 6.0, '${localization.filteredByGroup}: ${filteredEntity.listDisplayName}',
child: InkWell( onPressed: viewModel.onViewEntityFilterPressed,
onTap: () => viewModel.onViewClientFilterPressed(context), onClearPressed: viewModel.onClearEntityFilterPressed,
child: Row( ),
children: <Widget>[
SizedBox(width: 18.0),
Expanded(
child: Text(
'$label: ${filteredEntity.listDisplayName}',
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
),
),
),
IconButton(
icon: Icon(
Icons.close,
color: Colors.white,
),
onPressed: () => viewModel.onClearEntityFilterPressed(),
)
],
),
),
)
: Container(),
Expanded( Expanded(
child: !viewModel.isLoaded child: !viewModel.isLoaded
? (viewModel.isLoading ? LoadingIndicator() : SizedBox()) ? (viewModel.isLoading ? LoadingIndicator() : SizedBox())

View File

@ -46,7 +46,7 @@ class PaymentListVM {
@required this.onRefreshed, @required this.onRefreshed,
@required this.onEntityAction, @required this.onEntityAction,
@required this.onClearEntityFilterPressed, @required this.onClearEntityFilterPressed,
@required this.onViewClientFilterPressed, @required this.onViewEntityFilterPressed,
@required this.listState, @required this.listState,
}); });
@ -85,7 +85,7 @@ class PaymentListVM {
handlePaymentAction(context, payments, action), handlePaymentAction(context, payments, action),
onClearEntityFilterPressed: () => onClearEntityFilterPressed: () =>
store.dispatch(FilterPaymentsByEntity()), store.dispatch(FilterPaymentsByEntity()),
onViewClientFilterPressed: (BuildContext context) { onViewEntityFilterPressed: (BuildContext context) {
switch (state.paymentListState.filterEntityType) { switch (state.paymentListState.filterEntityType) {
case EntityType.client: case EntityType.client:
store.dispatch(ViewClient( store.dispatch(ViewClient(
@ -114,7 +114,7 @@ class PaymentListVM {
final Function(BuildContext, PaymentEntity) onPaymentTap; final Function(BuildContext, PaymentEntity) onPaymentTap;
final Function(BuildContext) onRefreshed; final Function(BuildContext) onRefreshed;
final Function onClearEntityFilterPressed; final Function onClearEntityFilterPressed;
final Function(BuildContext) onViewClientFilterPressed; final Function(BuildContext) onViewEntityFilterPressed;
final Function(BuildContext, List<PaymentEntity>, EntityAction) final Function(BuildContext, List<PaymentEntity>, EntityAction)
onEntityAction; onEntityAction;
} }

View File

@ -6,6 +6,7 @@ import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart'; import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
import 'package:invoiceninja_flutter/ui/app/help_text.dart'; import 'package:invoiceninja_flutter/ui/app/help_text.dart';
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart'; import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
import 'package:invoiceninja_flutter/ui/app/lists/list_filter.dart';
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart'; import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
import 'package:invoiceninja_flutter/ui/project/project_list_item.dart'; import 'package:invoiceninja_flutter/ui/project/project_list_item.dart';
import 'package:invoiceninja_flutter/ui/project/project_list_vm.dart'; import 'package:invoiceninja_flutter/ui/project/project_list_vm.dart';
@ -31,36 +32,13 @@ class ProjectList extends StatelessWidget {
return Column( return Column(
children: <Widget>[ children: <Widget>[
filteredClient != null if (filteredClient != null)
? Material( ListFilterMessage(
color: Colors.orangeAccent, title:
elevation: 6.0, '${localization.filteredByGroup}: ${filteredClient.listDisplayName}',
child: InkWell( onPressed: viewModel.onViewEntityFilterPressed,
onTap: () => viewModel.onViewEntityFilterPressed(context), onClearPressed: viewModel.onClearEntityFilterPressed,
child: Row( ),
children: <Widget>[
SizedBox(width: 18.0),
Expanded(
child: Text(
'${localization.filteredByClient}: ${filteredClient.listDisplayName}',
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
),
),
),
IconButton(
icon: Icon(
Icons.close,
color: Colors.white,
),
onPressed: () => viewModel.onClearEntityFilterPressed(),
)
],
),
),
)
: Container(),
Expanded( Expanded(
child: !viewModel.isLoaded child: !viewModel.isLoaded
? (viewModel.isLoading ? LoadingIndicator() : SizedBox()) ? (viewModel.isLoading ? LoadingIndicator() : SizedBox())

View File

@ -4,6 +4,7 @@ import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart'; import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
import 'package:invoiceninja_flutter/ui/app/help_text.dart'; import 'package:invoiceninja_flutter/ui/app/help_text.dart';
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart'; import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
import 'package:invoiceninja_flutter/ui/app/lists/list_filter.dart';
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart'; import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
import 'package:invoiceninja_flutter/ui/task/task_list_item.dart'; import 'package:invoiceninja_flutter/ui/task/task_list_item.dart';
import 'package:invoiceninja_flutter/ui/task/task_list_vm.dart'; import 'package:invoiceninja_flutter/ui/task/task_list_vm.dart';
@ -44,36 +45,13 @@ class TaskList extends StatelessWidget {
return Column( return Column(
children: <Widget>[ children: <Widget>[
filteredEntity != null if (filteredEntity != null)
? Material( ListFilterMessage(
color: Colors.orangeAccent, title:
elevation: 6.0, '${localization.filteredByGroup}: ${filteredEntity.listDisplayName}',
child: InkWell( onPressed: viewModel.onViewEntityFilterPressed,
onTap: () => viewModel.onViewEntityFilterPressed(context), onClearPressed: viewModel.onClearEntityFilterPressed,
child: Row( ),
children: <Widget>[
SizedBox(width: 18.0),
Expanded(
child: Text(
'$label: ${filteredEntity.listDisplayName}',
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
),
),
),
IconButton(
icon: Icon(
Icons.close,
color: Colors.white,
),
onPressed: () => viewModel.onClearEntityFilterPressed(),
)
],
),
),
)
: Container(),
Expanded( Expanded(
child: !viewModel.isLoaded child: !viewModel.isLoaded
? (viewModel.isLoading ? LoadingIndicator() : SizedBox()) ? (viewModel.isLoading ? LoadingIndicator() : SizedBox())