Settings
This commit is contained in:
parent
a0047acaa2
commit
dab542e652
|
|
@ -141,6 +141,49 @@ String paymentStatsForClient(
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var memoizedPaymentStatsForUser = memo5((String userId,
|
||||||
|
BuiltMap<String, PaymentEntity> paymentMap,
|
||||||
|
BuiltMap<String, InvoiceEntity> invoiceMap,
|
||||||
|
String activeLabel,
|
||||||
|
String archivedLabel) =>
|
||||||
|
paymentStatsForClient(
|
||||||
|
userId, paymentMap, invoiceMap, activeLabel, archivedLabel));
|
||||||
|
|
||||||
|
String paymentStatsForUser(
|
||||||
|
String userId,
|
||||||
|
BuiltMap<String, PaymentEntity> paymentMap,
|
||||||
|
BuiltMap<String, InvoiceEntity> invoiceMap,
|
||||||
|
String activeLabel,
|
||||||
|
String archivedLabel) {
|
||||||
|
int countActive = 0;
|
||||||
|
int countArchived = 0;
|
||||||
|
paymentMap.forEach((paymentId, payment) {
|
||||||
|
if (invoiceMap.containsKey(payment.invoiceId))
|
||||||
|
// TODO enable this code
|
||||||
|
//&& invoiceMap[payment.invoiceId].userId == userId)
|
||||||
|
{
|
||||||
|
if (payment.isActive) {
|
||||||
|
countActive++;
|
||||||
|
} else if (payment.isArchived) {
|
||||||
|
countArchived++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
String str = '';
|
||||||
|
if (countActive > 0) {
|
||||||
|
str = '$countActive $activeLabel';
|
||||||
|
if (countArchived > 0) {
|
||||||
|
str += ' • ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (countArchived > 0) {
|
||||||
|
str += '$countArchived $archivedLabel';
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
bool hasPaymentChanges(
|
bool hasPaymentChanges(
|
||||||
PaymentEntity payment, BuiltMap<String, PaymentEntity> paymentMap) =>
|
PaymentEntity payment, BuiltMap<String, PaymentEntity> paymentMap) =>
|
||||||
payment.isNew ? payment.isChanged : payment != paymentMap[payment.id];
|
payment.isNew ? payment.isChanged : payment != paymentMap[payment.id];
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,44 @@ String quoteStatsForClient(
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var memoizedQuoteStatsForUser = memo4((String userId,
|
||||||
|
BuiltMap<String, InvoiceEntity> quoteMap,
|
||||||
|
String activeLabel,
|
||||||
|
String archivedLabel) =>
|
||||||
|
quoteStatsForUser(userId, quoteMap, activeLabel, archivedLabel));
|
||||||
|
|
||||||
|
String quoteStatsForUser(
|
||||||
|
String userId,
|
||||||
|
BuiltMap<String, InvoiceEntity> quoteMap,
|
||||||
|
String activeLabel,
|
||||||
|
String archivedLabel) {
|
||||||
|
int countActive = 0;
|
||||||
|
int countArchived = 0;
|
||||||
|
quoteMap.forEach((quoteId, quote) {
|
||||||
|
// TODO change to user id match
|
||||||
|
if (quote.clientId == userId) {
|
||||||
|
if (quote.isActive) {
|
||||||
|
countActive++;
|
||||||
|
} else if (quote.isArchived) {
|
||||||
|
countArchived++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
String str = '';
|
||||||
|
if (countActive > 0) {
|
||||||
|
str = '$countActive $activeLabel';
|
||||||
|
if (countArchived > 0) {
|
||||||
|
str += ' • ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (countArchived > 0) {
|
||||||
|
str += '$countArchived $archivedLabel';
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
bool hasQuoteChanges(
|
bool hasQuoteChanges(
|
||||||
InvoiceEntity quote, BuiltMap<String, InvoiceEntity> quoteMap) =>
|
InvoiceEntity quote, BuiltMap<String, InvoiceEntity> quoteMap) =>
|
||||||
quote.isNew ? quote.isChanged : quote != quoteMap[quote.id];
|
quote.isNew ? quote.isChanged : quote != quoteMap[quote.id];
|
||||||
|
|
|
||||||
|
|
@ -158,12 +158,12 @@ class SettingsList extends StatelessWidget {
|
||||||
viewModel: viewModel,
|
viewModel: viewModel,
|
||||||
icon: FontAwesomeIcons.solidEnvelope,
|
icon: FontAwesomeIcons.solidEnvelope,
|
||||||
),
|
),
|
||||||
/*
|
|
||||||
SettingsListTile(
|
SettingsListTile(
|
||||||
section: kSettingsTemplatesAndReminders,
|
section: kSettingsTemplatesAndReminders,
|
||||||
viewModel: viewModel,
|
viewModel: viewModel,
|
||||||
icon: FontAwesomeIcons.solidClock,
|
icon: FontAwesomeIcons.file,
|
||||||
),
|
),
|
||||||
|
/*
|
||||||
SettingsListTile(
|
SettingsListTile(
|
||||||
section: kSettingsCreditCardsAndBanks,
|
section: kSettingsCreditCardsAndBanks,
|
||||||
viewModel: viewModel,
|
viewModel: viewModel,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/forms/app_form.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/settings_scaffold.dart';
|
import 'package:invoiceninja_flutter/ui/settings/settings_scaffold.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/templates_and_reminders_vm.dart';
|
import 'package:invoiceninja_flutter/ui/settings/templates_and_reminders_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||||
|
|
||||||
class TemplatesAndReminders extends StatefulWidget {
|
class TemplatesAndReminders extends StatefulWidget {
|
||||||
const TemplatesAndReminders({
|
const TemplatesAndReminders({
|
||||||
|
|
@ -18,8 +20,9 @@ class TemplatesAndReminders extends StatefulWidget {
|
||||||
|
|
||||||
class _TemplatesAndRemindersState extends State<TemplatesAndReminders>
|
class _TemplatesAndRemindersState extends State<TemplatesAndReminders>
|
||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
//static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
|
FocusScopeNode _focusNode;
|
||||||
TabController _controller;
|
TabController _controller;
|
||||||
|
|
||||||
bool autoValidate = false;
|
bool autoValidate = false;
|
||||||
|
|
@ -31,11 +34,13 @@ class _TemplatesAndRemindersState extends State<TemplatesAndReminders>
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_controller = TabController(vsync: this, length: 3);
|
_focusNode = FocusScopeNode();
|
||||||
|
_controller = TabController(vsync: this, length: 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
_focusNode.dispose();
|
||||||
_controller.dispose();
|
_controller.dispose();
|
||||||
_controllers.forEach((dynamic controller) {
|
_controllers.forEach((dynamic controller) {
|
||||||
controller.removeListener(_onChanged);
|
controller.removeListener(_onChanged);
|
||||||
|
|
@ -75,12 +80,65 @@ class _TemplatesAndRemindersState extends State<TemplatesAndReminders>
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final localization = AppLocalization.of(context);
|
final localization = AppLocalization.of(context);
|
||||||
//final viewModel = widget.viewModel;
|
final viewModel = widget.viewModel;
|
||||||
|
final state = viewModel.state;
|
||||||
|
|
||||||
return SettingsScaffold(
|
return SettingsScaffold(
|
||||||
title: localization.templatesAndReminders,
|
title: localization.templatesAndReminders,
|
||||||
onSavePressed: null,
|
onSavePressed: viewModel.onSavePressed,
|
||||||
body: SizedBox(),
|
appBarBottom: TabBar(
|
||||||
|
key: ValueKey(state.settingsUIState.updatedAt),
|
||||||
|
controller: _controller,
|
||||||
|
isScrollable: true,
|
||||||
|
tabs: [
|
||||||
|
Tab(
|
||||||
|
text: localization.invoices,
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
text: localization.quotes,
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
text: localization.payments,
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
text: localization.firstReminder,
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
text: localization.secondReminder,
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
text: localization.thirdReminder,
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
text: localization.endlessReminder,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: AppTabForm(
|
||||||
|
tabController: _controller,
|
||||||
|
formKey: _formKey,
|
||||||
|
focusNode: _focusNode,
|
||||||
|
children: <Widget>[
|
||||||
|
TemplateEditor(),
|
||||||
|
TemplateEditor(),
|
||||||
|
TemplateEditor(),
|
||||||
|
TemplateEditor(),
|
||||||
|
TemplateEditor(),
|
||||||
|
TemplateEditor(),
|
||||||
|
TemplateEditor(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TemplateEditor extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListView(
|
||||||
|
children: <Widget>[
|
||||||
|
Text('test')
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,14 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
import 'package:invoiceninja_flutter/constants.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/templates_and_reminders.dart';
|
import 'package:invoiceninja_flutter/ui/settings/templates_and_reminders.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
|
|
||||||
|
|
@ -27,6 +34,8 @@ class TemplatesAndRemindersScreen extends StatelessWidget {
|
||||||
class TemplatesAndRemindersVM {
|
class TemplatesAndRemindersVM {
|
||||||
TemplatesAndRemindersVM({
|
TemplatesAndRemindersVM({
|
||||||
@required this.state,
|
@required this.state,
|
||||||
|
@required this.settings,
|
||||||
|
@required this.onSettingsChanged,
|
||||||
@required this.onSavePressed,
|
@required this.onSavePressed,
|
||||||
@required this.onCancelPressed,
|
@required this.onCancelPressed,
|
||||||
});
|
});
|
||||||
|
|
@ -35,13 +44,37 @@ class TemplatesAndRemindersVM {
|
||||||
final state = store.state;
|
final state = store.state;
|
||||||
|
|
||||||
return TemplatesAndRemindersVM(
|
return TemplatesAndRemindersVM(
|
||||||
state: state,
|
state: state,
|
||||||
onSavePressed: null,
|
settings: state.uiState.settingsUIState.settings,
|
||||||
onCancelPressed: null,
|
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 AppState state;
|
||||||
|
final SettingsEntity settings;
|
||||||
|
final Function(SettingsEntity) onSettingsChanged;
|
||||||
final Function(BuildContext) onSavePressed;
|
final Function(BuildContext) onSavePressed;
|
||||||
final Function(BuildContext) onCancelPressed;
|
final Function(BuildContext) onCancelPressed;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import 'package:flutter_redux/flutter_redux.dart';
|
||||||
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_selectors.dart';
|
import 'package:invoiceninja_flutter/redux/invoice/invoice_selectors.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/payment/payment_selectors.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/quote/quote_selectors.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart';
|
import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/buttons/edit_icon_button.dart';
|
import 'package:invoiceninja_flutter/ui/app/buttons/edit_icon_button.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/entities/entity_state_title.dart';
|
import 'package:invoiceninja_flutter/ui/app/entities/entity_state_title.dart';
|
||||||
|
|
@ -29,6 +31,7 @@ class UserView extends StatelessWidget {
|
||||||
final localization = AppLocalization.of(context);
|
final localization = AppLocalization.of(context);
|
||||||
final user = viewModel.user;
|
final user = viewModel.user;
|
||||||
final state = StoreProvider.of<AppState>(context).state;
|
final state = StoreProvider.of<AppState>(context).state;
|
||||||
|
final company = state.selectedCompany;
|
||||||
final userCompany = state.userCompany;
|
final userCompany = state.userCompany;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
|
@ -100,7 +103,6 @@ class UserView extends StatelessWidget {
|
||||||
localization.active,
|
localization.active,
|
||||||
localization.archived),
|
localization.archived),
|
||||||
),
|
),
|
||||||
/*
|
|
||||||
EntityListTile(
|
EntityListTile(
|
||||||
bottomPadding: 1,
|
bottomPadding: 1,
|
||||||
icon: getEntityIcon(EntityType.payment),
|
icon: getEntityIcon(EntityType.payment),
|
||||||
|
|
@ -131,6 +133,7 @@ class UserView extends StatelessWidget {
|
||||||
localization.archived),
|
localization.archived),
|
||||||
)
|
)
|
||||||
: Container(),
|
: Container(),
|
||||||
|
/*
|
||||||
company.isModuleEnabled(EntityType.project)
|
company.isModuleEnabled(EntityType.project)
|
||||||
? EntityListTile(
|
? EntityListTile(
|
||||||
bottomPadding: 1,
|
bottomPadding: 1,
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ 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': {
|
||||||
|
'endless_reminder': 'Endless Reminder',
|
||||||
'filtered_by_user': 'Filtered by User',
|
'filtered_by_user': 'Filtered by User',
|
||||||
'administrator': 'Administrator',
|
'administrator': 'Administrator',
|
||||||
'administrator_help': 'Allow user to manage users, change settings and modify all records',
|
'administrator_help': 'Allow user to manage users, change settings and modify all records',
|
||||||
|
|
@ -15404,6 +15405,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
|
|
||||||
String get filteredByUser => _localizedValues[localeCode]['filtered_by_user'];
|
String get filteredByUser => _localizedValues[localeCode]['filtered_by_user'];
|
||||||
|
|
||||||
|
String get endlessReminder => _localizedValues[localeCode]['endless_reminder'];
|
||||||
|
|
||||||
String lookup(String key) {
|
String lookup(String key) {
|
||||||
final lookupKey = toSnakeCase(key);
|
final lookupKey = toSnakeCase(key);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue