From 5ede2460866bf408e46beb2395dd8275c28b3f9c Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Fri, 27 May 2022 12:32:03 +0300 Subject: [PATCH] Add CTA to add a gateway (for admins w/o gateways) --- lib/redux/app/app_actions.dart | 2 + lib/redux/ui/pref_reducer.dart | 8 ++++ lib/redux/ui/pref_state.dart | 4 ++ lib/redux/ui/pref_state.g.dart | 53 ++++++++++++++++++-------- lib/ui/dashboard/dashboard_panels.dart | 41 ++++++++++++++++++++ lib/utils/i18n.dart | 13 +++++++ 6 files changed, 105 insertions(+), 16 deletions(-) diff --git a/lib/redux/app/app_actions.dart b/lib/redux/app/app_actions.dart index 7bcd214f5..75c51ce89 100644 --- a/lib/redux/app/app_actions.dart +++ b/lib/redux/app/app_actions.dart @@ -89,6 +89,8 @@ class DismissNativeWarning implements PersistUI {} class DismissNativeWarningPermanently implements PersistUI, PersistPrefs {} +class DismissGatewayWarningPermanently implements PersistUI, PersistPrefs {} + class ViewMainScreen { ViewMainScreen({this.addDelay = false}); diff --git a/lib/redux/ui/pref_reducer.dart b/lib/redux/ui/pref_reducer.dart index e8020c6e6..9a2a7bb91 100644 --- a/lib/redux/ui/pref_reducer.dart +++ b/lib/redux/ui/pref_reducer.dart @@ -57,6 +57,8 @@ PrefState prefReducer( historySidebarReducer(state.historySidebarMode, action) ..hideDesktopWarning = hideDesktopWarningReducer(state.hideDesktopWarning, action) + ..hideGatewayWarning = + hideGatewayWarningReducer(state.hideGatewayWarning, action) ..textScaleFactor = textScaleFactorReducer(state.textScaleFactor, action) ..isMenuVisible = menuVisibleReducer(state.isMenuVisible, action) ..isHistoryVisible = historyVisibleReducer(state.isHistoryVisible, action) @@ -218,6 +220,12 @@ Reducer hideDesktopWarningReducer = combineReducers([ }), ]); +Reducer hideGatewayWarningReducer = combineReducers([ + TypedReducer((filter, action) { + return true; + }), +]); + Reducer filterClearedAtReducer = combineReducers([ TypedReducer((filterClearedAt, action) { return action.filter == null diff --git a/lib/redux/ui/pref_state.dart b/lib/redux/ui/pref_state.dart index bb4f69b4f..8282f9478 100644 --- a/lib/redux/ui/pref_state.dart +++ b/lib/redux/ui/pref_state.dart @@ -37,6 +37,7 @@ abstract class PrefState implements Built { longPressSelectionIsDefault: true, tapSelectedToEdit: false, hideDesktopWarning: false, + hideGatewayWarning: false, showKanban: false, showPdfPreview: true, persistData: false, @@ -139,6 +140,8 @@ abstract class PrefState implements Built { bool get hideDesktopWarning; + bool get hideGatewayWarning; + bool get editAfterSaving; double get textScaleFactor; @@ -206,6 +209,7 @@ abstract class PrefState implements Built { ..isPreviewVisible = false ..isFilterVisible = false ..hideDesktopWarning = false + ..hideGatewayWarning = false ..tapSelectedToEdit = false ..persistData = false ..persistUI = true diff --git a/lib/redux/ui/pref_state.g.dart b/lib/redux/ui/pref_state.g.dart index bab8a7e20..4d548a7e6 100644 --- a/lib/redux/ui/pref_state.g.dart +++ b/lib/redux/ui/pref_state.g.dart @@ -187,6 +187,9 @@ class _$PrefStateSerializer implements StructuredSerializer { 'hideDesktopWarning', serializers.serialize(object.hideDesktopWarning, specifiedType: const FullType(bool)), + 'hideGatewayWarning', + serializers.serialize(object.hideGatewayWarning, + specifiedType: const FullType(bool)), 'editAfterSaving', serializers.serialize(object.editAfterSaving, specifiedType: const FullType(bool)), @@ -319,6 +322,10 @@ class _$PrefStateSerializer implements StructuredSerializer { result.hideDesktopWarning = serializers.deserialize(value, specifiedType: const FullType(bool)) as bool; break; + case 'hideGatewayWarning': + result.hideGatewayWarning = serializers.deserialize(value, + specifiedType: const FullType(bool)) as bool; + break; case 'editAfterSaving': result.editAfterSaving = serializers.deserialize(value, specifiedType: const FullType(bool)) as bool; @@ -620,6 +627,8 @@ class _$PrefState extends PrefState { @override final bool hideDesktopWarning; @override + final bool hideGatewayWarning; + @override final bool editAfterSaving; @override final double textScaleFactor; @@ -656,6 +665,7 @@ class _$PrefState extends PrefState { this.enableTooltips, this.colorTheme, this.hideDesktopWarning, + this.hideGatewayWarning, this.editAfterSaving, this.textScaleFactor, this.sortFields, @@ -707,6 +717,8 @@ class _$PrefState extends PrefState { colorTheme, 'PrefState', 'colorTheme'); BuiltValueNullFieldError.checkNotNull( hideDesktopWarning, 'PrefState', 'hideDesktopWarning'); + BuiltValueNullFieldError.checkNotNull( + hideGatewayWarning, 'PrefState', 'hideGatewayWarning'); BuiltValueNullFieldError.checkNotNull( editAfterSaving, 'PrefState', 'editAfterSaving'); BuiltValueNullFieldError.checkNotNull( @@ -752,6 +764,7 @@ class _$PrefState extends PrefState { enableTooltips == other.enableTooltips && colorTheme == other.colorTheme && hideDesktopWarning == other.hideDesktopWarning && + hideGatewayWarning == other.hideGatewayWarning && editAfterSaving == other.editAfterSaving && textScaleFactor == other.textScaleFactor && sortFields == other.sortFields && @@ -779,22 +792,22 @@ class _$PrefState extends PrefState { $jc( $jc( $jc( - $jc($jc($jc($jc($jc($jc($jc($jc($jc($jc(0, appLayout.hashCode), moduleLayout.hashCode), menuSidebarMode.hashCode), historySidebarMode.hashCode), useSidebarEditor.hashCode), customColors.hashCode), isPreviewVisible.hashCode), isMenuVisible.hashCode), showKanban.hashCode), - showPdfPreview.hashCode), - enableTouchEvents.hashCode), - isHistoryVisible.hashCode), - enableDarkMode.hashCode), - isFilterVisible.hashCode), - persistData.hashCode), - persistUI.hashCode), - longPressSelectionIsDefault.hashCode), - requireAuthentication.hashCode), - tapSelectedToEdit.hashCode), - enableJSPDF.hashCode), - rowsPerPage.hashCode), - enableTooltips.hashCode), - colorTheme.hashCode), - hideDesktopWarning.hashCode), + $jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc(0, appLayout.hashCode), moduleLayout.hashCode), menuSidebarMode.hashCode), historySidebarMode.hashCode), useSidebarEditor.hashCode), customColors.hashCode), isPreviewVisible.hashCode), isMenuVisible.hashCode), showKanban.hashCode), showPdfPreview.hashCode), + enableTouchEvents.hashCode), + isHistoryVisible.hashCode), + enableDarkMode.hashCode), + isFilterVisible.hashCode), + persistData.hashCode), + persistUI.hashCode), + longPressSelectionIsDefault.hashCode), + requireAuthentication.hashCode), + tapSelectedToEdit.hashCode), + enableJSPDF.hashCode), + rowsPerPage.hashCode), + enableTooltips.hashCode), + colorTheme.hashCode), + hideDesktopWarning.hashCode), + hideGatewayWarning.hashCode), editAfterSaving.hashCode), textScaleFactor.hashCode), sortFields.hashCode), @@ -828,6 +841,7 @@ class _$PrefState extends PrefState { ..add('enableTooltips', enableTooltips) ..add('colorTheme', colorTheme) ..add('hideDesktopWarning', hideDesktopWarning) + ..add('hideGatewayWarning', hideGatewayWarning) ..add('editAfterSaving', editAfterSaving) ..add('textScaleFactor', textScaleFactor) ..add('sortFields', sortFields) @@ -954,6 +968,11 @@ class PrefStateBuilder implements Builder { set hideDesktopWarning(bool hideDesktopWarning) => _$this._hideDesktopWarning = hideDesktopWarning; + bool _hideGatewayWarning; + bool get hideGatewayWarning => _$this._hideGatewayWarning; + set hideGatewayWarning(bool hideGatewayWarning) => + _$this._hideGatewayWarning = hideGatewayWarning; + bool _editAfterSaving; bool get editAfterSaving => _$this._editAfterSaving; set editAfterSaving(bool editAfterSaving) => @@ -1007,6 +1026,7 @@ class PrefStateBuilder implements Builder { _enableTooltips = $v.enableTooltips; _colorTheme = $v.colorTheme; _hideDesktopWarning = $v.hideDesktopWarning; + _hideGatewayWarning = $v.hideGatewayWarning; _editAfterSaving = $v.editAfterSaving; _textScaleFactor = $v.textScaleFactor; _sortFields = $v.sortFields.toBuilder(); @@ -1065,6 +1085,7 @@ class PrefStateBuilder implements Builder { enableTooltips: BuiltValueNullFieldError.checkNotNull(enableTooltips, 'PrefState', 'enableTooltips'), colorTheme: BuiltValueNullFieldError.checkNotNull(colorTheme, 'PrefState', 'colorTheme'), hideDesktopWarning: BuiltValueNullFieldError.checkNotNull(hideDesktopWarning, 'PrefState', 'hideDesktopWarning'), + hideGatewayWarning: BuiltValueNullFieldError.checkNotNull(hideGatewayWarning, 'PrefState', 'hideGatewayWarning'), editAfterSaving: BuiltValueNullFieldError.checkNotNull(editAfterSaving, 'PrefState', 'editAfterSaving'), textScaleFactor: BuiltValueNullFieldError.checkNotNull(textScaleFactor, 'PrefState', 'textScaleFactor'), sortFields: sortFields.build(), diff --git a/lib/ui/dashboard/dashboard_panels.dart b/lib/ui/dashboard/dashboard_panels.dart index fea39b194..e5f5548da 100644 --- a/lib/ui/dashboard/dashboard_panels.dart +++ b/lib/ui/dashboard/dashboard_panels.dart @@ -7,10 +7,13 @@ import 'package:flutter/material.dart'; // Package imports: import 'package:charts_common/common.dart'; import 'package:charts_flutter/flutter.dart' as charts; +import 'package:flutter_redux/flutter_redux.dart'; import 'package:invoiceninja_flutter/redux/app/app_actions.dart'; +import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/task/task_actions.dart'; import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart'; import 'package:invoiceninja_flutter/ui/app/app_border.dart'; +import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/live_text.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; @@ -407,6 +410,7 @@ class DashboardPanels extends StatelessWidget { Widget build(BuildContext context) { final state = viewModel.state; final company = state.company; + final localization = AppLocalization.of(context); if (!state.staticState.isLoaded) { return LoadingIndicator(); @@ -466,6 +470,7 @@ class DashboardPanels extends StatelessWidget { } final entityTypes = [ + EntityType.dashboard, if (company.isModuleEnabled(EntityType.task) && runningTasks.isNotEmpty) EntityType.taskStatus, if (company.isModuleEnabled(EntityType.invoice)) EntityType.invoice, @@ -490,6 +495,42 @@ class DashboardPanels extends StatelessWidget { } switch (entityTypes[index]) { + case EntityType.dashboard: + if (!state.userCompany.isAdmin || + state.prefState.hideGatewayWarning || + state.companyGatewayState.list.isNotEmpty) { + return SizedBox(); + } + + return Padding( + padding: const EdgeInsets.only(top: 8), + child: FormCard( + child: Row( + children: [ + Expanded( + child: Text(localization.addGatewayHelpMessage), + ), + TextButton( + onPressed: () { + createEntityByType( + context: context, + entityType: EntityType.companyGateway, + ); + }, + child: Text(localization.addGateway)), + IconButton( + onPressed: () { + final store = StoreProvider.of(context); + store + .dispatch(DismissGatewayWarningPermanently()); + }, + icon: Icon( + Icons.clear, + color: Colors.grey, + )) + ], + )), + ); case EntityType.invoice: return _InvoiceChart( viewModel: viewModel, diff --git a/lib/utils/i18n.dart b/lib/utils/i18n.dart index 7bc3b8e36..7c577f6b5 100644 --- a/lib/utils/i18n.dart +++ b/lib/utils/i18n.dart @@ -16,6 +16,9 @@ mixin LocalizationsProvider on LocaleCodeAware { static final Map> _localizedValues = { 'en': { // STARTER: lang key - do not remove comment + 'add_gateway': 'Add Gateway', + 'add_gateway_help_message': + 'Add a payment gateway (ie. Stripe, WePay or PayPal) to accept online payments', 'left': 'Left', 'right': 'Right', 'center': 'Center', @@ -70508,12 +70511,22 @@ mixin LocalizationsProvider on LocaleCodeAware { String get left => _localizedValues[localeCode]['left'] ?? _localizedValues['en']['left']; + String get right => _localizedValues[localeCode]['right'] ?? _localizedValues['en']['right']; + String get center => _localizedValues[localeCode]['center'] ?? _localizedValues['en']['center']; + String get addGateway => + _localizedValues[localeCode]['add_gateway'] ?? + _localizedValues['en']['add_gateway']; + + String get addGatewayHelpMessage => + _localizedValues[localeCode]['add_gateway_help_message'] ?? + _localizedValues['en']['add_gateway_help_message']; + // STARTER: lang field - do not remove comment String lookup(String key) {