added fields to task view, changed icon of task editing.
This commit is contained in:
parent
aa0f56231f
commit
1ef9ed4e67
|
@ -1,18 +1,30 @@
|
|||
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:vikunja_app/utils/priority.dart';
|
||||
|
||||
import '../models/label.dart';
|
||||
import '../models/task.dart';
|
||||
import '../pages/list/task_edit.dart';
|
||||
import '../stores/project_store.dart';
|
||||
import '../theme/constants.dart';
|
||||
import 'label.dart';
|
||||
|
||||
class TaskBottomSheet extends StatefulWidget {
|
||||
final Task task;
|
||||
final bool showInfo;
|
||||
final bool loading;
|
||||
final Function onEdit;
|
||||
final ValueSetter<bool>? onMarkedAsDone;
|
||||
final ProjectProvider taskState;
|
||||
|
||||
const TaskBottomSheet({
|
||||
Key? key,
|
||||
required this.task,
|
||||
required this.onEdit,
|
||||
required this.taskState,
|
||||
this.loading = false,
|
||||
this.showInfo = false,
|
||||
this.onMarkedAsDone,
|
||||
|
@ -35,28 +47,96 @@ class TaskBottomSheetState extends State<TaskBottomSheet> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ThemeData theme = Theme.of(context);
|
||||
return Container(
|
||||
height: MediaQuery.of(context).size.height * 0.9,
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(20, 10, 10, 20),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
||||
children: <Widget>[
|
||||
Row(
|
||||
// Title and edit button
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(_currentTask.title),
|
||||
BackButton(),
|
||||
Text(_currentTask.title, style: theme.textTheme.headlineLarge),
|
||||
IconButton(onPressed: () {
|
||||
Navigator.push<Task>(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (buildContext) => TaskEditPage(
|
||||
task: _currentTask,
|
||||
taskState: widget.taskState,
|
||||
),
|
||||
),
|
||||
)
|
||||
.then((task) => setState(() {
|
||||
if (task != null) _currentTask = task;
|
||||
}))
|
||||
.whenComplete(() => widget.onEdit());
|
||||
}, icon: Icon(Icons.edit)),
|
||||
],
|
||||
),
|
||||
Wrap(
|
||||
spacing: 10,
|
||||
children: _currentTask.labels.map((Label label) {
|
||||
return LabelComponent(
|
||||
label: label,
|
||||
);
|
||||
}).toList()),
|
||||
|
||||
// description with html rendering
|
||||
Text("Description", style: theme.textTheme.headlineSmall),
|
||||
Padding(padding: EdgeInsets.fromLTRB(10, 0, 0, 0),
|
||||
child: HtmlWidget(_currentTask.description.isNotEmpty ? _currentTask.description : "No description"),
|
||||
),
|
||||
// Due date
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.access_time),
|
||||
Padding(padding: EdgeInsets.fromLTRB(10, 0, 0, 0)),
|
||||
Text(_currentTask.dueDate != null ? vDateFormatShort.format(_currentTask.dueDate!.toLocal()) : "No due date"),
|
||||
],
|
||||
),
|
||||
// start date
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.play_arrow_rounded),
|
||||
Padding(padding: EdgeInsets.fromLTRB(10, 0, 0, 0)),
|
||||
Text(_currentTask.startDate != null ? vDateFormatShort.format(_currentTask.startDate!.toLocal()) : "No start date"),
|
||||
],
|
||||
),
|
||||
// end date
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.stop_rounded),
|
||||
Padding(padding: EdgeInsets.fromLTRB(10, 0, 0, 0)),
|
||||
Text(_currentTask.endDate != null ? vDateFormatShort.format(_currentTask.endDate!.toLocal()) : "No end date"),
|
||||
],
|
||||
),
|
||||
// priority
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.priority_high),
|
||||
Padding(padding: EdgeInsets.fromLTRB(10, 0, 0, 0)),
|
||||
Text(_currentTask.priority != null ? priorityToString(_currentTask.priority) : "No priority"),
|
||||
],
|
||||
),
|
||||
// progress
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.percent),
|
||||
Padding(padding: EdgeInsets.fromLTRB(10, 0, 0, 0)),
|
||||
Text(_currentTask.percent_done != null ? (_currentTask.percent_done! * 100).toInt().toString() + "%" : "Unset"),
|
||||
],
|
||||
),
|
||||
HtmlWidget(_currentTask.description),
|
||||
],
|
||||
),
|
||||
)
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ class TaskTileState extends State<TaskTile> with AutomaticKeepAliveClientMixin {
|
|||
? null
|
||||
: HtmlWidget(_currentTask.description),
|
||||
trailing: IconButton(
|
||||
icon: Icon(Icons.settings),
|
||||
icon: Icon(Icons.edit),
|
||||
onPressed: () {},
|
||||
),
|
||||
);
|
||||
|
@ -110,7 +110,7 @@ class TaskTileState extends State<TaskTile> with AutomaticKeepAliveClientMixin {
|
|||
showModalBottomSheet<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return TaskBottomSheet(task: widget.task);
|
||||
return TaskBottomSheet(task: widget.task, onEdit: widget.onEdit, taskState: taskState);
|
||||
});
|
||||
},
|
||||
title: widget.showInfo
|
||||
|
@ -137,7 +137,7 @@ class TaskTileState extends State<TaskTile> with AutomaticKeepAliveClientMixin {
|
|||
},
|
||||
),
|
||||
trailing: IconButton(
|
||||
icon: Icon(Icons.settings),
|
||||
icon: Icon(Icons.edit),
|
||||
onPressed: () {
|
||||
Navigator.push<Task>(
|
||||
context,
|
||||
|
|
|
@ -3,9 +3,9 @@ import 'package:vikunja_app/models/label.dart';
|
|||
|
||||
class LabelComponent extends StatelessWidget {
|
||||
final Label label;
|
||||
final VoidCallback onDelete;
|
||||
final VoidCallback? onDelete;
|
||||
|
||||
const LabelComponent({Key? key, required this.label, required this.onDelete})
|
||||
const LabelComponent({Key? key, required this.label, this.onDelete})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
|
|
|
@ -20,6 +20,7 @@ class Task {
|
|||
final bool done;
|
||||
Color? color;
|
||||
final double? kanbanPosition;
|
||||
final double? percent_done;
|
||||
final User createdBy;
|
||||
Duration? repeatAfter;
|
||||
final List<Task> subtasks;
|
||||
|
@ -45,6 +46,7 @@ class Task {
|
|||
this.repeatAfter,
|
||||
this.color,
|
||||
this.kanbanPosition,
|
||||
this.percent_done,
|
||||
this.subtasks = const [],
|
||||
this.labels = const [],
|
||||
this.attachments = const [],
|
||||
|
@ -90,6 +92,9 @@ class Task {
|
|||
kanbanPosition = json['kanban_position'] is int
|
||||
? json['kanban_position'].toDouble()
|
||||
: json['kanban_position'],
|
||||
percent_done = json['percent_done'] is int
|
||||
? json['percent_done'].toDouble()
|
||||
: json['percent_done'],
|
||||
labels = json['labels'] != null
|
||||
? (json['labels'] as List<dynamic>)
|
||||
.map((label) => Label.fromJson(label))
|
||||
|
@ -128,6 +133,7 @@ class Task {
|
|||
'repeat_after': repeatAfter?.inSeconds,
|
||||
'hex_color': color?.value.toRadixString(16).padLeft(8, '0').substring(2),
|
||||
'kanban_position': kanbanPosition,
|
||||
'percent_done': percent_done,
|
||||
'project_id': projectId,
|
||||
'labels': labels.map((label) => label.toJSON()).toList(),
|
||||
'subtasks': subtasks.map((subtask) => subtask.toJSON()).toList(),
|
||||
|
@ -157,6 +163,7 @@ class Task {
|
|||
bool? done,
|
||||
Color? color,
|
||||
double? kanbanPosition,
|
||||
double? percent_done,
|
||||
User? createdBy,
|
||||
Duration? repeatAfter,
|
||||
List<Task>? subtasks,
|
||||
|
@ -182,6 +189,7 @@ class Task {
|
|||
done: done ?? this.done,
|
||||
color: color ?? this.color,
|
||||
kanbanPosition: kanbanPosition ?? this.kanbanPosition,
|
||||
percent_done: percent_done ?? this.percent_done,
|
||||
createdBy: createdBy ?? this.createdBy,
|
||||
repeatAfter: repeatAfter ?? this.repeatAfter,
|
||||
subtasks: subtasks ?? this.subtasks,
|
||||
|
|
|
@ -252,7 +252,7 @@ class _TaskEditPageState extends State<TaskEditPage> {
|
|||
_reminderDates.add(DateTime(0));
|
||||
var currentIndex = _reminderDates.length - 1;
|
||||
|
||||
// FIXME: Why does putting this into a row fails?
|
||||
// FIXME: Why does putting this into a row fail?
|
||||
setState(() => _reminderInputs.add(
|
||||
VikunjaDateTimePicker(
|
||||
label: 'Reminder',
|
||||
|
|
|
@ -30,4 +30,5 @@ const vStandardVerticalPadding = EdgeInsets.symmetric(vertical: 5.0);
|
|||
const vStandardHorizontalPadding = EdgeInsets.symmetric(horizontal: 5.0);
|
||||
const vStandardPadding = EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0);
|
||||
|
||||
var vDateFormatLong = DateFormat("EEEE, MMMM d, yyyy 'at' H:mm");
|
||||
var vDateFormatLong = DateFormat("EEEE, MMMM d, yyyy 'at' H:mm");
|
||||
var vDateFormatShort = DateFormat("d MMM yyyy, H:mm");
|
Loading…
Reference in New Issue