Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
hillelcoren committed May 3, 2022
2 parents 53aa6a0 + 1751ba1 commit 61a759d
Show file tree
Hide file tree
Showing 16 changed files with 133 additions and 61 deletions.
6 changes: 3 additions & 3 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 5.0.80;
MARKETING_VERSION = 5.0.81;
PRODUCT_BUNDLE_IDENTIFIER = com.invoiceninja.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
Expand Down Expand Up @@ -510,7 +510,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 5.0.80;
MARKETING_VERSION = 5.0.81;
PRODUCT_BUNDLE_IDENTIFIER = com.invoiceninja.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
Expand All @@ -534,7 +534,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 5.0.80;
MARKETING_VERSION = 5.0.81;
PRODUCT_BUNDLE_IDENTIFIER = com.invoiceninja.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
Expand Down
2 changes: 1 addition & 1 deletion lib/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Constants {
}

// TODO remove version once #46609 is fixed
const String kClientVersion = '5.0.80';
const String kClientVersion = '5.0.81';
const String kMinServerVersion = '5.0.4';

const String kAppName = 'Invoice Ninja';
Expand Down
2 changes: 2 additions & 0 deletions lib/data/web_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class WebClient {
url += '&per_page=999999';
}

url += '&t=${DateTime.now().millisecondsSinceEpoch}';

print('GET: $url');

final client = http.Client();
Expand Down
67 changes: 61 additions & 6 deletions lib/ui/app/entity_dropdown.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/.env.dart';
import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/main_app.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/ui/app/app_border.dart';
import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
Expand All @@ -38,6 +39,7 @@ class EntityDropdown extends StatefulWidget {
this.onFieldSubmitted,
this.overrideSuggestedAmount,
this.overrideSuggestedLabel,
this.onCreateNew,
});

final EntityType entityType;
Expand All @@ -54,6 +56,7 @@ class EntityDropdown extends StatefulWidget {
final Function(Completer<SelectableEntity> completer) onAddPressed;
final Function(BaseEntity) overrideSuggestedAmount;
final Function(BaseEntity) overrideSuggestedLabel;
final Function(Completer<SelectableEntity> completer, String) onCreateNew;

@override
_EntityDropdownState createState() => _EntityDropdownState();
Expand Down Expand Up @@ -104,6 +107,8 @@ class _EntityDropdownState extends State<EntityDropdown> {
super.didUpdateWidget(oldWidget);

if (widget.entityId != oldWidget.entityId) {
final state = StoreProvider.of<AppState>(context).state;
_entityMap = widget.entityMap ?? state.getEntityMap(widget.entityType);
_textController.text = _getEntityLabel(_entityMap[widget.entityId]);
}
}
Expand Down Expand Up @@ -252,6 +257,12 @@ class _EntityDropdownState extends State<EntityDropdown> {
return <SelectableEntity>[];
}

if (widget.onCreateNew != null &&
options.isEmpty &&
textEditingValue.text.isNotEmpty) {
options.add(_AutocompleteEntity(name: textEditingValue.text));
}

return options;
},
displayStringForOption: (entity) => entity.listDisplayName,
Expand All @@ -266,14 +277,32 @@ class _EntityDropdownState extends State<EntityDropdown> {
return;
}

widget.onSelected(entity);
void _wrapUp(SelectableEntity entity) {
widget.onSelected(entity);

_focusNode.requestFocus();
_focusNode.requestFocus();

WidgetsBinding.instance.addPostFrameCallback((duration) {
_textController.selection = TextSelection.fromPosition(
TextPosition(offset: _textController.text.length));
});
WidgetsBinding.instance.addPostFrameCallback((duration) {
_textController.selection = TextSelection.fromPosition(
TextPosition(offset: _textController.text.length));
});
}

if (entity?.id == _AutocompleteEntity.KEY) {
final name = (entity as _AutocompleteEntity).name;
_textController.text = name;
_focusNode.removeListener(_onFocusChanged);
final completer = Completer<SelectableEntity>();
completer.future.then((value) {
_wrapUp(value);
_focusNode.addListener(_onFocusChanged);
}).catchError((dynamic error) {
_focusNode.addListener(_onFocusChanged);
});
widget.onCreateNew(completer, name);
} else {
_wrapUp(entity);
}
},
fieldViewBuilder: (BuildContext context,
TextEditingController textEditingController,
Expand Down Expand Up @@ -551,3 +580,29 @@ class EntityAutocompleteListTile extends StatelessWidget {
);
}
}

