@ -0,0 +1,45 @@ | |||
package gq.yigit.mycity; | |||
import android.graphics.Bitmap; | |||
import android.graphics.BitmapFactory; | |||
import android.os.AsyncTask; | |||
import android.util.Log; | |||
import java.io.InputStream; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
public class ImageDownload extends AsyncTask<String, Void, Bitmap> { | |||
private List<imageListener> listeners = new ArrayList<>(); | |||
@Override | |||
protected Bitmap doInBackground(String... URL) { | |||
String imageURL = URL[0]; | |||
Log.d("[BOOKMARK]",imageURL); | |||
Bitmap bitmap = null; | |||
try { | |||
// Download Image from URL | |||
InputStream input = new java.net.URL(imageURL).openStream(); | |||
// Decode Bitmap | |||
bitmap = BitmapFactory.decodeStream(input); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
return bitmap; | |||
} | |||
@Override | |||
protected void onPostExecute(Bitmap result) { | |||
for (imageListener hl : listeners) | |||
hl.imageDownloaded(result); | |||
} | |||
public void addListener(imageListener toAdd) { | |||
listeners.add(toAdd); | |||
} | |||
} |
@ -1,4 +0,0 @@ | |||
package gq.yigit.mycity; | |||
public class VotesActivity { | |||
} |
@ -0,0 +1,7 @@ | |||
package gq.yigit.mycity; | |||
import android.graphics.Bitmap; | |||
public interface imageListener { | |||
public void imageDownloaded(Bitmap img); | |||
} |
@ -0,0 +1,77 @@ | |||
package gq.yigit.mycity.vote; | |||
import android.support.v7.widget.RecyclerView; | |||
import android.util.Log; | |||
import android.view.LayoutInflater; | |||
import android.view.View; | |||
import android.view.ViewGroup; | |||
import android.widget.ImageView; | |||
import android.widget.TextView; | |||
import gq.yigit.mycity.R; | |||
import gq.yigit.mycity.vote.VotesFragment.OnListFragmentInteractionListener; | |||
import gq.yigit.mycity.vote.VotesContent.VoteItem; | |||
import java.util.List; | |||
public class MyVotesRecyclerViewAdapter extends RecyclerView.Adapter<MyVotesRecyclerViewAdapter.ViewHolder> { | |||
private final List<VoteItem> mValues; | |||
private final OnListFragmentInteractionListener mListener; | |||
public MyVotesRecyclerViewAdapter(List<VoteItem> items, OnListFragmentInteractionListener listener) { | |||
mValues = items; | |||
mListener = listener; | |||
} | |||
@Override | |||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { | |||
View view = LayoutInflater.from(parent.getContext()) | |||
.inflate(R.layout.fragment_votes, parent, false); | |||
return new ViewHolder(view); | |||
} | |||
@Override | |||
public void onBindViewHolder(final ViewHolder holder, int position) { | |||
holder.mItem = mValues.get(position); | |||
holder.mIdView.setText(mValues.get(position).name); | |||
holder.mContentView.setText(mValues.get(position).details); | |||
holder.mImageView.setImageBitmap(mValues.get(position).img); | |||
holder.mView.setOnClickListener(new View.OnClickListener() { | |||
@Override | |||
public void onClick(View v) { | |||
if (null != mListener) { | |||
mListener.onListFragmentInteraction(holder.mItem); | |||
} | |||
} | |||
}); | |||
} | |||
@Override | |||
public int getItemCount() { | |||
return mValues.size(); | |||
} | |||
public class ViewHolder extends RecyclerView.ViewHolder { | |||
public final View mView; | |||
public final TextView mIdView; | |||
public final TextView mContentView; | |||
public final ImageView mImageView; | |||
public VoteItem mItem; | |||
public ViewHolder(View view) { | |||
super(view); | |||
mView = view; | |||
mIdView = (TextView) view.findViewById(R.id.item_number); | |||
mContentView = (TextView) view.findViewById(R.id.content); | |||
mImageView = (ImageView) view.findViewById(R.id.vote_img); | |||
} | |||
@Override | |||
public String toString() { | |||
return super.toString() + " '" + mContentView.getText() + "'"; | |||
} | |||
} | |||
} |
@ -0,0 +1,40 @@ | |||
package gq.yigit.mycity.vote; | |||
import android.graphics.Bitmap; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
public class VotesContent { | |||
public static final List<VoteItem> ITEMS = new ArrayList<VoteItem>(); | |||
public static final Map<String, VoteItem> ITEM_MAP = new HashMap<String, VoteItem>(); | |||
public static void addItem(VoteItem item) { | |||
ITEMS.add(item); | |||
ITEM_MAP.put(item.id, item); | |||
} | |||
public static class VoteItem { | |||
public final String id; | |||
public final String name; | |||
public final String details; | |||
public final Bitmap img; | |||
public VoteItem(String id, String name, String details, Bitmap img) { | |||
this.id = id; | |||
this.name = name; | |||
this.details = details; | |||
this.img = img; | |||
} | |||
@Override | |||
public String toString() { | |||
return name; | |||
} | |||
} | |||
} |
@ -0,0 +1,137 @@ | |||
package gq.yigit.mycity.vote; | |||
import android.content.Context; | |||
import android.graphics.Bitmap; | |||
import android.os.Bundle; | |||
import android.support.v4.app.Fragment; | |||
import android.support.v7.widget.GridLayoutManager; | |||
import android.support.v7.widget.LinearLayoutManager; | |||
import android.support.v7.widget.RecyclerView; | |||
import android.util.Log; | |||
import android.view.LayoutInflater; | |||
import android.view.View; | |||
import android.view.ViewGroup; | |||
import gq.yigit.mycity.*; | |||
import gq.yigit.mycity.vote.VotesContent.VoteItem; | |||
import org.json.JSONArray; | |||
import org.json.JSONObject; | |||
import java.util.HashMap; | |||
public class VotesFragment extends Fragment implements responseListener, imageListener { | |||
private static final String ARG_COLUMN_COUNT = "column-count"; | |||
private int mColumnCount = 1; | |||
private OnListFragmentInteractionListener mListener; | |||
public RecyclerView recyclerView; | |||
public String url; | |||
public int img_count = 0; | |||
public JSONArray votes; | |||
public ImageDownload img_downloader; | |||
public int j = 0; | |||
public VotesFragment() { | |||
} | |||
public static VotesFragment newInstance(int columnCount) { | |||
VotesFragment fragment = new VotesFragment(); | |||
Bundle args = new Bundle(); | |||
args.putInt(ARG_COLUMN_COUNT, columnCount); | |||
fragment.setArguments(args); | |||
return fragment; | |||
} | |||
@Override | |||
public void onCreate(Bundle savedInstanceState) { | |||
super.onCreate(savedInstanceState); | |||
if (getArguments() != null) { | |||
mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT); | |||
} | |||
} | |||
@Override | |||
public View onCreateView(LayoutInflater inflater, ViewGroup container, | |||
Bundle savedInstanceState) { | |||
View view = inflater.inflate(R.layout.fragment_votes_list, container, false); | |||
// Set the adapter | |||
if (view instanceof RecyclerView) { | |||
Context context = view.getContext(); | |||
recyclerView = (RecyclerView) view; | |||
if (mColumnCount <= 1) { | |||
recyclerView.setLayoutManager(new LinearLayoutManager(context)); | |||
} else { | |||
recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount)); | |||
} | |||
FileActions file_manager = new FileActions(); | |||
url = (file_manager.readFromFile(context,"server.config")).trim(); | |||
WebRequest web_manager = new WebRequest(url + "/votings",true,new HashMap<String,String>()); | |||
web_manager.addListener(this); | |||
web_manager.execute(); | |||
} | |||
return view; | |||
} | |||
@Override | |||
public void onAttach(Context context) { | |||
super.onAttach(context); | |||
if (context instanceof OnListFragmentInteractionListener) { | |||
mListener = (OnListFragmentInteractionListener) context; | |||
} else { | |||
throw new RuntimeException(context.toString() | |||
+ " must implement OnListFragmentInteractionListener"); | |||
} | |||
} | |||
@Override | |||
public void onDetach() { | |||
super.onDetach(); | |||
mListener = null; | |||
} | |||
public interface OnListFragmentInteractionListener { | |||
void onListFragmentInteraction(VoteItem item); | |||
} | |||
public void receivedResponse(boolean success, String response){ | |||
if(success) { | |||
try { | |||
votes = new JSONArray(response); | |||
img_downloader = new ImageDownload(); | |||
img_downloader.addListener(this); | |||
img_downloader.execute(url+ ((JSONObject)votes.get(j)).getString("img")); | |||
}catch (Exception e){ | |||
Log.e("[ERROR]:",e.getMessage()); | |||
} | |||
Log.i("[INFO]",VotesContent.ITEMS.toString()); | |||
}else{ | |||
Log.e("[ERROR]:",response); | |||
} | |||
} | |||
public void imageDownloaded(Bitmap img){ | |||
try { | |||
JSONObject vote = (JSONObject) votes.get(j); | |||
vote.put("img",img); | |||
j++; | |||
if(j>votes.length()-1) { | |||
for (int i = 0; i < votes.length(); i++) { | |||
JSONObject poll = (JSONObject) votes.get(i); | |||
VotesContent.addItem(new VoteItem(poll.get("id").toString(), poll.get("name").toString(), poll.get("desc").toString(), (Bitmap) poll.get("img"))); | |||
} | |||
recyclerView.setAdapter(new MyVotesRecyclerViewAdapter(VotesContent.ITEMS, mListener)); | |||
}else{ | |||
img_downloader = new ImageDownload(); | |||
img_downloader.addListener(this); | |||
img_downloader.execute(url+ ((JSONObject)votes.get(j)).getString("img")); | |||
} | |||
} catch (Exception e) { | |||
Log.e("[ERROR]", e.toString()); | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<shape xmlns:android="http://schemas.android.com/apk/res/android" | |||
android:shape="rectangle"> | |||
<corners | |||
android:radius="2dp" | |||
android:topRightRadius="0dp" | |||
android:bottomRightRadius="0dp" | |||
android:bottomLeftRadius="0dp"/> | |||
<stroke | |||
android:width="1dp" | |||
android:color="@android:color/black" /> | |||
</shape> |
@ -0,0 +1,37 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:orientation="horizontal" | |||
android:background="@drawable/vote_style" | |||
android:layout_marginBottom="10dp"> | |||
<ImageView | |||
android:layout_width="150dp" | |||
android:layout_height="50dp" app:srcCompat="@mipmap/ic_launcher" android:id="@+id/vote_img" | |||
android:layout_weight="1"/> | |||
<LinearLayout | |||
android:orientation="vertical" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" android:layout_weight="1"> | |||
<TextView | |||
android:id="@+id/item_number" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:layout_margin="4dp" | |||
android:textAppearance="?attr/textAppearanceListItem" android:textSize="14sp"/> | |||
<LinearLayout | |||
android:orientation="vertical" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" android:layout_weight="1" | |||
android:layout_marginLeft="16dp"> | |||
<TextView | |||
android:id="@+id/content" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:layout_margin="4dp" | |||
android:textAppearance="?attr/textAppearanceListItem" android:textColor="#b5b5b5" | |||
android:textSize="12sp"/> | |||
</LinearLayout> | |||
</LinearLayout> | |||
</LinearLayout> |
@ -0,0 +1,18 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<android.support.v7.widget.RecyclerView | |||
xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:id="@+id/list" | |||
android:name="gq.yigit.mycity.VotesFragment" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:layout_marginLeft="16dp" | |||
android:layout_marginTop="60dp" | |||
android:layout_marginRight="16dp" | |||
app:layoutManager="LinearLayoutManager" | |||
tools:context=".vote.VotesFragment" | |||
tools:listitem="@layout/fragment_votes" | |||
android:divider="@android:color/transparent" | |||
android:dividerHeight="100.0sp" | |||
android:clipChildren="false" android:clipToPadding="false" android:scrollbars="vertical"/> |
@ -1,14 +0,0 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" | |||
android:layout_height="match_parent"> | |||
<TextView | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:text="Bonjour!" | |||
app:layout_constraintBottom_toBottomOf="parent" | |||
app:layout_constraintLeft_toLeftOf="parent" | |||
app:layout_constraintRight_toRightOf="parent" | |||
app:layout_constraintTop_toTopOf="parent"/> | |||
</android.support.constraint.ConstraintLayout> |
@ -1,84 +1,97 @@ | |||
import os | |||
import ssl | |||
import json | |||
from flask import Flask, send_from_directory | |||
from flask_restful import Resource, Api, abort, reqparse | |||
from flask import Flask, send_from_directory, request | |||
from flask_restful import Resource, Api, abort | |||
app = Flask(__name__) | |||
api = Api(app) | |||
parser = reqparse.RequestParser() | |||
parser.add_argument('name', required=True) | |||
parser.add_argument('desc') | |||
parser.add_argument('img') | |||
parser.add_argument('votes', required=True) | |||
with open(os.path.join(app.root_path, 'votings.json'), 'r') as f: | |||
votings = json.load(f) | |||
votings = json.load(f) | |||
class Votings(Resource): | |||
def get(self): | |||
voting = [ | |||
{ | |||
'id' : v['id'], | |||
'name': v['name'], | |||
'desc': v['desc'], | |||
'img' : v['img'] | |||
} | |||
for v in votings | |||
] | |||
return voting | |||
def post(self): | |||
args = parser.parse_args() | |||
voting_id = len(votings) + 1 | |||
voting = { | |||
'id': voting_id, | |||
'name': args['name'], | |||
'desc': args['desc'], | |||
'img' : args['img'], | |||
'votes': [ | |||
{ | |||
'id': k, | |||
'name': vote['name'], | |||
'desc': vote['desc'], | |||
'votes': 0 | |||
} | |||
for k, vote in enumerate(json.loads(args['votes'])) | |||
] | |||
} | |||
votings.append(voting) | |||
with open(os.path.join(app.root_path, 'votings.json'), 'w') as f: | |||
json.dump(votings, f, indent=4) | |||
return voting | |||
def get(self): | |||
voting = [ | |||
{ | |||
'id' : v['id'], | |||
'name': v['name'], | |||
'desc': v['desc'], | |||
'img' : v['img'] | |||
} | |||
for v in votings | |||
] | |||
return voting | |||
def post(self): | |||
""" | |||
Example POST Data: | |||
name=<voting_name>& | |||
desc=<voting_desc>& # OPTIONAL | |||
img=<voting_img>& # OPTIONAL | |||
votes=[ | |||
{ | |||
"name": "<vote_name>", | |||
"desc": "<vote_desc>" # OPTIONAL | |||
}, | |||
(...) | |||
] | |||
""" | |||
args = request.form | |||
voting_id = len(votings) + 1 | |||
voting = { | |||
'id': voting_id, | |||
'name': args['name'], | |||
'desc': args.get('desc'), | |||
'img' : args.get('img'), | |||
'votes': [ | |||
{ | |||
'id' : k, | |||
'name': vote['name'], | |||
'desc': vote.get('desc'), | |||
'votes': 0 | |||
} | |||
for k, vote in enumerate(json.loads(args['votes'])) | |||
] | |||
} | |||
votings.append(voting) | |||
with open(os.path.join(app.root_path, 'votings.json'), 'w') as f: | |||
json.dump(votings, f, indent=4) | |||
return voting | |||
class Voting(Resource): | |||
def get(self, voting_id): | |||
try: | |||
return votings[voting_id - 1] | |||
except: | |||
abort(404, error="Voting {} doesn't exist".format(voting_id)) | |||
def get(self, voting_id): | |||
try: | |||
return votings[voting_id - 1] | |||
except: | |||
abort(404, error="Voting {} doesn't exist".format(voting_id)) | |||
class Vote(Resource): | |||
def get(self, voting_id, vote_id): | |||
votings[voting_id - 1]['votes'][vote_id - 1]['votes'] += 1 | |||
with open(os.path.join(app.root_path, 'votings.json'), 'w') as f: | |||
json.dump(votings, f, indent=4) | |||
return votings[voting_id - 1] | |||
def get(self): | |||
""" | |||
Example URL Query: | |||
/vote?voting_id=<voting_id>&vote_id=<vote_id> | |||
""" | |||
voting_id = int(request.args['voting_id']) | |||
vote_id = int(request.args['vote_id']) | |||
votings[voting_id - 1]['votes'][vote_id - 1]['votes'] += 1 | |||
with open(os.path.join(app.root_path, 'votings.json'), 'w') as f: | |||
json.dump(votings, f, indent=4) | |||
return votings[voting_id - 1] | |||
api.add_resource(Votings, '/votings', '/votings/') | |||
api.add_resource(Voting, '/votings/<int:voting_id>') | |||
api.add_resource(Vote, '/vote/<int:voting_id>/<int:vote_id>') | |||
api.add_resource(Vote, '/vote', '/vote/') | |||
@app.route('/img/<path:path>') | |||
def send_img(path): | |||
return send_from_directory('images', path) | |||
return send_from_directory('images', path) | |||
if __name__ == '__main__': | |||
app.run(host='0.0.0.0', port=5000, debug=True) | |||
app.run(host='0.0.0.0', port=5000) |