From 5175c272cdec6d1ccf2d3e8ed642e3590dec4be8 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Thu, 24 Oct 2019 10:45:03 +0300 Subject: [PATCH] Settings --- lib/constants.dart | 4 + lib/data/models/company_model.dart | 14 +++- lib/data/models/company_model.g.dart | 23 +++++- lib/ui/settings/client_portal.dart | 105 ++++++++++++++++++++------- lib/ui/settings/email_settings.dart | 8 +- lib/utils/i18n.dart | 10 +-- 6 files changed, 123 insertions(+), 41 deletions(-) diff --git a/lib/constants.dart b/lib/constants.dart index 93af7b6f3..f8840522a 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -109,6 +109,10 @@ const String kGatewayTypeCustom3 = '12'; const String kGatewayStripe = 'd14dd26a37cecc30fdd65700bfb55b23'; +const String kClientPortalModeSubdomain = 'subdomain'; +const String kClientPortalModeDomain = 'domain'; +const String kClientPortalModeIFrame = 'iframe'; + const String kEmailDesignPlain = 'plain'; const String kEmailDesignLight = 'light'; const String kEmailDesignDark = 'dark'; diff --git a/lib/data/models/company_model.dart b/lib/data/models/company_model.dart index 6891f3807..1774a6324 100644 --- a/lib/data/models/company_model.dart +++ b/lib/data/models/company_model.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; +import 'package:flutter/foundation.dart'; import 'package:invoiceninja_flutter/constants.dart'; import 'package:invoiceninja_flutter/data/models/company_gateway_model.dart'; import 'package:invoiceninja_flutter/data/models/entities.dart'; @@ -50,6 +51,10 @@ abstract class CompanyEntity extends Object @BuiltValueField(wireName: 'industry_id') String get industryId; + @nullable + @BuiltValueField(wireName: 'portal_mode') + String get portalMode; + // TODO remove this @nullable String get plan; @@ -174,8 +179,13 @@ abstract class CompanyEntity extends Object } } - bool get isSelfHost => - appUrl != null && appUrl.isNotEmpty && appUrl != kAppUrl; + bool get isSelfHost { + if (!kReleaseMode) { + return true; + } + + return appUrl != null && appUrl.isNotEmpty && appUrl != kAppUrl; + } bool get isHosted => !isSelfHost; diff --git a/lib/data/models/company_model.g.dart b/lib/data/models/company_model.g.dart index f5258f85f..546a09d08 100644 --- a/lib/data/models/company_model.g.dart +++ b/lib/data/models/company_model.g.dart @@ -62,6 +62,12 @@ class _$CompanyEntitySerializer implements StructuredSerializer { ..add(serializers.serialize(object.industryId, specifiedType: const FullType(String))); } + if (object.portalMode != null) { + result + ..add('portal_mode') + ..add(serializers.serialize(object.portalMode, + specifiedType: const FullType(String))); + } if (object.plan != null) { result ..add('plan') @@ -215,6 +221,10 @@ class _$CompanyEntitySerializer implements StructuredSerializer { result.industryId = serializers.deserialize(value, specifiedType: const FullType(String)) as String; break; + case 'portal_mode': + result.portalMode = serializers.deserialize(value, + specifiedType: const FullType(String)) as String; + break; case 'plan': result.plan = serializers.deserialize(value, specifiedType: const FullType(String)) as String; @@ -1422,6 +1432,8 @@ class _$CompanyEntity extends CompanyEntity { @override final String industryId; @override + final String portalMode; + @override final String plan; @override final String companyKey; @@ -1476,6 +1488,7 @@ class _$CompanyEntity extends CompanyEntity { _$CompanyEntity._( {this.sizeId, this.industryId, + this.portalMode, this.plan, this.companyKey, this.appUrl, @@ -1528,6 +1541,7 @@ class _$CompanyEntity extends CompanyEntity { return other is CompanyEntity && sizeId == other.sizeId && industryId == other.industryId && + portalMode == other.portalMode && plan == other.plan && companyKey == other.companyKey && appUrl == other.appUrl && @@ -1574,7 +1588,7 @@ class _$CompanyEntity extends CompanyEntity { $jc( $jc( $jc( - $jc($jc($jc($jc($jc($jc($jc($jc(0, sizeId.hashCode), industryId.hashCode), plan.hashCode), companyKey.hashCode), appUrl.hashCode), startOfWeek.hashCode), financialYearStart.hashCode), + $jc($jc($jc($jc($jc($jc($jc($jc($jc(0, sizeId.hashCode), industryId.hashCode), portalMode.hashCode), plan.hashCode), companyKey.hashCode), appUrl.hashCode), startOfWeek.hashCode), financialYearStart.hashCode), groups.hashCode), taxRates.hashCode), taskStatuses.hashCode), @@ -1601,6 +1615,7 @@ class _$CompanyEntity extends CompanyEntity { return (newBuiltValueToStringHelper('CompanyEntity') ..add('sizeId', sizeId) ..add('industryId', industryId) + ..add('portalMode', portalMode) ..add('plan', plan) ..add('companyKey', companyKey) ..add('appUrl', appUrl) @@ -1641,6 +1656,10 @@ class CompanyEntityBuilder String get industryId => _$this._industryId; set industryId(String industryId) => _$this._industryId = industryId; + String _portalMode; + String get portalMode => _$this._portalMode; + set portalMode(String portalMode) => _$this._portalMode = portalMode; + String _plan; String get plan => _$this._plan; set plan(String plan) => _$this._plan = plan; @@ -1766,6 +1785,7 @@ class CompanyEntityBuilder if (_$v != null) { _sizeId = _$v.sizeId; _industryId = _$v.industryId; + _portalMode = _$v.portalMode; _plan = _$v.plan; _companyKey = _$v.companyKey; _appUrl = _$v.appUrl; @@ -1816,6 +1836,7 @@ class CompanyEntityBuilder new _$CompanyEntity._( sizeId: sizeId, industryId: industryId, + portalMode: portalMode, plan: plan, companyKey: companyKey, appUrl: appUrl, diff --git a/lib/ui/settings/client_portal.dart b/lib/ui/settings/client_portal.dart index add5cd8e5..b71ab60f8 100644 --- a/lib/ui/settings/client_portal.dart +++ b/lib/ui/settings/client_portal.dart @@ -1,10 +1,15 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:invoiceninja_flutter/constants.dart'; +import 'package:invoiceninja_flutter/data/models/entities.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/bool_dropdown_button.dart'; import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart'; import 'package:invoiceninja_flutter/ui/settings/client_portal_vm.dart'; import 'package:invoiceninja_flutter/ui/settings/settings_scaffold.dart'; +import 'package:invoiceninja_flutter/utils/icons.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; class ClientPortal extends StatefulWidget { @@ -86,6 +91,8 @@ class _ClientPortalState extends State final localization = AppLocalization.of(context); final viewModel = widget.viewModel; final state = viewModel.state; + final company = viewModel.company; + final settings = viewModel.settings; return SettingsScaffold( title: localization.clientPortal, @@ -112,38 +119,84 @@ class _ClientPortalState extends State children: [ ListView( children: [ + if (!state.settingsUIState.isFiltered) + FormCard( + children: [ + InputDecorator( + decoration: InputDecoration( + labelText: localization.portalMode, + ), + //isEmpty: false, + child: DropdownButtonHideUnderline( + child: DropdownButton( + value: viewModel.company.portalMode, + isExpanded: true, + isDense: true, + onChanged: (value) => viewModel.onCompanyChanged( + viewModel.company + .rebuild((b) => b..portalMode = value)), + items: [ + DropdownMenuItem( + child: Text(localization.subdomain), + value: kClientPortalModeSubdomain, + ), + if (company.isEnterprisePlan) + DropdownMenuItem( + child: Text(localization.domain), + value: kClientPortalModeDomain, + ), + DropdownMenuItem( + child: Text('iFrame'), + value: kClientPortalModeIFrame, + ), + ]), + ), + ), + DecoratedFormField( + label: localization.subdomain, + controller: _subdomainController, + ), + if (company.portalMode == kClientPortalModeDomain && + company.isEnterprisePlan) + DecoratedFormField( + label: localization.domain, + controller: _domainController, + keyboardType: TextInputType.url, + ), + if (company.portalMode == kClientPortalModeIFrame) + DecoratedFormField( + label: 'iFrame', + controller: _iFrameController, + keyboardType: TextInputType.url, + ), + ], + ), FormCard( children: [ - InputDecorator( - decoration: InputDecoration( - labelText: localization.linkType, - ), - //isEmpty: false, - child: DropdownButtonHideUnderline( - child: DropdownButton( - //value: companyGateway.gatewayTypeId, - isExpanded: true, - isDense: true, - //onChanged: (value) => viewModel.onChanged(companyGateway.rebuild((b) => b..gatewayTypeId = value)), - items: []), - ), + BoolDropdownButton( + label: localization.clientPortal, + value: false, + showBlank: state.settingsUIState.isFiltered, + iconData: FontAwesomeIcons.cloud, + onChanged: (value) => null, ), - DecoratedFormField( - label: localization.subdomain, - controller: _subdomainController, + BoolDropdownButton( + label: localization.dashboard, + value: false, + showBlank: state.settingsUIState.isFiltered, + iconData: FontAwesomeIcons.tachometerAlt, + onChanged: (value) => null, ), - DecoratedFormField( - label: localization.domain, - controller: _domainController, - keyboardType: TextInputType.url, - ), - DecoratedFormField( - label: 'iFrame', - controller: _iFrameController, - keyboardType: TextInputType.url, + BoolDropdownButton( + label: localization.tasks, + value: settings.showTasksInPortal, + showBlank: state.settingsUIState.isFiltered, + iconData: getEntityIcon(EntityType.task), + onChanged: (value) => viewModel.onSettingsChanged( + settings.rebuild((b) => b..showTasksInPortal = value)), ), ], - ) + ), ], ), ListView(), diff --git a/lib/ui/settings/email_settings.dart b/lib/ui/settings/email_settings.dart index 6df8f2ae3..9e9003eff 100644 --- a/lib/ui/settings/email_settings.dart +++ b/lib/ui/settings/email_settings.dart @@ -13,7 +13,6 @@ import 'package:invoiceninja_flutter/ui/settings/email_settings_vm.dart'; import 'package:invoiceninja_flutter/ui/settings/settings_scaffold.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:zefyr/zefyr.dart'; -import 'package:quill_delta/quill_delta.dart'; class EmailSettings extends StatefulWidget { const EmailSettings({ @@ -76,10 +75,10 @@ class _EmailSettingsState extends State .forEach((dynamic controller) => controller.removeListener(_onChanged)); final settings = widget.viewModel.settings; - final signature = settings.emailFooter ?? ''; + final signature = settings.emailFooter; // return NotusDocument.fromJson(jsonDecode(contents)); - final doc = NotusDocument.fromJson(jsonDecode(signature)); + final doc = signature != null ? NotusDocument.fromJson(jsonDecode(signature)) : NotusDocument(); _zefyrController = ZefyrController(doc)..addListener(_onZefyrChanged); //_zefyrController.compose(Delta()..insert(signature)); @@ -219,7 +218,7 @@ class _EmailSettingsState extends State ], ), Container( - color: Colors.white, + color: Colors.grey.shade100, child: _zefyrController == null ? LoadingIndicator() : ZefyrScaffold( @@ -227,6 +226,7 @@ class _EmailSettingsState extends State padding: EdgeInsets.all(16), controller: _zefyrController, focusNode: _zefyrNode, + autofocus: false, ), ), ), diff --git a/lib/utils/i18n.dart b/lib/utils/i18n.dart index 7247468b4..ac41dabba 100644 --- a/lib/utils/i18n.dart +++ b/lib/utils/i18n.dart @@ -16,9 +16,7 @@ mixin LocalizationsProvider on LocaleCodeAware { 'en': { 'subdomain': 'Subdomain', 'domain': 'Domain', - 'link_type': 'Link Type', - 'custom_subdomain': 'Custom Subdomain', - 'custom_domain': 'Custom Domain', + 'portal_mode': 'Portal Mode', 'email_signature': 'Email Signature', 'enable_email_markup_help': 'Make it easier for your clients to pay you by adding schema.org markup to your emails.', @@ -15056,11 +15054,7 @@ mixin LocalizationsProvider on LocaleCodeAware { String get emailSignature => _localizedValues[localeCode]['email_signature']; - String get linkType => _localizedValues[localeCode]['link_type']; - - String get customSubdomain => _localizedValues[localeCode]['custom_subdomain']; - - String get customDomain => _localizedValues[localeCode]['custom_domain']; + String get portalMode => _localizedValues[localeCode]['portal_mode']; String get domain => _localizedValues[localeCode]['domain'];