diff --git a/lib/constants.dart b/lib/constants.dart index 9c16e4a5c..32c00e30c 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; // This version must be updated in tandem with the pubspec version. -const String kAppVersion = '0.1.50'; +const String kAppVersion = '2.0.0'; const String kSiteUrl = 'https://invoiceninja.com'; const String kAppUrl = 'https://admin.invoiceninja.com'; const String kAppPlansURL = diff --git a/lib/data/models/company_model.dart b/lib/data/models/company_model.dart index 903505104..1617f94ec 100644 --- a/lib/data/models/company_model.dart +++ b/lib/data/models/company_model.dart @@ -15,6 +15,7 @@ abstract class CompanyEntity companyKey: '', name: '', plan: '', + settings: SettingsEntity(), logoUrl: '', appUrl: '', convertProductExchangeRate: false, @@ -46,7 +47,8 @@ abstract class CompanyEntity showCurrencyCode: false, showInvoiceItemTaxes: false, startOfWeek: 1, - timezoneId: '1', // TODO set to default EST timezone + timezoneId: '1', + // TODO set to default EST timezone customPaymentTerms: BuiltList(), taxRates: BuiltList(), taskStatuses: BuiltList(), @@ -104,6 +106,8 @@ abstract class CompanyEntity @BuiltValueField(wireName: 'currency_id') String get companyCurrencyId; + SettingsEntity get settings; + // TODO remove this @nullable @BuiltValueField(wireName: 'timezone_id') @@ -554,7 +558,8 @@ abstract class UserEntity implements Built { BuiltMap get permissionsMap; bool can(UserPermission permission, EntityType entityType) => - isAdmin || permissionsMap.containsKey('${permission}_$entityType'); + (isAdmin ?? false) || + permissionsMap.containsKey('${permission}_$entityType'); bool canView(EntityType entityType) => can(UserPermission.view, entityType); @@ -619,3 +624,22 @@ abstract class TokenEntity implements Built { static Serializer get serializer => _$tokenEntitySerializer; } + +abstract class SettingsEntity + implements Built { + factory SettingsEntity() { + return _$SettingsEntity._( + //timezoneId: '', + ); + } + + SettingsEntity._(); + + @BuiltValueField(wireName: 'timezone_id') + int get timezoneIdInt; + + String get timezoneId => timezoneId.toString(); + + static Serializer get serializer => + _$settingsEntitySerializer; +} diff --git a/lib/data/models/company_model.g.dart b/lib/data/models/company_model.g.dart index 34d49ac1a..ab640ee5c 100644 --- a/lib/data/models/company_model.g.dart +++ b/lib/data/models/company_model.g.dart @@ -16,6 +16,8 @@ Serializer _$userEntitySerializer = new _$UserEntitySerializer(); Serializer _$userCompanyEntitySerializer = new _$UserCompanyEntitySerializer(); Serializer _$tokenEntitySerializer = new _$TokenEntitySerializer(); +Serializer _$settingsEntitySerializer = + new _$SettingsEntitySerializer(); class _$CompanyEntitySerializer implements StructuredSerializer { @override @@ -32,6 +34,9 @@ class _$CompanyEntitySerializer implements StructuredSerializer { 'company_key', serializers.serialize(object.companyKey, specifiedType: const FullType(String)), + 'settings', + serializers.serialize(object.settings, + specifiedType: const FullType(SettingsEntity)), 'country_id', serializers.serialize(object.countryId, specifiedType: const FullType(String)), @@ -451,6 +456,10 @@ class _$CompanyEntitySerializer implements StructuredSerializer { result.companyCurrencyId = serializers.deserialize(value, specifiedType: const FullType(String)) as String; break; + case 'settings': + result.settings.replace(serializers.deserialize(value, + specifiedType: const FullType(SettingsEntity)) as SettingsEntity); + break; case 'timezone_id': result.timezoneId = serializers.deserialize(value, specifiedType: const FullType(String)) as String; @@ -1029,6 +1038,48 @@ class _$TokenEntitySerializer implements StructuredSerializer { } } +class _$SettingsEntitySerializer + implements StructuredSerializer { + @override + final Iterable types = const [SettingsEntity, _$SettingsEntity]; + @override + final String wireName = 'SettingsEntity'; + + @override + Iterable serialize(Serializers serializers, SettingsEntity object, + {FullType specifiedType = FullType.unspecified}) { + final result = [ + 'timezone_id', + serializers.serialize(object.timezoneIdInt, + specifiedType: const FullType(int)), + ]; + + return result; + } + + @override + SettingsEntity deserialize( + Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = new SettingsEntityBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current as String; + iterator.moveNext(); + final dynamic value = iterator.current; + switch (key) { + case 'timezone_id': + result.timezoneIdInt = serializers.deserialize(value, + specifiedType: const FullType(int)) as int; + break; + } + } + + return result.build(); + } +} + class _$CompanyEntity extends CompanyEntity { @override final String name; @@ -1043,6 +1094,8 @@ class _$CompanyEntity extends CompanyEntity { @override final String companyCurrencyId; @override + final SettingsEntity settings; + @override final String timezoneId; @override final String countryId; @@ -1169,6 +1222,7 @@ class _$CompanyEntity extends CompanyEntity { this.logoUrl, this.appUrl, this.companyCurrencyId, + this.settings, this.timezoneId, this.countryId, this.dateFormatId, @@ -1234,6 +1288,9 @@ class _$CompanyEntity extends CompanyEntity { if (companyKey == null) { throw new BuiltValueNullFieldError('CompanyEntity', 'companyKey'); } + if (settings == null) { + throw new BuiltValueNullFieldError('CompanyEntity', 'settings'); + } if (countryId == null) { throw new BuiltValueNullFieldError('CompanyEntity', 'countryId'); } @@ -1259,6 +1316,7 @@ class _$CompanyEntity extends CompanyEntity { logoUrl == other.logoUrl && appUrl == other.appUrl && companyCurrencyId == other.companyCurrencyId && + settings == other.settings && timezoneId == other.timezoneId && countryId == other.countryId && dateFormatId == other.dateFormatId && @@ -1339,7 +1397,7 @@ class _$CompanyEntity extends CompanyEntity { $jc( $jc( $jc( - $jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc(0, name.hashCode), plan.hashCode), companyKey.hashCode), logoUrl.hashCode), appUrl.hashCode), companyCurrencyId.hashCode), timezoneId.hashCode), countryId.hashCode), dateFormatId.hashCode), datetimeFormatId.hashCode), defaultInvoiceTerms.hashCode), enableInvoiceTaxes.hashCode), enableInvoiceItemTaxes.hashCode), defaultInvoiceDesignId.hashCode), defaultQuoteDesignId.hashCode), languageId.hashCode), defaultInvoiceFooter.hashCode), showInvoiceItemTaxes.hashCode), enableMilitaryTime.hashCode), defaultTaxName1.hashCode), defaultTaxRate1.hashCode), defaultTaxName2.hashCode), defaultTaxRate2.hashCode), defaultQuoteTerms.hashCode), showCurrencyCode.hashCode), enableSecondTaxRate.hashCode), startOfWeek.hashCode), financialYearStart.hashCode), enabledModules.hashCode), defaultPaymentTerms.hashCode), defaultPaymentTypeId.hashCode), defaultTaskRate.hashCode), enableInclusiveTaxes.hashCode), convertProductExchangeRate.hashCode), enableCustomInvoiceTaxes1.hashCode), enableCustomInvoiceTaxes2.hashCode), taxRates.hashCode), taskStatuses.hashCode), taskStatusMap.hashCode), expenseCategories.hashCode), expenseCategoryMap.hashCode), users.hashCode), userMap.hashCode), customFields.hashCode), customPaymentTerms.hashCode), + $jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc(0, name.hashCode), plan.hashCode), companyKey.hashCode), logoUrl.hashCode), appUrl.hashCode), companyCurrencyId.hashCode), settings.hashCode), timezoneId.hashCode), countryId.hashCode), dateFormatId.hashCode), datetimeFormatId.hashCode), defaultInvoiceTerms.hashCode), enableInvoiceTaxes.hashCode), enableInvoiceItemTaxes.hashCode), defaultInvoiceDesignId.hashCode), defaultQuoteDesignId.hashCode), languageId.hashCode), defaultInvoiceFooter.hashCode), showInvoiceItemTaxes.hashCode), enableMilitaryTime.hashCode), defaultTaxName1.hashCode), defaultTaxRate1.hashCode), defaultTaxName2.hashCode), defaultTaxRate2.hashCode), defaultQuoteTerms.hashCode), showCurrencyCode.hashCode), enableSecondTaxRate.hashCode), startOfWeek.hashCode), financialYearStart.hashCode), enabledModules.hashCode), defaultPaymentTerms.hashCode), defaultPaymentTypeId.hashCode), defaultTaskRate.hashCode), enableInclusiveTaxes.hashCode), convertProductExchangeRate.hashCode), enableCustomInvoiceTaxes1.hashCode), enableCustomInvoiceTaxes2.hashCode), taxRates.hashCode), taskStatuses.hashCode), taskStatusMap.hashCode), expenseCategories.hashCode), expenseCategoryMap.hashCode), users.hashCode), userMap.hashCode), customFields.hashCode), customPaymentTerms.hashCode), invoiceFields.hashCode), emailFooter.hashCode), emailSubjectInvoice.hashCode), @@ -1370,6 +1428,7 @@ class _$CompanyEntity extends CompanyEntity { ..add('logoUrl', logoUrl) ..add('appUrl', appUrl) ..add('companyCurrencyId', companyCurrencyId) + ..add('settings', settings) ..add('timezoneId', timezoneId) ..add('countryId', countryId) ..add('dateFormatId', dateFormatId) @@ -1461,6 +1520,11 @@ class CompanyEntityBuilder set companyCurrencyId(String companyCurrencyId) => _$this._companyCurrencyId = companyCurrencyId; + SettingsEntityBuilder _settings; + SettingsEntityBuilder get settings => + _$this._settings ??= new SettingsEntityBuilder(); + set settings(SettingsEntityBuilder settings) => _$this._settings = settings; + String _timezoneId; String get timezoneId => _$this._timezoneId; set timezoneId(String timezoneId) => _$this._timezoneId = timezoneId; @@ -1764,6 +1828,7 @@ class CompanyEntityBuilder _logoUrl = _$v.logoUrl; _appUrl = _$v.appUrl; _companyCurrencyId = _$v.companyCurrencyId; + _settings = _$v.settings?.toBuilder(); _timezoneId = _$v.timezoneId; _countryId = _$v.countryId; _dateFormatId = _$v.dateFormatId; @@ -1852,6 +1917,7 @@ class CompanyEntityBuilder logoUrl: logoUrl, appUrl: appUrl, companyCurrencyId: companyCurrencyId, + settings: settings.build(), timezoneId: timezoneId, countryId: countryId, dateFormatId: dateFormatId, @@ -1913,6 +1979,9 @@ class CompanyEntityBuilder } catch (_) { String _$failedField; try { + _$failedField = 'settings'; + settings.build(); + _$failedField = 'taxRates'; _taxRates?.build(); _$failedField = 'taskStatuses'; @@ -2561,4 +2630,84 @@ class TokenEntityBuilder implements Builder { } } +class _$SettingsEntity extends SettingsEntity { + @override + final int timezoneIdInt; + + factory _$SettingsEntity([void Function(SettingsEntityBuilder) updates]) => + (new SettingsEntityBuilder()..update(updates)).build(); + + _$SettingsEntity._({this.timezoneIdInt}) : super._() { + if (timezoneIdInt == null) { + throw new BuiltValueNullFieldError('SettingsEntity', 'timezoneIdInt'); + } + } + + @override + SettingsEntity rebuild(void Function(SettingsEntityBuilder) updates) => + (toBuilder()..update(updates)).build(); + + @override + SettingsEntityBuilder toBuilder() => + new SettingsEntityBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is SettingsEntity && timezoneIdInt == other.timezoneIdInt; + } + + @override + int get hashCode { + return $jf($jc(0, timezoneIdInt.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('SettingsEntity') + ..add('timezoneIdInt', timezoneIdInt)) + .toString(); + } +} + +class SettingsEntityBuilder + implements Builder { + _$SettingsEntity _$v; + + int _timezoneIdInt; + int get timezoneIdInt => _$this._timezoneIdInt; + set timezoneIdInt(int timezoneIdInt) => _$this._timezoneIdInt = timezoneIdInt; + + SettingsEntityBuilder(); + + SettingsEntityBuilder get _$this { + if (_$v != null) { + _timezoneIdInt = _$v.timezoneIdInt; + _$v = null; + } + return this; + } + + @override + void replace(SettingsEntity other) { + if (other == null) { + throw new ArgumentError.notNull('other'); + } + _$v = other as _$SettingsEntity; + } + + @override + void update(void Function(SettingsEntityBuilder) updates) { + if (updates != null) updates(this); + } + + @override + _$SettingsEntity build() { + final _$result = + _$v ?? new _$SettingsEntity._(timezoneIdInt: timezoneIdInt); + replace(_$result); + return _$result; + } +} + // ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/lib/data/models/serializers.g.dart b/lib/data/models/serializers.g.dart index f94ef5ce1..ca9a1ed38 100644 --- a/lib/data/models/serializers.g.dart +++ b/lib/data/models/serializers.g.dart @@ -96,6 +96,7 @@ Serializers _$serializers = (new Serializers().toBuilder() ..add(ProjectUIState.serializer) ..add(QuoteState.serializer) ..add(QuoteUIState.serializer) + ..add(SettingsEntity.serializer) ..add(SizeEntity.serializer) ..add(SizeItemResponse.serializer) ..add(SizeListResponse.serializer) diff --git a/lib/redux/app/app_middleware.dart b/lib/redux/app/app_middleware.dart index fe904a961..0a75ad5d0 100644 --- a/lib/redux/app/app_middleware.dart +++ b/lib/redux/app/app_middleware.dart @@ -323,16 +323,18 @@ Middleware _createAccountLoaded() { if (action.loadCompanies) { for (int i = 0; i < response.userCompanies.length; i++) { final UserCompanyEntity userCompany = response.userCompanies[i]; - - final SharedPreferences prefs = await SharedPreferences.getInstance(); - prefs.setString(getCompanyTokenKey(i), userCompany.token.token); + print('user company: $userCompany'); store.dispatch(SelectCompany(i + 1, userCompany)); + print('selected 1'); store.dispatch(LoadCompanySuccess(userCompany)); + print('selected 2'); } store.dispatch(SelectCompany(1, response.userCompanies[0])); + print('selected 3'); store.dispatch(UserLoginSuccess()); + print('selected 4'); } if (action.completer != null) { diff --git a/lib/redux/app/app_state.dart b/lib/redux/app/app_state.dart index e28f66773..f843d7b87 100644 --- a/lib/redux/app/app_state.dart +++ b/lib/redux/app/app_state.dart @@ -275,7 +275,8 @@ abstract class AppState implements Built { @override String toString() { - return 'URL: ${authState.url}, ${selectedCompany.plan}'; + return 'Settings: ${selectedCompanyState.company.settings}'; + //return 'URL: ${authState.url}, ${selectedCompany.plan}'; //return 'Is Testing: ${uiState.isTesting}'; //return 'Route: ${uiState.currentRoute}, Previous: ${uiState.previousRoute}, Layout: ${uiState.layout}, Menu: ${uiState.isMenuVisible}, History: ${uiState.isHistoryVisible}'; } diff --git a/lib/redux/company/company_reducer.dart b/lib/redux/company/company_reducer.dart index f24894d4e..598e4d050 100644 --- a/lib/redux/company/company_reducer.dart +++ b/lib/redux/company/company_reducer.dart @@ -44,6 +44,8 @@ Reducer companyEntityReducer = combineReducers([ UserCompanyEntity loadCompanySuccessReducer( UserCompanyEntity company, LoadCompanySuccess action) { + return action.company; + var userCompany = action.company; if (userCompany.company.taskStatuses != null) { diff --git a/lib/ui/app/app_drawer.dart b/lib/ui/app/app_drawer.dart index 7bc8dbee0..aa42b01af 100644 --- a/lib/ui/app/app_drawer.dart +++ b/lib/ui/app/app_drawer.dart @@ -165,25 +165,6 @@ class AppDrawer extends StatelessWidget { child: ListView( shrinkWrap: true, children: [ - if (Platform.isIOS && - isHosted(context) && - !isPaidAccount(context)) - Material( - color: Colors.green, - child: ListTile( - leading: Icon( - FontAwesomeIcons.superpowers, - color: Colors.white, - ), - title: Text(localization.upgrade, - style: TextStyle(color: Colors.white)), - onTap: () => showDialog( - context: context, - builder: (BuildContext context) { - return UpgradeDialog(); - }), - ), - ), DrawerTile( company: company, icon: FontAwesomeIcons.tachometerAlt,