Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
hillelcoren committed Jul 4, 2024
2 parents 9e6a4b0 + eafb3bb commit 444c7c5
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 89 deletions.
2 changes: 2 additions & 0 deletions lib/data/models/client_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,8 @@ abstract class ClientEntity extends Object
actions.add(EntityAction.runTemplate);
}

actions.add(EntityAction.assignGroup);

if (!multiselect) {
actions.add(EntityAction.addComment);
}
Expand Down
1 change: 1 addition & 0 deletions lib/data/models/models.dart
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ class EntityAction extends EnumClass {
static const EntityAction bulkUpdate = _$bulkUpdate;
static const EntityAction reconnect = _$reconnect;
static const EntityAction addComment = _$addComment;
static const EntityAction assignGroup = _$assignGroup;

@override
String toString() {
Expand Down
4 changes: 4 additions & 0 deletions lib/data/models/models.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

113 changes: 113 additions & 0 deletions lib/redux/client/client_actions.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
// Dart imports:
import 'dart:async';
import 'dart:convert';

// Flutter imports:
import 'package:flutter/material.dart';

// Package imports:
import 'package:built_collection/built_collection.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:flutter_styled_toast/flutter_styled_toast.dart';
import 'package:http/http.dart';
import 'package:invoiceninja_flutter/data/web_client.dart';
import 'package:invoiceninja_flutter/main_app.dart';
import 'package:invoiceninja_flutter/redux/document/document_actions.dart';
import 'package:invoiceninja_flutter/redux/static/static_selectors.dart';
import 'package:invoiceninja_flutter/ui/app/forms/client_picker.dart';
import 'package:invoiceninja_flutter/ui/app/forms/dynamic_selector.dart';
import 'package:invoiceninja_flutter/utils/dialogs.dart';
import 'package:url_launcher/url_launcher.dart';

Expand Down Expand Up @@ -541,6 +546,15 @@ void handleClientAction(BuildContext? context, List<BaseEntity> clients,
),
);
break;
case EntityAction.assignGroup:
showDialog<void>(
context: context,
barrierDismissible: false,
builder: (context) => _AssignGroupDialog(
clients: clients,
),
);
break;
case EntityAction.runTemplate:
showDialog<void>(
context: context,
Expand Down Expand Up @@ -627,6 +641,105 @@ class UpdateClientTab implements PersistUI {
final int? tabIndex;
}

class _AssignGroupDialog extends StatefulWidget {
const _AssignGroupDialog({
required this.clients,
});

final List<BaseEntity> clients;

@override
State<_AssignGroupDialog> createState() => __AssignGroupDialogState();
}

class __AssignGroupDialogState extends State<_AssignGroupDialog> {
String _groupId = '';
bool _isLoading = false;

@override
Widget build(BuildContext context) {
final localization = AppLocalization.of(context)!;
final store = StoreProvider.of<AppState>(context);
final state = store.state;

return AlertDialog(
title: Text(localization.assignGroup),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text((_isLoading ? localization.cancel : localization.close)
.toUpperCase()),
),
TextButton(
onPressed: _groupId.isEmpty || _isLoading
? null
: () {
final credentials = state.credentials;
final url = '${credentials.url}/clients/bulk';
final data = {
'ids': widget.clients.map((entity) => entity.id).toList(),
'group_settings_id': _groupId,
'action': EntityAction.assignGroup.toApiParam(),
};

setState(() => _isLoading = true);

WebClient()
.post(url, credentials.token, data: jsonEncode(data))
.then((response) async {
setState(() => _isLoading = false);
Navigator.of(navigatorKey.currentContext!).pop();
showToast(localization.assignedGroup);
store.dispatch(RefreshData());
}).catchError((error) {
showErrorDialog(message: error);
setState(() => _isLoading = false);
});
},
child: Text(
localization.submit.toUpperCase(),
),
),
],
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
widget.clients.length == 1
? localization.lookup(EntityType.client.snakeCase)
: localization.lookup(EntityType.client.plural) +
' (${widget.clients.length})',
style: Theme.of(context).textTheme.bodySmall,
),
SizedBox(height: 8),
...widget.clients
.map((entity) => Text(entity.listDisplayName))
.toList(),
if (_isLoading) ...[
SizedBox(height: 32),
LinearProgressIndicator()
] else ...[
SizedBox(height: 16),
DynamicSelector(
entityType: EntityType.group,
entityIds: memoizedGroupList(state.groupState.map),
entityId: _groupId,
onChanged: (groupId) {
setState(() {
_groupId = groupId;
});
}),
],
],
),
),
);
}
}

