Task item details
This commit is contained in:
parent
cd826cd709
commit
b0886f5ccd
|
|
@ -85,13 +85,20 @@ class TaskFields {
|
|||
}
|
||||
|
||||
abstract class TaskTime implements Built<TaskTime, TaskTimeBuilder> {
|
||||
factory TaskTime({DateTime startDate, DateTime endDate}) {
|
||||
factory TaskTime({
|
||||
DateTime startDate,
|
||||
DateTime endDate,
|
||||
String description,
|
||||
bool isBillable,
|
||||
}) {
|
||||
return _$TaskTime._(
|
||||
startDate: startDate ??
|
||||
DateTime.fromMillisecondsSinceEpoch(
|
||||
(DateTime.now().millisecondsSinceEpoch / 1000).floor() * 1000,
|
||||
isUtc: true),
|
||||
endDate: endDate,
|
||||
description: description ?? '',
|
||||
isBillable: isBillable ?? true,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -107,6 +114,10 @@ abstract class TaskTime implements Built<TaskTime, TaskTimeBuilder> {
|
|||
@nullable
|
||||
DateTime get endDate;
|
||||
|
||||
String get description;
|
||||
|
||||
bool get isBillable;
|
||||
|
||||
Duration get duration => (endDate ?? DateTime.now()).difference(startDate);
|
||||
|
||||
List<dynamic> get asList {
|
||||
|
|
|
|||
|
|
@ -109,7 +109,14 @@ class _$TaskTimeSerializer implements StructuredSerializer<TaskTime> {
|
|||
@override
|
||||
Iterable<Object> serialize(Serializers serializers, TaskTime object,
|
||||
{FullType specifiedType = FullType.unspecified}) {
|
||||
final result = <Object>[];
|
||||
final result = <Object>[
|
||||
'description',
|
||||
serializers.serialize(object.description,
|
||||
specifiedType: const FullType(String)),
|
||||
'isBillable',
|
||||
serializers.serialize(object.isBillable,
|
||||
specifiedType: const FullType(bool)),
|
||||
];
|
||||
Object value;
|
||||
value = object.startDate;
|
||||
if (value != null) {
|
||||
|
|
@ -147,6 +154,14 @@ class _$TaskTimeSerializer implements StructuredSerializer<TaskTime> {
|
|||
result.endDate = serializers.deserialize(value,
|
||||
specifiedType: const FullType(DateTime)) as DateTime;
|
||||
break;
|
||||
case 'description':
|
||||
result.description = serializers.deserialize(value,
|
||||
specifiedType: const FullType(String)) as String;
|
||||
break;
|
||||
case 'isBillable':
|
||||
result.isBillable = serializers.deserialize(value,
|
||||
specifiedType: const FullType(bool)) as bool;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -559,11 +574,22 @@ class _$TaskTime extends TaskTime {
|
|||
final DateTime startDate;
|
||||
@override
|
||||
final DateTime endDate;
|
||||
@override
|
||||
final String description;
|
||||
@override
|
||||
final bool isBillable;
|
||||
|
||||
factory _$TaskTime([void Function(TaskTimeBuilder) updates]) =>
|
||||
(new TaskTimeBuilder()..update(updates))._build();
|
||||
|
||||
_$TaskTime._({this.startDate, this.endDate}) : super._();
|
||||
_$TaskTime._(
|
||||
{this.startDate, this.endDate, this.description, this.isBillable})
|
||||
: super._() {
|
||||
BuiltValueNullFieldError.checkNotNull(
|
||||
description, r'TaskTime', 'description');
|
||||
BuiltValueNullFieldError.checkNotNull(
|
||||
isBillable, r'TaskTime', 'isBillable');
|
||||
}
|
||||
|
||||
@override
|
||||
TaskTime rebuild(void Function(TaskTimeBuilder) updates) =>
|
||||
|
|
@ -577,7 +603,9 @@ class _$TaskTime extends TaskTime {
|
|||
if (identical(other, this)) return true;
|
||||
return other is TaskTime &&
|
||||
startDate == other.startDate &&
|
||||
endDate == other.endDate;
|
||||
endDate == other.endDate &&
|
||||
description == other.description &&
|
||||
isBillable == other.isBillable;
|
||||
}
|
||||
|
||||
int __hashCode;
|
||||
|
|
@ -587,6 +615,8 @@ class _$TaskTime extends TaskTime {
|
|||
var _$hash = 0;
|
||||
_$hash = $jc(_$hash, startDate.hashCode);
|
||||
_$hash = $jc(_$hash, endDate.hashCode);
|
||||
_$hash = $jc(_$hash, description.hashCode);
|
||||
_$hash = $jc(_$hash, isBillable.hashCode);
|
||||
_$hash = $jf(_$hash);
|
||||
return __hashCode ??= _$hash;
|
||||
}
|
||||
|
|
@ -595,7 +625,9 @@ class _$TaskTime extends TaskTime {
|
|||
String toString() {
|
||||
return (newBuiltValueToStringHelper(r'TaskTime')
|
||||
..add('startDate', startDate)
|
||||
..add('endDate', endDate))
|
||||
..add('endDate', endDate)
|
||||
..add('description', description)
|
||||
..add('isBillable', isBillable))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -611,6 +643,14 @@ class TaskTimeBuilder implements Builder<TaskTime, TaskTimeBuilder> {
|
|||
DateTime get endDate => _$this._endDate;
|
||||
set endDate(DateTime endDate) => _$this._endDate = endDate;
|
||||
|
||||
String _description;
|
||||
String get description => _$this._description;
|
||||
set description(String description) => _$this._description = description;
|
||||
|
||||
bool _isBillable;
|
||||
bool get isBillable => _$this._isBillable;
|
||||
set isBillable(bool isBillable) => _$this._isBillable = isBillable;
|
||||
|
||||
TaskTimeBuilder();
|
||||
|
||||
TaskTimeBuilder get _$this {
|
||||
|
|
@ -618,6 +658,8 @@ class TaskTimeBuilder implements Builder<TaskTime, TaskTimeBuilder> {
|
|||
if ($v != null) {
|
||||
_startDate = $v.startDate;
|
||||
_endDate = $v.endDate;
|
||||
_description = $v.description;
|
||||
_isBillable = $v.isBillable;
|
||||
_$v = null;
|
||||
}
|
||||
return this;
|
||||
|
|
@ -638,8 +680,14 @@ class TaskTimeBuilder implements Builder<TaskTime, TaskTimeBuilder> {
|
|||
TaskTime build() => _build();
|
||||
|
||||
_$TaskTime _build() {
|
||||
final _$result =
|
||||
_$v ?? new _$TaskTime._(startDate: startDate, endDate: endDate);
|
||||
final _$result = _$v ??
|
||||
new _$TaskTime._(
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
description: BuiltValueNullFieldError.checkNotNull(
|
||||
description, r'TaskTime', 'description'),
|
||||
isBillable: BuiltValueNullFieldError.checkNotNull(
|
||||
isBillable, r'TaskTime', 'isBillable'));
|
||||
replace(_$result);
|
||||
return _$result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ class _TaskEditDesktopState extends State<TaskEditDesktop> {
|
|||
final state = viewModel.state;
|
||||
|
||||
final company = state.company;
|
||||
final settings = company.settings;
|
||||
final client = state.clientState.get(task.clientId);
|
||||
final showEndDate = company.showTaskEndDate;
|
||||
final taskTimes = task.getTaskTimes(sort: false);
|
||||
|
|
@ -303,16 +304,17 @@ class _TaskEditDesktopState extends State<TaskEditDesktop> {
|
|||
key: ValueKey('__table_${_updatedAt}__'),
|
||||
padding: const EdgeInsets.symmetric(horizontal: kMobileDialogPadding),
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: Text(localization.startDate)),
|
||||
Expanded(child: Text(localization.startTime)),
|
||||
if (showEndDate) Expanded(child: Text(localization.endDate)),
|
||||
Expanded(child: Text(localization.endTime)),
|
||||
Expanded(child: Text(localization.duration)),
|
||||
SizedBox(width: 40),
|
||||
],
|
||||
),
|
||||
if (!settings.showTaskItemDescription)
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: Text(localization.startDate)),
|
||||
Expanded(child: Text(localization.startTime)),
|
||||
if (showEndDate) Expanded(child: Text(localization.endDate)),
|
||||
Expanded(child: Text(localization.endTime)),
|
||||
Expanded(child: Text(localization.duration)),
|
||||
SizedBox(width: 40),
|
||||
],
|
||||
),
|
||||
...taskTimes.map((taskTime) {
|
||||
final index = taskTimes.indexOf(taskTime);
|
||||
return Row(
|
||||
|
|
@ -331,6 +333,9 @@ class _TaskEditDesktopState extends State<TaskEditDesktop> {
|
|||
child: DatePicker(
|
||||
key: ValueKey(
|
||||
'__${_startTimeUpdatedAt}_${_durationUpdateAt}_${index}__'),
|
||||
labelText: settings.showTaskItemDescription
|
||||
? localization.startDate
|
||||
: null,
|
||||
selectedDate: taskTimes[index].startDate ==
|
||||
null
|
||||
? null
|
||||
|
|
@ -357,6 +362,9 @@ class _TaskEditDesktopState extends State<TaskEditDesktop> {
|
|||
child: TimePicker(
|
||||
key: ValueKey(
|
||||
'__${_durationUpdateAt}_${index}__'),
|
||||
labelText: settings.showTaskItemDescription
|
||||
? localization.startTime
|
||||
: null,
|
||||
selectedDateTime: taskTimes[index].startDate,
|
||||
onSelected: (timeOfDay) {
|
||||
final taskTime = taskTimes[index]
|
||||
|
|
@ -379,6 +387,9 @@ class _TaskEditDesktopState extends State<TaskEditDesktop> {
|
|||
child: DatePicker(
|
||||
key: ValueKey(
|
||||
'__${_startDateUpdatedAt}_${_durationUpdateAt}_${_endTimeUpdatedAt}_${index}__'),
|
||||
labelText: settings.showTaskItemDescription
|
||||
? localization.endDate
|
||||
: null,
|
||||
selectedDate: taskTimes[index].endDate ==
|
||||
null
|
||||
? null
|
||||
|
|
@ -404,6 +415,9 @@ class _TaskEditDesktopState extends State<TaskEditDesktop> {
|
|||
child: TimePicker(
|
||||
key: ValueKey(
|
||||
'__${_endDateUpdatedAt}_${_durationUpdateAt}_${index}__'),
|
||||
labelText: settings.showTaskItemDescription
|
||||
? localization.endTime
|
||||
: null,
|
||||
selectedDateTime: taskTimes[index].endDate,
|
||||
isEndTime: true,
|
||||
onSelected: (timeOfDay) {
|
||||
|
|
@ -426,6 +440,9 @@ class _TaskEditDesktopState extends State<TaskEditDesktop> {
|
|||
child: DurationPicker(
|
||||
key: ValueKey(
|
||||
'__${_startTimeUpdatedAt}_${_endTimeUpdatedAt}_${_startDateUpdatedAt}_${_endDateUpdatedAt}_${index}__'),
|
||||
labelText: settings.showTaskItemDescription
|
||||
? localization.duration
|
||||
: null,
|
||||
onSelected: (Duration duration) {
|
||||
final taskTime = taskTimes[index]
|
||||
.copyWithDuration(duration);
|
||||
|
|
@ -446,7 +463,7 @@ class _TaskEditDesktopState extends State<TaskEditDesktop> {
|
|||
),
|
||||
],
|
||||
),
|
||||
if (company.settings.showTaskItemDescription)
|
||||
if (settings.showTaskItemDescription)
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(bottom: 16, right: 16),
|
||||
|
|
@ -484,154 +501,6 @@ class _TaskEditDesktopState extends State<TaskEditDesktop> {
|
|||
}).toList(),
|
||||
],
|
||||
),
|
||||
/*
|
||||
FormCard(
|
||||
padding: const EdgeInsets.symmetric(horizontal: kMobileDialogPadding),
|
||||
child: Table(
|
||||
key: ValueKey('__table_old_${_updatedAt}__'),
|
||||
columnWidths: {
|
||||
showEndDate ? 5 : 4: FixedColumnWidth(kMinInteractiveDimension),
|
||||
},
|
||||
children: [
|
||||
TableRow(
|
||||
children: [
|
||||
TableHeader(localization.startDate, isFirst: true),
|
||||
TableHeader(localization.startTime),
|
||||
if (showEndDate) TableHeader(localization.endDate),
|
||||
TableHeader(localization.endTime),
|
||||
TableHeader(localization.duration),
|
||||
TableHeader(''),
|
||||
],
|
||||
decoration: tableHeaderColor.isNotEmpty
|
||||
? BoxDecoration(
|
||||
color: convertHexStringToColor(tableHeaderColor),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
for (var index = 0; index < taskTimes.length; index++) ...[
|
||||
TableRow(children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: DatePicker(
|
||||
key: ValueKey(
|
||||
'__${_startTimeUpdatedAt}_${_durationUpdateAt}_${index}__'),
|
||||
selectedDate: taskTimes[index].startDate == null
|
||||
? null
|
||||
: convertDateTimeToSqlDate(
|
||||
taskTimes[index].startDate.toLocal()),
|
||||
onSelected: (date, _) {
|
||||
final taskTime = taskTimes[index]
|
||||
.copyWithStartDate(date, syncDates: !showEndDate);
|
||||
viewModel.onUpdatedTaskTime(taskTime, index);
|
||||
setState(() {
|
||||
_startDateUpdatedAt =
|
||||
DateTime.now().millisecondsSinceEpoch;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: TimePicker(
|
||||
key: ValueKey('__${_durationUpdateAt}_${index}__'),
|
||||
selectedDateTime: taskTimes[index].startDate,
|
||||
onSelected: (timeOfDay) {
|
||||
final taskTime =
|
||||
taskTimes[index].copyWithStartTime(timeOfDay);
|
||||
viewModel.onUpdatedTaskTime(taskTime, index);
|
||||
setState(() {
|
||||
_startTimeUpdatedAt =
|
||||
DateTime.now().millisecondsSinceEpoch;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
if (showEndDate)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: DatePicker(
|
||||
key: ValueKey(
|
||||
'__${_startDateUpdatedAt}_${_durationUpdateAt}_${_endTimeUpdatedAt}_${index}__'),
|
||||
selectedDate: taskTimes[index].endDate == null
|
||||
? null
|
||||
: convertDateTimeToSqlDate(
|
||||
taskTimes[index].endDate.toLocal()),
|
||||
onSelected: (date, _) {
|
||||
final taskTime =
|
||||
taskTimes[index].copyWithEndDate(date);
|
||||
viewModel.onUpdatedTaskTime(taskTime, index);
|
||||
setState(() {
|
||||
_endDateUpdatedAt =
|
||||
DateTime.now().millisecondsSinceEpoch;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: TimePicker(
|
||||
key: ValueKey(
|
||||
'__${_endDateUpdatedAt}_${_durationUpdateAt}_${index}__'),
|
||||
selectedDateTime: taskTimes[index].endDate,
|
||||
isEndTime: true,
|
||||
onSelected: (timeOfDay) {
|
||||
final taskTime =
|
||||
taskTimes[index].copyWithEndTime(timeOfDay);
|
||||
viewModel.onUpdatedTaskTime(taskTime, index);
|
||||
setState(() {
|
||||
_endTimeUpdatedAt =
|
||||
DateTime.now().millisecondsSinceEpoch;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: DurationPicker(
|
||||
key: ValueKey(
|
||||
'__${_startTimeUpdatedAt}_${_endTimeUpdatedAt}_${_startDateUpdatedAt}_${_endDateUpdatedAt}_${index}__'),
|
||||
onSelected: (Duration duration) {
|
||||
final taskTime =
|
||||
taskTimes[index].copyWithDuration(duration);
|
||||
viewModel.onUpdatedTaskTime(taskTime, index);
|
||||
setState(() {
|
||||
_durationUpdateAt =
|
||||
DateTime.now().millisecondsSinceEpoch;
|
||||
});
|
||||
},
|
||||
selectedDuration: (taskTimes[index].startDate == null ||
|
||||
taskTimes[index].endDate == null)
|
||||
? null
|
||||
: taskTimes[index].duration,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4),
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
Icons.clear,
|
||||
color: overlapping.contains(index) ? Colors.red : null,
|
||||
),
|
||||
tooltip: overlapping.contains(index)
|
||||
? localization.invalidTime
|
||||
: localization.remove,
|
||||
onPressed: taskTimes[index].isEmpty
|
||||
? null
|
||||
: () {
|
||||
viewModel.onRemoveTaskTime(index);
|
||||
setState(() {
|
||||
_updatedAt =
|
||||
DateTime.now().millisecondsSinceEpoch;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
]),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
*/
|
||||
SizedBox(
|
||||
height: kMobileDialogPadding,
|
||||
),
|
||||
|
|
|
|||
Loading…
Reference in New Issue