Add Nordigen

This commit is contained in:
Hillel Coren 2023-12-26 13:08:37 +02:00
parent 23fd64fec4
commit 74a4cfa682
5 changed files with 138 additions and 15 deletions

View File

@ -53,6 +53,11 @@ const String kFacebookUrl = 'https://www.facebook.com/invoiceninja';
const String kYouTubeUrl = const String kYouTubeUrl =
'https://www.youtube.com/channel/UCXAHcBvhW05PDtWYIq7WDFA/videos'; 'https://www.youtube.com/channel/UCXAHcBvhW05PDtWYIq7WDFA/videos';
const String kYodleeCoverageUrl =
'https://www.yodlee.com/open-banking/data-connections';
const String kNordigenCoverageUrl =
'https://gocardless.com/bank-account-data/coverage';
const String kTaskExtensionUrl = const String kTaskExtensionUrl =
'https://chromewebstore.google.com/detail/invoice-ninja-tasks/dlfcbfdpemfnjbjlladogijcchfmmaaf'; 'https://chromewebstore.google.com/detail/invoice-ninja-tasks/dlfcbfdpemfnjbjlladogijcchfmmaaf';
const String kTaskExtensionYouTubeUrl = const String kTaskExtensionYouTubeUrl =

View File

@ -53,6 +53,9 @@ class BankAccountFields {
abstract class BankAccountEntity extends Object abstract class BankAccountEntity extends Object
with BaseEntity with BaseEntity
implements Built<BankAccountEntity, BankAccountEntityBuilder> { implements Built<BankAccountEntity, BankAccountEntityBuilder> {
static const String INTEGRATION_TYPE_YODLEE = 'yodlee';
static const String INTEGRATION_TYPE_NORDIGEN = 'nordigen';
factory BankAccountEntity({String? id, AppState? state}) { factory BankAccountEntity({String? id, AppState? state}) {
return _$BankAccountEntity._( return _$BankAccountEntity._(
id: id ?? BaseEntity.nextId, id: id ?? BaseEntity.nextId,

View File

@ -12,11 +12,13 @@ class LearnMoreUrl extends StatelessWidget {
required this.child, required this.child,
required this.url, required this.url,
this.label, this.label,
this.isVertical = false,
}); });
final Widget child; final Widget child;
final String url; final String url;
final String? label; final String? label;
final bool isVertical;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -26,26 +28,43 @@ class LearnMoreUrl extends StatelessWidget {
return child; return child;
} }
return Row( if (isVertical) {
children: <Widget>[ return Column(
Expanded( crossAxisAlignment: CrossAxisAlignment.start,
flex: 2, children: [
child: child, child,
), SizedBox(height: 8),
SizedBox( OutlinedButton(
width: 10,
),
Expanded(
child: TextButton(
child: Text( child: Text(
label ?? localization!.learnMore, label ?? localization!.learnMore,
maxLines: 4, maxLines: 4,
), ),
onPressed: () => launchUrl(Uri.parse(url)), onPressed: () => launchUrl(Uri.parse(url)),
), ),
), ],
], );
); } else {
return Row(
children: <Widget>[
Expanded(
flex: 2,
child: child,
),
SizedBox(
width: 10,
),
Expanded(
child: TextButton(
child: Text(
label ?? localization!.learnMore,
maxLines: 4,
),
onPressed: () => launchUrl(Uri.parse(url)),
),
),
],
);
}
} }
} }

View File

