Add related links in tables

This commit is contained in:
Hillel Coren 2022-04-25 22:47:04 +03:00
parent 54ab592734
commit 4512a5ee43
9 changed files with 49 additions and 18 deletions

View File

@ -9,11 +9,13 @@ class CopyToClipboard extends StatelessWidget {
@required this.value, @required this.value,
this.child, this.child,
this.showBorder = false, this.showBorder = false,
this.onLongPress,
}) : super(key: key); }) : super(key: key);
final Widget child; final Widget child;
final String value; final String value;
final bool showBorder; final bool showBorder;
final Function onLongPress;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -41,13 +43,18 @@ class CopyToClipboard extends StatelessWidget {
if (showBorder) { if (showBorder) {
return ConstrainedBox( return ConstrainedBox(
child: OutlinedButton(onPressed: onTap, child: widget), child: OutlinedButton(
onPressed: onTap,
child: widget,
onLongPress: onLongPress,
),
constraints: BoxConstraints(maxWidth: 180), constraints: BoxConstraints(maxWidth: 180),
); );
} else { } else {
return InkWell( return InkWell(
child: widget, child: widget,
onTap: onTap, onTap: onTap,
onLongPress: onLongPress,
); );
} }
} }

View File

@ -29,6 +29,9 @@ class LinkTextRelatedEntity extends StatelessWidget {
viewEntity(entity: relation); viewEntity(entity: relation);
viewEntity(entity: entity, addToStack: true); viewEntity(entity: entity, addToStack: true);
}, },
onLongPress: () {
editEntity(context: context, entity: entity);
},
); );
} }
} }

View File

@ -7,6 +7,7 @@ import 'package:flutter_redux/flutter_redux.dart';
// Project imports: // Project imports:
import 'package:invoiceninja_flutter/data/models/entities.dart'; import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/ui/app/link_text.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
@ -88,11 +89,11 @@ class EntityPresenter {
? localization.archived ? localization.archived
: localization.deleted); : localization.deleted);
case EntityFields.createdBy: case EntityFields.createdBy:
return Text( final user = state.userState.get(entity.createdUserId);
state.userState.map[entity.createdUserId]?.listDisplayName ?? ''); return LinkTextRelatedEntity(entity: user, relation: entity);
case EntityFields.assignedTo: case EntityFields.assignedTo:
return Text( final user = state.userState.get(entity.assignedUserId);
state.userState.map[entity.assignedUserId]?.listDisplayName ?? ''); return LinkTextRelatedEntity(entity: user, relation: entity);
case EntityFields.isDeleted: case EntityFields.isDeleted:
return Text(entity.isDeleted ? localization.yes : localization.no); return Text(entity.isDeleted ? localization.yes : localization.no);
} }

View File

