This commit is contained in:
Hillel Coren 2018-09-25 18:19:26 +03:00
parent 751bfa62ff
commit ac56a46ed6
16 changed files with 86 additions and 45 deletions

View File

@ -56,9 +56,9 @@ abstract class ClientEntity extends Object
implements Built<ClientEntity, ClientEntityBuilder> {
static int counter = 0;
factory ClientEntity() {
factory ClientEntity({int id}) {
return _$ClientEntity._(
id: --ClientEntity.counter,
id: id ?? --ClientEntity.counter,
name: '',
displayName: '',
balance: 0.0,

View File

@ -88,9 +88,9 @@ abstract class InvoiceEntity extends Object
implements Built<InvoiceEntity, InvoiceEntityBuilder> {
static int counter = 0;
factory InvoiceEntity({bool isQuote = false}) {
factory InvoiceEntity({int id, bool isQuote = false}) {
return _$InvoiceEntity._(
id: --InvoiceEntity.counter,
id: id ?? --InvoiceEntity.counter,
amount: 0.0,
balance: 0.0,
clientId: 0,
@ -448,7 +448,7 @@ abstract class InvoiceEntity extends Object
bool isBetween(String startDate, String endDate) {
return startDate.compareTo(invoiceDate) <= 0 &&
endDate.compareTo(invoiceDate) >= 0;
endDate.compareTo(invoiceDate) == 1;
}
double get requestedAmount => partial > 0 ? partial : amount;
@ -474,7 +474,7 @@ abstract class InvoiceEntity extends Object
String get invitationDownloadLink => invitations.first?.downloadLink;
PaymentEntity createPayment(CompanyEntity company) {
return PaymentEntity(company).rebuild((b) => b
return PaymentEntity(company: company).rebuild((b) => b
..invoiceId = id
..clientId = clientId
..amount = balance);

View File

@ -56,9 +56,9 @@ abstract class PaymentEntity extends Object
implements Built<PaymentEntity, PaymentEntityBuilder> {
static int counter = 0;
factory PaymentEntity([CompanyEntity company]) {
factory PaymentEntity({int id, CompanyEntity company}) {
return _$PaymentEntity._(
id: --PaymentEntity.counter,
id: id ?? --PaymentEntity.counter,
amount: 0.0,
transactionReference: '',
paymentDate: convertDateTimeToSqlDate(),

View File

@ -30,7 +30,8 @@ List<ChartMoneyData> chartOutstandingInvoices({
final Map<String, double> totals = {};
invoiceMap.forEach((int, invoice) {
final client = clientMap[invoice.clientId] ?? ClientEntity();
final client =
clientMap[invoice.clientId] ?? ClientEntity(id: invoice.clientId);
final currencyId =
client.currencyId > 0 ? client.currencyId : company.currencyId;
@ -39,7 +40,8 @@ List<ChartMoneyData> chartOutstandingInvoices({
invoice.isQuote ||
invoice.isRecurring) {
// skip it
} else if (!invoice.isBetween(settings.startDate(company), settings.endDate(company))) {
} else if (!invoice.isBetween(
settings.startDate(company), settings.endDate(company))) {
// skip it
} else if (settings.currencyId > 0 && settings.currencyId != currencyId) {
// skip it
@ -55,7 +57,7 @@ List<ChartMoneyData> chartOutstandingInvoices({
var date = DateTime.parse(settings.startDate(company));
final endDate = DateTime.parse(settings.endDate(company));
while (! date.isAfter(endDate)) {
while (!date.isAfter(endDate)) {
final key = convertDateTimeToSqlDate(date);
if (totals.containsKey(key)) {
data.add(ChartMoneyData(date, totals[key]));
@ -84,14 +86,17 @@ List<ChartMoneyData> chartPayments(
final Map<String, double> totals = {};
paymentMap.forEach((int, payment) {
final invoice = invoiceMap[payment.invoiceId] ?? InvoiceEntity();
final client = clientMap[invoice.clientId] ?? ClientEntity();
final invoice =
invoiceMap[payment.invoiceId] ?? InvoiceEntity(id: payment.invoiceId);
final client =
clientMap[invoice.clientId] ?? ClientEntity(id: invoice.clientId);
final currencyId =
client.currencyId > 0 ? client.currencyId : company.currencyId;
if (payment.isDeleted) {
// skip it
} else if (!payment.isBetween(settings.startDate(company), settings.endDate(company))) {
} else if (!payment.isBetween(
settings.startDate(company), settings.endDate(company))) {
// skip it
} else if (settings.currencyId > 0 && settings.currencyId != currencyId) {
// skip it
@ -107,7 +112,7 @@ List<ChartMoneyData> chartPayments(
var date = DateTime.parse(settings.startDate(company));
final endDate = DateTime.parse(settings.endDate(company));
while (! date.isAfter(endDate)) {
while (!date.isAfter(endDate)) {
final key = convertDateTimeToSqlDate(date);
if (totals.containsKey(key)) {
data.add(ChartMoneyData(date, totals[key]));

View File

@ -29,7 +29,7 @@ List<int> dropdownInvoiceSelector(BuiltMap<int, InvoiceEntity> invoiceMap,
ClientEntity invoiceClientSelector(
InvoiceEntity invoice, BuiltMap<int, ClientEntity> clientMap) {
return clientMap[invoice.clientId] ?? ClientEntity();
return clientMap[invoice.clientId] ?? ClientEntity(id: invoice.clientId);
}
var memoizedFilteredInvoiceList = memo4(
@ -47,7 +47,7 @@ List<int> filteredInvoicesSelector(
ListUIState invoiceListState) {
final list = invoiceList.where((invoiceId) {
final invoice = invoiceMap[invoiceId];
final client = clientMap[invoice.clientId] ?? ClientEntity();
final client = clientMap[invoice.clientId] ?? ClientEntity(id: invoice.clientId);
if (client == null || !client.isActive) {
return false;
}

View File

@ -17,13 +17,16 @@ List<PaymentEntity> paymentsByInvoiceSelector(int invoiceId,
}
InvoiceEntity paymentInvoiceSelector(int paymentId, AppState state) {
final payment = state.paymentState.map[paymentId] ?? PaymentEntity();
return state.invoiceState.map[payment.invoiceId] ?? InvoiceEntity();
final payment =
state.paymentState.map[paymentId] ?? PaymentEntity(id: paymentId);
return state.invoiceState.map[payment.invoiceId] ??
InvoiceEntity(id: payment.invoiceId);
}
ClientEntity paymentClientSelector(int paymentId, AppState state) {
final invoice = paymentInvoiceSelector(paymentId, state);
return state.clientState.map[invoice.clientId] ?? ClientEntity();
return state.clientState.map[invoice.clientId] ??
ClientEntity(id: invoice.clientId);
}
var memoizedDropdownPaymentList = memo2(

View File

@ -44,7 +44,7 @@ abstract class PaymentUIState extends Object with EntityUIState implements Built
factory PaymentUIState(CompanyEntity company) {
return _$PaymentUIState._(
listUIState: ListUIState(PaymentFields.paymentDate),
editing: PaymentEntity(company),
editing: PaymentEntity(company: company),
selectedId: 0,
);
}

View File

@ -12,13 +12,14 @@ import 'package:invoiceninja_flutter/ui/app/app_drawer_vm.dart';
import 'package:invoiceninja_flutter/ui/settings/settings_screen.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:invoiceninja_flutter/utils/platforms.dart';
import 'package:redux/redux.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:cached_network_image/cached_network_image.dart';
// STARTER: import - do not remove comment
import 'package:invoiceninja_flutter/redux/payment/payment_actions.dart';
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
import 'package:url_launcher/url_launcher.dart';
class AppDrawer extends StatelessWidget {
final AppDrawerVM viewModel;
@ -83,8 +84,8 @@ class AppDrawer extends StatelessWidget {
final ThemeData themeData = Theme.of(context);
final TextStyle aboutTextStyle = themeData.textTheme.body2;
//final TextStyle linkStyle =
//themeData.textTheme.body2.copyWith(color: themeData.accentColor);
final TextStyle linkStyle =
themeData.textTheme.body2.copyWith(color: themeData.accentColor);
return Drawer(
child: ListView(
@ -192,7 +193,7 @@ class AppDrawer extends StatelessWidget {
onCreateTap: () {
navigator.pop();
store.dispatch(EditPayment(
payment: PaymentEntity(company), context: context));
payment: PaymentEntity(company: company), context: context));
},
),
DrawerTile(
@ -217,10 +218,26 @@ class AppDrawer extends StatelessWidget {
builder: (BuildContext context) => AlertDialog(
semanticLabel: 'Task & Expenses',
title: Text('Task & Expenses'),
content: Text(
'Thank for your patience while we work to implement these features.\n\n' +
'We hope to have them completed in the next few months.\n\n'
'Until then we\'ll continue to support the legacy mobile apps.'),
content: RichText(
text: TextSpan(
children: <TextSpan>[
TextSpan(
style: aboutTextStyle,
text:
localization.thanksForPatience + ' ',
),
_LinkTextSpan(
style: linkStyle,
url: getLegacyAppURL(context),
text: localization.legacyMobileApp,
),
TextSpan(
style: aboutTextStyle,
text: '.',
),
],
),
),
actions: <Widget>[
FlatButton(
child: Text(localization.ok.toUpperCase()),

View File

@ -89,7 +89,7 @@ class ClientListVM {
break;
case EntityAction.payment:
store.dispatch(EditPayment(
payment: PaymentEntity(state.selectedCompany)
payment: PaymentEntity(company: state.selectedCompany)
.rebuild((b) => b.clientId = client.id),
context: context));
break;

View File

@ -94,7 +94,7 @@ class _ClientViewState extends State<ClientView>
onTap: () {
Navigator.of(context).pop();
store.dispatch(EditPayment(
payment: PaymentEntity(company)
payment: PaymentEntity(company: company)
.rebuild((b) => b.clientId = client.id),
context: context));
},

View File

@ -21,8 +21,8 @@ class InvoiceEmailScreen extends StatelessWidget {
final state = store.state;
final invoiceId = state.uiState.invoiceUIState.selectedId;
final invoice = state.invoiceState.map[invoiceId];
final client =
state.clientState.map[invoice.clientId] ?? ClientEntity();
final client = state.clientState.map[invoice.clientId] ??
ClientEntity(id: invoice.clientId);
if (client.areActivitiesStale) {
store.dispatch(LoadClient(clientId: client.id, loadActivities: true));
}
@ -86,7 +86,8 @@ class EmailInvoiceVM extends EmailEntityVM {
isSaving: state.isSaving,
company: state.selectedCompany,
invoice: invoice,
client: state.clientState.map[invoice.clientId] ?? ClientEntity(),
client: state.clientState.map[invoice.clientId] ??
ClientEntity(id: invoice.clientId),
onSendPressed: (context, template, subject, body) =>
store.dispatch(EmailInvoiceRequest(
completer: popCompleter(context, true),

View File

@ -116,8 +116,8 @@ class InvoiceViewVM extends EntityViewVM {
factory InvoiceViewVM.fromStore(Store<AppState> store) {
final state = store.state;
final invoice = state.invoiceState.map[state.invoiceUIState.selectedId];
final client =
store.state.clientState.map[invoice.clientId] ?? ClientEntity();
final client = store.state.clientState.map[invoice.clientId] ??
ClientEntity(id: invoice.clientId);
Future<Null> _handleRefresh(BuildContext context) {
final completer = snackBarCompleter(

View File

@ -68,7 +68,8 @@ class PaymentScreen extends StatelessWidget {
backgroundColor: Theme.of(context).primaryColorDark,
onPressed: () {
store.dispatch(EditPayment(
payment: PaymentEntity(company), context: context));
payment: PaymentEntity(company: company),
context: context));
},
child: Icon(
Icons.add,

View File

@ -20,6 +20,9 @@ class AppLocalization {
static final Map<String, Map<String, String>> _localizedValues = {
'en': {
'thanks_for_patience':
'Thank for your patience while we work to implement these features.\n\nWe hope to have them completed in the next few months.\n\nUntil then we\'ll continue to support the',
'legacy_mobile_app': 'legacy mobile app',
'today': 'Today',
'custom_range': 'Custom',
'date_range': 'Date Range',
@ -8344,6 +8347,12 @@ class AppLocalization {
},
};
String get thanksForPatience =>
_localizedValues[locale.toString()]['thanks_for_patience'];
String get legacyMobileApp =>
_localizedValues[locale.toString()]['legacy_mobile_app'];
String get today => _localizedValues[locale.toString()]['today'];
String get customRange => _localizedValues[locale.toString()]['custom_range'];

View File

@ -1,11 +1,15 @@
import 'package:flutter/material.dart';
String getMapURL(BuildContext context) {
final bool iOS = Theme.of(context).platform == TargetPlatform.iOS;
return iOS
? 'http://maps.apple.com/?address='
: 'https://maps.google.com/?q=';
}
bool isAndroid(BuildContext context) =>
Theme.of(context).platform == TargetPlatform.android;
String getMapURL(BuildContext context) => isAndroid(context)
? 'https://maps.google.com/?q='
: 'http://maps.apple.com/?address=';
String getLegacyAppURL(BuildContext context) => isAndroid(context)
? 'https://play.google.com/store/apps/details?id=com.invoiceninja.invoiceninja'
: 'https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=1220337560&mt=8';
String getPlatform(BuildContext context) =>
Theme.of(context).platform == TargetPlatform.iOS ? 'ios' : 'android';
Theme.of(context).platform == TargetPlatform.iOS ? 'ios' : 'android';

View File

@ -15,7 +15,8 @@ String processTemplate(
final state = StoreProvider.of<AppState>(context).state;
final localization = AppLocalization.of(context);
final company = state.selectedCompany;
final client = state.clientState.map[invoice.clientId] ?? ClientEntity();
final client = state.clientState.map[invoice.clientId] ??
ClientEntity(id: invoice.clientId);
final contact = client.contacts.first;
final String sampleButton = '[${localization.button}]';