Settings
This commit is contained in:
parent
16fdb6f5ca
commit
1cb94eafd8
|
|
@ -45,7 +45,7 @@ import 'package:invoiceninja_flutter/ui/settings/device_settings_list_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/email_settings_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/email_settings_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/import_export_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/import_export_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/invoice_design_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/invoice_design_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/invoice_settings_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/system_settings_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/localization_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/localization_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/notifications_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/notifications_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/online_payments_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/online_payments_vm.dart';
|
||||||
|
|
@ -354,7 +354,7 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
|
||||||
GroupSettingsScreen.route: (context) => GroupSettingsScreen(),
|
GroupSettingsScreen.route: (context) => GroupSettingsScreen(),
|
||||||
GroupEditScreen.route: (context) => GroupEditScreen(),
|
GroupEditScreen.route: (context) => GroupEditScreen(),
|
||||||
GroupViewScreen.route: (context) => GroupViewScreen(),
|
GroupViewScreen.route: (context) => GroupViewScreen(),
|
||||||
InvoiceSettingsScreen.route: (context) => InvoiceSettingsScreen(),
|
SystemSettingsScreen.route: (context) => SystemSettingsScreen(),
|
||||||
InvoiceDesignScreen.route: (context) => InvoiceDesignScreen(),
|
InvoiceDesignScreen.route: (context) => InvoiceDesignScreen(),
|
||||||
ClientPortalScreen.route: (context) => ClientPortalScreen(),
|
ClientPortalScreen.route: (context) => ClientPortalScreen(),
|
||||||
BuyNowButtonsScreen.route: (context) => BuyNowButtonsScreen(),
|
BuyNowButtonsScreen.route: (context) => BuyNowButtonsScreen(),
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import 'package:invoiceninja_flutter/ui/settings/device_settings_list_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/email_settings_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/email_settings_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/import_export_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/import_export_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/invoice_design_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/invoice_design_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/invoice_settings_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/system_settings_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/localization_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/localization_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/notifications_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/notifications_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/products_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/products_vm.dart';
|
||||||
|
|
@ -205,7 +205,7 @@ class SettingsScreens extends StatelessWidget {
|
||||||
screen = GroupEditScreen();
|
screen = GroupEditScreen();
|
||||||
break;
|
break;
|
||||||
case kSettingsInvoiceSettings:
|
case kSettingsInvoiceSettings:
|
||||||
screen = InvoiceSettingsScreen();
|
screen = SystemSettingsScreen();
|
||||||
break;
|
break;
|
||||||
case kSettingsInvoiceDesign:
|
case kSettingsInvoiceDesign:
|
||||||
screen = InvoiceDesignScreen();
|
screen = InvoiceDesignScreen();
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ class _ClientPortalState extends State<ClientPortal>
|
||||||
|
|
||||||
return SettingsScaffold(
|
return SettingsScaffold(
|
||||||
title: localization.clientPortal,
|
title: localization.clientPortal,
|
||||||
onSavePressed: null,
|
onSavePressed: viewModel.onSavePressed,
|
||||||
appBarBottom: TabBar(
|
appBarBottom: TabBar(
|
||||||
key: ValueKey(state.settingsUIState.updatedAt),
|
key: ValueKey(state.settingsUIState.updatedAt),
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
|
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/settings/invoice_settings_vm.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/settings/settings_scaffold.dart';
|
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
|
||||||
|
|
||||||
class InvoiceSettings extends StatefulWidget {
|
|
||||||
const InvoiceSettings({
|
|
||||||
Key key,
|
|
||||||
@required this.viewModel,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final InvoiceSettingsVM viewModel;
|
|
||||||
|
|
||||||
@override
|
|
||||||
_InvoiceSettingsState createState() => _InvoiceSettingsState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _InvoiceSettingsState extends State<InvoiceSettings>
|
|
||||||
with SingleTickerProviderStateMixin {
|
|
||||||
//static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
|
||||||
|
|
||||||
TabController _controller;
|
|
||||||
|
|
||||||
bool autoValidate = false;
|
|
||||||
|
|
||||||
final _nameController = TextEditingController();
|
|
||||||
|
|
||||||
List<TextEditingController> _controllers = [];
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_controller = TabController(vsync: this, length: 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_controller.dispose();
|
|
||||||
_controllers.forEach((dynamic controller) {
|
|
||||||
controller.removeListener(_onChanged);
|
|
||||||
controller.dispose();
|
|
||||||
});
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
_controllers = [_nameController];
|
|
||||||
|
|
||||||
_controllers
|
|
||||||
.forEach((dynamic controller) => controller.removeListener(_onChanged));
|
|
||||||
|
|
||||||
/*
|
|
||||||
final product = widget.viewModel.product;
|
|
||||||
_productKeyController.text = product.productKey;
|
|
||||||
*/
|
|
||||||
|
|
||||||
_controllers
|
|
||||||
.forEach((dynamic controller) => controller.addListener(_onChanged));
|
|
||||||
|
|
||||||
super.didChangeDependencies();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onChanged() {
|
|
||||||
/*
|
|
||||||
final product = widget.viewModel.product.rebuild((b) => b
|
|
||||||
..customValue2 = _custom2Controller.text.trim());
|
|
||||||
if (product != widget.viewModel.product) {
|
|
||||||
widget.viewModel.onChanged(product);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final localization = AppLocalization.of(context);
|
|
||||||
//final viewModel = widget.viewModel;
|
|
||||||
|
|
||||||
return SettingsScaffold(
|
|
||||||
title: localization.invoiceSettings,
|
|
||||||
onSavePressed: null,
|
|
||||||
body: SizedBox(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
|
||||||
import 'package:invoiceninja_flutter/constants.dart';
|
|
||||||
import 'package:invoiceninja_flutter/ui/settings/invoice_settings.dart';
|
|
||||||
import 'package:redux/redux.dart';
|
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
|
||||||
|
|
||||||
class InvoiceSettingsScreen extends StatelessWidget {
|
|
||||||
const InvoiceSettingsScreen({Key key}) : super(key: key);
|
|
||||||
static const String route = '/$kSettings/$kSettingsInvoiceSettings';
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return StoreConnector<AppState, InvoiceSettingsVM>(
|
|
||||||
converter: InvoiceSettingsVM.fromStore,
|
|
||||||
builder: (context, viewModel) {
|
|
||||||
return InvoiceSettings(
|
|
||||||
viewModel: viewModel,
|
|
||||||
key: ValueKey(viewModel.state.settingsUIState.updatedAt),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class InvoiceSettingsVM {
|
|
||||||
InvoiceSettingsVM({
|
|
||||||
@required this.state,
|
|
||||||
@required this.onSavePressed,
|
|
||||||
@required this.onCancelPressed,
|
|
||||||
});
|
|
||||||
|
|
||||||
static InvoiceSettingsVM fromStore(Store<AppState> store) {
|
|
||||||
final state = store.state;
|
|
||||||
|
|
||||||
return InvoiceSettingsVM(
|
|
||||||
state: state,
|
|
||||||
onSavePressed: null,
|
|
||||||
onCancelPressed: null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final AppState state;
|
|
||||||
final Function(BuildContext) onSavePressed;
|
|
||||||
final Function(BuildContext) onCancelPressed;
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,329 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.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/decorated_form_field.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/settings/system_settings_vm.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/settings/settings_scaffold.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
|
||||||
|
class SystemSettings extends StatefulWidget {
|
||||||
|
const SystemSettings({
|
||||||
|
Key key,
|
||||||
|
@required this.viewModel,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final SystemSettingsVM viewModel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
_SystemSettingsState createState() => _SystemSettingsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SystemSettingsState extends State<SystemSettings>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
|
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
|
FocusScopeNode _focusNode;
|
||||||
|
TabController _controller;
|
||||||
|
|
||||||
|
bool autoValidate = false;
|
||||||
|
|
||||||
|
final _recurringPrefixController = TextEditingController();
|
||||||
|
|
||||||
|
List<TextEditingController> _controllers = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_focusNode = FocusScopeNode();
|
||||||
|
_controller = TabController(vsync: this, length: 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_focusNode.dispose();
|
||||||
|
_controller.dispose();
|
||||||
|
_controllers.forEach((dynamic controller) {
|
||||||
|
controller.removeListener(_onChanged);
|
||||||
|
controller.dispose();
|
||||||
|
});
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
_controllers = [
|
||||||
|
_recurringPrefixController,
|
||||||
|
];
|
||||||
|
|
||||||
|
_controllers
|
||||||
|
.forEach((dynamic controller) => controller.removeListener(_onChanged));
|
||||||
|
|
||||||
|
|
||||||
|
//_recurringPrefixController.text = widget.viewModel.settings.
|
||||||
|
/*
|
||||||
|
final product = widget.viewModel.product;
|
||||||
|
_productKeyController.text = product.productKey;
|
||||||
|
*/
|
||||||
|
|
||||||
|
_controllers
|
||||||
|
.forEach((dynamic controller) => controller.addListener(_onChanged));
|
||||||
|
|
||||||
|
super.didChangeDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onChanged() {
|
||||||
|
/*
|
||||||
|
final product = widget.viewModel.product.rebuild((b) => b
|
||||||
|
..customValue2 = _custom2Controller.text.trim());
|
||||||
|
if (product != widget.viewModel.product) {
|
||||||
|
widget.viewModel.onChanged(product);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final localization = AppLocalization.of(context);
|
||||||
|
final viewModel = widget.viewModel;
|
||||||
|
final settings = viewModel.settings;
|
||||||
|
final state = viewModel.state;
|
||||||
|
|
||||||
|
return SettingsScaffold(
|
||||||
|
title: localization.systemSettings,
|
||||||
|
onSavePressed: null,
|
||||||
|
appBarBottom: TabBar(
|
||||||
|
key: ValueKey(state.settingsUIState.updatedAt),
|
||||||
|
controller: _controller,
|
||||||
|
tabs: [
|
||||||
|
Tab(
|
||||||
|
text: localization.general,
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
text: localization.clients,
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
text: localization.products,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: AppTabForm(
|
||||||
|
tabController: _controller,
|
||||||
|
formKey: _formKey,
|
||||||
|
focusNode: _focusNode,
|
||||||
|
children: <Widget>[
|
||||||
|
ListView(
|
||||||
|
children: <Widget>[
|
||||||
|
FormCard(
|
||||||
|
children: <Widget>[
|
||||||
|
InputDecorator(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: localization.padding,
|
||||||
|
),
|
||||||
|
//isEmpty: false,
|
||||||
|
child: DropdownButtonHideUnderline(
|
||||||
|
child: DropdownButton<int>(
|
||||||
|
//value:
|
||||||
|
isExpanded: true,
|
||||||
|
isDense: true,
|
||||||
|
/*
|
||||||
|
onChanged: (value) => viewModel.onSettingsChanged(
|
||||||
|
settings
|
||||||
|
.rebuild((b) => b..portalMode = value)),
|
||||||
|
*/
|
||||||
|
items: List<int>.generate(10, (i) => i + 1)
|
||||||
|
.map((value) => DropdownMenuItem(
|
||||||
|
child: Text('${'0' * value}1'),
|
||||||
|
value: value,
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
DecoratedFormField(
|
||||||
|
label: localization.recurringPrefix,
|
||||||
|
controller: _recurringPrefixController,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
ListView(children: <Widget>[
|
||||||
|
FormCard(
|
||||||
|
children: <Widget>[
|
||||||
|
EntityNumberSettings(),
|
||||||
|
CustomFieldsSettings(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
ListView(
|
||||||
|
children: <Widget>[
|
||||||
|
FormCard(
|
||||||
|
children: <Widget>[
|
||||||
|
EntityNumberSettings(),
|
||||||
|
CustomFieldsSettings(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EntityNumberSettings extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_EntityNumberSettingsState createState() => _EntityNumberSettingsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EntityNumberSettingsState extends State<EntityNumberSettings> {
|
||||||
|
final _counterController = TextEditingController();
|
||||||
|
final _patternController = TextEditingController();
|
||||||
|
|
||||||
|
List<TextEditingController> _controllers = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controllers.forEach((dynamic controller) {
|
||||||
|
controller.removeListener(_onChanged);
|
||||||
|
controller.dispose();
|
||||||
|
});
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
_controllers = [
|
||||||
|
_counterController,
|
||||||
|
_patternController,
|
||||||
|
];
|
||||||
|
|
||||||
|
_controllers
|
||||||
|
.forEach((dynamic controller) => controller.removeListener(_onChanged));
|
||||||
|
|
||||||
|
/*
|
||||||
|
final product = widget.viewModel.product;
|
||||||
|
_productKeyController.text = product.productKey;
|
||||||
|
*/
|
||||||
|
|
||||||
|
_controllers
|
||||||
|
.forEach((dynamic controller) => controller.addListener(_onChanged));
|
||||||
|
|
||||||
|
super.didChangeDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onChanged() {
|
||||||
|
/*
|
||||||
|
final product = widget.viewModel.product.rebuild((b) => b
|
||||||
|
..customValue2 = _custom2Controller.text.trim());
|
||||||
|
if (product != widget.viewModel.product) {
|
||||||
|
widget.viewModel.onChanged(product);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final localization = AppLocalization.of(context);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: <Widget>[
|
||||||
|
DecoratedFormField(
|
||||||
|
label: localization.pattern,
|
||||||
|
controller: _patternController,
|
||||||
|
),
|
||||||
|
DecoratedFormField(
|
||||||
|
label: localization.counter,
|
||||||
|
controller: _counterController,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomFieldsSettings extends StatefulWidget {
|
||||||
|
const CustomFieldsSettings({this.fieldLabel});
|
||||||
|
|
||||||
|
final String fieldLabel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
_CustomFieldsSettingsState createState() => _CustomFieldsSettingsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CustomFieldsSettingsState extends State<CustomFieldsSettings> {
|
||||||
|
final _customField1Controller = TextEditingController();
|
||||||
|
final _customField2Controller = TextEditingController();
|
||||||
|
final _customField3Controller = TextEditingController();
|
||||||
|
final _customField4Controller = TextEditingController();
|
||||||
|
|
||||||
|
List<TextEditingController> _controllers = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controllers.forEach((dynamic controller) {
|
||||||
|
controller.removeListener(_onChanged);
|
||||||
|
controller.dispose();
|
||||||
|
});
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
_controllers = [
|
||||||
|
_customField1Controller,
|
||||||
|
_customField2Controller,
|
||||||
|
_customField3Controller,
|
||||||
|
_customField4Controller,
|
||||||
|
];
|
||||||
|
|
||||||
|
_controllers
|
||||||
|
.forEach((dynamic controller) => controller.removeListener(_onChanged));
|
||||||
|
|
||||||
|
/*
|
||||||
|
final product = widget.viewModel.product;
|
||||||
|
_productKeyController.text = product.productKey;
|
||||||
|
*/
|
||||||
|
|
||||||
|
_controllers
|
||||||
|
.forEach((dynamic controller) => controller.addListener(_onChanged));
|
||||||
|
|
||||||
|
super.didChangeDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onChanged() {
|
||||||
|
/*
|
||||||
|
final product = widget.viewModel.product.rebuild((b) => b
|
||||||
|
..customValue2 = _custom2Controller.text.trim());
|
||||||
|
if (product != widget.viewModel.product) {
|
||||||
|
widget.viewModel.onChanged(product);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final localization = AppLocalization.of(context);
|
||||||
|
|
||||||
|
return FormCard(
|
||||||
|
children: <Widget>[
|
||||||
|
DecoratedFormField(
|
||||||
|
label: widget.fieldLabel,
|
||||||
|
controller: _customField1Controller,
|
||||||
|
),
|
||||||
|
DecoratedFormField(
|
||||||
|
label: widget.fieldLabel,
|
||||||
|
controller: _customField2Controller,
|
||||||
|
),
|
||||||
|
DecoratedFormField(
|
||||||
|
label: widget.fieldLabel,
|
||||||
|
controller: _customField2Controller,
|
||||||
|
),
|
||||||
|
DecoratedFormField(
|
||||||
|
label: widget.fieldLabel,
|
||||||
|
controller: _customField2Controller,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
import 'package:invoiceninja_flutter/constants.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/company_model.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/group/group_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/settings/system_settings.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
import 'package:redux/redux.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
|
|
||||||
|
class SystemSettingsScreen extends StatelessWidget {
|
||||||
|
const SystemSettingsScreen({Key key}) : super(key: key);
|
||||||
|
static const String route = '/$kSettings/$kSettingsInvoiceSettings';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return StoreConnector<AppState, SystemSettingsVM>(
|
||||||
|
converter: SystemSettingsVM.fromStore,
|
||||||
|
builder: (context, viewModel) {
|
||||||
|
return SystemSettings(
|
||||||
|
viewModel: viewModel,
|
||||||
|
key: ValueKey(viewModel.state.settingsUIState.updatedAt),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SystemSettingsVM {
|
||||||
|
SystemSettingsVM({
|
||||||
|
@required this.state,
|
||||||
|
@required this.onSavePressed,
|
||||||
|
@required this.onCancelPressed,
|
||||||
|
@required this.settings,
|
||||||
|
@required this.onSettingsChanged,
|
||||||
|
});
|
||||||
|
|
||||||
|
static SystemSettingsVM fromStore(Store<AppState> store) {
|
||||||
|
final state = store.state;
|
||||||
|
|
||||||
|
return SystemSettingsVM(
|
||||||
|
state: state,
|
||||||
|
settings: state.uiState.settingsUIState.settings,
|
||||||
|
onSettingsChanged: (settings) {
|
||||||
|
store.dispatch(UpdateSettings(settings: settings));
|
||||||
|
},
|
||||||
|
onCancelPressed: (context) => store.dispatch(ResetSettings()),
|
||||||
|
onSavePressed: (context) {
|
||||||
|
final settingsUIState = state.uiState.settingsUIState;
|
||||||
|
final completer = snackBarCompleter(
|
||||||
|
context, AppLocalization.of(context).savedSettings);
|
||||||
|
switch (settingsUIState.entityType) {
|
||||||
|
case EntityType.company:
|
||||||
|
store.dispatch(SaveCompanyRequest(
|
||||||
|
completer: completer,
|
||||||
|
company: settingsUIState.userCompany.company));
|
||||||
|
break;
|
||||||
|
case EntityType.group:
|
||||||
|
store.dispatch(SaveGroupRequest(
|
||||||
|
completer: completer, group: settingsUIState.group));
|
||||||
|
break;
|
||||||
|
case EntityType.client:
|
||||||
|
store.dispatch(SaveClientRequest(
|
||||||
|
completer: completer, client: settingsUIState.client));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
final AppState state;
|
||||||
|
final Function(BuildContext) onSavePressed;
|
||||||
|
final Function(BuildContext) onCancelPressed;
|
||||||
|
final SettingsEntity settings;
|
||||||
|
final Function(SettingsEntity) onSettingsChanged;
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,23 @@ abstract class LocaleCodeAware {
|
||||||
mixin LocalizationsProvider on LocaleCodeAware {
|
mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
static final Map<String, Map<String, String>> _localizedValues = {
|
static final Map<String, Map<String, String>> _localizedValues = {
|
||||||
'en': {
|
'en': {
|
||||||
|
'recurring_prefix': 'Recurring Prefix',
|
||||||
|
'padding': 'Padding',
|
||||||
|
'general': 'General',
|
||||||
|
'invoice_field': 'Invoice Field',
|
||||||
|
'client_field': 'Client Field',
|
||||||
|
'product_field': 'Product Field',
|
||||||
|
'quote_field': 'Quote Field',
|
||||||
|
'payment_field': 'Payment Field',
|
||||||
|
'contact_field': 'Contact Field',
|
||||||
|
'vendor_field': 'Vendor Field',
|
||||||
|
'expense_field': 'Expense Field',
|
||||||
|
'project_field': 'Project Field',
|
||||||
|
'task_field': 'Task Field',
|
||||||
|
'group_field': 'Group Field',
|
||||||
|
'counter': 'Counter',
|
||||||
|
'prefix': 'Prefix',
|
||||||
|
'pattern': 'Pattern',
|
||||||
'messages': 'Messages',
|
'messages': 'Messages',
|
||||||
'custom_css': 'Custom CSS',
|
'custom_css': 'Custom CSS',
|
||||||
'custom_javascript': 'Custom JavaScript',
|
'custom_javascript': 'Custom JavaScript',
|
||||||
|
|
@ -170,7 +187,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
'tax_rates': 'Tax Rates',
|
'tax_rates': 'Tax Rates',
|
||||||
'notifications': 'Notifications',
|
'notifications': 'Notifications',
|
||||||
'import_export': 'Import | Export',
|
'import_export': 'Import | Export',
|
||||||
'invoice_settings': 'Invoice Settings',
|
'system_settings': 'System Settings',
|
||||||
'invoice_design': 'Invoice Design',
|
'invoice_design': 'Invoice Design',
|
||||||
'buy_now_buttons': 'Buy Now Buttons',
|
'buy_now_buttons': 'Buy Now Buttons',
|
||||||
'email_settings': 'Email Settings',
|
'email_settings': 'Email Settings',
|
||||||
|
|
@ -14794,8 +14811,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
|
|
||||||
String get importExport => _localizedValues[localeCode]['import_export'];
|
String get importExport => _localizedValues[localeCode]['import_export'];
|
||||||
|
|
||||||
String get invoiceSettings =>
|
String get systemSettings => _localizedValues[localeCode]['system_settings'];
|
||||||
_localizedValues[localeCode]['invoice_settings'];
|
|
||||||
|
|
||||||
String get invoiceDesign => _localizedValues[localeCode]['invoice_design'];
|
String get invoiceDesign => _localizedValues[localeCode]['invoice_design'];
|
||||||
|
|
||||||
|
|
@ -15118,21 +15134,51 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
String get requireQuoteSignature =>
|
String get requireQuoteSignature =>
|
||||||
_localizedValues[localeCode]['require_quote_signature'];
|
_localizedValues[localeCode]['require_quote_signature'];
|
||||||
|
|
||||||
String get signatureOnPdf =>
|
String get signatureOnPdf => _localizedValues[localeCode]['signature_on_pdf'];
|
||||||
_localizedValues[localeCode]['signature_on_pdf'];
|
|
||||||
|
|
||||||
String get signatureOnPdfHelp =>
|
String get signatureOnPdfHelp =>
|
||||||
_localizedValues[localeCode]['signature_on_pdf_help'];
|
_localizedValues[localeCode]['signature_on_pdf_help'];
|
||||||
|
|
||||||
String get customCss =>
|
String get customCss => _localizedValues[localeCode]['custom_css'];
|
||||||
_localizedValues[localeCode]['custom_css'];
|
|
||||||
|
|
||||||
String get customJavascript =>
|
String get customJavascript =>
|
||||||
_localizedValues[localeCode]['custom_javascript'];
|
_localizedValues[localeCode]['custom_javascript'];
|
||||||
|
|
||||||
String get messages =>
|
String get messages => _localizedValues[localeCode]['messages'];
|
||||||
_localizedValues[localeCode]['messages'];
|
|
||||||
|
|
||||||
|
String get prefix => _localizedValues[localeCode]['prefix'];
|
||||||
|
|
||||||
|
String get pattern => _localizedValues[localeCode]['pattern'];
|
||||||
|
|
||||||
|
String get counter => _localizedValues[localeCode]['counter'];
|
||||||
|
|
||||||
|
String get invoiceField => _localizedValues[localeCode]['invoice_field'];
|
||||||
|
|
||||||
|
String get clientField => _localizedValues[localeCode]['client_field'];
|
||||||
|
|
||||||
|
String get productField => _localizedValues[localeCode]['product_field'];
|
||||||
|
|
||||||
|
String get quotField => _localizedValues[localeCode]['quote_field'];
|
||||||
|
|
||||||
|
String get paymentField => _localizedValues[localeCode]['payment_field'];
|
||||||
|
|
||||||
|
String get contactField => _localizedValues[localeCode]['contact_field'];
|
||||||
|
|
||||||
|
String get vendorField => _localizedValues[localeCode]['vendor_field'];
|
||||||
|
|
||||||
|
String get expenseField => _localizedValues[localeCode]['expense_field'];
|
||||||
|
|
||||||
|
String get projectField => _localizedValues[localeCode]['project_field'];
|
||||||
|
|
||||||
|
String get taskField => _localizedValues[localeCode]['task_field'];
|
||||||
|
|
||||||
|
String get groupField => _localizedValues[localeCode]['group_field'];
|
||||||
|
|
||||||
|
String get general => _localizedValues[localeCode]['general'];
|
||||||
|
|
||||||
|
String get padding => _localizedValues[localeCode]['padding'];
|
||||||
|
|
||||||
|
String get recurringPrefix => _localizedValues[localeCode]['recurring_prefix'];
|
||||||
|
|
||||||
String lookup(String key) {
|
String lookup(String key) {
|
||||||
final lookupKey = toSnakeCase(key);
|
final lookupKey = toSnakeCase(key);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue