Merge branch 'develop' of github.com:invoiceninja/flutter-mobile into develop

This commit is contained in:
Hillel Coren 2020-06-30 17:09:12 +03:00
commit 086b750b21
29 changed files with 471 additions and 150 deletions

View File

@ -9,6 +9,7 @@ import 'package:invoiceninja_flutter/data/models/gateway_token_model.dart';
import 'package:invoiceninja_flutter/data/models/group_model.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/static/static_state.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart';
part 'client_model.g.dart';
@ -323,7 +324,12 @@ abstract class ClientEntity extends Object
bool get hasEmailAddress =>
contacts.where((contact) => contact.email?.isNotEmpty).isNotEmpty;
int compareTo(ClientEntity client, String sortField, bool sortAscending) {
int compareTo(
ClientEntity client,
String sortField,
bool sortAscending,
BuiltMap<String, UserEntity> userMap,
StaticState staticState) {
int response = 0;
final ClientEntity clientA = sortAscending ? this : client;
final ClientEntity clientB = sortAscending ? client : this;
@ -356,9 +362,91 @@ abstract class ClientEntity extends Object
case ClientFields.idNumber:
response = clientA.idNumber.compareTo(clientB.idNumber);
break;
case ClientFields.website:
response = clientA.website
.toLowerCase()
.compareTo(clientB.website.toLowerCase());
break;
case ClientFields.address1:
response = clientA.address1
.toLowerCase()
.compareTo(clientB.address1.toLowerCase());
break;
case ClientFields.address2:
response = clientA.address2
.toLowerCase()
.compareTo(clientB.address2.toLowerCase());
break;
case ClientFields.phone:
response = clientA.phone
.toLowerCase()
.compareTo(clientB.phone.toLowerCase());
break;
case ClientFields.publicNotes:
response = clientA.publicNotes
.toLowerCase()
.compareTo(clientB.publicNotes.toLowerCase());
break;
case ClientFields.privateNotes:
response = clientA.privateNotes
.toLowerCase()
.compareTo(clientB.privateNotes.toLowerCase());
break;
case ClientFields.vatNumber:
response = clientA.vatNumber
.toLowerCase()
.compareTo(clientB.vatNumber.toLowerCase());
break;
case ClientFields.assignedToId:
case EntityFields.assignedTo:
final userA = userMap[clientA.assignedUserId] ?? UserEntity();
final userB = userMap[clientB.assignedUserId] ?? UserEntity();
response = userA.listDisplayName
.toLowerCase()
.compareTo(userB.listDisplayName.toLowerCase());
break;
case ClientFields.createdById:
case EntityFields.createdBy:
final userA = userMap[clientA.createdUserId] ?? UserEntity();
final userB = userMap[clientB.createdUserId] ?? UserEntity();
response = userA.listDisplayName
.toLowerCase()
.compareTo(userB.listDisplayName.toLowerCase());
break;
case ClientFields.country:
final countryA = staticState.countryMap[clientA.countryId] ?? CountryEntity();
final countryB = staticState.countryMap[clientB.countryId] ?? CountryEntity();
response = countryA.name.toLowerCase()
.compareTo(countryB.name.toLowerCase());
break;
case ClientFields.currency:
final currencyA = staticState.currencyMap[clientA.currencyId] ?? CurrencyEntity();
final currencyB = staticState.currencyMap[clientB.currencyId] ?? CurrencyEntity();
response = currencyA.name.toLowerCase()
.compareTo(currencyB.name.toLowerCase());
break;
case EntityFields.state:
case ClientFields.state:
final stateA = EntityState.valueOf(clientA.entityState) ?? EntityState.active;
final stateB = EntityState.valueOf(clientB.entityState) ?? EntityState.active;
response = stateA.name.toLowerCase()
.compareTo(stateB.name.toLowerCase());
break;
case ClientFields.language:
final languageA = staticState.languageMap[clientA.languageId] ?? LanguageEntity();
final languageB = staticState.languageMap[clientB.languageId] ?? LanguageEntity();
response = languageA.name.toLowerCase()
.compareTo(languageB.name.toLowerCase());
break;
case ClientFields.createdAt:
response = clientA.createdAt.compareTo(clientB.createdAt);
break;
case ClientFields.archivedAt:
response = clientA.archivedAt.compareTo(clientB.archivedAt);
break;
case ClientFields.lastLoginAt:
response = clientA.lastLogin.compareTo(clientB.lastLogin);
break;
case ClientFields.custom1:
response = clientA.customValue1
.toLowerCase()

View File

@ -8,6 +8,7 @@ import 'package:invoiceninja_flutter/data/models/mixins/invoice_mixin.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/data/models/quote_model.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/static/static_state.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart';
part 'invoice_model.g.dart';
@ -376,7 +377,9 @@ abstract class InvoiceEntity extends Object
{InvoiceEntity invoice,
String sortField,
bool sortAscending,
BuiltMap<String, ClientEntity> clientMap}) {
BuiltMap<String, ClientEntity> clientMap,
StaticState staticState,
BuiltMap<String, UserEntity> userMap}) {
int response = 0;
final InvoiceEntity invoiceA = sortAscending ? this : invoice;
final InvoiceEntity invoiceB = sortAscending ? invoice : this;
@ -394,9 +397,15 @@ abstract class InvoiceEntity extends Object
case CreditFields.amount:
response = invoiceA.amount.compareTo(invoiceB.amount);
break;
case EntityFields.createdAt:
response = invoiceA.createdAt.compareTo(invoiceB.createdAt);
break;
case EntityFields.updatedAt:
response = invoiceA.updatedAt.compareTo(invoiceB.updatedAt);
break;
case EntityFields.archivedAt:
response = invoiceA.archivedAt.compareTo(invoiceB.archivedAt);
break;
case InvoiceFields.invoiceDate:
case QuoteFields.date:
case CreditFields.date:
@ -405,13 +414,58 @@ abstract class InvoiceEntity extends Object
case InvoiceFields.balance:
response = invoiceA.balance.compareTo(invoiceB.balance);
break;
case InvoiceFields.discount:
response = invoiceA.discount.compareTo(invoiceB.discount);
break;
case InvoiceFields.documents:
response = invoiceA.documents.length.compareTo(invoiceB.documents.length);
break;
case InvoiceFields.poNumber:
response = invoiceA.poNumber.compareTo(invoiceB.poNumber);
break;
case InvoiceFields.statusId:
response = invoiceA.statusId.compareTo(invoiceB.statusId);
break;
case InvoiceFields.status:
response = (staticState.invoiceStatusMap[invoiceA.statusId]?.name ?? '')
.toLowerCase()
.compareTo(
staticState.invoiceStatusMap[invoiceB.statusId]?.name ?? '');
break;
case EntityFields.state:
final stateA = EntityState.valueOf(invoiceA.entityState) ?? EntityState.active;
final stateB = EntityState.valueOf(invoiceB.entityState) ?? EntityState.active;
response = stateA.name.toLowerCase()
.compareTo(stateB.name.toLowerCase());
break;
case InvoiceFields.dueDate:
case QuoteFields.validUntil:
response = invoiceA.dueDate.compareTo(invoiceB.dueDate);
break;
case EntityFields.assignedTo:
final userA = userMap[invoiceA.assignedUserId] ?? UserEntity();
final userB = userMap[invoiceB.assignedUserId] ?? UserEntity();
response = userA.listDisplayName
.toLowerCase()
.compareTo(userB.listDisplayName.toLowerCase());
break;
case EntityFields.createdBy:
final userA = userMap[invoiceA.createdUserId] ?? UserEntity();
final userB = userMap[invoiceB.createdUserId] ?? UserEntity();
response = userA.listDisplayName
.toLowerCase()
.compareTo(userB.listDisplayName.toLowerCase());
break;
case InvoiceFields.publicNotes:
response = invoiceA.publicNotes
.toLowerCase()
.compareTo(invoiceB.publicNotes.toLowerCase());
break;
case InvoiceFields.privateNotes:
response = invoiceA.privateNotes
.toLowerCase()
.compareTo(invoiceB.privateNotes.toLowerCase());
break;
case InvoiceFields.customValue1:
response = invoiceA.customValue1
.toLowerCase()

View File

@ -57,7 +57,6 @@ class PaymentFields {
static const String privateNotes = 'private_notes';
static const String exchangeRate = 'exchange_rate';
static const String exchangeCurrencyId = 'exchange_currency_id';
static const String paymentStatusId = 'payment_status_id';
static const String paymentStatus = 'payment_status';
static const String customValue1 = 'custom1';
static const String customValue2 = 'custom2';
@ -190,7 +189,8 @@ abstract class PaymentEntity extends Object
String sortField,
bool sortAscending,
BuiltMap<String, InvoiceEntity> invoiceMap,
BuiltMap<String, ClientEntity> clientMap}) {
BuiltMap<String, ClientEntity> clientMap,
BuiltMap<String, UserEntity> userMap}) {
int response = 0;
final PaymentEntity paymentA = sortAscending ? this : payment;
final PaymentEntity paymentB = sortAscending ? payment : this;
@ -199,6 +199,12 @@ abstract class PaymentEntity extends Object
case PaymentFields.amount:
response = paymentA.amount.compareTo(paymentB.amount);
break;
case PaymentFields.exchangeRate:
response = paymentA.exchangeRate.compareTo(paymentB.exchangeRate);
break;
case PaymentFields.refunded:
response = paymentA.refunded.compareTo(paymentB.refunded);
break;
case PaymentFields.paymentNumber:
response = paymentA.number
.toLowerCase()
@ -211,9 +217,20 @@ abstract class PaymentEntity extends Object
case PaymentFields.paymentDate:
response = paymentA.date.compareTo(paymentB.date);
break;
case PaymentFields.privateNotes:
response = paymentA.privateNotes
.toLowerCase()
.compareTo(paymentB.date.toLowerCase());
break;
case EntityFields.updatedAt:
response = paymentA.updatedAt.compareTo(paymentB.updatedAt);
break;
case EntityFields.createdAt:
response = paymentA.createdAt.compareTo(paymentB.createdAt);
break;
case EntityFields.archivedAt:
response = paymentA.archivedAt.compareTo(paymentB.archivedAt);
break;
case PaymentFields.paymentStatus:
response = paymentA.statusId.compareTo(paymentB.statusId);
break;
@ -251,6 +268,26 @@ abstract class PaymentEntity extends Object
.toLowerCase()
.compareTo(clientB.displayName.toLowerCase());
break;
case EntityFields.assignedTo:
final userA = userMap[paymentA.assignedUserId] ?? UserEntity();
final userB = userMap[paymentB.assignedUserId] ?? UserEntity();
response = userA.listDisplayName
.toLowerCase()
.compareTo(userB.listDisplayName.toLowerCase());
break;
case EntityFields.createdBy:
final userA = userMap[paymentA.createdUserId] ?? UserEntity();
final userB = userMap[paymentB.createdUserId] ?? UserEntity();
response = userA.listDisplayName
.toLowerCase()
.compareTo(userB.listDisplayName.toLowerCase());
break;
case EntityFields.state:
final stateA = EntityState.valueOf(paymentA.entityState) ?? EntityState.active;
final stateB = EntityState.valueOf(paymentB.entityState) ?? EntityState.active;
response = stateA.name.toLowerCase()
.compareTo(stateB.name.toLowerCase());
break;
default:
print('## ERROR: sort by payment.$sortField is not implemented');
break;

View File

@ -168,8 +168,12 @@ abstract class ProductEntity extends Object
@override
FormatNumberType get listDisplayAmountType => FormatNumberType.money;
int compareTo(ProductEntity product,
[String sortField, bool sortAscending = true]) {
int compareTo(
ProductEntity product, [
String sortField,
bool sortAscending = true,
BuiltMap<String, UserEntity> userMap,
]) {
int response = 0;
final ProductEntity productA = sortAscending ? this : product;
final ProductEntity productB = sortAscending ? product : this;
@ -192,11 +196,37 @@ abstract class ProductEntity extends Object
case ProductFields.updatedAt:
response = productA.updatedAt.compareTo(productB.updatedAt);
break;
case EntityFields.createdAt:
response = productA.createdAt.compareTo(productB.createdAt);
break;
case ProductFields.archivedAt:
response = productA.archivedAt.compareTo(productB.archivedAt);
break;
case ProductFields.notes:
response = productA.notes
.toLowerCase()
.compareTo(productB.notes.toLowerCase());
break;
case EntityFields.assignedTo:
final userA = userMap[productA.assignedUserId] ?? UserEntity();
final userB = userMap[productB.assignedUserId] ?? UserEntity();
response = userA.listDisplayName
.toLowerCase()
.compareTo(userB.listDisplayName.toLowerCase());
break;
case EntityFields.createdBy:
final userA = userMap[productA.createdUserId] ?? UserEntity();
final userB = userMap[productB.createdUserId] ?? UserEntity();
response = userA.listDisplayName
.toLowerCase()
.compareTo(userB.listDisplayName.toLowerCase());
break;
case EntityFields.state:
final stateA = EntityState.valueOf(productA.entityState) ?? EntityState.active;
final stateB = EntityState.valueOf(productB.entityState) ?? EntityState.active;
response = stateA.name.toLowerCase()
.compareTo(stateB.name.toLowerCase());
break;
case ProductFields.customValue1:
response = productA.customValue1
.toLowerCase()

View File

@ -1,39 +1,50 @@
import 'package:invoiceninja_flutter/data/models/group_model.dart';
import 'package:invoiceninja_flutter/redux/static/static_state.dart';
import 'package:memoize/memoize.dart';
import 'package:built_collection/built_collection.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
var memoizedDropdownClientList = memo2(
(BuiltMap<String, ClientEntity> clientMap, BuiltList<String> clientList) =>
dropdownClientsSelector(clientMap, clientList));
var memoizedDropdownClientList = memo4(
(BuiltMap<String, ClientEntity> clientMap, BuiltList<String> clientList,
BuiltMap<String, UserEntity> userMap, StaticState staticState) =>
dropdownClientsSelector(clientMap, clientList, userMap, staticState));
List<String> dropdownClientsSelector(
BuiltMap<String, ClientEntity> clientMap, BuiltList<String> clientList) {
BuiltMap<String, ClientEntity> clientMap,
BuiltList<String> clientList,
BuiltMap<String, UserEntity> userMap,
StaticState staticState) {
final list =
clientList.where((clientId) => clientMap[clientId].isActive).toList();
list.sort((clientAId, clientBId) {
final clientA = clientMap[clientAId];
final clientB = clientMap[clientBId];
return clientA.compareTo(clientB, ClientFields.name, true);
return clientA.compareTo(
clientB, ClientFields.name, true, userMap, staticState);
});
return list;
}
var memoizedFilteredClientList = memo4((BuiltMap<String, ClientEntity>
clientMap,
var memoizedFilteredClientList = memo6(
(BuiltMap<String, ClientEntity> clientMap,
BuiltList<String> clientList,
BuiltMap<String, GroupEntity> groupMap,
ListUIState clientListState) =>
filteredClientsSelector(clientMap, clientList, groupMap, clientListState));
ListUIState clientListState,
BuiltMap<String, UserEntity> userMap,
StaticState staticState) =>
filteredClientsSelector(clientMap, clientList, groupMap,
clientListState, userMap, staticState));
List<String> filteredClientsSelector(
BuiltMap<String, ClientEntity> clientMap,
BuiltList<String> clientList,
BuiltMap<String, GroupEntity> groupMap,
ListUIState clientListState) {
ListUIState clientListState,
BuiltMap<String, UserEntity> userMap,
StaticState staticState) {
final list = clientList.where((clientId) {
final client = clientMap[clientId];
final group = groupMap[client.groupId] ?? GroupEntity(id: client.groupId);
@ -78,8 +89,8 @@ List<String> filteredClientsSelector(
list.sort((clientAId, clientBId) {
final clientA = clientMap[clientAId];
final clientB = clientMap[clientBId];
return clientA.compareTo(
clientB, clientListState.sortField, clientListState.sortAscending);
return clientA.compareTo(clientB, clientListState.sortField,
clientListState.sortAscending, userMap, staticState);
});
return list;

View File

@ -1,20 +1,26 @@
import 'package:invoiceninja_flutter/redux/static/static_state.dart';
import 'package:memoize/memoize.dart';
import 'package:built_collection/built_collection.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
var memoizedDropdownCreditList = memo4(
var memoizedDropdownCreditList = memo6(
(BuiltMap<String, InvoiceEntity> creditMap,
BuiltMap<String, ClientEntity> clientMap,
BuiltList<String> creditList,
String clientId) =>
dropdownCreditSelector(creditMap, clientMap, creditList, clientId));
String clientId,
StaticState staticState,
BuiltMap<String, UserEntity> userMap) =>
dropdownCreditSelector(
creditMap, clientMap, creditList, clientId, staticState, userMap));
List<String> dropdownCreditSelector(
BuiltMap<String, InvoiceEntity> creditMap,
BuiltMap<String, ClientEntity> clientMap,
BuiltList<String> creditList,
String clientId) {
String clientId,
StaticState staticState,
BuiltMap<String, UserEntity> userMap) {
final list = creditList.where((creditId) {
final credit = creditMap[creditId];
if (clientId != null &&
@ -37,7 +43,8 @@ List<String> dropdownCreditSelector(
clientMap: clientMap,
sortAscending: true,
sortField: ClientFields.name,
);
staticState: staticState,
userMap: userMap);
});
return list;
@ -48,18 +55,23 @@ ClientEntity creditClientSelector(
return clientMap[credit.clientId];
}
var memoizedFilteredCreditList = memo4((BuiltMap<String, InvoiceEntity>
creditMap,
var memoizedFilteredCreditList = memo6(
(BuiltMap<String, InvoiceEntity> creditMap,
BuiltList<String> creditList,
BuiltMap<String, ClientEntity> clientMap,
ListUIState creditListState) =>
filteredCreditsSelector(creditMap, creditList, clientMap, creditListState));
ListUIState creditListState,
StaticState staticState,
BuiltMap<String, UserEntity> userMap) =>
filteredCreditsSelector(creditMap, creditList, clientMap,
creditListState, staticState, userMap));
List<String> filteredCreditsSelector(
BuiltMap<String, InvoiceEntity> creditMap,
BuiltList<String> creditList,
BuiltMap<String, ClientEntity> clientMap,
ListUIState creditListState) {
ListUIState creditListState,
StaticState staticState,
BuiltMap<String, UserEntity> userMap) {
final list = creditList.where((creditId) {
final credit = creditMap[creditId];
final client =
@ -106,7 +118,8 @@ List<String> filteredCreditsSelector(
sortField: creditListState.sortField,
sortAscending: creditListState.sortAscending,
clientMap: clientMap,
);
staticState: staticState,
userMap: userMap);
});
return list;

View File

@ -1,20 +1,26 @@
import 'package:invoiceninja_flutter/redux/static/static_state.dart';
import 'package:memoize/memoize.dart';
import 'package:built_collection/built_collection.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
var memoizedDropdownInvoiceList = memo4(
var memoizedDropdownInvoiceList = memo6(
(BuiltMap<String, InvoiceEntity> invoiceMap,
BuiltMap<String, ClientEntity> clientMap,
BuiltList<String> invoiceList,
String clientId) =>
dropdownInvoiceSelector(invoiceMap, clientMap, invoiceList, clientId));
String clientId,
StaticState staticState,
BuiltMap<String, UserEntity> userMap) =>
dropdownInvoiceSelector(invoiceMap, clientMap, invoiceList, clientId,
staticState, userMap));
List<String> dropdownInvoiceSelector(
BuiltMap<String, InvoiceEntity> invoiceMap,
BuiltMap<String, ClientEntity> clientMap,
BuiltList<String> invoiceList,
String clientId) {
String clientId,
StaticState staticState,
BuiltMap<String, UserEntity> userMap) {
final list = invoiceList.where((invoiceId) {
final invoice = invoiceMap[invoiceId];
if (clientId != null &&
@ -39,21 +45,23 @@ List<String> dropdownInvoiceSelector(
clientMap: clientMap,
sortAscending: false,
sortField: InvoiceFields.invoiceNumber,
);
staticState: staticState,
userMap: userMap);
});
return list;
}
var memoizedFilteredInvoiceList = memo5((
BuiltMap<String, InvoiceEntity> invoiceMap,
var memoizedFilteredInvoiceList = memo7(
(BuiltMap<String, InvoiceEntity> invoiceMap,
BuiltList<String> invoiceList,
BuiltMap<String, ClientEntity> clientMap,
BuiltMap<String, PaymentEntity> paymentMap,
ListUIState invoiceListState,
) =>
filteredInvoicesSelector(
invoiceMap, invoiceList, clientMap, paymentMap, invoiceListState));
StaticState staticState,
BuiltMap<String, UserEntity> userMap) =>
filteredInvoicesSelector(invoiceMap, invoiceList, clientMap, paymentMap,
invoiceListState, staticState, userMap));
List<String> filteredInvoicesSelector(
BuiltMap<String, InvoiceEntity> invoiceMap,
@ -61,7 +69,8 @@ List<String> filteredInvoicesSelector(
BuiltMap<String, ClientEntity> clientMap,
BuiltMap<String, PaymentEntity> paymentMap,
ListUIState invoiceListState,
) {
StaticState staticState,
BuiltMap<String, UserEntity> userMap) {
final Map<String, List<String>> invoicePaymentMap = {};
if (invoiceListState.filterEntityType == EntityType.payment) {
@ -132,7 +141,8 @@ List<String> filteredInvoicesSelector(
sortField: invoiceListState.sortField,
sortAscending: invoiceListState.sortAscending,
clientMap: clientMap,
);
staticState: staticState,
userMap: userMap);
});
return list;

View File

@ -18,18 +18,22 @@ List<PaymentEntity> paymentsByInvoiceSelector(String invoiceId,
.toList();
}
var memoizedDropdownPaymentList = memo4((BuiltMap<String, PaymentEntity>
paymentMap,
var memoizedDropdownPaymentList = memo5((
BuiltMap<String, PaymentEntity> paymentMap,
BuiltList<String> paymentList,
BuiltMap<String, InvoiceEntity> invoiceMap,
BuiltMap<String, ClientEntity> clientMap) =>
dropdownPaymentsSelector(paymentMap, paymentList, invoiceMap, clientMap));
BuiltMap<String, ClientEntity> clientMap,
BuiltMap<String, UserEntity> userMap,
) =>
dropdownPaymentsSelector(
paymentMap, paymentList, invoiceMap, clientMap, userMap));
List<String> dropdownPaymentsSelector(
BuiltMap<String, PaymentEntity> paymentMap,
BuiltList<String> paymentList,
BuiltMap<String, InvoiceEntity> invoiceMap,
BuiltMap<String, ClientEntity> clientMap,
BuiltMap<String, UserEntity> userMap,
) {
final list =
paymentList.where((paymentId) => paymentMap[paymentId].isActive).toList();
@ -44,26 +48,28 @@ List<String> dropdownPaymentsSelector(
sortField: PaymentFields.paymentDate,
invoiceMap: invoiceMap,
clientMap: clientMap,
);
userMap: userMap);
});
return list;
}
var memoizedFilteredPaymentList = memo5(
var memoizedFilteredPaymentList = memo6(
(BuiltMap<String, PaymentEntity> paymentMap,
BuiltList<String> paymentList,
BuiltMap<String, InvoiceEntity> invoiceMap,
BuiltMap<String, ClientEntity> clientMap,
BuiltMap<String, UserEntity> userMap,
ListUIState paymentListState) =>
filteredPaymentsSelector(
paymentMap, paymentList, invoiceMap, clientMap, paymentListState));
filteredPaymentsSelector(paymentMap, paymentList, invoiceMap, clientMap,
userMap, paymentListState));
List<String> filteredPaymentsSelector(
BuiltMap<String, PaymentEntity> paymentMap,
BuiltList<String> paymentList,
BuiltMap<String, InvoiceEntity> invoiceMap,
BuiltMap<String, ClientEntity> clientMap,
BuiltMap<String, UserEntity> userMap,
ListUIState paymentListState) {
final list = paymentList.where((paymentId) {
final payment = paymentMap[paymentId];
@ -106,7 +112,7 @@ List<String> filteredPaymentsSelector(
sortField: paymentListState.sortField,
invoiceMap: invoiceMap,
clientMap: clientMap,
);
userMap: userMap);
});
return list;

View File

@ -29,20 +29,23 @@ InvoiceItemEntity convertProductToInvoiceItem({
}
}
var memoizedDropdownProductList = memo2(
(BuiltMap<String, ProductEntity> productMap,
BuiltList<String> productList) =>
dropdownProductsSelector(productMap, productList));
var memoizedDropdownProductList = memo3(
(BuiltMap<String, ProductEntity> productMap, BuiltList<String> productList,
BuiltMap<String, UserEntity> userMap) =>
dropdownProductsSelector(productMap, productList, userMap));
List<String> dropdownProductsSelector(
BuiltMap<String, ProductEntity> productMap, BuiltList<String> productList) {
BuiltMap<String, ProductEntity> productMap,
BuiltList<String> productList,
BuiltMap<String, UserEntity> userMap) {
final list =
productList.where((productId) => productMap[productId].isActive).toList();
list.sort((productAId, productBId) {
final productA = productMap[productAId];
final productB = productMap[productBId];
return productA.compareTo(productB, ProductFields.productKey, true);
return productA.compareTo(
productB, ProductFields.productKey, true, userMap);
});
return list;
@ -63,15 +66,19 @@ List<String> productList(BuiltMap<String, ProductEntity> productMap) {
return list;
}
var memoizedFilteredProductList = memo3(
(BuiltMap<String, ProductEntity> productMap, BuiltList<String> productList,
ListUIState productListState) =>
filteredProductsSelector(productMap, productList, productListState));
var memoizedFilteredProductList = memo4(
(BuiltMap<String, ProductEntity> productMap,
BuiltList<String> productList,
ListUIState productListState,
BuiltMap<String, UserEntity> userMap) =>
filteredProductsSelector(
productMap, productList, productListState, userMap));
List<String> filteredProductsSelector(
BuiltMap<String, ProductEntity> productMap,
BuiltList<String> productList,
ListUIState productListState) {
ListUIState productListState,
BuiltMap<String, UserEntity> userMap) {
final list = productList.where((productId) {
final product = productMap[productId];
if (!product.matchesStates(productListState.stateFilters)) {
@ -94,8 +101,8 @@ List<String> filteredProductsSelector(
list.sort((productAId, productBId) {
final productA = productMap[productAId];
final productB = productMap[productBId];
return productA.compareTo(
productB, productListState.sortField, productListState.sortAscending);
return productA.compareTo(productB, productListState.sortField,
productListState.sortAscending, userMap);
});
return list;

View File

@ -1,3 +1,4 @@
import 'package:invoiceninja_flutter/redux/static/static_state.dart';
import 'package:memoize/memoize.dart';
import 'package:built_collection/built_collection.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
@ -8,17 +9,22 @@ ClientEntity quoteClientSelector(
return clientMap[quote.clientId];
}
var memoizedFilteredQuoteList = memo4((BuiltMap<String, InvoiceEntity> quoteMap,
var memoizedFilteredQuoteList = memo6((BuiltMap<String, InvoiceEntity> quoteMap,
BuiltList<String> quoteList,
BuiltMap<String, ClientEntity> clientMap,
ListUIState quoteListState) =>
filteredQuotesSelector(quoteMap, quoteList, clientMap, quoteListState));
ListUIState quoteListState,
StaticState staticState,
BuiltMap<String, UserEntity> userMap) =>
filteredQuotesSelector(
quoteMap, quoteList, clientMap, quoteListState, staticState, userMap));
List<String> filteredQuotesSelector(
BuiltMap<String, InvoiceEntity> quoteMap,
BuiltList<String> quoteList,
BuiltMap<String, ClientEntity> clientMap,
ListUIState quoteListState) {
ListUIState quoteListState,
StaticState staticState,
BuiltMap<String, UserEntity> userMap) {
final list = quoteList.where((quoteId) {
final quote = quoteMap[quoteId];
final client =
@ -65,7 +71,8 @@ List<String> filteredQuotesSelector(
sortField: quoteListState.sortField,
sortAscending: quoteListState.sortAscending,
clientMap: clientMap,
);
staticState: staticState,
userMap: userMap);
});
return list;

View File

@ -1,7 +1,9 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/client/client_selectors.dart';
import 'package:invoiceninja_flutter/redux/client/client_state.dart';
import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart';
@ -25,6 +27,8 @@ class ClientPicker extends StatelessWidget {
@override
Widget build(BuildContext context) {
final localization = AppLocalization.of(context);
final store = StoreProvider.of<AppState>(context);
final state = store.state;
return EntityDropdown(
key: ValueKey('__client_${clientId}__'),
@ -32,7 +36,8 @@ class ClientPicker extends StatelessWidget {
labelText: localization.client,
entityId: clientId,
autofocus: autofocus,
entityList: memoizedDropdownClientList(clientState.map, clientState.list),
entityList: memoizedDropdownClientList(clientState.map, clientState.list,
state.userState.map, state.staticState),
entityMap: clientState.map,
validator: (String val) => val.trim().isEmpty
? AppLocalization.of(context).pleaseSelectAClient

View File

@ -128,8 +128,13 @@ class ClientListVM {
return ClientListVM(
state: state,
clientList: memoizedFilteredClientList(state.clientState.map,
state.clientState.list, state.groupState.map, state.clientListState),
clientList: memoizedFilteredClientList(
state.clientState.map,
state.clientState.list,
state.groupState.map,
state.clientListState,
state.userState.map,
state.staticState),
clientMap: state.clientState.map,
isLoading: state.isLoading,
isLoaded: state.clientState.isLoaded,

View File

@ -44,8 +44,13 @@ class ClientScreenVM {
return ClientScreenVM(
clientMap: state.clientState.map,
clientList: memoizedFilteredClientList(state.clientState.map,
state.clientState.list, state.groupState.map, state.clientListState),
clientList: memoizedFilteredClientList(
state.clientState.map,
state.clientState.list,
state.groupState.map,
state.clientListState,
state.userState.map,
state.staticState),
userCompany: state.userCompany,
isInMultiselect: state.clientListState.isInMultiselect(),
);

View File

@ -145,8 +145,13 @@ class CreditListVM extends EntityListVM {
state: state,
user: state.user,
listState: state.creditListState,
invoiceList: memoizedFilteredCreditList(state.creditState.map,
state.creditState.list, state.clientState.map, state.creditListState),
invoiceList: memoizedFilteredCreditList(
state.creditState.map,
state.creditState.list,
state.clientState.map,
state.creditListState,
state.staticState,
state.userState.map),
invoiceMap: state.creditState.map,
clientMap: state.clientState.map,
isLoading: state.isLoading,

View File

@ -47,8 +47,13 @@ class CreditScreenVM {
return CreditScreenVM(
creditMap: state.creditState.map,
creditList: memoizedFilteredCreditList(state.creditState.map,
state.creditState.list, state.clientState.map, state.creditListState),
creditList: memoizedFilteredCreditList(
state.creditState.map,
state.creditState.list,
state.clientState.map,
state.creditListState,
state.staticState,
state.userState.map),
userCompany: state.userCompany,
isInMultiselect: state.creditListState.isInMultiselect(),
onEntityAction: (BuildContext context, List<BaseEntity> credits,

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/ui/app/entity_dropdown.dart';
import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart';
import 'package:invoiceninja_flutter/ui/app/forms/date_picker.dart';
@ -84,6 +86,8 @@ class ExpenseEditDetailsState extends State<ExpenseEditDetails> {
@override
Widget build(BuildContext context) {
final localization = AppLocalization.of(context);
final store = StoreProvider.of<AppState>(context);
final state = store.state;
final viewModel = widget.viewModel;
final expense = viewModel.expense;
final company = viewModel.company;
@ -121,7 +125,10 @@ class ExpenseEditDetailsState extends State<ExpenseEditDetails> {
labelText: localization.client,
entityId: expense.clientId,
entityList: memoizedDropdownClientList(
clientState.map, clientState.list),
clientState.map,
clientState.list,
state.userState.map,
state.staticState),
onSelected: (client) {
final currencyId =
(client as ClientEntity)?.settings?.currencyId ??

View File

@ -68,8 +68,8 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
final invoice = viewModel.invoice;
final lineItems = invoice.lineItems.toList();
final productState = state.productState;
final productIds =
memoizedDropdownProductList(productState.map, productState.list);
final productIds = memoizedDropdownProductList(
productState.map, productState.list, state.userState.map);
if (lineItems.where((item) => item.isEmpty).isEmpty) {
lineItems.add(InvoiceItemEntity());

View File

@ -187,7 +187,8 @@ class InvoiceListVM extends EntityListVM {
state.clientState.map,
state.paymentState.map,
state.invoiceListState,
),
state.staticState,
state.userState.map),
invoiceMap: state.invoiceState.map,
clientMap: state.clientState.map,
isLoading: state.isLoading,

View File

@ -50,7 +50,8 @@ class InvoiceScreenVM {
state.clientState.map,
state.paymentState.map,
state.invoiceListState,
),
state.staticState,
state.userState.map),
userCompany: state.userCompany,
isInMultiselect: state.invoiceListState.isInMultiselect(),
);

View File

@ -150,7 +150,10 @@ class _PaymentEditState extends State<PaymentEdit> {
..invoices.clear()));
},
entityList: memoizedDropdownClientList(
state.clientState.map, state.clientState.list),
state.clientState.map,
state.clientState.list,
state.userState.map,
state.staticState),
),
if (payment.isForInvoice != true &&
payment.isForCredit != true)
@ -359,7 +362,9 @@ class _PaymentableEditorState extends State<PaymentableEditor> {
state.invoiceState.map,
state.clientState.map,
state.invoiceState.list,
payment.clientId),
payment.clientId,
state.staticState,
state.userState.map),
onSelected: (selected) {
final invoice = selected as InvoiceEntity;
_amountController.text = formatNumber(invoice.balance, context,
@ -380,7 +385,9 @@ class _PaymentableEditorState extends State<PaymentableEditor> {
state.creditState.map,
state.clientState.map,
state.creditState.list,
payment.clientId),
payment.clientId,
state.staticState,
state.userState.map),
onSelected: (selected) {
final credit = selected as InvoiceEntity;
_amountController.text = formatNumber(credit.balance, context,

View File

@ -125,6 +125,7 @@ class PaymentListVM {
state.paymentState.list,
state.invoiceState.map,
state.clientState.map,
state.userState.map,
state.paymentListState),
paymentMap: state.paymentState.map,
clientMap: state.clientState.map,

View File

@ -12,7 +12,6 @@ class PaymentPresenter extends EntityPresenter {
PaymentFields.paymentNumber,
PaymentFields.client,
PaymentFields.amount,
PaymentFields.paymentStatus,
PaymentFields.invoiceNumber,
PaymentFields.paymentDate,
PaymentFields.transactionReference,

View File

@ -49,6 +49,7 @@ class PaymentScreenVM {
state.paymentState.list,
state.invoiceState.map,
state.clientState.map,
state.userState.map,
state.paymentListState),
userCompany: state.userCompany,
isInMultiselect: state.paymentListState.isInMultiselect(),

View File

@ -110,7 +110,7 @@ class ProductListVM {
return ProductListVM(
state: state,
productList: memoizedFilteredProductList(state.productState.map,
state.productState.list, state.productListState),
state.productState.list, state.productListState, state.userState.map),
productMap: state.productState.map,
isLoading: state.isLoading,
isLoaded: state.productState.isLoaded,

View File

@ -45,7 +45,7 @@ class ProductScreenVM {
return ProductScreenVM(
productMap: state.productState.map,
productList: memoizedFilteredProductList(state.productState.map,
state.productState.list, state.productListState),
state.productState.list, state.productListState, state.userState.map),
userCompany: state.userCompany,
isInMultiselect: state.productListState.isInMultiselect(),
);

View File

@ -137,7 +137,10 @@ class _ProjectEditState extends State<ProjectEdit> {
labelText: localization.client,
entityId: project.clientId,
entityList: memoizedDropdownClientList(
state.clientState.map, state.clientState.list),
state.clientState.map,
state.clientState.list,
state.userState.map,
state.staticState),
validator: (String val) => val.trim().isEmpty
? localization.pleaseSelectAClient
: null,

View File

@ -144,8 +144,13 @@ class QuoteListVM extends EntityListVM {
state: state,
user: state.user,
listState: state.quoteListState,
invoiceList: memoizedFilteredQuoteList(state.quoteState.map,
state.quoteState.list, state.clientState.map, state.quoteListState),
invoiceList: memoizedFilteredQuoteList(
state.quoteState.map,
state.quoteState.list,
state.clientState.map,
state.quoteListState,
state.staticState,
state.userState.map),
invoiceMap: state.quoteState.map,
clientMap: state.clientState.map,
isLoading: state.isLoading,

View File

@ -44,8 +44,13 @@ class QuoteScreenVM {
return QuoteScreenVM(
quoteMap: state.quoteState.map,
quoteList: memoizedFilteredQuoteList(state.quoteState.map,
state.quoteState.list, state.clientState.map, state.quoteListState),
quoteList: memoizedFilteredQuoteList(
state.quoteState.map,
state.quoteState.list,
state.clientState.map,
state.quoteListState,
state.staticState,
state.userState.map),
userCompany: state.userCompany,
isInMultiselect: state.quoteListState.isInMultiselect(),
);

View File

@ -93,7 +93,10 @@ class _TaskEditDetailsState extends State<TaskEditDetails> {
labelText: localization.client,
entityId: task.clientId,
entityList: memoizedDropdownClientList(
state.clientState.map, state.clientState.list),
state.clientState.map,
state.clientState.list,
state.userState.map,
state.staticState),
onSelected: (client) {
viewModel.onChanged(task.rebuild((b) => b
..clientId = client?.id