This commit is contained in:
Hillel Coren 2018-12-13 22:44:16 +02:00
parent 753e0e8590
commit 4763b8cba7
12 changed files with 106 additions and 178 deletions

View File

@ -367,7 +367,7 @@ abstract class ClientEntity extends Object
actions.add(null);
}
return actions..addAll(getEntityBaseActions(user: user));
return actions..addAll(getBaseActions(user: user));
}
@override

View File

@ -136,7 +136,7 @@ abstract class BaseEntity implements SelectableEntity {
bool get isArchived => archivedAt != null && !isDeleted;
List<EntityAction> getEntityBaseActions({UserEntity user}) {
List<EntityAction> getBaseActions({UserEntity user}) {
final actions = <EntityAction>[];
if (user.canEditEntity(this) && (isArchived || isDeleted)) {

View File

@ -420,7 +420,7 @@ abstract class InvoiceEntity extends Object
actions.add(null);
}
return actions..addAll(getEntityBaseActions(user: user));
return actions..addAll(getBaseActions(user: user));
}
InvoiceEntity applyTax(TaxRateEntity taxRate) {

View File

@ -186,7 +186,7 @@ abstract class PaymentEntity extends Object
actions.add(null);
}
return actions..addAll(getEntityBaseActions(user: user));
return actions..addAll(getBaseActions(user: user));
}
@override

View File

@ -205,7 +205,7 @@ abstract class ProductEntity extends Object
actions.add(null);
}
return actions..addAll(getEntityBaseActions(user: user));
return actions..addAll(getBaseActions(user: user));
}
static Serializer<ProductEntity> get serializer => _$productEntitySerializer;

View File