class _MergClientPicker extends StatefulWidget {
const _MergClientPicker({
Key? key,
Expand Down
75 changes: 20 additions & 55 deletions lib/ui/app/portal_links.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,17 @@ import 'package:invoiceninja_flutter/ui/app/icon_text.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:url_launcher/url_launcher.dart';

enum PortalLinkStyle {
buttons,
dropdown,
}

class PortalLinks extends StatelessWidget {
const PortalLinks({
Key? key,
required this.viewLink,
required this.copyLink,
required this.client,
this.style,
}) : super(key: key);

final String viewLink;
final String copyLink;
final ClientEntity? client;
final PortalLinkStyle? style;

@override
Widget build(BuildContext context) {
Expand All @@ -46,53 +39,25 @@ class PortalLinks extends StatelessWidget {
showToast(localization!.copiedToClipboard.replaceFirst(':value ', ''));
};

if (style == PortalLinkStyle.dropdown) {
return PopupMenuButton<String>(
itemBuilder: (BuildContext context) => [
PopupMenuItem(
child: IconText(
text: localization!.viewPortal, icon: Icons.open_in_new),
value: localization.viewPortal,
),
PopupMenuItem(
child: IconText(text: localization.copyLink, icon: Icons.copy),
value: localization.copyLink,
),
],
onSelected: (value) {
if (value == localization!.viewPortal) {
viewLinkPressed();
} else {
copyLinkPressed();
}
},
);
} else {
return Row(
children: [
Expanded(
child: OutlinedButton(
onPressed: viewLinkPressed,
child: Text(
localization!.viewPortal,
maxLines: 2,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
)),
),
SizedBox(width: 8),
Expanded(
child: OutlinedButton(
onPressed: copyLinkPressed,
child: Text(
localization.copyLink,
maxLines: 2,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
)),
),
],
);
}
return PopupMenuButton<String>(
itemBuilder: (BuildContext context) => [
PopupMenuItem(
child:
IconText(text: localization!.viewPortal, icon: Icons.open_in_new),
value: localization.viewPortal,
),
PopupMenuItem(
child: IconText(text: localization.copyLink, icon: Icons.copy),
value: localization.copyLink,
),
],
onSelected: (value) {
if (value == localization!.viewPortal) {
viewLinkPressed();
} else {
copyLinkPressed();
}
},
);
}
}
22 changes: 5 additions & 17 deletions lib/ui/client/view/client_view_fullwidth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -387,26 +387,14 @@ class _ClientViewFullwidthState extends State<ClientViewFullwidth>
CustomFieldType.contact4,
contact.customValue4)),
SizedBox(height: 8),
if (!hasMultipleContacts) ...[
PortalLinks(
viewLink: contact.silentLink,
copyLink: contact.link,
client: client,
style: PortalLinkStyle.buttons,
),
SizedBox(height: 16),
] else
SizedBox(height: 8),
],
),
),
if (hasMultipleContacts)
PortalLinks(
client: client,
viewLink: contact.silentLink,
copyLink: contact.link,
style: PortalLinkStyle.dropdown,
)
PortalLinks(
client: client,
viewLink: contact.silentLink,
copyLink: contact.link,
)
],
);
}).toList(),
Expand Down
23 changes: 6 additions & 17 deletions lib/ui/vendor/view/vendor_view_fullwidth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ class _VendorViewFullwidthState extends State<VendorViewFullwidth>
SizedBox(height: 8),
...vendor.contacts.map((contact) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
Expand Down Expand Up @@ -294,26 +295,14 @@ class _VendorViewFullwidthState extends State<VendorViewFullwidth>
CustomFieldType.vendorContact4,
contact.customValue4)),
SizedBox(height: 8),
if (!hasMultipleContacts) ...[
PortalLinks(
viewLink: contact.silentLink,
copyLink: contact.link,
client: null,
style: PortalLinkStyle.buttons,
),
SizedBox(height: 16),
] else
SizedBox(height: 8),
],
),
),
if (hasMultipleContacts)
PortalLinks(
client: null,
viewLink: contact.silentLink,
copyLink: contact.link,
style: PortalLinkStyle.dropdown,
)
PortalLinks(
client: null,
viewLink: contact.silentLink,
copyLink: contact.link,
)
],
);
}).toList()
Expand Down
10 changes: 10 additions & 0 deletions lib/utils/i18n.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ mixin LocalizationsProvider on LocaleCodeAware {
static final Map<String, Map<String, String>> _localizedValues = {
'en': {
// STARTER: lang key - do not remove comment
'assigned_group': 'Successfully assigned group',
'assign_group': 'Assign Group',
'merge_to_pdf': 'Merge to PDF',
'emails': 'Emails',
'latest_requires_php_version':
Expand Down Expand Up @@ -117525,6 +117527,14 @@ mixin LocalizationsProvider on LocaleCodeAware {
_localizedValues[localeCode]!['merge_to_pdf'] ??
_localizedValues['en']!['merge_to_pdf']!;

String get assignGroup =>
_localizedValues[localeCode]!['assign_group'] ??
_localizedValues['en']!['assign_group']!;

String get assignedGroup =>
_localizedValues[localeCode]!['assigned_group'] ??
_localizedValues['en']!['assigned_group']!;

// STARTER: lang field - do not remove comment

String lookup(String? key, {String? overrideLocaleCode}) {
Expand Down
2 changes: 2 additions & 0 deletions lib/utils/icons.dart
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ IconData? getEntityActionIcon(EntityAction? entityAction) {
return MdiIcons.squareEditOutline;
case EntityAction.addComment:
return MdiIcons.comment;
case EntityAction.assignGroup:
return MdiIcons.accountMultiple;
default:
return null;
}
Expand Down

0 comments on commit 444c7c5

Please sign in to comment.