diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/arrays/PostsList.java b/app/src/main/java/org/communiquons/android/comunic/client/data/arrays/PostsList.java index 4e46123..25289d9 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/data/arrays/PostsList.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/data/arrays/PostsList.java @@ -71,6 +71,23 @@ public class PostsList extends ArrayList { } + /** + * Search a post by ID in the list + * + * Warning ! The post MUST be in the list else an exception will be thrown + * + * @param id The ID of the post to find + * @return Information about the post + */ + public Post find(int id) { + for (Post post : this){ + if(post.getId() == id) + return post; + } + + throw new AssertionError(); + } + /** * Get IDs of the related groups * diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/arrays/SurveyChoicesList.java b/app/src/main/java/org/communiquons/android/comunic/client/data/arrays/SurveyChoicesList.java new file mode 100644 index 0000000..c005ec3 --- /dev/null +++ b/app/src/main/java/org/communiquons/android/comunic/client/data/arrays/SurveyChoicesList.java @@ -0,0 +1,28 @@ +package org.communiquons.android.comunic.client.data.arrays; + +import org.communiquons.android.comunic.client.data.models.SurveyChoice; + +import java.util.ArrayList; + +/** + * Handles a list of SurveyChoicesList + * + * @author Pierre HUBERT + */ +public class SurveyChoicesList extends ArrayList { + + /** + * Find a choice specified by its ID in the list + * + * @param id The ID of the choice to find + * @return Matching choice + */ + public SurveyChoice find(int id) { + + for(SurveyChoice choice : this) + if(choice.getChoiceID() == id) + return choice; + + throw new AssertionError(); + } +} diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/enums/PostTypes.java b/app/src/main/java/org/communiquons/android/comunic/client/data/enums/PostTypes.java index 5d9f4ef..79e4d81 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/data/enums/PostTypes.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/data/enums/PostTypes.java @@ -39,6 +39,11 @@ public enum PostTypes { */ COUNTDOWN, + /** + * Survey + */ + SURVEY, + /** * Unknown type */ diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/helpers/PostsHelper.java b/app/src/main/java/org/communiquons/android/comunic/client/data/helpers/PostsHelper.java index 5b40b7b..a836e90 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/data/helpers/PostsHelper.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/data/helpers/PostsHelper.java @@ -4,17 +4,17 @@ import android.content.Context; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import org.communiquons.android.comunic.client.data.arrays.PostsList; +import org.communiquons.android.comunic.client.data.enums.PageType; +import org.communiquons.android.comunic.client.data.enums.PostTypes; +import org.communiquons.android.comunic.client.data.enums.PostUserAccess; +import org.communiquons.android.comunic.client.data.enums.PostVisibilityLevels; import org.communiquons.android.comunic.client.data.models.APIFileRequest; import org.communiquons.android.comunic.client.data.models.APIPostFile; import org.communiquons.android.comunic.client.data.models.APIRequest; import org.communiquons.android.comunic.client.data.models.APIResponse; import org.communiquons.android.comunic.client.data.models.CreatePost; -import org.communiquons.android.comunic.client.data.enums.PageType; import org.communiquons.android.comunic.client.data.models.Post; -import org.communiquons.android.comunic.client.data.enums.PostTypes; -import org.communiquons.android.comunic.client.data.enums.PostUserAccess; -import org.communiquons.android.comunic.client.data.enums.PostVisibilityLevels; -import org.communiquons.android.comunic.client.data.arrays.PostsList; import org.communiquons.android.comunic.client.data.models.WebLink; import org.json.JSONArray; import org.json.JSONException; @@ -412,6 +412,10 @@ public class PostsHelper { if(!json.isNull("time_end")) post.setTime_end(json.getInt("time_end")); + //Get information about survey if required + if(post.getType() == PostTypes.SURVEY) + post.setSurvey(SurveyHelper.APIToSurvey(json.getJSONObject("data_survey"))); + return post; } @@ -469,6 +473,9 @@ public class PostsHelper { case "countdown": return PostTypes.COUNTDOWN; + case "survey": + return PostTypes.SURVEY; + default: return PostTypes.UNKNOWN; diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/helpers/SurveyHelper.java b/app/src/main/java/org/communiquons/android/comunic/client/data/helpers/SurveyHelper.java new file mode 100644 index 0000000..21a24ce --- /dev/null +++ b/app/src/main/java/org/communiquons/android/comunic/client/data/helpers/SurveyHelper.java @@ -0,0 +1,83 @@ +package org.communiquons.android.comunic.client.data.helpers; + +import android.content.Context; + +import org.communiquons.android.comunic.client.data.models.APIRequest; +import org.communiquons.android.comunic.client.data.models.APIResponse; +import org.communiquons.android.comunic.client.data.models.Survey; +import org.communiquons.android.comunic.client.data.models.SurveyChoice; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Iterator; + +/** + * Survey helper + * + * @author Pierre HUBERT + */ +public class SurveyHelper extends BaseHelper { + + public SurveyHelper(Context context) { + super(context); + } + + /** + * Cancel the response to a survey + * + * @param postID The ID of the target post + * @return TRUE in case of success / FALSE else + */ + public boolean cancelResponse(int postID){ + APIRequest request = new APIRequest(getContext(), "surveys/cancel_response"); + request.addInt("postID", postID); + + try { + return new APIRequestHelper().exec(request).getResponse_code() == 200; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * Turn an API JSON object into a Survey + * + * @param object The object to parse + * @return Generated Survey + * @throws JSONException In case of failure + */ + public static Survey APIToSurvey(JSONObject object) throws JSONException { + Survey survey = new Survey(); + survey.setId(object.getInt("ID")); + survey.setUserID(object.getInt("userID")); + survey.setPostID(object.getInt("postID")); + survey.setCreate_time(object.getInt("creation_time")); + survey.setQuestion(object.getString("question")); + survey.setUser_choice(object.getInt("user_choice")); + + JSONObject choicesObject = object.getJSONObject("choices"); + for (Iterator it = choicesObject.keys(); it.hasNext(); ) { + String key = it.next(); + survey.addChoice(APIToSurveyChoice(choicesObject.getJSONObject(key))); + } + + return survey; + } + + + /** + * Turn an API JSON object into a SurveyChoice object + * + * @param object The object to convert + * @return Generated SurveyChoice object + * @throws JSONException in case of failure + */ + private static SurveyChoice APIToSurveyChoice(JSONObject object) throws JSONException { + SurveyChoice surveyChoice = new SurveyChoice(); + surveyChoice.setChoiceID(object.getInt("choiceID")); + surveyChoice.setName(object.getString("name")); + surveyChoice.setResponses(object.getInt("responses")); + return surveyChoice; + } +} diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/models/Post.java b/app/src/main/java/org/communiquons/android/comunic/client/data/models/Post.java index bc43b8e..c88b924 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/data/models/Post.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/data/models/Post.java @@ -52,6 +52,9 @@ public class Post { //Countdown timer private int time_end; + //Survey + private Survey survey; + //Set and get the ID of the post public void setId(int id) { @@ -240,5 +243,17 @@ public class Post { public void setTime_end(int time_end) { this.time_end = time_end; } + + public Survey getSurvey() { + return survey; + } + + public boolean hasSurvey(){ + return this.survey != null; + } + + public void setSurvey(Survey survey) { + this.survey = survey; + } } diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/models/Survey.java b/app/src/main/java/org/communiquons/android/comunic/client/data/models/Survey.java new file mode 100644 index 0000000..daf9240 --- /dev/null +++ b/app/src/main/java/org/communiquons/android/comunic/client/data/models/Survey.java @@ -0,0 +1,88 @@ +package org.communiquons.android.comunic.client.data.models; + +import org.communiquons.android.comunic.client.data.arrays.SurveyChoicesList; + +import java.util.ArrayList; + +/** + * Base survey object + * + * @author Pierre HUBERT + */ +public class Survey { + + //Private fields + private int id; + private int userID; + private int postID; + private int create_time; + private String question; + private int user_choice; + private SurveyChoicesList choices = new SurveyChoicesList(); + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getUserID() { + return userID; + } + + public void setUserID(int userID) { + this.userID = userID; + } + + public int getPostID() { + return postID; + } + + public void setPostID(int postID) { + this.postID = postID; + } + + public int getCreate_time() { + return create_time; + } + + public void setCreate_time(int create_time) { + this.create_time = create_time; + } + + public String getQuestion() { + return question; + } + + public void setQuestion(String question) { + this.question = question; + } + + public int getUser_choice() { + return user_choice; + } + + public boolean hasUserResponded(){ + return user_choice > 0; + } + + public void setUser_choice(int user_choice) { + this.user_choice = user_choice; + } + + public SurveyChoicesList getChoices() { + return choices; + } + + public void addChoice(SurveyChoice choice){ + if(this.choices == null) + this.choices = new SurveyChoicesList(); + choices.add(choice); + } + + public void setChoices(SurveyChoicesList choices) { + this.choices = choices; + } +} diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/models/SurveyChoice.java b/app/src/main/java/org/communiquons/android/comunic/client/data/models/SurveyChoice.java new file mode 100644 index 0000000..8cf3707 --- /dev/null +++ b/app/src/main/java/org/communiquons/android/comunic/client/data/models/SurveyChoice.java @@ -0,0 +1,47 @@ +package org.communiquons.android.comunic.client.data.models; + +/** + * Survey choice base model + * + * @author Pierre HUBERT + */ +public class SurveyChoice { + + //Private field + private int choiceID; + private String name; + private int responses; + + + public int getChoiceID() { + return choiceID; + } + + public void setChoiceID(int choiceID) { + this.choiceID = choiceID; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getResponses() { + return responses; + } + + public void addOneResponse(){ + responses++; + } + + public void removeOneResponse(){ + responses--; + } + + public void setResponses(int responses) { + this.responses = responses; + } +} diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/PostsAdapter.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/PostsAdapter.java index 2b00566..3f8d41a 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/PostsAdapter.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/PostsAdapter.java @@ -30,6 +30,7 @@ import org.communiquons.android.comunic.client.ui.views.EnlargeableWebImageView; import org.communiquons.android.comunic.client.ui.views.LikeButtonView; import org.communiquons.android.comunic.client.ui.views.MovieView; import org.communiquons.android.comunic.client.ui.views.PDFLinkButtonView; +import org.communiquons.android.comunic.client.ui.views.SurveyView; import org.communiquons.android.comunic.client.ui.views.WebLinkView; import org.communiquons.android.comunic.client.ui.views.WebUserAccountImage; @@ -58,6 +59,7 @@ public class PostsAdapter extends BaseRecyclerViewAdapter { private static final int VIEW_TYPE_POST_PDF = 3; private static final int VIEW_TYPE_POST_WEBLINK = 4; private static final int VIEW_TYPE_POST_COUNTDOWN = 5; + private static final int VIEW_TYPE_POST_SURVEY = 6; /** * Posts list @@ -123,6 +125,9 @@ public class PostsAdapter extends BaseRecyclerViewAdapter { case COUNTDOWN: return VIEW_TYPE_POST_COUNTDOWN; + case SURVEY: + return VIEW_TYPE_POST_SURVEY; + case TEXT: default: return VIEW_TYPE_POST_TEXT; @@ -152,6 +157,9 @@ public class PostsAdapter extends BaseRecyclerViewAdapter { case VIEW_TYPE_POST_COUNTDOWN: return new CountdownPostHolder(view); + case VIEW_TYPE_POST_SURVEY: + return new SurveyPostHolder(view); + default: return new TextPostHolder(view); } @@ -510,4 +518,29 @@ public class PostsAdapter extends BaseRecyclerViewAdapter { mCountDownView.setTime_end(getPost(position).getTime_end()); } } + + /** + * Survey post holder + */ + private class SurveyPostHolder extends TextPostHolder { + + private SurveyView mSurveyView; + + SurveyPostHolder(@NonNull View itemView) { + super(itemView); + + mSurveyView = new SurveyView(getContext()); + mSurveyView.setOnSurveyUpdateListener(mListener); + getAdditionalViewsLayout().addView(mSurveyView, new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT)); + } + + @Override + void bind(int position) { + super.bind(position); + + mSurveyView.setSurvey(getPost(position).getSurvey()); + } + } } diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/asynctasks/CancelSurveyResponseTask.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/asynctasks/CancelSurveyResponseTask.java new file mode 100644 index 0000000..a64abda --- /dev/null +++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/asynctasks/CancelSurveyResponseTask.java @@ -0,0 +1,21 @@ +package org.communiquons.android.comunic.client.ui.asynctasks; + +import android.content.Context; + +import org.communiquons.android.comunic.client.data.helpers.SurveyHelper; + +/** + * Cancel the response to a survey + * + * @author Pierre HUBERT + */ +public class CancelSurveyResponseTask extends SafeAsyncTask { + public CancelSurveyResponseTask(Context context) { + super(context); + } + + @Override + protected Boolean doInBackground(Integer... integers) { + return new SurveyHelper(getContext()).cancelResponse(integers[0]); + } +} diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/fragments/AbstractPostsListFragment.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/fragments/AbstractPostsListFragment.java index 71dbf14..302d13b 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/ui/fragments/AbstractPostsListFragment.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/fragments/AbstractPostsListFragment.java @@ -34,10 +34,14 @@ import org.communiquons.android.comunic.client.data.helpers.LikesHelper; import org.communiquons.android.comunic.client.data.helpers.PostsHelper; import org.communiquons.android.comunic.client.data.models.Comment; import org.communiquons.android.comunic.client.data.models.Post; +import org.communiquons.android.comunic.client.data.models.Survey; +import org.communiquons.android.comunic.client.data.models.SurveyChoice; import org.communiquons.android.comunic.client.data.models.UserInfo; import org.communiquons.android.comunic.client.data.utils.AccountUtils; import org.communiquons.android.comunic.client.data.utils.StringsUtils; import org.communiquons.android.comunic.client.ui.adapters.PostsAdapter; +import org.communiquons.android.comunic.client.ui.asynctasks.CancelSurveyResponseTask; +import org.communiquons.android.comunic.client.ui.asynctasks.SafeAsyncTask; import org.communiquons.android.comunic.client.ui.listeners.OnScrollChangeDetectListener; import org.communiquons.android.comunic.client.ui.listeners.onPostUpdateListener; import org.communiquons.android.comunic.client.ui.views.EditCommentContentView; @@ -913,4 +917,48 @@ public abstract class AbstractPostsListFragment extends AbstractFragment return super.onContextItemSelected(item); } + + @Override + public void onCancelSurveyResponse(Survey survey) { + + final int postID = survey.getPostID(); + + getTasksManager().unsetSpecificTasks(CancelSurveyResponseTask.class); + CancelSurveyResponseTask cancelSurveyResponseTask = + new CancelSurveyResponseTask(getActivity()); + cancelSurveyResponseTask.setOnPostExecuteListener(new SafeAsyncTask.OnPostExecuteListener() { + @Override + public void OnPostExecute(Boolean success) { + delete_callback(postID, success); + } + }); + cancelSurveyResponseTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, survey.getPostID()); + getTasksManager().addTask(cancelSurveyResponseTask); + } + + /** + * Delete survey callback + * + * @param postID The ID of the related post + * @param success TRUE in case of success / FALSE else + */ + private void delete_callback(int postID, boolean success){ + + //Check for failure + if(!success){ + Toast.makeText(getActivity(), R.string.err_cancel_response, Toast.LENGTH_SHORT).show(); + return; + } + + Survey survey = getPostsList().find(postID).getSurvey(); + survey.getChoices().find(survey.getUser_choice()).removeOneResponse(); + survey.setUser_choice(0); + + mPostsAdapter.notifyDataSetChanged(); + } + + @Override + public void onRespondToSurvey(Survey survey, int choiceID) { + + } } diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/listeners/OnSurveyUpdateListener.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/listeners/OnSurveyUpdateListener.java new file mode 100644 index 0000000..f82067d --- /dev/null +++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/listeners/OnSurveyUpdateListener.java @@ -0,0 +1,26 @@ +package org.communiquons.android.comunic.client.ui.listeners; + +import org.communiquons.android.comunic.client.data.models.Survey; + +/** + * Actions done when there is the need to perform an update on a survey + * + * @author Pierre HUBERT + */ +public interface OnSurveyUpdateListener { + + /** + * This method is called when the user requests to cancel the response to a survey + * + * @param survey The target survey + */ + void onCancelSurveyResponse(Survey survey); + + /** + * This method is called when the user want to respond to survey + * + * @param survey The target survey + * @param choiceID Selected choice by the user + */ + void onRespondToSurvey(Survey survey, int choiceID); +} diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/listeners/onPostUpdateListener.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/listeners/onPostUpdateListener.java index ae9450f..a9b2fc6 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/ui/listeners/onPostUpdateListener.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/listeners/onPostUpdateListener.java @@ -12,7 +12,7 @@ import org.communiquons.android.comunic.client.ui.views.EditCommentContentView; * * @author Pierre HUBERT */ -public interface onPostUpdateListener { +public interface onPostUpdateListener extends OnSurveyUpdateListener { /** * This method is called when a comment creation request is made diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/views/SurveyView.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/views/SurveyView.java new file mode 100644 index 0000000..c898f17 --- /dev/null +++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/views/SurveyView.java @@ -0,0 +1,158 @@ +package org.communiquons.android.comunic.client.ui.views; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.constraint.ConstraintLayout; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; + +import org.communiquons.android.comunic.client.R; +import org.communiquons.android.comunic.client.data.models.Survey; +import org.communiquons.android.comunic.client.data.models.SurveyChoice; +import org.communiquons.android.comunic.client.ui.listeners.OnSurveyUpdateListener; +import org.communiquons.android.comunic.client.ui.utils.UiUtils; + +public class SurveyView extends BaseFrameLayoutView implements View.OnClickListener { + + /** + * Current survey + */ + private Survey mSurvey; + + /** + * Update listener + */ + private OnSurveyUpdateListener mOnSurveyUpdateListener; + + /** + * Views + */ + private TextView mQuestion; + private LinearLayout mChoicesList; + private ConstraintLayout mCancelSurveyResponseForm; + private TextView mSelectedChoiceView; + private Button mCancelButton; + private ConstraintLayout mSendResponseForm; + private Spinner mResponsesSpinner; + private Button mResponseButton; + + + public SurveyView(@NonNull Context context) { + this(context, null); + } + + public SurveyView(@NonNull Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public SurveyView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + View view = inflate(getContext(), R.layout.view_survey, this); + mQuestion = view.findViewById(R.id.question); + mCancelSurveyResponseForm = view.findViewById(R.id.cancelSurveyResponseForm); + + mChoicesList = view.findViewById(R.id.choicesTarget); + mSelectedChoiceView = view.findViewById(R.id.selectedChoiceView); + mCancelButton = view.findViewById(R.id.cancelButton); + + mSendResponseForm = view.findViewById(R.id.sendResponseForm); + mResponsesSpinner = view.findViewById(R.id.responsesSpinner); + mResponseButton = view.findViewById(R.id.respondButton); + + mCancelButton.setOnClickListener(this); + mResponseButton.setOnClickListener(this); + } + + /** + * Set the survey updates listener + * + * @param onSurveyUpdateListener The new listener + */ + public void setOnSurveyUpdateListener(@Nullable OnSurveyUpdateListener onSurveyUpdateListener) { + this.mOnSurveyUpdateListener = onSurveyUpdateListener; + } + + /** + * Change the current survey + * + * @param survey The new survey to display + */ + public void setSurvey(Survey survey){ + this.mSurvey = survey; + + mChoicesList.removeAllViews(); + + mQuestion.setText(survey.getQuestion()); + + //Process the list of choices + for(SurveyChoice choice : survey.getChoices()){ + + TextView textView = new TextView(getContext()); + textView.setText(UiUtils.getString(getContext(), R.string.survey_choice, + choice.getResponses(), choice.getName())); + mChoicesList.addView(textView, new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + + } + + mCancelSurveyResponseForm.setVisibility(survey.hasUserResponded() ? + View.VISIBLE : View.GONE); + mSendResponseForm.setVisibility(survey.hasUserResponded() ? + View.GONE : View.VISIBLE); + + //Render the right part of the view + if (survey.hasUserResponded()) { + renderCancelResponseForm(); + } else { + renderRespondForm(); + } + } + + /** + * Render cancel response form + */ + private void renderCancelResponseForm(){ + + //Display the choice of the user + mSelectedChoiceView.setText(UiUtils.getString(getContext(), + R.string.survey_your_choice, + mSurvey.getChoices().find(mSurvey.getUser_choice()).getName())); + + + } + + /** + * Render respond form + */ + private void renderRespondForm(){ + + } + + @Override + public void onClick(View v) { + + //Cancel response to survey + if(v.equals(mCancelButton)){ + if(mOnSurveyUpdateListener != null) + mOnSurveyUpdateListener.onCancelSurveyResponse(mSurvey); + } + + //Respond to a survey + if(v.equals(mResponseButton)){ + if(mOnSurveyUpdateListener != null) + mOnSurveyUpdateListener.onRespondToSurvey(mSurvey, -1); + //TODO : implement + } + + } + + +} diff --git a/app/src/main/res/layout/view_survey.xml b/app/src/main/res/layout/view_survey.xml new file mode 100644 index 0000000..1be6948 --- /dev/null +++ b/app/src/main/res/layout/view_survey.xml @@ -0,0 +1,112 @@ + + + + + + + + + +