@ -2,6 +2,7 @@ import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart';
part 'project_model.g.dart';
@ -101,6 +102,12 @@ abstract class ProjectEntity extends Object
@BuiltValueField(wireName: 'custom_value2')
String get customValue2;
List<EntityAction> getEntityActions({UserEntity user, ClientEntity client}) {
final actions = <EntityAction>[];
return actions..addAll(getBaseActions(user: user));
}
int compareTo(ProjectEntity project, String sortField, bool sortAscending) {
int response = 0;
final ProjectEntity projectA = sortAscending ? this : project;

View File

@ -132,7 +132,7 @@ class _ProjectEditState extends State<ProjectEdit> {
entityList: memoizedDropdownClientList(
state.clientState.map, state.clientState.list),
validator: (String val) => val.trim().isEmpty
? AppLocalization.of(context).pleaseSelectAClient
? localization.pleaseSelectAClient
: null,
onSelected: (clientId) {
viewModel.onChanged(
@ -146,7 +146,7 @@ class _ProjectEditState extends State<ProjectEdit> {
autocorrect: false,
controller: _nameController,
validator: (String val) => val.trim().isEmpty
? AppLocalization.of(context).pleaseEnterAName
? localization.pleaseEnterAName
: null,
decoration: InputDecoration(
labelText: localization.name,

View File

@ -9,7 +9,6 @@ import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
import 'package:invoiceninja_flutter/ui/project/project_screen.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/project/project_actions.dart';

View File

@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
import 'package:invoiceninja_flutter/ui/project/project_list_item.dart';
import 'package:invoiceninja_flutter/ui/project/project_list_vm.dart';
import 'package:invoiceninja_flutter/utils/icons.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
class ProjectList extends StatelessWidget {
@ -34,48 +35,34 @@ class ProjectList extends StatelessWidget {
return _buildListView(context);
}
void _showMenu(BuildContext context, ProjectEntity project) async {
if (project == null) {
return;
}
void _showMenu(
BuildContext context, ProjectEntity project) async {
if (project == null) {
return;
}
final user = viewModel.user;
final message = await showDialog<String>(
context: context,
builder: (BuildContext context) => SimpleDialog(children: <Widget>[
user.canCreate(EntityType.project)
? ListTile(
leading: Icon(Icons.control_point_duplicate),
title: Text(AppLocalization.of(context).clone),
onTap: () => viewModel.onEntityAction(
context, project, EntityAction.clone),
)
: Container(),
Divider(),
user.canEditEntity(project) && !project.isActive
? ListTile(
leading: Icon(Icons.restore),
title: Text(AppLocalization.of(context).restore),
onTap: () => viewModel.onEntityAction(
context, project, EntityAction.restore),
)
: Container(),
user.canEditEntity(project) && project.isActive
? ListTile(
leading: Icon(Icons.archive),
title: Text(AppLocalization.of(context).archive),
onTap: () => viewModel.onEntityAction(
context, project, EntityAction.archive),
)
: Container(),
user.canEditEntity(project) && !project.isDeleted
? ListTile(
leading: Icon(Icons.delete),
title: Text(AppLocalization.of(context).delete),
onTap: () => viewModel.onEntityAction(
context, project, EntityAction.delete),
)
: Container(),
]));
builder: (BuildContext dialogContext) => SimpleDialog(
children: project
.getEntityActions(user: user)
.map((entityAction) {
if (entityAction == null) {
return Divider();
} else {
return ListTile(
leading: Icon(getEntityActionIcon(entityAction)),
title: Text(AppLocalization.of(context)
.lookup(entityAction.toString())),
onTap: () {
Navigator.of(dialogContext).pop();
viewModel.onEntityAction(context, project, entityAction);
},
);
}
}).toList()));
if (message != null) {
Scaffold.of(context).showSnackBar(SnackBar(
content: SnackBarRow(

View File

@ -38,7 +38,6 @@ class ProjectListVM {
@required this.isLoading,
@required this.isLoaded,
@required this.onProjectTap,
@required this.onDismissed,
@required this.onRefreshed,
@required this.onEntityAction,
});
@ -57,69 +56,45 @@ class ProjectListVM {
final state = store.state;
return ProjectListVM(
user: state.user,
projectList: memoizedFilteredProjectList(state.projectState.map,
state.projectState.list, state.projectListState),
projectMap: state.projectState.map,
isLoading: state.isLoading,
isLoaded: state.projectState.isLoaded,
filter: state.projectUIState.listUIState.filter,
onProjectTap: (context, project) {
store.dispatch(EditProject(project: project, context: context));
},
onEntityAction: (context, project, action) {
switch (action) {
case EntityAction.clone:
Navigator.of(context).pop();
store.dispatch(
EditProject(context: context, project: project.clone));
break;
case EntityAction.restore:
store.dispatch(RestoreProjectRequest(
popCompleter(
context, AppLocalization.of(context).restoredProject),
project.id));
break;
case EntityAction.archive:
store.dispatch(ArchiveProjectRequest(
popCompleter(
context, AppLocalization.of(context).archivedProject),
project.id));
break;
case EntityAction.delete:
store.dispatch(DeleteProjectRequest(
popCompleter(
context, AppLocalization.of(context).deletedProject),
project.id));
break;
}
},
onRefreshed: (context) => _handleRefresh(context),
onDismissed: (BuildContext context, ProjectEntity project,
DismissDirection direction) {
final localization = AppLocalization.of(context);
if (direction == DismissDirection.endToStart) {
if (project.isDeleted || project.isArchived) {
store.dispatch(RestoreProjectRequest(
snackBarCompleter(context, localization.restoredProject),
project.id));
} else {
store.dispatch(ArchiveProjectRequest(
snackBarCompleter(context, localization.archivedProject),
project.id));
}
} else if (direction == DismissDirection.startToEnd) {
if (project.isDeleted) {
store.dispatch(RestoreProjectRequest(
snackBarCompleter(context, localization.restoredProject),
project.id));
} else {
store.dispatch(DeleteProjectRequest(
snackBarCompleter(context, localization.deletedProject),
project.id));
}
}
});
user: state.user,
projectList: memoizedFilteredProjectList(state.projectState.map,
state.projectState.list, state.projectListState),
projectMap: state.projectState.map,
isLoading: state.isLoading,
isLoaded: state.projectState.isLoaded,
filter: state.projectUIState.listUIState.filter,
onProjectTap: (context, project) {
store.dispatch(EditProject(project: project, context: context));
},
onEntityAction: (context, project, action) {
switch (action) {
case EntityAction.clone:
Navigator.of(context).pop();
store.dispatch(
EditProject(context: context, project: project.clone));
break;
case EntityAction.restore:
store.dispatch(RestoreProjectRequest(
snackBarCompleter(
context, AppLocalization.of(context).restoredProject),
project.id));
break;
case EntityAction.archive:
store.dispatch(ArchiveProjectRequest(
snackBarCompleter(
context, AppLocalization.of(context).archivedProject),
project.id));
break;
case EntityAction.delete:
store.dispatch(DeleteProjectRequest(
snackBarCompleter(
context, AppLocalization.of(context).deletedProject),
project.id));
break;
}
},
onRefreshed: (context) => _handleRefresh(context),
);
}
final UserEntity user;
@ -129,7 +104,6 @@ class ProjectListVM {
final bool isLoading;
final bool isLoaded;
final Function(BuildContext, ProjectEntity) onProjectTap;
final Function(BuildContext, ProjectEntity, DismissDirection) onDismissed;
final Function(BuildContext) onRefreshed;
final Function(BuildContext, ProjectEntity, EntityAction) onEntityAction;
}

View File

@ -5,6 +5,7 @@ import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
import 'package:invoiceninja_flutter/ui/app/snackbar_row.dart';
import 'package:invoiceninja_flutter/ui/stub/stub_list_item.dart';
import 'package:invoiceninja_flutter/ui/stub/stub_list_vm.dart';
import 'package:invoiceninja_flutter/utils/icons.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
class StubList extends StatelessWidget {
@ -34,48 +35,34 @@ class StubList extends StatelessWidget {
return _buildListView(context);
}
void _showMenu(BuildContext context, StubEntity stub) async {
if (stub == null) {
return;
}
void _showMenu(
BuildContext context, StubEntity stub) async {
if (stub == null) {
return;
}
final user = viewModel.user;
final message = await showDialog<String>(
context: context,
builder: (BuildContext context) => SimpleDialog(children: <Widget>[
user.canCreate(EntityType.stub)
? ListTile(
leading: Icon(Icons.control_point_duplicate),
title: Text(AppLocalization.of(context).clone),
onTap: () => viewModel.onEntityAction(
context, stub, EntityAction.clone),
)
: Container(),
Divider(),
user.canEditEntity(stub) && !stub.isActive
? ListTile(
leading: Icon(Icons.restore),
title: Text(AppLocalization.of(context).restore),
onTap: () => viewModel.onEntityAction(
context, stub, EntityAction.restore),
)
: Container(),
user.canEditEntity(stub) && stub.isActive
? ListTile(
leading: Icon(Icons.archive),
title: Text(AppLocalization.of(context).archive),
onTap: () => viewModel.onEntityAction(
context, stub, EntityAction.archive),
)
: Container(),
user.canEditEntity(stub) && !stub.isDeleted
? ListTile(
leading: Icon(Icons.delete),
title: Text(AppLocalization.of(context).delete),
onTap: () => viewModel.onEntityAction(
context, stub, EntityAction.delete),
)
: Container(),
]));
builder: (BuildContext dialogContext) => SimpleDialog(
children: stub
.getEntityActions(user: user)
.map((entityAction) {
if (entityAction == null) {
return Divider();
} else {
return ListTile(
leading: Icon(getEntityActionIcon(entityAction)),
title: Text(AppLocalization.of(context)
.lookup(entityAction.toString())),
onTap: () {
Navigator.of(dialogContext).pop();
viewModel.onEntityAction(context, stub, entityAction);
},
);
}
}).toList()));
if (message != null) {
Scaffold.of(context).showSnackBar(SnackBar(
content: SnackBarRow(

View File

@ -38,7 +38,6 @@ class StubListVM {
@required this.isLoading,
@required this.isLoaded,
@required this.onStubTap,
@required this.onDismissed,
@required this.onRefreshed,
@required this.onEntityAction,
});
@ -95,31 +94,7 @@ class StubListVM {
}
},
onRefreshed: (context) => _handleRefresh(context),
onDismissed: (BuildContext context, StubEntity stub,
DismissDirection direction) {
final localization = AppLocalization.of(context);
if (direction == DismissDirection.endToStart) {
if (stub.isDeleted || stub.isArchived) {
store.dispatch(RestoreStubRequest(
snackBarCompleter(context, localization.restoredStub),
stub.id));
} else {
store.dispatch(ArchiveStubRequest(
snackBarCompleter(context, localization.archivedStub),
stub.id));
}
} else if (direction == DismissDirection.startToEnd) {
if (stub.isDeleted) {
store.dispatch(RestoreStubRequest(
snackBarCompleter(context, localization.restoredStub),
stub.id));
} else {
store.dispatch(DeleteStubRequest(
snackBarCompleter(context, localization.deletedStub),
stub.id));
}
}
});
);
}
final UserEntity user;
@ -129,7 +104,6 @@ class StubListVM {
final bool isLoading;
final bool isLoaded;
final Function(BuildContext, StubEntity) onStubTap;
final Function(BuildContext, StubEntity, DismissDirection) onDismissed;
final Function(BuildContext) onRefreshed;
final Function(BuildContext, StubEntity, EntityAction) onEntityAction;
}