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