format
continuous-integration/drone/pr Build is passing
Details
continuous-integration/drone/pr Build is passing
Details
This commit is contained in:
parent
fbd8efa2b2
commit
780ee537f6
|
@ -80,13 +80,13 @@ class _ListPageState extends State<ListPage> {
|
|||
task: task,
|
||||
loading: false,
|
||||
onEdit: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TaskEditPage(
|
||||
task: task,
|
||||
),
|
||||
),
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TaskEditPage(
|
||||
task: task,
|
||||
),
|
||||
),
|
||||
),
|
||||
onMarkedAsDone: (done) {
|
||||
VikunjaGlobal.of(context)
|
||||
.taskService
|
||||
|
@ -112,13 +112,13 @@ class _ListPageState extends State<ListPage> {
|
|||
task: task,
|
||||
loading: true,
|
||||
onEdit: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TaskEditPage(
|
||||
task: task,
|
||||
),
|
||||
),
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TaskEditPage(
|
||||
task: task,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -57,248 +57,240 @@ class _TaskEditPageState extends State<TaskEditPage> {
|
|||
),
|
||||
body: Builder(
|
||||
builder: (BuildContext context) => SafeArea(
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: ListView(padding: const EdgeInsets.all(16.0), children: <
|
||||
Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: ListView(padding: const EdgeInsets.all(16.0), children: <
|
||||
Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: TextFormField(
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.multiline,
|
||||
initialValue: widget.task.text,
|
||||
onSaved: (text) => _text = text,
|
||||
validator: (text) {
|
||||
if (text.length < 3 || text.length > 250) {
|
||||
return 'The text needs to have between 3 and 250 characters.';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
decoration: new InputDecoration(
|
||||
labelText: 'Text',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: TextFormField(
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.multiline,
|
||||
initialValue: widget.task.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',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
),
|
||||
VikunjaDateTimePicker(
|
||||
icon: Icon(Icons.access_time),
|
||||
label: 'Due Date',
|
||||
initialValue: widget.task.dueDate,
|
||||
onSaved: (duedate) => _dueDate = duedate,
|
||||
),
|
||||
VikunjaDateTimePicker(
|
||||
label: 'Start Date',
|
||||
initialValue: widget.task.startDate,
|
||||
onSaved: (startDate) => _startDate = startDate,
|
||||
),
|
||||
VikunjaDateTimePicker(
|
||||
label: 'End Date',
|
||||
initialValue: widget.task.endDate,
|
||||
onSaved: (endDate) => _endDate = endDate,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: TextFormField(
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.multiline,
|
||||
initialValue: widget.task.text,
|
||||
onSaved: (text) => _text = text,
|
||||
validator: (text) {
|
||||
if (text.length < 3 || text.length > 250) {
|
||||
return 'The text needs to have between 3 and 250 characters.';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
keyboardType: TextInputType.number,
|
||||
initialValue: getRepeatAfterValueFromDuration(
|
||||
widget.task.repeatAfter)
|
||||
?.toString(),
|
||||
onSaved: (repeatAfter) => _repeatAfter =
|
||||
getDurationFromType(repeatAfter, _repeatAfterType),
|
||||
decoration: new InputDecoration(
|
||||
labelText: 'Text',
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'Repeat after',
|
||||
border: InputBorder.none,
|
||||
icon: Icon(Icons.repeat),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: TextFormField(
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.multiline,
|
||||
initialValue: widget.task.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',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
),
|
||||
VikunjaDateTimePicker(
|
||||
icon: Icon(Icons.access_time),
|
||||
label: 'Due Date',
|
||||
initialValue: widget.task.dueDate,
|
||||
onSaved: (duedate) => _dueDate = duedate,
|
||||
),
|
||||
VikunjaDateTimePicker(
|
||||
label: 'Start Date',
|
||||
initialValue: widget.task.startDate,
|
||||
onSaved: (startDate) => _startDate = startDate,
|
||||
),
|
||||
VikunjaDateTimePicker(
|
||||
label: 'End Date',
|
||||
initialValue: widget.task.endDate,
|
||||
onSaved: (endDate) => _endDate = endDate,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: TextFormField(
|
||||
keyboardType: TextInputType.number,
|
||||
initialValue: getRepeatAfterValueFromDuration(
|
||||
widget.task.repeatAfter)
|
||||
?.toString(),
|
||||
onSaved: (repeatAfter) => _repeatAfter =
|
||||
getDurationFromType(
|
||||
repeatAfter, _repeatAfterType),
|
||||
decoration: new InputDecoration(
|
||||
labelText: 'Repeat after',
|
||||
border: InputBorder.none,
|
||||
icon: Icon(Icons.repeat),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: DropdownButton<String>(
|
||||
isExpanded: true,
|
||||
isDense: true,
|
||||
value: _repeatAfterType ??
|
||||
getRepeatAfterTypeFromDuration(
|
||||
widget.task.repeatAfter),
|
||||
onChanged: (String newValue) {
|
||||
setState(() {
|
||||
_repeatAfterType = newValue;
|
||||
});
|
||||
},
|
||||
items: <String>[
|
||||
'Hours',
|
||||
'Days',
|
||||
'Weeks',
|
||||
'Months',
|
||||
'Years'
|
||||
].map<DropdownMenuItem<String>>((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: _reminderInputs,
|
||||
),
|
||||
GestureDetector(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 15, left: 2),
|
||||
child: Icon(
|
||||
Icons.alarm_add,
|
||||
color: Colors.grey,
|
||||
)),
|
||||
Text(
|
||||
'Add a reminder',
|
||||
style: TextStyle(
|
||||
color: Colors.grey,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
// We add a new entry every time we add a new input, to make sure all inputs have a place where they can put their value.
|
||||
_reminderDates.add(null);
|
||||
var currentIndex = _reminderDates.length - 1;
|
||||
|
||||
// FIXME: Why does putting this into a row fails?
|
||||
setState(() => _reminderInputs.add(Row(
|
||||
children: <Widget>[
|
||||
VikunjaDateTimePicker(
|
||||
label: 'Reminder',
|
||||
onSaved: (reminder) =>
|
||||
_reminderDates[currentIndex] = reminder,
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () => print('tapped'),
|
||||
child: Icon(Icons.close),
|
||||
)
|
||||
],
|
||||
)));
|
||||
}),
|
||||
InputDecorator(
|
||||
isEmpty: _priority == null,
|
||||
decoration: InputDecoration(
|
||||
icon: const Icon(Icons.flag),
|
||||
labelText: 'Priority',
|
||||
border: InputBorder.none,
|
||||
),
|
||||
child: new DropdownButton<String>(
|
||||
value: _priorityToString(_priority),
|
||||
Expanded(
|
||||
child: DropdownButton<String>(
|
||||
isExpanded: true,
|
||||
isDense: true,
|
||||
value: _repeatAfterType ??
|
||||
getRepeatAfterTypeFromDuration(
|
||||
widget.task.repeatAfter),
|
||||
onChanged: (String newValue) {
|
||||
setState(() {
|
||||
_priority = _priorityFromString(newValue);
|
||||
_repeatAfterType = newValue;
|
||||
});
|
||||
},
|
||||
items: [
|
||||
'Unset',
|
||||
'Low',
|
||||
'Medium',
|
||||
'High',
|
||||
'Urgent',
|
||||
'DO NOW'
|
||||
].map((String value) {
|
||||
return new DropdownMenuItem(
|
||||
items: <String>[
|
||||
'Hours',
|
||||
'Days',
|
||||
'Weeks',
|
||||
'Months',
|
||||
'Years'
|
||||
].map<DropdownMenuItem<String>>((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: new Text(value),
|
||||
child: Text(value),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
Wrap(
|
||||
spacing: 10,
|
||||
children: _labels.map((Label label) {
|
||||
return LabelComponent(
|
||||
label: label,
|
||||
onDelete: () {
|
||||
_removeLabel(label);
|
||||
},
|
||||
);
|
||||
}).toList()),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width - 80,
|
||||
child: TypeAheadFormField(
|
||||
textFieldConfiguration: TextFieldConfiguration(
|
||||
controller: _labelTypeAheadController,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Add a new label')),
|
||||
suggestionsCallback: (pattern) {
|
||||
return _searchLabel(pattern);
|
||||
},
|
||||
itemBuilder: (context, suggestion) {
|
||||
return ListTile(
|
||||
title: Text(suggestion),
|
||||
);
|
||||
},
|
||||
transitionBuilder:
|
||||
(context, suggestionsBox, controller) {
|
||||
return suggestionsBox;
|
||||
},
|
||||
onSuggestionSelected: (suggestion) {
|
||||
_addLabel(suggestion);
|
||||
},
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () =>
|
||||
_createAndAddLabel(_labelTypeAheadController.text),
|
||||
icon: Icon(Icons.add),
|
||||
)
|
||||
],
|
||||
),
|
||||
Builder(
|
||||
builder: (context) => Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: FancyButton(
|
||||
onPressed: !_loading
|
||||
? () {
|
||||
if (_formKey.currentState.validate()) {
|
||||
Form.of(context).save();
|
||||
_saveTask(context);
|
||||
}
|
||||
}
|
||||
: null,
|
||||
child: _loading
|
||||
? CircularProgressIndicator()
|
||||
: VikunjaButtonText('Save'),
|
||||
))),
|
||||
]),
|
||||
],
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: _reminderInputs,
|
||||
),
|
||||
GestureDetector(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 15, left: 2),
|
||||
child: Icon(
|
||||
Icons.alarm_add,
|
||||
color: Colors.grey,
|
||||
)),
|
||||
Text(
|
||||
'Add a reminder',
|
||||
style: TextStyle(
|
||||
color: Colors.grey,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
// We add a new entry every time we add a new input, to make sure all inputs have a place where they can put their value.
|
||||
_reminderDates.add(null);
|
||||
var currentIndex = _reminderDates.length - 1;
|
||||
|
||||
// FIXME: Why does putting this into a row fails?
|
||||
setState(() => _reminderInputs.add(Row(
|
||||
children: <Widget>[
|
||||
VikunjaDateTimePicker(
|
||||
label: 'Reminder',
|
||||
onSaved: (reminder) =>
|
||||
_reminderDates[currentIndex] = reminder,
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () => print('tapped'),
|
||||
child: Icon(Icons.close),
|
||||
)
|
||||
],
|
||||
)));
|
||||
}),
|
||||
InputDecorator(
|
||||
isEmpty: _priority == null,
|
||||
decoration: InputDecoration(
|
||||
icon: const Icon(Icons.flag),
|
||||
labelText: 'Priority',
|
||||
border: InputBorder.none,
|
||||
),
|
||||
child: new DropdownButton<String>(
|
||||
value: _priorityToString(_priority),
|
||||
isExpanded: true,
|
||||
isDense: true,
|
||||
onChanged: (String newValue) {
|
||||
setState(() {
|
||||
_priority = _priorityFromString(newValue);
|
||||
});
|
||||
},
|
||||
items: ['Unset', 'Low', 'Medium', 'High', 'Urgent', 'DO NOW']
|
||||
.map((String value) {
|
||||
return new DropdownMenuItem(
|
||||
value: value,
|
||||
child: new Text(value),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
Wrap(
|
||||
spacing: 10,
|
||||
children: _labels.map((Label label) {
|
||||
return LabelComponent(
|
||||
label: label,
|
||||
onDelete: () {
|
||||
_removeLabel(label);
|
||||
},
|
||||
);
|
||||
}).toList()),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width - 80,
|
||||
child: TypeAheadFormField(
|
||||
textFieldConfiguration: TextFieldConfiguration(
|
||||
controller: _labelTypeAheadController,
|
||||
decoration:
|
||||
InputDecoration(labelText: 'Add a new label')),
|
||||
suggestionsCallback: (pattern) {
|
||||
return _searchLabel(pattern);
|
||||
},
|
||||
itemBuilder: (context, suggestion) {
|
||||
return ListTile(
|
||||
title: Text(suggestion),
|
||||
);
|
||||
},
|
||||
transitionBuilder: (context, suggestionsBox, controller) {
|
||||
return suggestionsBox;
|
||||
},
|
||||
onSuggestionSelected: (suggestion) {
|
||||
_addLabel(suggestion);
|
||||
},
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () =>
|
||||
_createAndAddLabel(_labelTypeAheadController.text),
|
||||
icon: Icon(Icons.add),
|
||||
)
|
||||
],
|
||||
),
|
||||
Builder(
|
||||
builder: (context) => Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: FancyButton(
|
||||
onPressed: !_loading
|
||||
? () {
|
||||
if (_formKey.currentState.validate()) {
|
||||
Form.of(context).save();
|
||||
_saveTask(context);
|
||||
}
|
||||
}
|
||||
: null,
|
||||
child: _loading
|
||||
? CircularProgressIndicator()
|
||||
: VikunjaButtonText('Save'),
|
||||
))),
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
Reference in New Issue