Refactor entity actions
This commit is contained in:
parent
c3237fd659
commit
ccb07c4373
|
|
@ -106,8 +106,6 @@ class ExpenseStatusColors {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
const List<int> kPaymentTerms = [0, -1, 7, 10, 14, 15, 30, 60, 90];
|
||||
|
||||
const String kDesignCustom1 = 'Custom 1';
|
||||
|
|
|
|||
|
|
@ -68,7 +68,11 @@ abstract class ExpenseEntity extends Object
|
|||
with BaseEntity, SelectableEntity, BelongsToClient
|
||||
implements Built<ExpenseEntity, ExpenseEntityBuilder> {
|
||||
factory ExpenseEntity(
|
||||
{int id, CompanyEntity company, UIState uiState, VendorEntity vendor, ClientEntity client}) {
|
||||
{int id,
|
||||
CompanyEntity company,
|
||||
UIState uiState,
|
||||
VendorEntity vendor,
|
||||
ClientEntity client}) {
|
||||
return _$ExpenseEntity._(
|
||||
id: id ?? --ExpenseEntity.counter,
|
||||
privateNotes: '',
|
||||
|
|
|
|||
|
|
@ -120,8 +120,6 @@ abstract class CurrencyEntity extends Object
|
|||
@override
|
||||
double get listDisplayAmount => null;
|
||||
|
||||
|
||||
|
||||
static Serializer<CurrencyEntity> get serializer =>
|
||||
_$currencyEntitySerializer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -311,7 +311,8 @@ Middleware<AppState> _createAccountLoaded() {
|
|||
};
|
||||
}
|
||||
|
||||
Middleware<AppState> _createPersistStatic(PersistenceRepository staticRepository) {
|
||||
Middleware<AppState> _createPersistStatic(
|
||||
PersistenceRepository staticRepository) {
|
||||
return (Store<AppState> store, dynamic action, NextDispatcher next) {
|
||||
// first process the action so the data is in the state
|
||||
next(action);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ var memoizedDropdownExpenseCategoriesList = memo2(
|
|||
List<int> dropdownExpenseCategoriesSelector(
|
||||
BuiltMap<int, ExpenseCategoryEntity> categoryMap,
|
||||
BuiltList<ExpenseCategoryEntity> categoryList) {
|
||||
|
||||
final list = categoryList
|
||||
//.where((category) => category.isActive)
|
||||
.map((category) => category.id)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,13 @@ import 'package:flutter/widgets.dart';
|
|||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja_flutter/redux/expense/expense_selectors.dart';
|
||||
|
||||
class ViewExpenseList implements PersistUI {
|
||||
ViewExpenseList(this.context);
|
||||
|
|
@ -227,3 +234,47 @@ class FilterExpensesByEntity implements PersistUI {
|
|||
final int entityId;
|
||||
final EntityType entityType;
|
||||
}
|
||||
|
||||
void handleExpenseAction(
|
||||
BuildContext context, ExpenseEntity expense, EntityAction action) {
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
final state = store.state;
|
||||
final CompanyEntity company = state.selectedCompany;
|
||||
final localization = AppLocalization.of(context);
|
||||
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
store.dispatch(EditExpense(context: context, expense: expense));
|
||||
break;
|
||||
case EntityAction.clone:
|
||||
store.dispatch(EditExpense(context: context, expense: expense.clone));
|
||||
break;
|
||||
case EntityAction.newInvoice:
|
||||
final item = convertExpenseToInvoiceItem(expense: expense);
|
||||
store.dispatch(EditInvoice(
|
||||
invoice: InvoiceEntity(company: company).rebuild((b) => b
|
||||
..hasExpenses = true
|
||||
..clientId = expense.clientId
|
||||
..invoiceItems.add(item)),
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.viewInvoice:
|
||||
store.dispatch(
|
||||
ViewInvoice(invoiceId: expense.invoiceId, context: context));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreExpenseRequest(
|
||||
snackBarCompleter(context, localization.restoredExpense),
|
||||
expense.id));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveExpenseRequest(
|
||||
snackBarCompleter(context, localization.archivedExpense),
|
||||
expense.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteExpenseRequest(
|
||||
snackBarCompleter(context, localization.deletedExpense), expense.id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,13 +89,13 @@ ListUIState _filterExpensesByState(
|
|||
ListUIState _filterExpensesByStatus(
|
||||
ListUIState expenseListState, FilterExpensesByStatus action) {
|
||||
if (expenseListState.statusFilters.contains(action.status)) {
|
||||
return expenseListState.rebuild((b) => b..statusFilters.remove(action.status));
|
||||
return expenseListState
|
||||
.rebuild((b) => b..statusFilters.remove(action.status));
|
||||
} else {
|
||||
return expenseListState.rebuild((b) => b..statusFilters.add(action.status));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ListUIState _filterExpenses(
|
||||
ListUIState expenseListState, FilterExpenses action) {
|
||||
return expenseListState.rebuild((b) => b..filter = action.filter);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,17 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja_flutter/redux/payment/payment_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
|
||||
import 'package:invoiceninja_flutter/utils/pdf.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class ViewInvoiceList implements PersistUI {
|
||||
ViewInvoiceList(this.context);
|
||||
|
|
@ -302,3 +310,63 @@ class FilterInvoicesByCustom2 implements PersistUI {
|
|||
|
||||
final String value;
|
||||
}
|
||||
|
||||
void handleInvoiceAction(
|
||||
BuildContext context, InvoiceEntity invoice, EntityAction action) async {
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
final state = store.state;
|
||||
final CompanyEntity company = state.selectedCompany;
|
||||
final localization = AppLocalization.of(context);
|
||||
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
store.dispatch(EditInvoice(context: context, invoice: invoice));
|
||||
break;
|
||||
case EntityAction.pdf:
|
||||
viewPdf(invoice, context);
|
||||
break;
|
||||
case EntityAction.clientPortal:
|
||||
if (await canLaunch(invoice.invitationSilentLink)) {
|
||||
await launch(invoice.invitationSilentLink,
|
||||
forceSafariVC: false, forceWebView: false);
|
||||
}
|
||||
break;
|
||||
case EntityAction.markSent:
|
||||
store.dispatch(MarkSentInvoiceRequest(
|
||||
snackBarCompleter(context, localization.markedInvoiceAsSent),
|
||||
invoice.id));
|
||||
break;
|
||||
case EntityAction.sendEmail:
|
||||
store.dispatch(ShowEmailInvoice(
|
||||
completer: snackBarCompleter(context, localization.emailedInvoice),
|
||||
invoice: invoice,
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.cloneToInvoice:
|
||||
store.dispatch(
|
||||
EditInvoice(context: context, invoice: invoice.cloneToInvoice));
|
||||
break;
|
||||
case EntityAction.cloneToQuote:
|
||||
store.dispatch(EditQuote(context: context, quote: invoice.cloneToQuote));
|
||||
break;
|
||||
case EntityAction.enterPayment:
|
||||
store.dispatch(EditPayment(
|
||||
context: context,
|
||||
payment: invoice.createPayment(company)));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreInvoiceRequest(
|
||||
snackBarCompleter(context, localization.restoredInvoice),
|
||||
invoice.id));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveInvoiceRequest(
|
||||
snackBarCompleter(context, localization.archivedInvoice),
|
||||
invoice.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteInvoiceRequest(
|
||||
snackBarCompleter(context, localization.deletedInvoice), invoice.id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ InvoiceEntity _addInvoiceItem(InvoiceEntity invoice, AddInvoiceItem action) {
|
|||
InvoiceEntity _addInvoiceItems(InvoiceEntity invoice, AddInvoiceItems action) {
|
||||
return invoice.rebuild((b) => b
|
||||
..hasTasks = action.invoiceItems.where((item) => item.isTask).isNotEmpty
|
||||
..hasExpenses = action.invoiceItems.where((item) => item.isExpense).isNotEmpty
|
||||
..hasExpenses =
|
||||
action.invoiceItems.where((item) => item.isExpense).isNotEmpty
|
||||
..invoiceItems.addAll(action.invoiceItems));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@ import 'package:flutter/widgets.dart';
|
|||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
||||
class ViewPaymentList implements PersistUI {
|
||||
ViewPaymentList(this.context);
|
||||
|
|
@ -236,3 +240,33 @@ class FilterPaymentsByEntity implements PersistUI {
|
|||
final int entityId;
|
||||
final EntityType entityType;
|
||||
}
|
||||
|
||||
void handlePaymentAction(
|
||||
BuildContext context, PaymentEntity payment, EntityAction action) {
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
final localization = AppLocalization.of(context);
|
||||
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
store.dispatch(EditPayment(context: context, payment: payment));
|
||||
break;
|
||||
case EntityAction.sendEmail:
|
||||
store.dispatch(EmailPaymentRequest(
|
||||
snackBarCompleter(context, localization.emailedPayment), payment));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestorePaymentRequest(
|
||||
snackBarCompleter(context, localization.restoredPayment),
|
||||
payment.id));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchivePaymentRequest(
|
||||
snackBarCompleter(context, localization.archivedPayment),
|
||||
payment.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeletePaymentRequest(
|
||||
snackBarCompleter(context, localization.deletedPayment), payment.id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
|||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
||||
|
||||
class ViewProductList implements PersistUI {
|
||||
ViewProductList(this.context);
|
||||
|
||||
|
|
@ -179,7 +178,6 @@ class FilterProductDropdown {
|
|||
final String filter;
|
||||
}
|
||||
|
||||
|
||||
void handleProductAction(
|
||||
BuildContext context, ProductEntity product, EntityAction action) {
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
|
|
@ -199,8 +197,7 @@ void handleProductAction(
|
|||
store.dispatch(EditProduct(context: context, product: product));
|
||||
break;
|
||||
case EntityAction.clone:
|
||||
store.dispatch(
|
||||
EditProduct(context: context, product: product.clone));
|
||||
store.dispatch(EditProduct(context: context, product: product.clone));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreProductRequest(
|
||||
|
|
@ -214,8 +211,7 @@ void handleProductAction(
|
|||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteProductRequest(
|
||||
snackBarCompleter(context, localization.deletedProduct),
|
||||
product.id));
|
||||
snackBarCompleter(context, localization.deletedProduct), product.id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,13 @@ import 'package:flutter/widgets.dart';
|
|||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja_flutter/redux/project/project_selectors.dart';
|
||||
|
||||
class ViewProjectList implements PersistUI {
|
||||
ViewProjectList(this.context);
|
||||
|
|
@ -221,3 +228,47 @@ class FilterProjectsByEntity implements PersistUI {
|
|||
final int entityId;
|
||||
final EntityType entityType;
|
||||
}
|
||||
|
||||
void handleProjectAction(
|
||||
BuildContext context, ProjectEntity project, EntityAction action) {
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
final state = store.state;
|
||||
final CompanyEntity company = state.selectedCompany;
|
||||
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
store.dispatch(EditProject(context: context, project: project));
|
||||
break;
|
||||
case EntityAction.newInvoice:
|
||||
final items =
|
||||
convertProjectToInvoiceItem(project: project, context: context);
|
||||
store.dispatch(EditInvoice(
|
||||
invoice: InvoiceEntity(company: company).rebuild((b) => b
|
||||
..hasTasks = true
|
||||
..clientId = project.clientId
|
||||
..invoiceItems.addAll(items)),
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.clone:
|
||||
store.dispatch(EditProject(context: context, project: project.clone));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreProjectRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).restoredProject),
|
||||
project.id));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveProjectRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).archivedProject),
|
||||
project.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteProjectRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).deletedProject),
|
||||
project.id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/utils/pdf.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ViewQuoteList implements PersistUI {
|
||||
ViewQuoteList(this.context);
|
||||
|
|
@ -322,3 +329,65 @@ class ConvertQuoteFailure implements StopSaving {
|
|||
|
||||
final dynamic error;
|
||||
}
|
||||
|
||||
Future handleQuoteAction(
|
||||
BuildContext context, InvoiceEntity quote, EntityAction action) async {
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
final localization = AppLocalization.of(context);
|
||||
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
store.dispatch(EditQuote(context: context, quote: quote));
|
||||
break;
|
||||
case EntityAction.pdf:
|
||||
viewPdf(quote, context);
|
||||
break;
|
||||
case EntityAction.clientPortal:
|
||||
if (await canLaunch(quote.invitationSilentLink)) {
|
||||
await launch(quote.invitationSilentLink,
|
||||
forceSafariVC: false, forceWebView: false);
|
||||
}
|
||||
break;
|
||||
case EntityAction.viewInvoice:
|
||||
store.dispatch(
|
||||
ViewInvoice(context: context, invoiceId: quote.quoteInvoiceId));
|
||||
break;
|
||||
case EntityAction.convert:
|
||||
final Completer<InvoiceEntity> completer = Completer<InvoiceEntity>();
|
||||
store.dispatch(ConvertQuote(completer, quote.id));
|
||||
completer.future.then((InvoiceEntity invoice) {
|
||||
store.dispatch(ViewInvoice(invoiceId: invoice.id, context: context));
|
||||
});
|
||||
break;
|
||||
case EntityAction.markSent:
|
||||
store.dispatch(MarkSentQuoteRequest(
|
||||
snackBarCompleter(context, localization.markedQuoteAsSent),
|
||||
quote.id));
|
||||
break;
|
||||
case EntityAction.sendEmail:
|
||||
store.dispatch(ShowEmailQuote(
|
||||
completer: snackBarCompleter(context, localization.emailedQuote),
|
||||
quote: quote,
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.cloneToInvoice:
|
||||
store.dispatch(
|
||||
EditInvoice(context: context, invoice: quote.cloneToInvoice));
|
||||
break;
|
||||
case EntityAction.cloneToQuote:
|
||||
store.dispatch(EditQuote(context: context, quote: quote.cloneToQuote));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreQuoteRequest(
|
||||
snackBarCompleter(context, localization.restoredQuote), quote.id));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveQuoteRequest(
|
||||
snackBarCompleter(context, localization.archivedQuote), quote.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteQuoteRequest(
|
||||
snackBarCompleter(context, localization.deletedQuote), quote.id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,15 @@ import 'package:flutter/widgets.dart';
|
|||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja_flutter/redux/task/task_selectors.dart';
|
||||
|
||||
class ViewTaskList implements PersistUI {
|
||||
ViewTaskList(this.context);
|
||||
|
|
@ -259,3 +268,73 @@ class FilterTasksByEntity implements PersistUI {
|
|||
final int entityId;
|
||||
final EntityType entityType;
|
||||
}
|
||||
|
||||
void handleTaskAction(
|
||||
BuildContext context, TaskEntity task, EntityAction action) {
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
final state = store.state;
|
||||
final CompanyEntity company = state.selectedCompany;
|
||||
final localization = AppLocalization.of(context);
|
||||
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
store.dispatch(EditTask(context: context, task: task));
|
||||
break;
|
||||
case EntityAction.start:
|
||||
case EntityAction.stop:
|
||||
case EntityAction.resume:
|
||||
final Completer<TaskEntity> completer = new Completer<TaskEntity>();
|
||||
final localization = AppLocalization.of(context);
|
||||
store
|
||||
.dispatch(SaveTaskRequest(completer: completer, task: task.toggle()));
|
||||
completer.future.then((savedTask) {
|
||||
Scaffold.of(context).showSnackBar(SnackBar(
|
||||
content: SnackBarRow(
|
||||
message: savedTask.isRunning
|
||||
? (savedTask.duration > 0
|
||||
? localization.resumedTask
|
||||
: localization.startedTask)
|
||||
: localization.stoppedTask,
|
||||
)));
|
||||
}).catchError((Object error) {
|
||||
showDialog<ErrorDialog>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return ErrorDialog(error);
|
||||
});
|
||||
});
|
||||
|
||||
break;
|
||||
case EntityAction.newInvoice:
|
||||
final item = convertTaskToInvoiceItem(task: task, context: context);
|
||||
store.dispatch(EditInvoice(
|
||||
invoice:
|
||||
InvoiceEntity(company: company).rebuild((b) => b
|
||||
..hasTasks = true
|
||||
..clientId = task.clientId
|
||||
..invoiceItems.add(item)),
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.viewInvoice:
|
||||
store.dispatch(ViewInvoice(invoiceId: task.invoiceId, context: context));
|
||||
break;
|
||||
case EntityAction.clone:
|
||||
store.dispatch(EditTask(context: context, task: task.clone));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreTaskRequest(
|
||||
snackBarCompleter(context, localization.restoredTask),
|
||||
task.id));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveTaskRequest(
|
||||
snackBarCompleter(context, localization.archivedTask),
|
||||
task.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteTaskRequest(
|
||||
snackBarCompleter(context, localization.deletedTask),
|
||||
task.id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,11 @@ import 'package:flutter/widgets.dart';
|
|||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/redux/expense/expense_actions.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
|
||||
class ViewVendorList implements PersistUI {
|
||||
ViewVendorList(this.context);
|
||||
|
|
@ -251,3 +256,34 @@ class FilterVendorsByEntity implements PersistUI {
|
|||
final int entityId;
|
||||
final EntityType entityType;
|
||||
}
|
||||
|
||||
void handleVendorAction(
|
||||
BuildContext context, VendorEntity vendor, EntityAction action) {
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
final state = store.state;
|
||||
final CompanyEntity company = state.selectedCompany;
|
||||
final localization = AppLocalization.of(context);
|
||||
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
store.dispatch(EditVendor(context: context, vendor: vendor));
|
||||
break;
|
||||
case EntityAction.newExpense:
|
||||
store.dispatch(EditExpense(
|
||||
expense: ExpenseEntity(company: company, vendor: vendor),
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreVendorRequest(
|
||||
snackBarCompleter(context, localization.restoredVendor), vendor.id));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveVendorRequest(
|
||||
snackBarCompleter(context, localization.archivedVendor), vendor.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteVendorRequest(
|
||||
snackBarCompleter(context, localization.deletedVendor), vendor.id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,27 +47,26 @@ class ClientList extends StatelessWidget {
|
|||
final clientId = viewModel.clientList[index];
|
||||
final client = viewModel.clientMap[clientId];
|
||||
final user = viewModel.user;
|
||||
|
||||
void showDialog() => showEntityActionsDialog(
|
||||
entity: client,
|
||||
context: context,
|
||||
user: user,
|
||||
onEntityAction: viewModel.onEntityAction);
|
||||
|
||||
return ClientListItem(
|
||||
user: viewModel.user,
|
||||
filter: viewModel.filter,
|
||||
client: client,
|
||||
onEntityAction: (EntityAction action) {
|
||||
if (action == EntityAction.more) {
|
||||
showEntityActionsDialog(
|
||||
entity: client,
|
||||
context: context,
|
||||
user: user,
|
||||
onEntityAction: viewModel.onEntityAction);
|
||||
showDialog();
|
||||
} else {
|
||||
viewModel.onEntityAction(context, client, action);
|
||||
}
|
||||
},
|
||||
onTap: () => viewModel.onClientTap(context, client),
|
||||
onLongPress: () => showEntityActionsDialog(
|
||||
entity: client,
|
||||
context: context,
|
||||
user: user,
|
||||
onEntityAction: viewModel.onEntityAction),
|
||||
onLongPress: () => showDialog(),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -59,11 +59,13 @@ class ClientListItem extends StatelessWidget {
|
|||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
filterMatch != null ? Text(
|
||||
filterMatch != null
|
||||
? Text(
|
||||
filterMatch,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
) : SizedBox(),
|
||||
)
|
||||
: SizedBox(),
|
||||
EntityStateLabel(client),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ class _CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||
user: viewModel.company.user,
|
||||
isSaving: viewModel.isSaving,
|
||||
entity: client,
|
||||
onSelected: viewModel.onActionSelected,
|
||||
onSelected: viewModel.onEntityAction,
|
||||
entityActions: viewModel.client.getActions(user: user),
|
||||
)
|
||||
],
|
||||
|
|
|
|||
|
|
@ -145,8 +145,8 @@ class ClientOverview extends StatelessWidget {
|
|||
title: localization.expenses,
|
||||
onTap: () =>
|
||||
viewModel.onEntityPressed(context, EntityType.expense),
|
||||
onLongPress: () =>
|
||||
viewModel.onEntityPressed(context, EntityType.expense, true),
|
||||
onLongPress: () => viewModel.onEntityPressed(
|
||||
context, EntityType.expense, true),
|
||||
subtitle: memoizedExpenseStatsForClient(
|
||||
client.id,
|
||||
state.expenseState.map,
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class ClientViewVM {
|
|||
ClientViewVM({
|
||||
@required this.client,
|
||||
@required this.company,
|
||||
@required this.onActionSelected,
|
||||
@required this.onEntityAction,
|
||||
@required this.onEntityPressed,
|
||||
@required this.onEditPressed,
|
||||
@required this.onBackPressed,
|
||||
|
|
@ -173,14 +173,14 @@ class ClientViewVM {
|
|||
store.dispatch(UpdateCurrentRoute(ClientScreen.route));
|
||||
}
|
||||
},
|
||||
onActionSelected: (BuildContext context, EntityAction action) =>
|
||||
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||
handleClientAction(context, client, action),
|
||||
);
|
||||
}
|
||||
|
||||
final ClientEntity client;
|
||||
final CompanyEntity company;
|
||||
final Function(BuildContext, EntityAction) onActionSelected;
|
||||
final Function(BuildContext, EntityAction) onEntityAction;
|
||||
final Function(BuildContext) onEditPressed;
|
||||
final Function onBackPressed;
|
||||
final Function(BuildContext, EntityType, [bool]) onEntityPressed;
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ class ExpenseEditDocumentsState extends State<ExpenseEditDocuments> {
|
|||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
final List<TextEditingController> _controllers = [
|
||||
];
|
||||
final List<TextEditingController> _controllers = [];
|
||||
|
||||
_controllers
|
||||
.forEach((dynamic controller) => controller.removeListener(_onChanged));
|
||||
|
|
@ -71,8 +70,7 @@ class ExpenseEditDocumentsState extends State<ExpenseEditDocuments> {
|
|||
viewModel.onChanged(
|
||||
expense.rebuild((b) => b..invoiceDocuments = value));
|
||||
viewModel.onAddDocumentsChanged(value);
|
||||
}
|
||||
)
|
||||
})
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
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/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||
|
|
@ -17,41 +18,6 @@ class ExpenseList extends StatelessWidget {
|
|||
|
||||
final ExpenseListVM viewModel;
|
||||
|
||||
void _showMenu(BuildContext context, ExpenseEntity expense) async {
|
||||
if (expense == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final user = viewModel.user;
|
||||
final message = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (BuildContext dialogContext) => SimpleDialog(
|
||||
children: expense
|
||||
.getActions(user: user, includeEdit: true)
|
||||
.map((entityAction) {
|
||||
if (entityAction == null) {
|
||||
return Divider();
|
||||
} else {
|
||||
return ListTile(
|
||||
leading: Icon(getEntityActionIcon(entityAction)),
|
||||
title: Text(AppLocalization.of(context)
|
||||
.lookup(entityAction.toString())),
|
||||
onTap: () {
|
||||
Navigator.of(dialogContext).pop();
|
||||
viewModel.onEntityAction(context, expense, entityAction);
|
||||
},
|
||||
);
|
||||
}
|
||||
}).toList()));
|
||||
|
||||
if (message != null) {
|
||||
Scaffold.of(context).showSnackBar(SnackBar(
|
||||
content: SnackBarRow(
|
||||
message: message,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localization = AppLocalization.of(context);
|
||||
|
|
@ -119,12 +85,21 @@ class ExpenseList extends StatelessWidget {
|
|||
separatorBuilder: (context, index) => ListDivider(),
|
||||
itemCount: viewModel.expenseList.length,
|
||||
itemBuilder: (BuildContext context, index) {
|
||||
final user = viewModel.user;
|
||||
final expenseId = viewModel.expenseList[index];
|
||||
final expense = viewModel.expenseMap[expenseId];
|
||||
final client =
|
||||
viewModel.state.clientState.map[expense.clientId];
|
||||
final vendor =
|
||||
viewModel.state.vendorState.map[expense.vendorId];
|
||||
|
||||
void showDialog() => showEntityActionsDialog(
|
||||
entity: expense,
|
||||
context: context,
|
||||
user: user,
|
||||
client: client,
|
||||
onEntityAction: viewModel.onEntityAction);
|
||||
|
||||
return ExpenseListItem(
|
||||
user: viewModel.user,
|
||||
filter: viewModel.filter,
|
||||
|
|
@ -134,13 +109,13 @@ class ExpenseList extends StatelessWidget {
|
|||
onTap: () => viewModel.onExpenseTap(context, expense),
|
||||
onEntityAction: (EntityAction action) {
|
||||
if (action == EntityAction.more) {
|
||||
_showMenu(context, expense);
|
||||
showDialog();
|
||||
} else {
|
||||
viewModel.onEntityAction(
|
||||
context, expense, action);
|
||||
}
|
||||
},
|
||||
onLongPress: () => _showMenu(context, expense),
|
||||
onLongPress: () => showDialog(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import 'dart:async';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -92,49 +91,9 @@ class ExpenseListVM {
|
|||
onExpenseTap: (context, expense) {
|
||||
store.dispatch(ViewExpense(expenseId: expense.id, context: context));
|
||||
},
|
||||
onEntityAction: (context, expense, action) {
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
store.dispatch(EditExpense(context: context, expense: expense));
|
||||
break;
|
||||
case EntityAction.clone:
|
||||
store.dispatch(
|
||||
EditExpense(context: context, expense: expense.clone));
|
||||
break;
|
||||
case EntityAction.newInvoice:
|
||||
final item = convertExpenseToInvoiceItem(expense: expense);
|
||||
store.dispatch(EditInvoice(
|
||||
invoice: InvoiceEntity(company: state.selectedCompany)
|
||||
.rebuild((b) => b
|
||||
..hasExpenses = true
|
||||
..clientId = expense.clientId
|
||||
..invoiceItems.add(item)),
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.viewInvoice:
|
||||
store.dispatch(
|
||||
ViewInvoice(invoiceId: expense.invoiceId, context: context));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreExpenseRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).restoredExpense),
|
||||
expense.id));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveExpenseRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).archivedExpense),
|
||||
expense.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteExpenseRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).deletedExpense),
|
||||
expense.id));
|
||||
break;
|
||||
}
|
||||
},
|
||||
onEntityAction:
|
||||
(BuildContext context, BaseEntity expense, EntityAction action) =>
|
||||
handleExpenseAction(context, expense, action),
|
||||
onRefreshed: (context) => _handleRefresh(context),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ class _CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||
user: viewModel.company.user,
|
||||
isSaving: viewModel.isSaving,
|
||||
entity: expense,
|
||||
onSelected: viewModel.onActionSelected,
|
||||
onSelected: viewModel.onEntityAction,
|
||||
entityActions: viewModel.expense.getActions(user: user),
|
||||
)
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/expense/expense_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||
|
|
@ -42,7 +41,7 @@ class ExpenseViewVM {
|
|||
@required this.state,
|
||||
@required this.expense,
|
||||
@required this.company,
|
||||
@required this.onActionSelected,
|
||||
@required this.onEntityAction,
|
||||
@required this.onEntityPressed,
|
||||
@required this.onEditPressed,
|
||||
@required this.onBackPressed,
|
||||
|
|
@ -120,50 +119,17 @@ class ExpenseViewVM {
|
|||
break;
|
||||
}
|
||||
},
|
||||
onActionSelected: (BuildContext context, EntityAction action) {
|
||||
final localization = AppLocalization.of(context);
|
||||
switch (action) {
|
||||
case EntityAction.clone:
|
||||
store.dispatch(
|
||||
EditExpense(context: context, expense: expense.clone));
|
||||
break;
|
||||
case EntityAction.newInvoice:
|
||||
final item = convertExpenseToInvoiceItem(expense: expense);
|
||||
store.dispatch(EditInvoice(
|
||||
invoice: InvoiceEntity(company: state.selectedCompany)
|
||||
.rebuild((b) => b
|
||||
..hasExpenses = true
|
||||
..clientId = expense.clientId
|
||||
..invoiceItems.add(item)),
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.viewInvoice:
|
||||
store.dispatch(
|
||||
ViewInvoice(invoiceId: expense.invoiceId, context: context));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveExpenseRequest(
|
||||
popCompleter(context, localization.archivedExpense),
|
||||
expense.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteExpenseRequest(
|
||||
popCompleter(context, localization.deletedExpense),
|
||||
expense.id));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreExpenseRequest(
|
||||
snackBarCompleter(context, localization.restoredExpense),
|
||||
expense.id));
|
||||
break;
|
||||
}
|
||||
});
|
||||
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||
handleExpenseAction(context, expense, action),
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
final AppState state;
|
||||
final ExpenseEntity expense;
|
||||
final CompanyEntity company;
|
||||
final Function(BuildContext, EntityAction) onActionSelected;
|
||||
final Function(BuildContext, EntityAction) onEntityAction;
|
||||
final Function(BuildContext, EntityType, [bool]) onEntityPressed;
|
||||
final Function(BuildContext) onEditPressed;
|
||||
final Function onBackPressed;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/invoice_model.dart';
|
||||
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/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.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/utils/icons.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
||||
class InvoiceList extends StatelessWidget {
|
||||
|
|
@ -18,43 +16,6 @@ class InvoiceList extends StatelessWidget {
|
|||
|
||||
final EntityListVM viewModel;
|
||||
|
||||
void _showMenu(
|
||||
BuildContext context, InvoiceEntity invoice, ClientEntity client) async {
|
||||
if (invoice == null || client == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final user = viewModel.user;
|
||||
final message = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (BuildContext dialogContext) => SimpleDialog(
|
||||
children: invoice
|
||||
.getActions(
|
||||
user: user, client: client, includeEdit: true)
|
||||
.map((entityAction) {
|
||||
if (entityAction == null) {
|
||||
return Divider();
|
||||
} else {
|
||||
return ListTile(
|
||||
leading: Icon(getEntityActionIcon(entityAction)),
|
||||
title: Text(AppLocalization.of(context)
|
||||
.lookup(entityAction.toString())),
|
||||
onTap: () {
|
||||
Navigator.of(dialogContext).pop();
|
||||
viewModel.onEntityAction(context, invoice, entityAction);
|
||||
},
|
||||
);
|
||||
}
|
||||
}).toList()));
|
||||
|
||||
if (message != null) {
|
||||
Scaffold.of(context).showSnackBar(SnackBar(
|
||||
content: SnackBarRow(
|
||||
message: message,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localization = AppLocalization.of(context);
|
||||
|
|
@ -117,11 +78,20 @@ class InvoiceList extends StatelessWidget {
|
|||
separatorBuilder: (context, index) => ListDivider(),
|
||||
itemCount: viewModel.invoiceList.length,
|
||||
itemBuilder: (BuildContext context, index) {
|
||||
final user = viewModel.user;
|
||||
final invoiceId = viewModel.invoiceList[index];
|
||||
final invoice = viewModel.invoiceMap[invoiceId];
|
||||
final client =
|
||||
viewModel.clientMap[invoice.clientId] ??
|
||||
ClientEntity();
|
||||
|
||||
void showDialog() => showEntityActionsDialog(
|
||||
entity: invoice,
|
||||
context: context,
|
||||
user: user,
|
||||
client: client,
|
||||
onEntityAction: viewModel.onEntityAction);
|
||||
|
||||
return InvoiceListItem(
|
||||
user: viewModel.user,
|
||||
filter: viewModel.filter,
|
||||
|
|
@ -132,14 +102,13 @@ class InvoiceList extends StatelessWidget {
|
|||
viewModel.onInvoiceTap(context, invoice),
|
||||
onEntityAction: (EntityAction action) {
|
||||
if (action == EntityAction.more) {
|
||||
_showMenu(context, invoice, client);
|
||||
showDialog();
|
||||
} else {
|
||||
viewModel.onEntityAction(
|
||||
context, invoice, action);
|
||||
}
|
||||
},
|
||||
onLongPress: () =>
|
||||
_showMenu(context, invoice, client),
|
||||
onLongPress: () => showDialog(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -6,18 +6,14 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/payment/payment_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/utils/pdf.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_list.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class InvoiceListBuilder extends StatelessWidget {
|
||||
const InvoiceListBuilder({Key key}) : super(key: key);
|
||||
|
|
@ -136,63 +132,9 @@ class InvoiceListVM extends EntityListVM {
|
|||
ViewClient(
|
||||
clientId: state.invoiceListState.filterEntityId,
|
||||
context: context)),
|
||||
onEntityAction: (context, invoice, action) async {
|
||||
final localization = AppLocalization.of(context);
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
store.dispatch(EditInvoice(context: context, invoice: invoice));
|
||||
break;
|
||||
case EntityAction.pdf:
|
||||
viewPdf(invoice, context);
|
||||
break;
|
||||
case EntityAction.clientPortal:
|
||||
if (await canLaunch(invoice.invitationSilentLink)) {
|
||||
await launch(invoice.invitationSilentLink,
|
||||
forceSafariVC: false, forceWebView: false);
|
||||
}
|
||||
break;
|
||||
case EntityAction.markSent:
|
||||
store.dispatch(MarkSentInvoiceRequest(
|
||||
snackBarCompleter(context, localization.markedInvoiceAsSent),
|
||||
invoice.id));
|
||||
break;
|
||||
case EntityAction.sendEmail:
|
||||
store.dispatch(ShowEmailInvoice(
|
||||
completer:
|
||||
snackBarCompleter(context, localization.emailedInvoice),
|
||||
invoice: invoice,
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.cloneToInvoice:
|
||||
store.dispatch(
|
||||
EditInvoice(context: context, invoice: invoice.cloneToInvoice));
|
||||
break;
|
||||
case EntityAction.cloneToQuote:
|
||||
store.dispatch(
|
||||
EditQuote(context: context, quote: invoice.cloneToQuote));
|
||||
break;
|
||||
case EntityAction.enterPayment:
|
||||
store.dispatch(EditPayment(
|
||||
context: context,
|
||||
payment: invoice.createPayment(state.selectedCompany)));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreInvoiceRequest(
|
||||
snackBarCompleter(context, localization.restoredInvoice),
|
||||
invoice.id));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveInvoiceRequest(
|
||||
snackBarCompleter(context, localization.archivedInvoice),
|
||||
invoice.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteInvoiceRequest(
|
||||
snackBarCompleter(context, localization.deletedInvoice),
|
||||
invoice.id));
|
||||
break;
|
||||
}
|
||||
},
|
||||
onEntityAction:
|
||||
(BuildContext context, BaseEntity invoice, EntityAction action) =>
|
||||
handleInvoiceAction(context, invoice, action),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -309,8 +309,7 @@ class _CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||
: Container(),
|
||||
ActionMenuButton(
|
||||
user: user,
|
||||
entityActions:
|
||||
invoice.getActions(client: client, user: user),
|
||||
entityActions: invoice.getActions(client: client, user: user),
|
||||
isSaving: viewModel.isSaving,
|
||||
entity: invoice,
|
||||
onSelected: viewModel.onActionSelected,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'package:invoiceninja_flutter/redux/payment/payment_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
|
@ -11,13 +10,11 @@ import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
|||
import 'package:invoiceninja_flutter/ui/invoice/invoice_screen.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/utils/pdf.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class InvoiceViewScreen extends StatelessWidget {
|
||||
const InvoiceViewScreen({Key key}) : super(key: key);
|
||||
|
|
@ -93,7 +90,7 @@ class InvoiceViewVM extends EntityViewVM {
|
|||
ClientEntity client,
|
||||
bool isSaving,
|
||||
bool isDirty,
|
||||
Function(BuildContext, EntityAction) onActionSelected,
|
||||
Function(BuildContext, EntityAction) onEntityAction,
|
||||
Function(BuildContext, [InvoiceItemEntity]) onEditPressed,
|
||||
Function(BuildContext, [bool]) onClientPressed,
|
||||
Function(BuildContext, PaymentEntity, [bool]) onPaymentPressed,
|
||||
|
|
@ -106,7 +103,7 @@ class InvoiceViewVM extends EntityViewVM {
|
|||
client: client,
|
||||
isSaving: isSaving,
|
||||
isDirty: isDirty,
|
||||
onActionSelected: onActionSelected,
|
||||
onActionSelected: onEntityAction,
|
||||
onEditPressed: onEditPressed,
|
||||
onClientPressed: onClientPressed,
|
||||
onPaymentPressed: onPaymentPressed,
|
||||
|
|
@ -179,61 +176,8 @@ class InvoiceViewVM extends EntityViewVM {
|
|||
entityId: invoice.id, entityType: EntityType.invoice));
|
||||
store.dispatch(ViewPaymentList(context));
|
||||
},
|
||||
onActionSelected: (BuildContext context, EntityAction action) async {
|
||||
final localization = AppLocalization.of(context);
|
||||
switch (action) {
|
||||
case EntityAction.pdf:
|
||||
viewPdf(invoice, context);
|
||||
break;
|
||||
case EntityAction.clientPortal:
|
||||
if (await canLaunch(invoice.invitationSilentLink)) {
|
||||
await launch(invoice.invitationSilentLink,
|
||||
forceSafariVC: false, forceWebView: false);
|
||||
}
|
||||
break;
|
||||
case EntityAction.markSent:
|
||||
store.dispatch(MarkSentInvoiceRequest(
|
||||
snackBarCompleter(context, localization.markedInvoiceAsSent),
|
||||
invoice.id));
|
||||
break;
|
||||
case EntityAction.sendEmail:
|
||||
store.dispatch(ShowEmailInvoice(
|
||||
completer:
|
||||
snackBarCompleter(context, localization.emailedInvoice),
|
||||
invoice: invoice,
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveInvoiceRequest(
|
||||
popCompleter(context, localization.archivedInvoice),
|
||||
invoice.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteInvoiceRequest(
|
||||
popCompleter(context, localization.deletedInvoice),
|
||||
invoice.id));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreInvoiceRequest(
|
||||
snackBarCompleter(context, localization.restoredInvoice),
|
||||
invoice.id));
|
||||
break;
|
||||
case EntityAction.cloneToInvoice:
|
||||
Navigator.of(context).pop();
|
||||
store.dispatch(EditInvoice(
|
||||
context: context, invoice: invoice.cloneToInvoice));
|
||||
break;
|
||||
case EntityAction.cloneToQuote:
|
||||
Navigator.of(context).pop();
|
||||
store.dispatch(
|
||||
EditQuote(context: context, quote: invoice.cloneToQuote));
|
||||
break;
|
||||
case EntityAction.enterPayment:
|
||||
store.dispatch(EditPayment(
|
||||
context: context,
|
||||
payment: invoice.createPayment(state.selectedCompany)));
|
||||
break;
|
||||
}
|
||||
});
|
||||
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||
handleInvoiceAction(context, invoice, action),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/payment_model.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
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/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.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/utils/icons.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
||||
class PaymentList extends StatelessWidget {
|
||||
|
|
@ -21,43 +19,6 @@ class PaymentList extends StatelessWidget {
|
|||
|
||||
final PaymentListVM viewModel;
|
||||
|
||||
void _showMenu(
|
||||
BuildContext context, PaymentEntity payment, ClientEntity client) async {
|
||||
if (payment == null || client == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final user = viewModel.user;
|
||||
final message = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (BuildContext dialogContext) => SimpleDialog(
|
||||
children: payment
|
||||
.getActions(
|
||||
user: user, client: client, includeEdit: true)
|
||||
.map((entityAction) {
|
||||
if (entityAction == null) {
|
||||
return Divider();
|
||||
} else {
|
||||
return ListTile(
|
||||
leading: Icon(getEntityActionIcon(entityAction)),
|
||||
title: Text(AppLocalization.of(context)
|
||||
.lookup(entityAction.toString())),
|
||||
onTap: () {
|
||||
Navigator.of(dialogContext).pop();
|
||||
viewModel.onEntityAction(context, payment, entityAction);
|
||||
},
|
||||
);
|
||||
}
|
||||
}).toList()));
|
||||
|
||||
if (message != null) {
|
||||
Scaffold.of(context).showSnackBar(SnackBar(
|
||||
content: SnackBarRow(
|
||||
message: message,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localization = AppLocalization.of(context);
|
||||
|
|
@ -134,10 +95,19 @@ class PaymentList extends StatelessWidget {
|
|||
separatorBuilder: (context, index) => ListDivider(),
|
||||
itemCount: viewModel.paymentList.length,
|
||||
itemBuilder: (BuildContext context, index) {
|
||||
final user = viewModel.user;
|
||||
final paymentId = viewModel.paymentList[index];
|
||||
final payment = state.paymentState.map[paymentId];
|
||||
final client =
|
||||
paymentClientSelector(paymentId, state);
|
||||
|
||||
void showDialog() => showEntityActionsDialog(
|
||||
entity: payment,
|
||||
context: context,
|
||||
user: user,
|
||||
client: client,
|
||||
onEntityAction: viewModel.onEntityAction);
|
||||
|
||||
return PaymentListItem(
|
||||
user: viewModel.user,
|
||||
filter: viewModel.filter,
|
||||
|
|
@ -146,14 +116,13 @@ class PaymentList extends StatelessWidget {
|
|||
viewModel.onPaymentTap(context, payment),
|
||||
onEntityAction: (EntityAction action) {
|
||||
if (action == EntityAction.more) {
|
||||
_showMenu(context, payment, client);
|
||||
showDialog();
|
||||
} else {
|
||||
viewModel.onEntityAction(
|
||||
context, payment, action);
|
||||
}
|
||||
},
|
||||
onLongPress: () =>
|
||||
_showMenu(context, payment, client),
|
||||
onLongPress: () => showDialog(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -79,34 +79,9 @@ class PaymentListVM {
|
|||
onPaymentTap: (context, payment) {
|
||||
store.dispatch(ViewPayment(paymentId: payment.id, context: context));
|
||||
},
|
||||
onEntityAction: (context, payment, action) {
|
||||
final localization = AppLocalization.of(context);
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
store.dispatch(EditPayment(context: context, payment: payment));
|
||||
break;
|
||||
case EntityAction.sendEmail:
|
||||
store.dispatch(EmailPaymentRequest(
|
||||
snackBarCompleter(context, localization.emailedPayment),
|
||||
payment));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestorePaymentRequest(
|
||||
snackBarCompleter(context, localization.restoredPayment),
|
||||
payment.id));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchivePaymentRequest(
|
||||
snackBarCompleter(context, localization.archivedPayment),
|
||||
payment.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeletePaymentRequest(
|
||||
snackBarCompleter(context, localization.deletedPayment),
|
||||
payment.id));
|
||||
break;
|
||||
}
|
||||
},
|
||||
onEntityAction:
|
||||
(BuildContext context, BaseEntity payment, EntityAction action) =>
|
||||
handlePaymentAction(context, payment, action),
|
||||
onClearEntityFilterPressed: () =>
|
||||
store.dispatch(FilterPaymentsByEntity()),
|
||||
onViewClientFilterPressed: (BuildContext context) {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class _PaymentViewState extends State<PaymentView> {
|
|||
user: viewModel.company.user,
|
||||
isSaving: viewModel.isSaving,
|
||||
entity: payment,
|
||||
onSelected: viewModel.onActionSelected,
|
||||
onSelected: viewModel.onEntityAction,
|
||||
entityActions: viewModel.payment.getActions(
|
||||
user: viewModel.company.user, client: client),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ import 'package:flutter/material.dart';
|
|||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/payment/payment_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/payment/payment_actions.dart';
|
||||
|
|
@ -37,7 +35,7 @@ class PaymentViewVM {
|
|||
PaymentViewVM({
|
||||
@required this.payment,
|
||||
@required this.company,
|
||||
@required this.onActionSelected,
|
||||
@required this.onEntityAction,
|
||||
@required this.onEditPressed,
|
||||
@required this.onClientPressed,
|
||||
@required this.onInvoicePressed,
|
||||
|
|
@ -71,35 +69,14 @@ class PaymentViewVM {
|
|||
invoice: state.invoiceState.map[payment.invoiceId],
|
||||
context: context)
|
||||
: ViewInvoice(invoiceId: payment.invoiceId, context: context)),
|
||||
onActionSelected: (BuildContext context, EntityAction action) {
|
||||
final localization = AppLocalization.of(context);
|
||||
switch (action) {
|
||||
case EntityAction.sendEmail:
|
||||
store.dispatch(EmailPaymentRequest(
|
||||
popCompleter(context, localization.emailedPayment), payment));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchivePaymentRequest(
|
||||
popCompleter(context, localization.archivedClient),
|
||||
payment.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeletePaymentRequest(
|
||||
popCompleter(context, localization.deletedClient),
|
||||
payment.id));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestorePaymentRequest(
|
||||
snackBarCompleter(context, localization.restoredClient),
|
||||
payment.id));
|
||||
break;
|
||||
}
|
||||
});
|
||||
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||
handlePaymentAction(context, payment, action),
|
||||
);
|
||||
}
|
||||
|
||||
final PaymentEntity payment;
|
||||
final CompanyEntity company;
|
||||
final Function(BuildContext, EntityAction) onActionSelected;
|
||||
final Function(BuildContext, EntityAction) onEntityAction;
|
||||
final Function(BuildContext) onEditPressed;
|
||||
final Function(BuildContext, [bool]) onInvoicePressed;
|
||||
final Function(BuildContext, [bool]) onClientPressed;
|
||||
|
|
|
|||
|
|
@ -71,8 +71,18 @@ class ProductEditVM {
|
|||
: AppLocalization.of(context).updatedProduct),
|
||||
product: product));
|
||||
},
|
||||
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||
handleProductAction(context, product, action),
|
||||
onEntityAction: (BuildContext context, EntityAction action) {
|
||||
// TODO Add view page for products
|
||||
// Prevent duplicate global key error
|
||||
if (action == EntityAction.clone) {
|
||||
Navigator.pop(context);
|
||||
WidgetsBinding.instance.addPostFrameCallback((duration) {
|
||||
handleProductAction(context, product, action);
|
||||
});
|
||||
} else {
|
||||
handleProductAction(context, product, action);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,27 +46,26 @@ class ProductList extends StatelessWidget {
|
|||
itemBuilder: (BuildContext context, index) {
|
||||
final productId = viewModel.productList[index];
|
||||
final product = viewModel.productMap[productId];
|
||||
|
||||
void showDialog() => showEntityActionsDialog(
|
||||
entity: product,
|
||||
context: context,
|
||||
user: viewModel.user,
|
||||
onEntityAction: viewModel.onEntityAction);
|
||||
|
||||
return ProductListItem(
|
||||
user: viewModel.user,
|
||||
filter: viewModel.filter,
|
||||
product: product,
|
||||
onEntityAction: (EntityAction action) {
|
||||
if (action == EntityAction.more) {
|
||||
showEntityActionsDialog(
|
||||
entity: product,
|
||||
context: context,
|
||||
user: viewModel.user,
|
||||
onEntityAction: viewModel.onEntityAction);
|
||||
showDialog();
|
||||
} else {
|
||||
viewModel.onEntityAction(context, product, action);
|
||||
}
|
||||
},
|
||||
onTap: () => viewModel.onProductTap(context, product),
|
||||
onLongPress: () => showEntityActionsDialog(
|
||||
entity: product,
|
||||
context: context,
|
||||
user: viewModel.user,
|
||||
onEntityAction: viewModel.onEntityAction),
|
||||
onLongPress: () => showDialog(),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
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/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||
|
|
@ -17,43 +18,6 @@ class ProjectList extends StatelessWidget {
|
|||
|
||||
final ProjectListVM viewModel;
|
||||
|
||||
void _showMenu(
|
||||
BuildContext context, ProjectEntity project, ClientEntity client) async {
|
||||
if (project == null || client == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final user = viewModel.user;
|
||||
final message = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (BuildContext dialogContext) => SimpleDialog(
|
||||
children: project
|
||||
.getActions(
|
||||
user: user, client: client, includeEdit: true)
|
||||
.map((entityAction) {
|
||||
if (entityAction == null) {
|
||||
return Divider();
|
||||
} else {
|
||||
return ListTile(
|
||||
leading: Icon(getEntityActionIcon(entityAction)),
|
||||
title: Text(AppLocalization.of(context)
|
||||
.lookup(entityAction.toString())),
|
||||
onTap: () {
|
||||
Navigator.of(dialogContext).pop();
|
||||
viewModel.onEntityAction(context, project, entityAction);
|
||||
},
|
||||
);
|
||||
}
|
||||
}).toList()));
|
||||
|
||||
if (message != null) {
|
||||
Scaffold.of(context).showSnackBar(SnackBar(
|
||||
content: SnackBarRow(
|
||||
message: message,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localization = AppLocalization.of(context);
|
||||
|
|
@ -116,30 +80,37 @@ class ProjectList extends StatelessWidget {
|
|||
separatorBuilder: (context, index) => ListDivider(),
|
||||
itemCount: viewModel.projectList.length,
|
||||
itemBuilder: (BuildContext context, index) {
|
||||
final user = viewModel.user;
|
||||
final projectId = viewModel.projectList[index];
|
||||
final project = viewModel.projectMap[projectId];
|
||||
final client =
|
||||
viewModel.clientMap[project.clientId] ??
|
||||
ClientEntity(id: project.clientId);
|
||||
|
||||
void showDialog() => showEntityActionsDialog(
|
||||
entity: project,
|
||||
context: context,
|
||||
user: user,
|
||||
client: client,
|
||||
onEntityAction: viewModel.onEntityAction);
|
||||
|
||||
return ProjectListItem(
|
||||
user: viewModel.user,
|
||||
filter: viewModel.filter,
|
||||
project: project,
|
||||
client:
|
||||
viewModel.clientMap[project.clientId] ??
|
||||
client: viewModel.clientMap[project.clientId] ??
|
||||
ClientEntity(),
|
||||
onTap: () =>
|
||||
viewModel.onProjectTap(context, project),
|
||||
onEntityAction: (EntityAction action) {
|
||||
if (action == EntityAction.more) {
|
||||
_showMenu(context, project, client);
|
||||
showDialog();
|
||||
} else {
|
||||
viewModel.onEntityAction(
|
||||
context, project, action);
|
||||
}
|
||||
},
|
||||
onLongPress: () =>
|
||||
_showMenu(context, project, client),
|
||||
onLongPress: () => showDialog(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -84,46 +83,9 @@ class ProjectListVM {
|
|||
onProjectTap: (context, project) {
|
||||
store.dispatch(ViewProject(projectId: project.id, context: context));
|
||||
},
|
||||
onEntityAction: (context, project, action) {
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
store.dispatch(EditProject(context: context, project: project));
|
||||
break;
|
||||
case EntityAction.newInvoice:
|
||||
final items =
|
||||
convertProjectToInvoiceItem(project: project, context: context);
|
||||
store.dispatch(EditInvoice(
|
||||
invoice: InvoiceEntity(company: state.selectedCompany)
|
||||
.rebuild((b) => b
|
||||
..hasTasks = true
|
||||
..clientId = project.clientId
|
||||
..invoiceItems.addAll(items)),
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.clone:
|
||||
store.dispatch(
|
||||
EditProject(context: context, project: project.clone));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreProjectRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).restoredProject),
|
||||
project.id));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveProjectRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).archivedProject),
|
||||
project.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteProjectRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).deletedProject),
|
||||
project.id));
|
||||
break;
|
||||
}
|
||||
},
|
||||
onEntityAction:
|
||||
(BuildContext context, BaseEntity project, EntityAction action) =>
|
||||
handleProjectAction(context, project, action),
|
||||
onRefreshed: (context) => _handleRefresh(context),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,11 +187,11 @@ class _CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||
: Container(),
|
||||
ActionMenuButton(
|
||||
user: user,
|
||||
entityActions: project.getActions(
|
||||
client: viewModel.client, user: user),
|
||||
entityActions:
|
||||
project.getActions(client: viewModel.client, user: user),
|
||||
isSaving: viewModel.isSaving,
|
||||
entity: project,
|
||||
onSelected: viewModel.onActionSelected,
|
||||
onSelected: viewModel.onEntityAction,
|
||||
)
|
||||
],
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/project/project_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/redux/task/task_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||
import 'package:invoiceninja_flutter/ui/project/project_screen.dart';
|
||||
|
|
@ -41,7 +39,7 @@ class ProjectViewVM {
|
|||
@required this.project,
|
||||
@required this.client,
|
||||
@required this.company,
|
||||
@required this.onActionSelected,
|
||||
@required this.onEntityAction,
|
||||
@required this.onTasksPressed,
|
||||
@required this.onEditPressed,
|
||||
@required this.onBackPressed,
|
||||
|
|
@ -99,48 +97,17 @@ class ProjectViewVM {
|
|||
store.dispatch(UpdateCurrentRoute(ProjectScreen.route));
|
||||
}
|
||||
},
|
||||
onActionSelected: (BuildContext context, EntityAction action) {
|
||||
final localization = AppLocalization.of(context);
|
||||
switch (action) {
|
||||
case EntityAction.newInvoice:
|
||||
final items = convertProjectToInvoiceItem(
|
||||
project: project, context: context);
|
||||
store.dispatch(EditInvoice(
|
||||
invoice: InvoiceEntity(company: state.selectedCompany)
|
||||
.rebuild((b) => b
|
||||
..hasTasks = true
|
||||
..clientId = project.clientId
|
||||
..invoiceItems.addAll(items)),
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.clone:
|
||||
store.dispatch(
|
||||
EditProject(context: context, project: project.clone));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveProjectRequest(
|
||||
popCompleter(context, localization.archivedProject),
|
||||
project.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteProjectRequest(
|
||||
popCompleter(context, localization.deletedProject),
|
||||
project.id));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreProjectRequest(
|
||||
snackBarCompleter(context, localization.restoredProject),
|
||||
project.id));
|
||||
break;
|
||||
}
|
||||
});
|
||||
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||
handleProjectAction(context, project, action),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
final AppState state;
|
||||
final ProjectEntity project;
|
||||
final ClientEntity client;
|
||||
final CompanyEntity company;
|
||||
final Function(BuildContext, EntityAction) onActionSelected;
|
||||
final Function(BuildContext, EntityAction) onEntityAction;
|
||||
final Function(BuildContext) onEditPressed;
|
||||
final Function(BuildContext, [bool]) onClientPressed;
|
||||
final Function onBackPressed;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/quote/quote_selectors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -13,11 +12,9 @@ import 'package:invoiceninja_flutter/ui/invoice/invoice_list.dart';
|
|||
import 'package:invoiceninja_flutter/ui/invoice/invoice_list_vm.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/utils/pdf.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class QuoteListBuilder extends StatelessWidget {
|
||||
const QuoteListBuilder({Key key}) : super(key: key);
|
||||
|
|
@ -99,71 +96,9 @@ class QuoteListVM extends EntityListVM {
|
|||
onViewEntityFilterPressed: (BuildContext context) => store.dispatch(
|
||||
ViewClient(
|
||||
clientId: state.quoteListState.filterEntityId, context: context)),
|
||||
onEntityAction: (context, quote, action) async {
|
||||
final localization = AppLocalization.of(context);
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
store.dispatch(EditQuote(context: context, quote: quote));
|
||||
break;
|
||||
case EntityAction.pdf:
|
||||
viewPdf(quote, context);
|
||||
break;
|
||||
case EntityAction.clientPortal:
|
||||
if (await canLaunch(quote.invitationSilentLink)) {
|
||||
await launch(quote.invitationSilentLink,
|
||||
forceSafariVC: false, forceWebView: false);
|
||||
}
|
||||
break;
|
||||
case EntityAction.viewInvoice:
|
||||
store.dispatch(
|
||||
ViewInvoice(context: context, invoiceId: quote.quoteInvoiceId));
|
||||
break;
|
||||
case EntityAction.convert:
|
||||
final Completer<InvoiceEntity> completer =
|
||||
Completer<InvoiceEntity>();
|
||||
store.dispatch(ConvertQuote(completer, quote.id));
|
||||
completer.future.then((InvoiceEntity invoice) {
|
||||
store.dispatch(
|
||||
ViewInvoice(invoiceId: invoice.id, context: context));
|
||||
});
|
||||
break;
|
||||
case EntityAction.markSent:
|
||||
store.dispatch(MarkSentQuoteRequest(
|
||||
snackBarCompleter(context, localization.markedQuoteAsSent),
|
||||
quote.id));
|
||||
break;
|
||||
case EntityAction.sendEmail:
|
||||
store.dispatch(ShowEmailQuote(
|
||||
completer:
|
||||
snackBarCompleter(context, localization.emailedQuote),
|
||||
quote: quote,
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.cloneToInvoice:
|
||||
store.dispatch(
|
||||
EditInvoice(context: context, invoice: quote.cloneToInvoice));
|
||||
break;
|
||||
case EntityAction.cloneToQuote:
|
||||
store.dispatch(
|
||||
EditQuote(context: context, quote: quote.cloneToQuote));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreQuoteRequest(
|
||||
snackBarCompleter(context, localization.restoredQuote),
|
||||
quote.id));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveQuoteRequest(
|
||||
snackBarCompleter(context, localization.archivedQuote),
|
||||
quote.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteQuoteRequest(
|
||||
snackBarCompleter(context, localization.deletedQuote),
|
||||
quote.id));
|
||||
break;
|
||||
}
|
||||
},
|
||||
onEntityAction:
|
||||
(BuildContext context, BaseEntity quote, EntityAction action) =>
|
||||
handleQuoteAction(context, quote, action),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,20 +3,17 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view_vm.dart';
|
||||
import 'package:invoiceninja_flutter/ui/quote/quote_screen.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/utils/pdf.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class QuoteViewScreen extends StatelessWidget {
|
||||
const QuoteViewScreen({Key key}) : super(key: key);
|
||||
|
|
@ -46,7 +43,7 @@ class QuoteViewVM extends EntityViewVM {
|
|||
ClientEntity client,
|
||||
bool isSaving,
|
||||
bool isDirty,
|
||||
Function(BuildContext, EntityAction) onActionSelected,
|
||||
Function(BuildContext, EntityAction) onEntityAction,
|
||||
Function(BuildContext, [InvoiceItemEntity]) onEditPressed,
|
||||
Function(BuildContext, [bool]) onClientPressed,
|
||||
Function(BuildContext) onPaymentsPressed,
|
||||
|
|
@ -59,7 +56,7 @@ class QuoteViewVM extends EntityViewVM {
|
|||
client: client,
|
||||
isSaving: isSaving,
|
||||
isDirty: isDirty,
|
||||
onActionSelected: onActionSelected,
|
||||
onActionSelected: onEntityAction,
|
||||
onEditPressed: onEditPressed,
|
||||
onClientPressed: onClientPressed,
|
||||
onPaymentsPressed: onPaymentsPressed,
|
||||
|
|
@ -113,67 +110,9 @@ class QuoteViewVM extends EntityViewVM {
|
|||
store.dispatch(longPress
|
||||
? EditClient(client: client, context: context)
|
||||
: ViewClient(clientId: client.id, context: context)),
|
||||
onActionSelected: (BuildContext context, EntityAction action) async {
|
||||
final localization = AppLocalization.of(context);
|
||||
switch (action) {
|
||||
case EntityAction.pdf:
|
||||
viewPdf(quote, context);
|
||||
break;
|
||||
case EntityAction.clientPortal:
|
||||
if (await canLaunch(quote.invitationSilentLink)) {
|
||||
await launch(quote.invitationSilentLink,
|
||||
forceSafariVC: false, forceWebView: false);
|
||||
}
|
||||
break;
|
||||
case EntityAction.viewInvoice:
|
||||
store.dispatch(ViewInvoice(
|
||||
context: context, invoiceId: quote.quoteInvoiceId));
|
||||
break;
|
||||
case EntityAction.convert:
|
||||
final Completer<InvoiceEntity> completer =
|
||||
Completer<InvoiceEntity>();
|
||||
store.dispatch(ConvertQuote(completer, quote.id));
|
||||
completer.future.then((InvoiceEntity invoice) {
|
||||
store.dispatch(
|
||||
ViewInvoice(invoiceId: invoice.id, context: context));
|
||||
});
|
||||
break;
|
||||
case EntityAction.markSent:
|
||||
store.dispatch(MarkSentQuoteRequest(
|
||||
snackBarCompleter(context, localization.markedQuoteAsSent),
|
||||
quote.id));
|
||||
break;
|
||||
case EntityAction.sendEmail:
|
||||
store.dispatch(ShowEmailQuote(
|
||||
completer:
|
||||
snackBarCompleter(context, localization.emailedQuote),
|
||||
quote: quote,
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveQuoteRequest(
|
||||
popCompleter(context, localization.archivedQuote), quote.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteQuoteRequest(
|
||||
popCompleter(context, localization.deletedQuote), quote.id));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreQuoteRequest(
|
||||
snackBarCompleter(context, localization.restoredQuote),
|
||||
quote.id));
|
||||
break;
|
||||
case EntityAction.cloneToInvoice:
|
||||
Navigator.of(context).pop();
|
||||
store.dispatch(
|
||||
EditInvoice(context: context, invoice: quote.cloneToInvoice));
|
||||
break;
|
||||
case EntityAction.cloneToQuote:
|
||||
Navigator.of(context).pop();
|
||||
store.dispatch(
|
||||
EditQuote(context: context, quote: quote.cloneToQuote));
|
||||
break;
|
||||
}
|
||||
});
|
||||
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||
handleQuoteAction(context, quote, action),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
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/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.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/utils/icons.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
||||
class TaskList extends StatelessWidget {
|
||||
|
|
@ -17,43 +16,6 @@ class TaskList extends StatelessWidget {
|
|||
|
||||
final TaskListVM viewModel;
|
||||
|
||||
void _showMenu(
|
||||
BuildContext context, TaskEntity task, ClientEntity client) async {
|
||||
if (task == null || client == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final user = viewModel.user;
|
||||
final message = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (BuildContext dialogContext) => SimpleDialog(
|
||||
children: task
|
||||
.getActions(
|
||||
user: user, client: client, includeEdit: true)
|
||||
.map((entityAction) {
|
||||
if (entityAction == null) {
|
||||
return Divider();
|
||||
} else {
|
||||
return ListTile(
|
||||
leading: Icon(getEntityActionIcon(entityAction)),
|
||||
title: Text(AppLocalization.of(context)
|
||||
.lookup(entityAction.toString())),
|
||||
onTap: () {
|
||||
Navigator.of(dialogContext).pop();
|
||||
viewModel.onEntityAction(context, task, entityAction);
|
||||
},
|
||||
);
|
||||
}
|
||||
}).toList()));
|
||||
|
||||
if (message != null) {
|
||||
Scaffold.of(context).showSnackBar(SnackBar(
|
||||
content: SnackBarRow(
|
||||
message: message,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localization = AppLocalization.of(context);
|
||||
|
|
@ -127,10 +89,19 @@ class TaskList extends StatelessWidget {
|
|||
separatorBuilder: (context, index) => ListDivider(),
|
||||
itemCount: viewModel.taskList.length,
|
||||
itemBuilder: (BuildContext context, index) {
|
||||
final user = viewModel.user;
|
||||
final taskId = viewModel.taskList[index];
|
||||
final task = viewModel.taskMap[taskId];
|
||||
final client = viewModel.clientMap[task.clientId] ??
|
||||
ClientEntity();
|
||||
|
||||
void showDialog() => showEntityActionsDialog(
|
||||
entity: task,
|
||||
context: context,
|
||||
user: user,
|
||||
client: client,
|
||||
onEntityAction: viewModel.onEntityAction);
|
||||
|
||||
return TaskListItem(
|
||||
user: viewModel.user,
|
||||
filter: viewModel.filter,
|
||||
|
|
@ -139,18 +110,16 @@ class TaskList extends StatelessWidget {
|
|||
ClientEntity(),
|
||||
project: viewModel
|
||||
.state.projectState.map[task.projectId],
|
||||
onTap: () =>
|
||||
viewModel.onTaskTap(context, task),
|
||||
onTap: () => viewModel.onTaskTap(context, task),
|
||||
onEntityAction: (EntityAction action) {
|
||||
if (action == EntityAction.more) {
|
||||
_showMenu(context, task, client);
|
||||
showDialog();
|
||||
} else {
|
||||
viewModel.onEntityAction(
|
||||
context, task, action);
|
||||
}
|
||||
},
|
||||
onLongPress: () =>
|
||||
_showMenu(context, task, client),
|
||||
onLongPress: () => showDialog(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/project/project_actions.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||
import 'package:redux/redux.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
|
@ -99,73 +96,9 @@ class TaskListVM {
|
|||
onTaskTap: (context, task) {
|
||||
store.dispatch(ViewTask(taskId: task.id, context: context));
|
||||
},
|
||||
onEntityAction: (context, task, action) {
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
store.dispatch(EditTask(context: context, task: task));
|
||||
break;
|
||||
case EntityAction.start:
|
||||
case EntityAction.stop:
|
||||
case EntityAction.resume:
|
||||
final Completer<TaskEntity> completer = new Completer<TaskEntity>();
|
||||
final localization = AppLocalization.of(context);
|
||||
store.dispatch(
|
||||
SaveTaskRequest(completer: completer, task: task.toggle()));
|
||||
completer.future.then((savedTask) {
|
||||
Scaffold.of(context).showSnackBar(SnackBar(
|
||||
content: SnackBarRow(
|
||||
message: savedTask.isRunning
|
||||
? (savedTask.duration > 0
|
||||
? localization.resumedTask
|
||||
: localization.startedTask)
|
||||
: localization.stoppedTask,
|
||||
)));
|
||||
}).catchError((Object error) {
|
||||
showDialog<ErrorDialog>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return ErrorDialog(error);
|
||||
});
|
||||
});
|
||||
|
||||
break;
|
||||
case EntityAction.newInvoice:
|
||||
final item = convertTaskToInvoiceItem(task: task, context: context);
|
||||
store.dispatch(EditInvoice(
|
||||
invoice: InvoiceEntity(company: state.selectedCompany)
|
||||
.rebuild((b) => b
|
||||
..hasTasks = true
|
||||
..clientId = task.clientId
|
||||
..invoiceItems.add(item)),
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.viewInvoice:
|
||||
store.dispatch(
|
||||
ViewInvoice(invoiceId: task.invoiceId, context: context));
|
||||
break;
|
||||
case EntityAction.clone:
|
||||
store.dispatch(EditTask(context: context, task: task.clone));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreTaskRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).restoredTask),
|
||||
task.id));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveTaskRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).archivedTask),
|
||||
task.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteTaskRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).deletedTask),
|
||||
task.id));
|
||||
break;
|
||||
}
|
||||
},
|
||||
onEntityAction:
|
||||
(BuildContext context, BaseEntity task, EntityAction action) =>
|
||||
handleTaskAction(context, task, action),
|
||||
onRefreshed: (context) => _handleRefresh(context),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ class _CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||
task.getActions(client: viewModel.client, user: user),
|
||||
isSaving: viewModel.isSaving,
|
||||
entity: task,
|
||||
onSelected: viewModel.onActionSelected,
|
||||
onSelected: viewModel.onEntityAction,
|
||||
)
|
||||
],
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/project/project_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/task/task_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
|
|
@ -47,7 +45,7 @@ class TaskViewVM {
|
|||
@required this.project,
|
||||
@required this.company,
|
||||
@required this.state,
|
||||
@required this.onActionSelected,
|
||||
@required this.onEntityAction,
|
||||
@required this.onEditPressed,
|
||||
@required this.onBackPressed,
|
||||
@required this.onRefreshed,
|
||||
|
|
@ -151,47 +149,11 @@ class TaskViewVM {
|
|||
store.dispatch(UpdateCurrentRoute(TaskScreen.route));
|
||||
}
|
||||
},
|
||||
onActionSelected: (BuildContext context, EntityAction action) {
|
||||
final localization = AppLocalization.of(context);
|
||||
switch (action) {
|
||||
case EntityAction.resume:
|
||||
case EntityAction.start:
|
||||
case EntityAction.stop:
|
||||
_toggleTask(context);
|
||||
break;
|
||||
case EntityAction.newInvoice:
|
||||
final item =
|
||||
convertTaskToInvoiceItem(task: task, context: context);
|
||||
store.dispatch(EditInvoice(
|
||||
invoice: InvoiceEntity(company: state.selectedCompany)
|
||||
.rebuild((b) => b
|
||||
..hasTasks = true
|
||||
..clientId = task.clientId
|
||||
..invoiceItems.add(item)),
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.clone:
|
||||
store.dispatch(EditTask(context: context, task: task.clone));
|
||||
break;
|
||||
case EntityAction.viewInvoice:
|
||||
store.dispatch(
|
||||
ViewInvoice(invoiceId: task.invoiceId, context: context));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveTaskRequest(
|
||||
popCompleter(context, localization.archivedTask), task.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteTaskRequest(
|
||||
popCompleter(context, localization.deletedTask), task.id));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreTaskRequest(
|
||||
snackBarCompleter(context, localization.restoredTask),
|
||||
task.id));
|
||||
break;
|
||||
}
|
||||
});
|
||||
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||
handleTaskAction(context, task, action),
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
final AppState state;
|
||||
|
|
@ -199,7 +161,7 @@ class TaskViewVM {
|
|||
final ClientEntity client;
|
||||
final ProjectEntity project;
|
||||
final CompanyEntity company;
|
||||
final Function(BuildContext, EntityAction) onActionSelected;
|
||||
final Function(BuildContext, EntityAction) onEntityAction;
|
||||
final Function(BuildContext, [TaskTime]) onEditPressed;
|
||||
final Function onBackPressed;
|
||||
final Function(BuildContext) onFabPressed;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
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/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
|
||||
|
|
@ -17,41 +18,6 @@ class VendorList extends StatelessWidget {
|
|||
|
||||
final VendorListVM viewModel;
|
||||
|
||||
void _showMenu(BuildContext context, VendorEntity vendor) async {
|
||||
if (vendor == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final user = viewModel.user;
|
||||
final message = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (BuildContext dialogContext) => SimpleDialog(
|
||||
children: vendor
|
||||
.getActions(user: user, includeEdit: true)
|
||||
.map((entityAction) {
|
||||
if (entityAction == null) {
|
||||
return Divider();
|
||||
} else {
|
||||
return ListTile(
|
||||
leading: Icon(getEntityActionIcon(entityAction)),
|
||||
title: Text(AppLocalization.of(context)
|
||||
.lookup(entityAction.toString())),
|
||||
onTap: () {
|
||||
Navigator.of(dialogContext).pop();
|
||||
viewModel.onEntityAction(context, vendor, entityAction);
|
||||
},
|
||||
);
|
||||
}
|
||||
}).toList()));
|
||||
|
||||
if (message != null) {
|
||||
Scaffold.of(context).showSnackBar(SnackBar(
|
||||
content: SnackBarRow(
|
||||
message: message,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
|
|
@ -78,8 +44,16 @@ class VendorList extends StatelessWidget {
|
|||
separatorBuilder: (context, index) => ListDivider(),
|
||||
itemCount: viewModel.vendorList.length,
|
||||
itemBuilder: (BuildContext context, index) {
|
||||
final user = viewModel.user;
|
||||
final vendorId = viewModel.vendorList[index];
|
||||
final vendor = viewModel.vendorMap[vendorId];
|
||||
|
||||
void showDialog() => showEntityActionsDialog(
|
||||
entity: vendor,
|
||||
context: context,
|
||||
user: user,
|
||||
onEntityAction: viewModel.onEntityAction);
|
||||
|
||||
return VendorListItem(
|
||||
user: viewModel.user,
|
||||
filter: viewModel.filter,
|
||||
|
|
@ -88,13 +62,13 @@ class VendorList extends StatelessWidget {
|
|||
viewModel.onVendorTap(context, vendor),
|
||||
onEntityAction: (EntityAction action) {
|
||||
if (action == EntityAction.more) {
|
||||
_showMenu(context, vendor);
|
||||
showDialog();
|
||||
} else {
|
||||
viewModel.onEntityAction(
|
||||
context, vendor, action);
|
||||
}
|
||||
},
|
||||
onLongPress: () => _showMenu(context, vendor),
|
||||
onLongPress: () => showDialog(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:invoiceninja_flutter/redux/expense/expense_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
|
|
@ -78,37 +77,9 @@ class VendorListVM {
|
|||
onVendorTap: (context, vendor) {
|
||||
store.dispatch(ViewVendor(vendorId: vendor.id, context: context));
|
||||
},
|
||||
onEntityAction: (context, vendor, action) {
|
||||
switch (action) {
|
||||
case EntityAction.edit:
|
||||
store.dispatch(EditVendor(context: context, vendor: vendor));
|
||||
break;
|
||||
case EntityAction.newExpense:
|
||||
store.dispatch(EditExpense(
|
||||
expense: ExpenseEntity(
|
||||
company: state.selectedCompany, vendor: vendor),
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreVendorRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).restoredVendor),
|
||||
vendor.id));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveVendorRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).archivedVendor),
|
||||
vendor.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteVendorRequest(
|
||||
snackBarCompleter(
|
||||
context, AppLocalization.of(context).deletedVendor),
|
||||
vendor.id));
|
||||
break;
|
||||
}
|
||||
},
|
||||
onEntityAction:
|
||||
(BuildContext context, BaseEntity vendor, EntityAction action) =>
|
||||
handleVendorAction(context, vendor, action),
|
||||
onRefreshed: (context) => _handleRefresh(context),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ class _CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||
user: viewModel.company.user,
|
||||
isSaving: viewModel.isSaving,
|
||||
entity: vendor,
|
||||
onSelected: viewModel.onActionSelected,
|
||||
onSelected: viewModel.onEntityAction,
|
||||
entityActions: viewModel.vendor.getActions(user: user),
|
||||
)
|
||||
],
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class VendorViewVM {
|
|||
@required this.vendor,
|
||||
@required this.company,
|
||||
@required this.onAddExpensePressed,
|
||||
@required this.onActionSelected,
|
||||
@required this.onEntityAction,
|
||||
@required this.onEntityPressed,
|
||||
@required this.onEditPressed,
|
||||
@required this.onBackPressed,
|
||||
|
|
@ -107,38 +107,16 @@ class VendorViewVM {
|
|||
onAddExpensePressed: (context) => store.dispatch(EditExpense(
|
||||
expense: ExpenseEntity(company: company, vendor: vendor),
|
||||
context: context)),
|
||||
onActionSelected: (BuildContext context, EntityAction action) {
|
||||
final localization = AppLocalization.of(context);
|
||||
switch (action) {
|
||||
case EntityAction.newExpense:
|
||||
store.dispatch(EditExpense(
|
||||
expense: ExpenseEntity(
|
||||
company: state.selectedCompany, vendor: vendor),
|
||||
context: context));
|
||||
break;
|
||||
case EntityAction.archive:
|
||||
store.dispatch(ArchiveVendorRequest(
|
||||
popCompleter(context, localization.archivedVendor),
|
||||
vendor.id));
|
||||
break;
|
||||
case EntityAction.delete:
|
||||
store.dispatch(DeleteVendorRequest(
|
||||
popCompleter(context, localization.deletedVendor),
|
||||
vendor.id));
|
||||
break;
|
||||
case EntityAction.restore:
|
||||
store.dispatch(RestoreVendorRequest(
|
||||
snackBarCompleter(context, localization.restoredVendor),
|
||||
vendor.id));
|
||||
break;
|
||||
}
|
||||
});
|
||||
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||
handleVendorAction(context, vendor, action),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
final AppState state;
|
||||
final VendorEntity vendor;
|
||||
final CompanyEntity company;
|
||||
final Function(BuildContext, EntityAction) onActionSelected;
|
||||
final Function(BuildContext, EntityAction) onEntityAction;
|
||||
final Function(BuildContext) onEditPressed;
|
||||
final Function(BuildContext, EntityType, [bool]) onEntityPressed;
|
||||
final Function onBackPressed;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:invoiceninja_flutter/utils/strings.dart';
|
||||
|
||||
abstract class LocaleCodeAware {
|
||||
|
||||
LocaleCodeAware(this.localeCode);
|
||||
|
||||
final String localeCode;
|
||||
|
|
@ -13,7 +12,6 @@ abstract class LocaleCodeAware {
|
|||
/// It should be used by a [LocaleCodeAware] to get the i18n strings for
|
||||
/// a specified locale.
|
||||
mixin LocalizationsProvider on LocaleCodeAware {
|
||||
|
||||
static final Map<String, Map<String, String>> _localizedValues = {
|
||||
'en': {
|
||||
'expense_date': 'Expense Date',
|
||||
|
|
@ -11415,17 +11413,14 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
},
|
||||
};
|
||||
|
||||
String get createdProject =>
|
||||
_localizedValues[localeCode]['created_project'];
|
||||
String get createdProject => _localizedValues[localeCode]['created_project'];
|
||||
|
||||
String get updatedProject =>
|
||||
_localizedValues[localeCode]['updated_project'];
|
||||
String get updatedProject => _localizedValues[localeCode]['updated_project'];
|
||||
|
||||
String get archivedProject =>
|
||||
_localizedValues[localeCode]['archived_project'];
|
||||
|
||||
String get deletedProject =>
|
||||
_localizedValues[localeCode]['deleted_project'];
|
||||
String get deletedProject => _localizedValues[localeCode]['deleted_project'];
|
||||
|
||||
String get restoredProject =>
|
||||
_localizedValues[localeCode]['restored_project'];
|
||||
|
|
@ -11435,8 +11430,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
String get thankYouForUsingOurApp =>
|
||||
_localizedValues[localeCode]['thank_you_for_using_our_app'];
|
||||
|
||||
String get ifYouLikeIt =>
|
||||
_localizedValues[localeCode]['if_you_like_it'];
|
||||
String get ifYouLikeIt => _localizedValues[localeCode]['if_you_like_it'];
|
||||
|
||||
String get clickHere => _localizedValues[localeCode]['click_here'];
|
||||
|
||||
|
|
@ -11451,8 +11445,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get locked => _localizedValues[localeCode]['locked'];
|
||||
|
||||
String get authenticate =>
|
||||
_localizedValues[localeCode]['authenticate'];
|
||||
String get authenticate => _localizedValues[localeCode]['authenticate'];
|
||||
|
||||
String get pleaseAuthenticate =>
|
||||
_localizedValues[localeCode]['please_authenticate'];
|
||||
|
|
@ -11466,8 +11459,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get hostedLogin => _localizedValues[localeCode]['hosted_login'];
|
||||
|
||||
String get selfhostLogin =>
|
||||
_localizedValues[localeCode]['selfhost_login'];
|
||||
String get selfhostLogin => _localizedValues[localeCode]['selfhost_login'];
|
||||
|
||||
String get googleLogin => _localizedValues[localeCode]['google_login'];
|
||||
|
||||
|
|
@ -11481,17 +11473,14 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get previous => _localizedValues[localeCode]['previous'];
|
||||
|
||||
String get currentPeriod =>
|
||||
_localizedValues[localeCode]['current_period'];
|
||||
String get currentPeriod => _localizedValues[localeCode]['current_period'];
|
||||
|
||||
String get comparisonPeriod =>
|
||||
_localizedValues[localeCode]['comparison_period'];
|
||||
|
||||
String get previousPeriod =>
|
||||
_localizedValues[localeCode]['previous_period'];
|
||||
String get previousPeriod => _localizedValues[localeCode]['previous_period'];
|
||||
|
||||
String get previousYear =>
|
||||
_localizedValues[localeCode]['previous_year'];
|
||||
String get previousYear => _localizedValues[localeCode]['previous_year'];
|
||||
|
||||
String get compareTo => _localizedValues[localeCode]['compare_to'];
|
||||
|
||||
|
|
@ -11511,11 +11500,9 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get custom => _localizedValues[localeCode]['custom'];
|
||||
|
||||
String get cloneToInvoice =>
|
||||
_localizedValues[localeCode]['clone_to_invoice'];
|
||||
String get cloneToInvoice => _localizedValues[localeCode]['clone_to_invoice'];
|
||||
|
||||
String get cloneToQuote =>
|
||||
_localizedValues[localeCode]['clone_to_quote'];
|
||||
String get cloneToQuote => _localizedValues[localeCode]['clone_to_quote'];
|
||||
|
||||
String get viewInvoice => _localizedValues[localeCode]['view_invoice'];
|
||||
|
||||
|
|
@ -11552,25 +11539,20 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
String get editRecurringQuote =>
|
||||
_localizedValues[localeCode]['edit_recurring_quote'];
|
||||
|
||||
String get billingAddress =>
|
||||
_localizedValues[localeCode]['billing_address'];
|
||||
String get billingAddress => _localizedValues[localeCode]['billing_address'];
|
||||
|
||||
String get shippingAddress =>
|
||||
_localizedValues[localeCode]['shipping_address'];
|
||||
|
||||
String get totalRevenue =>
|
||||
_localizedValues[localeCode]['total_revenue'];
|
||||
String get totalRevenue => _localizedValues[localeCode]['total_revenue'];
|
||||
|
||||
String get averageInvoice =>
|
||||
_localizedValues[localeCode]['average_invoice'];
|
||||
String get averageInvoice => _localizedValues[localeCode]['average_invoice'];
|
||||
|
||||
String get outstanding => _localizedValues[localeCode]['outstanding'];
|
||||
|
||||
String get invoicesSent =>
|
||||
_localizedValues[localeCode]['invoices_sent'];
|
||||
String get invoicesSent => _localizedValues[localeCode]['invoices_sent'];
|
||||
|
||||
String get activeClients =>
|
||||
_localizedValues[localeCode]['active_clients'];
|
||||
String get activeClients => _localizedValues[localeCode]['active_clients'];
|
||||
|
||||
String get close => _localizedValues[localeCode]['close'];
|
||||
|
||||
|
|
@ -11657,8 +11639,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get error => _localizedValues[localeCode]['error'];
|
||||
|
||||
String get couldNotLaunch =>
|
||||
_localizedValues[localeCode]['could_not_launch'];
|
||||
String get couldNotLaunch => _localizedValues[localeCode]['could_not_launch'];
|
||||
|
||||
String get contacts => _localizedValues[localeCode]['contacts'];
|
||||
|
||||
|
|
@ -11678,8 +11659,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get remove => _localizedValues[localeCode]['remove'];
|
||||
|
||||
String get emailIsInvalid =>
|
||||
_localizedValues[localeCode]['email_is_invalid'];
|
||||
String get emailIsInvalid => _localizedValues[localeCode]['email_is_invalid'];
|
||||
|
||||
String get product => _localizedValues[localeCode]['product'];
|
||||
|
||||
|
|
@ -11687,51 +11667,40 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get newProduct => _localizedValues[localeCode]['new_product'];
|
||||
|
||||
String get createdProduct =>
|
||||
_localizedValues[localeCode]['created_product'];
|
||||
String get createdProduct => _localizedValues[localeCode]['created_product'];
|
||||
|
||||
String get updatedProduct =>
|
||||
_localizedValues[localeCode]['updated_product'];
|
||||
String get updatedProduct => _localizedValues[localeCode]['updated_product'];
|
||||
|
||||
String get archivedProduct =>
|
||||
_localizedValues[localeCode]['archived_product'];
|
||||
|
||||
String get deletedProduct =>
|
||||
_localizedValues[localeCode]['deleted_product'];
|
||||
String get deletedProduct => _localizedValues[localeCode]['deleted_product'];
|
||||
|
||||
String get restoredProduct =>
|
||||
_localizedValues[localeCode]['restored_product'];
|
||||
|
||||
String get newVendor => _localizedValues[localeCode]['new_vendor'];
|
||||
|
||||
String get createdVendor =>
|
||||
_localizedValues[localeCode]['created_vendor'];
|
||||
String get createdVendor => _localizedValues[localeCode]['created_vendor'];
|
||||
|
||||
String get updatedVendor =>
|
||||
_localizedValues[localeCode]['updated_vendor'];
|
||||
String get updatedVendor => _localizedValues[localeCode]['updated_vendor'];
|
||||
|
||||
String get archivedVendor =>
|
||||
_localizedValues[localeCode]['archived_vendor'];
|
||||
String get archivedVendor => _localizedValues[localeCode]['archived_vendor'];
|
||||
|
||||
String get deletedVendor =>
|
||||
_localizedValues[localeCode]['deleted_vendor'];
|
||||
String get deletedVendor => _localizedValues[localeCode]['deleted_vendor'];
|
||||
|
||||
String get restoredVendor =>
|
||||
_localizedValues[localeCode]['restored_vendor'];
|
||||
String get restoredVendor => _localizedValues[localeCode]['restored_vendor'];
|
||||
|
||||
String get newExpense => _localizedValues[localeCode]['new_expense'];
|
||||
|
||||
String get createdExpense =>
|
||||
_localizedValues[localeCode]['created_expense'];
|
||||
String get createdExpense => _localizedValues[localeCode]['created_expense'];
|
||||
|
||||
String get updatedExpense =>
|
||||
_localizedValues[localeCode]['updated_expense'];
|
||||
String get updatedExpense => _localizedValues[localeCode]['updated_expense'];
|
||||
|
||||
String get archivedExpense =>
|
||||
_localizedValues[localeCode]['archived_expense'];
|
||||
|
||||
String get deletedExpense =>
|
||||
_localizedValues[localeCode]['deleted_expense'];
|
||||
String get deletedExpense => _localizedValues[localeCode]['deleted_expense'];
|
||||
|
||||
String get restoredExpense =>
|
||||
_localizedValues[localeCode]['restored_expense'];
|
||||
|
|
@ -11748,20 +11717,15 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get newClient => _localizedValues[localeCode]['new_client'];
|
||||
|
||||
String get createdClient =>
|
||||
_localizedValues[localeCode]['created_client'];
|
||||
String get createdClient => _localizedValues[localeCode]['created_client'];
|
||||
|
||||
String get updatedClient =>
|
||||
_localizedValues[localeCode]['updated_client'];
|
||||
String get updatedClient => _localizedValues[localeCode]['updated_client'];
|
||||
|
||||
String get archivedClient =>
|
||||
_localizedValues[localeCode]['archived_client'];
|
||||
String get archivedClient => _localizedValues[localeCode]['archived_client'];
|
||||
|
||||
String get deletedClient =>
|
||||
_localizedValues[localeCode]['deleted_client'];
|
||||
String get deletedClient => _localizedValues[localeCode]['deleted_client'];
|
||||
|
||||
String get restoredClient =>
|
||||
_localizedValues[localeCode]['restored_client'];
|
||||
String get restoredClient => _localizedValues[localeCode]['restored_client'];
|
||||
|
||||
String get address1 => _localizedValues[localeCode]['address1'];
|
||||
|
||||
|
|
@ -11781,31 +11745,25 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get newInvoice => _localizedValues[localeCode]['new_invoice'];
|
||||
|
||||
String get createdInvoice =>
|
||||
_localizedValues[localeCode]['created_invoice'];
|
||||
String get createdInvoice => _localizedValues[localeCode]['created_invoice'];
|
||||
|
||||
String get updatedInvoice =>
|
||||
_localizedValues[localeCode]['updated_invoice'];
|
||||
String get updatedInvoice => _localizedValues[localeCode]['updated_invoice'];
|
||||
|
||||
String get archivedInvoice =>
|
||||
_localizedValues[localeCode]['archived_invoice'];
|
||||
|
||||
String get deletedInvoice =>
|
||||
_localizedValues[localeCode]['deleted_invoice'];
|
||||
String get deletedInvoice => _localizedValues[localeCode]['deleted_invoice'];
|
||||
|
||||
String get restoredInvoice =>
|
||||
_localizedValues[localeCode]['restored_invoice'];
|
||||
|
||||
String get emailedInvoice =>
|
||||
_localizedValues[localeCode]['emailed_invoice'];
|
||||
String get emailedInvoice => _localizedValues[localeCode]['emailed_invoice'];
|
||||
|
||||
String get emailedPayment =>
|
||||
_localizedValues[localeCode]['emailed_payment'];
|
||||
String get emailedPayment => _localizedValues[localeCode]['emailed_payment'];
|
||||
|
||||
String get amount => _localizedValues[localeCode]['amount'];
|
||||
|
||||
String get invoiceNumber =>
|
||||
_localizedValues[localeCode]['invoice_number'];
|
||||
String get invoiceNumber => _localizedValues[localeCode]['invoice_number'];
|
||||
|
||||
String get invoiceDate => _localizedValues[localeCode]['invoice_date'];
|
||||
|
||||
|
|
@ -11817,8 +11775,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get publicNotes => _localizedValues[localeCode]['public_notes'];
|
||||
|
||||
String get privateNotes =>
|
||||
_localizedValues[localeCode]['private_notes'];
|
||||
String get privateNotes => _localizedValues[localeCode]['private_notes'];
|
||||
|
||||
String get frequency => _localizedValues[localeCode]['frequency'];
|
||||
|
||||
|
|
@ -11834,8 +11791,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get items => _localizedValues[localeCode]['items'];
|
||||
|
||||
String get partialDeposit =>
|
||||
_localizedValues[localeCode]['partial_deposit'];
|
||||
String get partialDeposit => _localizedValues[localeCode]['partial_deposit'];
|
||||
|
||||
String get description => _localizedValues[localeCode]['description'];
|
||||
|
||||
|
|
@ -11855,16 +11811,14 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get dueDate => _localizedValues[localeCode]['due_date'];
|
||||
|
||||
String get partialDueDate =>
|
||||
_localizedValues[localeCode]['partial_due_date'];
|
||||
String get partialDueDate => _localizedValues[localeCode]['partial_due_date'];
|
||||
|
||||
String get status => _localizedValues[localeCode]['status'];
|
||||
|
||||
String get invoiceStatusId =>
|
||||
_localizedValues[localeCode]['invoice_status_id'];
|
||||
|
||||
String get quoteStatusId =>
|
||||
_localizedValues[localeCode]['quote_status'];
|
||||
String get quoteStatusId => _localizedValues[localeCode]['quote_status'];
|
||||
|
||||
String get clickPlusToAddItem =>
|
||||
_localizedValues[localeCode]['click_plus_to_add_item'];
|
||||
|
|
@ -11872,8 +11826,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
String get clickPlusToAddTime =>
|
||||
_localizedValues[localeCode]['click_plus_to_add_time'];
|
||||
|
||||
String get countSelected =>
|
||||
_localizedValues[localeCode]['count_selected'];
|
||||
String get countSelected => _localizedValues[localeCode]['count_selected'];
|
||||
|
||||
String get total => _localizedValues[localeCode]['total'];
|
||||
|
||||
|
|
@ -11928,23 +11881,17 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get paid => _localizedValues[localeCode]['paid'];
|
||||
|
||||
String get invoiceStatus1 =>
|
||||
_localizedValues[localeCode]['invoice_status_1'];
|
||||
String get invoiceStatus1 => _localizedValues[localeCode]['invoice_status_1'];
|
||||
|
||||
String get invoiceStatus2 =>
|
||||
_localizedValues[localeCode]['invoice_status_2'];
|
||||
String get invoiceStatus2 => _localizedValues[localeCode]['invoice_status_2'];
|
||||
|
||||
String get invoiceStatus3 =>
|
||||
_localizedValues[localeCode]['invoice_status_3'];
|
||||
String get invoiceStatus3 => _localizedValues[localeCode]['invoice_status_3'];
|
||||
|
||||
String get invoiceStatus4 =>
|
||||
_localizedValues[localeCode]['invoice_status_4'];
|
||||
String get invoiceStatus4 => _localizedValues[localeCode]['invoice_status_4'];
|
||||
|
||||
String get invoiceStatus5 =>
|
||||
_localizedValues[localeCode]['invoice_status_5'];
|
||||
String get invoiceStatus5 => _localizedValues[localeCode]['invoice_status_5'];
|
||||
|
||||
String get invoiceStatus6 =>
|
||||
_localizedValues[localeCode]['invoice_status_6'];
|
||||
String get invoiceStatus6 => _localizedValues[localeCode]['invoice_status_6'];
|
||||
|
||||
String get markSent => _localizedValues[localeCode]['mark_sent'];
|
||||
|
||||
|
|
@ -11954,8 +11901,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
String get done => _localizedValues[localeCode]['done'];
|
||||
|
||||
String get pleaseEnterAClientOrContactName =>
|
||||
_localizedValues[localeCode]
|
||||
['please_enter_a_client_or_contact_name'];
|
||||
_localizedValues[localeCode]['please_enter_a_client_or_contact_name'];
|
||||
|
||||
String get darkMode => _localizedValues[localeCode]['dark_mode'];
|
||||
|
||||
|
|
@ -11964,13 +11910,11 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get refreshData => _localizedValues[localeCode]['refresh_data'];
|
||||
|
||||
String get blankContact =>
|
||||
_localizedValues[localeCode]['blank_contact'];
|
||||
String get blankContact => _localizedValues[localeCode]['blank_contact'];
|
||||
|
||||
String get activity => _localizedValues[localeCode]['activity'];
|
||||
|
||||
String get noRecordsFound =>
|
||||
_localizedValues[localeCode]['no_records_found'];
|
||||
String get noRecordsFound => _localizedValues[localeCode]['no_records_found'];
|
||||
|
||||
String get clone => _localizedValues[localeCode]['clone'];
|
||||
|
||||
|
|
@ -11980,39 +11924,31 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get size => _localizedValues[localeCode]['size'];
|
||||
|
||||
String get paymentTerms =>
|
||||
_localizedValues[localeCode]['payment_terms'];
|
||||
String get paymentTerms => _localizedValues[localeCode]['payment_terms'];
|
||||
|
||||
String get paymentDate => _localizedValues[localeCode]['payment_date'];
|
||||
|
||||
String get paymentStatus =>
|
||||
_localizedValues[localeCode]['payment_status'];
|
||||
String get paymentStatus => _localizedValues[localeCode]['payment_status'];
|
||||
|
||||
String get net => _localizedValues[localeCode]['net'];
|
||||
|
||||
String get clientPortal =>
|
||||
_localizedValues[localeCode]['client_portal'];
|
||||
String get clientPortal => _localizedValues[localeCode]['client_portal'];
|
||||
|
||||
String get showTasks => _localizedValues[localeCode]['show_tasks'];
|
||||
|
||||
String get emailReminders =>
|
||||
_localizedValues[localeCode]['email_reminders'];
|
||||
String get emailReminders => _localizedValues[localeCode]['email_reminders'];
|
||||
|
||||
String get enabled => _localizedValues[localeCode]['enabled'];
|
||||
|
||||
String get recipients => _localizedValues[localeCode]['recipients'];
|
||||
|
||||
String get initialEmail =>
|
||||
_localizedValues[localeCode]['initial_email'];
|
||||
String get initialEmail => _localizedValues[localeCode]['initial_email'];
|
||||
|
||||
String get firstReminder =>
|
||||
_localizedValues[localeCode]['first_reminder'];
|
||||
String get firstReminder => _localizedValues[localeCode]['first_reminder'];
|
||||
|
||||
String get secondReminder =>
|
||||
_localizedValues[localeCode]['second_reminder'];
|
||||
String get secondReminder => _localizedValues[localeCode]['second_reminder'];
|
||||
|
||||
String get thirdReminder =>
|
||||
_localizedValues[localeCode]['third_reminder'];
|
||||
String get thirdReminder => _localizedValues[localeCode]['third_reminder'];
|
||||
|
||||
String get template => _localizedValues[localeCode]['template'];
|
||||
|
||||
|
|
@ -12024,8 +11960,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get sendEmail => _localizedValues[localeCode]['send_email'];
|
||||
|
||||
String get emailReceipt =>
|
||||
_localizedValues[localeCode]['email_receipt'];
|
||||
String get emailReceipt => _localizedValues[localeCode]['email_receipt'];
|
||||
|
||||
String get documents => _localizedValues[localeCode]['documents'];
|
||||
|
||||
|
|
@ -12050,20 +11985,16 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
String get transactionReference =>
|
||||
_localizedValues[localeCode]['transaction_reference'];
|
||||
|
||||
String get enterPayment =>
|
||||
_localizedValues[localeCode]['enter_payment'];
|
||||
String get enterPayment => _localizedValues[localeCode]['enter_payment'];
|
||||
|
||||
String get createdPayment =>
|
||||
_localizedValues[localeCode]['created_payment'];
|
||||
String get createdPayment => _localizedValues[localeCode]['created_payment'];
|
||||
|
||||
String get updatedPayment =>
|
||||
_localizedValues[localeCode]['updated_payment'];
|
||||
String get updatedPayment => _localizedValues[localeCode]['updated_payment'];
|
||||
|
||||
String get archivedPayment =>
|
||||
_localizedValues[localeCode]['archived_payment'];
|
||||
|
||||
String get deletedPayment =>
|
||||
_localizedValues[localeCode]['deleted_payment'];
|
||||
String get deletedPayment => _localizedValues[localeCode]['deleted_payment'];
|
||||
|
||||
String get restoredPayment =>
|
||||
_localizedValues[localeCode]['restored_payment'];
|
||||
|
|
@ -12074,20 +12005,15 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get newQuote => _localizedValues[localeCode]['new_quote'];
|
||||
|
||||
String get createdQuote =>
|
||||
_localizedValues[localeCode]['created_quote'];
|
||||
String get createdQuote => _localizedValues[localeCode]['created_quote'];
|
||||
|
||||
String get updatedQuote =>
|
||||
_localizedValues[localeCode]['updated_quote'];
|
||||
String get updatedQuote => _localizedValues[localeCode]['updated_quote'];
|
||||
|
||||
String get archivedQuote =>
|
||||
_localizedValues[localeCode]['archived_quote'];
|
||||
String get archivedQuote => _localizedValues[localeCode]['archived_quote'];
|
||||
|
||||
String get deletedQuote =>
|
||||
_localizedValues[localeCode]['deleted_quote'];
|
||||
String get deletedQuote => _localizedValues[localeCode]['deleted_quote'];
|
||||
|
||||
String get restoredQuote =>
|
||||
_localizedValues[localeCode]['restored_quote'];
|
||||
String get restoredQuote => _localizedValues[localeCode]['restored_quote'];
|
||||
|
||||
String get expense => _localizedValues[localeCode]['expense'];
|
||||
|
||||
|
|
@ -12202,16 +12128,14 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
String get oneTimePassword =>
|
||||
_localizedValues[localeCode]['one_time_password'];
|
||||
|
||||
String get emailedQuote =>
|
||||
_localizedValues[localeCode]['emailed_quote'];
|
||||
String get emailedQuote => _localizedValues[localeCode]['emailed_quote'];
|
||||
|
||||
String get markedQuoteAsSent =>
|
||||
_localizedValues[localeCode]['marked_quote_as_sent'];
|
||||
|
||||
String get expired => _localizedValues[localeCode]['expired'];
|
||||
|
||||
String get budgetedHours =>
|
||||
_localizedValues[localeCode]['budgeted_hours'];
|
||||
String get budgetedHours => _localizedValues[localeCode]['budgeted_hours'];
|
||||
|
||||
String get pleaseEnterAName =>
|
||||
_localizedValues[localeCode]['please_enter_a_name'];
|
||||
|
|
@ -12220,13 +12144,11 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get updatedTask => _localizedValues[localeCode]['updated_task'];
|
||||
|
||||
String get archivedTask =>
|
||||
_localizedValues[localeCode]['archived_task'];
|
||||
String get archivedTask => _localizedValues[localeCode]['archived_task'];
|
||||
|
||||
String get deletedTask => _localizedValues[localeCode]['deleted_task'];
|
||||
|
||||
String get restoredTask =>
|
||||
_localizedValues[localeCode]['restored_task'];
|
||||
String get restoredTask => _localizedValues[localeCode]['restored_task'];
|
||||
|
||||
String get newTask => _localizedValues[localeCode]['new_task'];
|
||||
|
||||
|
|
@ -12246,8 +12168,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get manual => _localizedValues[localeCode]['manual'];
|
||||
|
||||
String get autoStartTasks =>
|
||||
_localizedValues[localeCode]['auto_start_tasks'];
|
||||
String get autoStartTasks => _localizedValues[localeCode]['auto_start_tasks'];
|
||||
|
||||
String get now => _localizedValues[localeCode]['now'];
|
||||
|
||||
|
|
@ -12279,8 +12200,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get design => _localizedValues[localeCode]['design'];
|
||||
|
||||
String get copyShipping =>
|
||||
_localizedValues[localeCode]['copy_shipping'];
|
||||
String get copyShipping => _localizedValues[localeCode]['copy_shipping'];
|
||||
|
||||
String get copyBilling => _localizedValues[localeCode]['copy_billing'];
|
||||
|
||||
|
|
@ -12288,44 +12208,34 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
|||
|
||||
String get category => _localizedValues[localeCode]['category'];
|
||||
|
||||
String get markBillable =>
|
||||
_localizedValues[localeCode]['mark_billable'];
|
||||
String get markBillable => _localizedValues[localeCode]['mark_billable'];
|
||||
|
||||
String get markPaid => _localizedValues[localeCode]['mark_paid'];
|
||||
|
||||
String get convertCurrency =>
|
||||
_localizedValues[localeCode]['convert_currency'];
|
||||
|
||||
String get exchangeRate =>
|
||||
_localizedValues[localeCode]['exchange_rate'];
|
||||
String get exchangeRate => _localizedValues[localeCode]['exchange_rate'];
|
||||
|
||||
String get addDocumentsToInvoice =>
|
||||
_localizedValues[localeCode]['add_documents_to_invoice'];
|
||||
|
||||
String get pending =>
|
||||
_localizedValues[localeCode]['pending'];
|
||||
String get pending => _localizedValues[localeCode]['pending'];
|
||||
|
||||
String get converted =>
|
||||
_localizedValues[localeCode]['converted'];
|
||||
String get converted => _localizedValues[localeCode]['converted'];
|
||||
|
||||
String get expenseStatus1 =>
|
||||
_localizedValues[localeCode]['expense_status_1'];
|
||||
String get expenseStatus1 => _localizedValues[localeCode]['expense_status_1'];
|
||||
|
||||
String get expenseStatus2 =>
|
||||
_localizedValues[localeCode]['expense_status_2'];
|
||||
String get expenseStatus2 => _localizedValues[localeCode]['expense_status_2'];
|
||||
|
||||
String get expenseStatus3 =>
|
||||
_localizedValues[localeCode]['expense_status_3'];
|
||||
|
||||
String get expenseDate =>
|
||||
_localizedValues[localeCode]['expense_date'];
|
||||
String get expenseStatus3 => _localizedValues[localeCode]['expense_status_3'];
|
||||
|
||||
String get expenseDate => _localizedValues[localeCode]['expense_date'];
|
||||
|
||||
String lookup(String key) {
|
||||
final lookupKey = toSnakeCase(key);
|
||||
return _localizedValues[localeCode][lookupKey] ??
|
||||
_localizedValues[localeCode]
|
||||
[lookupKey.replaceFirst('_id', '')] ??
|
||||
_localizedValues[localeCode][lookupKey.replaceFirst('_id', '')] ??
|
||||
key;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@ class AppLocalization extends LocaleCodeAware with LocalizationsProvider {
|
|||
static AppLocalization of(BuildContext context) {
|
||||
return Localizations.of<AppLocalization>(context, AppLocalization);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalization> {
|
||||
|
|
|
|||
Loading…
Reference in New Issue