@ -10,6 +10,7 @@ import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/ui/app/copy_to_clipboard.dart'; import 'package:invoiceninja_flutter/ui/app/copy_to_clipboard.dart';
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart'; import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:url_launcher/url_launcher.dart';
class ClientPresenter extends EntityPresenter { class ClientPresenter extends EntityPresenter {
static List<String> getDefaultTableFields(UserCompanyEntity userCompany) { static List<String> getDefaultTableFields(UserCompanyEntity userCompany) {
@ -68,6 +69,7 @@ class ClientPresenter extends EntityPresenter {
return CopyToClipboard( return CopyToClipboard(
value: client.primaryContact.email, value: client.primaryContact.email,
showBorder: true, showBorder: true,
onLongPress: () => launch('mailto:${client.primaryContact.email}'),
); );
case ClientFields.contactPhone: case ClientFields.contactPhone:
return Text(client.primaryContact.phone); return Text(client.primaryContact.phone);

View File

@ -14,6 +14,7 @@ import 'package:invoiceninja_flutter/ui/app/link_text.dart';
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart'; import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:url_launcher/url_launcher.dart';
class CreditPresenter extends EntityPresenter { class CreditPresenter extends EntityPresenter {
static List<String> getDefaultTableFields(UserCompanyEntity userCompany) { static List<String> getDefaultTableFields(UserCompanyEntity userCompany) {
@ -127,7 +128,8 @@ class CreditPresenter extends EntityPresenter {
final project = state.projectState.get(credit.projectId); final project = state.projectState.get(credit.projectId);
return LinkTextRelatedEntity(entity: project, relation: credit); return LinkTextRelatedEntity(entity: project, relation: credit);
case CreditFields.vendor: case CreditFields.vendor:
return Text(state.vendorState.get(credit.vendorId).name); final vendor = state.vendorState.get(credit.vendorId);
return LinkTextRelatedEntity(entity: vendor, relation: credit);
case CreditFields.clientState: case CreditFields.clientState:
return Text(client.state); return Text(client.state);
case CreditFields.clientCity: case CreditFields.clientCity:
@ -140,12 +142,16 @@ class CreditPresenter extends EntityPresenter {
case CreditFields.contactEmail: case CreditFields.contactEmail:
final contact = creditContactSelector( final contact = creditContactSelector(
credit, state.clientState.get(credit.clientId)); credit, state.clientState.get(credit.clientId));
if (contact == null) {
return SizedBox();
}
if (field == CreditFields.contactName) { if (field == CreditFields.contactName) {
return Text(contact?.fullName ?? ''); return Text(contact.fullName ?? '');
} }
return CopyToClipboard( return CopyToClipboard(
value: contact?.email ?? '', value: contact.email,
showBorder: true, showBorder: true,
onLongPress: () => launch('mailto:${contact.email}'),
); );
case CreditFields.partial: case CreditFields.partial:
return Text(formatNumber(credit.partial, context)); return Text(formatNumber(credit.partial, context));

View File

@ -72,8 +72,8 @@ class ExpensePresenter extends EntityPresenter {
return EntityStatusChip(entity: expense, showState: true); return EntityStatusChip(entity: expense, showState: true);
case ExpenseFields.vendor: case ExpenseFields.vendor:
case ExpenseFields.vendorId: case ExpenseFields.vendorId:
return Text((state.vendorState.map[expense.vendorId] ?? VendorEntity()) final vendor = state.vendorState.get(expense.vendorId);
.listDisplayName); return LinkTextRelatedEntity(entity: vendor, relation: expense);
case ExpenseFields.clientId: case ExpenseFields.clientId:
case ExpenseFields.client: case ExpenseFields.client:
final client = state.clientState.get(expense.clientId); final client = state.clientState.get(expense.clientId);

View File

@ -14,6 +14,7 @@ import 'package:invoiceninja_flutter/ui/app/link_text.dart';
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart'; import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:url_launcher/url_launcher.dart';
class InvoicePresenter extends EntityPresenter { class InvoicePresenter extends EntityPresenter {
static List<String> getDefaultTableFields(UserCompanyEntity userCompany) { static List<String> getDefaultTableFields(UserCompanyEntity userCompany) {
@ -84,7 +85,8 @@ class InvoicePresenter extends EntityPresenter {
final project = state.projectState.get(invoice.projectId); final project = state.projectState.get(invoice.projectId);
return LinkTextRelatedEntity(entity: project, relation: invoice); return LinkTextRelatedEntity(entity: project, relation: invoice);
case InvoiceFields.vendor: case InvoiceFields.vendor:
return Text(state.vendorState.get(invoice.vendorId).name); final vendor = state.vendorState.get(invoice.vendorId);
return LinkTextRelatedEntity(entity: vendor, relation: invoice);
case InvoiceFields.date: case InvoiceFields.date:
return Text(formatDate(invoice.date, context)); return Text(formatDate(invoice.date, context));
case InvoiceFields.lastSentDate: case InvoiceFields.lastSentDate:
@ -159,12 +161,16 @@ class InvoicePresenter extends EntityPresenter {
case InvoiceFields.contactEmail: case InvoiceFields.contactEmail:
final contact = invoiceContactSelector( final contact = invoiceContactSelector(
invoice, state.clientState.get(invoice.clientId)); invoice, state.clientState.get(invoice.clientId));
if (contact == null) {
return SizedBox();
}
if (field == InvoiceFields.contactName) { if (field == InvoiceFields.contactName) {
return Text(contact?.fullName ?? ''); return Text(contact.fullName);
} }
return CopyToClipboard( return CopyToClipboard(
value: contact?.email ?? '', value: contact.email,
showBorder: true, showBorder: true,
onLongPress: () => launch('mailto:${contact.email}'),
); );
case InvoiceFields.partial: case InvoiceFields.partial:
return Text(formatNumber(invoice.partial, context)); return Text(formatNumber(invoice.partial, context));

View File

@ -15,6 +15,7 @@ import 'package:invoiceninja_flutter/ui/app/link_text.dart';
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart'; import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:url_launcher/url_launcher.dart';
class QuotePresenter extends EntityPresenter { class QuotePresenter extends EntityPresenter {
static List<String> getDefaultTableFields(UserCompanyEntity userCompany) { static List<String> getDefaultTableFields(UserCompanyEntity userCompany) {
@ -120,7 +121,8 @@ class QuotePresenter extends EntityPresenter {
final project = state.projectState.get(quote.projectId); final project = state.projectState.get(quote.projectId);
return LinkTextRelatedEntity(entity: project, relation: quote); return LinkTextRelatedEntity(entity: project, relation: quote);
case QuoteFields.vendor: case QuoteFields.vendor:
return Text(state.vendorState.get(quote.vendorId).name); final vendor = state.vendorState.get(quote.vendorId);
return LinkTextRelatedEntity(entity: vendor, relation: quote);
case QuoteFields.clientState: case QuoteFields.clientState:
return Text(client.state); return Text(client.state);
case QuoteFields.clientCity: case QuoteFields.clientCity:
@ -133,12 +135,16 @@ class QuotePresenter extends EntityPresenter {
case QuoteFields.contactEmail: case QuoteFields.contactEmail:
final contact = final contact =
quoteContactSelector(quote, state.clientState.get(quote.clientId)); quoteContactSelector(quote, state.clientState.get(quote.clientId));
if (contact == null) {
return SizedBox();
}
if (field == QuoteFields.contactName) { if (field == QuoteFields.contactName) {
return Text(contact?.fullName ?? ''); return Text(contact.fullName);
} }
return CopyToClipboard( return CopyToClipboard(
value: contact?.email ?? '', value: contact.email,
showBorder: true, showBorder: true,
onLongPress: () => launch('mailto:${contact.email}'),
); );
case QuoteFields.partial: case QuoteFields.partial:
return Text(formatNumber(quote.partial, context)); return Text(formatNumber(quote.partial, context));

View File

@ -72,8 +72,8 @@ class RecurringExpensePresenter extends EntityPresenter {
return EntityStatusChip(entity: expense, showState: true); return EntityStatusChip(entity: expense, showState: true);
case RecurringExpenseFields.vendor: case RecurringExpenseFields.vendor:
case RecurringExpenseFields.vendorId: case RecurringExpenseFields.vendorId:
return Text((state.vendorState.map[expense.vendorId] ?? VendorEntity()) final vendor = state.vendorState.get(expense.vendorId);
.listDisplayName); return LinkTextRelatedEntity(entity: vendor, relation: expense);
case RecurringExpenseFields.clientId: case RecurringExpenseFields.clientId:
case RecurringExpenseFields.client: case RecurringExpenseFields.client:
final client = state.clientState.get(expense.clientId); final client = state.clientState.get(expense.clientId);