Refactor
This commit is contained in:
parent
30a028a07d
commit
ea16feae8f
|
|
@ -9,6 +9,7 @@ import 'package:invoiceninja_flutter/data/models/static/static_data_model.dart';
|
|||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/company_gateway/company_gateway_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/document/document_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/expense/expense_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/group/group_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
|
||||
|
|
@ -21,6 +22,7 @@ import 'package:invoiceninja_flutter/redux/tax_rate/tax_rate_actions.dart';
|
|||
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
|
||||
import 'package:invoiceninja_flutter/redux/user/user_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/dialogs.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
||||
|
|
@ -662,49 +664,80 @@ void editEntityById(
|
|||
Completer completer}) {
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
final navigator = Navigator.of(context);
|
||||
final localization = AppLocalization.of(context);
|
||||
final map = store.state.getEntityMap(entityType);
|
||||
final entity = map[entityId] as BaseEntity;
|
||||
|
||||
switch (entityType) {
|
||||
case EntityType.client:
|
||||
store.dispatch(EditClient(
|
||||
store.dispatch(
|
||||
EditClient(
|
||||
client: map[entityId],
|
||||
navigator: navigator,
|
||||
completer: completer,
|
||||
));
|
||||
completer: completer ??
|
||||
snackBarCompleter<ClientEntity>(
|
||||
context,
|
||||
entity.isNew
|
||||
? localization.createdClient
|
||||
: localization.updatedClient)),
|
||||
);
|
||||
break;
|
||||
case EntityType.user:
|
||||
store.dispatch(EditUser(
|
||||
store.dispatch(
|
||||
EditUser(
|
||||
user: map[entityId],
|
||||
navigator: navigator,
|
||||
completer: completer,
|
||||
));
|
||||
completer: completer ??
|
||||
snackBarCompleter<UserEntity>(
|
||||
context,
|
||||
entity.isNew
|
||||
? localization.createdUser
|
||||
: localization.updatedUser)),
|
||||
);
|
||||
break;
|
||||
case EntityType.project:
|
||||
store.dispatch(EditProject(
|
||||
project: map[entityId],
|
||||
navigator: navigator,
|
||||
completer: completer,
|
||||
));
|
||||
completer: completer ??
|
||||
snackBarCompleter<ProjectEntity>(
|
||||
context,
|
||||
entity.isNew
|
||||
? localization.createdProject
|
||||
: localization.updatedProject)));
|
||||
break;
|
||||
case EntityType.taxRate:
|
||||
store.dispatch(EditTaxRate(
|
||||
taxRate: map[entityId],
|
||||
navigator: navigator,
|
||||
completer: completer,
|
||||
));
|
||||
completer: completer ??
|
||||
snackBarCompleter<TaxRateEntity>(
|
||||
context,
|
||||
entity.isNew
|
||||
? localization.createdTaxRate
|
||||
: localization.updatedTaxRate)));
|
||||
break;
|
||||
case EntityType.companyGateway:
|
||||
store.dispatch(EditCompanyGateway(
|
||||
companyGateway: map[entityId],
|
||||
navigator: navigator,
|
||||
completer: completer,
|
||||
));
|
||||
completer: completer ??
|
||||
snackBarCompleter<CompanyGatewayEntity>(
|
||||
context,
|
||||
entity.isNew
|
||||
? localization.createdCompanyGateway
|
||||
: localization.updatedCompanyGateway)));
|
||||
break;
|
||||
case EntityType.invoice:
|
||||
store.dispatch(EditInvoice(
|
||||
invoice: map[entityId],
|
||||
navigator: navigator,
|
||||
completer: completer,
|
||||
completer: completer ??
|
||||
snackBarCompleter<InvoiceEntity>(
|
||||
context,
|
||||
entity.isNew
|
||||
? localization.createdInvoice
|
||||
: localization.updatedInvoice),
|
||||
invoiceItemIndex: subIndex,
|
||||
));
|
||||
break;
|
||||
|
|
@ -715,7 +748,12 @@ void editEntityById(
|
|||
store.dispatch(EditQuote(
|
||||
quote: map[entityId],
|
||||
navigator: navigator,
|
||||
completer: completer,
|
||||
completer: completer ??
|
||||
snackBarCompleter<InvoiceEntity>(
|
||||
context,
|
||||
entity.isNew
|
||||
? localization.createdQuote
|
||||
: localization.updatedQuote),
|
||||
quoteItemIndex: subIndex,
|
||||
));
|
||||
break;
|
||||
|
|
@ -723,28 +761,47 @@ void editEntityById(
|
|||
store.dispatch(EditVendor(
|
||||
vendor: map[entityId],
|
||||
navigator: navigator,
|
||||
completer: completer,
|
||||
completer: completer ??
|
||||
snackBarCompleter<VendorEntity>(
|
||||
context,
|
||||
entity.isNew
|
||||
? localization.createdVendor
|
||||
: localization.updatedVendor),
|
||||
));
|
||||
break;
|
||||
case EntityType.product:
|
||||
store.dispatch(EditProduct(
|
||||
product: map[entityId],
|
||||
navigator: navigator,
|
||||
completer: completer,
|
||||
));
|
||||
completer: completer ??
|
||||
snackBarCompleter<ProductEntity>(
|
||||
context,
|
||||
entity.isNew
|
||||
? localization.createdProduct
|
||||
: localization.updatedProduct)));
|
||||
break;
|
||||
case EntityType.task:
|
||||
store.dispatch(EditTask(
|
||||
task: map[entityId],
|
||||
navigator: navigator,
|
||||
completer: completer,
|
||||
completer: completer ??
|
||||
snackBarCompleter<TaskEntity>(
|
||||
context,
|
||||
entity.isNew
|
||||
? localization.createdTask
|
||||
: localization.updatedTask),
|
||||
));
|
||||
break;
|
||||
case EntityType.expense:
|
||||
store.dispatch(EditExpense(
|
||||
expense: map[entityId],
|
||||
navigator: navigator,
|
||||
completer: completer,
|
||||
completer: completer ??
|
||||
snackBarCompleter<ExpenseEntity>(
|
||||
context,
|
||||
entity.isNew
|
||||
? localization.createdExpense
|
||||
: localization.updatedExpense),
|
||||
));
|
||||
break;
|
||||
//case EntityType.expenseCategory:
|
||||
|
|
@ -757,14 +814,24 @@ void editEntityById(
|
|||
store.dispatch(EditPayment(
|
||||
payment: map[entityId],
|
||||
navigator: navigator,
|
||||
completer: completer,
|
||||
completer: completer ??
|
||||
snackBarCompleter<PaymentEntity>(
|
||||
context,
|
||||
entity.isNew
|
||||
? localization.createdPayment
|
||||
: localization.updatedPayment),
|
||||
));
|
||||
break;
|
||||
case EntityType.group:
|
||||
store.dispatch(EditGroup(
|
||||
group: map[entityId],
|
||||
navigator: navigator,
|
||||
completer: completer,
|
||||
completer: completer ??
|
||||
snackBarCompleter<GroupEntity>(
|
||||
context,
|
||||
entity.isNew
|
||||
? localization.createdGroup
|
||||
: localization.updatedGroup),
|
||||
));
|
||||
break;
|
||||
// TODO Add to starter
|
||||
|
|
@ -782,3 +849,59 @@ void editEntity(
|
|||
entityType: entity.entityType,
|
||||
subIndex: subIndex,
|
||||
completer: completer);
|
||||
|
||||
void handleEntityAction(
|
||||
BuildContext context, BaseEntity entity, dynamic action) {
|
||||
handleEntitiesActions(context, [entity], action);
|
||||
}
|
||||
|
||||
void handleEntitiesActions(
|
||||
BuildContext context, List<BaseEntity> entities, dynamic action) {
|
||||
if (entities.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (entities.first.entityType) {
|
||||
case EntityType.client:
|
||||
handleClientAction(context, entities, action);
|
||||
break;
|
||||
case EntityType.product:
|
||||
handleProductAction(context, entities, action);
|
||||
break;
|
||||
case EntityType.invoice:
|
||||
handleInvoiceAction(context, entities, action);
|
||||
break;
|
||||
case EntityType.payment:
|
||||
handlePaymentAction(context, entities, action);
|
||||
break;
|
||||
case EntityType.quote:
|
||||
handleQuoteAction(context, entities, action);
|
||||
break;
|
||||
case EntityType.task:
|
||||
handleTaskAction(context, entities, action);
|
||||
break;
|
||||
case EntityType.project:
|
||||
handleProjectAction(context, entities, action);
|
||||
break;
|
||||
case EntityType.expense:
|
||||
handleExpenseAction(context, entities, action);
|
||||
break;
|
||||
case EntityType.vendor:
|
||||
handleVendorAction(context, entities, action);
|
||||
break;
|
||||
case EntityType.user:
|
||||
handleUserAction(context, entities, action);
|
||||
break;
|
||||
case EntityType.companyGateway:
|
||||
handleCompanyGatewayAction(context, entities, action);
|
||||
break;
|
||||
case EntityType.taxRate:
|
||||
handleTaxRateAction(context, entities, action);
|
||||
break;
|
||||
case EntityType.group:
|
||||
handleGroupAction(context, entities, action);
|
||||
break;
|
||||
case EntityType.document:
|
||||
handleDocumentAction(context, entities, action);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_redux/flutter_redux.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart';
|
||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||
|
||||
import 'buttons/edit_icon_button.dart';
|
||||
import 'entities/entity_state_title.dart';
|
||||
|
||||
class ViewScaffold extends StatelessWidget {
|
||||
|
|
@ -19,6 +23,10 @@ class ViewScaffold extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
final state = store.state;
|
||||
final userCompany = state.userCompany;
|
||||
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
return true;
|
||||
|
|
@ -28,6 +36,24 @@ class ViewScaffold extends StatelessWidget {
|
|||
automaticallyImplyLeading: isMobile(context),
|
||||
title: EntityStateTitle(entity: entity),
|
||||
bottom: appBarBottom,
|
||||
actions: entity.isNew
|
||||
? []
|
||||
: [
|
||||
userCompany.canEditEntity(entity)
|
||||
? EditIconButton(
|
||||
isVisible: !entity.isDeleted,
|
||||
onPressed: () =>
|
||||
editEntity(context: context, entity: entity),
|
||||
)
|
||||
: Container(),
|
||||
ActionMenuButton(
|
||||
isSaving: state.isSaving,
|
||||
entity: entity,
|
||||
onSelected: (context, action) =>
|
||||
handleEntityAction(context, entity, action),
|
||||
entityActions: entity.getActions(userCompany: userCompany),
|
||||
)
|
||||
],
|
||||
),
|
||||
body: body,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ import 'package:invoiceninja_flutter/data/models/models.dart';
|
|||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
|
||||
import 'package:invoiceninja_flutter/ui/client/client_screen.dart';
|
||||
import 'package:invoiceninja_flutter/ui/client/view/client_view.dart';
|
||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ class CompanyGatewayEditVM {
|
|||
@required this.origCompanyGateway,
|
||||
@required this.onSavePressed,
|
||||
@required this.onCancelPressed,
|
||||
@required this.onBackPressed,
|
||||
@required this.isLoading,
|
||||
});
|
||||
|
||||
|
|
@ -64,13 +63,6 @@ class CompanyGatewayEditVM {
|
|||
onChanged: (CompanyGatewayEntity companyGateway) {
|
||||
store.dispatch(UpdateCompanyGateway(companyGateway));
|
||||
},
|
||||
onBackPressed: () {
|
||||
if (state.uiState.currentRoute.contains(CompanyGatewayScreen.route)) {
|
||||
store.dispatch(UpdateCurrentRoute(companyGateway.isNew
|
||||
? CompanyGatewayScreen.route
|
||||
: CompanyGatewayViewScreen.route));
|
||||
}
|
||||
},
|
||||
onCancelPressed: (BuildContext context) {
|
||||
store.dispatch(UpdateCurrentRoute(state.uiState.previousRoute));
|
||||
},
|
||||
|
|
@ -111,7 +103,6 @@ class CompanyGatewayEditVM {
|
|||
final Function(CompanyGatewayEntity) onChanged;
|
||||
final Function(BuildContext) onSavePressed;
|
||||
final Function(BuildContext) onCancelPressed;
|
||||
final Function onBackPressed;
|
||||
final bool isLoading;
|
||||
final bool isSaving;
|
||||
final CompanyGatewayEntity origCompanyGateway;
|
||||
|
|
|
|||
|
|
@ -2,15 +2,12 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:invoiceninja_flutter/redux/document/document_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/buttons/edit_icon_button.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_state_title.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/view_scaffold.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/view/expense_view_details.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/view/expense_view_documents.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/view/expense_view_vm.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/view/expense_view_overview.dart';
|
||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||
|
||||
class ExpenseView extends StatefulWidget {
|
||||
const ExpenseView({
|
||||
|
|
@ -45,20 +42,46 @@ class _ExpenseViewState extends State<ExpenseView>
|
|||
final localization = AppLocalization.of(context);
|
||||
final viewModel = widget.viewModel;
|
||||
final company = viewModel.state.company;
|
||||
final expense = viewModel.expense;
|
||||
final documentState = viewModel.state.documentState;
|
||||
final documents =
|
||||
memoizedExpenseDocumentsSelector(documentState.map, viewModel.expense);
|
||||
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
viewModel.onBackPressed();
|
||||
return true;
|
||||
},
|
||||
child: Scaffold(
|
||||
appBar: _CustomAppBar(
|
||||
viewModel: viewModel,
|
||||
return ViewScaffold(
|
||||
entity: expense,
|
||||
appBarBottom: TabBar(
|
||||
controller: _controller,
|
||||
tabs: [
|
||||
Tab(
|
||||
text: localization.overview,
|
||||
),
|
||||
body: CustomTabBarView(
|
||||
viewModel: viewModel,
|
||||
Tab(
|
||||
text: localization.details,
|
||||
),
|
||||
Tab(
|
||||
text: documents.isEmpty
|
||||
? localization.documents
|
||||
: '${localization.documents} (${documents.length})',
|
||||
),
|
||||
],
|
||||
),
|
||||
body: TabBarView(
|
||||
controller: _controller,
|
||||
children: <Widget>[
|
||||
RefreshIndicator(
|
||||
onRefresh: () => viewModel.onRefreshed(context),
|
||||
child: ExpenseOverview(viewModel: viewModel),
|
||||
),
|
||||
RefreshIndicator(
|
||||
onRefresh: () => viewModel.onRefreshed(context),
|
||||
child: ExpenseViewDetails(expense: viewModel.expense),
|
||||
),
|
||||
RefreshIndicator(
|
||||
onRefresh: () => viewModel.onRefreshed(context),
|
||||
child: ExpenseViewDocuments(
|
||||
viewModel: viewModel, expense: viewModel.expense),
|
||||
),
|
||||
],
|
||||
),
|
||||
floatingActionButton: company.isEnterprisePlan
|
||||
? Builder(builder: (BuildContext context) {
|
||||
|
|
@ -80,112 +103,6 @@ class _ExpenseViewState extends State<ExpenseView>
|
|||
);
|
||||
})
|
||||
: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CustomTabBarView extends StatefulWidget {
|
||||
const CustomTabBarView({
|
||||
@required this.viewModel,
|
||||
@required this.controller,
|
||||
});
|
||||
|
||||
final ExpenseViewVM viewModel;
|
||||
final TabController controller;
|
||||
|
||||
@override
|
||||
_CustomTabBarViewState createState() => _CustomTabBarViewState();
|
||||
}
|
||||
|
||||
class _CustomTabBarViewState extends State<CustomTabBarView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final viewModel = widget.viewModel;
|
||||
|
||||
return TabBarView(
|
||||
controller: widget.controller,
|
||||
children: <Widget>[
|
||||
RefreshIndicator(
|
||||
onRefresh: () => viewModel.onRefreshed(context),
|
||||
child: ExpenseOverview(viewModel: viewModel),
|
||||
),
|
||||
RefreshIndicator(
|
||||
onRefresh: () => viewModel.onRefreshed(context),
|
||||
child: ExpenseViewDetails(expense: viewModel.expense),
|
||||
),
|
||||
RefreshIndicator(
|
||||
onRefresh: () => viewModel.onRefreshed(context),
|
||||
child: ExpenseViewDocuments(
|
||||
viewModel: viewModel, expense: viewModel.expense),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
const _CustomAppBar({
|
||||
@required this.viewModel,
|
||||
@required this.controller,
|
||||
});
|
||||
|
||||
final ExpenseViewVM viewModel;
|
||||
final TabController controller;
|
||||
|
||||
@override
|
||||
final Size preferredSize = const Size(double.infinity, kToolbarHeight * 2);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localization = AppLocalization.of(context);
|
||||
final expense = viewModel.expense;
|
||||
final userCompany = viewModel.state.userCompany;
|
||||
final documentState = viewModel.state.documentState;
|
||||
final documents =
|
||||
memoizedExpenseDocumentsSelector(documentState.map, viewModel.expense);
|
||||
|
||||
return AppBar(
|
||||
automaticallyImplyLeading: isMobile(context),
|
||||
title: EntityStateTitle(
|
||||
entity: expense,
|
||||
title: expense.publicNotes.isNotEmpty
|
||||
? expense.publicNotes
|
||||
: localization.expense,
|
||||
),
|
||||
bottom: TabBar(
|
||||
controller: controller,
|
||||
tabs: [
|
||||
Tab(
|
||||
text: localization.overview,
|
||||
),
|
||||
Tab(
|
||||
text: localization.details,
|
||||
),
|
||||
Tab(
|
||||
text: documents.isEmpty
|
||||
? localization.documents
|
||||
: '${localization.documents} (${documents.length})',
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: expense.isNew
|
||||
? []
|
||||
: [
|
||||
userCompany.canEditEntity(expense)
|
||||
? EditIconButton(
|
||||
isVisible: !expense.isDeleted,
|
||||
onPressed: () => viewModel.onEditPressed(context),
|
||||
)
|
||||
: Container(),
|
||||
ActionMenuButton(
|
||||
isSaving: viewModel.isSaving,
|
||||
entity: expense,
|
||||
onSelected: viewModel.onEntityAction,
|
||||
entityActions:
|
||||
viewModel.expense.getActions(userCompany: userCompany),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -46,7 +46,6 @@ class ExpenseViewVM {
|
|||
@required this.onEntityAction,
|
||||
@required this.onEntityPressed,
|
||||
@required this.onEditPressed,
|
||||
@required this.onBackPressed,
|
||||
@required this.onRefreshed,
|
||||
@required this.onUploadDocument,
|
||||
@required this.onDeleteDocument,
|
||||
|
|
@ -85,11 +84,6 @@ class ExpenseViewVM {
|
|||
context, AppLocalization.of(context).updatedExpense));
|
||||
},
|
||||
onRefreshed: (context) => _handleRefresh(context),
|
||||
onBackPressed: () {
|
||||
if (state.uiState.currentRoute.contains(ExpenseScreen.route)) {
|
||||
store.dispatch(UpdateCurrentRoute(ExpenseScreen.route));
|
||||
}
|
||||
},
|
||||
onEntityPressed: (BuildContext context, EntityType entityType,
|
||||
[longPress = false]) {
|
||||
switch (entityType) {
|
||||
|
|
@ -157,7 +151,6 @@ class ExpenseViewVM {
|
|||
final Function(BuildContext, EntityAction) onEntityAction;
|
||||
final Function(BuildContext, EntityType, [bool]) onEntityPressed;
|
||||
final Function(BuildContext) onEditPressed;
|
||||
final Function onBackPressed;
|
||||
final Function(BuildContext) onRefreshed;
|
||||
final Function(BuildContext, String) onUploadDocument;
|
||||
final Function(BuildContext, DocumentEntity) onDeleteDocument;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/edit_scaffold.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
|
||||
import 'package:invoiceninja_flutter/ui/group/edit/group_edit_vm.dart';
|
||||
|
|
@ -79,44 +80,19 @@ class _GroupEditState extends State<GroupEdit> {
|
|||
final localization = AppLocalization.of(context);
|
||||
final group = viewModel.group;
|
||||
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
viewModel.onBackPressed();
|
||||
return true;
|
||||
},
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: isMobile(context),
|
||||
title: Text(viewModel.group.isNew
|
||||
? localization.newGroup
|
||||
: localization.editGroup),
|
||||
actions: <Widget>[
|
||||
if (!isMobile(context))
|
||||
FlatButton(
|
||||
child: Text(
|
||||
localization.cancel,
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
onPressed: () => viewModel.onCancelPressed(context),
|
||||
),
|
||||
ActionFlatButton(
|
||||
tooltip: localization.save,
|
||||
isVisible: !(group.isDeleted ?? false),
|
||||
// TODO remove this
|
||||
isDirty: group.isNew || group != viewModel.origGroup,
|
||||
isSaving: viewModel.isSaving,
|
||||
onPressed: () {
|
||||
return EditScaffold(
|
||||
onCancelPressed: (context) => viewModel.onCancelPressed(context),
|
||||
title: group.isNew ? localization.newGroup : localization.editGroup,
|
||||
onSavePressed: (context) {
|
||||
if (!_formKey.currentState.validate()) {
|
||||
return;
|
||||
}
|
||||
viewModel.onSavePressed(context);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Form(
|
||||
key: _formKey,
|
||||
child: Builder(builder: (BuildContext context) {
|
||||
child: Builder(
|
||||
builder: (BuildContext context) {
|
||||
return ListView(
|
||||
children: <Widget>[
|
||||
FormCard(
|
||||
|
|
@ -129,7 +105,8 @@ class _GroupEditState extends State<GroupEdit> {
|
|||
),
|
||||
],
|
||||
);
|
||||
})),
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ class GroupEditVM {
|
|||
@required this.origGroup,
|
||||
@required this.onSavePressed,
|
||||
@required this.onCancelPressed,
|
||||
@required this.onBackPressed,
|
||||
@required this.isLoading,
|
||||
});
|
||||
|
||||
|
|
@ -64,12 +63,6 @@ class GroupEditVM {
|
|||
onChanged: (GroupEntity group) {
|
||||
store.dispatch(UpdateGroup(group));
|
||||
},
|
||||
onBackPressed: () {
|
||||
if (state.uiState.currentRoute.contains(GroupSettingsScreen.route)) {
|
||||
store.dispatch(UpdateCurrentRoute(
|
||||
group.isNew ? GroupSettingsScreen.route : GroupViewScreen.route));
|
||||
}
|
||||
},
|
||||
onCancelPressed: (BuildContext context) {
|
||||
createEntity(context: context, entity: GroupEntity(), force: true);
|
||||
store.dispatch(UpdateCurrentRoute(state.uiState.previousRoute));
|
||||
|
|
@ -104,7 +97,6 @@ class GroupEditVM {
|
|||
final Function(GroupEntity) onChanged;
|
||||
final Function(BuildContext) onSavePressed;
|
||||
final Function(BuildContext) onCancelPressed;
|
||||
final Function onBackPressed;
|
||||
final bool isLoading;
|
||||
final bool isSaving;
|
||||
final GroupEntity origGroup;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ class EntityViewVM {
|
|||
@required this.onUploadDocument,
|
||||
@required this.onDeleteDocument,
|
||||
@required this.onEditPressed,
|
||||
@required this.onBackPressed,
|
||||
@required this.onClientPressed,
|
||||
@required this.onPaymentsPressed,
|
||||
@required this.onPaymentPressed,
|
||||
|
|
@ -70,7 +69,6 @@ class EntityViewVM {
|
|||
final Function(BuildContext) onPaymentsPressed;
|
||||
final Function(BuildContext, PaymentEntity, [bool]) onPaymentPressed;
|
||||
final Function(BuildContext) onRefreshed;
|
||||
final Function onBackPressed;
|
||||
final Function(BuildContext, String) onUploadDocument;
|
||||
final Function(BuildContext, DocumentEntity) onDeleteDocument;
|
||||
final Function(BuildContext, DocumentEntity) onViewExpense;
|
||||
|
|
@ -90,7 +88,6 @@ class InvoiceViewVM extends EntityViewVM {
|
|||
Function(BuildContext, PaymentEntity, [bool]) onPaymentPressed,
|
||||
Function(BuildContext) onPaymentsPressed,
|
||||
Function(BuildContext) onRefreshed,
|
||||
Function onBackPressed,
|
||||
Function(BuildContext, String) onUploadDocument,
|
||||
Function(BuildContext, DocumentEntity) onDeleteDocument,
|
||||
Function(BuildContext, DocumentEntity) onViewExpense,
|
||||
|
|
@ -107,7 +104,6 @@ class InvoiceViewVM extends EntityViewVM {
|
|||
onPaymentPressed: onPaymentPressed,
|
||||
onPaymentsPressed: onPaymentsPressed,
|
||||
onRefreshed: onRefreshed,
|
||||
onBackPressed: onBackPressed,
|
||||
onUploadDocument: onUploadDocument,
|
||||
onDeleteDocument: onDeleteDocument,
|
||||
onViewExpense: onViewExpense);
|
||||
|
|
@ -140,11 +136,6 @@ class InvoiceViewVM extends EntityViewVM {
|
|||
context, AppLocalization.of(context).updatedInvoice));
|
||||
},
|
||||
onRefreshed: (context) => _handleRefresh(context),
|
||||
onBackPressed: () {
|
||||
if (state.uiState.currentRoute.contains(InvoiceScreen.route)) {
|
||||
store.dispatch(UpdateCurrentRoute(InvoiceScreen.route));
|
||||
}
|
||||
},
|
||||
onClientPressed: (BuildContext context, [bool longPress = false]) {
|
||||
if (longPress) {
|
||||
showEntityActionsDialog(
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ class ProductViewVM {
|
|||
@required this.company,
|
||||
@required this.onEntityAction,
|
||||
@required this.onEditPressed,
|
||||
@required this.onBackPressed,
|
||||
@required this.isSaving,
|
||||
@required this.isLoading,
|
||||
@required this.isDirty,
|
||||
|
|
@ -83,11 +82,6 @@ class ProductViewVM {
|
|||
onRefreshed: (context, loadActivities) =>
|
||||
_handleRefresh(context, loadActivities),
|
||||
*/
|
||||
onBackPressed: () {
|
||||
if (state.uiState.currentRoute.contains(ProductScreen.route)) {
|
||||
store.dispatch(UpdateCurrentRoute(ProductScreen.route));
|
||||
}
|
||||
},
|
||||
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||
handleProductAction(context, [product], action),
|
||||
);
|
||||
|
|
@ -98,7 +92,6 @@ class ProductViewVM {
|
|||
final CompanyEntity company;
|
||||
final Function(BuildContext, EntityAction) onEntityAction;
|
||||
final Function(BuildContext) onEditPressed;
|
||||
final Function onBackPressed;
|
||||
final Function(BuildContext, bool) onRefreshed;
|
||||
final bool isSaving;
|
||||
final bool isLoading;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ class ProjectViewVM {
|
|||
@required this.onEntityAction,
|
||||
@required this.onTasksPressed,
|
||||
@required this.onEditPressed,
|
||||
@required this.onBackPressed,
|
||||
@required this.onAddTaskPressed,
|
||||
@required this.onClientPressed,
|
||||
@required this.onRefreshed,
|
||||
|
|
@ -113,11 +112,6 @@ class ProjectViewVM {
|
|||
..clientId = project.clientId),
|
||||
force: true);
|
||||
},
|
||||
onBackPressed: () {
|
||||
if (state.uiState.currentRoute.contains(ProjectScreen.route)) {
|
||||
store.dispatch(UpdateCurrentRoute(ProjectScreen.route));
|
||||
}
|
||||
},
|
||||
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||
handleProjectAction(context, [project], action),
|
||||
);
|
||||
|
|
@ -130,7 +124,6 @@ class ProjectViewVM {
|
|||
final Function(BuildContext, EntityAction) onEntityAction;
|
||||
final Function(BuildContext) onEditPressed;
|
||||
final Function(BuildContext, [bool]) onClientPressed;
|
||||
final Function onBackPressed;
|
||||
final Function(BuildContext) onAddTaskPressed;
|
||||
final Function(BuildContext, {bool longPress}) onTasksPressed;
|
||||
final Function(BuildContext) onRefreshed;
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ class QuoteViewVM extends EntityViewVM {
|
|||
Function(BuildContext) onPaymentsPressed,
|
||||
Function(BuildContext, PaymentEntity) onPaymentPressed,
|
||||
Function(BuildContext) onRefreshed,
|
||||
Function onBackPressed,
|
||||
Function(BuildContext, String) onUploadDocument,
|
||||
Function(BuildContext, DocumentEntity) onDeleteDocument,
|
||||
Function(BuildContext, DocumentEntity) onViewExpense,
|
||||
|
|
@ -71,7 +70,6 @@ class QuoteViewVM extends EntityViewVM {
|
|||
onPaymentsPressed: onPaymentsPressed,
|
||||
onPaymentPressed: onPaymentPressed,
|
||||
onRefreshed: onRefreshed,
|
||||
onBackPressed: onBackPressed,
|
||||
onUploadDocument: onUploadDocument,
|
||||
onDeleteDocument: onDeleteDocument,
|
||||
onViewExpense: onViewExpense,
|
||||
|
|
@ -107,11 +105,6 @@ class QuoteViewVM extends EntityViewVM {
|
|||
context, AppLocalization.of(context).updatedQuote));
|
||||
},
|
||||
onRefreshed: (context) => _handleRefresh(context),
|
||||
onBackPressed: () {
|
||||
if (state.uiState.currentRoute.contains(QuoteScreen.route)) {
|
||||
store.dispatch(UpdateCurrentRoute(QuoteScreen.route));
|
||||
}
|
||||
},
|
||||
onClientPressed: (BuildContext context, [bool longPress = false]) {
|
||||
if (longPress) {
|
||||
showEntityActionsDialog(
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ class TaskViewVM {
|
|||
@required this.state,
|
||||
@required this.onEntityAction,
|
||||
@required this.onEditPressed,
|
||||
@required this.onBackPressed,
|
||||
@required this.onRefreshed,
|
||||
@required this.onClientPressed,
|
||||
@required this.onProjectPressed,
|
||||
|
|
@ -157,11 +156,6 @@ class TaskViewVM {
|
|||
*/
|
||||
},
|
||||
onRefreshed: (context) => _handleRefresh(context),
|
||||
onBackPressed: () {
|
||||
if (state.uiState.currentRoute.contains(TaskScreen.route)) {
|
||||
store.dispatch(UpdateCurrentRoute(TaskScreen.route));
|
||||
}
|
||||
},
|
||||
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||
handleTaskAction(context, [task], action),
|
||||
);
|
||||
|
|
@ -174,7 +168,6 @@ class TaskViewVM {
|
|||
final CompanyEntity company;
|
||||
final Function(BuildContext, EntityAction) onEntityAction;
|
||||
final Function(BuildContext, [TaskTime]) onEditPressed;
|
||||
final Function onBackPressed;
|
||||
final Function(BuildContext) onFabPressed;
|
||||
final Function(BuildContext) onRefreshed;
|
||||
final Function(BuildContext, [bool]) onClientPressed;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ class TaxRateEditVM {
|
|||
@required this.origTaxRate,
|
||||
@required this.onSavePressed,
|
||||
@required this.onCancelPressed,
|
||||
@required this.onBackPressed,
|
||||
@required this.isLoading,
|
||||
});
|
||||
|
||||
|
|
@ -68,13 +67,6 @@ class TaxRateEditVM {
|
|||
createEntity(context: context, entity: TaxRateEntity(), force: true);
|
||||
store.dispatch(UpdateCurrentRoute(state.uiState.previousRoute));
|
||||
},
|
||||
onBackPressed: () {
|
||||
if (state.uiState.currentRoute.contains(TaxRateSettingsScreen.route)) {
|
||||
store.dispatch(UpdateCurrentRoute(taxRate.isNew
|
||||
? TaxRateSettingsScreen.route
|
||||
: TaxRateViewScreen.route));
|
||||
}
|
||||
},
|
||||
onSavePressed: (BuildContext context) {
|
||||
final Completer<TaxRateEntity> completer =
|
||||
new Completer<TaxRateEntity>();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:invoiceninja_flutter/constants.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/company_model.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/edit_scaffold.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/forms/app_form.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
|
||||
|
|
@ -108,40 +109,16 @@ class _UserEditState extends State<UserEdit> {
|
|||
final user = viewModel.user;
|
||||
final userCompany = user.userCompany;
|
||||
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
viewModel.onBackPressed();
|
||||
return true;
|
||||
},
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: isMobile(context),
|
||||
title: Text(viewModel.user.isNew
|
||||
? localization.newUser
|
||||
: localization.editUser),
|
||||
actions: <Widget>[
|
||||
if (!isMobile(context))
|
||||
FlatButton(
|
||||
child: Text(
|
||||
localization.cancel,
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
onPressed: () => viewModel.onCancelPressed(context),
|
||||
),
|
||||
ActionFlatButton(
|
||||
tooltip: localization.save,
|
||||
isVisible: user.isActive,
|
||||
isDirty: user.isNew || user != viewModel.origUser,
|
||||
isSaving: viewModel.isSaving,
|
||||
onPressed: () {
|
||||
return EditScaffold(
|
||||
title:
|
||||
viewModel.user.isNew ? localization.newUser : localization.editUser,
|
||||
onCancelPressed: (context) => viewModel.onCancelPressed(context),
|
||||
onSavePressed: (context) {
|
||||
if (!_formKey.currentState.validate()) {
|
||||
return;
|
||||
}
|
||||
viewModel.onSavePressed(context);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
body: AppForm(
|
||||
focusNode: _focusNode,
|
||||
formKey: _formKey,
|
||||
|
|
@ -219,8 +196,7 @@ class _UserEditState extends State<UserEdit> {
|
|||
onChanged: (value) =>
|
||||
_togglePermission(kPermissionCreateAll),
|
||||
),
|
||||
onTap: () =>
|
||||
_togglePermission(kPermissionCreateAll)),
|
||||
onTap: () => _togglePermission(kPermissionCreateAll)),
|
||||
DataCell(
|
||||
_PermissionCheckbox(
|
||||
userCompany: userCompany,
|
||||
|
|
@ -245,8 +221,7 @@ class _UserEditState extends State<UserEdit> {
|
|||
EntityType.payment,
|
||||
EntityType.quote,
|
||||
].map((EntityType type) {
|
||||
final createPermission =
|
||||
'create_' + toSnakeCase('$type');
|
||||
final createPermission = 'create_' + toSnakeCase('$type');
|
||||
final editPermission = 'edit_' + toSnakeCase('$type');
|
||||
final viewPermission = 'view_' + toSnakeCase('$type');
|
||||
return DataRow(cells: [
|
||||
|
|
@ -298,7 +273,6 @@ class _UserEditState extends State<UserEdit> {
|
|||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ class UserEditVM {
|
|||
@required this.origUser,
|
||||
@required this.onSavePressed,
|
||||
@required this.onCancelPressed,
|
||||
@required this.onBackPressed,
|
||||
@required this.isLoading,
|
||||
});
|
||||
|
||||
|
|
@ -66,12 +65,6 @@ class UserEditVM {
|
|||
onUserChanged: (UserEntity user) {
|
||||
store.dispatch(UpdateUser(user));
|
||||
},
|
||||
onBackPressed: () {
|
||||
if (state.uiState.currentRoute.contains(UserScreen.route)) {
|
||||
store.dispatch(UpdateCurrentRoute(
|
||||
user.isNew ? UserScreen.route : UserViewScreen.route));
|
||||
}
|
||||
},
|
||||
onCancelPressed: (BuildContext context) {
|
||||
createEntity(context: context, entity: UserEntity(), force: true);
|
||||
store.dispatch(UpdateCurrentRoute(state.uiState.previousRoute));
|
||||
|
|
@ -107,7 +100,6 @@ class UserEditVM {
|
|||
final Function(UserEntity) onUserChanged;
|
||||
final Function(BuildContext) onSavePressed;
|
||||
final Function(BuildContext) onCancelPressed;
|
||||
final Function onBackPressed;
|
||||
final bool isLoading;
|
||||
final bool isSaving;
|
||||
final UserEntity origUser;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ class VendorViewVM {
|
|||
@required this.onEntityAction,
|
||||
@required this.onEntityPressed,
|
||||
@required this.onEditPressed,
|
||||
@required this.onBackPressed,
|
||||
@required this.onRefreshed,
|
||||
@required this.isSaving,
|
||||
@required this.isLoading,
|
||||
|
|
@ -77,11 +76,6 @@ class VendorViewVM {
|
|||
context, AppLocalization.of(context).updatedVendor));
|
||||
},
|
||||
onRefreshed: (context) => _handleRefresh(context),
|
||||
onBackPressed: () {
|
||||
if (state.uiState.currentRoute.contains(VendorScreen.route)) {
|
||||
store.dispatch(UpdateCurrentRoute(VendorScreen.route));
|
||||
}
|
||||
},
|
||||
onEntityPressed: (BuildContext context, EntityType entityType,
|
||||
[longPress = false]) {
|
||||
switch (entityType) {
|
||||
|
|
@ -115,7 +109,6 @@ class VendorViewVM {
|
|||
final Function(BuildContext, EntityAction) onEntityAction;
|
||||
final Function(BuildContext) onEditPressed;
|
||||
final Function(BuildContext, EntityType, [bool]) onEntityPressed;
|
||||
final Function onBackPressed;
|
||||
final Function(BuildContext) onRefreshed;
|
||||
final Function(BuildContext) onAddExpensePressed;
|
||||
final bool isSaving;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ class StubViewVM {
|
|||
@required this.company,
|
||||
@required this.onEntityAction,
|
||||
@required this.onEditPressed,
|
||||
@required this.onBackPressed,
|
||||
@required this.onRefreshed,
|
||||
@required this.isSaving,
|
||||
@required this.isLoading,
|
||||
|
|
@ -75,11 +74,6 @@ class StubViewVM {
|
|||
context, AppLocalization.of(context).updatedStub));
|
||||
},
|
||||
onRefreshed: (context) => _handleRefresh(context),
|
||||
onBackPressed: () {
|
||||
if (state.uiState.currentRoute.contains(StubScreen.route)) {
|
||||
store.dispatch(UpdateCurrentRoute(StubScreen.route));
|
||||
}
|
||||
},
|
||||
onEntityAction: (BuildContext context, EntityAction action) =>
|
||||
handleStubAction(context, stub, action),
|
||||
);
|
||||
|
|
@ -90,7 +84,6 @@ class StubViewVM {
|
|||
final CompanyEntity company;
|
||||
final Function(BuildContext, EntityAction) onEntityAction;
|
||||
final Function(BuildContext) onEditPressed;
|
||||
final Function onBackPressed;
|
||||
final Function(BuildContext) onRefreshed;
|
||||
final bool isSaving;
|
||||
final bool isLoading;
|
||||
|
|
|
|||
Loading…
Reference in New Issue