diff --git a/lib/ui/app/lists/activity_list_tile.dart b/lib/ui/app/lists/activity_list_tile.dart new file mode 100644 index 000000000..bacc1209a --- /dev/null +++ b/lib/ui/app/lists/activity_list_tile.dart @@ -0,0 +1,83 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_redux/flutter_redux.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:invoiceninja_flutter/data/models/entities.dart'; +import 'package:invoiceninja_flutter/redux/app/app_state.dart'; +import 'package:invoiceninja_flutter/redux/client/client_actions.dart'; +import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart'; +import 'package:invoiceninja_flutter/utils/formatting.dart'; +import 'package:invoiceninja_flutter/utils/localization.dart'; + +class ActivityListTile extends StatelessWidget { + const ActivityListTile({ + Key key, + @required this.activity, + }) : super(key: key); + + final ActivityEntity activity; + + IconData getIconData(EntityType entityType) { + switch (entityType) { + case EntityType.client: + return FontAwesomeIcons.users; + case EntityType.invoice: + return FontAwesomeIcons.filePdfO; + case EntityType.payment: + return FontAwesomeIcons.creditCard; + case EntityType.credit: + return FontAwesomeIcons.creditCard; + case EntityType.quote: + return FontAwesomeIcons.fileAltO; + case EntityType.vendor: + return FontAwesomeIcons.building; + case EntityType.expense: + return FontAwesomeIcons.fileImageO; + case EntityType.task: + return FontAwesomeIcons.clockO; + default: + return null; + } + } + + @override + Widget build(BuildContext context) { + final localization = AppLocalization.of(context); + final store = StoreProvider.of(context); + final state = store.state; + + String title = localization.lookup('activity_${activity.activityTypeId}'); + title = activity.getDescription( + title, + user: state.selectedCompany.userMap[activity.userId], + client: state.clientState.map[activity.clientId], + invoice: state.invoiceState.map[activity.invoiceId], + ); + + return ListTile( + leading: Icon(getIconData(activity.entityType)), + title: Text(title), + onTap: () { + switch (activity.entityType) { + case EntityType.client: + store.dispatch( + ViewClient(clientId: activity.clientId, context: context)); + break; + case EntityType.invoice: + store.dispatch( + ViewInvoice(invoiceId: activity.invoiceId, context: context)); + break; + } + }, + trailing: Icon(Icons.navigate_next), + subtitle: Row( + children: [ + Text(formatDate( + convertTimestampToSqlDate(activity.updatedAt), context, + showTime: true)), + SizedBox(width: 10.0), + (activity.isSystem ?? false) ? Icon(FontAwesomeIcons.server) : Container(), + ], + ), + ); + } +} diff --git a/lib/ui/client/view/client_view.dart b/lib/ui/client/view/client_view.dart index 6dde96826..0e580fbc2 100644 --- a/lib/ui/client/view/client_view.dart +++ b/lib/ui/client/view/client_view.dart @@ -53,7 +53,9 @@ class _ClientViewState extends State return true; }, child: Scaffold( - backgroundColor: Theme.of(context).backgroundColor, + backgroundColor: Theme + .of(context) + .backgroundColor, appBar: _CustomAppBar( viewModel: viewModel, controller: _controller, @@ -63,7 +65,9 @@ class _ClientViewState extends State controller: _controller, ), floatingActionButton: FloatingActionButton( - backgroundColor: Theme.of(context).primaryColorDark, + backgroundColor: Theme + .of(context) + .primaryColorDark, onPressed: () { showDialog( context: context, @@ -148,7 +152,9 @@ class _CustomTabBarViewState extends State { void _onTabChange() { final viewModel = widget.viewModel; - if (widget.controller.index == 2 && viewModel.client.activities.isEmpty) { + + if (widget.controller.index == 2 && viewModel.client.activities.isEmpty && + !viewModel.isLoading) { viewModel.onRefreshed(context); } } @@ -196,7 +202,7 @@ class _CustomAppBar extends StatelessWidget implements PreferredSizeWidget { return AppBar( title: - Text(client.displayName ?? ''), // Text(localizations.clientDetails), + Text(client.displayName ?? ''), // Text(localizations.clientDetails), bottom: TabBar( controller: controller, //isScrollable: true, @@ -215,16 +221,16 @@ class _CustomAppBar extends StatelessWidget implements PreferredSizeWidget { actions: client.isNew ? [] : [ - EditIconButton( - isVisible: !client.isDeleted, - onPressed: () => viewModel.onEditPressed(context), - ), - ActionMenuButton( - isSaving: viewModel.isSaving, - entity: client, - onSelected: viewModel.onActionSelected, - ) - ], + EditIconButton( + isVisible: !client.isDeleted, + onPressed: () => viewModel.onEditPressed(context), + ), + ActionMenuButton( + isSaving: viewModel.isSaving, + entity: client, + onSelected: viewModel.onActionSelected, + ) + ], ); } } diff --git a/lib/ui/client/view/client_view_activity.dart b/lib/ui/client/view/client_view_activity.dart index 1d4be1cac..94cba72c4 100644 --- a/lib/ui/client/view/client_view_activity.dart +++ b/lib/ui/client/view/client_view_activity.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:invoiceninja_flutter/data/models/client_model.dart'; +import 'package:invoiceninja_flutter/ui/app/lists/activity_list_tile.dart'; import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart'; class ClientViewActivity extends StatelessWidget { @@ -20,8 +21,7 @@ class ClientViewActivity extends StatelessWidget { itemCount: activities.length, itemBuilder: (BuildContext context, index) { final activity = activities[index]; - return Text(activity.key); - //return ActivityListTile(activity: activity); + return ActivityListTile(activity: activity); }, ); diff --git a/lib/ui/client/view/client_view_vm.dart b/lib/ui/client/view/client_view_vm.dart index d0a00ab64..63e0092bd 100644 --- a/lib/ui/client/view/client_view_vm.dart +++ b/lib/ui/client/view/client_view_vm.dart @@ -42,6 +42,7 @@ class ClientViewVM { final Function(BuildContext) onInvoicesPressed; final Function(BuildContext) onRefreshed; final bool isSaving; + final bool isLoading; final bool isDirty; ClientViewVM({ @@ -52,6 +53,7 @@ class ClientViewVM { @required this.onInvoicesPressed, @required this.onBackPressed, @required this.isSaving, + @required this.isLoading, @required this.isDirty, @required this.onRefreshed, }); @@ -73,6 +75,7 @@ class ClientViewVM { return ClientViewVM( isSaving: state.isSaving, + isLoading: state.isLoading, isDirty: client.isNew, client: client, company: state.selectedCompany, diff --git a/lib/ui/dashboard/dashboard_activity.dart b/lib/ui/dashboard/dashboard_activity.dart index d827582ec..c4621d479 100644 --- a/lib/ui/dashboard/dashboard_activity.dart +++ b/lib/ui/dashboard/dashboard_activity.dart @@ -1,15 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:flutter_redux/flutter_redux.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:invoiceninja_flutter/data/models/entities.dart'; -import 'package:invoiceninja_flutter/data/models/models.dart'; -import 'package:invoiceninja_flutter/redux/app/app_state.dart'; -import 'package:invoiceninja_flutter/redux/client/client_actions.dart'; -import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart'; +import 'package:invoiceninja_flutter/ui/app/lists/activity_list_tile.dart'; import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart'; import 'package:invoiceninja_flutter/ui/dashboard/dashboard_vm.dart'; -import 'package:invoiceninja_flutter/utils/formatting.dart'; -import 'package:invoiceninja_flutter/utils/localization.dart'; class DashboardActivity extends StatelessWidget { const DashboardActivity({ @@ -37,76 +29,3 @@ class DashboardActivity extends StatelessWidget { } } -class ActivityListTile extends StatelessWidget { - const ActivityListTile({ - Key key, - @required this.activity, - }) : super(key: key); - - final ActivityEntity activity; - - IconData getIconData(EntityType entityType) { - switch (entityType) { - case EntityType.client: - return FontAwesomeIcons.users; - case EntityType.invoice: - return FontAwesomeIcons.filePdfO; - case EntityType.payment: - return FontAwesomeIcons.creditCard; - case EntityType.credit: - return FontAwesomeIcons.creditCard; - case EntityType.quote: - return FontAwesomeIcons.fileAltO; - case EntityType.vendor: - return FontAwesomeIcons.building; - case EntityType.expense: - return FontAwesomeIcons.fileImageO; - case EntityType.task: - return FontAwesomeIcons.clockO; - default: - return null; - } - } - - @override - Widget build(BuildContext context) { - final localization = AppLocalization.of(context); - final store = StoreProvider.of(context); - final state = store.state; - - String title = localization.lookup('activity_${activity.activityTypeId}'); - title = activity.getDescription( - title, - user: state.selectedCompany.userMap[activity.userId], - client: state.clientState.map[activity.clientId], - invoice: state.invoiceState.map[activity.invoiceId], - ); - - return ListTile( - leading: Icon(getIconData(activity.entityType)), - title: Text(title), - onTap: () { - switch (activity.entityType) { - case EntityType.client: - store.dispatch( - ViewClient(clientId: activity.clientId, context: context)); - break; - case EntityType.invoice: - store.dispatch( - ViewInvoice(invoiceId: activity.invoiceId, context: context)); - break; - } - }, - trailing: Icon(Icons.navigate_next), - subtitle: Row( - children: [ - Text(formatDate( - convertTimestampToSqlDate(activity.updatedAt), context, - showTime: true)), - SizedBox(width: 10.0), - (activity.isSystem ?? false) ? Icon(FontAwesomeIcons.server) : Container(), - ], - ), - ); - } -} diff --git a/lib/utils/formatting.dart b/lib/utils/formatting.dart index bbd764fd8..81a3a5a0a 100644 --- a/lib/utils/formatting.dart +++ b/lib/utils/formatting.dart @@ -191,7 +191,6 @@ String formatDate(String value, BuildContext context, {bool showTime = false}) { ? company.datetimeFormatId : kDefaultDateTimeFormat; final formatter = DateFormat(dateTimeFormats[dateTimeFormatId].format); - print(DateTime.tryParse(value).timeZoneName); return formatter.format(DateTime.tryParse(value).toLocal()); } else { final dateFormats = state.staticState.dateFormatMap;