This commit is contained in:
Hillel Coren 2018-08-26 12:50:44 -07:00
parent 5ed5f85124
commit 128c025224
7 changed files with 52 additions and 24 deletions

View File

@ -17,8 +17,8 @@ Join the Android beta: https://play.google.com/apps/testing/com.invoiceninja.inv
- [x] Clients - [x] Clients
- [x] Products - [x] Products
- [x] Invoices - [x] Invoices
- [x] Quotes
- [ ] Payments - [ ] Payments
- [ ] Quotes
- [ ] Credits - [ ] Credits
- [ ] Recurring - [ ] Recurring
- [ ] Vendors - [ ] Vendors

View File

@ -1,7 +1,8 @@
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:invoiceninja_flutter/redux/company/company_selectors.dart'; import 'package:invoiceninja_flutter/redux/company/company_selectors.dart';
import 'package:invoiceninja_flutter/ui/app/app_builder.dart'; import 'package:invoiceninja_flutter/ui/app/app_builder.dart';
import 'package:invoiceninja_flutter/ui/app/invoice/invoice_email_vm.dart'; import 'package:invoiceninja_flutter/ui/invoice/invoice_email_vm.dart';
import 'package:invoiceninja_flutter/ui/quote/quote_email_vm.dart';
import 'package:redux/redux.dart'; import 'package:redux/redux.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -146,6 +147,7 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
}, },
QuoteViewScreen.route: (context) => QuoteViewScreen(), QuoteViewScreen.route: (context) => QuoteViewScreen(),
QuoteEditScreen.route: (context) => QuoteEditScreen(), QuoteEditScreen.route: (context) => QuoteEditScreen(),
QuoteEmailScreen.route: (context) => QuoteEmailScreen(),
SettingsScreen.route: (context) => SettingsScreen(), SettingsScreen.route: (context) => SettingsScreen(),
}, },
); );

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart'; import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart'; import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
import 'package:invoiceninja_flutter/ui/app/invoice/invoice_email_vm.dart'; import 'package:invoiceninja_flutter/ui/invoice/invoice_email_vm.dart';
import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/invoice/edit/invoice_edit_vm.dart';
import 'package:invoiceninja_flutter/ui/invoice/invoice_screen.dart'; import 'package:invoiceninja_flutter/ui/invoice/invoice_screen.dart';
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view_vm.dart'; import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view_vm.dart';

View File