@ -11,6 +11,7 @@ import 'package:invoiceninja_flutter/redux/bank_account/bank_account_actions.dar
import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart'; import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart';
import 'package:invoiceninja_flutter/ui/app/app_bottom_bar.dart'; import 'package:invoiceninja_flutter/ui/app/app_bottom_bar.dart';
import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.dart'; import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.dart';
import 'package:invoiceninja_flutter/ui/app/forms/learn_more.dart';
import 'package:invoiceninja_flutter/ui/app/help_text.dart'; import 'package:invoiceninja_flutter/ui/app/help_text.dart';
import 'package:invoiceninja_flutter/ui/app/list_scaffold.dart'; import 'package:invoiceninja_flutter/ui/app/list_scaffold.dart';
import 'package:invoiceninja_flutter/ui/app/list_filter.dart'; import 'package:invoiceninja_flutter/ui/app/list_filter.dart';
@ -19,6 +20,7 @@ import 'package:invoiceninja_flutter/ui/bank_account/bank_account_presenter.dart
import 'package:invoiceninja_flutter/utils/dialogs.dart'; import 'package:invoiceninja_flutter/utils/dialogs.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:invoiceninja_flutter/utils/platforms.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'bank_account_screen_vm.dart'; import 'bank_account_screen_vm.dart';
@ -34,6 +36,91 @@ class BankAccountScreen extends StatelessWidget {
final BankAccountScreenVM viewModel; final BankAccountScreenVM viewModel;
void connectAccounts(BuildContext context) { void connectAccounts(BuildContext context) {
final localization = AppLocalization.of(context)!;
String integrationType = BankAccountEntity.INTEGRATION_TYPE_NORDIGEN;
if (isHosted(context)) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(localization.selectProvider),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(localization.close.toUpperCase()))
],
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text('Envestnet - Yodlee'),
Text(
localization.supportedRegions +
': USA, Australia, UK & India',
style: Theme.of(context).textTheme.bodySmall),
Row(
children: [
Expanded(
child: AppButton(
label: localization.learnMore.toUpperCase(),
onPressed: () =>
launchUrl(Uri.parse(kYodleeCoverageUrl)),
iconData: Icons.info_outline,
),
),
SizedBox(width: kTableColumnGap),
Expanded(
child: AppButton(
label: localization.connect.toUpperCase(),
onPressed: () => _connectAccounts(
context,
BankAccountEntity.INTEGRATION_TYPE_YODLEE,
),
iconData: Icons.link,
),
),
],
),
SizedBox(height: 30),
Text('GoCardless - Nordigen'),
Text(localization.supportedRegions + ': Europe & UK',
style: Theme.of(context).textTheme.bodySmall),
Row(
children: [
Expanded(
child: AppButton(
label: localization.learnMore.toUpperCase(),
onPressed: () =>
launchUrl(Uri.parse(kNordigenCoverageUrl)),
iconData: Icons.info_outline,
),
),
SizedBox(width: kTableColumnGap),
Expanded(
child: AppButton(
label: localization.connect.toUpperCase(),
onPressed: () => _connectAccounts(
context,
BankAccountEntity.INTEGRATION_TYPE_NORDIGEN,
),
iconData: Icons.link,
),
),
],
),
],
),
),
);
},
);
} else {
_connectAccounts(context, integrationType);
}
}
void _connectAccounts(BuildContext context, String integrationType) {
final store = StoreProvider.of<AppState>(context); final store = StoreProvider.of<AppState>(context);
final state = store.state; final state = store.state;
final webClient = WebClient(); final webClient = WebClient();
@ -41,7 +128,6 @@ class BankAccountScreen extends StatelessWidget {
final url = '${credentials.url}/one_time_token'; final url = '${credentials.url}/one_time_token';
store.dispatch(StartSaving()); store.dispatch(StartSaving());
webClient webClient
.post(url, credentials.token, .post(url, credentials.token,
data: jsonEncode({ data: jsonEncode({

View File

@ -18,6 +18,8 @@ mixin LocalizationsProvider on LocaleCodeAware {
static final Map<String, Map<String, String>> _localizedValues = { static final Map<String, Map<String, String>> _localizedValues = {
'en': { 'en': {
// STARTER: lang key - do not remove comment // STARTER: lang key - do not remove comment
'supported_regions': 'Supported Regions',
'select_provider': 'Select Provider',
'payment_type_credit': 'Payment Type Credit', 'payment_type_credit': 'Payment Type Credit',
'payment_type_debit': 'Payment Type Debit', 'payment_type_debit': 'Payment Type Debit',
'send_emails_to': 'Send Emails To', 'send_emails_to': 'Send Emails To',
@ -111466,6 +111468,14 @@ mixin LocalizationsProvider on LocaleCodeAware {
_localizedValues[localeCode]!['send_emails_to'] ?? _localizedValues[localeCode]!['send_emails_to'] ??
_localizedValues['en']!['send_emails_to']!; _localizedValues['en']!['send_emails_to']!;
String get selectProvider =>
_localizedValues[localeCode]!['select_provider'] ??
_localizedValues['en']!['select_provider']!;
String get supportedRegions =>
_localizedValues[localeCode]!['supported_regions'] ??
_localizedValues['en']!['supported_regions']!;
// STARTER: lang field - do not remove comment // STARTER: lang field - do not remove comment
String lookup(String? key) { String lookup(String? key) {