This commit is contained in:
Hillel Coren 2019-11-17 09:08:22 +02:00
parent 3b83a86a29
commit bd66941380
3 changed files with 156 additions and 115 deletions

View File

@ -258,7 +258,6 @@ abstract class CompanyEntity extends Object
}
}
// TODO remove this
if ([
EntityType.recurringInvoice,
@ -437,10 +436,18 @@ abstract class UserCompanyEntity
String get permissions;
bool can(UserPermission permission, EntityType entityType) =>
(isAdmin ?? false) ||
permissions.contains('${permission}_all') ||
permissions.contains('${permission}_$entityType');
bool can(UserPermission permission, EntityType entityType) {
if (entityType == null) {
return false;
}
if (isAdmin ?? false) {
return true;
}
return permissions.contains('${permission}_all') ||
permissions.contains('${permission}_$entityType');
}
bool canView(EntityType entityType) => can(UserPermission.view, entityType);
@ -1478,7 +1485,6 @@ abstract class SettingsEntity
@BuiltValueField(wireName: 'email_template_reminder4')
String get emailBodyReminder4;
// Added
@nullable
@BuiltValueField(wireName: 'enable_client_portal')
@ -1496,7 +1502,6 @@ abstract class SettingsEntity
@BuiltValueField(wireName: 'client_manual_payment_notification')
bool get clientManualPaymentNotification;
// TODO remove this field
@nullable
@BuiltValueField(wireName: 'custom_payment_terms')

View File

@ -1,7 +1,10 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/data/models/company_gateway_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/group_model.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
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';
@ -108,6 +111,61 @@ class FilterCompany implements PersistUI {
final String filter;
}
void viewEntitiesByType({BuildContext context, EntityType entityType}) {
final store = StoreProvider.of<AppState>(context);
switch (entityType) {
case EntityType.client:
store.dispatch(ViewClientList(context: context));
break;
case EntityType.user:
store.dispatch(ViewUserList(context: context));
break;
case EntityType.project:
store.dispatch(ViewProjectList(context: context));
break;
case EntityType.taxRate:
store.dispatch(ViewTaxRateList(context: context));
break;
case EntityType.companyGateway:
store.dispatch(ViewCompanyGatewayList(context: context));
break;
case EntityType.invoice:
store.dispatch(ViewInvoiceList(context: context));
break;
//case EntityType.recurringInvoice:
//store.dispatch(ViewRecurringInvoice(recurringInvoiceId: entityId, context: context));
//break;
case EntityType.quote:
store.dispatch(ViewQuoteList(context: context));
break;
case EntityType.vendor:
store.dispatch(ViewVendorList(context: context));
break;
case EntityType.product:
store.dispatch(ViewProductList(context: context));
break;
case EntityType.task:
store.dispatch(ViewTaskList(context: context));
break;
case EntityType.expense:
store.dispatch(ViewExpenseList(context: context));
break;
//case EntityType.expenseCategory:
//store.dispatch(ViewExpenseCategory(taxRateId: entityId, context: context));
//break;
//case EntityType.credit:
//store.dispatch(ViewCredit(creditId: entityId, context: context));
//break;
case EntityType.payment:
store.dispatch(ViewPaymentList(context: context));
break;
case EntityType.group:
store.dispatch(ViewGroupList(context: context));
break;
// TODO Add to starter
}
}
void viewEntityById(
{BuildContext context, String entityId, EntityType entityType}) {
final store = StoreProvider.of<AppState>(context);
@ -165,6 +223,72 @@ void viewEntityById(
}
}
void createEntityByType({BuildContext context, EntityType entityType}) {
final store = StoreProvider.of<AppState>(context);
final state = store.state;
final company = state.company;
switch (entityType) {
case EntityType.client:
store.dispatch(EditClient(context: context, client: ClientEntity()));
break;
case EntityType.user:
store.dispatch(EditUser(context: context, user: UserEntity()));
break;
case EntityType.project:
store.dispatch(EditProject(context: context, project: ProjectEntity()));
break;
case EntityType.taxRate:
store.dispatch(EditTaxRate(context: context, taxRate: TaxRateEntity()));
break;
case EntityType.companyGateway:
store.dispatch(EditCompanyGateway(
context: context, companyGateway: CompanyGatewayEntity()));
break;
case EntityType.invoice:
store.dispatch(EditInvoice(
context: context, invoice: InvoiceEntity(company: company)));
break;
//case EntityType.recurringInvoice:
//store.dispatch(ViewRecurringInvoice(recurringInvoiceId: entityId, context: context));
//break;
case EntityType.quote:
store.dispatch(EditQuote(
context: context,
quote: InvoiceEntity(company: company, isQuote: true)));
break;
case EntityType.vendor:
store.dispatch(EditVendor(context: context, vendor: VendorEntity()));
break;
case EntityType.product:
store.dispatch(EditProduct(context: context, product: ProductEntity()));
break;
case EntityType.task:
store.dispatch(EditTask(
context: context,
task: TaskEntity(isRunning: state.prefState.autoStartTasks)));
break;
case EntityType.expense:
store.dispatch(EditExpense(
context: context,
expense: ExpenseEntity(prefState: state.prefState)));
break;
//case EntityType.expenseCategory:
//store.dispatch(ViewExpenseCategory(taxRateId: entityId, context: context));
//break;
//case EntityType.credit:
//store.dispatch(ViewCredit(creditId: entityId, context: context));
//break;
case EntityType.payment:
store.dispatch(EditPayment(
context: context, payment: PaymentEntity(company: company)));
break;
case EntityType.group:
store.dispatch(EditGroup(context: context, group: GroupEntity()));
break;
// TODO Add to starter
}
}
void editEntityById(
{BuildContext context, String entityId, EntityType entityType}) {
final store = StoreProvider.of<AppState>(context);

View File

@ -1,10 +1,7 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/redux/expense/expense_actions.dart';
import 'package:invoiceninja_flutter/redux/project/project_actions.dart';
import 'package:invoiceninja_flutter/redux/task/task_actions.dart';
import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart';
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
import 'package:invoiceninja_flutter/ui/app/debug/state_inspector.dart';
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
import 'package:invoiceninja_flutter/ui/app/resources/cached_image.dart';
@ -14,10 +11,7 @@ import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
import 'package:invoiceninja_flutter/redux/dashboard/dashboard_actions.dart';
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
import 'package:invoiceninja_flutter/redux/product/product_actions.dart';
import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart';
import 'package:invoiceninja_flutter/ui/app/menu_drawer_vm.dart';
import 'package:invoiceninja_flutter/ui/app/lists/selected_indicator.dart';
@ -25,8 +19,6 @@ import 'package:invoiceninja_flutter/utils/icons.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:invoiceninja_flutter/utils/platforms.dart';
import 'package:invoiceninja_flutter/redux/payment/payment_actions.dart';
import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart';
import 'package:url_launcher/url_launcher.dart';
// STARTER: import - do not remove comment
@ -139,7 +131,6 @@ class MenuDrawer extends StatelessWidget {
));
final Store<AppState> store = StoreProvider.of<AppState>(context);
final NavigatorState navigator = Navigator.of(context);
final state = store.state;
final enableDarkMode = state.prefState.enableDarkMode;
final localization = AppLocalization.of(context);
@ -183,79 +174,30 @@ class MenuDrawer extends StatelessWidget {
entityType: EntityType.client,
icon: getEntityIcon(EntityType.client),
title: localization.clients,
onTap: () =>
store.dispatch(ViewClientList(context: context)),
onCreateTap: () {
if (isMobile(context)) {
navigator.pop();
}
store.dispatch(EditClient(
client: ClientEntity(), context: context));
},
),
DrawerTile(
company: company,
entityType: EntityType.product,
icon: getEntityIcon(EntityType.product),
title: localization.products,
onTap: () {
store.dispatch(ViewProductList(context: context));
},
onCreateTap: () {
if (isMobile(context)) {
navigator.pop();
}
store.dispatch(EditProduct(
product: ProductEntity(), context: context));
},
),
DrawerTile(
company: company,
entityType: EntityType.invoice,
icon: getEntityIcon(EntityType.invoice),
title: localization.invoices,
onTap: () =>
store.dispatch(ViewInvoiceList(context: context)),
onCreateTap: () {
if (isMobile(context)) {
navigator.pop();
}
store.dispatch(EditInvoice(
invoice: InvoiceEntity(company: company),
context: context));
},
),
DrawerTile(
company: company,
entityType: EntityType.payment,
icon: getEntityIcon(EntityType.payment),
title: localization.payments,
onTap: () =>
store.dispatch(ViewPaymentList(context: context)),
onCreateTap: () {
if (isMobile(context)) {
navigator.pop();
}
store.dispatch(EditPayment(
payment: PaymentEntity(company: company),
context: context));
},
),
DrawerTile(
company: company,
entityType: EntityType.quote,
icon: getEntityIcon(EntityType.quote),
title: localization.quotes,
onTap: () =>
store.dispatch(ViewQuoteList(context: context)),
onCreateTap: () {
if (isMobile(context)) {
navigator.pop();
}
store.dispatch(EditQuote(
quote: InvoiceEntity(isQuote: true),
context: context));
},
),
if (Config.DEMO_MODE) ...[
DrawerTile(
@ -263,64 +205,24 @@ class MenuDrawer extends StatelessWidget {
entityType: EntityType.project,
icon: getEntityIcon(EntityType.project),
title: localization.projects,
onTap: () =>
store.dispatch(ViewProjectList(context: context)),
onCreateTap: () {
if (isMobile(context)) {
navigator.pop();
}
store.dispatch(EditProject(
project: ProjectEntity(), context: context));
},
),
DrawerTile(
company: company,
entityType: EntityType.task,
icon: getEntityIcon(EntityType.task),
title: localization.tasks,
onTap: () =>
store.dispatch(ViewTaskList(context: context)),
onCreateTap: () {
if (isMobile(context)) {
navigator.pop();
}
store.dispatch(EditTask(
task: TaskEntity(
isRunning: state.prefState.autoStartTasks),
context: context));
},
),
DrawerTile(
company: company,
entityType: EntityType.vendor,
icon: getEntityIcon(EntityType.vendor),
title: localization.vendors,
onTap: () =>
store.dispatch(ViewVendorList(context: context)),
onCreateTap: () {
if (isMobile(context)) {
navigator.pop();
}
store.dispatch(EditVendor(
vendor: VendorEntity(), context: context));
},
),
DrawerTile(
company: company,
entityType: EntityType.expense,
icon: getEntityIcon(EntityType.expense),
title: localization.expenses,
onTap: () =>
store.dispatch(ViewExpenseList(context: context)),
onCreateTap: () {
if (isMobile(context)) {
navigator.pop();
}
store.dispatch(EditExpense(
expense: ExpenseEntity(
company: company, prefState: state.prefState),
context: context));
},
),
],
// STARTER: menu - do not remove comment
@ -329,9 +231,6 @@ class MenuDrawer extends StatelessWidget {
icon: kIsWeb ? Icons.settings : FontAwesomeIcons.cog,
title: localization.settings,
onTap: () {
if (isMobile(context)) {
navigator.pop();
}
store.dispatch(ViewSettings(
context: context,
userCompany: state.userCompany));
@ -355,9 +254,10 @@ class DrawerTile extends StatelessWidget {
@required this.company,
@required this.icon,
@required this.title,
@required this.onTap,
this.onCreateTap,
this.onTap,
this.entityType,
this.onLongPress,
this.onCreateTap,
});
final CompanyEntity company;
@ -365,6 +265,7 @@ class DrawerTile extends StatelessWidget {
final IconData icon;
final String title;
final Function onTap;
final Function onLongPress;
final Function onCreateTap;
@override
@ -372,6 +273,7 @@ class DrawerTile extends StatelessWidget {
final store = StoreProvider.of<AppState>(context);
final uiState = store.state.uiState;
final userCompany = store.state.userCompany;
final NavigatorState navigator = Navigator.of(context);
if (entityType != null && !userCompany.canViewOrCreate(entityType)) {
return Container();
@ -389,13 +291,23 @@ class DrawerTile extends StatelessWidget {
child: ListTile(
dense: true,
leading: Icon(icon, size: 22),
title: Tooltip(message: title, child: Text(title)),
onTap: onTap,
trailing: onCreateTap == null || !userCompany.canCreate(entityType)
title: Text(title),
onTap: () => entityType != null
? viewEntitiesByType(context: context, entityType: entityType)
: onTap(),
onLongPress: () => entityType != null
? createEntityByType(context: context, entityType: entityType)
: null,
trailing: !userCompany.canCreate(entityType)
? null
: IconButton(
icon: Icon(Icons.add_circle_outline),
onPressed: onCreateTap,
onPressed: () {
if (isMobile(context)) {
navigator.pop();
}
createEntityByType(context: context, entityType: entityType);
},
),
),
);