class _AutocompleteEntity extends Object with SelectableEntity {
_AutocompleteEntity({this.name});

static const KEY = '__new__';

final String name;

@override
String get id => KEY;

@override
bool matchesFilter(String filter) => true;

@override
String matchesFilterValue(String filter) => null;

@override
String get listDisplayName {
final localization = AppLocalization.of(navigatorKey.currentContext);
return '${localization.create}: $name';
}

@override
double get listDisplayAmount => null;
}
5 changes: 4 additions & 1 deletion lib/ui/app/forms/notification_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ class NotificationSettings extends StatelessWidget {
value = NOTIFY_NONE;
}
return DataRow(cells: [
DataCell(Text(localization.lookup(eventType))),
// workaround for mistake in translations
DataCell(Text(eventType == kNotificationsInvoiceSent
? localization.notificationInvoiceSent
: localization.lookup(eventType))),
DataCell(isAllEnabled
? value == NOTIFY_ALL
? IconText(
Expand Down
7 changes: 7 additions & 0 deletions lib/ui/expense/edit/expense_edit_details.dart
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,13 @@ class ExpenseEditDetailsState extends State<ExpenseEditDetails> {
onAddPressed: (completer) {
viewModel.onAddVendorPressed(context, completer);
},
/*
onCreateNew: (completer, name) {
store.dispatch(SaveVendorRequest(
vendor: VendorEntity().rebuild((b) => b..name = name),
completer: completer));
},
*/
),
if (!expense.isInvoiced) ...[
EntityDropdown(
Expand Down
14 changes: 5 additions & 9 deletions lib/ui/reports/reports_screen_vm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -404,10 +404,8 @@ class ReportsScreenVM {
final value = row[i]
.renderText(context, column)
.trim()
.replaceAll('"', '\\"');
csvData += value.contains(' ') || value.contains('"')
? '"$value",'
: '$value,';
.replaceAll('"', '""');
csvData += '"$value",';
}
csvData = csvData.substring(0, csvData.length - 1);
});
Expand All @@ -432,14 +430,12 @@ class ReportsScreenVM {
groupTotals.rows.forEach((group) {
final row = groupTotals.totals[group];
csvData +=
'"${group.trim().replaceAll('"', '\\"')}",${row['count'].toInt()}';
'"${group.trim().replaceAll('"', '""')}",${row['count'].toInt()}';

columns.forEach((column) {
final value =
row[column].toString().trim().replaceAll('"', '\\"');
csvData += value.contains(' ') || value.contains('"')
? ',"$value"'
: ',$value';
row[column].toString().trim().replaceAll('"', '""');
csvData += ',"$value"';
});

csvData += '\n';
Expand Down
7 changes: 0 additions & 7 deletions lib/ui/settings/client_portal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -392,13 +392,6 @@ class _ClientPortalState extends State<ClientPortal>
.rebuild((b) => b..enablePortalDashboard = value)),
),
*/
BoolDropdownButton(
label: localization.tasks,
value: settings.enablePortalTasks,
iconData: getEntityIcon(EntityType.task),
onChanged: (value) => viewModel.onSettingsChanged(
settings.rebuild((b) => b..enablePortalTasks = value)),
),
BoolDropdownButton(
label: localization.documentUpload,
helpLabel: localization.documentUploadHelp,
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/settings/settings_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ class SettingsSearch extends StatelessWidget {
'task_settings',
'auto_start_tasks',
'show_tasks_table',
'client_portal',
],
],
kSettingsTaskStatuses: [
Expand Down Expand Up @@ -515,7 +516,6 @@ class SettingsSearch extends StatelessWidget {
[
'client_portal',
'dashboard',
'tasks',
'portal_mode',
'subdomain',
'domain',
Expand Down
57 changes: 34 additions & 23 deletions lib/ui/settings/task_settings.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Flutter imports:
import 'package:flutter/material.dart';
import 'package:invoiceninja_flutter/constants.dart';

// Project imports:
import 'package:invoiceninja_flutter/data/models/settings_model.dart';
Expand All @@ -8,9 +9,11 @@ import 'package:invoiceninja_flutter/ui/app/edit_scaffold.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/app/forms/app_dropdown_button.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/task_settings_vm.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/icons.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';

class TaskSettings extends StatefulWidget {
Expand Down Expand Up @@ -160,29 +163,37 @@ class _TaskSettingsState extends State<TaskSettings> {
],
],
),
if ((settings.enablePortalTasks ?? false) != false)
FormCard(
children: [
AppDropdownButton<String>(
labelText: localization.tasksShownInPortal,
value: settings.clientPortalTasks,
onChanged: (dynamic value) {
viewModel.onSettingsChanged(
settings.rebuild((b) => b..clientPortalTasks = value));
},
items: [
SettingsEntity.PORTAL_TASKS_INVOICED,
SettingsEntity.PORTAL_TASKS_UNINVOICED,
SettingsEntity.PORTAL_TASKS_ALL,
]
.map((value) => DropdownMenuItem(
child: Text(localization.lookup(value)),
value: value,
))
.toList(),
),
],
),
FormCard(
children: [
BoolDropdownButton(
label: localization.clientPortal,
value: settings.enablePortalTasks,
iconData: getSettingIcon(kSettingsClientPortal),
onChanged: (value) => viewModel.onSettingsChanged(
settings.rebuild((b) => b..enablePortalTasks = value)),
),
AppDropdownButton<String>(
labelText: localization.tasksShownInPortal,
value: settings.clientPortalTasks,
onChanged: ((settings.enablePortalTasks ?? false) != false)
? (dynamic value) {
viewModel.onSettingsChanged(settings
.rebuild((b) => b..clientPortalTasks = value));
}
: null,
items: [
SettingsEntity.PORTAL_TASKS_INVOICED,
SettingsEntity.PORTAL_TASKS_UNINVOICED,
SettingsEntity.PORTAL_TASKS_ALL,
]
.map((value) => DropdownMenuItem(
child: Text(localization.lookup(value)),
value: value,
))
.toList(),
),
],
),
if (!viewModel.state.settingsUIState.isFiltered)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
Expand Down
5 changes: 5 additions & 0 deletions lib/utils/i18n.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mixin LocalizationsProvider on LocaleCodeAware {
static final Map<String, Map<String, String>> _localizedValues = {
'en': {
// STARTER: lang key - do not remove comment
'notification_invoice_sent': 'Invoice Sent',
'auto_archive_paid_invoices': 'Auto Archive Paid',
'auto_archive_paid_invoices_help':
'Automatically archive invoices when they are paid.',
Expand Down Expand Up @@ -75031,6 +75032,10 @@ mixin LocalizationsProvider on LocaleCodeAware {
_localizedValues[localeCode]['auto_archive_cancelled_invoices_help'] ??
_localizedValues[localeCode]['auto_archive_cancelled_invoices_help'];

String get notificationInvoiceSent =>
_localizedValues[localeCode]['notification_invoice_sent'] ??
_localizedValues[localeCode]['notification_invoice_sent'];

// STARTER: lang field - do not remove comment

String lookup(String key) {
Expand Down
6 changes: 3 additions & 3 deletions macos/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 5.0.80;
MARKETING_VERSION = 5.0.81;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
Expand Down Expand Up @@ -554,7 +554,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 5.0.80;
MARKETING_VERSION = 5.0.81;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
Expand All @@ -576,7 +576,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 5.0.80;
MARKETING_VERSION = 5.0.81;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
Expand Down
4 changes: 2 additions & 2 deletions pubspec.foss.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: invoiceninja_flutter
description: Client for Invoice Ninja
version: 5.0.80+80
version: 5.0.81+81
homepage: https://invoiceninja.com
documentation: https://invoiceninja.github.io
publish_to: none
Expand Down Expand Up @@ -94,7 +94,7 @@ msix_config:
display_name: Invoice Ninja
publisher_display_name: Invoice Ninja
identity_name: InvoiceNinja.InvoiceNinja
msix_version: 5.0.80.0
msix_version: 5.0.81.0
publisher: CN=2B7AA393-06A0-46F5-AF85-1917142440C3
architecture: x64
capabilities: 'internetClient'
Expand Down
Loading

0 comments on commit 61a759d

Please sign in to comment.