List edit #21

Merged
JonasFranz merged 8 commits from feature/task-edit into master 2019-03-11 20:29:16 +00:00
5 changed files with 153 additions and 163 deletions
Showing only changes of commit 3a1409816a - Show all commits

View File

@ -46,10 +46,11 @@ class TaskTileState extends State<TaskTile> {
_currentTask.description == null || _currentTask.description.isEmpty
? null
: Text(_currentTask.description),
trailing: IconButton(icon: Icon(Icons.settings), onPressed: () {
print("test");
}
),
trailing: IconButton(
icon: Icon(Icons.settings),

Unrelated change

Unrelated change
onPressed: () {
print("test");
}),
);
}
return CheckboxListTile(

View File

@ -3,40 +3,40 @@ import 'package:vikunja_app/models/task.dart';
import 'package:vikunja_app/models/user.dart';
class TaskList {
final int id;
final String title, description;
final User owner;
final DateTime created, updated;
final List<Task> tasks;
final int id;
final String title, description;
final User owner;
final DateTime created, updated;
final List<Task> tasks;
TaskList(
{@required this.id,
@required this.title,
this.description,
this.owner,
this.created,
this.updated,
this.tasks});
TaskList(
{@required this.id,
@required this.title,
this.description,
this.owner,
this.created,
this.updated,
this.tasks});
TaskList.fromJson(Map<String, dynamic> json)
: id = json['id'],
owner = User.fromJson(json['owner']),
description = json['description'],
title = json['title'],
updated = DateTime.fromMillisecondsSinceEpoch(json['updated']),
created = DateTime.fromMillisecondsSinceEpoch(json['created']),
tasks = (json['tasks'] as List<dynamic>)
?.map((taskJson) => Task.fromJson(taskJson))
?.toList();
TaskList.fromJson(Map<String, dynamic> json)
: id = json['id'],
owner = User.fromJson(json['owner']),
description = json['description'],
title = json['title'],
updated = DateTime.fromMillisecondsSinceEpoch(json['updated']),
created = DateTime.fromMillisecondsSinceEpoch(json['created']),
tasks = (json['tasks'] as List<dynamic>)
?.map((taskJson) => Task.fromJson(taskJson))
?.toList();
toJSON() {
return {
"id": this.id,
"title": this.title,
"description": this.description,
"owner": this.owner?.toJSON(),
"created": this.created?.millisecondsSinceEpoch,
"updated": this.updated?.millisecondsSinceEpoch,
};
}
toJSON() {
return {
"id": this.id,
"title": this.title,
"description": this.description,
"owner": this.owner?.toJSON(),
"created": this.created?.millisecondsSinceEpoch,

Wrong indention, make format

Wrong indention, make format
"updated": this.updated?.millisecondsSinceEpoch,
};
}
}

View File

@ -46,5 +46,3 @@ class Task {
'createdBy': owner?.toJSON()
};
}

View File