@ -2,8 +2,9 @@ import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart'; import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart'; import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
import 'package:invoiceninja_flutter/ui/app/invoice/invoice_email_vm.dart'; import 'package:invoiceninja_flutter/ui/invoice/invoice_email_vm.dart';
import 'package:invoiceninja_flutter/ui/quote/edit/quote_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/quote/edit/quote_edit_vm.dart';
import 'package:invoiceninja_flutter/ui/quote/quote_email_vm.dart';
import 'package:invoiceninja_flutter/ui/quote/quote_screen.dart'; import 'package:invoiceninja_flutter/ui/quote/quote_screen.dart';
import 'package:invoiceninja_flutter/ui/quote/view/quote_view_vm.dart'; import 'package:invoiceninja_flutter/ui/quote/view/quote_view_vm.dart';
import 'package:redux/redux.dart'; import 'package:redux/redux.dart';
@ -68,7 +69,7 @@ Middleware<AppState> _editQuote() {
store.dispatch(UpdateCurrentRoute(QuoteEditScreen.route)); store.dispatch(UpdateCurrentRoute(QuoteEditScreen.route));
final quote = final quote =
await Navigator.of(action.context).pushNamed(QuoteEditScreen.route); await Navigator.of(action.context).pushNamed(QuoteEditScreen.route);
if (action.completer != null && quote != null) { if (action.completer != null && quote != null) {
action.completer.complete(quote); action.completer.complete(quote);
@ -80,7 +81,8 @@ Middleware<AppState> _showEmailQuote() {
return (Store<AppState> store, dynamic action, NextDispatcher next) async { return (Store<AppState> store, dynamic action, NextDispatcher next) async {
next(action); next(action);
final emailWasSent = await Navigator.of(action.context).pushNamed(InvoiceEmailScreen.route); final emailWasSent =
await Navigator.of(action.context).pushNamed(QuoteEmailScreen.route);
if (action.completer != null && emailWasSent) { if (action.completer != null && emailWasSent) {
action.completer.complete(null); action.completer.complete(null);
@ -92,8 +94,8 @@ Middleware<AppState> _archiveQuote(QuoteRepository repository) {
return (Store<AppState> store, dynamic action, NextDispatcher next) { return (Store<AppState> store, dynamic action, NextDispatcher next) {
final origQuote = store.state.quoteState.map[action.quoteId]; final origQuote = store.state.quoteState.map[action.quoteId];
repository repository
.saveData(store.state.selectedCompany, store.state.authState, .saveData(store.state.selectedCompany, store.state.authState, origQuote,
origQuote, EntityAction.archive) EntityAction.archive)
.then((dynamic quote) { .then((dynamic quote) {
store.dispatch(ArchiveQuoteSuccess(quote)); store.dispatch(ArchiveQuoteSuccess(quote));
if (action.completer != null) { if (action.completer != null) {
@ -115,8 +117,8 @@ Middleware<AppState> _deleteQuote(QuoteRepository repository) {
return (Store<AppState> store, dynamic action, NextDispatcher next) { return (Store<AppState> store, dynamic action, NextDispatcher next) {
final origQuote = store.state.quoteState.map[action.quoteId]; final origQuote = store.state.quoteState.map[action.quoteId];
repository repository
.saveData(store.state.selectedCompany, store.state.authState, .saveData(store.state.selectedCompany, store.state.authState, origQuote,
origQuote, EntityAction.delete) EntityAction.delete)
.then((InvoiceEntity quote) { .then((InvoiceEntity quote) {
store.dispatch(DeleteQuoteSuccess(quote)); store.dispatch(DeleteQuoteSuccess(quote));
store.dispatch(LoadClient(clientId: quote.clientId)); store.dispatch(LoadClient(clientId: quote.clientId));
@ -139,8 +141,8 @@ Middleware<AppState> _restoreQuote(QuoteRepository repository) {
return (Store<AppState> store, dynamic action, NextDispatcher next) { return (Store<AppState> store, dynamic action, NextDispatcher next) {
final origQuote = store.state.quoteState.map[action.quoteId]; final origQuote = store.state.quoteState.map[action.quoteId];
repository repository
.saveData(store.state.selectedCompany, store.state.authState, .saveData(store.state.selectedCompany, store.state.authState, origQuote,
origQuote, EntityAction.restore) EntityAction.restore)
.then((InvoiceEntity quote) { .then((InvoiceEntity quote) {
store.dispatch(RestoreQuoteSuccess(quote)); store.dispatch(RestoreQuoteSuccess(quote));
store.dispatch(LoadClient(clientId: quote.clientId)); store.dispatch(LoadClient(clientId: quote.clientId));
@ -163,8 +165,8 @@ Middleware<AppState> _markSentQuote(QuoteRepository repository) {
return (Store<AppState> store, dynamic action, NextDispatcher next) { return (Store<AppState> store, dynamic action, NextDispatcher next) {
final origQuote = store.state.quoteState.map[action.quoteId]; final origQuote = store.state.quoteState.map[action.quoteId];
repository repository
.saveData(store.state.selectedCompany, store.state.authState, .saveData(store.state.selectedCompany, store.state.authState, origQuote,
origQuote, EntityAction.markSent) EntityAction.markSent)
.then((dynamic quote) { .then((dynamic quote) {
store.dispatch(MarkSentQuoteSuccess(quote)); store.dispatch(MarkSentQuoteSuccess(quote));
store.dispatch(LoadClient(clientId: quote.clientId)); store.dispatch(LoadClient(clientId: quote.clientId));
@ -212,7 +214,7 @@ Middleware<AppState> _saveQuote(QuoteRepository repository) {
return (Store<AppState> store, dynamic action, NextDispatcher next) { return (Store<AppState> store, dynamic action, NextDispatcher next) {
repository repository
.saveData( .saveData(
store.state.selectedCompany, store.state.authState, action.quote) store.state.selectedCompany, store.state.authState, action.quote)
.then((dynamic quote) { .then((dynamic quote) {
if (action.quote.isNew) { if (action.quote.isNew) {
store.dispatch(AddQuoteSuccess(quote)); store.dispatch(AddQuoteSuccess(quote));
@ -275,7 +277,7 @@ Middleware<AppState> _loadQuotes(QuoteRepository repository) {
} }
final int updatedAt = final int updatedAt =
action.force ? 0 : (state.quoteState.lastUpdated / 1000).round(); action.force ? 0 : (state.quoteState.lastUpdated / 1000).round();
store.dispatch(LoadQuotesRequest()); store.dispatch(LoadQuotesRequest());
repository repository

View File

@ -2,7 +2,7 @@ import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart'; import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/ui/app/buttons/refresh_icon_button.dart'; import 'package:invoiceninja_flutter/ui/app/buttons/refresh_icon_button.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/app/invoice/invoice_email_vm.dart'; import 'package:invoiceninja_flutter/ui/invoice/invoice_email_vm.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/ui/app/lists/activity_list_tile.dart'; import 'package:invoiceninja_flutter/ui/app/lists/activity_list_tile.dart';
@ -14,7 +14,7 @@ import 'package:invoiceninja_flutter/utils/templates.dart';
import 'package:html/parser.dart'; import 'package:html/parser.dart';
class InvoiceEmailView extends StatefulWidget { class InvoiceEmailView extends StatefulWidget {
final EmailInvoiceVM viewModel; final EmailEntityVM viewModel;
const InvoiceEmailView({ const InvoiceEmailView({
Key key, Key key,
@ -68,14 +68,20 @@ class _InvoiceEmailViewState extends State<InvoiceEmailView> {
} }
void loadTemplate(EmailTemplate template) { void loadTemplate(EmailTemplate template) {
final company = widget.viewModel.company; final viewModel = widget.viewModel;
final company = viewModel.company;
selectedTemplate = template; selectedTemplate = template;
switch (template) { switch (template) {
case EmailTemplate.initial: case EmailTemplate.initial:
emailSubject = company.emailSubjectInvoice; if (viewModel.invoice.isQuote) {
emailBody = company.emailBodyInvoice; emailSubject = company.emailSubjectQuote;
emailBody = company.emailBodyQuote;
} else {
emailSubject = company.emailSubjectInvoice;
emailBody = company.emailBodyInvoice;
}
break; break;
case EmailTemplate.reminder1: case EmailTemplate.reminder1:
emailSubject = company.emailSubjectReminder1; emailSubject = company.emailSubjectReminder1;

View File

@ -41,7 +41,7 @@ class InvoiceEmailScreen extends StatelessWidget {
} }
} }
class EmailInvoiceVM { abstract class EmailEntityVM {
final bool isLoading; final bool isLoading;
final bool isSaving; final bool isSaving;
final CompanyEntity company; final CompanyEntity company;
@ -49,7 +49,7 @@ class EmailInvoiceVM {
final ClientEntity client; final ClientEntity client;
final Function(BuildContext, EmailTemplate, String, String) onSendPressed; final Function(BuildContext, EmailTemplate, String, String) onSendPressed;
EmailInvoiceVM({ EmailEntityVM({
@required this.isLoading, @required this.isLoading,
@required this.isSaving, @required this.isSaving,
@required this.company, @required this.company,
@ -57,6 +57,25 @@ class EmailInvoiceVM {
@required this.client, @required this.client,
@required this.onSendPressed, @required this.onSendPressed,
}); });
}
class EmailInvoiceVM extends EmailEntityVM {
EmailInvoiceVM({
bool isLoading,
bool isSaving,
CompanyEntity company,
InvoiceEntity invoice,
ClientEntity client,
Function(BuildContext, EmailTemplate, String, String) onSendPressed,
}): super(
isLoading: isLoading,
isSaving: isSaving,
company: company,
invoice: invoice,
client: client,
onSendPressed: onSendPressed,
);
factory EmailInvoiceVM.fromStore( factory EmailInvoiceVM.fromStore(
Store<AppState> store, InvoiceEntity invoice) { Store<AppState> store, InvoiceEntity invoice) {

View File

@ -9,7 +9,6 @@ import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart'; import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart';
import 'package:invoiceninja_flutter/ui/app/icon_message.dart'; import 'package:invoiceninja_flutter/ui/app/icon_message.dart';
import 'package:invoiceninja_flutter/ui/app/invoice/invoice_item_view.dart'; import 'package:invoiceninja_flutter/ui/app/invoice/invoice_item_view.dart';
import 'package:invoiceninja_flutter/ui/app/two_value_header.dart';
import 'package:invoiceninja_flutter/ui/quote/view/quote_view_vm.dart'; import 'package:invoiceninja_flutter/ui/quote/view/quote_view_vm.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';