mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-26 14:59:22 +00:00
Can create surveys
This commit is contained in:
parent
8af4a61072
commit
4e951c6a78
@ -158,6 +158,11 @@ class PostsHelper {
|
|||||||
"time-end", (post.timeEnd.millisecondsSinceEpoch / 1000).floor());
|
"time-end", (post.timeEnd.millisecondsSinceEpoch / 1000).floor());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PostKind.SURVEY:
|
||||||
|
request.addString("question", post.survey.question);
|
||||||
|
request.addString("answers", post.survey.answers.join("<>"));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw Exception("Unsupported post type :" + post.kind.toString());
|
throw Exception("Unsupported post type :" + post.kind.toString());
|
||||||
break;
|
break;
|
||||||
|
@ -9,6 +9,17 @@ import 'package:meta/meta.dart';
|
|||||||
///
|
///
|
||||||
/// @author Pierre HUBERT
|
/// @author Pierre HUBERT
|
||||||
|
|
||||||
|
class NewSurvey {
|
||||||
|
final String question;
|
||||||
|
final Set<String> answers;
|
||||||
|
|
||||||
|
const NewSurvey({
|
||||||
|
@required this.question,
|
||||||
|
@required this.answers,
|
||||||
|
}) : assert(question != null),
|
||||||
|
assert(answers.length > 1);
|
||||||
|
}
|
||||||
|
|
||||||
class NewPost {
|
class NewPost {
|
||||||
final PostTarget target;
|
final PostTarget target;
|
||||||
final int targetID;
|
final int targetID;
|
||||||
@ -18,6 +29,7 @@ class NewPost {
|
|||||||
final List<int> pdf;
|
final List<int> pdf;
|
||||||
final PostKind kind;
|
final PostKind kind;
|
||||||
final DateTime timeEnd;
|
final DateTime timeEnd;
|
||||||
|
final NewSurvey survey;
|
||||||
|
|
||||||
const NewPost({
|
const NewPost({
|
||||||
@required this.target,
|
@required this.target,
|
||||||
@ -28,6 +40,7 @@ class NewPost {
|
|||||||
@required this.image,
|
@required this.image,
|
||||||
@required this.pdf,
|
@required this.pdf,
|
||||||
@required this.timeEnd,
|
@required this.timeEnd,
|
||||||
|
@required this.survey,
|
||||||
}) : assert(target != null),
|
}) : assert(target != null),
|
||||||
assert(targetID != null),
|
assert(targetID != null),
|
||||||
assert(visibility != null),
|
assert(visibility != null),
|
||||||
@ -35,5 +48,6 @@ class NewPost {
|
|||||||
assert(kind != PostKind.TEXT || content.length > 3),
|
assert(kind != PostKind.TEXT || content.length > 3),
|
||||||
assert(kind != PostKind.IMAGE || image != null),
|
assert(kind != PostKind.IMAGE || image != null),
|
||||||
assert(kind != PostKind.PDF || pdf != null),
|
assert(kind != PostKind.PDF || pdf != null),
|
||||||
assert(kind != PostKind.COUNTDOWN || timeEnd != null);
|
assert(kind != PostKind.COUNTDOWN || timeEnd != null),
|
||||||
|
assert(kind != PostKind.SURVEY || survey != null);
|
||||||
}
|
}
|
||||||
|
137
lib/ui/dialogs/new_survey_dialog.dart
Normal file
137
lib/ui/dialogs/new_survey_dialog.dart
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
import 'package:comunic/models/new_post.dart';
|
||||||
|
import 'package:comunic/utils/intl_utils.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// Create a new survey dialog
|
||||||
|
///
|
||||||
|
/// @author Pierre Hubert
|
||||||
|
|
||||||
|
/// Show a dialog to prompt information about a new survey to create
|
||||||
|
Future<NewSurvey> showNewSurveyDialog(
|
||||||
|
{@required BuildContext context, NewSurvey initialSurvey}) async {
|
||||||
|
return await showDialog<NewSurvey>(
|
||||||
|
context: context,
|
||||||
|
builder: (c) => _SurveyDialog(
|
||||||
|
initialSurvey: initialSurvey,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SurveyDialog extends StatefulWidget {
|
||||||
|
final NewSurvey initialSurvey;
|
||||||
|
|
||||||
|
const _SurveyDialog({Key key, this.initialSurvey}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
__SurveyDialogState createState() => __SurveyDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class __SurveyDialogState extends State<_SurveyDialog> {
|
||||||
|
TextEditingController _questionController;
|
||||||
|
final _choiceController = TextEditingController();
|
||||||
|
var _choices = Set<String>();
|
||||||
|
|
||||||
|
bool get canConfirm =>
|
||||||
|
_questionController.text.length > 2 && _choices.length > 1;
|
||||||
|
|
||||||
|
NewSurvey get newSurvey =>
|
||||||
|
NewSurvey(question: _questionController.text, answers: _choices);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_questionController = TextEditingController(
|
||||||
|
text: widget.initialSurvey == null ? "" : widget.initialSurvey.question,
|
||||||
|
);
|
||||||
|
if (widget.initialSurvey != null) _choices = widget.initialSurvey.answers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text(tr("New survey")),
|
||||||
|
content: _buildBody(),
|
||||||
|
actions: <Widget>[
|
||||||
|
// Cancel
|
||||||
|
MaterialButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text(tr("Cancel").toUpperCase()),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Confirm
|
||||||
|
MaterialButton(
|
||||||
|
onPressed:
|
||||||
|
canConfirm ? () => Navigator.of(context).pop(newSurvey) : null,
|
||||||
|
child: Text(tr("Confirm").toUpperCase()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildBody() {
|
||||||
|
return ConstrainedBox(
|
||||||
|
constraints:
|
||||||
|
BoxConstraints(maxHeight: MediaQuery.of(context).size.height - 50),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: <Widget>[
|
||||||
|
// Survey question
|
||||||
|
TextField(
|
||||||
|
controller: _questionController,
|
||||||
|
onChanged: (s) => setState(() {}),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
alignLabelWithHint: true, labelText: tr("Question")),
|
||||||
|
),
|
||||||
|
|
||||||
|
Container(height: 30),
|
||||||
|
Text(tr("Current choices:")),
|
||||||
|
_buildCurrentChoices(),
|
||||||
|
|
||||||
|
Container(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
|
||||||
|
// Add choice form
|
||||||
|
TextField(
|
||||||
|
controller: _choiceController,
|
||||||
|
onChanged: (s) => setState(() {}),
|
||||||
|
onSubmitted: (s) => _addChoice(),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: tr("New choice..."),
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
icon: Icon(Icons.add),
|
||||||
|
onPressed: () => _choiceController.text.length > 0
|
||||||
|
? _addChoice()
|
||||||
|
: null,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildCurrentChoices() {
|
||||||
|
if (_choices.length == 0) return Text(tr("No choice yet."));
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: _choices
|
||||||
|
.map((f) => ListTile(
|
||||||
|
title: Text(f),
|
||||||
|
dense: true,
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: Icon(Icons.delete),
|
||||||
|
iconSize: 15,
|
||||||
|
onPressed: () => setState(() => _choices.remove(f)),
|
||||||
|
)))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _addChoice() {
|
||||||
|
if (_choiceController.text.length == 0) return;
|
||||||
|
setState(() {
|
||||||
|
_choices.add(_choiceController.text);
|
||||||
|
_choiceController.text = "";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import 'package:comunic/enums/post_target.dart';
|
|||||||
import 'package:comunic/enums/post_visibility_level.dart';
|
import 'package:comunic/enums/post_visibility_level.dart';
|
||||||
import 'package:comunic/helpers/posts_helper.dart';
|
import 'package:comunic/helpers/posts_helper.dart';
|
||||||
import 'package:comunic/models/new_post.dart';
|
import 'package:comunic/models/new_post.dart';
|
||||||
|
import 'package:comunic/ui/dialogs/new_survey_dialog.dart';
|
||||||
import 'package:comunic/utils/files_utils.dart';
|
import 'package:comunic/utils/files_utils.dart';
|
||||||
import 'package:comunic/utils/intl_utils.dart';
|
import 'package:comunic/utils/intl_utils.dart';
|
||||||
import 'package:comunic/utils/post_utils.dart';
|
import 'package:comunic/utils/post_utils.dart';
|
||||||
@ -50,6 +51,7 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
|
|||||||
File _postImage;
|
File _postImage;
|
||||||
List<int> _postPDF;
|
List<int> _postPDF;
|
||||||
DateTime _timeEnd;
|
DateTime _timeEnd;
|
||||||
|
NewSurvey _postSurvey;
|
||||||
|
|
||||||
bool get hasImage => _postImage != null;
|
bool get hasImage => _postImage != null;
|
||||||
|
|
||||||
@ -57,6 +59,8 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
|
|||||||
|
|
||||||
bool get hasTimeEnd => _timeEnd != null;
|
bool get hasTimeEnd => _timeEnd != null;
|
||||||
|
|
||||||
|
bool get hasSurvey => _postSurvey != null;
|
||||||
|
|
||||||
bool get canSubmitForm =>
|
bool get canSubmitForm =>
|
||||||
!_isCreating && _postTextController.text.length > 5 ||
|
!_isCreating && _postTextController.text.length > 5 ||
|
||||||
postKind != PostKind.TEXT;
|
postKind != PostKind.TEXT;
|
||||||
@ -68,6 +72,8 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
|
|||||||
return PostKind.PDF;
|
return PostKind.PDF;
|
||||||
else if (hasTimeEnd)
|
else if (hasTimeEnd)
|
||||||
return PostKind.COUNTDOWN;
|
return PostKind.COUNTDOWN;
|
||||||
|
else if (hasSurvey)
|
||||||
|
return PostKind.SURVEY;
|
||||||
else
|
else
|
||||||
return PostKind.TEXT;
|
return PostKind.TEXT;
|
||||||
}
|
}
|
||||||
@ -132,6 +138,13 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
|
|||||||
selected: postKind == PostKind.COUNTDOWN,
|
selected: postKind == PostKind.COUNTDOWN,
|
||||||
onTap: _pickCountdownTime,
|
onTap: _pickCountdownTime,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// Add survey
|
||||||
|
_PostOptionWidget(
|
||||||
|
icon: Icons.insert_chart,
|
||||||
|
selected: postKind == PostKind.SURVEY,
|
||||||
|
onTap: _pickSurvey,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -192,6 +205,7 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
|
|||||||
_postImage = null;
|
_postImage = null;
|
||||||
_postPDF = null;
|
_postPDF = null;
|
||||||
_timeEnd = null;
|
_timeEnd = null;
|
||||||
|
_postSurvey = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,6 +276,19 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pick a new survey for this post
|
||||||
|
Future<void> _pickSurvey() async {
|
||||||
|
final newSurvey =
|
||||||
|
await showNewSurveyDialog(context: context, initialSurvey: _postSurvey);
|
||||||
|
|
||||||
|
if (newSurvey == null) return;
|
||||||
|
|
||||||
|
_resetPostSelection();
|
||||||
|
setState(() {
|
||||||
|
_postSurvey = newSurvey;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// Submit new post
|
/// Submit new post
|
||||||
Future<void> _submitForm() async {
|
Future<void> _submitForm() async {
|
||||||
if (!canSubmitForm)
|
if (!canSubmitForm)
|
||||||
@ -271,15 +298,15 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await _postHelper.createPost(NewPost(
|
await _postHelper.createPost(NewPost(
|
||||||
target: widget.postTarget,
|
target: widget.postTarget,
|
||||||
targetID: widget.targetID,
|
targetID: widget.targetID,
|
||||||
visibility: _postVisibilityLevel,
|
visibility: _postVisibilityLevel,
|
||||||
content: _postTextController.text,
|
content: _postTextController.text,
|
||||||
kind: postKind,
|
kind: postKind,
|
||||||
image: _postImage,
|
image: _postImage,
|
||||||
pdf: _postPDF,
|
pdf: _postPDF,
|
||||||
timeEnd: _timeEnd,
|
timeEnd: _timeEnd,
|
||||||
));
|
survey: _postSurvey));
|
||||||
setState(() => _isCreating = false);
|
setState(() => _isCreating = false);
|
||||||
|
|
||||||
showSimpleSnack(context, tr("The post has been successfully created!"));
|
showSimpleSnack(context, tr("The post has been successfully created!"));
|
||||||
|
Loading…
Reference in New Issue
Block a user