@ -3,130 +3,120 @@ import 'package:vikunja_app/global.dart';
import 'package:vikunja_app/models/list.dart';
class ListEditPage extends StatefulWidget {
final TaskList list;
final TaskList list;
ListEditPage({this.list}) : super(key: Key(list.toString()));
ListEditPage({this.list}) : super(key: Key(list.toString()));
@override
State<StatefulWidget> createState() => _ListEditPageState();
@override
State<StatefulWidget> createState() => _ListEditPageState();
}
class _ListEditPageState extends State<ListEditPage> {
final _formKey = GlobalKey<FormState>();
bool _loading = false;
String _title, _description;
final _formKey = GlobalKey<FormState>();
bool _loading = false;
String _title, _description;
@override
Widget build(BuildContext ctx) {
@override
Widget build(BuildContext ctx) {
return Scaffold(
appBar: AppBar(
title: Text('Edit List'),
),
body: Builder(
builder: (BuildContext context) => SafeArea(
child: Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: TextFormField(
maxLines: null,
keyboardType: TextInputType.multiline,
initialValue: widget.list.title,
onSaved: (title) => _title = title,
validator: (title) {
if (title.length < 3 || title.length > 250) {
return 'The title needs to have between 3 and 250 characters.';
}
return null;
},
decoration:
new InputDecoration(labelText: 'Title'),
),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: TextFormField(
maxLines: null,
keyboardType: TextInputType.multiline,
initialValue: widget.list.description,
onSaved: (description) =>
_description = description,
validator: (description) {
if (description.length > 1000) {
return 'The description can have a maximum of 1000 characters.';
}
return null;
},
decoration: new InputDecoration(
labelText: 'Description'),
),
),
Builder(
builder: (context) => RaisedButton(
padding:
EdgeInsets.symmetric(vertical: 10.0),
onPressed: !_loading
? () {
if (_formKey.currentState
.validate()) {
Form.of(context)
.save(); // Why does this not work?
_saveList(context);
} else {
print(
"sdf"); // TODO: handle error
}
}
: null,
child: _loading
? CircularProgressIndicator()
: Text('Save'),
)),
])),
)));
}
return Scaffold(
appBar: AppBar(
title: Text('Edit List'),
),
body: Builder(
builder: (BuildContext context) =>
SafeArea(
child: Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.symmetric(
horizontal: 16.0),
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: TextFormField(
maxLines: null,
keyboardType: TextInputType.multiline,
initialValue: widget.list.title,
onSaved: (title) => _title = title,
validator: (title) {
if (title.length < 3 || title.length > 250) {
return 'The title needs to have between 3 and 250 characters.';
}
return null;
},
decoration:
new InputDecoration(labelText: 'Title'),
),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: TextFormField(
maxLines: null,
keyboardType: TextInputType.multiline,
initialValue: widget.list.description,
onSaved: (description) => _description = description,
validator: (description) {
if (description.length > 1000) {
return 'The description can have a maximum of 1000 characters.';
}
return null;
},
decoration:
new InputDecoration(labelText: 'Description'),
),
),
Builder(
builder: (context) => RaisedButton(
padding: EdgeInsets.symmetric(vertical: 10.0),
onPressed: !_loading
? () {
if (_formKey.currentState
.validate()) {
Form.of(context).save(); // Why does this not work?
_saveList(context);
} else {
print("sdf"); // TODO: handle error
}
}
: null,
child: _loading
? CircularProgressIndicator()
: Text('Save'),
)
),
]
)
),
)
)
);
}
_saveList(BuildContext context) async {
setState(() => _loading = true);
// FIXME: Do we need the try/catch block or is .then .catch .finally enough?
try {
Review

That's not possible. You may add a function like copyWith(...) as helper. But this may be to big for the problem.

That's not possible. You may add a function like copyWith(...) as helper. But this may be to big for the problem.
Review

I see, thanks!

I see, thanks!
Review

I see, thanks!

I see, thanks!
// FIXME: is there a way we can update the list without creating a new list object?
// aka updating the existing list we got from context (setters?)
TaskList updatedList = TaskList(
id: widget.list.id, title: _title, description: _description);
_saveList(BuildContext context) async {
setState(() => _loading = true);
// FIXME: Do we need the try/catch block or is .then .catch .finally enough?
try {
// FIXME: is there a way we can update the list without creating a new list object?
// aka updating the existing list we got from context (setters?)
TaskList updatedList = TaskList(
id: widget.list.id,
title: _title,
description: _description
);
// FIXME: When the api returns an error (status code != 2xx), this throws an exception
VikunjaGlobal.of(context).listService.update(updatedList)
.then((_) {
setState(() {});
final scaffold = Scaffold.of(context);
scaffold.showSnackBar(
SnackBar(
content: Text('The list was updated successfully!'),
)
);
}); // TODO: show the user a message the list was updated successfully
} catch(err) {
final scaffold = Scaffold.of(context);
scaffold.showSnackBar(
SnackBar(
content: Text('Something went wrong: ' + err.toString()),
action: SnackBarAction(
label: 'CLOSE', onPressed: scaffold.hideCurrentSnackBar),
),
);
} finally {
setState(() => _loading = false);
}
}
// FIXME: When the api returns an error (status code != 2xx), this throws an exception
VikunjaGlobal.of(context).listService.update(updatedList).then((_) {
setState(() {});
final scaffold = Scaffold.of(context);
scaffold.showSnackBar(SnackBar(
content: Text('The list was updated successfully!'),
));
}); // TODO: show the user a message the list was updated successfully
} catch (err) {
final scaffold = Scaffold.of(context);
scaffold.showSnackBar(
SnackBar(
content: Text('Something went wrong: ' + err.toString()),
action: SnackBarAction(
label: 'CLOSE', onPressed: scaffold.hideCurrentSnackBar),
),
);
} finally {
setState(() => _loading = false);

catch won't work here. You should use .catch instead

catch won't work here. You should use .catch instead

If I do this, is the whole try catch block still nessecary?

If I do this, is the whole `try` `catch` block still nessecary?

No, it's not since the that stuff is asynchron and will finish after the function already returned.

No, it's not since the that stuff is asynchron and will finish after the function already returned.
Review

Done.

Done.
}
}
}

View File

@ -42,12 +42,13 @@ class _ListPageState extends State<ListPage> {
title: new Text(_list.title),
actions: <Widget>[
IconButton(
icon: Icon(Icons.edit),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => ListEditPage(list: _list,))
)
)
icon: Icon(Icons.edit),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ListEditPage(
list: _list,
))))
],
),
body: !this._loading