Task statuses
This commit is contained in:
parent
4f73e10874
commit
6fecfca836
|
|
@ -172,8 +172,8 @@ abstract class TaskEntity extends Object
|
||||||
createdAt: 0,
|
createdAt: 0,
|
||||||
createdUserId: '',
|
createdUserId: '',
|
||||||
vendorId: '',
|
vendorId: '',
|
||||||
taskStatusId: '',
|
statusId: '',
|
||||||
taskStatusSortOrder: 0,
|
statusSortOrder: 0,
|
||||||
documents: BuiltList<DocumentEntity>(),
|
documents: BuiltList<DocumentEntity>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -389,13 +389,11 @@ abstract class TaskEntity extends Object
|
||||||
@BuiltValueField(wireName: 'custom_value4')
|
@BuiltValueField(wireName: 'custom_value4')
|
||||||
String get customValue4;
|
String get customValue4;
|
||||||
|
|
||||||
@nullable
|
@BuiltValueField(wireName: 'status_id')
|
||||||
@BuiltValueField(wireName: 'task_status_id')
|
String get statusId;
|
||||||
String get taskStatusId;
|
|
||||||
|
|
||||||
@nullable
|
@BuiltValueField(wireName: 'status_sort_order')
|
||||||
@BuiltValueField(wireName: 'task_status_sort_order')
|
int get statusSortOrder;
|
||||||
int get taskStatusSortOrder;
|
|
||||||
|
|
||||||
@nullable
|
@nullable
|
||||||
@BuiltValueField(wireName: 'vendor_id')
|
@BuiltValueField(wireName: 'vendor_id')
|
||||||
|
|
|
||||||
|
|
@ -180,6 +180,12 @@ class _$TaskEntitySerializer implements StructuredSerializer<TaskEntity> {
|
||||||
'custom_value2',
|
'custom_value2',
|
||||||
serializers.serialize(object.customValue2,
|
serializers.serialize(object.customValue2,
|
||||||
specifiedType: const FullType(String)),
|
specifiedType: const FullType(String)),
|
||||||
|
'status_id',
|
||||||
|
serializers.serialize(object.statusId,
|
||||||
|
specifiedType: const FullType(String)),
|
||||||
|
'status_sort_order',
|
||||||
|
serializers.serialize(object.statusSortOrder,
|
||||||
|
specifiedType: const FullType(int)),
|
||||||
'documents',
|
'documents',
|
||||||
serializers.serialize(object.documents,
|
serializers.serialize(object.documents,
|
||||||
specifiedType: const FullType(
|
specifiedType: const FullType(
|
||||||
|
|
@ -226,18 +232,6 @@ class _$TaskEntitySerializer implements StructuredSerializer<TaskEntity> {
|
||||||
..add(serializers.serialize(object.customValue4,
|
..add(serializers.serialize(object.customValue4,
|
||||||
specifiedType: const FullType(String)));
|
specifiedType: const FullType(String)));
|
||||||
}
|
}
|
||||||
if (object.taskStatusId != null) {
|
|
||||||
result
|
|
||||||
..add('task_status_id')
|
|
||||||
..add(serializers.serialize(object.taskStatusId,
|
|
||||||
specifiedType: const FullType(String)));
|
|
||||||
}
|
|
||||||
if (object.taskStatusSortOrder != null) {
|
|
||||||
result
|
|
||||||
..add('task_status_sort_order')
|
|
||||||
..add(serializers.serialize(object.taskStatusSortOrder,
|
|
||||||
specifiedType: const FullType(int)));
|
|
||||||
}
|
|
||||||
if (object.vendorId != null) {
|
if (object.vendorId != null) {
|
||||||
result
|
result
|
||||||
..add('vendor_id')
|
..add('vendor_id')
|
||||||
|
|
@ -330,12 +324,12 @@ class _$TaskEntitySerializer implements StructuredSerializer<TaskEntity> {
|
||||||
result.customValue4 = serializers.deserialize(value,
|
result.customValue4 = serializers.deserialize(value,
|
||||||
specifiedType: const FullType(String)) as String;
|
specifiedType: const FullType(String)) as String;
|
||||||
break;
|
break;
|
||||||
case 'task_status_id':
|
case 'status_id':
|
||||||
result.taskStatusId = serializers.deserialize(value,
|
result.statusId = serializers.deserialize(value,
|
||||||
specifiedType: const FullType(String)) as String;
|
specifiedType: const FullType(String)) as String;
|
||||||
break;
|
break;
|
||||||
case 'task_status_sort_order':
|
case 'status_sort_order':
|
||||||
result.taskStatusSortOrder = serializers.deserialize(value,
|
result.statusSortOrder = serializers.deserialize(value,
|
||||||
specifiedType: const FullType(int)) as int;
|
specifiedType: const FullType(int)) as int;
|
||||||
break;
|
break;
|
||||||
case 'vendor_id':
|
case 'vendor_id':
|
||||||
|
|
@ -690,9 +684,9 @@ class _$TaskEntity extends TaskEntity {
|
||||||
@override
|
@override
|
||||||
final String customValue4;
|
final String customValue4;
|
||||||
@override
|
@override
|
||||||
final String taskStatusId;
|
final String statusId;
|
||||||
@override
|
@override
|
||||||
final int taskStatusSortOrder;
|
final int statusSortOrder;
|
||||||
@override
|
@override
|
||||||
final String vendorId;
|
final String vendorId;
|
||||||
@override
|
@override
|
||||||
|
|
@ -730,8 +724,8 @@ class _$TaskEntity extends TaskEntity {
|
||||||
this.customValue2,
|
this.customValue2,
|
||||||
this.customValue3,
|
this.customValue3,
|
||||||
this.customValue4,
|
this.customValue4,
|
||||||
this.taskStatusId,
|
this.statusId,
|
||||||
this.taskStatusSortOrder,
|
this.statusSortOrder,
|
||||||
this.vendorId,
|
this.vendorId,
|
||||||
this.documents,
|
this.documents,
|
||||||
this.isChanged,
|
this.isChanged,
|
||||||
|
|
@ -764,6 +758,12 @@ class _$TaskEntity extends TaskEntity {
|
||||||
if (customValue2 == null) {
|
if (customValue2 == null) {
|
||||||
throw new BuiltValueNullFieldError('TaskEntity', 'customValue2');
|
throw new BuiltValueNullFieldError('TaskEntity', 'customValue2');
|
||||||
}
|
}
|
||||||
|
if (statusId == null) {
|
||||||
|
throw new BuiltValueNullFieldError('TaskEntity', 'statusId');
|
||||||
|
}
|
||||||
|
if (statusSortOrder == null) {
|
||||||
|
throw new BuiltValueNullFieldError('TaskEntity', 'statusSortOrder');
|
||||||
|
}
|
||||||
if (documents == null) {
|
if (documents == null) {
|
||||||
throw new BuiltValueNullFieldError('TaskEntity', 'documents');
|
throw new BuiltValueNullFieldError('TaskEntity', 'documents');
|
||||||
}
|
}
|
||||||
|
|
@ -804,8 +804,8 @@ class _$TaskEntity extends TaskEntity {
|
||||||
customValue2 == other.customValue2 &&
|
customValue2 == other.customValue2 &&
|
||||||
customValue3 == other.customValue3 &&
|
customValue3 == other.customValue3 &&
|
||||||
customValue4 == other.customValue4 &&
|
customValue4 == other.customValue4 &&
|
||||||
taskStatusId == other.taskStatusId &&
|
statusId == other.statusId &&
|
||||||
taskStatusSortOrder == other.taskStatusSortOrder &&
|
statusSortOrder == other.statusSortOrder &&
|
||||||
vendorId == other.vendorId &&
|
vendorId == other.vendorId &&
|
||||||
documents == other.documents &&
|
documents == other.documents &&
|
||||||
isChanged == other.isChanged &&
|
isChanged == other.isChanged &&
|
||||||
|
|
@ -847,8 +847,8 @@ class _$TaskEntity extends TaskEntity {
|
||||||
customValue2.hashCode),
|
customValue2.hashCode),
|
||||||
customValue3.hashCode),
|
customValue3.hashCode),
|
||||||
customValue4.hashCode),
|
customValue4.hashCode),
|
||||||
taskStatusId.hashCode),
|
statusId.hashCode),
|
||||||
taskStatusSortOrder.hashCode),
|
statusSortOrder.hashCode),
|
||||||
vendorId.hashCode),
|
vendorId.hashCode),
|
||||||
documents.hashCode),
|
documents.hashCode),
|
||||||
isChanged.hashCode),
|
isChanged.hashCode),
|
||||||
|
|
@ -876,8 +876,8 @@ class _$TaskEntity extends TaskEntity {
|
||||||
..add('customValue2', customValue2)
|
..add('customValue2', customValue2)
|
||||||
..add('customValue3', customValue3)
|
..add('customValue3', customValue3)
|
||||||
..add('customValue4', customValue4)
|
..add('customValue4', customValue4)
|
||||||
..add('taskStatusId', taskStatusId)
|
..add('statusId', statusId)
|
||||||
..add('taskStatusSortOrder', taskStatusSortOrder)
|
..add('statusSortOrder', statusSortOrder)
|
||||||
..add('vendorId', vendorId)
|
..add('vendorId', vendorId)
|
||||||
..add('documents', documents)
|
..add('documents', documents)
|
||||||
..add('isChanged', isChanged)
|
..add('isChanged', isChanged)
|
||||||
|
|
@ -943,14 +943,14 @@ class TaskEntityBuilder implements Builder<TaskEntity, TaskEntityBuilder> {
|
||||||
String get customValue4 => _$this._customValue4;
|
String get customValue4 => _$this._customValue4;
|
||||||
set customValue4(String customValue4) => _$this._customValue4 = customValue4;
|
set customValue4(String customValue4) => _$this._customValue4 = customValue4;
|
||||||
|
|
||||||
String _taskStatusId;
|
String _statusId;
|
||||||
String get taskStatusId => _$this._taskStatusId;
|
String get statusId => _$this._statusId;
|
||||||
set taskStatusId(String taskStatusId) => _$this._taskStatusId = taskStatusId;
|
set statusId(String statusId) => _$this._statusId = statusId;
|
||||||
|
|
||||||
int _taskStatusSortOrder;
|
int _statusSortOrder;
|
||||||
int get taskStatusSortOrder => _$this._taskStatusSortOrder;
|
int get statusSortOrder => _$this._statusSortOrder;
|
||||||
set taskStatusSortOrder(int taskStatusSortOrder) =>
|
set statusSortOrder(int statusSortOrder) =>
|
||||||
_$this._taskStatusSortOrder = taskStatusSortOrder;
|
_$this._statusSortOrder = statusSortOrder;
|
||||||
|
|
||||||
String _vendorId;
|
String _vendorId;
|
||||||
String get vendorId => _$this._vendorId;
|
String get vendorId => _$this._vendorId;
|
||||||
|
|
@ -1012,8 +1012,8 @@ class TaskEntityBuilder implements Builder<TaskEntity, TaskEntityBuilder> {
|
||||||
_customValue2 = _$v.customValue2;
|
_customValue2 = _$v.customValue2;
|
||||||
_customValue3 = _$v.customValue3;
|
_customValue3 = _$v.customValue3;
|
||||||
_customValue4 = _$v.customValue4;
|
_customValue4 = _$v.customValue4;
|
||||||
_taskStatusId = _$v.taskStatusId;
|
_statusId = _$v.statusId;
|
||||||
_taskStatusSortOrder = _$v.taskStatusSortOrder;
|
_statusSortOrder = _$v.statusSortOrder;
|
||||||
_vendorId = _$v.vendorId;
|
_vendorId = _$v.vendorId;
|
||||||
_documents = _$v.documents?.toBuilder();
|
_documents = _$v.documents?.toBuilder();
|
||||||
_isChanged = _$v.isChanged;
|
_isChanged = _$v.isChanged;
|
||||||
|
|
@ -1060,8 +1060,8 @@ class TaskEntityBuilder implements Builder<TaskEntity, TaskEntityBuilder> {
|
||||||
customValue2: customValue2,
|
customValue2: customValue2,
|
||||||
customValue3: customValue3,
|
customValue3: customValue3,
|
||||||
customValue4: customValue4,
|
customValue4: customValue4,
|
||||||
taskStatusId: taskStatusId,
|
statusId: statusId,
|
||||||
taskStatusSortOrder: taskStatusSortOrder,
|
statusSortOrder: statusSortOrder,
|
||||||
vendorId: vendorId,
|
vendorId: vendorId,
|
||||||
documents: documents.build(),
|
documents: documents.build(),
|
||||||
isChanged: isChanged,
|
isChanged: isChanged,
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,48 @@ List<String> filteredTaskStatusesSelector(
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var memoizedCalculateTaskStatusAmount = memo2((String taskStatusId,
|
||||||
|
BuiltMap<String, TaskEntity> taskMap) =>
|
||||||
|
calculateTaskStatusAmount(taskStatusId: taskStatusId, taskMap: taskMap));
|
||||||
|
|
||||||
|
int calculateTaskStatusAmount({
|
||||||
|
String taskStatusId,
|
||||||
|
BuiltMap<String, TaskEntity> taskMap,
|
||||||
|
}) {
|
||||||
|
int total = 0;
|
||||||
|
|
||||||
|
taskMap.forEach((taskId, task) {
|
||||||
|
if (task.statusId == taskStatusId) {
|
||||||
|
total += task.calculateDuration.inSeconds;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
var memoizedTaskStatsForTaskStatus = memo2(
|
||||||
|
(String companyGatewayId, BuiltMap<String, TaskEntity> taskMap) =>
|
||||||
|
taskStatsForTaskStatus(companyGatewayId, taskMap));
|
||||||
|
|
||||||
|
EntityStats taskStatsForTaskStatus(
|
||||||
|
String statusId,
|
||||||
|
BuiltMap<String, TaskEntity> taskMap,
|
||||||
|
) {
|
||||||
|
int countActive = 0;
|
||||||
|
int countArchived = 0;
|
||||||
|
taskMap.forEach((taskId, task) {
|
||||||
|
if (task.statusId == statusId) {
|
||||||
|
if (task.isActive) {
|
||||||
|
countActive++;
|
||||||
|
} else if (task.isArchived) {
|
||||||
|
countArchived++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return EntityStats(countActive: countActive, countArchived: countArchived);
|
||||||
|
}
|
||||||
|
|
||||||
bool hasTaskStatusChanges(TaskStatusEntity taskStatus,
|
bool hasTaskStatusChanges(TaskStatusEntity taskStatus,
|
||||||
BuiltMap<String, TaskStatusEntity> taskStatusMap) =>
|
BuiltMap<String, TaskStatusEntity> taskStatusMap) =>
|
||||||
taskStatus.isNew
|
taskStatus.isNew
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,6 @@ class _TaskEditDetailsState extends State<TaskEditDetails> {
|
||||||
final viewModel = widget.viewModel;
|
final viewModel = widget.viewModel;
|
||||||
final localization = AppLocalization.of(context);
|
final localization = AppLocalization.of(context);
|
||||||
final task = viewModel.task;
|
final task = viewModel.task;
|
||||||
final company = viewModel.company;
|
|
||||||
final state = viewModel.state;
|
final state = viewModel.state;
|
||||||
|
|
||||||
return ListView(
|
return ListView(
|
||||||
|
|
@ -137,22 +136,20 @@ class _TaskEditDetailsState extends State<TaskEditDetails> {
|
||||||
.onChanged(task.rebuild((b) => b..assignedUserId = userId)),
|
.onChanged(task.rebuild((b) => b..assignedUserId = userId)),
|
||||||
),
|
),
|
||||||
// TODO Remove isNotEmpty check in v2
|
// TODO Remove isNotEmpty check in v2
|
||||||
company.taskStatusMap.isNotEmpty
|
EntityDropdown(
|
||||||
? EntityDropdown(
|
key: ValueKey('__task_status_${task.statusId}__'),
|
||||||
key: ValueKey('__task_status_${task.taskStatusId}__'),
|
|
||||||
allowClearing: false,
|
allowClearing: false,
|
||||||
entityType: EntityType.taskStatus,
|
entityType: EntityType.taskStatus,
|
||||||
labelText: localization.status,
|
labelText: localization.status,
|
||||||
entityId: task.taskStatusId,
|
entityId: task.statusId,
|
||||||
entityList: company.taskStatusMap.keys.toList(),
|
entityList: state.taskStatusState.list.toList(),
|
||||||
onSelected: (selected) {
|
onSelected: (selected) {
|
||||||
final taskStatus = selected as TaskStatusEntity;
|
final taskStatus = selected as TaskStatusEntity;
|
||||||
viewModel.onChanged(task.rebuild((b) => b
|
viewModel.onChanged(task.rebuild((b) => b
|
||||||
..taskStatusId = taskStatus?.id
|
..statusId = taskStatus?.id
|
||||||
..taskStatusSortOrder = 9999));
|
..statusSortOrder = 9999));
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
: SizedBox(),
|
|
||||||
DecoratedFormField(
|
DecoratedFormField(
|
||||||
maxLines: 4,
|
maxLines: 4,
|
||||||
controller: _descriptionController,
|
controller: _descriptionController,
|
||||||
|
|
|
||||||
|
|
@ -57,11 +57,9 @@ class _TaskOverviewState extends State<TaskOverview> {
|
||||||
|
|
||||||
final Map<String, String> fields = {};
|
final Map<String, String> fields = {};
|
||||||
|
|
||||||
// TODO Remove isNotEmpty check in v2
|
if ((task.statusId ?? '').isNotEmpty) {
|
||||||
if (company.taskStatusMap.isNotEmpty &&
|
|
||||||
(task.taskStatusId ?? '').isNotEmpty) {
|
|
||||||
fields[localization.status] =
|
fields[localization.status] =
|
||||||
company.taskStatusMap[task.taskStatusId]?.name ?? '';
|
company.taskStatusMap[task.statusId]?.name ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task.customValue1.isNotEmpty) {
|
if (task.customValue1.isNotEmpty) {
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ class TaskStatusScreen extends StatelessWidget {
|
||||||
final userCompany = state.userCompany;
|
final userCompany = state.userCompany;
|
||||||
final localization = AppLocalization.of(context);
|
final localization = AppLocalization.of(context);
|
||||||
final listUIState = state.uiState.taskStatusUIState.listUIState;
|
final listUIState = state.uiState.taskStatusUIState.listUIState;
|
||||||
final isInMultiselect = listUIState.isInMultiselect();
|
|
||||||
|
|
||||||
return ListScaffold(
|
return ListScaffold(
|
||||||
entityType: EntityType.taskStatus,
|
entityType: EntityType.taskStatus,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,14 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:invoiceninja_flutter/data/models/models.dart';
|
||||||
|
import 'package:invoiceninja_flutter/redux/task_status/task_status_selectors.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/entities/entity_list_tile.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/entity_header.dart';
|
||||||
|
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/task_status/view/task_status_view_vm.dart';
|
import 'package:invoiceninja_flutter/ui/task_status/view/task_status_view_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/view_scaffold.dart';
|
import 'package:invoiceninja_flutter/ui/app/view_scaffold.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
|
|
||||||
class TaskStatusView extends StatefulWidget {
|
class TaskStatusView extends StatefulWidget {
|
||||||
const TaskStatusView({
|
const TaskStatusView({
|
||||||
|
|
@ -21,14 +28,33 @@ class _TaskStatusViewState extends State<TaskStatusView> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final viewModel = widget.viewModel;
|
final viewModel = widget.viewModel;
|
||||||
|
final state = viewModel.state;
|
||||||
final taskStatus = viewModel.taskStatus;
|
final taskStatus = viewModel.taskStatus;
|
||||||
|
final localization = AppLocalization.of(context);
|
||||||
|
final amount = memoizedCalculateTaskStatusAmount(
|
||||||
|
taskStatus.id, viewModel.state.taskState.map);
|
||||||
|
|
||||||
return ViewScaffold(
|
return ViewScaffold(
|
||||||
isFilter: widget.isFilter,
|
isFilter: widget.isFilter,
|
||||||
entity: taskStatus,
|
entity: taskStatus,
|
||||||
onBackPressed: () => viewModel.onBackPressed(),
|
onBackPressed: () => viewModel.onBackPressed(),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
children: <Widget>[],
|
children: <Widget>[
|
||||||
|
EntityHeader(
|
||||||
|
entity: taskStatus,
|
||||||
|
label: localization.total,
|
||||||
|
value: formatDuration(Duration(seconds: amount))),
|
||||||
|
ListDivider(),
|
||||||
|
EntitiesListTile(
|
||||||
|
entity: taskStatus,
|
||||||
|
isFilter: widget.isFilter,
|
||||||
|
entityType: EntityType.task,
|
||||||
|
title: localization.tasks,
|
||||||
|
subtitle: memoizedTaskStatsForTaskStatus(
|
||||||
|
taskStatus.id, state.taskState.map)
|
||||||
|
.present(localization.active, localization.archived),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue