From b0463d5f18d54bd881fd89168394f2c4be677360 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Tue, 12 Feb 2019 11:31:05 +0100 Subject: [PATCH 001/101] Make files --- Templates/index.html | 10 ++++++++++ connection.py | 0 data_manager.py | 6 ++++++ server.py | 0 util.py | 0 5 files changed, 16 insertions(+) create mode 100644 Templates/index.html create mode 100644 connection.py create mode 100644 data_manager.py create mode 100644 server.py create mode 100644 util.py diff --git a/Templates/index.html b/Templates/index.html new file mode 100644 index 000000000..dd2e60162 --- /dev/null +++ b/Templates/index.html @@ -0,0 +1,10 @@ + + + + + Inedx + + + + + \ No newline at end of file diff --git a/connection.py b/connection.py new file mode 100644 index 000000000..e69de29bb diff --git a/data_manager.py b/data_manager.py new file mode 100644 index 000000000..b8f6d3d4d --- /dev/null +++ b/data_manager.py @@ -0,0 +1,6 @@ +def collect_qestions(): + pass + + +def collect_answers(): + pass diff --git a/server.py b/server.py new file mode 100644 index 000000000..e69de29bb diff --git a/util.py b/util.py new file mode 100644 index 000000000..e69de29bb From 7b77c7ae98633e52cb61c7c672d4a21d59a9787d Mon Sep 17 00:00:00 2001 From: borosTamas Date: Tue, 12 Feb 2019 14:13:46 +0100 Subject: [PATCH 002/101] index template, collect questions --- Templates/index.html | 10 ---------- data_manager.py | 13 ++++++++++++- server.py | 15 +++++++++++++++ templates/index.html | 23 +++++++++++++++++++++++ 4 files changed, 50 insertions(+), 11 deletions(-) delete mode 100644 Templates/index.html create mode 100644 templates/index.html diff --git a/Templates/index.html b/Templates/index.html deleted file mode 100644 index dd2e60162..000000000 --- a/Templates/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Inedx - - - - - \ No newline at end of file diff --git a/data_manager.py b/data_manager.py index b8f6d3d4d..3b0af8fa7 100644 --- a/data_manager.py +++ b/data_manager.py @@ -1,5 +1,16 @@ +import csv + +DATA_HEADER = ['id','submission_time','view_number','vote_number','title','message','image'] +QUESTIONS = 'sample_data/question.csv' +ANSWERS = 'sample_data/answer.csv' + def collect_qestions(): - pass + with open(QUESTIONS, 'r') as questions: + result = [] + questions_dict = csv.DictReader(questions, fieldnames=DATA_HEADER) + for question in questions_dict: + result.append(question) + return result def collect_answers(): diff --git a/server.py b/server.py index e69de29bb..492c64205 100644 --- a/server.py +++ b/server.py @@ -0,0 +1,15 @@ +from flask import Flask, render_template +import data_manager +app = Flask(__name__) + +@app.route('/') +def render_index(): + questions = data_manager.collect_qestions() + return render_template('index.html', questions=questions) + + +if __name__=="__main__": + app.run( + debug=True, + port=5000 + ) diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 000000000..bdec7697e --- /dev/null +++ b/templates/index.html @@ -0,0 +1,23 @@ + + + + + Index + + +

ASK MATE

+

QUESTIONS:

+ + + {% for question in questions[1:]%} + + + {% endfor %} + + + +
{{question['title']}}
+ + + + \ No newline at end of file From cc6e6bbf78ce8d9ca3277d753c1fffe6d6fa2d90 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Feb 2019 11:34:39 +0100 Subject: [PATCH 003/101] commit before the lunch just for safe --- data_manager.py | 14 ++++++++++---- server.py | 7 ++++++- templates/index.html | 3 ++- templates/question_page.html | 10 ++++++++++ 4 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 templates/question_page.html diff --git a/data_manager.py b/data_manager.py index 3b0af8fa7..58e8a72c6 100644 --- a/data_manager.py +++ b/data_manager.py @@ -1,10 +1,13 @@ import csv +import os -DATA_HEADER = ['id','submission_time','view_number','vote_number','title','message','image'] -QUESTIONS = 'sample_data/question.csv' -ANSWERS = 'sample_data/answer.csv' +DATA_HEADER = ['id', 'submission_time', 'view_number', 'vote_number', 'title', 'message', 'image'] +QUESTIONS = DATA_FILE_PATH = os.getenv( + 'DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'sample_data/question.csv' +ANSWERS = DATA_FILE_PATH = os.getenv('DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'sample_data/answer.csv' -def collect_qestions(): + +def collect_questions(): with open(QUESTIONS, 'r') as questions: result = [] questions_dict = csv.DictReader(questions, fieldnames=DATA_HEADER) @@ -12,6 +15,9 @@ def collect_qestions(): result.append(question) return result +def find_question(id,list_of_questions): + for question in list_of_questions: + pass def collect_answers(): pass diff --git a/server.py b/server.py index 492c64205..d496071d1 100644 --- a/server.py +++ b/server.py @@ -4,9 +4,14 @@ @app.route('/') def render_index(): - questions = data_manager.collect_qestions() + questions = data_manager.collect_questions() return render_template('index.html', questions=questions) +@app.route('/question_page/') +def show_question(id): + question = question_data + return render_template('question_page/', question=question) + if __name__=="__main__": app.run( diff --git a/templates/index.html b/templates/index.html index bdec7697e..282932812 100644 --- a/templates/index.html +++ b/templates/index.html @@ -11,7 +11,8 @@

QUESTIONS:

{% for question in questions[1:]%} - {{question['title']}} + + {{question['title']}} {% endfor %} diff --git a/templates/question_page.html b/templates/question_page.html new file mode 100644 index 000000000..0da448017 --- /dev/null +++ b/templates/question_page.html @@ -0,0 +1,10 @@ + + + + + #question_title + + + + + \ No newline at end of file From 9a0066255216df251b8916c9dba9ed67f7b7dfde Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 13 Feb 2019 11:50:19 +0100 Subject: [PATCH 004/101] =?UTF-8?q?a=C3=AD=C3=ADa=C3=AD=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data_manager.py | 8 +++++++- server.py | 12 ++++++++---- templates/index.html | 3 --- templates/new_answer.html | 11 +++++++++++ 4 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 templates/new_answer.html diff --git a/data_manager.py b/data_manager.py index 58e8a72c6..a1d3a295d 100644 --- a/data_manager.py +++ b/data_manager.py @@ -1,6 +1,7 @@ import csv import os +ANSWERS_HEADER = ['id','submission_time','vote_number','question_id','message,image'] DATA_HEADER = ['id', 'submission_time', 'view_number', 'vote_number', 'title', 'message', 'image'] QUESTIONS = DATA_FILE_PATH = os.getenv( 'DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'sample_data/question.csv' @@ -20,4 +21,9 @@ def find_question(id,list_of_questions): pass def collect_answers(): - pass + with open(ANSWERS, 'r') as answers: + result = [] + answers_dict = csv.DictReader(answers, fieldnames=ANSWERS_HEADER) + for answers in answers_dict: + result.append(answers) + return result diff --git a/server.py b/server.py index d496071d1..1a2740cd4 100644 --- a/server.py +++ b/server.py @@ -7,10 +7,14 @@ def render_index(): questions = data_manager.collect_questions() return render_template('index.html', questions=questions) -@app.route('/question_page/') -def show_question(id): - question = question_data - return render_template('question_page/', question=question) +@app.route('/add-question') +def add_question(): + pass + +@app.route('/question//new-answer') +def post_an_answer(): + pass + if __name__=="__main__": diff --git a/templates/index.html b/templates/index.html index 282932812..f0fa2afd4 100644 --- a/templates/index.html +++ b/templates/index.html @@ -16,9 +16,6 @@

QUESTIONS:

{% endfor %} - - - \ No newline at end of file diff --git a/templates/new_answer.html b/templates/new_answer.html new file mode 100644 index 000000000..885ee5f08 --- /dev/null +++ b/templates/new_answer.html @@ -0,0 +1,11 @@ + + + + + Post an Answer + + +

Post an Answer

+ + + \ No newline at end of file From b2e4550f198f63f3588f15b83a65eafeb351b3b6 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Feb 2019 13:15:59 +0100 Subject: [PATCH 005/101] It works now --- data_manager.py | 7 +++++-- server.py | 5 +++-- templates/index.html | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/data_manager.py b/data_manager.py index 58e8a72c6..a9adb28e2 100644 --- a/data_manager.py +++ b/data_manager.py @@ -15,9 +15,12 @@ def collect_questions(): result.append(question) return result -def find_question(id,list_of_questions): +def find_question(id): + list_of_questions = collect_questions() for question in list_of_questions: - pass + if question['id'] == id: + result = question + return result def collect_answers(): pass diff --git a/server.py b/server.py index d496071d1..187df9e47 100644 --- a/server.py +++ b/server.py @@ -7,10 +7,11 @@ def render_index(): questions = data_manager.collect_questions() return render_template('index.html', questions=questions) + @app.route('/question_page/') def show_question(id): - question = question_data - return render_template('question_page/', question=question) + question = data_manager.find_question(id) + return render_template('question_page.html', question=question) if __name__=="__main__": diff --git a/templates/index.html b/templates/index.html index 282932812..e6fb62fc3 100644 --- a/templates/index.html +++ b/templates/index.html @@ -11,7 +11,7 @@

QUESTIONS:

{% for question in questions[1:]%} - + {{question['title']}} {% endfor %} From 427a940d86612e556bac1400a5ae4e37c4618b34 Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 13 Feb 2019 13:18:49 +0100 Subject: [PATCH 006/101] collect answer --- data_manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_manager.py b/data_manager.py index 2043725be..2184d3d68 100644 --- a/data_manager.py +++ b/data_manager.py @@ -4,8 +4,8 @@ ANSWERS_HEADER = ['id','submission_time','vote_number','question_id','message,image'] DATA_HEADER = ['id', 'submission_time', 'view_number', 'vote_number', 'title', 'message', 'image'] QUESTIONS = DATA_FILE_PATH = os.getenv( - 'DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'sample_data/question.csv' -ANSWERS = DATA_FILE_PATH = os.getenv('DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'sample_data/answer.csv' + 'DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else '/home/levente/Desktop/web/ask mate/ask-mate-python/sample_data/question.csv' +ANSWERS = DATA_FILE_PATH = os.getenv('DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else '/home/levente/Desktop/web/ask mate/ask-mate-python/sample_data/answer.csv' def collect_questions(): From c2f22c59500b3a4d93302fb7a61ce97a31584492 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Feb 2019 13:41:33 +0100 Subject: [PATCH 007/101] question page looks shit but works --- data_manager.py | 1 + templates/question_page.html | 26 ++++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/data_manager.py b/data_manager.py index a9adb28e2..f1a926b73 100644 --- a/data_manager.py +++ b/data_manager.py @@ -20,6 +20,7 @@ def find_question(id): for question in list_of_questions: if question['id'] == id: result = question + print(result["title"]) return result def collect_answers(): diff --git a/templates/question_page.html b/templates/question_page.html index 0da448017..2c55c897c 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -2,9 +2,31 @@ - #question_title + {{question['title']}} - + + + + + + + + + + + + + + + + + + + + + +
IDSubmission Timeview_numbervote_numbertitlemessageimage +
{{question['id']}}{{question['submission_time']}}{{question['view_number']}}{{question['vote_number']}}{{question['title']}}{{question['message']}}{{question['image']}}
\ No newline at end of file From be35d50ef30ff0456197351768157f273bfc898f Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Feb 2019 13:45:47 +0100 Subject: [PATCH 008/101] question page looks bad but its working --- data_manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_manager.py b/data_manager.py index adea882e5..5314e73c9 100644 --- a/data_manager.py +++ b/data_manager.py @@ -4,8 +4,8 @@ ANSWERS_HEADER = ['id','submission_time','vote_number','question_id','message,image'] DATA_HEADER = ['id', 'submission_time', 'view_number', 'vote_number', 'title', 'message', 'image'] QUESTIONS = DATA_FILE_PATH = os.getenv( - 'DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else '/home/levente/Desktop/web/ask mate/ask-mate-python/sample_data/question.csv' -ANSWERS = DATA_FILE_PATH = os.getenv('DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else '/home/levente/Desktop/web/ask mate/ask-mate-python/sample_data/answer.csv' + 'DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'ask-mate-python/sample_data/question.csv' +ANSWERS = DATA_FILE_PATH = os.getenv('DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'ask-mate-python/sample_data/answer.csv' def collect_questions(): From 23b9ae4a4a81db2212e146043f28210f6d9363de Mon Sep 17 00:00:00 2001 From: Zollli Date: Wed, 13 Feb 2019 13:50:12 +0100 Subject: [PATCH 009/101] implement add new question, write to csv in progress --- server.py | 12 +++++++++++- templates/add_question.html | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 templates/add_question.html diff --git a/server.py b/server.py index 187df9e47..c89bad157 100644 --- a/server.py +++ b/server.py @@ -1,4 +1,4 @@ -from flask import Flask, render_template +from flask import Flask, render_template,request import data_manager app = Flask(__name__) @@ -14,6 +14,16 @@ def show_question(id): return render_template('question_page.html', question=question) +@app.route('/add-question',methods=['GET','POST']) +def route_index(): + if request.method == 'POST': + result = request.form.get('question') + result2 = request.form.get('question_name') + print(result) + print(result2) + return render_template('add_question.html') + + if __name__=="__main__": app.run( debug=True, diff --git a/templates/add_question.html b/templates/add_question.html new file mode 100644 index 000000000..3f9f0c44c --- /dev/null +++ b/templates/add_question.html @@ -0,0 +1,19 @@ + + + + + Add New Question + + +

Add New Question

+
+ Question Name:
+
+ Question:
+
+
+ +
+ + + \ No newline at end of file From 5a4794ce18c0b25c2fe9c1cd74ccb77f4b2c26a1 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Feb 2019 13:54:05 +0100 Subject: [PATCH 010/101] question page looks better --- data_manager.py | 5 ++--- templates/question_page.html | 32 +++++++++----------------------- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/data_manager.py b/data_manager.py index 5314e73c9..2043725be 100644 --- a/data_manager.py +++ b/data_manager.py @@ -4,8 +4,8 @@ ANSWERS_HEADER = ['id','submission_time','vote_number','question_id','message,image'] DATA_HEADER = ['id', 'submission_time', 'view_number', 'vote_number', 'title', 'message', 'image'] QUESTIONS = DATA_FILE_PATH = os.getenv( - 'DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'ask-mate-python/sample_data/question.csv' -ANSWERS = DATA_FILE_PATH = os.getenv('DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'ask-mate-python/sample_data/answer.csv' + 'DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'sample_data/question.csv' +ANSWERS = DATA_FILE_PATH = os.getenv('DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'sample_data/answer.csv' def collect_questions(): @@ -21,7 +21,6 @@ def find_question(id): for question in list_of_questions: if question['id'] == id: result = question - print(result["title"]) return result def collect_answers(): diff --git a/templates/question_page.html b/templates/question_page.html index 2c55c897c..84f028a0b 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -5,28 +5,14 @@ {{question['title']}} - - - - - - - - - - - - - - - - - - - - - -
IDSubmission Timeview_numbervote_numbertitlemessageimage -
{{question['id']}}{{question['submission_time']}}{{question['view_number']}}{{question['vote_number']}}{{question['title']}}{{question['message']}}{{question['image']}}
+ + ID :{{question['id']}}
+ Submission Time: {{question['submission_time']}}
+ View Number: {{question['view_number']}}
+ Vote Number: {{question['vote_number']}}
+ Title: {{question['title']}}
+ Message:{{question['message']}}
+ Image:{{question['image']}}
+ \ No newline at end of file From 1666314c034a04afed4f396372223aa7bdcb3797 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Feb 2019 14:49:44 +0100 Subject: [PATCH 011/101] upgradet question page with answers --- data_manager.py | 9 ++++++--- server.py | 3 ++- templates/question_page.html | 19 ++++++++++++------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/data_manager.py b/data_manager.py index 2043725be..7bdaa0091 100644 --- a/data_manager.py +++ b/data_manager.py @@ -1,7 +1,7 @@ import csv import os -ANSWERS_HEADER = ['id','submission_time','vote_number','question_id','message,image'] +ANSWERS_HEADER = ['id','submission_time','vote_number','question_id','message','image'] DATA_HEADER = ['id', 'submission_time', 'view_number', 'vote_number', 'title', 'message', 'image'] QUESTIONS = DATA_FILE_PATH = os.getenv( 'DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'sample_data/question.csv' @@ -23,10 +23,13 @@ def find_question(id): result = question return result -def collect_answers(): +def collect_answers(id): with open(ANSWERS, 'r') as answers: result = [] answers_dict = csv.DictReader(answers, fieldnames=ANSWERS_HEADER) for answers in answers_dict: - result.append(answers) + if answers['question_id'] == id: + result.append(answers) + else: + result = [{'message':'There is no answers yet.'}] return result diff --git a/server.py b/server.py index c89bad157..6ad05cad5 100644 --- a/server.py +++ b/server.py @@ -11,7 +11,8 @@ def render_index(): @app.route('/question_page/') def show_question(id): question = data_manager.find_question(id) - return render_template('question_page.html', question=question) + answers = data_manager.collect_answers(id) + return render_template('question_page.html', question=question, answers=answers) @app.route('/add-question',methods=['GET','POST']) diff --git a/templates/question_page.html b/templates/question_page.html index 84f028a0b..bebc6d0fc 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -6,13 +6,18 @@ - ID :{{question['id']}}
- Submission Time: {{question['submission_time']}}
- View Number: {{question['view_number']}}
- Vote Number: {{question['vote_number']}}
- Title: {{question['title']}}
- Message:{{question['message']}}
- Image:{{question['image']}}
+ID :{{question['id']}}
+Submission Time: {{question['submission_time']}}
+View Number: {{question['view_number']}}
+Vote Number: +Title: {{question['title']}}
+Message:{{question['message']}}
+Image:{{question['image']}}
+ +

Answers:

+{%for answer in answers%} + {{answer['message']}}
+{%endfor%} \ No newline at end of file From f1bcec07cd8a5113bf9617e9fd5aef14318847a9 Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 13 Feb 2019 14:49:47 +0100 Subject: [PATCH 012/101] add answer --- data_manager.py | 24 +++++++++++++++++++++--- server.py | 13 +++++++++++++ templates/new_answer.html | 5 +++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/data_manager.py b/data_manager.py index 2043725be..e7157b391 100644 --- a/data_manager.py +++ b/data_manager.py @@ -1,11 +1,12 @@ import csv import os +import time -ANSWERS_HEADER = ['id','submission_time','vote_number','question_id','message,image'] +ANSWERS_HEADER = ['id','submission_time','vote_number','question_id','message','image'] DATA_HEADER = ['id', 'submission_time', 'view_number', 'vote_number', 'title', 'message', 'image'] QUESTIONS = DATA_FILE_PATH = os.getenv( - 'DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'sample_data/question.csv' -ANSWERS = DATA_FILE_PATH = os.getenv('DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'sample_data/answer.csv' + 'DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else '/home/levente/Desktop/web/ask mate/ask-mate-python/sample_data/question.csv' +ANSWERS = DATA_FILE_PATH = os.getenv('DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else '/home/levente/Desktop/web/ask mate/ask-mate-python/sample_data/answer.csv' def collect_questions(): @@ -16,13 +17,16 @@ def collect_questions(): result.append(question) return result + def find_question(id): list_of_questions = collect_questions() for question in list_of_questions: if question['id'] == id: result = question + print(result["title"]) return result + def collect_answers(): with open(ANSWERS, 'r') as answers: result = [] @@ -30,3 +34,17 @@ def collect_answers(): for answers in answers_dict: result.append(answers) return result + + +def add_answer(form_data): + new_id = collect_answers()[-1]['id'] + if new_id == 'id': + new_id = 1 + else: + new_id = int(new_id) + 1 + submission_time = int(time.time()) + prepared_data = [item for key, item in form_data.items()] + prepared_data = list(str(new_id)+str(submission_time)+str(''))+prepared_data + with open(ANSWERS, 'a', newline='') as csv_file: + writer = csv.writer(csv_file) + writer.writerow(prepared_data) diff --git a/server.py b/server.py index c89bad157..852eca34d 100644 --- a/server.py +++ b/server.py @@ -2,6 +2,8 @@ import data_manager app = Flask(__name__) +saved_data = {} + @app.route('/') def render_index(): questions = data_manager.collect_questions() @@ -14,6 +16,17 @@ def show_question(id): return render_template('question_page.html', question=question) +@app.route('/question_page//new-answer', methods=['GET','POST']) +def post_an_answer(id): + if request.method == 'POST': + saved_data['question_id'] = request.form['question'] + saved_data['message'] = request.form['message'] + saved_data['image'] = request.form['image'] + data_manager.add_answer(saved_data) + return redirect('/question_page/') + return render_template('new_answer.html', question=question) + + @app.route('/add-question',methods=['GET','POST']) def route_index(): if request.method == 'POST': diff --git a/templates/new_answer.html b/templates/new_answer.html index 885ee5f08..6b48c0ed0 100644 --- a/templates/new_answer.html +++ b/templates/new_answer.html @@ -6,6 +6,11 @@

Post an Answer

+Question ID
+{{question['id']}}
+Message
+
+Image
\ No newline at end of file From 1f8f67798032e56b2ccc1058b67e5b49690e2187 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Feb 2019 15:26:31 +0100 Subject: [PATCH 013/101] there is a problem with the file path --- data_manager.py | 23 ++++++++++++++++++++--- templates/question_page.html | 2 ++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/data_manager.py b/data_manager.py index f0d7dfeb9..c98afb493 100644 --- a/data_manager.py +++ b/data_manager.py @@ -5,8 +5,8 @@ ANSWERS_HEADER = ['id','submission_time','vote_number','question_id','message','image'] DATA_HEADER = ['id', 'submission_time', 'view_number', 'vote_number', 'title', 'message', 'image'] QUESTIONS = DATA_FILE_PATH = os.getenv( - 'DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else '/home/levente/Desktop/web/ask mate/ask-mate-python/sample_data/question.csv' -ANSWERS = DATA_FILE_PATH = os.getenv('DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else '/home/levente/Desktop/web/ask mate/ask-mate-python/sample_data/answer.csv' + 'DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'sample_data/question.csv' +ANSWERS = DATA_FILE_PATH = os.getenv('DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else 'sample_data/answer.csv' def collect_questions(): @@ -24,7 +24,7 @@ def find_question(id): result = question return result -def collect_answers(): +def collect_answers(id): with open(ANSWERS, 'r') as answers: result = [] answers_dict = csv.DictReader(answers, fieldnames=ANSWERS_HEADER) @@ -35,6 +35,23 @@ def collect_answers(): result = [{'message':'There is no answers yet.'}] return result +def update_question(question_dict): + with open(QUESTIONS,'r') as old_questions: + old_question_dict = csv.DictReader(old_questions, fieldnames=DATA_HEADER) + temporary_list=[] + for row in old_question_dict: + if row[id] == question_dict[id]: + row = question_dict + temporary_list.append(row) + else: + temporary_list.append(row) + + with open(QUESTIONS,'w') as new_qestions: + new_qestion_dict = csv.DictWriter(new_qestions, fieldnames= DATA_HEADER) + new_qestion_dict.writeheader() + for row in temporary_list[1:]: + new_qestion_dict.writerow(row) + def add_answer(form_data): new_id = collect_answers()[-1]['id'] diff --git a/templates/question_page.html b/templates/question_page.html index bebc6d0fc..73f2842fa 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -14,6 +14,8 @@ Message:{{question['message']}}
Image:{{question['image']}}
+edit question +

Answers:

{%for answer in answers%} From 48d76179ec7f77b9a31e04277397ced3717c72ae Mon Sep 17 00:00:00 2001 From: Zollli Date: Thu, 14 Feb 2019 10:59:30 +0100 Subject: [PATCH 014/101] implement add questions write to file, add questions in index page --- data_manager.py | 9 ++++++++- sample_data/new_questions.csv | 0 server.py | 7 +++---- templates/index.html | 2 ++ 4 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 sample_data/new_questions.csv diff --git a/data_manager.py b/data_manager.py index c98afb493..c075c982f 100644 --- a/data_manager.py +++ b/data_manager.py @@ -64,4 +64,11 @@ def add_answer(form_data): prepared_data = list(str(new_id)+str(submission_time)+str(''))+prepared_data with open(ANSWERS, 'a', newline='') as csv_file: writer = csv.writer(csv_file) - writer.writerow(prepared_data) + + +def csv_questionwriter(csv_file,dictvalue1,dictvalue2): + with open(csv_file, 'a', newline='') as csvfile: + fieldnames = ['question_name', 'question'] + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + writer.writeheader() + writer.writerow({'question_name' : dictvalue1, 'question' : dictvalue2}) \ No newline at end of file diff --git a/sample_data/new_questions.csv b/sample_data/new_questions.csv new file mode 100644 index 000000000..e69de29bb diff --git a/server.py b/server.py index 25a0992d4..4f70cc379 100644 --- a/server.py +++ b/server.py @@ -31,10 +31,9 @@ def post_an_answer(id): @app.route('/add-question',methods=['GET','POST']) def route_index(): if request.method == 'POST': - result = request.form.get('question') - result2 = request.form.get('question_name') - print(result) - print(result2) + question_name = request.form.get('question_name') + question = request.form.get('question') + data_manager.csv_questionwriter('sample_data/new_questions.csv',question_name,question) return render_template('add_question.html') diff --git a/templates/index.html b/templates/index.html index e61c98a36..0bff11951 100644 --- a/templates/index.html +++ b/templates/index.html @@ -6,7 +6,9 @@

ASK MATE

+Add new Question

QUESTIONS:

+ {% for question in questions[1:]%} From 915b2336082fdba6d1ae0c1d829a9b5138c51418 Mon Sep 17 00:00:00 2001 From: LibLev Date: Thu, 14 Feb 2019 12:47:48 +0100 Subject: [PATCH 015/101] dani belenyult --- data_manager.py | 20 +++++++++++--------- server.py | 8 +++++--- templates/new_answer.html | 6 ++++-- templates/question_page.html | 3 +++ 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/data_manager.py b/data_manager.py index f0d7dfeb9..b9fef7734 100644 --- a/data_manager.py +++ b/data_manager.py @@ -2,21 +2,22 @@ import os import time -ANSWERS_HEADER = ['id','submission_time','vote_number','question_id','message','image'] +ANSWERS_HEADER = ['id', 'submission_time', 'vote_number', 'question_id', 'message', 'image'] DATA_HEADER = ['id', 'submission_time', 'view_number', 'vote_number', 'title', 'message', 'image'] -QUESTIONS = DATA_FILE_PATH = os.getenv( - 'DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else '/home/levente/Desktop/web/ask mate/ask-mate-python/sample_data/question.csv' -ANSWERS = DATA_FILE_PATH = os.getenv('DATA_FILE_PATH') if 'DATA_FILE_PATH' in os.environ else '/home/levente/Desktop/web/ask mate/ask-mate-python/sample_data/answer.csv' + +QUESTIONS_FILE_PATH = os.getenv('QUESTIONS_FILE_PATH', 'sample_data/question.csv') +ANSWERS_FILE_PATH = os.getenv('ANSWERS_FILE_PATH', 'sample_data/answer.csv') def collect_questions(): - with open(QUESTIONS, 'r') as questions: + with open(QUESTIONS_FILE_PATH, 'r') as questions: result = [] questions_dict = csv.DictReader(questions, fieldnames=DATA_HEADER) for question in questions_dict: result.append(question) return result + def find_question(id): list_of_questions = collect_questions() for question in list_of_questions: @@ -24,15 +25,16 @@ def find_question(id): result = question return result + def collect_answers(): - with open(ANSWERS, 'r') as answers: + with open(ANSWERS_FILE_PATH, 'r') as answers: result = [] answers_dict = csv.DictReader(answers, fieldnames=ANSWERS_HEADER) for answers in answers_dict: if answers['question_id'] == id: result.append(answers) else: - result = [{'message':'There is no answers yet.'}] + result = [{'message': 'There is no answers yet.'}] return result @@ -44,7 +46,7 @@ def add_answer(form_data): new_id = int(new_id) + 1 submission_time = int(time.time()) prepared_data = [item for key, item in form_data.items()] - prepared_data = list(str(new_id)+str(submission_time)+str(''))+prepared_data - with open(ANSWERS, 'a', newline='') as csv_file: + prepared_data = list(str(new_id) + str(submission_time) + str('')) + prepared_data + with open(ANSWERS_FILE_PATH, 'a', newline='') as csv_file: writer = csv.writer(csv_file) writer.writerow(prepared_data) diff --git a/server.py b/server.py index 25a0992d4..382ce21a0 100644 --- a/server.py +++ b/server.py @@ -1,4 +1,4 @@ -from flask import Flask, render_template,request +from flask import Flask, render_template,request, redirect import data_manager app = Flask(__name__) @@ -13,19 +13,21 @@ def render_index(): @app.route('/question_page/') def show_question(id): question = data_manager.find_question(id) - answers = data_manager.collect_answers(id) + answers = data_manager.collect_answers() return render_template('question_page.html', question=question, answers=answers) @app.route('/question_page//new-answer', methods=['GET','POST']) def post_an_answer(id): + question = data_manager.find_question(id) + answer = data_manager.collect_answers() if request.method == 'POST': saved_data['question_id'] = request.form['question'] saved_data['message'] = request.form['message'] saved_data['image'] = request.form['image'] data_manager.add_answer(saved_data) return redirect('/question_page/') - return render_template('new_answer.html', question=question) + return render_template('new_answer.html', question=question, answer=answer) @app.route('/add-question',methods=['GET','POST']) diff --git a/templates/new_answer.html b/templates/new_answer.html index 6b48c0ed0..44f525004 100644 --- a/templates/new_answer.html +++ b/templates/new_answer.html @@ -6,11 +6,13 @@

Post an Answer

+

-{{question['id']}}
+

-
+

+ \ No newline at end of file diff --git a/templates/question_page.html b/templates/question_page.html index bebc6d0fc..4e3c30a08 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -19,5 +19,8 @@

Answers:

{%for answer in answers%} {{answer['message']}}
{%endfor%} + +Post an Answer + \ No newline at end of file From fb3d9b8fdcf7fa92495fc43a1ac0698b27027b4c Mon Sep 17 00:00:00 2001 From: LibLev Date: Thu, 14 Feb 2019 12:57:25 +0100 Subject: [PATCH 016/101] dani belenyult --- data_manager.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/data_manager.py b/data_manager.py index 0183f1b4a..0c0130b69 100644 --- a/data_manager.py +++ b/data_manager.py @@ -37,7 +37,7 @@ def collect_answers(): return result def update_question(question_dict): - with open(QUESTIONS,'r') as old_questions: + with open(QUESTIONS_FILE_PATH,'r') as old_questions: old_question_dict = csv.DictReader(old_questions, fieldnames=DATA_HEADER) temporary_list=[] for row in old_question_dict: @@ -47,7 +47,7 @@ def update_question(question_dict): else: temporary_list.append(row) - with open(QUESTIONS,'w') as new_qestions: + with open(QUESTIONS_FILE_PATH,'w') as new_qestions: new_qestion_dict = csv.DictWriter(new_qestions, fieldnames= DATA_HEADER) new_qestion_dict.writeheader() for row in temporary_list[1:]: @@ -62,9 +62,11 @@ def add_answer(form_data): new_id = int(new_id) + 1 submission_time = int(time.time()) prepared_data = [item for key, item in form_data.items()] - prepared_data = list(str(new_id) + str(submission_time) + str('')) + prepared_data + prepared_data = list(str(new_id)+str(submission_time)+str(''))+prepared_data with open(ANSWERS_FILE_PATH, 'a', newline='') as csv_file: writer = csv.writer(csv_file) + writer.writerow(prepared_data) + def csv_questionwriter(csv_file,dictvalue1,dictvalue2): From 9e3dfc5537bdce3b5fc93a5ec2377e9afc3ce813 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Thu, 14 Feb 2019 13:04:10 +0100 Subject: [PATCH 017/101] Merge branch 'master' of /home/boros/codecool/web_sql/ask-mate-python with conflicts. --- data_manager.py | 7 +++++-- sample_data/new_questions.csv | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/data_manager.py b/data_manager.py index 0c0130b69..767c243a8 100644 --- a/data_manager.py +++ b/data_manager.py @@ -17,6 +17,7 @@ def collect_questions(): result.append(question) return result + def find_question(id): list_of_questions = collect_questions() for question in list_of_questions: @@ -36,10 +37,12 @@ def collect_answers(): result = [{'message': 'There is no answers yet.'}] return result + def update_question(question_dict): with open(QUESTIONS_FILE_PATH,'r') as old_questions: + with open(QUESTIONS, 'r') as old_questions: old_question_dict = csv.DictReader(old_questions, fieldnames=DATA_HEADER) - temporary_list=[] + temporary_list = [] for row in old_question_dict: if row[id] == question_dict[id]: row = question_dict @@ -74,4 +77,4 @@ def csv_questionwriter(csv_file,dictvalue1,dictvalue2): fieldnames = ['question_name', 'question'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() - writer.writerow({'question_name' : dictvalue1, 'question' : dictvalue2}) \ No newline at end of file + writer.writerow({'question_name' : dictvalue1, 'question' : dictvalue2}) diff --git a/sample_data/new_questions.csv b/sample_data/new_questions.csv index e69de29bb..27b0fc469 100644 --- a/sample_data/new_questions.csv +++ b/sample_data/new_questions.csv @@ -0,0 +1,4 @@ +question_name,question +What is love?,Baby don't hurt me +question_name,question +is this the new file,who knows From 80cb165715be8e7cf2847756952d4f3947069b4e Mon Sep 17 00:00:00 2001 From: Zollli Date: Thu, 14 Feb 2019 13:11:12 +0100 Subject: [PATCH 018/101] implement edit questions --- server.py | 6 ++++++ templates/edit_question.html | 20 ++++++++++++++++++++ templates/question_page.html | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 templates/edit_question.html diff --git a/server.py b/server.py index 4f70cc379..7331bd212 100644 --- a/server.py +++ b/server.py @@ -37,6 +37,12 @@ def route_index(): return render_template('add_question.html') +@app.route('/question_page//edit_question') +def edit_question(id): + question = data_manager.find_question(id) + return render_template('edit_question.html', question=question) + + if __name__=="__main__": app.run( debug=True, diff --git a/templates/edit_question.html b/templates/edit_question.html new file mode 100644 index 000000000..f28dbdbbf --- /dev/null +++ b/templates/edit_question.html @@ -0,0 +1,20 @@ + + + + + Edit Question + + +

Edit Question

+

{{question['message']}}

+
+ Question Name:
+
+ Question:
+
+
+ + + + + diff --git a/templates/question_page.html b/templates/question_page.html index 73f2842fa..2b797b4fb 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -14,7 +14,7 @@ Message:{{question['message']}}
Image:{{question['image']}}
-edit question +edit question

Answers:

From 2257c26f7d2f957efb9fcea52fd3c4d675fcd032 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Thu, 14 Feb 2019 15:06:54 +0100 Subject: [PATCH 019/101] ad question page changed, update question wotking, + submission time --- data_manager.py | 38 ++++++++++++++++++++++------------- sample_data/new_questions.csv | 2 ++ sample_data/question.csv | 10 +++++---- server.py | 28 +++++++++++++++++++++++--- templates/add_question.html | 35 +++++++++++++++++++++++--------- templates/question_page.html | 4 ++-- 6 files changed, 85 insertions(+), 32 deletions(-) diff --git a/data_manager.py b/data_manager.py index 767c243a8..aa75b56c8 100644 --- a/data_manager.py +++ b/data_manager.py @@ -1,6 +1,7 @@ import csv import os import time +from datetime import datetime ANSWERS_HEADER = ['id', 'submission_time', 'vote_number', 'question_id', 'message', 'image'] DATA_HEADER = ['id', 'submission_time', 'view_number', 'vote_number', 'title', 'message', 'image'] @@ -26,32 +27,31 @@ def find_question(id): return result -def collect_answers(): +def collect_answers(id): with open(ANSWERS_FILE_PATH, 'r') as answers: result = [] answers_dict = csv.DictReader(answers, fieldnames=ANSWERS_HEADER) for answers in answers_dict: if answers['question_id'] == id: result.append(answers) - else: - result = [{'message': 'There is no answers yet.'}] + if len(result) < 1: + result = [{'message': 'there is no answer yet'}] return result def update_question(question_dict): - with open(QUESTIONS_FILE_PATH,'r') as old_questions: - with open(QUESTIONS, 'r') as old_questions: + with open(QUESTIONS_FILE_PATH, 'r') as old_questions: old_question_dict = csv.DictReader(old_questions, fieldnames=DATA_HEADER) temporary_list = [] for row in old_question_dict: - if row[id] == question_dict[id]: + if row['id'] == question_dict['id']: row = question_dict temporary_list.append(row) else: temporary_list.append(row) - with open(QUESTIONS_FILE_PATH,'w') as new_qestions: - new_qestion_dict = csv.DictWriter(new_qestions, fieldnames= DATA_HEADER) + with open(QUESTIONS_FILE_PATH, 'w') as new_qestions: + new_qestion_dict = csv.DictWriter(new_qestions, fieldnames=DATA_HEADER) new_qestion_dict.writeheader() for row in temporary_list[1:]: new_qestion_dict.writerow(row) @@ -65,16 +65,26 @@ def add_answer(form_data): new_id = int(new_id) + 1 submission_time = int(time.time()) prepared_data = [item for key, item in form_data.items()] - prepared_data = list(str(new_id)+str(submission_time)+str(''))+prepared_data + prepared_data = list(str(new_id) + str(submission_time) + str('')) + prepared_data with open(ANSWERS_FILE_PATH, 'a', newline='') as csv_file: writer = csv.writer(csv_file) writer.writerow(prepared_data) +def new_id(file_name): + with open(file_name, 'r') as file: + file_read = csv.DictReader(file, fieldnames=DATA_HEADER) + for row in file_read: + new_id = row['id'] + return int(new_id)+1 + -def csv_questionwriter(csv_file,dictvalue1,dictvalue2): +def csv_questionwriter(csv_file, dictvalue1, dictvalue2): with open(csv_file, 'a', newline='') as csvfile: - fieldnames = ['question_name', 'question'] - writer = csv.DictWriter(csvfile, fieldnames=fieldnames) - writer.writeheader() - writer.writerow({'question_name' : dictvalue1, 'question' : dictvalue2}) + writer = csv.DictWriter(csvfile, fieldnames=DATA_HEADER) + question_id = new_id(csv_file) + view_counter = 0 + vote_counter = 0 + submission_time = int(time.time()) + writer.writerow({'id': question_id, 'submission_time': submission_time, 'view_number': view_counter, + 'vote_number': vote_counter, 'title': dictvalue1, 'message': dictvalue2}) diff --git a/sample_data/new_questions.csv b/sample_data/new_questions.csv index 27b0fc469..dd04e5bd2 100644 --- a/sample_data/new_questions.csv +++ b/sample_data/new_questions.csv @@ -2,3 +2,5 @@ question_name,question What is love?,Baby don't hurt me question_name,question is this the new file,who knows +question_name,question +What is love?,baby dont hurt me diff --git a/sample_data/question.csv b/sample_data/question.csv index e65825dc3..891cec674 100644 --- a/sample_data/question.csv +++ b/sample_data/question.csv @@ -1,6 +1,6 @@ id,submission_time,view_number,vote_number,title,message,image -0,1493368154,29,7,"How to make lists in Python?","I am totally new to this, any hints?", -1,1493068124,15,9,"Wordpress loading multiple jQuery Versions","I developed a plugin that uses the jquery booklet plugin (http://builtbywill.com/booklet/#/) this plugin binds a function to $ so I cann call $('.myBook').booklet(); +0,1493368154,29,7,How to make lists in Python?,"I am totally new to this, any hints?", +1,1493068124,15,9,Wordpress loading multiple jQuery Versions,"I developed a plugin that uses the jquery booklet plugin (http://builtbywill.com/booklet/#/) this plugin binds a function to $ so I cann call $('.myBook').booklet(); I could easy managing the loading order with wp_enqueue_script so first I load jquery then I load booklet so everything is fine. @@ -8,7 +8,9 @@ BUT in my theme i also using jquery via webpack so the loading order is now foll jquery booklet -app.js (bundled file with webpack, including jquery)","images/image1.png" -2,1493015432,1364,57,"Drawing canvas with an image picked with Cordova Camera Plugin","I'm getting an image from device and drawing a canvas with filters using Pixi JS. It works all well using computer to get an image. But when I'm on IOS, it throws errors such as cross origin issue, or that I'm trying to use an unknown format. +app.js (bundled file with webpack, including jquery)",images/image1.png +2,1493015432,1364,57,Drawing canvas with an image picked with Cordova Camera Plugin,"I'm getting an image from device and drawing a canvas with filters using Pixi JS. It works all well using computer to get an image. But when I'm on IOS, it throws errors such as cross origin issue, or that I'm trying to use an unknown format. This is the code I'm using to draw the image (that works on web/desktop but not cordova built ios app)", +3,2019-02-14 12:53:10.069187,0,0,What is love?,"Baby don't hurt me, no more", +4,1550149052,0,0,time?,TIME?, diff --git a/server.py b/server.py index c19f016e2..e56b65239 100644 --- a/server.py +++ b/server.py @@ -13,9 +13,28 @@ def render_index(): @app.route('/question_page/') def show_question(id): question = data_manager.find_question(id) - answers = data_manager.collect_answers() + answers = data_manager.collect_answers(id) return render_template('question_page.html', question=question, answers=answers) +@app.route('/question_page//edit') +def edit_question(id): + result = data_manager.find_question(id) + return render_template('add_question.html', result=result) + +@app.route('/rewrite_question', methods=['POST']) +def rewrite_suestion(): + updated_question = { + 'id': request.form.get('id'), + 'submission_time': request.form.get('submission_time'), + 'view_number': request.form.get('view_number'), + 'vote_number': request.form.get('vote_number'), + 'title': request.form.get('title'), + 'message': request.form.get('message'), + 'image': request.form.get('image') + } + data_manager.update_question(updated_question) + return redirect('/') + @app.route('/question_page//new-answer', methods=['GET','POST']) def post_an_answer(id): @@ -32,11 +51,14 @@ def post_an_answer(id): @app.route('/add-question',methods=['GET','POST']) def route_index(): + result = [] if request.method == 'POST': + question_name = request.form.get('question_name') question = request.form.get('question') - data_manager.csv_questionwriter('sample_data/new_questions.csv',question_name,question) - return render_template('add_question.html') + data_manager.csv_questionwriter('sample_data/question.csv',question_name,question) + return redirect('/') + return render_template('add_question.html', result=result) if __name__=="__main__": diff --git a/templates/add_question.html b/templates/add_question.html index 3f9f0c44c..ce95d827b 100644 --- a/templates/add_question.html +++ b/templates/add_question.html @@ -5,15 +5,32 @@ Add New Question -

Add New Question

-
- Question Name:
-
- Question:
-
-
- - +{% if result == [] %} +

Add New Question

+
+ Question Name:
+
+ Question:
+
+
+ + +{% else %} +

Edit Question

+
+ Question Name:
+
+ Question:
+
+
+ + + + + + + {% endif %} + \ No newline at end of file diff --git a/templates/question_page.html b/templates/question_page.html index 75b841af5..eb4c18e42 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -9,12 +9,12 @@ ID :{{question['id']}}
Submission Time: {{question['submission_time']}}
View Number: {{question['view_number']}}
-Vote Number: +Vote Number: {{question['vote_number']}}
Title: {{question['title']}}
Message:{{question['message']}}
Image:{{question['image']}}
-edit question +edit question

Answers:

From 5b7bd87dd5b0a4be92ea49052ea06d6d1b4bb1ce Mon Sep 17 00:00:00 2001 From: LibLev Date: Thu, 14 Feb 2019 16:06:13 +0100 Subject: [PATCH 020/101] add answer is fucked the system --- data_manager.py | 29 ++++++++++++++++++++++------- sample_data/answer.csv | 2 ++ server.py | 12 +++++++----- templates/new_answer.html | 9 +++++---- templates/question_page.html | 6 +++--- 5 files changed, 39 insertions(+), 19 deletions(-) diff --git a/data_manager.py b/data_manager.py index 0c0130b69..d2717da0f 100644 --- a/data_manager.py +++ b/data_manager.py @@ -25,7 +25,7 @@ def find_question(id): return result -def collect_answers(): +def collect_answers(id): with open(ANSWERS_FILE_PATH, 'r') as answers: result = [] answers_dict = csv.DictReader(answers, fieldnames=ANSWERS_HEADER) @@ -54,18 +54,33 @@ def update_question(question_dict): new_qestion_dict.writerow(row) -def add_answer(form_data): - new_id = collect_answers()[-1]['id'] +def collect_all_answer(): + with open(ANSWERS_FILE_PATH, 'r') as all_answer: + result = [] + all_answer_dict = csv.DictReader(all_answer, fieldnames=ANSWERS_HEADER) + for answer in all_answer_dict: + result.append(answer) + return result + + +def id_generator(): + new_id = collect_all_answer()[-1]['id'] if new_id == 'id': new_id = 1 else: new_id = int(new_id) + 1 + return new_id + + +def submission_time_generator(): submission_time = int(time.time()) - prepared_data = [item for key, item in form_data.items()] - prepared_data = list(str(new_id)+str(submission_time)+str(''))+prepared_data + return submission_time + + +def add_answer(form_data): with open(ANSWERS_FILE_PATH, 'a', newline='') as csv_file: - writer = csv.writer(csv_file) - writer.writerow(prepared_data) + writer = csv.DictWriter(csv_file, fieldnames=ANSWERS_HEADER) + writer.writerow(form_data) diff --git a/sample_data/answer.csv b/sample_data/answer.csv index 3ddfa1ffb..3fb53903b 100644 --- a/sample_data/answer.csv +++ b/sample_data/answer.csv @@ -1,3 +1,5 @@ id,submission_time,vote_number,question_id,message,image 0,1493398154,4,0,"You need to use brackets: my_list = []", 1,1493088154,35,0,"Look it up in the Python docs", +2,1550153630,1,2,lkjfdslhljfhsalhflksahflksalkfjalkfjsa, +3,1550153655,1,1,éjsfkjdsalkflkajflkjsafésfjéasjé, diff --git a/server.py b/server.py index c19f016e2..a4c02f241 100644 --- a/server.py +++ b/server.py @@ -2,8 +2,6 @@ import data_manager app = Flask(__name__) -saved_data = {} - @app.route('/') def render_index(): questions = data_manager.collect_questions() @@ -13,20 +11,24 @@ def render_index(): @app.route('/question_page/') def show_question(id): question = data_manager.find_question(id) - answers = data_manager.collect_answers() + answers = data_manager.collect_answers(id) return render_template('question_page.html', question=question, answers=answers) @app.route('/question_page//new-answer', methods=['GET','POST']) def post_an_answer(id): + saved_data = {} question = data_manager.find_question(id) - answer = data_manager.collect_answers() + answer = data_manager.collect_answers(id) if request.method == 'POST': + saved_data['id'] = data_manager.id_generator() + saved_data['submission_time'] = data_manager.submission_time_generator() + saved_data['vote_number'] = 1 saved_data['question_id'] = request.form['question'] saved_data['message'] = request.form['message'] saved_data['image'] = request.form['image'] data_manager.add_answer(saved_data) - return redirect('/question_page/') + return redirect('/') return render_template('new_answer.html', question=question, answer=answer) diff --git a/templates/new_answer.html b/templates/new_answer.html index 44f525004..3432f7db0 100644 --- a/templates/new_answer.html +++ b/templates/new_answer.html @@ -6,13 +6,14 @@

Post an Answer

- +

-
+



- - +
+ + \ No newline at end of file diff --git a/templates/question_page.html b/templates/question_page.html index 75b841af5..acf32a72d 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -21,8 +21,8 @@

Answers:

{%for answer in answers%} {{answer['message']}}
{%endfor%} - -Post an Answer - + + Post an Answer + \ No newline at end of file From ed04bd0d1855100e0f4daad24dc4060ecc341001 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Thu, 14 Feb 2019 16:17:11 +0100 Subject: [PATCH 021/101] vote counter --- data_manager.py | 10 +++++++++- sample_data/answer.csv | 5 +++-- sample_data/question.csv | 2 +- server.py | 5 +---- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/data_manager.py b/data_manager.py index 0a9d32148..e4aedbb94 100644 --- a/data_manager.py +++ b/data_manager.py @@ -27,6 +27,14 @@ def find_question(id): return result +def update_view_number(question): + view = question['view_number'] + view = int(view)+1 + question['view_number'] = view + update_question(question) + + + def collect_answers(id): with open(ANSWERS_FILE_PATH, 'r') as answers: result = [] @@ -91,7 +99,7 @@ def new_id(file_name): file_read = csv.DictReader(file, fieldnames=DATA_HEADER) for row in file_read: new_id = row['id'] - return int(new_id)+1 + return int(new_id) + 1 def csv_questionwriter(csv_file, dictvalue1, dictvalue2): diff --git a/sample_data/answer.csv b/sample_data/answer.csv index 3fb53903b..e96425173 100644 --- a/sample_data/answer.csv +++ b/sample_data/answer.csv @@ -1,5 +1,6 @@ id,submission_time,vote_number,question_id,message,image 0,1493398154,4,0,"You need to use brackets: my_list = []", 1,1493088154,35,0,"Look it up in the Python docs", -2,1550153630,1,2,lkjfdslhljfhsalhflksahflksalkfjalkfjsa, -3,1550153655,1,1,éjsfkjdsalkflkajflkjsafésfjéasjé, +2,1550153630,1,2,lkjfdslhljfhsalhflksahflksalkfjalkfjsa, +3,1550153655,1,1,éjsfkjdsalkflkajflkjsafésfjéasjé, +4,1550157287,1,3,WHAT IS LOVE? BABY DON'T HURT ME NO MORE, diff --git a/sample_data/question.csv b/sample_data/question.csv index 891cec674..ca0284b1c 100644 --- a/sample_data/question.csv +++ b/sample_data/question.csv @@ -12,5 +12,5 @@ app.js (bundled file with webpack, including jquery)",images/image1.png 2,1493015432,1364,57,Drawing canvas with an image picked with Cordova Camera Plugin,"I'm getting an image from device and drawing a canvas with filters using Pixi JS. It works all well using computer to get an image. But when I'm on IOS, it throws errors such as cross origin issue, or that I'm trying to use an unknown format. This is the code I'm using to draw the image (that works on web/desktop but not cordova built ios app)", -3,2019-02-14 12:53:10.069187,0,0,What is love?,"Baby don't hurt me, no more", +3,2019-02-14 12:53:10.069187,33,0,What is love?,"Baby don't hurt me, no more", 4,1550149052,0,0,time?,TIME?, diff --git a/server.py b/server.py index 5a52697e3..ec01b6d51 100644 --- a/server.py +++ b/server.py @@ -12,6 +12,7 @@ def render_index(): def show_question(id): question = data_manager.find_question(id) answers = data_manager.collect_answers(id) + data_manager.update_view_number(question) return render_template('question_page.html', question=question, answers=answers) @app.route('/question_page//edit') @@ -63,10 +64,6 @@ def route_index(): return render_template('add_question.html', result=result) -@app.route('/question_page//edit_question') -def edit_question(id): - question = data_manager.find_question(id) - return render_template('edit_question.html', question=question) if __name__=="__main__": From 12f751e50ff28a1be50dc244f6636bb4633b8486 Mon Sep 17 00:00:00 2001 From: LibLev Date: Mon, 18 Feb 2019 11:00:54 +0100 Subject: [PATCH 022/101] =?UTF-8?q?Dani=20beleny=C3=BAlt...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data_manager.py | 1 - sample_data/answer.csv | 2 ++ sample_data/new_questions.csv | 6 ------ sample_data/question.csv | 17 ++++++++-------- server.py | 38 +++++++++++++++++++++-------------- templates/new_answer.html | 19 ++++++++++-------- templates/question_page.html | 7 ++++--- 7 files changed, 49 insertions(+), 41 deletions(-) delete mode 100644 sample_data/new_questions.csv diff --git a/data_manager.py b/data_manager.py index e4aedbb94..8cdbce778 100644 --- a/data_manager.py +++ b/data_manager.py @@ -1,7 +1,6 @@ import csv import os import time -from datetime import datetime ANSWERS_HEADER = ['id', 'submission_time', 'vote_number', 'question_id', 'message', 'image'] DATA_HEADER = ['id', 'submission_time', 'view_number', 'vote_number', 'title', 'message', 'image'] diff --git a/sample_data/answer.csv b/sample_data/answer.csv index e96425173..71733b294 100644 --- a/sample_data/answer.csv +++ b/sample_data/answer.csv @@ -4,3 +4,5 @@ id,submission_time,vote_number,question_id,message,image 2,1550153630,1,2,lkjfdslhljfhsalhflksahflksalkfjalkfjsa, 3,1550153655,1,1,éjsfkjdsalkflkajflkjsafésfjéasjé, 4,1550157287,1,3,WHAT IS LOVE? BABY DON'T HURT ME NO MORE, +5,1550158641,1,1,I belive I can fly, +6,1550159868,1,1,"kjhq,ehwlkewjfekjwf", diff --git a/sample_data/new_questions.csv b/sample_data/new_questions.csv deleted file mode 100644 index dd04e5bd2..000000000 --- a/sample_data/new_questions.csv +++ /dev/null @@ -1,6 +0,0 @@ -question_name,question -What is love?,Baby don't hurt me -question_name,question -is this the new file,who knows -question_name,question -What is love?,baby dont hurt me diff --git a/sample_data/question.csv b/sample_data/question.csv index ca0284b1c..3b8f2a7a8 100644 --- a/sample_data/question.csv +++ b/sample_data/question.csv @@ -1,6 +1,6 @@ -id,submission_time,view_number,vote_number,title,message,image -0,1493368154,29,7,How to make lists in Python?,"I am totally new to this, any hints?", -1,1493068124,15,9,Wordpress loading multiple jQuery Versions,"I developed a plugin that uses the jquery booklet plugin (http://builtbywill.com/booklet/#/) this plugin binds a function to $ so I cann call $('.myBook').booklet(); +id,submission_time,view_number,vote_number,title,message,image +0,1493368154,35,7,How to make lists in Python?,"I am totally new to this, any hints?", +1,1493068124,21,9,Wordpress loading multiple jQuery Versions,"I developed a plugin that uses the jquery booklet plugin (http://builtbywill.com/booklet/#/) this plugin binds a function to $ so I cann call $('.myBook').booklet(); I could easy managing the loading order with wp_enqueue_script so first I load jquery then I load booklet so everything is fine. @@ -8,9 +8,10 @@ BUT in my theme i also using jquery via webpack so the loading order is now foll jquery booklet -app.js (bundled file with webpack, including jquery)",images/image1.png -2,1493015432,1364,57,Drawing canvas with an image picked with Cordova Camera Plugin,"I'm getting an image from device and drawing a canvas with filters using Pixi JS. It works all well using computer to get an image. But when I'm on IOS, it throws errors such as cross origin issue, or that I'm trying to use an unknown format. +app.js (bundled file with webpack, including jquery)",images/image1.png +2,1493015432,1366,57,Drawing canvas with an image picked with Cordova Camera Plugin,"I'm getting an image from device and drawing a canvas with filters using Pixi JS. It works all well using computer to get an image. But when I'm on IOS, it throws errors such as cross origin issue, or that I'm trying to use an unknown format. -This is the code I'm using to draw the image (that works on web/desktop but not cordova built ios app)", -3,2019-02-14 12:53:10.069187,33,0,What is love?,"Baby don't hurt me, no more", -4,1550149052,0,0,time?,TIME?, +This is the code I'm using to draw the image (that works on web/desktop but not cordova built ios app)", +3,2019-02-14 12:53:10.069187,34,0,What is love?,"Baby don't hurt me, no more", +4,1550149052,0,0,time?,TIME?, +5,1550159933,1,0,What's your problem mate?,Why are you so sad?, diff --git a/server.py b/server.py index ec01b6d51..db884846e 100644 --- a/server.py +++ b/server.py @@ -35,21 +35,29 @@ def rewrite_suestion(): return redirect('/') -@app.route('/question_page//new-answer', methods=['GET','POST']) -def post_an_answer(id): - saved_data = {} - question = data_manager.find_question(id) - answer = data_manager.collect_answers(id) - if request.method == 'POST': - saved_data['id'] = data_manager.id_generator() - saved_data['submission_time'] = data_manager.submission_time_generator() - saved_data['vote_number'] = 1 - saved_data['question_id'] = request.form['question'] - saved_data['message'] = request.form['message'] - saved_data['image'] = request.form['image'] - data_manager.add_answer(saved_data) - return redirect('/') - return render_template('new_answer.html', question=question, answer=answer) +#@app.route('/question_page//new-answer', methods=['GET']) +#def post_an_answer(question_id): +# question = data_manager.find_question(id) +# answer = data_manager.collect_answers(id) +# return render_template('new_answer.html', question=question, answer=answer) + + +@app.route('/question_page//new-answer', methods=['POST']) +def post_an_answer(question_id): + new_answer = create_answer(question_id, request.form['message'], request.form['image']) + data_manager.add_answer(new_answer) + return redirect('/') + + +def create_answer(question_id, message, image): + return { + 'id': data_manager.id_generator(), + 'submission_time': data_manager.submission_time_generator(), + 'vote_number': 1, + 'question_id': question_id, + 'message': message, + 'image': image + } @app.route('/add-question',methods=['GET','POST']) diff --git a/templates/new_answer.html b/templates/new_answer.html index 3432f7db0..d15c5c714 100644 --- a/templates/new_answer.html +++ b/templates/new_answer.html @@ -6,14 +6,17 @@

Post an Answer

-
-

-
-
-
-
-
- + + +
+
+ +
+
+ +
+
+ \ No newline at end of file diff --git a/templates/question_page.html b/templates/question_page.html index 84e551d8e..a9116d259 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -19,10 +19,11 @@

Answers:

{%for answer in answers%} - {{answer['message']}}
+ {{answer['message']}} +
{%endfor%} - - Post an Answer + + Post an Answer \ No newline at end of file From 95212c3e9e84e6a40cd6da08205a7fc456f83704 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Mon, 18 Feb 2019 12:22:03 +0100 Subject: [PATCH 023/101] =?UTF-8?q?Most=20megint=20m=C5=B1k=C3=B6dik?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data_manager.py | 10 ++++++++++ sample_data/answer.csv | 7 +++++-- sample_data/question.csv | 19 +++++++++++-------- server.py | 23 +++++++++++------------ templates/question_page.html | 6 ++++-- 5 files changed, 41 insertions(+), 24 deletions(-) diff --git a/data_manager.py b/data_manager.py index 8cdbce778..715eb51fc 100644 --- a/data_manager.py +++ b/data_manager.py @@ -33,6 +33,16 @@ def update_view_number(question): update_question(question) +def update_vote_number(question,vote): + vote_number = question['vote_number'] + if vote == 'up': + vote_number = int(vote_number) + 1 + elif vote == 'down': + vote_number = int(vote_number) - 1 + question['view_number'] = vote_number + update_question(question) + + def collect_answers(id): with open(ANSWERS_FILE_PATH, 'r') as answers: diff --git a/sample_data/answer.csv b/sample_data/answer.csv index 71733b294..2ce783191 100644 --- a/sample_data/answer.csv +++ b/sample_data/answer.csv @@ -4,5 +4,8 @@ id,submission_time,vote_number,question_id,message,image 2,1550153630,1,2,lkjfdslhljfhsalhflksahflksalkfjalkfjsa, 3,1550153655,1,1,éjsfkjdsalkflkajflkjsafésfjéasjé, 4,1550157287,1,3,WHAT IS LOVE? BABY DON'T HURT ME NO MORE, -5,1550158641,1,1,I belive I can fly, -6,1550159868,1,1,"kjhq,ehwlkewjfekjwf", +5,1550158641,1,1,I belive I can fly, +6,1550159868,1,1,"kjhq,ehwlkewjfekjwf", +7,1550488533,1,7,"bármi, akármi", +8,1550488719,1,8,zzzzz, +9,1550488730,1,8,iiii, diff --git a/sample_data/question.csv b/sample_data/question.csv index 3b8f2a7a8..ed0f8bb59 100644 --- a/sample_data/question.csv +++ b/sample_data/question.csv @@ -1,6 +1,6 @@ -id,submission_time,view_number,vote_number,title,message,image -0,1493368154,35,7,How to make lists in Python?,"I am totally new to this, any hints?", -1,1493068124,21,9,Wordpress loading multiple jQuery Versions,"I developed a plugin that uses the jquery booklet plugin (http://builtbywill.com/booklet/#/) this plugin binds a function to $ so I cann call $('.myBook').booklet(); +id,submission_time,view_number,vote_number,title,message,image +0,1493368154,35,7,How to make lists in Python?,"I am totally new to this, any hints?", +1,1493068124,15,9,Wordpress loading multiple jQuery Versions,"I developed a plugin that uses the jquery booklet plugin (http://builtbywill.com/booklet/#/) this plugin binds a function to $ so I cann call $('.myBook').booklet(); I could easy managing the loading order with wp_enqueue_script so first I load jquery then I load booklet so everything is fine. @@ -8,10 +8,13 @@ BUT in my theme i also using jquery via webpack so the loading order is now foll jquery booklet -app.js (bundled file with webpack, including jquery)",images/image1.png +app.js (bundled file with webpack, including jquery)",images/image1.png 2,1493015432,1366,57,Drawing canvas with an image picked with Cordova Camera Plugin,"I'm getting an image from device and drawing a canvas with filters using Pixi JS. It works all well using computer to get an image. But when I'm on IOS, it throws errors such as cross origin issue, or that I'm trying to use an unknown format. -This is the code I'm using to draw the image (that works on web/desktop but not cordova built ios app)", -3,2019-02-14 12:53:10.069187,34,0,What is love?,"Baby don't hurt me, no more", -4,1550149052,0,0,time?,TIME?, -5,1550159933,1,0,What's your problem mate?,Why are you so sad?, +This is the code I'm using to draw the image (that works on web/desktop but not cordova built ios app)", +3,2019-02-14 12:53:10.069187,35,0,What is love?,"Baby don't hurt me, no more", +4,1550149052,0,0,time?,TIME?, +5,1550159933,1,0,What's your problem mate?,Why are you so sad?, +6,1550484185,2,0,élrwjféernf,ergkáemvéelv, +7,1550484304,4,0,jn kn-l -kl ,mk k-.m k. -. , +8,1550488705,4,0,lknkjn,ttttt, diff --git a/server.py b/server.py index db884846e..cf5998d15 100644 --- a/server.py +++ b/server.py @@ -21,7 +21,7 @@ def edit_question(id): return render_template('add_question.html', result=result) @app.route('/rewrite_question', methods=['POST']) -def rewrite_suestion(): +def rewrite_question(): updated_question = { 'id': request.form.get('id'), 'submission_time': request.form.get('submission_time'), @@ -35,18 +35,14 @@ def rewrite_suestion(): return redirect('/') -#@app.route('/question_page//new-answer', methods=['GET']) -#def post_an_answer(question_id): -# question = data_manager.find_question(id) -# answer = data_manager.collect_answers(id) -# return render_template('new_answer.html', question=question, answer=answer) - - -@app.route('/question_page//new-answer', methods=['POST']) +@app.route('/question_page//new-answer', methods=['GET','POST']) def post_an_answer(question_id): - new_answer = create_answer(question_id, request.form['message'], request.form['image']) - data_manager.add_answer(new_answer) - return redirect('/') + if request.method=='POST': + new_answer = create_answer(question_id, request.form['message'], request.form['image']) + data_manager.add_answer(new_answer) + return redirect('/') + question = data_manager.find_question(question_id) + return render_template('new_answer.html', question=question) def create_answer(question_id, message, image): @@ -72,6 +68,9 @@ def route_index(): return render_template('add_question.html', result=result) +@app.route('/question_page//vote', methods=['POST']) +def vote(): + vote if __name__=="__main__": diff --git a/templates/question_page.html b/templates/question_page.html index a9116d259..e39a0dbc8 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -10,6 +10,8 @@ Submission Time: {{question['submission_time']}}
View Number: {{question['view_number']}}
Vote Number: {{question['vote_number']}}
+
Vote up +
Vote down Title: {{question['title']}}
Message:{{question['message']}}
Image:{{question['image']}}
@@ -22,8 +24,8 @@

Answers:

{{answer['message']}}
{%endfor%} -
- Post an Answer + + Post an Answer \ No newline at end of file From ca12f5b0acc2842063747fbdddf7897b89e089d8 Mon Sep 17 00:00:00 2001 From: lterray Date: Mon, 28 Aug 2017 16:35:10 +0200 Subject: [PATCH 024/101] add sql sample data --- sample_data/askmatepart2-sample-data.sql | 127 +++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 sample_data/askmatepart2-sample-data.sql diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql new file mode 100644 index 000000000..369355a65 --- /dev/null +++ b/sample_data/askmatepart2-sample-data.sql @@ -0,0 +1,127 @@ +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 9.5.6 +-- Dumped by pg_dump version 9.5.6 + +ALTER TABLE IF EXISTS ONLY public.question DROP CONSTRAINT IF EXISTS pk_question_id CASCADE; +ALTER TABLE IF EXISTS ONLY public.answer DROP CONSTRAINT IF EXISTS pk_answer_id CASCADE; +ALTER TABLE IF EXISTS ONLY public.answer DROP CONSTRAINT IF EXISTS fk_question_id CASCADE; +ALTER TABLE IF EXISTS ONLY public.comment DROP CONSTRAINT IF EXISTS pk_comment_id CASCADE; +ALTER TABLE IF EXISTS ONLY public.comment DROP CONSTRAINT IF EXISTS fk_question_id CASCADE; +ALTER TABLE IF EXISTS ONLY public.comment DROP CONSTRAINT IF EXISTS fk_answer_id CASCADE; +ALTER TABLE IF EXISTS ONLY public.question_tag DROP CONSTRAINT IF EXISTS pk_question_tag_id CASCADE; +ALTER TABLE IF EXISTS ONLY public.question_tag DROP CONSTRAINT IF EXISTS fk_question_id CASCADE; +ALTER TABLE IF EXISTS ONLY public.tag DROP CONSTRAINT IF EXISTS pk_tag_id CASCADE; +ALTER TABLE IF EXISTS ONLY public.question_tag DROP CONSTRAINT IF EXISTS fk_tag_id CASCADE; + +DROP TABLE IF EXISTS public.question; +DROP SEQUENCE IF EXISTS public.question_id_seq; +CREATE TABLE question ( + id serial NOT NULL, + submission_time timestamp without time zone, + view_number integer, + vote_number integer, + title text, + message text, + image text +); + +DROP TABLE IF EXISTS public.answer; +DROP SEQUENCE IF EXISTS public.answer_id_seq; +CREATE TABLE answer ( + id serial NOT NULL, + submission_time timestamp without time zone, + vote_number integer, + question_id integer, + message text, + image text +); + +DROP TABLE IF EXISTS public.comment; +DROP SEQUENCE IF EXISTS public.comment_id_seq; +CREATE TABLE comment ( + id serial NOT NULL, + question_id integer, + answer_id integer, + message text, + submission_time timestamp without time zone, + edited_count integer +); + + +DROP TABLE IF EXISTS public.question_tag; +CREATE TABLE question_tag ( + question_id integer NOT NULL, + tag_id integer NOT NULL +); + +DROP TABLE IF EXISTS public.tag; +DROP SEQUENCE IF EXISTS public.tag_id_seq; +CREATE TABLE tag ( + id serial NOT NULL, + name text +); + + +ALTER TABLE ONLY answer + ADD CONSTRAINT pk_answer_id PRIMARY KEY (id); + +ALTER TABLE ONLY comment + ADD CONSTRAINT pk_comment_id PRIMARY KEY (id); + +ALTER TABLE ONLY question + ADD CONSTRAINT pk_question_id PRIMARY KEY (id); + +ALTER TABLE ONLY question_tag + ADD CONSTRAINT pk_question_tag_id PRIMARY KEY (question_id, tag_id); + +ALTER TABLE ONLY tag + ADD CONSTRAINT pk_tag_id PRIMARY KEY (id); + +ALTER TABLE ONLY comment + ADD CONSTRAINT fk_answer_id FOREIGN KEY (answer_id) REFERENCES answer(id); + +ALTER TABLE ONLY answer + ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id); + +ALTER TABLE ONLY question_tag + ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id); + +ALTER TABLE ONLY comment + ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id); + +ALTER TABLE ONLY question_tag + ADD CONSTRAINT fk_tag_id FOREIGN KEY (tag_id) REFERENCES tag(id); + +INSERT INTO question VALUES (0, '2017-04-28 08:29:00', 29, 7, 'How to make lists in Python?', 'I am totally new to this, any hints?', NULL); +INSERT INTO question VALUES (1, '2017-04-29 09:19:00', 15, 9, 'Wordpress loading multiple jQuery Versions', 'I developed a plugin that uses the jquery booklet plugin (http://builtbywill.com/booklet/#/) this plugin binds a function to $ so I cann call $(".myBook").booklet(); + +I could easy managing the loading order with wp_enqueue_script so first I load jquery then I load booklet so everything is fine. + +BUT in my theme i also using jquery via webpack so the loading order is now following: + +jquery +booklet +app.js (bundled file with webpack, including jquery)', 'images/image1.png'); +INSERT INTO question VALUES (2, '2017-05-01 10:41:00', 1364, 57, 'Drawing canvas with an image picked with Cordova Camera Plugin', 'I''m getting an image from device and drawing a canvas with filters using Pixi JS. It works all well using computer to get an image. But when I''m on IOS, it throws errors such as cross origin issue, or that I''m trying to use an unknown format. +', NULL); +SELECT pg_catalog.setval('question_id_seq', 2, true); + +INSERT INTO answer VALUES (1, '2017-04-28 16:49:00', 4, 1, 'You need to use brackets: my_list = []', NULL); +INSERT INTO answer VALUES (2, '2017-04-25 14:42:00', 35, 1, 'Look it up in the Python docs', 'images/image2.jpg'); +SELECT pg_catalog.setval('answer_id_seq', 2, true); + +INSERT INTO comment VALUES (1, 0, NULL, 'Please clarify the question as it is too vague!', '2017-05-01 05:49:00'); +INSERT INTO comment VALUES (2, NULL, 1, 'I think you could use my_list = list() as well.', '2017-05-02 16:55:00'); +SELECT pg_catalog.setval('comment_id_seq', 2, true); + +INSERT INTO tag VALUES (1, 'python'); +INSERT INTO tag VALUES (2, 'sql'); +INSERT INTO tag VALUES (3, 'css'); +SELECT pg_catalog.setval('tag_id_seq', 3, true); + +INSERT INTO question_tag VALUES (0, 1); +INSERT INTO question_tag VALUES (1, 3); +INSERT INTO question_tag VALUES (2, 3); From 0d66ea8483f7929ca35282a79772d5b58604904b Mon Sep 17 00:00:00 2001 From: LibLev Date: Tue, 26 Feb 2019 10:47:19 +0100 Subject: [PATCH 025/101] connenction been updated --- connection.py | 51 ++++++++++++++++++++++++++++++++++++++++ sample_data/question.csv | 22 ++++++++--------- 2 files changed, 62 insertions(+), 11 deletions(-) diff --git a/connection.py b/connection.py index e69de29bb..c9bda939a 100644 --- a/connection.py +++ b/connection.py @@ -0,0 +1,51 @@ +# Creates a decorator to handle the database connection/cursor opening/closing. +# Creates the cursor with RealDictCursor, thus it returns real dictionaries, where the column names are the keys. +import os +import psycopg2 +import psycopg2.extras + + +def get_connection_string(): + # setup connection string + # to do this, please define these environment variables first + user_name = os.environ.get('PSQL_USER_NAME') + password = os.environ.get('PSQL_PASSWORD') + host = os.environ.get('PSQL_HOST') + database_name = os.environ.get('PSQL_DB_NAME') + + env_variables_defined = user_name and password and host and database_name + + if env_variables_defined: + # this string describes all info for psycopg2 to connect to the database + return 'postgresql://{user_name}:{password}@{host}/{database_name}'.format( + user_name=user_name, + password=password, + host=host, + database_name=database_name + ) + else: + raise KeyError('Some necessary environment variable(s) are not defined') + + +def open_database(): + try: + connection_string = get_connection_string() + connection = psycopg2.connect(connection_string) + connection.autocommit = True + except psycopg2.DatabaseError as exception: + print('Database connection problem') + raise exception + return connection + + +def connection_handler(function): + def wrapper(*args, **kwargs): + connection = open_database() + # we set the cursor_factory parameter to return with a RealDictCursor cursor (cursor which provide dictionaries) + dict_cur = connection.cursor(cursor_factory=psycopg2.extras.RealDictCursor) + ret_value = function(dict_cur, *args, **kwargs) + dict_cur.close() + connection.close() + return ret_value + + return wrapper diff --git a/sample_data/question.csv b/sample_data/question.csv index ed0f8bb59..a9f480a89 100644 --- a/sample_data/question.csv +++ b/sample_data/question.csv @@ -1,6 +1,6 @@ -id,submission_time,view_number,vote_number,title,message,image -0,1493368154,35,7,How to make lists in Python?,"I am totally new to this, any hints?", -1,1493068124,15,9,Wordpress loading multiple jQuery Versions,"I developed a plugin that uses the jquery booklet plugin (http://builtbywill.com/booklet/#/) this plugin binds a function to $ so I cann call $('.myBook').booklet(); +id,submission_time,view_number,vote_number,title,message,image +0,1493368154,39,7,How to make lists in Python?,"I am totally new to this, any hints?", +1,1493068124,17,9,Wordpress loading multiple jQuery Versions,"I developed a plugin that uses the jquery booklet plugin (http://builtbywill.com/booklet/#/) this plugin binds a function to $ so I cann call $('.myBook').booklet(); I could easy managing the loading order with wp_enqueue_script so first I load jquery then I load booklet so everything is fine. @@ -8,13 +8,13 @@ BUT in my theme i also using jquery via webpack so the loading order is now foll jquery booklet -app.js (bundled file with webpack, including jquery)",images/image1.png +app.js (bundled file with webpack, including jquery)",images/image1.png 2,1493015432,1366,57,Drawing canvas with an image picked with Cordova Camera Plugin,"I'm getting an image from device and drawing a canvas with filters using Pixi JS. It works all well using computer to get an image. But when I'm on IOS, it throws errors such as cross origin issue, or that I'm trying to use an unknown format. -This is the code I'm using to draw the image (that works on web/desktop but not cordova built ios app)", -3,2019-02-14 12:53:10.069187,35,0,What is love?,"Baby don't hurt me, no more", -4,1550149052,0,0,time?,TIME?, -5,1550159933,1,0,What's your problem mate?,Why are you so sad?, -6,1550484185,2,0,élrwjféernf,ergkáemvéelv, -7,1550484304,4,0,jn kn-l -kl ,mk k-.m k. -. , -8,1550488705,4,0,lknkjn,ttttt, +This is the code I'm using to draw the image (that works on web/desktop but not cordova built ios app)", +3,2019-02-14 12:53:10.069187,35,0,What is love?,"Baby don't hurt me, no more", +4,1550149052,0,0,time?,TIME?, +5,1550159933,1,0,What's your problem mate?,Why are you so sad?, +6,1550484185,2,0,élrwjféernf,ergkáemvéelv, +7,1550484304,4,0,jn kn-l -kl ,mk k-.m k. -. , +8,1550488705,4,0,lknkjn,ttttt, From 2fd850f44694dfe0b179ac365bb9774eafd661e9 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Tue, 26 Feb 2019 13:08:28 +0100 Subject: [PATCH 026/101] collect question and answer, show question --- templates/question_page.html | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/templates/question_page.html b/templates/question_page.html index e39a0dbc8..b3d873c87 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -6,15 +6,15 @@ -ID :{{question['id']}}
-Submission Time: {{question['submission_time']}}
-View Number: {{question['view_number']}}
-Vote Number: {{question['vote_number']}}
-
Vote up -
Vote down -Title: {{question['title']}}
-Message:{{question['message']}}
-Image:{{question['image']}}
+ID :{{question[0]['id']}}
+Submission Time: {{question[0]['submission_time']}}
+View Number: {{question[0]['view_number']}}
+Vote Number: {{question[0]['vote_number']}}
+
Vote up +
Vote down +Title: {{question[0]['title']}}
+Message:{{question[0]['message']}}
+Image:{{question[0]['image']}}
edit question From b829aa1e0c05ea23f94ffa22e9ee04cc900b0e2e Mon Sep 17 00:00:00 2001 From: borosTamas Date: Tue, 26 Feb 2019 13:10:45 +0100 Subject: [PATCH 027/101] collect question and answer, show question --- data_manager.py | 55 ++++++++++++++++++++++---------------------- server.py | 10 ++++---- templates/index.html | 4 ++-- 3 files changed, 34 insertions(+), 35 deletions(-) diff --git a/data_manager.py b/data_manager.py index 715eb51fc..94f02690d 100644 --- a/data_manager.py +++ b/data_manager.py @@ -1,6 +1,7 @@ import csv import os import time +import connection ANSWERS_HEADER = ['id', 'submission_time', 'vote_number', 'question_id', 'message', 'image'] DATA_HEADER = ['id', 'submission_time', 'view_number', 'vote_number', 'title', 'message', 'image'] @@ -8,23 +9,23 @@ QUESTIONS_FILE_PATH = os.getenv('QUESTIONS_FILE_PATH', 'sample_data/question.csv') ANSWERS_FILE_PATH = os.getenv('ANSWERS_FILE_PATH', 'sample_data/answer.csv') - -def collect_questions(): - with open(QUESTIONS_FILE_PATH, 'r') as questions: - result = [] - questions_dict = csv.DictReader(questions, fieldnames=DATA_HEADER) - for question in questions_dict: - result.append(question) - return result - - -def find_question(id): - list_of_questions = collect_questions() - for question in list_of_questions: - if question['id'] == id: - result = question - return result - +@connection.connection_handler +def collect_questions(cursor): + cursor.execute(""" + SELECT * FROM question + """) + result = cursor.fetchall() + return result + +@connection.connection_handler +def find_question(cursor, q_id): + cursor.execute(""" + SELECT * from question + where id = %(q_id)s + """, + {'q_id': q_id}) + result = cursor.fetchall() + return result def update_view_number(question): view = question['view_number'] @@ -43,18 +44,16 @@ def update_vote_number(question,vote): update_question(question) +@connection.connection_handler +def collect_answers(cursor, q_id): + cursor.execute(""" + SELECT * from answer + where question_id = %(q_id)s + """, + {'q_id': q_id}) -def collect_answers(id): - with open(ANSWERS_FILE_PATH, 'r') as answers: - result = [] - answers_dict = csv.DictReader(answers, fieldnames=ANSWERS_HEADER) - for answers in answers_dict: - if answers['question_id'] == id: - result.append(answers) - if len(result) < 1: - result = [{'message': 'there is no answer yet'}] - return result - + result = cursor.fetchall() + return result def update_question(question_dict): with open(QUESTIONS_FILE_PATH, 'r') as old_questions: diff --git a/server.py b/server.py index cf5998d15..0da9b097c 100644 --- a/server.py +++ b/server.py @@ -8,11 +8,11 @@ def render_index(): return render_template('index.html', questions=questions) -@app.route('/question_page/') -def show_question(id): - question = data_manager.find_question(id) - answers = data_manager.collect_answers(id) - data_manager.update_view_number(question) +@app.route('/question_page/') +def show_question(question_id): + question = data_manager.find_question(q_id=question_id) + answers = data_manager.collect_answers(q_id=question_id) + #data_manager.update_view_number(question) return render_template('question_page.html', question=question, answers=answers) @app.route('/question_page//edit') diff --git a/templates/index.html b/templates/index.html index 0bff11951..98a2e00b0 100644 --- a/templates/index.html +++ b/templates/index.html @@ -11,9 +11,9 @@

QUESTIONS:

Question ID MessageImage Question ID Message Image
Question IDMessageImageQuestion IDMessageImage
- {% for question in questions[1:]%} + {% for question in questions%} - {% endfor %} From f6466d7b8292344f49da64bf0aa76426bdd50371 Mon Sep 17 00:00:00 2001 From: LibLev Date: Tue, 26 Feb 2019 13:13:39 +0100 Subject: [PATCH 028/101] update question/answer and add answer are ready to use --- data_manager.py | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/data_manager.py b/data_manager.py index 94f02690d..be5d5c7bf 100644 --- a/data_manager.py +++ b/data_manager.py @@ -55,22 +55,22 @@ def collect_answers(cursor, q_id): result = cursor.fetchall() return result -def update_question(question_dict): - with open(QUESTIONS_FILE_PATH, 'r') as old_questions: - old_question_dict = csv.DictReader(old_questions, fieldnames=DATA_HEADER) - temporary_list = [] - for row in old_question_dict: - if row['id'] == question_dict['id']: - row = question_dict - temporary_list.append(row) - else: - temporary_list.append(row) - - with open(QUESTIONS_FILE_PATH, 'w') as new_qestions: - new_qestion_dict = csv.DictWriter(new_qestions, fieldnames=DATA_HEADER) - new_qestion_dict.writeheader() - for row in temporary_list[1:]: - new_qestion_dict.writerow(row) +@connection.connection_handler +def update_question(cursor,datas): + cursor.execute(""" + UPDATE question + SET message=%s, image=%s + WHERE id=%s""", + (datas['message'], datas['image'], int(datas['id']))) + + +@connection.connection_handler +def update_answer(cursor,datas): + cursor.execute(""" + UPDATE answer + SET message=%s, image=%s + WHERE id=%s""", + (datas['message'], datas['image'], int(datas['id']))) def collect_all_answer(): @@ -96,10 +96,13 @@ def submission_time_generator(): return submission_time -def add_answer(form_data): - with open(ANSWERS_FILE_PATH, 'a', newline='') as csv_file: - writer = csv.DictWriter(csv_file, fieldnames=ANSWERS_HEADER) - writer.writerow(form_data) +@connection.connection_handler +def add_answer(cursor, form_data): + cursor.execute(""" + INSERT INTO answer(submission_time, vote_number, question_id, message, image) + VALUES (%s, %s, %s, %s, %s, %s)""", + (form_data['submission_time'], form_data['vote_number'], form_data['question_id'], + form_data['message'], form_data['image'])) def new_id(file_name): From 086b4a278efa0103a44d589399c4b06a9298365d Mon Sep 17 00:00:00 2001 From: Zollli Date: Tue, 26 Feb 2019 13:18:18 +0100 Subject: [PATCH 029/101] write q/a in progress --- data_manager.py | 22 ++++++++++++++++++++++ server.py | 9 +++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/data_manager.py b/data_manager.py index be5d5c7bf..a2c731d23 100644 --- a/data_manager.py +++ b/data_manager.py @@ -121,4 +121,26 @@ def csv_questionwriter(csv_file, dictvalue1, dictvalue2): vote_counter = 0 submission_time = int(time.time()) writer.writerow({'id': question_id, 'submission_time': submission_time, 'view_number': view_counter, + 'vote_number': vote_counter, 'title': dictvalue1, 'message': dictvalue2}) + + +@connection.connection_handler +def add_question(cursor,message): + submission_time = "time" + #int(time.time()) + vote_number = "vote_number" + image = "img" + view_number = "view_number" + title = "title" + cursor.execute(""" + INSERT INTO question(submission_time, view_number, vote_number, title, message, image) + VALUES (%(submission_time)s,%(view_number)s,%(vote_number)s, %(title)s,%(message)s,%(image)s); + """, + + {'submission_time': submission_time, 'view_number' : view_number,'vote_number': vote_number, + 'title' : title, 'message': message, 'image' : image}) + + + + diff --git a/server.py b/server.py index 0da9b097c..b973bc385 100644 --- a/server.py +++ b/server.py @@ -57,15 +57,16 @@ def create_answer(question_id, message, image): @app.route('/add-question',methods=['GET','POST']) -def route_index(): +def add_question(): result = [] + message = "" if request.method == 'POST': question_name = request.form.get('question_name') - question = request.form.get('question') - data_manager.csv_questionwriter('sample_data/question.csv',question_name,question) + message = request.form.get('message') + data_manager.add_question(message) return redirect('/') - return render_template('add_question.html', result=result) + return render_template('add_question.html', message=message,result = result) @app.route('/question_page//vote', methods=['POST']) From da13e70939b28f24842ec19d7c13d8ef5285fb76 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Tue, 26 Feb 2019 14:15:00 +0100 Subject: [PATCH 030/101] view number ready --- data_manager.py | 39 +++++++++++++++++++----------------- server.py | 5 ++++- templates/add_question.html | 1 + templates/edit_question.html | 20 ------------------ templates/home_button.html | 10 +++++++++ templates/new_answer.html | 1 + templates/question_page.html | 3 ++- 7 files changed, 39 insertions(+), 40 deletions(-) delete mode 100644 templates/edit_question.html create mode 100644 templates/home_button.html diff --git a/data_manager.py b/data_manager.py index a2c731d23..1965fc6f0 100644 --- a/data_manager.py +++ b/data_manager.py @@ -9,6 +9,7 @@ QUESTIONS_FILE_PATH = os.getenv('QUESTIONS_FILE_PATH', 'sample_data/question.csv') ANSWERS_FILE_PATH = os.getenv('ANSWERS_FILE_PATH', 'sample_data/answer.csv') + @connection.connection_handler def collect_questions(cursor): cursor.execute(""" @@ -17,24 +18,29 @@ def collect_questions(cursor): result = cursor.fetchall() return result + @connection.connection_handler def find_question(cursor, q_id): cursor.execute(""" SELECT * from question where id = %(q_id)s """, - {'q_id': q_id}) + {'q_id': q_id}) result = cursor.fetchall() return result -def update_view_number(question): - view = question['view_number'] - view = int(view)+1 - question['view_number'] = view - update_question(question) +@connection.connection_handler +def update_view_number(cursor, q_id): + cursor.execute(""" + update question + set view_number = view_number+1 + where id = %(q_id)s + """, + {'q_id': q_id}) -def update_vote_number(question,vote): + +def update_vote_number(question, vote): vote_number = question['vote_number'] if vote == 'up': vote_number = int(vote_number) + 1 @@ -50,13 +56,14 @@ def collect_answers(cursor, q_id): SELECT * from answer where question_id = %(q_id)s """, - {'q_id': q_id}) + {'q_id': q_id}) result = cursor.fetchall() return result + @connection.connection_handler -def update_question(cursor,datas): +def update_question(cursor, datas): cursor.execute(""" UPDATE question SET message=%s, image=%s @@ -65,7 +72,7 @@ def update_question(cursor,datas): @connection.connection_handler -def update_answer(cursor,datas): +def update_answer(cursor, datas): cursor.execute(""" UPDATE answer SET message=%s, image=%s @@ -126,9 +133,9 @@ def csv_questionwriter(csv_file, dictvalue1, dictvalue2): @connection.connection_handler -def add_question(cursor,message): +def add_question(cursor, message): submission_time = "time" - #int(time.time()) + # int(time.time()) vote_number = "vote_number" image = "img" view_number = "view_number" @@ -138,9 +145,5 @@ def add_question(cursor,message): VALUES (%(submission_time)s,%(view_number)s,%(vote_number)s, %(title)s,%(message)s,%(image)s); """, - {'submission_time': submission_time, 'view_number' : view_number,'vote_number': vote_number, - 'title' : title, 'message': message, 'image' : image}) - - - - + {'submission_time': submission_time, 'view_number': view_number, 'vote_number': vote_number, + 'title': title, 'message': message, 'image': image}) diff --git a/server.py b/server.py index b973bc385..48ada5181 100644 --- a/server.py +++ b/server.py @@ -2,6 +2,7 @@ import data_manager app = Flask(__name__) + @app.route('/') def render_index(): questions = data_manager.collect_questions() @@ -12,14 +13,16 @@ def render_index(): def show_question(question_id): question = data_manager.find_question(q_id=question_id) answers = data_manager.collect_answers(q_id=question_id) - #data_manager.update_view_number(question) + data_manager.update_view_number(q_id=question_id) return render_template('question_page.html', question=question, answers=answers) + @app.route('/question_page//edit') def edit_question(id): result = data_manager.find_question(id) return render_template('add_question.html', result=result) + @app.route('/rewrite_question', methods=['POST']) def rewrite_question(): updated_question = { diff --git a/templates/add_question.html b/templates/add_question.html index ce95d827b..6061d0ec4 100644 --- a/templates/add_question.html +++ b/templates/add_question.html @@ -5,6 +5,7 @@ Add New Question +{% include 'home_button.html' %} {% if result == [] %}

Add New Question

diff --git a/templates/edit_question.html b/templates/edit_question.html deleted file mode 100644 index f28dbdbbf..000000000 --- a/templates/edit_question.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - Edit Question - - -

Edit Question

-

{{question['message']}}

- - Question Name:
-
- Question:
-
-
- - - - - diff --git a/templates/home_button.html b/templates/home_button.html new file mode 100644 index 000000000..3e8d3d12b --- /dev/null +++ b/templates/home_button.html @@ -0,0 +1,10 @@ + + + + + Home + + + Home + + \ No newline at end of file diff --git a/templates/new_answer.html b/templates/new_answer.html index d15c5c714..d2b1ec898 100644 --- a/templates/new_answer.html +++ b/templates/new_answer.html @@ -5,6 +5,7 @@ Post an Answer +{% include 'home_button.html' %}

Post an Answer

diff --git a/templates/question_page.html b/templates/question_page.html index b3d873c87..521867014 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -5,7 +5,8 @@ {{question['title']}} - +
{% include 'home_button.html' %}
+
ID :{{question[0]['id']}}
Submission Time: {{question[0]['submission_time']}}
View Number: {{question[0]['view_number']}}
From f31186e604b9ef61ead5d52079bade956ae63510 Mon Sep 17 00:00:00 2001 From: LibLev Date: Tue, 26 Feb 2019 14:39:02 +0100 Subject: [PATCH 031/101] =?UTF-8?q?megy=20a=20baszakod=C3=A1s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data_manager.py | 14 +++++++------- sample_data/answer.csv | 11 ----------- sample_data/question.csv | 20 -------------------- server.py | 11 +++++------ templates/add_question.html | 14 +++++++------- templates/new_answer.html | 4 ++-- templates/question_page.html | 6 ++++-- 7 files changed, 25 insertions(+), 55 deletions(-) delete mode 100644 sample_data/answer.csv delete mode 100644 sample_data/question.csv diff --git a/data_manager.py b/data_manager.py index 1965fc6f0..9efc50762 100644 --- a/data_manager.py +++ b/data_manager.py @@ -80,13 +80,13 @@ def update_answer(cursor, datas): (datas['message'], datas['image'], int(datas['id']))) -def collect_all_answer(): - with open(ANSWERS_FILE_PATH, 'r') as all_answer: - result = [] - all_answer_dict = csv.DictReader(all_answer, fieldnames=ANSWERS_HEADER) - for answer in all_answer_dict: - result.append(answer) - return result +@connection.connection_handler +def collect_all_answer(cursor): + cursor.execute(""" + SELECT * FROM answer + """) + result = cursor.fetchall() + return result def id_generator(): diff --git a/sample_data/answer.csv b/sample_data/answer.csv deleted file mode 100644 index 2ce783191..000000000 --- a/sample_data/answer.csv +++ /dev/null @@ -1,11 +0,0 @@ -id,submission_time,vote_number,question_id,message,image -0,1493398154,4,0,"You need to use brackets: my_list = []", -1,1493088154,35,0,"Look it up in the Python docs", -2,1550153630,1,2,lkjfdslhljfhsalhflksahflksalkfjalkfjsa, -3,1550153655,1,1,éjsfkjdsalkflkajflkjsafésfjéasjé, -4,1550157287,1,3,WHAT IS LOVE? BABY DON'T HURT ME NO MORE, -5,1550158641,1,1,I belive I can fly, -6,1550159868,1,1,"kjhq,ehwlkewjfekjwf", -7,1550488533,1,7,"bármi, akármi", -8,1550488719,1,8,zzzzz, -9,1550488730,1,8,iiii, diff --git a/sample_data/question.csv b/sample_data/question.csv deleted file mode 100644 index a9f480a89..000000000 --- a/sample_data/question.csv +++ /dev/null @@ -1,20 +0,0 @@ -id,submission_time,view_number,vote_number,title,message,image -0,1493368154,39,7,How to make lists in Python?,"I am totally new to this, any hints?", -1,1493068124,17,9,Wordpress loading multiple jQuery Versions,"I developed a plugin that uses the jquery booklet plugin (http://builtbywill.com/booklet/#/) this plugin binds a function to $ so I cann call $('.myBook').booklet(); - -I could easy managing the loading order with wp_enqueue_script so first I load jquery then I load booklet so everything is fine. - -BUT in my theme i also using jquery via webpack so the loading order is now following: - -jquery -booklet -app.js (bundled file with webpack, including jquery)",images/image1.png -2,1493015432,1366,57,Drawing canvas with an image picked with Cordova Camera Plugin,"I'm getting an image from device and drawing a canvas with filters using Pixi JS. It works all well using computer to get an image. But when I'm on IOS, it throws errors such as cross origin issue, or that I'm trying to use an unknown format. - -This is the code I'm using to draw the image (that works on web/desktop but not cordova built ios app)", -3,2019-02-14 12:53:10.069187,35,0,What is love?,"Baby don't hurt me, no more", -4,1550149052,0,0,time?,TIME?, -5,1550159933,1,0,What's your problem mate?,Why are you so sad?, -6,1550484185,2,0,élrwjféernf,ergkáemvéelv, -7,1550484304,4,0,jn kn-l -kl ,mk k-.m k. -. , -8,1550488705,4,0,lknkjn,ttttt, diff --git a/server.py b/server.py index 48ada5181..c838f6f42 100644 --- a/server.py +++ b/server.py @@ -16,10 +16,9 @@ def show_question(question_id): data_manager.update_view_number(q_id=question_id) return render_template('question_page.html', question=question, answers=answers) - -@app.route('/question_page//edit') -def edit_question(id): - result = data_manager.find_question(id) +@app.route('/question_page//edit') +def edit_question(question_id): + result = data_manager.find_question(q_id=question_id) return render_template('add_question.html', result=result) @@ -34,7 +33,7 @@ def rewrite_question(): 'message': request.form.get('message'), 'image': request.form.get('image') } - data_manager.update_question(updated_question) + data_manager.update_question(datas=updated_question) return redirect('/') @@ -42,7 +41,7 @@ def rewrite_question(): def post_an_answer(question_id): if request.method=='POST': new_answer = create_answer(question_id, request.form['message'], request.form['image']) - data_manager.add_answer(new_answer) + data_manager.add_answer(form_data=new_answer) return redirect('/') question = data_manager.find_question(question_id) return render_template('new_answer.html', question=question) diff --git a/templates/add_question.html b/templates/add_question.html index 6061d0ec4..3c86de8de 100644 --- a/templates/add_question.html +++ b/templates/add_question.html @@ -20,15 +20,15 @@

Add New Question

Edit Question

Question Name:
-
+
Question:
-
+

- - - - - + + + + + {% endif %} diff --git a/templates/new_answer.html b/templates/new_answer.html index d2b1ec898..8cfa154a1 100644 --- a/templates/new_answer.html +++ b/templates/new_answer.html @@ -7,10 +7,10 @@ {% include 'home_button.html' %}

Post an Answer

- +

-
+


diff --git a/templates/question_page.html b/templates/question_page.html index 521867014..78c93e070 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -17,7 +17,9 @@ Message:{{question[0]['message']}}
Image:{{question[0]['image']}}
-edit question + + edit question +

Answers:

@@ -26,7 +28,7 @@

Answers:


{%endfor%} - Post an Answer + Post an Answer \ No newline at end of file From c5e4dac0bd0199192415c7f2b0dd45b4912c9fd3 Mon Sep 17 00:00:00 2001 From: LibLev Date: Tue, 26 Feb 2019 15:05:20 +0100 Subject: [PATCH 032/101] post answer --- data_manager.py | 15 +++------------ server.py | 1 - 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/data_manager.py b/data_manager.py index 9efc50762..fb0dff1c6 100644 --- a/data_manager.py +++ b/data_manager.py @@ -1,6 +1,6 @@ import csv import os -import time +import datetime import connection ANSWERS_HEADER = ['id', 'submission_time', 'vote_number', 'question_id', 'message', 'image'] @@ -89,17 +89,8 @@ def collect_all_answer(cursor): return result -def id_generator(): - new_id = collect_all_answer()[-1]['id'] - if new_id == 'id': - new_id = 1 - else: - new_id = int(new_id) + 1 - return new_id - - def submission_time_generator(): - submission_time = int(time.time()) + submission_time = datetime.datetime.now() return submission_time @@ -107,7 +98,7 @@ def submission_time_generator(): def add_answer(cursor, form_data): cursor.execute(""" INSERT INTO answer(submission_time, vote_number, question_id, message, image) - VALUES (%s, %s, %s, %s, %s, %s)""", + VALUES (%s, %s, %s, %s, %s)""", (form_data['submission_time'], form_data['vote_number'], form_data['question_id'], form_data['message'], form_data['image'])) diff --git a/server.py b/server.py index c838f6f42..001b9d1d1 100644 --- a/server.py +++ b/server.py @@ -49,7 +49,6 @@ def post_an_answer(question_id): def create_answer(question_id, message, image): return { - 'id': data_manager.id_generator(), 'submission_time': data_manager.submission_time_generator(), 'vote_number': 1, 'question_id': question_id, From b9b6a6c7d94b8a24b33b5b20d6df6af817a2ac3a Mon Sep 17 00:00:00 2001 From: Zollli Date: Tue, 26 Feb 2019 15:16:13 +0100 Subject: [PATCH 033/101] write q/a in progress --- data_manager.py | 29 ++++++++++-------------- sample_data/askmatepart2-sample-data.sql | 4 ---- server.py | 11 ++++++++- templates/add_question.html | 2 +- templates/question_page.html | 8 +++++-- 5 files changed, 29 insertions(+), 25 deletions(-) diff --git a/data_manager.py b/data_manager.py index a2c731d23..b62b3a229 100644 --- a/data_manager.py +++ b/data_manager.py @@ -1,6 +1,6 @@ import csv import os -import time +import time,datetime import connection ANSWERS_HEADER = ['id', 'submission_time', 'vote_number', 'question_id', 'message', 'image'] @@ -33,16 +33,13 @@ def update_view_number(question): question['view_number'] = view update_question(question) - -def update_vote_number(question,vote): - vote_number = question['vote_number'] - if vote == 'up': - vote_number = int(vote_number) + 1 - elif vote == 'down': - vote_number = int(vote_number) - 1 - question['view_number'] = vote_number - update_question(question) - +@connection.connection_handler +def update_vote_number(cursor,vote,q_id): + cursor.execute("""UPDATE question + set vote_number = vote_number + vote + WHERE question.id = %(q_id)s + """, + {'vote' : vote,'q_id' : q_id}) @connection.connection_handler def collect_answers(cursor, q_id): @@ -127,18 +124,16 @@ def csv_questionwriter(csv_file, dictvalue1, dictvalue2): @connection.connection_handler def add_question(cursor,message): - submission_time = "time" - #int(time.time()) - vote_number = "vote_number" + submission_time = datetime.datetime.now() + vote_number = 15 image = "img" - view_number = "view_number" + view_number = 0 title = "title" cursor.execute(""" INSERT INTO question(submission_time, view_number, vote_number, title, message, image) VALUES (%(submission_time)s,%(view_number)s,%(vote_number)s, %(title)s,%(message)s,%(image)s); """, - - {'submission_time': submission_time, 'view_number' : view_number,'vote_number': vote_number, + {'submission_time' : submission_time,'view_number' : view_number,'vote_number': vote_number, 'title' : title, 'message': message, 'image' : image}) diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index 369355a65..a51c461b8 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -17,7 +17,6 @@ ALTER TABLE IF EXISTS ONLY public.tag DROP CONSTRAINT IF EXISTS pk_tag_id CASCAD ALTER TABLE IF EXISTS ONLY public.question_tag DROP CONSTRAINT IF EXISTS fk_tag_id CASCADE; DROP TABLE IF EXISTS public.question; -DROP SEQUENCE IF EXISTS public.question_id_seq; CREATE TABLE question ( id serial NOT NULL, submission_time timestamp without time zone, @@ -29,7 +28,6 @@ CREATE TABLE question ( ); DROP TABLE IF EXISTS public.answer; -DROP SEQUENCE IF EXISTS public.answer_id_seq; CREATE TABLE answer ( id serial NOT NULL, submission_time timestamp without time zone, @@ -40,7 +38,6 @@ CREATE TABLE answer ( ); DROP TABLE IF EXISTS public.comment; -DROP SEQUENCE IF EXISTS public.comment_id_seq; CREATE TABLE comment ( id serial NOT NULL, question_id integer, @@ -58,7 +55,6 @@ CREATE TABLE question_tag ( ); DROP TABLE IF EXISTS public.tag; -DROP SEQUENCE IF EXISTS public.tag_id_seq; CREATE TABLE tag ( id serial NOT NULL, name text diff --git a/server.py b/server.py index b973bc385..0c92668e0 100644 --- a/server.py +++ b/server.py @@ -8,9 +8,18 @@ def render_index(): return render_template('index.html', questions=questions) -@app.route('/question_page/') +@app.route('/question_page/', methods=['GET','POST']) def show_question(question_id): question = data_manager.find_question(q_id=question_id) + vote = 0 + if request.method == 'POST': + vote_up = request.form.get('vote_up') + vote_down = request.form.get('vote_down') + if vote_up == 'up': + vote += 1 + if vote_down == 'down': + vote -= 1 + data_manager.update_vote_number(vote,question[0]) answers = data_manager.collect_answers(q_id=question_id) #data_manager.update_view_number(question) return render_template('question_page.html', question=question, answers=answers) diff --git a/templates/add_question.html b/templates/add_question.html index ce95d827b..b708c1fb1 100644 --- a/templates/add_question.html +++ b/templates/add_question.html @@ -11,7 +11,7 @@

Add New Question

Question Name:

Question:
-
+

diff --git a/templates/question_page.html b/templates/question_page.html index b3d873c87..d8db0e1fa 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -10,13 +10,17 @@ Submission Time: {{question[0]['submission_time']}}
View Number: {{question[0]['view_number']}}
Vote Number: {{question[0]['vote_number']}}
-
Vote up -
Vote down Title: {{question[0]['title']}}
Message:{{question[0]['message']}}
Image:{{question[0]['image']}}
edit question +

+
+ Vote UP
+ Vote DOWN
+ +

Answers:

From ab04c26181f352365f88512b537bc16e54318fa4 Mon Sep 17 00:00:00 2001 From: Zollli Date: Tue, 26 Feb 2019 16:03:20 +0100 Subject: [PATCH 034/101] ADD_question complete vote in progress --- data_manager.py | 2 +- server.py | 42 +++++++++++++++++------------------- templates/question_page.html | 38 ++++++++++++++++---------------- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/data_manager.py b/data_manager.py index c4c3ae79d..e707f198a 100644 --- a/data_manager.py +++ b/data_manager.py @@ -42,7 +42,7 @@ def update_view_number(cursor, q_id): @connection.connection_handler def update_vote_number(cursor,vote,q_id): cursor.execute("""UPDATE question - set vote_number = vote_number + vote + set vote_number = vote_number + %(vote)d WHERE question.id = %(q_id)s """, {'vote' : vote,'q_id' : q_id}) diff --git a/server.py b/server.py index c3e50d252..90474cc17 100644 --- a/server.py +++ b/server.py @@ -1,5 +1,6 @@ -from flask import Flask, render_template,request, redirect +from flask import Flask, render_template, request, redirect import data_manager + app = Flask(__name__) @@ -9,22 +10,25 @@ def render_index(): return render_template('index.html', questions=questions) -@app.route('/question_page/', methods=['GET','POST']) +@app.route('/question_page//vote') +def vote(question_id,vote_ud): + vote = 0 + if vote_ud == 'up': + vote += 1 + if vote_ud == 'down': + vote -= 1 + data_manager.update_vote_number(vote=vote, q_id=question_id) + return redirect('/question_page/') + + +@app.route('/question_page/') def show_question(question_id): question = data_manager.find_question(q_id=question_id) - vote = 0 - if request.method == 'POST': - vote_up = request.form.get('vote_up') - vote_down = request.form.get('vote_down') - if vote_up == 'up': - vote += 1 - if vote_down == 'down': - vote -= 1 - data_manager.update_vote_number(vote,question[0]) answers = data_manager.collect_answers(q_id=question_id) data_manager.update_view_number(q_id=question_id) return render_template('question_page.html', question=question, answers=answers) + @app.route('/question_page//edit') def edit_question(question_id): result = data_manager.find_question(q_id=question_id) @@ -46,9 +50,9 @@ def rewrite_question(): return redirect('/') -@app.route('/question_page//new-answer', methods=['GET','POST']) +@app.route('/question_page//new-answer', methods=['GET', 'POST']) def post_an_answer(question_id): - if request.method=='POST': + if request.method == 'POST': new_answer = create_answer(question_id, request.form['message'], request.form['image']) data_manager.add_answer(form_data=new_answer) return redirect('/') @@ -66,25 +70,19 @@ def create_answer(question_id, message, image): } -@app.route('/add-question',methods=['GET','POST']) +@app.route('/add-question', methods=['GET', 'POST']) def add_question(): result = [] message = "" if request.method == 'POST': - question_name = request.form.get('question_name') message = request.form.get('message') data_manager.add_question(message) return redirect('/') - return render_template('add_question.html', message=message,result = result) - - -@app.route('/question_page//vote', methods=['POST']) -def vote(): - vote + return render_template('add_question.html', message=message, result=result) -if __name__=="__main__": +if __name__ == "__main__": app.run( debug=True, port=5000 diff --git a/templates/question_page.html b/templates/question_page.html index 6dd22a987..6c4a879c9 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -2,35 +2,37 @@ - {{question['title']}} + {{ question['title'] }}
{% include 'home_button.html' %}

-ID :{{question[0]['id']}}
-Submission Time: {{question[0]['submission_time']}}
-View Number: {{question[0]['view_number']}}
-Vote Number: {{question[0]['vote_number']}}
-Title: {{question[0]['title']}}
-Message:{{question[0]['message']}}
-Image:{{question[0]['image']}}
+ID :{{ question[0]['id'] }}
+Submission Time: {{ question[0]['submission_time'] }}
+View Number: {{ question[0]['view_number'] }}
+Vote Number: {{ question[0]['vote_number'] }}
+Title: {{ question[0]['title'] }}
+Message:{{ question[0]['message'] }}
+Image:{{ question[0]['image'] }}
-edit question -

-
- Vote UP
- Vote DOWN
- + +edit question + + Vote UP
+ + Vote DOWN
+ +

Answers:

-{%for answer in answers%} - {{answer['message']}} +{% for answer in answers %} + {{ answer['message'] }}
-{%endfor%} +{% endfor %}
- Post an Answer + Post an Answer \ No newline at end of file From 855b84c308d499bd4370eecccf40727e7183f880 Mon Sep 17 00:00:00 2001 From: LibLev Date: Tue, 26 Feb 2019 16:27:27 +0100 Subject: [PATCH 035/101] edit answer is ready to use --- data_manager.py | 31 +++++++++++-------------------- server.py | 24 +++++++++++++++++++++++- templates/new_answer.html | 19 ++++++++++++++++++- templates/question_page.html | 3 +++ 4 files changed, 55 insertions(+), 22 deletions(-) diff --git a/data_manager.py b/data_manager.py index fb0dff1c6..fa818fc87 100644 --- a/data_manager.py +++ b/data_manager.py @@ -71,6 +71,17 @@ def update_question(cursor, datas): (datas['message'], datas['image'], int(datas['id']))) +@connection.connection_handler +def find_answer(cursor, a_id): + cursor.execute(""" + SELECT * from answer + where id = %(a_id)s + """, + {'a_id': a_id}) + result = cursor.fetchall() + return result + + @connection.connection_handler def update_answer(cursor, datas): cursor.execute(""" @@ -103,26 +114,6 @@ def add_answer(cursor, form_data): form_data['message'], form_data['image'])) -def new_id(file_name): - with open(file_name, 'r') as file: - file_read = csv.DictReader(file, fieldnames=DATA_HEADER) - for row in file_read: - new_id = row['id'] - return int(new_id) + 1 - - -def csv_questionwriter(csv_file, dictvalue1, dictvalue2): - with open(csv_file, 'a', newline='') as csvfile: - writer = csv.DictWriter(csvfile, fieldnames=DATA_HEADER) - question_id = new_id(csv_file) - view_counter = 0 - vote_counter = 0 - submission_time = int(time.time()) - writer.writerow({'id': question_id, 'submission_time': submission_time, 'view_number': view_counter, - - 'vote_number': vote_counter, 'title': dictvalue1, 'message': dictvalue2}) - - @connection.connection_handler def add_question(cursor, message): submission_time = "time" diff --git a/server.py b/server.py index 001b9d1d1..457951aaf 100644 --- a/server.py +++ b/server.py @@ -39,12 +39,15 @@ def rewrite_question(): @app.route('/question_page//new-answer', methods=['GET','POST']) def post_an_answer(question_id): + result = [] + message = "" if request.method=='POST': new_answer = create_answer(question_id, request.form['message'], request.form['image']) data_manager.add_answer(form_data=new_answer) return redirect('/') question = data_manager.find_question(question_id) - return render_template('new_answer.html', question=question) + return render_template('new_answer.html', question=question, result=result, message=message) + def create_answer(question_id, message, image): @@ -56,6 +59,25 @@ def create_answer(question_id, message, image): 'image': image } +@app.route('/question_page//update') +def edit_answer(answer_id): + result = data_manager.find_answer(a_id=answer_id) + return render_template('new_answer.html', result=result) + + +@app.route('/rewrite_answer', methods=['POST']) +def rewrite_answer(): + updated_answer = { + 'id': request.form.get('id'), + 'submission_time': request.form.get('submission_time'), + 'vote_number': request.form.get('vote_number'), + 'question_id': request.form.get('question_id'), + 'message': request.form.get('message'), + 'image': request.form.get('image'), + } + data_manager.update_answer(datas=updated_answer) + return redirect('/') + @app.route('/add-question',methods=['GET','POST']) def add_question(): diff --git a/templates/new_answer.html b/templates/new_answer.html index 8cfa154a1..720b293b5 100644 --- a/templates/new_answer.html +++ b/templates/new_answer.html @@ -6,6 +6,7 @@ {% include 'home_button.html' %} +{% if result == [] %}

Post an Answer

@@ -19,5 +20,21 @@

Post an Answer


+{% else %} +

Edit answer

+ + Answer:
+
+
+ + + + + + + + {% endif %} + + - \ No newline at end of file + diff --git a/templates/question_page.html b/templates/question_page.html index 78c93e070..243d74feb 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -25,6 +25,9 @@

Answers:

{%for answer in answers%} {{answer['message']}} + + edit answer +
{%endfor%} From cbe05de54079496896526cbd6d5da47c3677e7dc Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 27 Feb 2019 11:18:36 +0100 Subject: [PATCH 036/101] add question been fixed --- data_manager.py | 19 +++++++------------ server.py | 19 +++++++++++++++---- templates/add_question.html | 6 ++++-- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/data_manager.py b/data_manager.py index eef0d4793..067044b71 100644 --- a/data_manager.py +++ b/data_manager.py @@ -63,9 +63,9 @@ def collect_answers(cursor, q_id): def update_question(cursor, datas): cursor.execute(""" UPDATE question - SET message=%s, image=%s + SET title=%s, message=%s, image=%s WHERE id=%s""", - (datas['message'], datas['image'], int(datas['id']))) + (datas['title'],datas['message'], datas['image'], int(datas['id']))) @connection.connection_handler @@ -112,15 +112,10 @@ def add_answer(cursor, form_data): @connection.connection_handler -def add_question(cursor,message): - submission_time = datetime.datetime.now() - vote_number = 15 - image = "img" - view_number = 0 - title = "title" +def add_question(cursor,from_data): cursor.execute(""" INSERT INTO question(submission_time, view_number, vote_number, title, message, image) - VALUES (%(submission_time)s,%(view_number)s,%(vote_number)s, %(title)s,%(message)s,%(image)s); - """, - {'submission_time' : submission_time,'view_number' : view_number,'vote_number': vote_number, - 'title' : title, 'message': message, 'image' : image}) + VALUES (%s,%s,%s, %s,%s,%s)""", + (from_data['submission_time'], from_data['view_number'], from_data['vote_number'], from_data['title'], + from_data['message'], from_data['image'])) + diff --git a/server.py b/server.py index ba774fc36..3212902e7 100644 --- a/server.py +++ b/server.py @@ -97,11 +97,22 @@ def add_question(): result = [] message = "" if request.method == 'POST': - question_name = request.form.get('question_name') - message = request.form.get('message') - data_manager.add_question(message) + new_question = create_question(request.form['message'], request.form['image'], request.form['title']) + data_manager.add_question(from_data=new_question) return redirect('/') - return render_template('add_question.html', message=message, result=result) + return render_template('add_question.html', result=result, message=message) + + +def create_question(message, image, title): + return { + 'submission_time': data_manager.submission_time_generator(), + 'vote_number': 1, + 'message': message, + 'title': title, + 'image': image, + 'view_number' : 1 + } + if __name__ == "__main__": diff --git a/templates/add_question.html b/templates/add_question.html index d8a028846..6adbcfbe0 100644 --- a/templates/add_question.html +++ b/templates/add_question.html @@ -10,9 +10,11 @@

Add New Question

Question Name:
-
+
Question:

+ Image:
+
@@ -20,7 +22,7 @@

Add New Question

Edit Question

Question Name:
-
+
Question:


From 9a019b32d62e55fe851663e5d5d01dc6d313c599 Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 27 Feb 2019 11:49:54 +0100 Subject: [PATCH 037/101] show top 5 question and show all question --- data_manager.py | 9 +++++++++ server.py | 7 ++++++- templates/all_question.html | 20 ++++++++++++++++++++ templates/index.html | 5 +++-- 4 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 templates/all_question.html diff --git a/data_manager.py b/data_manager.py index 067044b71..f38deff08 100644 --- a/data_manager.py +++ b/data_manager.py @@ -18,6 +18,15 @@ def collect_questions(cursor): result = cursor.fetchall() return result +@connection.connection_handler +def collect_latest_5_question(cursor): + cursor.execute(""" + SELECT * FROM question + ORDER BY submission_time DESC + LIMIT 5""") + result = cursor.fetchall() + return result + @connection.connection_handler def find_question(cursor, q_id): diff --git a/server.py b/server.py index 3212902e7..6a17fa041 100644 --- a/server.py +++ b/server.py @@ -6,9 +6,14 @@ @app.route('/') def render_index(): - questions = data_manager.collect_questions() + questions = data_manager.collect_latest_5_question() return render_template('index.html', questions=questions) +@app.route('/all_question') +def show_all_question(): + questions = data_manager.collect_questions() + return render_template('all_question.html', questions=questions) + @app.route('/question_page//vote') def vote(question_id,vote_ud): diff --git a/templates/all_question.html b/templates/all_question.html new file mode 100644 index 000000000..f0fd881be --- /dev/null +++ b/templates/all_question.html @@ -0,0 +1,20 @@ + + + + + All Question + + +

All Question

+
+ {{question['title']}}
Question ID Question ID Message
Question ID
+ + {% for question in questions%} + + + {% endfor %} + + +
+ {{question['title']}}
+ + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 98a2e00b0..34d833881 100644 --- a/templates/index.html +++ b/templates/index.html @@ -7,7 +7,8 @@

ASK MATE

Add new Question -

QUESTIONS:

+Show All Question +

LATEST 5 QUESTION:

@@ -18,6 +19,6 @@

QUESTIONS:

{% endfor %} -
+
\ No newline at end of file From 533c0b9353b6fa33afd91d1173718125a425a97d Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 27 Feb 2019 13:01:10 +0100 Subject: [PATCH 038/101] search question kinda working --- data_manager.py | 12 +++++++++++- server.py | 10 ++++++++++ templates/add_question.html | 2 +- templates/home_button.html | 2 ++ templates/index.html | 15 +++++++++++---- 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/data_manager.py b/data_manager.py index f38deff08..fc1a4b316 100644 --- a/data_manager.py +++ b/data_manager.py @@ -1,4 +1,3 @@ -import csv import os import time,datetime import connection @@ -120,6 +119,17 @@ def add_answer(cursor, form_data): form_data['message'], form_data['image'])) +@connection.connection_handler +def search_question_id(cursor, title_name): + cursor.execute(""" + select id from question + where title = %(title_name)s + """, + {'title_name': title_name}) + result = cursor.fetchall() + return result + + @connection.connection_handler def add_question(cursor,from_data): cursor.execute(""" diff --git a/server.py b/server.py index 6a17fa041..db0bec016 100644 --- a/server.py +++ b/server.py @@ -9,6 +9,7 @@ def render_index(): questions = data_manager.collect_latest_5_question() return render_template('index.html', questions=questions) + @app.route('/all_question') def show_all_question(): questions = data_manager.collect_questions() @@ -26,6 +27,15 @@ def vote(question_id,vote_ud): return redirect('/question_page/') +@app.route('/search', methods=['POST']) +def search(): + question_title = request.form.get('question_title') + question_id = data_manager.search_question_id(question_title) + if question_id == []: + return redirect('/') + else: + return show_question(question_id[0]['id']) + @app.route('/question_page/') def show_question(question_id): question = data_manager.find_question(q_id=question_id) diff --git a/templates/add_question.html b/templates/add_question.html index 6adbcfbe0..5151799bc 100644 --- a/templates/add_question.html +++ b/templates/add_question.html @@ -20,7 +20,7 @@

Add New Question

{% else %}

Edit Question

-
+ Question Name:

Question:
diff --git a/templates/home_button.html b/templates/home_button.html index 3e8d3d12b..154fcb27a 100644 --- a/templates/home_button.html +++ b/templates/home_button.html @@ -6,5 +6,7 @@ Home + + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 34d833881..abe1a50ed 100644 --- a/templates/index.html +++ b/templates/index.html @@ -5,18 +5,25 @@ Index + + + + +
+

ASK MATE

Add new Question Show All Question

LATEST 5 QUESTION:

+ - {% for question in questions%} - + {% for question in questions %} + - {% endfor %} + {{ question['title'] }} + {% endfor %}
- {{question['title']}}

From 57647edb6eec3eda02b37a3b253791740d5c0b34 Mon Sep 17 00:00:00 2001 From: Zollli Date: Wed, 27 Feb 2019 13:03:48 +0100 Subject: [PATCH 039/101] vote in progress --- templates/question_page.html | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/templates/question_page.html b/templates/question_page.html index 8f0ad5a5d..a3b93f07a 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -19,17 +19,16 @@ edit question - - - Vote UP
- - Vote DOWN
- +
+ Vote UP
+ Vote DOWN
+ +

Answers:

{%for answer in answers%} {{answer['message']}} -
+ edit answer

From 74635d6fbca40a632e16986e09d3e44236769c25 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 27 Feb 2019 14:44:10 +0100 Subject: [PATCH 040/101] search question kinda working really --- data_manager.py | 29 ++++++++++++++++++++++++++++- server.py | 18 ++++++++++-------- templates/home_button.html | 4 ++++ templates/index.html | 2 +- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/data_manager.py b/data_manager.py index fc1a4b316..e56ce4c57 100644 --- a/data_manager.py +++ b/data_manager.py @@ -17,6 +17,33 @@ def collect_questions(cursor): result = cursor.fetchall() return result +@connection.connection_handler +def delete_question(cursor, q_id): + cursor.execute(""" + delete from question + where id = %(q_id)s + """, + {'q_id': q_id}) + cursor.execute(""" + delete from answer + where question_id = %(q_id)s + """, + {'q_id': q_id}) + +@connection.connection_handler +def find_searched_questions(cursor, searched_data): + searched_data = "%"+searched_data+"%" + cursor.execute(""" + select * from question + where title ilike %(searched_data)s + OR + message ilike %(searched_data)s + """, + {'searched_data': searched_data}) + result = cursor.fetchall() + return result + + @connection.connection_handler def collect_latest_5_question(cursor): cursor.execute(""" @@ -118,7 +145,7 @@ def add_answer(cursor, form_data): (form_data['submission_time'], form_data['vote_number'], form_data['question_id'], form_data['message'], form_data['image'])) - +# TODO delete this maybe @connection.connection_handler def search_question_id(cursor, title_name): cursor.execute(""" diff --git a/server.py b/server.py index db0bec016..9d4fa55ad 100644 --- a/server.py +++ b/server.py @@ -17,7 +17,7 @@ def show_all_question(): @app.route('/question_page//vote') -def vote(question_id,vote_ud): +def vote(): vote = 0 if vote_ud == 'up': vote += 1 @@ -26,15 +26,17 @@ def vote(question_id,vote_ud): data_manager.update_vote_number(vote=vote, q_id=question_id) return redirect('/question_page/') +#@app.route('/question_page/') + @app.route('/search', methods=['POST']) def search(): - question_title = request.form.get('question_title') - question_id = data_manager.search_question_id(question_title) - if question_id == []: - return redirect('/') - else: - return show_question(question_id[0]['id']) + question_data = request.form.get('question_data') + print(question_data) + result = data_manager.find_searched_questions(searched_data=question_data) + print(result) + return render_template('all_question.html', questions=result) + @app.route('/question_page/') def show_question(question_id): @@ -77,7 +79,6 @@ def post_an_answer(question_id): return render_template('new_answer.html', question=question, result=result, message=message) - def create_answer(question_id, message, image): return { 'submission_time': data_manager.submission_time_generator(), @@ -87,6 +88,7 @@ def create_answer(question_id, message, image): 'image': image } + @app.route('/question_page//update') def edit_answer(answer_id): result = data_manager.find_answer(a_id=answer_id) diff --git a/templates/home_button.html b/templates/home_button.html index 154fcb27a..65705f23c 100644 --- a/templates/home_button.html +++ b/templates/home_button.html @@ -8,5 +8,9 @@ Home +
+ + +
\ No newline at end of file diff --git a/templates/index.html b/templates/index.html index abe1a50ed..e4e7e643f 100644 --- a/templates/index.html +++ b/templates/index.html @@ -7,7 +7,7 @@
- +
From 7ecfc16423ec82d7764066bac2899c40dca5592b Mon Sep 17 00:00:00 2001 From: Zollli Date: Wed, 27 Feb 2019 15:01:24 +0100 Subject: [PATCH 041/101] implemented vote --- data_manager.py | 9 +++++---- server.py | 22 +++++++++++++--------- templates/question_page.html | 9 ++++++--- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/data_manager.py b/data_manager.py index fc1a4b316..ab8375552 100644 --- a/data_manager.py +++ b/data_manager.py @@ -49,11 +49,12 @@ def update_view_number(cursor, q_id): @connection.connection_handler def update_vote_number(cursor,vote,q_id): - cursor.execute("""UPDATE question - set vote_number = vote_number + %(vote)d - WHERE question.id = %(q_id)s + cursor.execute(""" + UPDATE question + set vote_number = %(vote)s + WHERE id = %(q_id)s """, - {'vote' : vote,'q_id' : q_id}) + {'vote' : vote,'q_id' : q_id}) @connection.connection_handler def collect_answers(cursor, q_id): diff --git a/server.py b/server.py index db0bec016..eb512cbf6 100644 --- a/server.py +++ b/server.py @@ -16,15 +16,19 @@ def show_all_question(): return render_template('all_question.html', questions=questions) -@app.route('/question_page//vote') -def vote(question_id,vote_ud): - vote = 0 - if vote_ud == 'up': - vote += 1 - if vote_ud == 'down': - vote -= 1 - data_manager.update_vote_number(vote=vote, q_id=question_id) - return redirect('/question_page/') +@app.route('/question_page/vote',methods=['GET','POST']) +def vote(): + vote = int(request.form.get('vote_num')) + vote_up = request.form.get('vote_up') + vote_down = request.form.get('vote_down') + q_id = request.form.get('q_id') + if request.method == 'POST': + if vote_up == 'up': + vote += 1 + elif vote_down == 'down': + vote -= 1 + data_manager.update_vote_number(vote=vote, q_id=q_id) + return redirect('/') @app.route('/search', methods=['POST']) diff --git a/templates/question_page.html b/templates/question_page.html index a3b93f07a..d7ead828b 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -19,9 +19,12 @@ edit question -
- Vote UP
- Vote DOWN
+ + + + + Vote UP
+ Vote DOWN
From f0d6d12eb86401099ae3ff44e2a0f800af99db52 Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 27 Feb 2019 15:17:24 +0100 Subject: [PATCH 042/101] all question html added --- templates/all_question.html | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/all_question.html b/templates/all_question.html index f0fd881be..2f2b2b302 100644 --- a/templates/all_question.html +++ b/templates/all_question.html @@ -5,6 +5,7 @@ All Question +{% include 'home_button.html' %}

All Question

From e223d15e18aae27f71e7f66813d86dc4a5bbe1be Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 27 Feb 2019 15:39:01 +0100 Subject: [PATCH 043/101] Merge branch 'master' of /home/boros/codecool/web_sql/ask-mate-python with conflicts. --- data_manager.py | 49 ++++++++++++++++++++++++------------ server.py | 22 +++++++++++++--- templates/question_page.html | 6 +++-- 3 files changed, 56 insertions(+), 21 deletions(-) diff --git a/data_manager.py b/data_manager.py index 533d7f608..714f9501e 100644 --- a/data_manager.py +++ b/data_manager.py @@ -1,5 +1,5 @@ import os -import time,datetime +import time, datetime import connection ANSWERS_HEADER = ['id', 'submission_time', 'vote_number', 'question_id', 'message', 'image'] @@ -17,22 +17,36 @@ def collect_questions(cursor): result = cursor.fetchall() return result + @connection.connection_handler def delete_question(cursor, q_id): cursor.execute(""" + delete from question_tag + where question_id = %(q_id)s; + delete from comment + where question_id = %(q_id)s; + delete from answer + where question_id = %(q_id)s; delete from question where id = %(q_id)s """, - {'q_id': q_id}) + {'q_id': q_id}) + + +@connection.connection_handler +def delete_answer(cursor, q_id, a_id): cursor.execute(""" + delete from comment + where question_id = %(q_id)s or answer_id = %(a_id)s; delete from answer - where question_id = %(q_id)s + where question_id = %(q_id)s and id = %(a_id)s """, - {'q_id': q_id}) + {'q_id': q_id, 'a_id': a_id}) + @connection.connection_handler def find_searched_questions(cursor, searched_data): - searched_data = "%"+searched_data+"%" + searched_data = "%" + searched_data + "%" cursor.execute(""" select * from question where title ilike %(searched_data)s @@ -74,14 +88,15 @@ def update_view_number(cursor, q_id): """, {'q_id': q_id}) + @connection.connection_handler -def update_vote_number(cursor,vote,q_id): - cursor.execute(""" - UPDATE question - set vote_number = %(vote)s - WHERE id = %(q_id)s +def update_vote_number(cursor, vote, q_id): + cursor.execute("""UPDATE question + set vote_number = vote_number + %(vote)d + WHERE question.id = %(q_id)s """, - {'vote' : vote,'q_id' : q_id}) + {'vote': vote, 'q_id': q_id}) + @connection.connection_handler def collect_answers(cursor, q_id): @@ -101,7 +116,7 @@ def update_question(cursor, datas): UPDATE question SET title=%s, message=%s, image=%s WHERE id=%s""", - (datas['title'],datas['message'], datas['image'], int(datas['id']))) + (datas['title'], datas['message'], datas['image'], int(datas['id']))) @connection.connection_handler @@ -146,6 +161,7 @@ def add_answer(cursor, form_data): (form_data['submission_time'], form_data['vote_number'], form_data['question_id'], form_data['message'], form_data['image'])) + # TODO delete this maybe @connection.connection_handler def search_question_id(cursor, title_name): @@ -159,10 +175,11 @@ def search_question_id(cursor, title_name): @connection.connection_handler -def add_question(cursor,from_data): +def add_question(cursor, from_data): cursor.execute(""" INSERT INTO question(submission_time, view_number, vote_number, title, message, image) VALUES (%s,%s,%s, %s,%s,%s)""", - (from_data['submission_time'], from_data['view_number'], from_data['vote_number'], from_data['title'], - from_data['message'], from_data['image'])) - + ( + from_data['submission_time'], from_data['view_number'], from_data['vote_number'], + from_data['title'], + from_data['message'], from_data['image'])) diff --git a/server.py b/server.py index a5b062f44..48e722863 100644 --- a/server.py +++ b/server.py @@ -16,8 +16,21 @@ def show_all_question(): return render_template('all_question.html', questions=questions) -@app.route('/question_page/vote',methods=['GET','POST']) +@app.route('/question_page//vote') def vote(): + vote = 0 + if vote_ud == 'up': + vote += 1 + if vote_ud == 'down': + vote -= 1 + data_manager.update_vote_number(vote=vote, q_id=question_id) + return redirect('/question_page/') + + +@app.route('/question_page//delete') +def delete_question(question_id): + data_manager.delete_question(q_id=question_id) + return show_all_question() vote = int(request.form.get('vote_num')) vote_up = request.form.get('vote_up') vote_down = request.form.get('vote_down') @@ -31,12 +44,15 @@ def vote(): return redirect('/') +@app.route('/question_page///answer-delete') +def delete_answer(question_id, answer_id): + data_manager.delete_answer(q_id=question_id, a_id=answer_id) + return show_question(question_id) + @app.route('/search', methods=['POST']) def search(): question_data = request.form.get('question_data') - print(question_data) result = data_manager.find_searched_questions(searched_data=question_data) - print(result) return render_template('all_question.html', questions=result) diff --git a/templates/question_page.html b/templates/question_page.html index d7ead828b..c0e030796 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -19,6 +19,7 @@ edit question + Delete question
@@ -33,8 +34,9 @@

Answers:

{{answer['message']}} edit answer - -
+ delete answer + +

{%endfor%}
Post an Answer From e041f8980ac6c2eb2a017e6a990330fb9a6f4c6a Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 27 Feb 2019 16:55:04 +0100 Subject: [PATCH 044/101] sort is fuckin' ready --- data_manager.py | 10 ++++++++++ server.py | 17 +++++++++++++++++ templates/all_question.html | 13 +++++++++++++ 3 files changed, 40 insertions(+) diff --git a/data_manager.py b/data_manager.py index 533d7f608..c21136c3f 100644 --- a/data_manager.py +++ b/data_manager.py @@ -9,6 +9,16 @@ ANSWERS_FILE_PATH = os.getenv('ANSWERS_FILE_PATH', 'sample_data/answer.csv') +@connection.connection_handler +def sort_questions(cursor, option, how): + option = option + cursor.execute(""" + SELECT * FROM question + ORDER BY {option} {how} + """.format(option=option,how=how)) + result = cursor.fetchall() + return result + @connection.connection_handler def collect_questions(cursor): cursor.execute(""" diff --git a/server.py b/server.py index a5b062f44..e677d94ca 100644 --- a/server.py +++ b/server.py @@ -16,6 +16,23 @@ def show_all_question(): return render_template('all_question.html', questions=questions) + +@app.route('/all_question/sort',methods=['GET', 'POST']) +def show_all_sorted_question(): + questions = sort_questions() + return render_template('all_question.html', questions=questions) + + + +def sort_questions(): + sort_options = request.form.get('sort_options') + option = request.form.get('options') + result = data_manager.sort_questions(option=option, how=sort_options) + return result + + + + @app.route('/question_page/vote',methods=['GET','POST']) def vote(): vote = int(request.form.get('vote_num')) diff --git a/templates/all_question.html b/templates/all_question.html index 2f2b2b302..cd052dfea 100644 --- a/templates/all_question.html +++ b/templates/all_question.html @@ -5,6 +5,19 @@ All Question + + Sort by: + + + + {% include 'home_button.html' %}

All Question

From 15f658f7a4c16015480d7bacd80800b34a851cdf Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 27 Feb 2019 17:10:15 +0100 Subject: [PATCH 045/101] add comment to question --- data_manager.py | 19 ++++++++++++++----- server.py | 13 ++++++++++++- templates/add_comment.html | 15 +++++++++++++++ templates/question_page.html | 7 +++++++ 4 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 templates/add_comment.html diff --git a/data_manager.py b/data_manager.py index 3905d0cb8..ed56ea51f 100644 --- a/data_manager.py +++ b/data_manager.py @@ -172,14 +172,23 @@ def add_answer(cursor, form_data): form_data['message'], form_data['image'])) -# TODO delete this maybe @connection.connection_handler -def search_question_id(cursor, title_name): +def add_comment_to_question(cursor, q_id, comment_message): cursor.execute(""" - select id from question - where title = %(title_name)s + insert into comment(question_id, message) + values (%(q_id)s,%(comment_message)s) + """, - {'title_name': title_name}) + {'q_id': q_id, 'comment_message': comment_message}) + + +@connection.connection_handler +def collect_comment(cursor, q_id): + cursor.execute(""" + Select message from comment + where question_id = %(q_id)s + """, + {'q_id': q_id}) result = cursor.fetchall() return result diff --git a/server.py b/server.py index 3af76cc6f..60b7052e6 100644 --- a/server.py +++ b/server.py @@ -64,8 +64,11 @@ def search(): def show_question(question_id): question = data_manager.find_question(q_id=question_id) answers = data_manager.collect_answers(q_id=question_id) + print(answers) data_manager.update_view_number(q_id=question_id) - return render_template('question_page.html', question=question, answers=answers) + comment = data_manager.collect_comment(q_id=question_id) + print(comment) + return render_template('question_page.html', question=question, answers=answers, comment=comment) @app.route('/question_page//edit') @@ -154,6 +157,14 @@ def create_question(message, image, title): } +@app.route('/question_page//comment', methods=['GET','POST']) +def add_comment(question_id): + if request.method=='POST': + message = request.form['message'] + data_manager.add_comment_to_question(q_id=question_id, comment_message=message) + return show_question(question_id) + return render_template('add_comment.html', question_id=question_id) + if __name__ == "__main__": app.run( diff --git a/templates/add_comment.html b/templates/add_comment.html new file mode 100644 index 000000000..fb654be94 --- /dev/null +++ b/templates/add_comment.html @@ -0,0 +1,15 @@ + + + + + ADD COMMENT + + +

Add Comment

+
+ Comment:
+
+ + + + \ No newline at end of file diff --git a/templates/question_page.html b/templates/question_page.html index c0e030796..15fbbc98b 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -15,12 +15,19 @@ Message:{{ question[0]['message'] }}
Image:{{ question[0]['image'] }}
+

Comments

+{% for message in comment%} + {{ message['message']}}
+{% endfor %} +
edit question Delete question
+Add Comment +
From 090bcfb2baf07f0959b601d238338ee384ca268a Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 27 Feb 2019 17:15:16 +0100 Subject: [PATCH 046/101] we get delete question back --- server.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/server.py b/server.py index 60b7052e6..216bc4a94 100644 --- a/server.py +++ b/server.py @@ -48,6 +48,22 @@ def vote(): return redirect('/') +@app.route('/question_page//delete') +def delete_question(question_id): + data_manager.delete_question(q_id=question_id) + return show_all_question() + vote = int(request.form.get('vote_num')) + vote_up = request.form.get('vote_up') + vote_down = request.form.get('vote_down') + q_id = request.form.get('q_id') + if request.method == 'POST': + if vote_up == 'up': + vote += 1 + elif vote_down == 'down': + vote -= 1 + data_manager.update_vote_number(vote=vote, q_id=q_id) + return redirect('/') + @app.route('/question_page///answer-delete') def delete_answer(question_id, answer_id): data_manager.delete_answer(q_id=question_id, a_id=answer_id) @@ -71,6 +87,7 @@ def show_question(question_id): return render_template('question_page.html', question=question, answers=answers, comment=comment) + @app.route('/question_page//edit') def edit_question(question_id): result = data_manager.find_question(q_id=question_id) From 653f3f26422af5e36cacd11b9ac6ec53096109d3 Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 27 Feb 2019 17:27:07 +0100 Subject: [PATCH 047/101] question page been edited --- server.py | 4 ---- templates/question_page.html | 10 +++++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/server.py b/server.py index 216bc4a94..3475819a0 100644 --- a/server.py +++ b/server.py @@ -16,7 +16,6 @@ def show_all_question(): return render_template('all_question.html', questions=questions) - @app.route('/all_question/sort',methods=['GET', 'POST']) def show_all_sorted_question(): questions = sort_questions() @@ -31,8 +30,6 @@ def sort_questions(): return result - - @app.route('/question_page/vote',methods=['GET','POST']) def vote(): vote = int(request.form.get('vote_num')) @@ -121,7 +118,6 @@ def post_an_answer(question_id): return render_template('new_answer.html', question=question, result=result, message=message) - def create_answer(question_id, message, image): return { 'submission_time': data_manager.submission_time_generator(), diff --git a/templates/question_page.html b/templates/question_page.html index 15fbbc98b..ac837adc0 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -15,17 +15,17 @@ Message:{{ question[0]['message'] }}
Image:{{ question[0]['image'] }}
-

Comments

-{% for message in comment%} - {{ message['message']}}
-{% endfor %} - edit question Delete question
+

Comments

+{% for message in comment%} + {{ message['message']}}
+{% endfor %} + Add Comment
From 632bca0cc0d5ab2618e8d758fa8b075ffb381f44 Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 27 Feb 2019 20:22:07 +0100 Subject: [PATCH 048/101] vote been fixed --- data_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_manager.py b/data_manager.py index ed56ea51f..b11b136fd 100644 --- a/data_manager.py +++ b/data_manager.py @@ -102,7 +102,7 @@ def update_view_number(cursor, q_id): @connection.connection_handler def update_vote_number(cursor, vote, q_id): cursor.execute("""UPDATE question - set vote_number = vote_number + %(vote)d + set vote_number = vote_number + %(vote)s WHERE question.id = %(q_id)s """, {'vote': vote, 'q_id': q_id}) From 9a68a9c1814ed52129c2758089bf367b2568a691 Mon Sep 17 00:00:00 2001 From: LibLev Date: Thu, 28 Feb 2019 13:55:21 +0100 Subject: [PATCH 049/101] add comment in progress --- data_manager.py | 22 +++++++++++++++++++++- server.py | 26 +++++++++++++++++++++----- templates/add_comment.html | 18 ++++++++++++++---- templates/question_page.html | 12 +++++++++--- 4 files changed, 65 insertions(+), 13 deletions(-) diff --git a/data_manager.py b/data_manager.py index b11b136fd..92a069688 100644 --- a/data_manager.py +++ b/data_manager.py @@ -183,7 +183,17 @@ def add_comment_to_question(cursor, q_id, comment_message): @connection.connection_handler -def collect_comment(cursor, q_id): +def add_comment_to_answer(cursor, a_id, comment_message): + cursor.execute(""" + insert into comment(answer_id, message) + values (%(a_id)s,%(comment_message)s) + + """, + {'a_id': a_id, 'comment_message': comment_message}) + + +@connection.connection_handler +def collect_comment_to_question(cursor, q_id): cursor.execute(""" Select message from comment where question_id = %(q_id)s @@ -192,6 +202,16 @@ def collect_comment(cursor, q_id): result = cursor.fetchall() return result +@connection.connection_handler +def collect_comment_to_answer(cursor, a_id): + cursor.execute(""" + Select message, answer_id from comment + where answer_id = %(a_id)s + """, + {'a_id': a_id}) + result = cursor.fetchall() + return result + @connection.connection_handler def add_question(cursor, from_data): diff --git a/server.py b/server.py index 3475819a0..3dda78df9 100644 --- a/server.py +++ b/server.py @@ -79,9 +79,13 @@ def show_question(question_id): answers = data_manager.collect_answers(q_id=question_id) print(answers) data_manager.update_view_number(q_id=question_id) - comment = data_manager.collect_comment(q_id=question_id) + comment = data_manager.collect_comment_to_question(q_id=question_id) print(comment) - return render_template('question_page.html', question=question, answers=answers, comment=comment) + answer_comment = [] + for answer in answers: + answer_comment.append(data_manager.collect_comment_to_answer(a_id= answer['id'])) + print(answer_comment) + return render_template('question_page.html', question=question, answers=answers, comment=comment, answer_comment=answer_comment) @@ -171,14 +175,26 @@ def create_question(message, image, title): @app.route('/question_page//comment', methods=['GET','POST']) -def add_comment(question_id): - if request.method=='POST': +def add_comment_to_question(question_id): + comment = 'question' + if request.method == 'POST': message = request.form['message'] - data_manager.add_comment_to_question(q_id=question_id, comment_message=message) + data_manager.add_comment_to_question(q_id=question_id, comment_message=message, comment=comment) + return show_question(question_id) return render_template('add_comment.html', question_id=question_id) +@app.route('/question_page///comment', methods=['GET','POST']) +def add_comment_to_answer(answer_id,question_id): + comment = 'answer' + if request.method == 'POST': + message = request.form['message'] + data_manager.add_comment_to_answer(a_id=answer_id, comment_message=message) + return show_question(question_id) + return render_template('add_comment.html', answer_id=answer_id, question_id=question_id, comment=comment) + + if __name__ == "__main__": app.run( debug=True, diff --git a/templates/add_comment.html b/templates/add_comment.html index fb654be94..ce080bd57 100644 --- a/templates/add_comment.html +++ b/templates/add_comment.html @@ -6,10 +6,20 @@

Add Comment

- - Comment:
-
- +{% if comment == 'question' %} + + Comment:
+
+ + +{% elif comment == 'answer' %} + + Comment:
+
+ + + +{% endif %} \ No newline at end of file diff --git a/templates/question_page.html b/templates/question_page.html index ac837adc0..b73e081b4 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -26,7 +26,7 @@

Comments

{{ message['message']}}
{% endfor %} -Add Comment +Add Comment
@@ -38,11 +38,17 @@

Comments

Answers:

{%for answer in answers%} - {{answer['message']}} + {{answer['message']}}
+ comments: + {% for comment in answer_comment %} + {% if comment['answer_id'] == answer['id'] %} + {{ comment['message'] }} + {% endif %} + {% endfor %} + Add Comment edit answer delete answer -

{%endfor%}
From 42847424aa163bfac8560bcb8eb05a25e7eec854 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Thu, 28 Feb 2019 14:32:05 +0100 Subject: [PATCH 050/101] Add comment to answer is ready, more info in the main page --- server.py | 17 ++++++++------- templates/index.html | 15 ++++++++++--- templates/question_page.html | 42 +++++++++++++++++++----------------- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/server.py b/server.py index 3dda78df9..a91e85844 100644 --- a/server.py +++ b/server.py @@ -22,7 +22,6 @@ def show_all_sorted_question(): return render_template('all_question.html', questions=questions) - def sort_questions(): sort_options = request.form.get('sort_options') option = request.form.get('options') @@ -61,11 +60,13 @@ def delete_question(question_id): data_manager.update_vote_number(vote=vote, q_id=q_id) return redirect('/') + @app.route('/question_page///answer-delete') def delete_answer(question_id, answer_id): data_manager.delete_answer(q_id=question_id, a_id=answer_id) return show_question(question_id) + @app.route('/search', methods=['POST']) def search(): question_data = request.form.get('question_data') @@ -83,10 +84,10 @@ def show_question(question_id): print(comment) answer_comment = [] for answer in answers: - answer_comment.append(data_manager.collect_comment_to_answer(a_id= answer['id'])) - print(answer_comment) - return render_template('question_page.html', question=question, answers=answers, comment=comment, answer_comment=answer_comment) - + print(answer['id']) + answer_comment.append(data_manager.collect_comment_to_answer(a_id=answer['id'])) + print(answer_comment[0]) + return render_template('question_page.html', question=question, answers=answers, comment=comment, answer_comment=answer_comment[0]) @app.route('/question_page//edit') @@ -179,14 +180,14 @@ def add_comment_to_question(question_id): comment = 'question' if request.method == 'POST': message = request.form['message'] - data_manager.add_comment_to_question(q_id=question_id, comment_message=message, comment=comment) + data_manager.add_comment_to_question(q_id=question_id, comment_message=message) return show_question(question_id) - return render_template('add_comment.html', question_id=question_id) + return render_template('add_comment.html', question_id=question_id, comment=comment) @app.route('/question_page///comment', methods=['GET','POST']) -def add_comment_to_answer(answer_id,question_id): +def add_comment_to_answer(answer_id, question_id): comment = 'answer' if request.method == 'POST': message = request.form['message'] diff --git a/templates/index.html b/templates/index.html index e4e7e643f..bedaf3511 100644 --- a/templates/index.html +++ b/templates/index.html @@ -17,15 +17,24 @@

ASK MATE

LATEST 5 QUESTION:

- + + + + + + {% for question in questions %} + {{ question['title'] }} + + + {% endfor %} -
TitleSubmission TimeView NumberVote Number
- {{ question['title'] }}{{ question['submission_time'] }}{{ question['view_number'] }}{{ question['vote_number'] }}

+ +
\ No newline at end of file diff --git a/templates/question_page.html b/templates/question_page.html index b73e081b4..6fbfc5ae9 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -16,43 +16,45 @@ Image:{{ question[0]['image'] }}
-edit question + edit question - Delete question
+ Delete question

Comments

-{% for message in comment%} - {{ message['message']}}
+{% for message in comment %} + {{ message['message'] }}
{% endfor %} -Add Comment +Add Comment
- - - Vote UP
- Vote DOWN
- + + + Vote UP
+ Vote DOWN
+

Answers:

-{%for answer in answers%} - {{answer['message']}}
- comments: +{% for answer in answers %} + {{ answer['message'] }}
+ comments:
{% for comment in answer_comment %} - {% if comment['answer_id'] == answer['id'] %} - {{ comment['message'] }} + {% if comment['answer_id'] == answer['id'] %} + {{ comment['message'] }}
{% endif %} {% endfor %}
- Add Comment - edit answer -
delete answer + Add + Comment + edit answer + + delete answer

-{%endfor%} +{% endfor %}
- Post an Answer + Post an Answer
\ No newline at end of file From 9b3e0279a52dc066c617a9e0603330876b9997f6 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Thu, 28 Feb 2019 14:58:50 +0100 Subject: [PATCH 051/101] search works everywhere --- templates/home_button.html | 2 +- templates/question_page.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/home_button.html b/templates/home_button.html index 65705f23c..c47d77db4 100644 --- a/templates/home_button.html +++ b/templates/home_button.html @@ -9,7 +9,7 @@
- +
diff --git a/templates/question_page.html b/templates/question_page.html index 6fbfc5ae9..17b73a5cd 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -12,7 +12,7 @@ View Number: {{ question[0]['view_number'] }}
Vote Number: {{ question[0]['vote_number'] }}
Title: {{ question[0]['title'] }}
-Message:{{ question[0]['message'] }}
+Message:
Image:{{ question[0]['image'] }}
From 8e66b19a89029d42cd13555ff2f16a3a8259da90 Mon Sep 17 00:00:00 2001 From: Zollli Date: Thu, 28 Feb 2019 15:19:03 +0100 Subject: [PATCH 052/101] css in progress --- static/css/main.css | 33 +++++++++++++++++++++++ templates/add_question.html | 1 + templates/all_question.html | 6 +++-- templates/home_button.html | 52 +++++++++++++++++++++++++++++++++--- templates/index.html | 7 +++-- templates/new_answer.html | 1 + templates/question_page.html | 3 ++- 7 files changed, 93 insertions(+), 10 deletions(-) create mode 100644 static/css/main.css diff --git a/static/css/main.css b/static/css/main.css new file mode 100644 index 000000000..68d4f4c88 --- /dev/null +++ b/static/css/main.css @@ -0,0 +1,33 @@ +body { + background-image: url("background.jpg"); + color:white; + } + +.button { + background-color: #555555; + border: none; + color: white; + padding: 10px 24px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 20px; + border-radius: 4px; +} + +.backgroundColor { + color: white; + padding: middle; + text-align: center; + } + +h1 { + color: white; + text-align: center; + letter-spacing: 3px; + word-spacing: 8px; + text-shadow: 3px 2px black; + } + + + diff --git a/templates/add_question.html b/templates/add_question.html index 5151799bc..99a80740b 100644 --- a/templates/add_question.html +++ b/templates/add_question.html @@ -3,6 +3,7 @@ Add New Question + {% include 'home_button.html' %} diff --git a/templates/all_question.html b/templates/all_question.html index cd052dfea..c3e959bad 100644 --- a/templates/all_question.html +++ b/templates/all_question.html @@ -3,8 +3,12 @@ All Question + + +{% include 'home_button.html' %} +

ALL QUESTION

Sort by: -{% include 'home_button.html' %} -

All Question

{% for question in questions%} diff --git a/templates/home_button.html b/templates/home_button.html index 65705f23c..dcdbd7e57 100644 --- a/templates/home_button.html +++ b/templates/home_button.html @@ -3,14 +3,60 @@ Home + + + + + +

- - + - +
\ No newline at end of file diff --git a/templates/index.html b/templates/index.html index e4e7e643f..153f4c797 100644 --- a/templates/index.html +++ b/templates/index.html @@ -3,21 +3,20 @@ Index + - +

ASK MATE

Add new QuestionShow All Question

LATEST 5 QUESTION:

-
- {% for question in questions %} diff --git a/templates/new_answer.html b/templates/new_answer.html index 720b293b5..d1f1f0034 100644 --- a/templates/new_answer.html +++ b/templates/new_answer.html @@ -3,6 +3,7 @@ Post an Answer + {% include 'home_button.html' %} diff --git a/templates/question_page.html b/templates/question_page.html index d7ead828b..ed40e1863 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -3,15 +3,16 @@ {{ question['title'] }} +
{% include 'home_button.html' %}

+

{{ question[0]['title'] }}

ID :{{ question[0]['id'] }}
Submission Time: {{ question[0]['submission_time'] }}
View Number: {{ question[0]['view_number'] }}
Vote Number: {{ question[0]['vote_number'] }}
-Title: {{ question[0]['title'] }}
Message:{{ question[0]['message'] }}
Image:{{ question[0]['image'] }}
From 499ee04a27147d0ccba8b00cdab0c1f040a23800 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Thu, 28 Feb 2019 15:22:28 +0100 Subject: [PATCH 053/101] really working show comments --- server.py | 10 +++++----- templates/question_page.html | 10 +++++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/server.py b/server.py index a91e85844..90f05bfc0 100644 --- a/server.py +++ b/server.py @@ -81,13 +81,13 @@ def show_question(question_id): print(answers) data_manager.update_view_number(q_id=question_id) comment = data_manager.collect_comment_to_question(q_id=question_id) - print(comment) answer_comment = [] for answer in answers: - print(answer['id']) - answer_comment.append(data_manager.collect_comment_to_answer(a_id=answer['id'])) - print(answer_comment[0]) - return render_template('question_page.html', question=question, answers=answers, comment=comment, answer_comment=answer_comment[0]) + temporary = data_manager.collect_comment_to_answer(a_id=answer['id']) + if len(temporary)>0: + answer_comment.append(temporary[0]) + print(answer_comment) + return render_template('question_page.html', question=question, answers=answers, comment=comment, answer_comment=answer_comment) @app.route('/question_page//edit') diff --git a/templates/question_page.html b/templates/question_page.html index 17b73a5cd..d5f6cb487 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -7,13 +7,17 @@
{% include 'home_button.html' %}

+
ID :{{ question[0]['id'] }}
Submission Time: {{ question[0]['submission_time'] }}
View Number: {{ question[0]['view_number'] }}
Vote Number: {{ question[0]['vote_number'] }}
+
+
Title: {{ question[0]['title'] }}
Message:
Image:{{ question[0]['image'] }}
+
edit question @@ -23,7 +27,7 @@

Comments

{% for message in comment %} - {{ message['message'] }}
+
{{ message['message'] }}

{% endfor %} Add Comment @@ -38,11 +42,11 @@

Comments

Answers:

{% for answer in answers %} - {{ answer['message'] }}
+
{{ answer['message'] }}

comments:
{% for comment in answer_comment %} {% if comment['answer_id'] == answer['id'] %} - {{ comment['message'] }}
+
{{ comment['message'] }}

{% endif %} {% endfor %} From b57fbcc61883b4348be4762e30a6970fd6a29aee Mon Sep 17 00:00:00 2001 From: Zollli Date: Thu, 28 Feb 2019 15:29:29 +0100 Subject: [PATCH 054/101] css in progress --- static/css/background.jpg | Bin 0 -> 91620 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 static/css/background.jpg diff --git a/static/css/background.jpg b/static/css/background.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1182c73f8037ee97b4dcdddb8cea91ce39cd32ba GIT binary patch literal 91620 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 literal 0 HcmV?d00001 From ef043727541ed8fa40fba399ca866ac8d60f8f0b Mon Sep 17 00:00:00 2001 From: borosTamas Date: Thu, 28 Feb 2019 15:53:36 +0100 Subject: [PATCH 055/101] somewhere in the way of css --- server.py | 2 -- static/css/main.css | 28 +++++++++++++++++++++++++++- templates/question_page.html | 10 +++++----- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/server.py b/server.py index 90f05bfc0..3efe78cd8 100644 --- a/server.py +++ b/server.py @@ -78,7 +78,6 @@ def search(): def show_question(question_id): question = data_manager.find_question(q_id=question_id) answers = data_manager.collect_answers(q_id=question_id) - print(answers) data_manager.update_view_number(q_id=question_id) comment = data_manager.collect_comment_to_question(q_id=question_id) answer_comment = [] @@ -86,7 +85,6 @@ def show_question(question_id): temporary = data_manager.collect_comment_to_answer(a_id=answer['id']) if len(temporary)>0: answer_comment.append(temporary[0]) - print(answer_comment) return render_template('question_page.html', question=question, answers=answers, comment=comment, answer_comment=answer_comment) diff --git a/static/css/main.css b/static/css/main.css index 68d4f4c88..be5c3cbc3 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -2,7 +2,33 @@ body { background-image: url("background.jpg"); color:white; } - +#main_data { + max-width: fit-content; + position: center; + background-color: lightgray; +} +#data{ + position: relative; + margin-right: fill; + float: right; + background-color: lightgray; + backface-visibility: initial; +} +#answer{ + position: center; + float: bottom; + background-color: lightgray; +} +#question_comment{ + background-color: darkgray ; + color: black; + font-max-size: small; +} +#answer_comment{ + background-color: darkgray ; + color: black; + font-max-size: small; +} .button { background-color: #555555; border: none; diff --git a/templates/question_page.html b/templates/question_page.html index 820330c8a..2f624d346 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -8,17 +8,17 @@
{% include 'home_button.html' %}

-
+

{{ question[0]['title'] }}

+
ID :{{ question[0]['id'] }}
Submission Time: {{ question[0]['submission_time'] }}
View Number: {{ question[0]['view_number'] }}
Vote Number: {{ question[0]['vote_number'] }}
-
-Title: {{ question[0]['title'] }}
-Message:
-Message:{{ question[0]['message'] }}
+ +
+Message:

{{ question[0]['message'] }}


Image:{{ question[0]['image'] }}
From e3f472f18652240bbea4a04b2426d533ba25fcb9 Mon Sep 17 00:00:00 2001 From: Zollli Date: Thu, 28 Feb 2019 16:13:25 +0100 Subject: [PATCH 056/101] css in progress --- static/css/main.css | 23 ++++++++++++++++++----- templates/index.html | 5 ++++- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/static/css/main.css b/static/css/main.css index 68d4f4c88..8c2f33582 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -13,13 +13,9 @@ body { display: inline-block; font-size: 20px; border-radius: 4px; + } -.backgroundColor { - color: white; - padding: middle; - text-align: center; - } h1 { color: white; @@ -29,5 +25,22 @@ h1 { text-shadow: 3px 2px black; } +h2 { + color: white; + text-shadow: 3px 2px black; +} +thead { + color: white; + text-shadow: 3px 2px black; +} +#title_Color { + color: white; + text-shadow: 3px 2px white; +} + +p.thicker { + font-weight: 900; +} + diff --git a/templates/index.html b/templates/index.html index 73dfa0c4e..a32ddcf9c 100644 --- a/templates/index.html +++ b/templates/index.html @@ -24,15 +24,18 @@

LATEST 5 QUESTION:

+

+

{% for question in questions %}
- {% endfor %} +
Vote Number
+
{{ question['title'] }}
{{ question['submission_time'] }} {{ question['view_number'] }} {{ question['vote_number'] }}

From 82f0854144a7a78bec13441aaa7ca31199b12920 Mon Sep 17 00:00:00 2001 From: Zollli Date: Thu, 28 Feb 2019 16:31:34 +0100 Subject: [PATCH 057/101] css index,all question,home finished --- templates/add_question.html | 3 +++ templates/all_question.html | 2 ++ 2 files changed, 5 insertions(+) diff --git a/templates/add_question.html b/templates/add_question.html index 99a80740b..b40211d08 100644 --- a/templates/add_question.html +++ b/templates/add_question.html @@ -12,10 +12,13 @@

Add New Question

Question Name:

+

Question:

+

Image:
+


diff --git a/templates/all_question.html b/templates/all_question.html index c3e959bad..3b4eca0eb 100644 --- a/templates/all_question.html +++ b/templates/all_question.html @@ -22,6 +22,8 @@

ALL QUESTION

+

+

{% for question in questions%} From 11bcf0dbbe77f6b79068dc3655b44ff846e15bb8 Mon Sep 17 00:00:00 2001 From: Zollli Date: Thu, 28 Feb 2019 17:04:23 +0100 Subject: [PATCH 058/101] vote fixed --- data_manager.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/data_manager.py b/data_manager.py index 92a069688..2eac7e7f7 100644 --- a/data_manager.py +++ b/data_manager.py @@ -101,9 +101,10 @@ def update_view_number(cursor, q_id): @connection.connection_handler def update_vote_number(cursor, vote, q_id): - cursor.execute("""UPDATE question - set vote_number = vote_number + %(vote)s - WHERE question.id = %(q_id)s + cursor.execute(""" + UPDATE question + set vote_number = %(vote)s + WHERE id = %(q_id)s """, {'vote': vote, 'q_id': q_id}) From 23cf8009a20bb3c8e943afe4b3be5997636377ce Mon Sep 17 00:00:00 2001 From: borosTamas Date: Thu, 28 Feb 2019 17:21:20 +0100 Subject: [PATCH 059/101] last push i hope, edit answer and ediq question, drops back to question page --- data_manager.py | 2 +- sample_data/askmatepart2-sample-data.sql | 10 +++++----- server.py | 4 ++-- static/css/main.css | 17 ++++++++++------- templates/add_comment.html | 1 + templates/home_button.html | 6 +++--- templates/index.html | 5 +---- templates/new_answer.html | 5 ++--- templates/question_page.html | 18 +++++++++--------- 9 files changed, 34 insertions(+), 34 deletions(-) diff --git a/data_manager.py b/data_manager.py index 2eac7e7f7..5c16508a0 100644 --- a/data_manager.py +++ b/data_manager.py @@ -38,7 +38,7 @@ def delete_question(cursor, q_id): delete from answer where question_id = %(q_id)s; delete from question - where id = %(q_id)s + where id = %(q_id)s """, {'q_id': q_id}) diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index a51c461b8..074965291 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -77,19 +77,19 @@ ALTER TABLE ONLY tag ADD CONSTRAINT pk_tag_id PRIMARY KEY (id); ALTER TABLE ONLY comment - ADD CONSTRAINT fk_answer_id FOREIGN KEY (answer_id) REFERENCES answer(id); + ADD CONSTRAINT fk_answer_id FOREIGN KEY (answer_id) REFERENCES answer(id) on delete cascade; ALTER TABLE ONLY answer - ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id); + ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id) on delete cascade; ALTER TABLE ONLY question_tag - ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id); + ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id) on delete cascade; ALTER TABLE ONLY comment - ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id); + ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id) on delete cascade; ALTER TABLE ONLY question_tag - ADD CONSTRAINT fk_tag_id FOREIGN KEY (tag_id) REFERENCES tag(id); + ADD CONSTRAINT fk_tag_id FOREIGN KEY (tag_id) REFERENCES tag(id) on delete cascade; INSERT INTO question VALUES (0, '2017-04-28 08:29:00', 29, 7, 'How to make lists in Python?', 'I am totally new to this, any hints?', NULL); INSERT INTO question VALUES (1, '2017-04-29 09:19:00', 15, 9, 'Wordpress loading multiple jQuery Versions', 'I developed a plugin that uses the jquery booklet plugin (http://builtbywill.com/booklet/#/) this plugin binds a function to $ so I cann call $(".myBook").booklet(); diff --git a/server.py b/server.py index 3efe78cd8..193b0e5f4 100644 --- a/server.py +++ b/server.py @@ -106,7 +106,7 @@ def rewrite_question(): 'image': request.form.get('image') } data_manager.update_question(datas=updated_question) - return redirect('/') + return show_question(updated_question['id']) @app.route('/question_page//new-answer', methods=['GET','POST']) @@ -148,7 +148,7 @@ def rewrite_answer(): 'image': request.form.get('image'), } data_manager.update_answer(datas=updated_answer) - return redirect('/') + return show_question(updated_answer['question_id']) @app.route('/add-question', methods=['GET', 'POST']) diff --git a/static/css/main.css b/static/css/main.css index 167ed5103..7aeb2db11 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -3,29 +3,32 @@ body { color:white; } #main_data { - max-width: fit-content; + background-color: rgb(232,232,232,0.2); + width: 400px; position: center; - background-color: lightgray; } #data{ position: relative; margin-right: fill; float: right; - background-color: lightgray; - backface-visibility: initial; + width: 400px; + backrgb(232,232,232)ground-color: lightgray; } #answer{ + width: 400px; position: center; float: bottom; - background-color: lightgray; + background-color: rgb(232,232,232,0.2) } #question_comment{ - background-color: darkgray ; + width: 400px; + background-color: rgb(232,232,232,0.2) ; color: black; font-max-size: small; } #answer_comment{ - background-color: darkgray ; + width: 400px; + background-color: rgb(232,232,232,0.2); color: black; font-max-size: small; } diff --git a/templates/add_comment.html b/templates/add_comment.html index ce080bd57..442af8d7f 100644 --- a/templates/add_comment.html +++ b/templates/add_comment.html @@ -3,6 +3,7 @@ ADD COMMENT +

Add Comment

diff --git a/templates/home_button.html b/templates/home_button.html index dcdbd7e57..f2d4a1a68 100644 --- a/templates/home_button.html +++ b/templates/home_button.html @@ -54,9 +54,9 @@

-
- -
+ + + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index a32ddcf9c..2b0ff830c 100644 --- a/templates/index.html +++ b/templates/index.html @@ -7,10 +7,7 @@

ASK MATE

Add new Question diff --git a/templates/new_answer.html b/templates/new_answer.html index d1f1f0034..bf4a5c35a 100644 --- a/templates/new_answer.html +++ b/templates/new_answer.html @@ -10,9 +10,8 @@ {% if result == [] %}

Post an Answer

-
-
-
+ +


diff --git a/templates/question_page.html b/templates/question_page.html index 2f624d346..31528bf0f 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -18,22 +18,22 @@

{{ question[0]['title'] }}

-Message:

{{ question[0]['message'] }}


+Message:

{{ question[0]['message'] }}


Image:{{ question[0]['image'] }}
- edit question + - Delete question
+

Comments

{% for message in comment %}
{{ message['message'] }}

{% endfor %} -Add Comment + @@ -53,15 +53,15 @@

Answers:

{% endif %} {% endfor %} - Add - Comment - edit answer + + - delete answer +

{% endfor %} - Post an Answer + \ No newline at end of file From 8cacf60c5af2f6cdb34fe192ac69e818e09f0a51 Mon Sep 17 00:00:00 2001 From: LibLev Date: Mon, 4 Mar 2019 15:31:28 +0100 Subject: [PATCH 060/101] valami --- templates/add_question.html | 6 ++++-- templates/index.html | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/templates/add_question.html b/templates/add_question.html index b40211d08..5db5c1097 100644 --- a/templates/add_question.html +++ b/templates/add_question.html @@ -13,10 +13,12 @@

Add New Question

Question Name:

- Question:
+ Question: +

- Image:
+ Image: +


diff --git a/templates/index.html b/templates/index.html index 2b0ff830c..481852621 100644 --- a/templates/index.html +++ b/templates/index.html @@ -10,7 +10,7 @@
{% include 'home_button.html' %}

ASK MATE

-Add new Question +Add new Question Show All Question

LATEST 5 QUESTION:

Question ID Message
From a3e90c5a3b54f6f01ac6ff84a20f3a6d49725363 Mon Sep 17 00:00:00 2001 From: LibLev Date: Mon, 11 Mar 2019 10:45:53 +0100 Subject: [PATCH 061/101] css has been updated --- static/css/background.jpg | Bin 91620 -> 0 bytes static/css/main.css | 29 +++++++++++++++++++---------- templates/index.html | 2 +- 3 files changed, 20 insertions(+), 11 deletions(-) delete mode 100644 static/css/background.jpg diff --git a/static/css/background.jpg b/static/css/background.jpg deleted file mode 100644 index 1182c73f8037ee97b4dcdddb8cea91ce39cd32ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91620 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 diff --git a/static/css/main.css b/static/css/main.css index 7aeb2db11..ff892ae2f 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -1,6 +1,6 @@ body { background-image: url("background.jpg"); - color:white; + color:black; } #main_data { background-color: rgb(232,232,232,0.2); @@ -18,8 +18,10 @@ body { width: 400px; position: center; float: bottom; - background-color: rgb(232,232,232,0.2) + background-color: rgb(232,232,232,0.2); + border-radius: 5px; } + #question_comment{ width: 400px; background-color: rgb(232,232,232,0.2) ; @@ -47,24 +49,24 @@ body { h1 { - color: white; + color: black; text-align: center; letter-spacing: 3px; word-spacing: 8px; - text-shadow: 3px 2px black; + text-shadow: 3px 2px gray; } h2 { - color: white; - text-shadow: 3px 2px black; + color: black; + text-shadow: 3px 2px gray; } thead { - color: white; - text-shadow: 3px 2px black; + color: black; + text-shadow: 3px 2px gray; } #title_Color { - color: white; - text-shadow: 3px 2px white; + color: black; + text-shadow: 3px 2px gray; } p.thicker { @@ -72,4 +74,11 @@ p.thicker { } +textarea{ + background-color: darkkhaki; + border-radius: 5px; +} + + + diff --git a/templates/index.html b/templates/index.html index 481852621..a5e0f58ce 100644 --- a/templates/index.html +++ b/templates/index.html @@ -11,7 +11,7 @@

ASK MATE

Add new Question -Show All Question +Show All Question

LATEST 5 QUESTION:

From d0070dfd2fa445ec75b5405af029db34053bee62 Mon Sep 17 00:00:00 2001 From: LibLev Date: Mon, 11 Mar 2019 10:46:18 +0100 Subject: [PATCH 062/101] new background --- static/css/background.jpg | Bin 0 -> 120721 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 static/css/background.jpg diff --git a/static/css/background.jpg b/static/css/background.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6bea2e7633405d7d054c87fd9ff8d3fef4faa544 GIT binary patch literal 120721 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%0Ad>Pa3lnX`ppH0W1)G}G$QY6V3bX|E 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 Zd2#E@rwVb}mHKi%s`CB6DraZ8|Jl$XohbkS literal 0 HcmV?d00001 From e1a0fb49274aacd9e13d1dfe59cddd367eb4274d Mon Sep 17 00:00:00 2001 From: lterray Date: Mon, 28 Aug 2017 16:35:10 +0200 Subject: [PATCH 063/101] add sql sample data --- sample_data/askmatepart2-sample-data.sql | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index 074965291..c4289f5c2 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -17,6 +17,7 @@ ALTER TABLE IF EXISTS ONLY public.tag DROP CONSTRAINT IF EXISTS pk_tag_id CASCAD ALTER TABLE IF EXISTS ONLY public.question_tag DROP CONSTRAINT IF EXISTS fk_tag_id CASCADE; DROP TABLE IF EXISTS public.question; +DROP SEQUENCE IF EXISTS public.question_id_seq; CREATE TABLE question ( id serial NOT NULL, submission_time timestamp without time zone, @@ -28,6 +29,7 @@ CREATE TABLE question ( ); DROP TABLE IF EXISTS public.answer; +DROP SEQUENCE IF EXISTS public.answer_id_seq; CREATE TABLE answer ( id serial NOT NULL, submission_time timestamp without time zone, @@ -38,6 +40,7 @@ CREATE TABLE answer ( ); DROP TABLE IF EXISTS public.comment; +DROP SEQUENCE IF EXISTS public.comment_id_seq; CREATE TABLE comment ( id serial NOT NULL, question_id integer, @@ -55,6 +58,10 @@ CREATE TABLE question_tag ( ); DROP TABLE IF EXISTS public.tag; +<<<<<<< HEAD +======= +DROP SEQUENCE IF EXISTS public.tag_id_seq; +>>>>>>> add sql sample data CREATE TABLE tag ( id serial NOT NULL, name text @@ -77,6 +84,7 @@ ALTER TABLE ONLY tag ADD CONSTRAINT pk_tag_id PRIMARY KEY (id); ALTER TABLE ONLY comment +<<<<<<< HEAD ADD CONSTRAINT fk_answer_id FOREIGN KEY (answer_id) REFERENCES answer(id) on delete cascade; ALTER TABLE ONLY answer @@ -90,6 +98,21 @@ ALTER TABLE ONLY comment ALTER TABLE ONLY question_tag ADD CONSTRAINT fk_tag_id FOREIGN KEY (tag_id) REFERENCES tag(id) on delete cascade; +======= + ADD CONSTRAINT fk_answer_id FOREIGN KEY (answer_id) REFERENCES answer(id); + +ALTER TABLE ONLY answer + ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id); + +ALTER TABLE ONLY question_tag + ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id); + +ALTER TABLE ONLY comment + ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id); + +ALTER TABLE ONLY question_tag + ADD CONSTRAINT fk_tag_id FOREIGN KEY (tag_id) REFERENCES tag(id); +>>>>>>> add sql sample data INSERT INTO question VALUES (0, '2017-04-28 08:29:00', 29, 7, 'How to make lists in Python?', 'I am totally new to this, any hints?', NULL); INSERT INTO question VALUES (1, '2017-04-29 09:19:00', 15, 9, 'Wordpress loading multiple jQuery Versions', 'I developed a plugin that uses the jquery booklet plugin (http://builtbywill.com/booklet/#/) this plugin binds a function to $ so I cann call $(".myBook").booklet(); From d1b3c598019ac9ee72ad921b51bf0841a48349c2 Mon Sep 17 00:00:00 2001 From: szrudi Date: Tue, 25 Sep 2018 13:55:21 +0200 Subject: [PATCH 064/101] Remove drop sequence from sample SQL --- sample_data/askmatepart2-sample-data.sql | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index c4289f5c2..2f350da1d 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -17,7 +17,6 @@ ALTER TABLE IF EXISTS ONLY public.tag DROP CONSTRAINT IF EXISTS pk_tag_id CASCAD ALTER TABLE IF EXISTS ONLY public.question_tag DROP CONSTRAINT IF EXISTS fk_tag_id CASCADE; DROP TABLE IF EXISTS public.question; -DROP SEQUENCE IF EXISTS public.question_id_seq; CREATE TABLE question ( id serial NOT NULL, submission_time timestamp without time zone, @@ -29,7 +28,6 @@ CREATE TABLE question ( ); DROP TABLE IF EXISTS public.answer; -DROP SEQUENCE IF EXISTS public.answer_id_seq; CREATE TABLE answer ( id serial NOT NULL, submission_time timestamp without time zone, @@ -40,7 +38,6 @@ CREATE TABLE answer ( ); DROP TABLE IF EXISTS public.comment; -DROP SEQUENCE IF EXISTS public.comment_id_seq; CREATE TABLE comment ( id serial NOT NULL, question_id integer, @@ -58,10 +55,6 @@ CREATE TABLE question_tag ( ); DROP TABLE IF EXISTS public.tag; -<<<<<<< HEAD -======= -DROP SEQUENCE IF EXISTS public.tag_id_seq; ->>>>>>> add sql sample data CREATE TABLE tag ( id serial NOT NULL, name text From a18fb8977835e1efb594fb59054570090fc15141 Mon Sep 17 00:00:00 2001 From: LibLev Date: Mon, 11 Mar 2019 13:20:52 +0100 Subject: [PATCH 065/101] question_data_manager --- data_manager.py | 97 +------------------------------- question_data_manager.py | 118 +++++++++++++++++++++++++++++++++++++++ server.py | 21 +++---- static/css/main.css | 10 +++- templates/index.html | 2 +- 5 files changed, 139 insertions(+), 109 deletions(-) create mode 100644 question_data_manager.py diff --git a/data_manager.py b/data_manager.py index 5c16508a0..51a996f58 100644 --- a/data_manager.py +++ b/data_manager.py @@ -1,47 +1,6 @@ -import os -import time, datetime +import datetime import connection -ANSWERS_HEADER = ['id', 'submission_time', 'vote_number', 'question_id', 'message', 'image'] -DATA_HEADER = ['id', 'submission_time', 'view_number', 'vote_number', 'title', 'message', 'image'] - -QUESTIONS_FILE_PATH = os.getenv('QUESTIONS_FILE_PATH', 'sample_data/question.csv') -ANSWERS_FILE_PATH = os.getenv('ANSWERS_FILE_PATH', 'sample_data/answer.csv') - - -@connection.connection_handler -def sort_questions(cursor, option, how): - option = option - cursor.execute(""" - SELECT * FROM question - ORDER BY {option} {how} - """.format(option=option,how=how)) - result = cursor.fetchall() - return result - -@connection.connection_handler -def collect_questions(cursor): - cursor.execute(""" - SELECT * FROM question - """) - result = cursor.fetchall() - return result - - -@connection.connection_handler -def delete_question(cursor, q_id): - cursor.execute(""" - delete from question_tag - where question_id = %(q_id)s; - delete from comment - where question_id = %(q_id)s; - delete from answer - where question_id = %(q_id)s; - delete from question - where id = %(q_id)s - """, - {'q_id': q_id}) - @connection.connection_handler def delete_answer(cursor, q_id, a_id): @@ -54,41 +13,6 @@ def delete_answer(cursor, q_id, a_id): {'q_id': q_id, 'a_id': a_id}) -@connection.connection_handler -def find_searched_questions(cursor, searched_data): - searched_data = "%" + searched_data + "%" - cursor.execute(""" - select * from question - where title ilike %(searched_data)s - OR - message ilike %(searched_data)s - """, - {'searched_data': searched_data}) - result = cursor.fetchall() - return result - - -@connection.connection_handler -def collect_latest_5_question(cursor): - cursor.execute(""" - SELECT * FROM question - ORDER BY submission_time DESC - LIMIT 5""") - result = cursor.fetchall() - return result - - -@connection.connection_handler -def find_question(cursor, q_id): - cursor.execute(""" - SELECT * from question - where id = %(q_id)s - """, - {'q_id': q_id}) - result = cursor.fetchall() - return result - - @connection.connection_handler def update_view_number(cursor, q_id): cursor.execute(""" @@ -121,15 +45,6 @@ def collect_answers(cursor, q_id): return result -@connection.connection_handler -def update_question(cursor, datas): - cursor.execute(""" - UPDATE question - SET title=%s, message=%s, image=%s - WHERE id=%s""", - (datas['title'], datas['message'], datas['image'], int(datas['id']))) - - @connection.connection_handler def find_answer(cursor, a_id): cursor.execute(""" @@ -214,12 +129,4 @@ def collect_comment_to_answer(cursor, a_id): return result -@connection.connection_handler -def add_question(cursor, from_data): - cursor.execute(""" - INSERT INTO question(submission_time, view_number, vote_number, title, message, image) - VALUES (%s,%s,%s, %s,%s,%s)""", - ( - from_data['submission_time'], from_data['view_number'], from_data['vote_number'], - from_data['title'], - from_data['message'], from_data['image'])) + diff --git a/question_data_manager.py b/question_data_manager.py new file mode 100644 index 000000000..679cdf22f --- /dev/null +++ b/question_data_manager.py @@ -0,0 +1,118 @@ +import datetime +import connection + + +@connection.connection_handler +def sort_questions(cursor, option, how): + option = option + cursor.execute(""" + SELECT * FROM question + ORDER BY {option} {how} + """.format(option=option,how=how)) + result = cursor.fetchall() + return result + + +@connection.connection_handler +def collect_questions(cursor): + cursor.execute(""" + SELECT * FROM question + """) + result = cursor.fetchall() + return result@connection.connection_handler + + + +@connection.connection_handler +def delete_question(cursor, q_id): + cursor.execute(""" + delete from question_tag + where question_id = %(q_id)s; + delete from comment + where question_id = %(q_id)s; + delete from answer + where question_id = %(q_id)s; + delete from question + where id = %(q_id)s + """, + {'q_id': q_id}) + + +@connection.connection_handler +def find_searched_questions(cursor, searched_data): + searched_data = "%" + searched_data + "%" + cursor.execute(""" + select * from question + where title ilike %(searched_data)s + OR + message ilike %(searched_data)s + """, + {'searched_data': searched_data}) + result = cursor.fetchall() + return result + + +@connection.connection_handler +def collect_latest_5_question(cursor): + cursor.execute(""" + SELECT * FROM question + ORDER BY submission_time DESC + LIMIT 5""") + result = cursor.fetchall() + return result + + +@connection.connection_handler +def find_question(cursor, q_id): + cursor.execute(""" + SELECT * from question + where id = %(q_id)s + """, + {'q_id': q_id}) + result = cursor.fetchall() + return result + + +@connection.connection_handler +def update_question(cursor, datas): + cursor.execute(""" + UPDATE question + SET title=%s, message=%s, image=%s + WHERE id=%s""", + (datas['title'], datas['message'], datas['image'], int(datas['id']))) + + +@connection.connection_handler +def add_question(cursor, from_data): + cursor.execute(""" + INSERT INTO question(submission_time, view_number, vote_number, title, message, image) + VALUES (%s,%s,%s, %s,%s,%s)""", + ( + from_data['submission_time'], from_data['view_number'], from_data['vote_number'], + from_data['title'], + from_data['message'], from_data['image'])) + + +def submission_time_generator(): + submission_time = datetime.datetime.now() + return submission_time + +@connection.connection_handler +def update_view_number(cursor, q_id): + cursor.execute(""" + update question + set view_number = view_number+1 + where id = %(q_id)s + """, + {'q_id': q_id}) + + +@connection.connection_handler +def update_vote_number(cursor, vote, q_id): + cursor.execute(""" + UPDATE question + set vote_number = %(vote)s + WHERE id = %(q_id)s + """, + {'vote': vote, 'q_id': q_id}) + diff --git a/server.py b/server.py index 193b0e5f4..13f731864 100644 --- a/server.py +++ b/server.py @@ -1,4 +1,5 @@ from flask import Flask, render_template, request, redirect +import question_data_manager import data_manager app = Flask(__name__) @@ -6,13 +7,13 @@ @app.route('/') def render_index(): - questions = data_manager.collect_latest_5_question() + questions = question_data_manager.collect_latest_5_question() return render_template('index.html', questions=questions) @app.route('/all_question') def show_all_question(): - questions = data_manager.collect_questions() + questions = question_data_manager.collect_questions() return render_template('all_question.html', questions=questions) @@ -25,7 +26,7 @@ def show_all_sorted_question(): def sort_questions(): sort_options = request.form.get('sort_options') option = request.form.get('options') - result = data_manager.sort_questions(option=option, how=sort_options) + result = question_data_manager.sort_questions(option=option, how=sort_options) return result @@ -46,7 +47,7 @@ def vote(): @app.route('/question_page//delete') def delete_question(question_id): - data_manager.delete_question(q_id=question_id) + question_data_manager.delete_question(q_id=question_id) return show_all_question() vote = int(request.form.get('vote_num')) vote_up = request.form.get('vote_up') @@ -70,13 +71,13 @@ def delete_answer(question_id, answer_id): @app.route('/search', methods=['POST']) def search(): question_data = request.form.get('question_data') - result = data_manager.find_searched_questions(searched_data=question_data) + result = question_data_manager.find_searched_questions(searched_data=question_data) return render_template('all_question.html', questions=result) @app.route('/question_page/') def show_question(question_id): - question = data_manager.find_question(q_id=question_id) + question = question_data_manager.find_question(q_id=question_id) answers = data_manager.collect_answers(q_id=question_id) data_manager.update_view_number(q_id=question_id) comment = data_manager.collect_comment_to_question(q_id=question_id) @@ -90,7 +91,7 @@ def show_question(question_id): @app.route('/question_page//edit') def edit_question(question_id): - result = data_manager.find_question(q_id=question_id) + result = question_data_manager.find_question(q_id=question_id) return render_template('add_question.html', result=result) @@ -105,7 +106,7 @@ def rewrite_question(): 'message': request.form.get('message'), 'image': request.form.get('image') } - data_manager.update_question(datas=updated_question) + question_data_manager.update_question(datas=updated_question) return show_question(updated_question['id']) @@ -117,7 +118,7 @@ def post_an_answer(question_id): new_answer = create_answer(question_id, request.form['message'], request.form['image']) data_manager.add_answer(form_data=new_answer) return redirect('/') - question = data_manager.find_question(question_id) + question = question_data_manager.find_question(question_id) return render_template('new_answer.html', question=question, result=result, message=message) @@ -157,7 +158,7 @@ def add_question(): message = "" if request.method == 'POST': new_question = create_question(request.form['message'], request.form['image'], request.form['title']) - data_manager.add_question(from_data=new_question) + question_data_manager.add_question(from_data=new_question) return redirect('/') return render_template('add_question.html', result=result, message=message) diff --git a/static/css/main.css b/static/css/main.css index ff892ae2f..36f54d879 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -2,11 +2,13 @@ body { background-image: url("background.jpg"); color:black; } + #main_data { background-color: rgb(232,232,232,0.2); width: 400px; position: center; } + #data{ position: relative; margin-right: fill; @@ -14,6 +16,7 @@ body { width: 400px; backrgb(232,232,232)ground-color: lightgray; } + #answer{ width: 400px; position: center; @@ -28,12 +31,14 @@ body { color: black; font-max-size: small; } + #answer_comment{ width: 400px; background-color: rgb(232,232,232,0.2); color: black; font-max-size: small; } + .button { background-color: #555555; border: none; @@ -60,10 +65,12 @@ h2 { color: black; text-shadow: 3px 2px gray; } + thead { color: black; text-shadow: 3px 2px gray; } + #title_Color { color: black; text-shadow: 3px 2px gray; @@ -79,6 +86,3 @@ textarea{ border-radius: 5px; } - - - diff --git a/templates/index.html b/templates/index.html index a5e0f58ce..35fd81ca9 100644 --- a/templates/index.html +++ b/templates/index.html @@ -25,7 +25,7 @@

LATEST 5 QUESTION:

{% for question in questions %}
- From eb688127ee8063c9e505603917a0d87275b207b0 Mon Sep 17 00:00:00 2001 From: Zollli Date: Mon, 11 Mar 2019 14:39:09 +0100 Subject: [PATCH 066/101] add answer_data_manager.py all answer function data_manager to answer_data_manager --- answer_data_manager.py | 71 ++++++++++++++++++++++++++++++++++++++++++ data_manager.py | 2 +- server.py | 9 +++--- 3 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 answer_data_manager.py diff --git a/answer_data_manager.py b/answer_data_manager.py new file mode 100644 index 000000000..a537f88c8 --- /dev/null +++ b/answer_data_manager.py @@ -0,0 +1,71 @@ +import connection + +@connection.connection_handler +def delete_answer(cursor, q_id, a_id): + cursor.execute(""" + delete from comment + where question_id = %(q_id)s or answer_id = %(a_id)s; + delete from answer + where question_id = %(q_id)s and id = %(a_id)s + """, + {'q_id': q_id, 'a_id': a_id}) + + +@connection.connection_handler +def collect_answers(cursor, q_id): + cursor.execute(""" + SELECT * from answer + where question_id = %(q_id)s + """, + {'q_id': q_id}) + result = cursor.fetchall() + return result + + +@connection.connection_handler +def find_answer(cursor, a_id): + cursor.execute(""" + SELECT * from answer + where id = %(a_id)s + """, + {'a_id': a_id}) + result = cursor.fetchall() + return result + + +@connection.connection_handler +def update_answer(cursor, datas): + cursor.execute(""" + UPDATE answer + SET message=%s, image=%s + WHERE id=%s""", + (datas['message'], datas['image'], int(datas['id']))) + + +@connection.connection_handler +def collect_all_answer(cursor): + cursor.execute(""" + SELECT * FROM answer + """) + result = cursor.fetchall() + return result + + +@connection.connection_handler +def add_answer(cursor, form_data): + cursor.execute(""" + INSERT INTO answer(submission_time, vote_number, question_id, message, image) + VALUES (%s, %s, %s, %s, %s)""", + (form_data['submission_time'], form_data['vote_number'], form_data['question_id'], + form_data['message'], form_data['image'])) + + + +@connection.connection_handler +def update_vote_number(cursor, vote, q_id): + cursor.execute(""" + UPDATE question + set vote_number = %(vote)s + WHERE id = %(q_id)s + """, + {'vote': vote, 'q_id': q_id}) \ No newline at end of file diff --git a/data_manager.py b/data_manager.py index 5c16508a0..7c4a0ed48 100644 --- a/data_manager.py +++ b/data_manager.py @@ -1,5 +1,5 @@ import os -import time, datetime +import datetime import connection ANSWERS_HEADER = ['id', 'submission_time', 'vote_number', 'question_id', 'message', 'image'] diff --git a/server.py b/server.py index 193b0e5f4..a88229ae9 100644 --- a/server.py +++ b/server.py @@ -1,5 +1,6 @@ from flask import Flask, render_template, request, redirect import data_manager +import answer_data_manager app = Flask(__name__) @@ -63,7 +64,7 @@ def delete_question(question_id): @app.route('/question_page///answer-delete') def delete_answer(question_id, answer_id): - data_manager.delete_answer(q_id=question_id, a_id=answer_id) + answer_data_manager.delete_answer(q_id=question_id, a_id=answer_id) return show_question(question_id) @@ -115,7 +116,7 @@ def post_an_answer(question_id): message = "" if request.method=='POST': new_answer = create_answer(question_id, request.form['message'], request.form['image']) - data_manager.add_answer(form_data=new_answer) + answer_data_manager.add_answer(form_data=new_answer) return redirect('/') question = data_manager.find_question(question_id) return render_template('new_answer.html', question=question, result=result, message=message) @@ -133,7 +134,7 @@ def create_answer(question_id, message, image): @app.route('/question_page//update') def edit_answer(answer_id): - result = data_manager.find_answer(a_id=answer_id) + result = answer_data_manager.find_answer(a_id=answer_id) return render_template('new_answer.html', result=result) @@ -147,7 +148,7 @@ def rewrite_answer(): 'message': request.form.get('message'), 'image': request.form.get('image'), } - data_manager.update_answer(datas=updated_answer) + answer_data_manager.update_answer(datas=updated_answer) return show_question(updated_answer['question_id']) From dd3adab2ffb0bb48c145562163987fb1afac11a5 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Mon, 11 Mar 2019 14:47:43 +0100 Subject: [PATCH 067/101] Hotfix on show all comments for an answer --- server.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/server.py b/server.py index 193b0e5f4..49311a1b6 100644 --- a/server.py +++ b/server.py @@ -83,9 +83,11 @@ def show_question(question_id): answer_comment = [] for answer in answers: temporary = data_manager.collect_comment_to_answer(a_id=answer['id']) - if len(temporary)>0: - answer_comment.append(temporary[0]) - return render_template('question_page.html', question=question, answers=answers, comment=comment, answer_comment=answer_comment) + if len(temporary) > 0: + answer_comment.append(temporary) + if len(answer_comment) <= 0: + answer_comment = [None] + return render_template('question_page.html', question=question, answers=answers, comment=comment, answer_comment=answer_comment[0]) @app.route('/question_page//edit') From cf824543c964ddaf6bc1b56d522a083fb544e2a5 Mon Sep 17 00:00:00 2001 From: Zollli Date: Mon, 11 Mar 2019 15:04:52 +0100 Subject: [PATCH 068/101] deleted data_manager, comment_data_manager created, timegenerator --> util --- answer_data_manager.py | 12 +++- comment_data_manager.py | 65 ++++++++++++++++++++ data_manager.py | 133 ---------------------------------------- server.py | 23 +++---- util.py | 6 ++ 5 files changed, 94 insertions(+), 145 deletions(-) create mode 100644 comment_data_manager.py delete mode 100644 data_manager.py diff --git a/answer_data_manager.py b/answer_data_manager.py index a537f88c8..7b9a0bf3a 100644 --- a/answer_data_manager.py +++ b/answer_data_manager.py @@ -68,4 +68,14 @@ def update_vote_number(cursor, vote, q_id): set vote_number = %(vote)s WHERE id = %(q_id)s """, - {'vote': vote, 'q_id': q_id}) \ No newline at end of file + {'vote': vote, 'q_id': q_id}) + + +@connection.connection_handler +def update_view_number(cursor, q_id): + cursor.execute(""" + update question + set view_number = view_number+1 + where id = %(q_id)s + """, + {'q_id': q_id}) \ No newline at end of file diff --git a/comment_data_manager.py b/comment_data_manager.py new file mode 100644 index 000000000..74cffc0ac --- /dev/null +++ b/comment_data_manager.py @@ -0,0 +1,65 @@ +import connection + + +@connection.connection_handler +def update_view_number(cursor, q_id): + cursor.execute(""" + update question + set view_number = view_number+1 + where id = %(q_id)s + """, + {'q_id': q_id}) + + +@connection.connection_handler +def update_vote_number(cursor, vote, q_id): + cursor.execute(""" + UPDATE question + set vote_number = %(vote)s + WHERE id = %(q_id)s + """, + {'vote': vote, 'q_id': q_id}) + + +@connection.connection_handler +def add_comment_to_question(cursor, q_id, comment_message): + cursor.execute(""" + insert into comment(question_id, message) + values (%(q_id)s,%(comment_message)s) + + """, + {'q_id': q_id, 'comment_message': comment_message}) + + +@connection.connection_handler +def add_comment_to_answer(cursor, a_id, comment_message): + cursor.execute(""" + insert into comment(answer_id, message) + values (%(a_id)s,%(comment_message)s) + + """, + {'a_id': a_id, 'comment_message': comment_message}) + + +@connection.connection_handler +def collect_comment_to_question(cursor, q_id): + cursor.execute(""" + Select message from comment + where question_id = %(q_id)s + """, + {'q_id': q_id}) + result = cursor.fetchall() + return result + +@connection.connection_handler +def collect_comment_to_answer(cursor, a_id): + cursor.execute(""" + Select message, answer_id from comment + where answer_id = %(a_id)s + """, + {'a_id': a_id}) + result = cursor.fetchall() + return result + + + diff --git a/data_manager.py b/data_manager.py deleted file mode 100644 index 36c63856e..000000000 --- a/data_manager.py +++ /dev/null @@ -1,133 +0,0 @@ -import os -import datetime -import connection - - -@connection.connection_handler -def delete_answer(cursor, q_id, a_id): - cursor.execute(""" - delete from comment - where question_id = %(q_id)s or answer_id = %(a_id)s; - delete from answer - where question_id = %(q_id)s and id = %(a_id)s - """, - {'q_id': q_id, 'a_id': a_id}) - - -@connection.connection_handler -def update_view_number(cursor, q_id): - cursor.execute(""" - update question - set view_number = view_number+1 - where id = %(q_id)s - """, - {'q_id': q_id}) - - -@connection.connection_handler -def update_vote_number(cursor, vote, q_id): - cursor.execute(""" - UPDATE question - set vote_number = %(vote)s - WHERE id = %(q_id)s - """, - {'vote': vote, 'q_id': q_id}) - - -@connection.connection_handler -def collect_answers(cursor, q_id): - cursor.execute(""" - SELECT * from answer - where question_id = %(q_id)s - """, - {'q_id': q_id}) - - result = cursor.fetchall() - return result - - -@connection.connection_handler -def find_answer(cursor, a_id): - cursor.execute(""" - SELECT * from answer - where id = %(a_id)s - """, - {'a_id': a_id}) - result = cursor.fetchall() - return result - - -@connection.connection_handler -def update_answer(cursor, datas): - cursor.execute(""" - UPDATE answer - SET message=%s, image=%s - WHERE id=%s""", - (datas['message'], datas['image'], int(datas['id']))) - - -@connection.connection_handler -def collect_all_answer(cursor): - cursor.execute(""" - SELECT * FROM answer - """) - result = cursor.fetchall() - return result - - -def submission_time_generator(): - submission_time = datetime.datetime.now() - return submission_time - - -@connection.connection_handler -def add_answer(cursor, form_data): - cursor.execute(""" - INSERT INTO answer(submission_time, vote_number, question_id, message, image) - VALUES (%s, %s, %s, %s, %s)""", - (form_data['submission_time'], form_data['vote_number'], form_data['question_id'], - form_data['message'], form_data['image'])) - - -@connection.connection_handler -def add_comment_to_question(cursor, q_id, comment_message): - cursor.execute(""" - insert into comment(question_id, message) - values (%(q_id)s,%(comment_message)s) - - """, - {'q_id': q_id, 'comment_message': comment_message}) - - -@connection.connection_handler -def add_comment_to_answer(cursor, a_id, comment_message): - cursor.execute(""" - insert into comment(answer_id, message) - values (%(a_id)s,%(comment_message)s) - - """, - {'a_id': a_id, 'comment_message': comment_message}) - - -@connection.connection_handler -def collect_comment_to_question(cursor, q_id): - cursor.execute(""" - Select message from comment - where question_id = %(q_id)s - """, - {'q_id': q_id}) - result = cursor.fetchall() - return result - -@connection.connection_handler -def collect_comment_to_answer(cursor, a_id): - cursor.execute(""" - Select message, answer_id from comment - where answer_id = %(a_id)s - """, - {'a_id': a_id}) - result = cursor.fetchall() - return result - - - diff --git a/server.py b/server.py index 360e36c0a..080451996 100644 --- a/server.py +++ b/server.py @@ -1,7 +1,8 @@ from flask import Flask, render_template, request, redirect import question_data_manager -import data_manager +import comment_data_manager import answer_data_manager +import util app = Flask(__name__) @@ -42,7 +43,7 @@ def vote(): vote += 1 elif vote_down == 'down': vote -= 1 - data_manager.update_vote_number(vote=vote, q_id=q_id) + comment_data_manager.update_vote_number(vote=vote, q_id=q_id) return redirect('/') @@ -59,7 +60,7 @@ def delete_question(question_id): vote += 1 elif vote_down == 'down': vote -= 1 - data_manager.update_vote_number(vote=vote, q_id=q_id) + comment_data_manager.update_vote_number(vote=vote, q_id=q_id) return redirect('/') @@ -79,12 +80,12 @@ def search(): @app.route('/question_page/') def show_question(question_id): question = question_data_manager.find_question(q_id=question_id) - answers = data_manager.collect_answers(q_id=question_id) - data_manager.update_view_number(q_id=question_id) - comment = data_manager.collect_comment_to_question(q_id=question_id) + answers = answer_data_manager.collect_answers(q_id=question_id) + comment_data_manager.update_view_number(q_id=question_id) + comment = comment_data_manager.collect_comment_to_question(q_id=question_id) answer_comment = [] for answer in answers: - temporary = data_manager.collect_comment_to_answer(a_id=answer['id']) + temporary = comment_data_manager.collect_comment_to_answer(a_id=answer['id']) if len(temporary)>0: answer_comment.append(temporary[0]) return render_template('question_page.html', question=question, answers=answers, comment=comment, answer_comment=answer_comment) @@ -125,7 +126,7 @@ def post_an_answer(question_id): def create_answer(question_id, message, image): return { - 'submission_time': data_manager.submission_time_generator(), + 'submission_time': util.submission_time_generator(), 'vote_number': 1, 'question_id': question_id, 'message': message, @@ -166,7 +167,7 @@ def add_question(): def create_question(message, image, title): return { - 'submission_time': data_manager.submission_time_generator(), + 'submission_time': util.submission_time_generator(), 'vote_number': 1, 'message': message, 'title': title, @@ -180,7 +181,7 @@ def add_comment_to_question(question_id): comment = 'question' if request.method == 'POST': message = request.form['message'] - data_manager.add_comment_to_question(q_id=question_id, comment_message=message) + comment_data_manager.add_comment_to_question(q_id=question_id, comment_message=message) return show_question(question_id) return render_template('add_comment.html', question_id=question_id, comment=comment) @@ -191,7 +192,7 @@ def add_comment_to_answer(answer_id, question_id): comment = 'answer' if request.method == 'POST': message = request.form['message'] - data_manager.add_comment_to_answer(a_id=answer_id, comment_message=message) + comment_data_manager.add_comment_to_answer(a_id=answer_id, comment_message=message) return show_question(question_id) return render_template('add_comment.html', answer_id=answer_id, question_id=question_id, comment=comment) diff --git a/util.py b/util.py index e69de29bb..3608f481c 100644 --- a/util.py +++ b/util.py @@ -0,0 +1,6 @@ +import datetime + + +def submission_time_generator(): + submission_time = datetime.datetime.now() + return submission_time \ No newline at end of file From 0184b38ff83cfc8573410adf80f5c4f22753f7f6 Mon Sep 17 00:00:00 2001 From: LibLev Date: Tue, 12 Mar 2019 11:12:03 +0100 Subject: [PATCH 069/101] user table has been created in database --- question_data_manager.py | 2 +- sample_data/askmatepart2-sample-data.sql | 33 +++++++++++++++++++++--- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/question_data_manager.py b/question_data_manager.py index 679cdf22f..d1257dccf 100644 --- a/question_data_manager.py +++ b/question_data_manager.py @@ -19,7 +19,7 @@ def collect_questions(cursor): SELECT * FROM question """) result = cursor.fetchall() - return result@connection.connection_handler + return result diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index 074965291..3ef4798b7 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -15,6 +15,19 @@ ALTER TABLE IF EXISTS ONLY public.question_tag DROP CONSTRAINT IF EXISTS pk_ques ALTER TABLE IF EXISTS ONLY public.question_tag DROP CONSTRAINT IF EXISTS fk_question_id CASCADE; ALTER TABLE IF EXISTS ONLY public.tag DROP CONSTRAINT IF EXISTS pk_tag_id CASCADE; ALTER TABLE IF EXISTS ONLY public.question_tag DROP CONSTRAINT IF EXISTS fk_tag_id CASCADE; +ALTER TABLE IF EXISTS ONLY public.user DROP CONSTRAINT IF EXISTS pk_user_id CASCADE; +ALTER TABLE IF EXISTS ONLY public.question DROP constraint IF EXISTS fk_user_id CASCADE ; +ALTER TABLE IF EXISTS ONLY public.answer DROP constraint IF EXISTS fk_user_id CASCADE ; + + +DROP TABLE IF EXISTS public.user; +CREATE TABLE "user"( + id serial NOT NULL, + submission_time timestamp without time zone, + user_name text, + hashed_password text +); + DROP TABLE IF EXISTS public.question; CREATE TABLE question ( @@ -24,7 +37,8 @@ CREATE TABLE question ( vote_number integer, title text, message text, - image text + image text, + user_id integer ); DROP TABLE IF EXISTS public.answer; @@ -34,7 +48,8 @@ CREATE TABLE answer ( vote_number integer, question_id integer, message text, - image text + image text, + user_id integer ); DROP TABLE IF EXISTS public.comment; @@ -44,7 +59,8 @@ CREATE TABLE comment ( answer_id integer, message text, submission_time timestamp without time zone, - edited_count integer + edited_count integer, + user_id integer ); @@ -60,6 +76,8 @@ CREATE TABLE tag ( name text ); +ALTER TABLE ONLY "user" + ADD CONSTRAINT pk_user_id PRIMARY KEY (id); ALTER TABLE ONLY answer ADD CONSTRAINT pk_answer_id PRIMARY KEY (id); @@ -76,6 +94,15 @@ ALTER TABLE ONLY question_tag ALTER TABLE ONLY tag ADD CONSTRAINT pk_tag_id PRIMARY KEY (id); +ALTER TABLE ONLY answer + ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES "user"(id) on delete cascade; + +ALTER TABLE ONLY question + ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES "user"(id) on delete cascade; + +ALTER TABLE ONLY comment + ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES "user"(id) on delete cascade; + ALTER TABLE ONLY comment ADD CONSTRAINT fk_answer_id FOREIGN KEY (answer_id) REFERENCES answer(id) on delete cascade; From 2647c89425117eed757b83938e832e6d1203f886 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Tue, 12 Mar 2019 11:12:58 +0100 Subject: [PATCH 070/101] login buttons and html --- sample_data/askmatepart2-sample-data.sql | 1 + templates/home_button.html | 6 +++++- templates/reg_log.html | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 templates/reg_log.html diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index 2f350da1d..e9b5ba120 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -61,6 +61,7 @@ CREATE TABLE tag ( ); + ALTER TABLE ONLY answer ADD CONSTRAINT pk_answer_id PRIMARY KEY (id); diff --git a/templates/home_button.html b/templates/home_button.html index f2d4a1a68..e193b2caf 100644 --- a/templates/home_button.html +++ b/templates/home_button.html @@ -52,7 +52,11 @@ -

+
+ Login + Sig in +
+
diff --git a/templates/reg_log.html b/templates/reg_log.html new file mode 100644 index 000000000..7296b215f --- /dev/null +++ b/templates/reg_log.html @@ -0,0 +1,16 @@ + + + + + Login + + +

{{ log }}

+ + +
+ + + + + \ No newline at end of file From d32bc8b254f2e2b6c7ccc05af35ff6a2b230b653 Mon Sep 17 00:00:00 2001 From: Zollli Date: Tue, 12 Mar 2019 13:30:05 +0100 Subject: [PATCH 071/101] added vote to answer --- answer_data_manager.py | 8 ++++---- question_data_manager.py | 5 ++--- server.py | 21 ++++++++++++++++++--- templates/question_page.html | 18 +++++++++++++----- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/answer_data_manager.py b/answer_data_manager.py index 7b9a0bf3a..c42cc4a87 100644 --- a/answer_data_manager.py +++ b/answer_data_manager.py @@ -62,13 +62,13 @@ def add_answer(cursor, form_data): @connection.connection_handler -def update_vote_number(cursor, vote, q_id): +def update_vote_number_answer(cursor, vote, a_id): cursor.execute(""" - UPDATE question + UPDATE answer set vote_number = %(vote)s - WHERE id = %(q_id)s + WHERE id = %(a_id)s """, - {'vote': vote, 'q_id': q_id}) + {'vote': vote, 'a_id': a_id}) @connection.connection_handler diff --git a/question_data_manager.py b/question_data_manager.py index 679cdf22f..070b329fd 100644 --- a/question_data_manager.py +++ b/question_data_manager.py @@ -19,8 +19,7 @@ def collect_questions(cursor): SELECT * FROM question """) result = cursor.fetchall() - return result@connection.connection_handler - + return result @connection.connection_handler @@ -108,7 +107,7 @@ def update_view_number(cursor, q_id): @connection.connection_handler -def update_vote_number(cursor, vote, q_id): +def update_vote_number_question(cursor, vote, q_id): cursor.execute(""" UPDATE question set vote_number = %(vote)s diff --git a/server.py b/server.py index 080451996..5cc7fdb5c 100644 --- a/server.py +++ b/server.py @@ -32,8 +32,8 @@ def sort_questions(): return result -@app.route('/question_page/vote',methods=['GET','POST']) -def vote(): +@app.route('/question_page/vote_question',methods=['GET','POST']) +def vote_question(): vote = int(request.form.get('vote_num')) vote_up = request.form.get('vote_up') vote_down = request.form.get('vote_down') @@ -43,10 +43,25 @@ def vote(): vote += 1 elif vote_down == 'down': vote -= 1 - comment_data_manager.update_vote_number(vote=vote, q_id=q_id) + question_data_manager.update_vote_number_question(vote=vote, q_id=q_id) return redirect('/') +@app.route('/question_page/vote_answer',methods=['GET','POST']) +def vote_answer(): + vote = int(request.form.get('vote_num')) + vote_up = request.form.get('vote_up') + vote_down = request.form.get('vote_down') + a_id = request.form.get('a_id') + if request.method == 'POST': + if vote_up == 'up': + vote += 1 + elif vote_down == 'down': + vote -= 1 + answer_data_manager.update_vote_number_answer(vote=vote, a_id=a_id) + return redirect('/') + + @app.route('/question_page//delete') def delete_question(question_id): question_data_manager.delete_question(q_id=question_id) diff --git a/templates/question_page.html b/templates/question_page.html index 31528bf0f..e2c81ddbf 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -28,24 +28,32 @@

{{ question[0]['title'] }}


-

Comments

+

Comments:

{% for message in comment %}
{{ message['message'] }}

{% endfor %} -
+ - Vote UP
- Vote DOWN
+ Vote Up Question
+ Vote Down Question

Answers:

{% for answer in answers %}
{{ answer['message'] }}

+

Vote Number: {{ answer['vote_number'] }}

+
+ + + Vote Up Answer
+ Vote Down Answer
+ + comments:
{% for comment in answer_comment %} {% if comment['answer_id'] == answer['id'] %} @@ -54,7 +62,7 @@

Answers:

{% endfor %}
+ Comment: From 2a094f51ca5bb927e316851250e9c47935107198 Mon Sep 17 00:00:00 2001 From: Zollli Date: Tue, 12 Mar 2019 13:38:25 +0100 Subject: [PATCH 072/101] fixed comment_data_manager --- server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.py b/server.py index c6952ad8d..d08a9a836 100644 --- a/server.py +++ b/server.py @@ -100,7 +100,7 @@ def show_question(question_id): comment = comment_data_manager.collect_comment_to_question(q_id=question_id) answer_comment = [] for answer in answers: - temporary = data_manager.collect_comment_to_answer(a_id=answer['id']) + temporary = comment_data_manager.collect_comment_to_answer(a_id=answer['id']) if len(temporary) > 0: answer_comment.append(temporary) if len(answer_comment) <= 0: From 21a25725438b8e655b0e097b891e86a4f8d023b1 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Tue, 12 Mar 2019 14:00:28 +0100 Subject: [PATCH 073/101] registration complete --- password_hash.py | 12 +++++++ server.py | 35 ++++++++++++++----- templates/home_button.html | 2 +- templates/{reg_log.html => registration.html} | 10 +++--- user_data_manager.py | 9 +++++ 5 files changed, 54 insertions(+), 14 deletions(-) create mode 100644 password_hash.py rename templates/{reg_log.html => registration.html} (58%) create mode 100644 user_data_manager.py diff --git a/password_hash.py b/password_hash.py new file mode 100644 index 000000000..b33419c43 --- /dev/null +++ b/password_hash.py @@ -0,0 +1,12 @@ +import bcrypt + + +def hash_password(plain_text_password): + # By using bcrypt, the salt is saved into the hash itself + hashed_bytes = bcrypt.hashpw(plain_text_password.encode('utf-8'), bcrypt.gensalt()) + return hashed_bytes.decode('utf-8') + + +def verify_password(plain_text_password, hashed_password): + hashed_bytes_password = hashed_password.encode('utf-8') + return bcrypt.checkpw(plain_text_password.encode('utf-8'), hashed_bytes_password) \ No newline at end of file diff --git a/server.py b/server.py index a23ba8f5a..edbe87e18 100644 --- a/server.py +++ b/server.py @@ -3,6 +3,8 @@ import comment_data_manager import answer_data_manager import util +import password_hash +import user_data_manager app = Flask(__name__) @@ -19,7 +21,7 @@ def show_all_question(): return render_template('all_question.html', questions=questions) -@app.route('/all_question/sort',methods=['GET', 'POST']) +@app.route('/all_question/sort', methods=['GET', 'POST']) def show_all_sorted_question(): questions = sort_questions() return render_template('all_question.html', questions=questions) @@ -32,7 +34,7 @@ def sort_questions(): return result -@app.route('/question_page/vote',methods=['GET','POST']) +@app.route('/question_page/vote', methods=['GET', 'POST']) def vote(): vote = int(request.form.get('vote_num')) vote_up = request.form.get('vote_up') @@ -90,7 +92,8 @@ def show_question(question_id): answer_comment.append(temporary) if len(answer_comment) <= 0: answer_comment = [None] - return render_template('question_page.html', question=question, answers=answers, comment=comment, answer_comment=answer_comment[0]) + return render_template('question_page.html', question=question, answers=answers, comment=comment, + answer_comment=answer_comment[0]) @app.route('/question_page//edit') @@ -99,6 +102,22 @@ def edit_question(question_id): return render_template('add_question.html', result=result) +@app.route('/registration', methods=['GET', 'POST']) +def registration(): + if request.method == 'POST': + username, password = get_registration_data() + submission_time = util.submission_time_generator() + user_data_manager.insert_new_user(submission_time= submission_time, username=username, h_password=password) + return redirect('/') + return render_template('registration.html') + + +def get_registration_data(): + user_name = request.form.get('user_name') + password = password_hash.hash_password(request.form.get('password')) + return user_name, password + + @app.route('/rewrite_question', methods=['POST']) def rewrite_question(): updated_question = { @@ -114,11 +133,11 @@ def rewrite_question(): return show_question(updated_question['id']) -@app.route('/question_page//new-answer', methods=['GET','POST']) +@app.route('/question_page//new-answer', methods=['GET', 'POST']) def post_an_answer(question_id): result = [] message = "" - if request.method=='POST': + if request.method == 'POST': new_answer = create_answer(question_id, request.form['message'], request.form['image']) answer_data_manager.add_answer(form_data=new_answer) return redirect('/') @@ -174,11 +193,11 @@ def create_question(message, image, title): 'message': message, 'title': title, 'image': image, - 'view_number' : 1 + 'view_number': 1 } -@app.route('/question_page//comment', methods=['GET','POST']) +@app.route('/question_page//comment', methods=['GET', 'POST']) def add_comment_to_question(question_id): comment = 'question' if request.method == 'POST': @@ -189,7 +208,7 @@ def add_comment_to_question(question_id): return render_template('add_comment.html', question_id=question_id, comment=comment) -@app.route('/question_page///comment', methods=['GET','POST']) +@app.route('/question_page///comment', methods=['GET', 'POST']) def add_comment_to_answer(answer_id, question_id): comment = 'answer' if request.method == 'POST': diff --git a/templates/home_button.html b/templates/home_button.html index e193b2caf..a47d8c807 100644 --- a/templates/home_button.html +++ b/templates/home_button.html @@ -54,7 +54,7 @@
diff --git a/templates/reg_log.html b/templates/registration.html similarity index 58% rename from templates/reg_log.html rename to templates/registration.html index 7296b215f..885bd7dfa 100644 --- a/templates/reg_log.html +++ b/templates/registration.html @@ -2,15 +2,15 @@ - Login + registration -

{{ log }}

-
+

registration

+
- - + + \ No newline at end of file diff --git a/user_data_manager.py b/user_data_manager.py new file mode 100644 index 000000000..2ec0a4977 --- /dev/null +++ b/user_data_manager.py @@ -0,0 +1,9 @@ +import connection + +@connection.connection_handler +def insert_new_user(cursor, submission_time, username, h_password): + cursor.execute(""" + insert into "user" (submission_time, user_name,hashed_password) + values (%(submission_time)s, %(username)s, %(h_password)s) + """, + {'submission_time':submission_time,'username': username, 'h_password': h_password}) From d2271263fee0480468fafc7aee9e9f9699c2efce Mon Sep 17 00:00:00 2001 From: borosTamas Date: Tue, 12 Mar 2019 14:18:48 +0100 Subject: [PATCH 074/101] registration complete --- templates/home_button.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/home_button.html b/templates/home_button.html index a47d8c807..1bbec0827 100644 --- a/templates/home_button.html +++ b/templates/home_button.html @@ -54,7 +54,7 @@
From 41cb51c4fe68e6db53831a2976a67cd401fe844e Mon Sep 17 00:00:00 2001 From: LibLev Date: Tue, 12 Mar 2019 14:26:20 +0100 Subject: [PATCH 075/101] login in progress: html is almost done but the server don't get any data from there need to be fix! --- password_hash.py | 29 +++++++++++++++++++++++ question_data_manager.py | 6 ----- sample_data/askmatepart2-sample-data.sql | 3 +++ server.py | 30 ++++++++++++++++++++++-- static/css/main.css | 5 ++++ templates/home_button.html | 5 +--- templates/index.html | 7 ++++++ templates/login.html | 15 ++++++++++++ user_data_manager.py | 10 ++++++++ util.py | 3 ++- 10 files changed, 100 insertions(+), 13 deletions(-) create mode 100644 password_hash.py create mode 100644 templates/login.html create mode 100644 user_data_manager.py diff --git a/password_hash.py b/password_hash.py new file mode 100644 index 000000000..b2df39f74 --- /dev/null +++ b/password_hash.py @@ -0,0 +1,29 @@ +import bcrypt + + +def hash_password(plain_text_password): + # By using bcrypt, the salt is saved into the hash itself + hashed_bytes = bcrypt.hashpw(plain_text_password.encode('utf-8'), bcrypt.gensalt()) + return hashed_bytes.decode('utf-8') + + +def verify_password(plain_text_password, hashed_password): + hashed_bytes_password = hashed_password.encode('utf-8') + return bcrypt.checkpw(plain_text_password.encode('utf-8'), hashed_bytes_password) + + +if __name__ == '__main__': + # Test the above functions manually + original_password = 'my_very_secureP4ssword!' # From registration form + print('original_password: ' + original_password) + + hashed_password = hash_password(original_password) # This shall be saved in the DB + print('hashed_password: ' + hashed_password) + + user_input_password = 'Hey Siri, what is my password?' # From a login form, a mistyped input + is_matching = verify_password(user_input_password, hashed_password) + print('is_matching: ' + str(is_matching)) + + user_input_password = 'my_very_secureP4ssword!' # From a login form, the correct input + is_matching = verify_password(user_input_password, hashed_password) + print('is_matching: ' + str(is_matching)) \ No newline at end of file diff --git a/question_data_manager.py b/question_data_manager.py index d1257dccf..c8a4409ba 100644 --- a/question_data_manager.py +++ b/question_data_manager.py @@ -1,4 +1,3 @@ -import datetime import connection @@ -92,11 +91,6 @@ def add_question(cursor, from_data): from_data['title'], from_data['message'], from_data['image'])) - -def submission_time_generator(): - submission_time = datetime.datetime.now() - return submission_time - @connection.connection_handler def update_view_number(cursor, q_id): cursor.execute(""" diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index 81501ea4a..1c437a7f5 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -157,6 +157,9 @@ INSERT INTO comment VALUES (1, 0, NULL, 'Please clarify the question as it is to INSERT INTO comment VALUES (2, NULL, 1, 'I think you could use my_list = list() as well.', '2017-05-02 16:55:00'); SELECT pg_catalog.setval('comment_id_seq', 2, true); +INSERT INTO "user" VALUES (1, '2017-05-01 05:49:00', 'levente', '$2b$12$R8SYQ7.S9FcrlGMCJsawjuP8AG/KpmMENIz8pSTGx2PN/W/8s2lq2'); +SELECT pg_catalog.setval('user_id_seq', 1, true); + INSERT INTO tag VALUES (1, 'python'); INSERT INTO tag VALUES (2, 'sql'); INSERT INTO tag VALUES (3, 'css'); diff --git a/server.py b/server.py index a23ba8f5a..550cc39ca 100644 --- a/server.py +++ b/server.py @@ -1,16 +1,42 @@ -from flask import Flask, render_template, request, redirect +from flask import Flask, render_template, request, redirect, session, url_for, escape import question_data_manager import comment_data_manager import answer_data_manager import util + app = Flask(__name__) +app.secret_key = b'_5#y2L"F4Q8z\n\xec]/' @app.route('/') def render_index(): + if 'username' in session: + username = session['username'] + else: + username = 'You are not loged in' questions = question_data_manager.collect_latest_5_question() - return render_template('index.html', questions=questions) + return render_template('index.html', questions=questions, username=username) + + +@app.route('/login', methods=['GET', 'POST']) +def login(): + if request.method == 'POST': + session['username'] = request.form['username'] + print('username') + return redirect(url_for('render_index')) + return ''' +
+

+

+ + ''' + +@app.route('/logout') +def logout(): + # remove the username from the session if it's there + session.pop('username', None) + return redirect(url_for('render_index')) @app.route('/all_question') diff --git a/static/css/main.css b/static/css/main.css index 36f54d879..e2206c663 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -86,3 +86,8 @@ textarea{ border-radius: 5px; } +#login{ + position: absolute; + right: 5px; +} + diff --git a/templates/home_button.html b/templates/home_button.html index e193b2caf..54535cb56 100644 --- a/templates/home_button.html +++ b/templates/home_button.html @@ -52,10 +52,7 @@

-
- Login - Sig in -
+
diff --git a/templates/index.html b/templates/index.html index 35fd81ca9..f3fe7106b 100644 --- a/templates/index.html +++ b/templates/index.html @@ -6,6 +6,13 @@ + diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 000000000..e1fd65f59 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,15 @@ + + + + + Login + + +
+ Login + + + Sig in +
+ + \ No newline at end of file diff --git a/user_data_manager.py b/user_data_manager.py new file mode 100644 index 000000000..ca835355c --- /dev/null +++ b/user_data_manager.py @@ -0,0 +1,10 @@ +import connection + +@connection.connection_handler +def login(cursor): + cursor.execute(""" + SELECT * + FROM "user" + + """) + diff --git a/util.py b/util.py index 3608f481c..e82686ed5 100644 --- a/util.py +++ b/util.py @@ -3,4 +3,5 @@ def submission_time_generator(): submission_time = datetime.datetime.now() - return submission_time \ No newline at end of file + return submission_time + From 4f3e5a290701ac9b490b407d856f6bed3f15349b Mon Sep 17 00:00:00 2001 From: LibLev Date: Tue, 12 Mar 2019 15:05:51 +0100 Subject: [PATCH 076/101] login in server almost done... html send the datas to server. missing: user_data_manager functions and the login function in the server --- server.py | 16 ++++++++-------- templates/home_button.html | 7 ++++++- templates/index.html | 9 +-------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/server.py b/server.py index 3c9b9f06d..3d1553463 100644 --- a/server.py +++ b/server.py @@ -16,7 +16,7 @@ def render_index(): if 'username' in session: username = session['username'] else: - username = 'You are not loged in' + username = None questions = question_data_manager.collect_latest_5_question() return render_template('index.html', questions=questions, username=username) @@ -25,14 +25,14 @@ def render_index(): def login(): if request.method == 'POST': session['username'] = request.form['username'] - print('username') + password = request.form['password'] + hashed_password = password_hash.hash_password(password) + verify = password_hash.verify_password(password, hashed_password) + print(request.form['username']) + print(request.form['password']) return redirect(url_for('render_index')) - return ''' - -

-

- - ''' + return redirect(url_for("render_index")) + @app.route('/logout') def logout(): diff --git a/templates/home_button.html b/templates/home_button.html index 1bbec0827..598fc8456 100644 --- a/templates/home_button.html +++ b/templates/home_button.html @@ -53,7 +53,12 @@ Home

- Login + {{ username }} +
+ + + + Sign in

diff --git a/templates/index.html b/templates/index.html index f3fe7106b..2f0c26329 100644 --- a/templates/index.html +++ b/templates/index.html @@ -6,15 +6,8 @@ - -

+
{{ question['title'] }} {{ question['submission_time'] }} {{ question['view_number'] }}
+ + {% for user in users %} + + + + + + +
{{ user.id }}{{ user.name }}
+ + + \ No newline at end of file diff --git a/user_data_manager.py b/user_data_manager.py index 2ec0a4977..887fd4437 100644 --- a/user_data_manager.py +++ b/user_data_manager.py @@ -1,9 +1,20 @@ import connection + @connection.connection_handler def insert_new_user(cursor, submission_time, username, h_password): cursor.execute(""" insert into "user" (submission_time, user_name,hashed_password) values (%(submission_time)s, %(username)s, %(h_password)s) """, - {'submission_time':submission_time,'username': username, 'h_password': h_password}) + {'submission_time': submission_time, 'username': username, 'h_password': h_password}) + + +@connection.connection_handler +def select_all_user(cursor): + cursor.execute(""" + select * from "user" + """) + result=cursor.fetchall() + return result + From a82da1966c93adb1c9520f2079a34ad6398309ad Mon Sep 17 00:00:00 2001 From: Zollli Date: Tue, 12 Mar 2019 15:12:45 +0100 Subject: [PATCH 078/101] fixed askmate sql, deleted head<<<--- --- sample_data/askmatepart2-sample-data.sql | 16 +--------------- user_data_manager.py | 1 + 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index 81501ea4a..f6c845ae4 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -105,7 +105,7 @@ ALTER TABLE ONLY comment ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES "user"(id) on delete cascade; ALTER TABLE ONLY comment -<<<<<<< HEAD + ADD CONSTRAINT fk_answer_id FOREIGN KEY (answer_id) REFERENCES answer(id) on delete cascade; ALTER TABLE ONLY answer @@ -119,21 +119,7 @@ ALTER TABLE ONLY comment ALTER TABLE ONLY question_tag ADD CONSTRAINT fk_tag_id FOREIGN KEY (tag_id) REFERENCES tag(id) on delete cascade; -======= - ADD CONSTRAINT fk_answer_id FOREIGN KEY (answer_id) REFERENCES answer(id); - -ALTER TABLE ONLY answer - ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id); - -ALTER TABLE ONLY question_tag - ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id); - -ALTER TABLE ONLY comment - ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id); -ALTER TABLE ONLY question_tag - ADD CONSTRAINT fk_tag_id FOREIGN KEY (tag_id) REFERENCES tag(id); ->>>>>>> add sql sample data INSERT INTO question VALUES (0, '2017-04-28 08:29:00', 29, 7, 'How to make lists in Python?', 'I am totally new to this, any hints?', NULL); INSERT INTO question VALUES (1, '2017-04-29 09:19:00', 15, 9, 'Wordpress loading multiple jQuery Versions', 'I developed a plugin that uses the jquery booklet plugin (http://builtbywill.com/booklet/#/) this plugin binds a function to $ so I cann call $(".myBook").booklet(); diff --git a/user_data_manager.py b/user_data_manager.py index 2ec0a4977..05e779896 100644 --- a/user_data_manager.py +++ b/user_data_manager.py @@ -7,3 +7,4 @@ def insert_new_user(cursor, submission_time, username, h_password): values (%(submission_time)s, %(username)s, %(h_password)s) """, {'submission_time':submission_time,'username': username, 'h_password': h_password}) + From 873ddb1f419ab4ed2e4b803386e6a8a68839f230 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Tue, 12 Mar 2019 17:03:12 +0100 Subject: [PATCH 079/101] too many changes is one brach, add user id for new question and answer, find user id by username --- TODO | 3 +++ answer_data_manager.py | 6 ++--- question_data_manager.py | 6 ++--- sample_data/askmatepart2-sample-data.sql | 16 ++---------- server.py | 31 ++++++++++-------------- templates/index.html | 2 -- templates/login.html | 15 ------------ user_data_manager.py | 19 ++++++++++++--- util.py | 2 ++ 9 files changed, 41 insertions(+), 59 deletions(-) create mode 100644 TODO delete mode 100644 templates/login.html diff --git a/TODO b/TODO new file mode 100644 index 000000000..778d56d71 --- /dev/null +++ b/TODO @@ -0,0 +1,3 @@ +#TODO redirect +#TODO login/logout +#TODO CSS \ No newline at end of file diff --git a/answer_data_manager.py b/answer_data_manager.py index c42cc4a87..2d22a48ac 100644 --- a/answer_data_manager.py +++ b/answer_data_manager.py @@ -54,10 +54,10 @@ def collect_all_answer(cursor): @connection.connection_handler def add_answer(cursor, form_data): cursor.execute(""" - INSERT INTO answer(submission_time, vote_number, question_id, message, image) - VALUES (%s, %s, %s, %s, %s)""", + INSERT INTO answer(submission_time, vote_number, question_id, message, image,user_id) + VALUES (%s, %s, %s, %s, %s,%s)""", (form_data['submission_time'], form_data['vote_number'], form_data['question_id'], - form_data['message'], form_data['image'])) + form_data['message'], form_data['image'], form_data['user_id'])) diff --git a/question_data_manager.py b/question_data_manager.py index 9458c48ee..e8d7cdb64 100644 --- a/question_data_manager.py +++ b/question_data_manager.py @@ -84,12 +84,12 @@ def update_question(cursor, datas): @connection.connection_handler def add_question(cursor, from_data): cursor.execute(""" - INSERT INTO question(submission_time, view_number, vote_number, title, message, image) - VALUES (%s,%s,%s, %s,%s,%s)""", + INSERT INTO question(submission_time, view_number, vote_number, title, message, image,user_id) + VALUES (%s,%s,%s, %s,%s,%s,%s)""", ( from_data['submission_time'], from_data['view_number'], from_data['vote_number'], from_data['title'], - from_data['message'], from_data['image'])) + from_data['message'], from_data['image'], from_data['user_id'])) @connection.connection_handler def update_view_number(cursor, q_id): diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index fe83261fe..ae8bd8669 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -25,7 +25,8 @@ CREATE TABLE "user"( id serial NOT NULL, submission_time timestamp without time zone, user_name text, - hashed_password text + hashed_password text, + reputation integer ); @@ -106,19 +107,6 @@ ALTER TABLE ONLY comment ALTER TABLE ONLY comment - ADD CONSTRAINT fk_answer_id FOREIGN KEY (answer_id) REFERENCES answer(id) on delete cascade; - -ALTER TABLE ONLY answer - ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id) on delete cascade; - -ALTER TABLE ONLY question_tag - ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id) on delete cascade; - -ALTER TABLE ONLY comment - ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id) on delete cascade; - -ALTER TABLE ONLY question_tag - ADD CONSTRAINT fk_tag_id FOREIGN KEY (tag_id) REFERENCES tag(id) on delete cascade; INSERT INTO question VALUES (0, '2017-04-28 08:29:00', 29, 7, 'How to make lists in Python?', 'I am totally new to this, any hints?', NULL); diff --git a/server.py b/server.py index 3d1553463..e29d3266c 100644 --- a/server.py +++ b/server.py @@ -93,24 +93,13 @@ def vote_answer(): @app.route('/question_page//delete') def delete_question(question_id): question_data_manager.delete_question(q_id=question_id) - return show_all_question() - vote = int(request.form.get('vote_num')) - vote_up = request.form.get('vote_up') - vote_down = request.form.get('vote_down') - q_id = request.form.get('q_id') - if request.method == 'POST': - if vote_up == 'up': - vote += 1 - elif vote_down == 'down': - vote -= 1 - comment_data_manager.update_vote_number(vote=vote, q_id=q_id) - return redirect('/') + return redirect(url_for('show_all_question')) @app.route('/question_page///answer-delete') def delete_answer(question_id, answer_id): answer_data_manager.delete_answer(q_id=question_id, a_id=answer_id) - return show_question(question_id) + return redirect(url_for('show_question',question_id=question_id)) @app.route('/search', methods=['POST']) @@ -132,7 +121,7 @@ def show_question(question_id): if len(temporary) > 0: answer_comment.append(temporary) if len(answer_comment) <= 0: - answer_comment = [None] + answer_comment = [''] return render_template('question_page.html', question=question, answers=answers, comment=comment, answer_comment=answer_comment[0]) @@ -148,7 +137,8 @@ def registration(): if request.method == 'POST': username, password = get_registration_data() submission_time = util.submission_time_generator() - user_data_manager.insert_new_user(submission_time= submission_time, username=username, h_password=password) + reputation=0 + user_data_manager.insert_new_user(submission_time= submission_time, username=username, h_password=password, user_reputation = reputation) return redirect('/') return render_template('registration.html') @@ -171,7 +161,7 @@ def rewrite_question(): 'image': request.form.get('image') } question_data_manager.update_question(datas=updated_question) - return show_question(updated_question['id']) + return redirect(url_for('show_question', question_id=updated_question['id'])) @app.route('/question_page//new-answer', methods=['GET', 'POST']) @@ -187,12 +177,14 @@ def post_an_answer(question_id): def create_answer(question_id, message, image): + user_id=user_data_manager.get_user_id(username=session['username']) return { 'submission_time': util.submission_time_generator(), 'vote_number': 1, 'question_id': question_id, 'message': message, - 'image': image + 'image': image, + 'user_id': user_id['id'] } @@ -228,13 +220,16 @@ def add_question(): def create_question(message, image, title): + user_name = session['username'] + user_id = user_data_manager.get_user_id(username=user_name) return { 'submission_time': util.submission_time_generator(), 'vote_number': 1, 'message': message, 'title': title, 'image': image, - 'view_number': 1 + 'view_number': 1, + 'user_id': user_id['id'] } diff --git a/templates/index.html b/templates/index.html index 2f0c26329..2043ef17a 100644 --- a/templates/index.html +++ b/templates/index.html @@ -21,8 +21,6 @@

LATEST 5 QUESTION:

Vote Number -

-

{% for question in questions %} diff --git a/templates/login.html b/templates/login.html deleted file mode 100644 index e1fd65f59..000000000 --- a/templates/login.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Login - - - - - \ No newline at end of file diff --git a/user_data_manager.py b/user_data_manager.py index 05e779896..b9cda3405 100644 --- a/user_data_manager.py +++ b/user_data_manager.py @@ -1,10 +1,21 @@ import connection @connection.connection_handler -def insert_new_user(cursor, submission_time, username, h_password): +def insert_new_user(cursor, submission_time, username, h_password, user_reputation): cursor.execute(""" - insert into "user" (submission_time, user_name,hashed_password) - values (%(submission_time)s, %(username)s, %(h_password)s) + insert into "user" (submission_time, user_name,hashed_password, reputation) + values (%(submission_time)s, %(username)s, %(h_password)s, %(user_reputation)s) """, - {'submission_time':submission_time,'username': username, 'h_password': h_password}) + {'submission_time':submission_time,'username': username, 'h_password': h_password, 'user_reputation':user_reputation}) + + +@connection.connection_handler +def get_user_id(cursor, username): + cursor.execute(""" + select id from "user" + where user_name = %(username)s + """, + {'username': username}) + result = cursor.fetchone() + return result diff --git a/util.py b/util.py index e82686ed5..aa5cb9b7b 100644 --- a/util.py +++ b/util.py @@ -1,6 +1,8 @@ import datetime + + def submission_time_generator(): submission_time = datetime.datetime.now() return submission_time From 5e1d2e32981df5154969a060f64f65ef5aeb8ae6 Mon Sep 17 00:00:00 2001 From: LibLev Date: Tue, 12 Mar 2019 20:24:31 +0100 Subject: [PATCH 080/101] now you can log in but if you do anything on the page its automaticaly logout... it have to fix and the logout its not working YET --- server.py | 19 ++++++++++++++----- static/css/main.css | 5 +++-- templates/home_button.html | 12 +----------- templates/index.html | 4 ++-- templates/login.html | 11 +++++++---- user_data_manager.py | 13 +++++++++++++ 6 files changed, 40 insertions(+), 24 deletions(-) diff --git a/server.py b/server.py index 3d1553463..fd973c3c2 100644 --- a/server.py +++ b/server.py @@ -13,24 +13,33 @@ @app.route('/') def render_index(): + login_message = 'You are not loged in' if 'username' in session: username = session['username'] else: username = None questions = question_data_manager.collect_latest_5_question() - return render_template('index.html', questions=questions, username=username) + return render_template('index.html', questions=questions, username=username, login_message=login_message) @app.route('/login', methods=['GET', 'POST']) def login(): + questions = question_data_manager.collect_latest_5_question() if request.method == 'POST': session['username'] = request.form['username'] + username = session['username'] password = request.form['password'] - hashed_password = password_hash.hash_password(password) + h_password = user_data_manager.get_hashed_password(user_name=username) + hashed_password = h_password[0]['hashed_password'] verify = password_hash.verify_password(password, hashed_password) - print(request.form['username']) - print(request.form['password']) - return redirect(url_for('render_index')) + if verify == True: + login_message = 'Loged in as ' + username + return render_template('index.html', password=password, hashed_password=hashed_password, verify=verify, + login_message=login_message, questions=questions) + else: + login_message = 'Invalid username or password' + return render_template('index.html', password=password, hashed_password=hashed_password, verify=verify, + login_message=login_message, questions=questions) return redirect(url_for("render_index")) diff --git a/static/css/main.css b/static/css/main.css index e2206c663..9059c08e1 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -86,8 +86,9 @@ textarea{ border-radius: 5px; } -#login{ +.login{ position: absolute; - right: 5px; + right: 10px; } + diff --git a/templates/home_button.html b/templates/home_button.html index 598fc8456..844d7218e 100644 --- a/templates/home_button.html +++ b/templates/home_button.html @@ -52,17 +52,7 @@ -
- {{ username }} -
- - - -
- Sign in -
-
- +

diff --git a/templates/index.html b/templates/index.html index 2f0c26329..07316d727 100644 --- a/templates/index.html +++ b/templates/index.html @@ -6,9 +6,9 @@ +
{% include 'home_button.html' %}
- +

ASK MATE

Add new Question Show All Question diff --git a/templates/login.html b/templates/login.html index e1fd65f59..0c9ada38e 100644 --- a/templates/login.html +++ b/templates/login.html @@ -6,10 +6,13 @@
- Login - - - Sig in + {{ login_message }} + + + + + + Sign in
\ No newline at end of file diff --git a/user_data_manager.py b/user_data_manager.py index 05e779896..65c4c78a1 100644 --- a/user_data_manager.py +++ b/user_data_manager.py @@ -8,3 +8,16 @@ def insert_new_user(cursor, submission_time, username, h_password): """, {'submission_time':submission_time,'username': username, 'h_password': h_password}) + +@connection.connection_handler +def get_hashed_password(cursor, user_name): + cursor.execute(""" + SELECT hashed_password + FROM "user" + WHERE user_name = %(user_name)s + """, + {'user_name' : user_name}) + result = cursor.fetchall() + return result + + From fc949cf0a5b0bbfd1b370c997c46fe7c33a72362 Mon Sep 17 00:00:00 2001 From: LibLev Date: Tue, 12 Mar 2019 21:45:01 +0100 Subject: [PATCH 081/101] now you can login and logout but if you want to open an other page its automatically logout... --- static/css/main.css | 4 ++++ templates/add_comment.html | 1 + templates/add_question.html | 1 + templates/index.html | 4 ++++ templates/login.html | 2 +- templates/logout.html | 15 +++++++++++++++ templates/new_answer.html | 1 + templates/question_page.html | 1 + templates/registration.html | 1 + 9 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 templates/logout.html diff --git a/static/css/main.css b/static/css/main.css index 9059c08e1..69771f487 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -91,4 +91,8 @@ textarea{ right: 10px; } +.logout{ + position: absolute; + right: 10px; +} diff --git a/templates/add_comment.html b/templates/add_comment.html index 442af8d7f..4d1735136 100644 --- a/templates/add_comment.html +++ b/templates/add_comment.html @@ -6,6 +6,7 @@ +

Add Comment

{% if comment == 'question' %}
diff --git a/templates/add_question.html b/templates/add_question.html index 5db5c1097..780eaca6d 100644 --- a/templates/add_question.html +++ b/templates/add_question.html @@ -6,6 +6,7 @@ + {% include 'home_button.html' %} {% if result == [] %}

Add New Question

diff --git a/templates/index.html b/templates/index.html index 07316d727..cfd203edf 100644 --- a/templates/index.html +++ b/templates/index.html @@ -6,7 +6,11 @@ +{% if verify == True %} +
{% include 'logout.html' %}
+{% else %} +{% endif %}
{% include 'home_button.html' %}

ASK MATE

diff --git a/templates/login.html b/templates/login.html index 0c9ada38e..bc1509628 100644 --- a/templates/login.html +++ b/templates/login.html @@ -15,4 +15,4 @@ Sign in - \ No newline at end of file + diff --git a/templates/logout.html b/templates/logout.html new file mode 100644 index 000000000..778fe56cc --- /dev/null +++ b/templates/logout.html @@ -0,0 +1,15 @@ + + + + + Logout + + +
+ + \ No newline at end of file diff --git a/templates/new_answer.html b/templates/new_answer.html index bf4a5c35a..fee3a43b3 100644 --- a/templates/new_answer.html +++ b/templates/new_answer.html @@ -6,6 +6,7 @@ + {% include 'home_button.html' %} {% if result == [] %}

Post an Answer

diff --git a/templates/question_page.html b/templates/question_page.html index e2c81ddbf..70719df1d 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -6,6 +6,7 @@ +
{% include 'home_button.html' %}

diff --git a/templates/registration.html b/templates/registration.html index 885bd7dfa..47ae150dd 100644 --- a/templates/registration.html +++ b/templates/registration.html @@ -5,6 +5,7 @@ registration +

registration

From 06a867cf0f3cbddfa9047112f41532845b44b8c3 Mon Sep 17 00:00:00 2001 From: LibLev Date: Tue, 12 Mar 2019 22:42:52 +0100 Subject: [PATCH 082/101] signin button has been changed --- static/css/main.css | 1 + templates/add_question.html | 2 -- templates/login.html | 6 ++++-- templates/logout.html | 7 +------ templates/registration.html | 1 - 5 files changed, 6 insertions(+), 11 deletions(-) diff --git a/static/css/main.css b/static/css/main.css index 69771f487..62b3f7a5a 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -96,3 +96,4 @@ textarea{ right: 10px; } + diff --git a/templates/add_question.html b/templates/add_question.html index 780eaca6d..99c394363 100644 --- a/templates/add_question.html +++ b/templates/add_question.html @@ -6,8 +6,6 @@ - -{% include 'home_button.html' %} {% if result == [] %}

Add New Question

diff --git a/templates/login.html b/templates/login.html index bc1509628..8926d2b87 100644 --- a/templates/login.html +++ b/templates/login.html @@ -6,13 +6,15 @@ diff --git a/templates/logout.html b/templates/logout.html index 778fe56cc..54f0a2a54 100644 --- a/templates/logout.html +++ b/templates/logout.html @@ -5,11 +5,6 @@ Logout - +
\ No newline at end of file diff --git a/templates/registration.html b/templates/registration.html index 47ae150dd..885bd7dfa 100644 --- a/templates/registration.html +++ b/templates/registration.html @@ -5,7 +5,6 @@ registration -

registration

From 275a1cf945b3b1b5502b7e25a32be16aa9024880 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Mar 2019 11:05:02 +0100 Subject: [PATCH 083/101] list all users --- server.py | 22 +++++++--------------- templates/all_users.html | 17 ++++++++++++++--- templates/index.html | 1 + 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/server.py b/server.py index 822ab57ab..a004911a4 100644 --- a/server.py +++ b/server.py @@ -103,17 +103,7 @@ def vote_answer(): def delete_question(question_id): question_data_manager.delete_question(q_id=question_id) return show_all_question() - vote = int(request.form.get('vote_num')) - vote_up = request.form.get('vote_up') - vote_down = request.form.get('vote_down') - q_id = request.form.get('q_id') - if request.method == 'POST': - if vote_up == 'up': - vote += 1 - elif vote_down == 'down': - vote -= 1 - comment_data_manager.update_vote_number(vote=vote, q_id=q_id) - return redirect('/') + @app.route('/question_page///answer-delete') @@ -151,10 +141,6 @@ def edit_question(question_id): result = question_data_manager.find_question(q_id=question_id) return render_template('add_question.html', result=result) -@app.route('/all-user') -def list_all_user(): - result=user_data_manager.select_all_user() - return render_template('all_users.html', users=result) @app.route('/registration', methods=['GET', 'POST']) def registration(): @@ -272,6 +258,12 @@ def add_comment_to_answer(answer_id, question_id): return render_template('add_comment.html', answer_id=answer_id, question_id=question_id, comment=comment) +@app.route('/all-user') +def list_all_user(): + result = user_data_manager.select_all_user() + return render_template('all_users.html', users=result) + + if __name__ == "__main__": app.run( debug=True, diff --git a/templates/all_users.html b/templates/all_users.html index 148cbcae0..f1ae9ca15 100644 --- a/templates/all_users.html +++ b/templates/all_users.html @@ -3,19 +3,30 @@ Users + + +
{% include 'home_button.html' %}

All User

+ + + + + + {% for user in users %} - - + + + +
IDUser NameReputationSubmission Time
{{ user.id }}{{ user.name }}{{ user['id'] }}{{ user['user_name'] }}{{ user['reputation'] }}{{ user['submission_time']}}
- +{% endfor %} \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index cfd203edf..ef26beae8 100644 --- a/templates/index.html +++ b/templates/index.html @@ -14,6 +14,7 @@
{% include 'home_button.html' %}

ASK MATE

+All User Add new Question Show All Question

LATEST 5 QUESTION:

From 2dc968f3bc7f23a47c8356cecc235f7bec588af9 Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 13 Mar 2019 11:29:09 +0100 Subject: [PATCH 084/101] now you can login and if you go any other page from the index it's stay logged in, but unfortunatelly the login message don't show up. --- server.py | 5 +++-- templates/add_comment.html | 6 +++++- templates/add_question.html | 5 +++++ templates/all_question.html | 6 +++++- templates/index.html | 2 +- templates/logout.html | 4 ++++ templates/new_answer.html | 6 +++++- templates/question_page.html | 6 +++++- 8 files changed, 33 insertions(+), 7 deletions(-) diff --git a/server.py b/server.py index fd973c3c2..9b6fc3377 100644 --- a/server.py +++ b/server.py @@ -13,11 +13,12 @@ @app.route('/') def render_index(): - login_message = 'You are not loged in' if 'username' in session: username = session['username'] + login_message = 'Logged in as ' + username else: username = None + login_message = 'You are not loged in' questions = question_data_manager.collect_latest_5_question() return render_template('index.html', questions=questions, username=username, login_message=login_message) @@ -33,7 +34,7 @@ def login(): hashed_password = h_password[0]['hashed_password'] verify = password_hash.verify_password(password, hashed_password) if verify == True: - login_message = 'Loged in as ' + username + login_message = 'Logged in as ' + username return render_template('index.html', password=password, hashed_password=hashed_password, verify=verify, login_message=login_message, questions=questions) else: diff --git a/templates/add_comment.html b/templates/add_comment.html index 4d1735136..8911e9782 100644 --- a/templates/add_comment.html +++ b/templates/add_comment.html @@ -6,7 +6,11 @@ - +{% if username != None %} +
{% include 'logout.html' %}
+{% else %} + +{% endif %}

Add Comment

{% if comment == 'question' %} diff --git a/templates/add_question.html b/templates/add_question.html index 99c394363..3f9e6d603 100644 --- a/templates/add_question.html +++ b/templates/add_question.html @@ -6,6 +6,11 @@ +{% if username != None %} +
{% include 'logout.html' %}
+{% else %} + +{% endif %} {% if result == [] %}

Add New Question

diff --git a/templates/all_question.html b/templates/all_question.html index 3b4eca0eb..b89c9a1be 100644 --- a/templates/all_question.html +++ b/templates/all_question.html @@ -6,7 +6,11 @@ - +{% if username != None %} +
{% include 'logout.html' %}
+{% else %} + +{% endif %} {% include 'home_button.html' %}

ALL QUESTION

diff --git a/templates/index.html b/templates/index.html index cfd203edf..ee3e4bea9 100644 --- a/templates/index.html +++ b/templates/index.html @@ -6,7 +6,7 @@ -{% if verify == True %} +{% if username != None %}
{% include 'logout.html' %}
{% else %} diff --git a/templates/logout.html b/templates/logout.html index 54f0a2a54..2d5accc5e 100644 --- a/templates/logout.html +++ b/templates/logout.html @@ -6,5 +6,9 @@
+ + + + \ No newline at end of file diff --git a/templates/new_answer.html b/templates/new_answer.html index fee3a43b3..0600c250a 100644 --- a/templates/new_answer.html +++ b/templates/new_answer.html @@ -6,7 +6,11 @@ - +{% if username != None %} +
{% include 'logout.html' %}
+{% else %} + +{% endif %} {% include 'home_button.html' %} {% if result == [] %}

Post an Answer

diff --git a/templates/question_page.html b/templates/question_page.html index 70719df1d..22130257d 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -6,7 +6,11 @@ - +{% if username != None %} +
{% include 'logout.html' %}
+{% else %} + +{% endif %}
{% include 'home_button.html' %}

From 49300a4acacae703d79b11e00e31a002cfbfe08d Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Mar 2019 11:30:29 +0100 Subject: [PATCH 085/101] merge thing --- sample_data/askmatepart2-sample-data.sql | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index ae8bd8669..3feb03a0d 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -50,7 +50,8 @@ CREATE TABLE answer ( question_id integer, message text, image text, - user_id integer + user_id integer, + accepted boolean ); DROP TABLE IF EXISTS public.comment; @@ -106,7 +107,19 @@ ALTER TABLE ONLY comment ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES "user"(id) on delete cascade; ALTER TABLE ONLY comment + ADD CONSTRAINT fk_answer_id FOREIGN KEY (answer_id) REFERENCES answer(id) on delete cascade; + +ALTER TABLE ONLY answer + ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id) on delete cascade; + +ALTER TABLE ONLY question_tag + ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id) on delete cascade; + +ALTER TABLE ONLY comment + ADD CONSTRAINT fk_question_id FOREIGN KEY (question_id) REFERENCES question(id) on delete cascade; +ALTER TABLE ONLY question_tag + ADD CONSTRAINT fk_tag_id FOREIGN KEY (tag_id) REFERENCES tag(id) on delete cascade; INSERT INTO question VALUES (0, '2017-04-28 08:29:00', 29, 7, 'How to make lists in Python?', 'I am totally new to this, any hints?', NULL); From b6c95e4a5d6f307e3cce9f836c179e7f2dac0ba2 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Mar 2019 13:00:31 +0100 Subject: [PATCH 086/101] accept answer done --- answer_data_manager.py | 15 ++++++++++++--- server.py | 11 ++++++++++- templates/question_page.html | 9 +++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/answer_data_manager.py b/answer_data_manager.py index 2d22a48ac..f8e3d6690 100644 --- a/answer_data_manager.py +++ b/answer_data_manager.py @@ -54,12 +54,21 @@ def collect_all_answer(cursor): @connection.connection_handler def add_answer(cursor, form_data): cursor.execute(""" - INSERT INTO answer(submission_time, vote_number, question_id, message, image,user_id) - VALUES (%s, %s, %s, %s, %s,%s)""", + INSERT INTO answer(submission_time, vote_number, question_id, message, image,user_id,accepted) + VALUES (%s, %s, %s, %s, %s,%s,%s)""", (form_data['submission_time'], form_data['vote_number'], form_data['question_id'], - form_data['message'], form_data['image'], form_data['user_id'])) + form_data['message'], form_data['image'], form_data['user_id'], form_data['accepted'])) +@connection.connection_handler +def accept_answer(cursor, a_id): + cursor.execute(""" + Update answer + set accepted = TRUE + where id = %(a_id)s + """, + {'a_id': a_id}) + @connection.connection_handler def update_vote_number_answer(cursor, vote, a_id): diff --git a/server.py b/server.py index 97cce92bb..dcf314aba 100644 --- a/server.py +++ b/server.py @@ -186,6 +186,14 @@ def post_an_answer(question_id): return render_template('new_answer.html', question=question, result=result, message=message) +@app.route('/accept-answer', methods=['POST', 'GET']) +def accept_answer(): + answer_id = request.form['a_id'] + question_id = request.form['q_id'] + answer_data_manager.accept_answer(a_id=answer_id) + return redirect(url_for('show_question', question_id=question_id)) + + def create_answer(question_id, message, image): user_id=user_data_manager.get_user_id(username=session['username']) return { @@ -194,7 +202,8 @@ def create_answer(question_id, message, image): 'question_id': question_id, 'message': message, 'image': image, - 'user_id': user_id['id'] + 'user_id': user_id['id'], + 'accepted': False } diff --git a/templates/question_page.html b/templates/question_page.html index 22130257d..54d28404c 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -59,6 +59,15 @@

Answers:

Vote Down Answer
+ {% if answer['accepted'] == True %} +

accepted

+ {% else %} +
+ + + +
+ {% endif %} comments:
{% for comment in answer_comment %} {% if comment['answer_id'] == answer['id'] %} From 887ae503573badf76e31869f8d6934eb48921cd5 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Mar 2019 13:15:59 +0100 Subject: [PATCH 087/101] sho images from url --- static/css/main.css | 4 ++++ templates/add_question.html | 2 +- templates/new_answer.html | 2 +- templates/question_page.html | 3 ++- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/static/css/main.css b/static/css/main.css index 62b3f7a5a..04ce14d54 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -38,6 +38,10 @@ body { color: black; font-max-size: small; } +.accepted_answer{ + background-color: lawngreen; + width: 80px; +} .button { background-color: #555555; diff --git a/templates/add_question.html b/templates/add_question.html index 3f9e6d603..d56144918 100644 --- a/templates/add_question.html +++ b/templates/add_question.html @@ -23,7 +23,7 @@

Add New Question

Image:
- +


diff --git a/templates/new_answer.html b/templates/new_answer.html index 0600c250a..59d34acc0 100644 --- a/templates/new_answer.html +++ b/templates/new_answer.html @@ -22,7 +22,7 @@

Post an Answer


Image
-
+
{% else %} diff --git a/templates/question_page.html b/templates/question_page.html index 54d28404c..313ff5134 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -24,7 +24,7 @@

{{ question[0]['title'] }}

Message:

{{ question[0]['message'] }}


-Image:{{ question[0]['image'] }}
+Image:
@@ -51,6 +51,7 @@

Comments:

Answers:

{% for answer in answers %}
{{ answer['message'] }}

+

Vote Number: {{ answer['vote_number'] }}

From 676f091d84de8b43c926312dfc9928c5cbad5cc4 Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 13 Mar 2019 13:36:53 +0100 Subject: [PATCH 088/101] now you can login and stay login, if you try to use an invalid username or password you'll get an invalid message, and you can logout --- server.py | 38 ++++++++++++++++++------------------ templates/add_comment.html | 2 +- templates/add_question.html | 3 ++- templates/all_question.html | 2 +- templates/all_users.html | 6 +++++- templates/index.html | 2 +- templates/new_answer.html | 2 +- templates/question_page.html | 2 +- user_data_manager.py | 12 +++++++++++- 9 files changed, 42 insertions(+), 27 deletions(-) diff --git a/server.py b/server.py index 97cce92bb..f4d50c34c 100644 --- a/server.py +++ b/server.py @@ -13,41 +13,41 @@ @app.route('/') def render_index(): - if 'username' in session: - username = session['username'] - login_message = 'Logged in as ' + username - else: - username = None - login_message = 'You are not loged in' + login_message = 'You are not logged in' questions = question_data_manager.collect_latest_5_question() - return render_template('index.html', questions=questions, username=username, login_message=login_message) + return render_template('index.html', questions=questions, login_message=login_message) @app.route('/login', methods=['GET', 'POST']) def login(): questions = question_data_manager.collect_latest_5_question() if request.method == 'POST': - session['username'] = request.form['username'] - username = session['username'] + username = request.form['username'] password = request.form['password'] - h_password = user_data_manager.get_hashed_password(user_name=username) - hashed_password = h_password[0]['hashed_password'] - verify = password_hash.verify_password(password, hashed_password) - if verify == True: - login_message = 'Logged in as ' + username - return render_template('index.html', password=password, hashed_password=hashed_password, verify=verify, - login_message=login_message, questions=questions) + find_user = user_data_manager.find_user(username=username) + if find_user != None: + h_password = user_data_manager.get_hashed_password(user_name=username) + hashed_password = h_password['hashed_password'] + verify = password_hash.verify_password(password, hashed_password) + if verify == True: + session['verify'] = verify + session['username'] = username + login_message = 'Logged in as ' + username + return render_template('index.html', verify=verify, login_message=login_message, questions=questions) + else: + session['verify'] = verify + login_message = 'Invalid username or password' + return render_template('index.html', login_message=login_message, questions=questions) else: login_message = 'Invalid username or password' - return render_template('index.html', password=password, hashed_password=hashed_password, verify=verify, - login_message=login_message, questions=questions) + return render_template('index.html', login_message=login_message, questions=questions) return redirect(url_for("render_index")) @app.route('/logout') def logout(): # remove the username from the session if it's there - session.pop('username', None) + session.clear() return redirect(url_for('render_index')) diff --git a/templates/add_comment.html b/templates/add_comment.html index 8911e9782..a6752f55e 100644 --- a/templates/add_comment.html +++ b/templates/add_comment.html @@ -6,7 +6,7 @@ -{% if username != None %} +{% if session['verify'] == True %}
{% include 'logout.html' %}
{% else %} diff --git a/templates/add_question.html b/templates/add_question.html index 3f9e6d603..2c2833ab6 100644 --- a/templates/add_question.html +++ b/templates/add_question.html @@ -6,11 +6,12 @@ -{% if username != None %} +{% if session['verify'] == True %}
{% include 'logout.html' %}
{% else %} {% endif %} +
{% include 'home_button.html' %}
{% if result == [] %}

Add New Question

diff --git a/templates/all_question.html b/templates/all_question.html index b89c9a1be..2d4d64858 100644 --- a/templates/all_question.html +++ b/templates/all_question.html @@ -6,7 +6,7 @@ -{% if username != None %} +{% if session['verify'] == True %}
{% include 'logout.html' %}
{% else %} diff --git a/templates/all_users.html b/templates/all_users.html index f1ae9ca15..2dce691f8 100644 --- a/templates/all_users.html +++ b/templates/all_users.html @@ -6,7 +6,11 @@ - +{% if session['verify'] == True %} +
{% include 'logout.html' %}
+{% else %} + +{% endif %}
{% include 'home_button.html' %}

All User

diff --git a/templates/index.html b/templates/index.html index 9c69648f3..68d8b5378 100644 --- a/templates/index.html +++ b/templates/index.html @@ -6,7 +6,7 @@ -{% if username != None %} +{% if session['verify'] == True %}
{% include 'logout.html' %}
{% else %} diff --git a/templates/new_answer.html b/templates/new_answer.html index 0600c250a..e1473267b 100644 --- a/templates/new_answer.html +++ b/templates/new_answer.html @@ -6,7 +6,7 @@ -{% if username != None %} +{% if session['verify'] == True %}
{% include 'logout.html' %}
{% else %} diff --git a/templates/question_page.html b/templates/question_page.html index 22130257d..b5e61eb0e 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -6,7 +6,7 @@ -{% if username != None %} +{% if session['verify'] == True %}
{% include 'logout.html' %}
{% else %} diff --git a/user_data_manager.py b/user_data_manager.py index 3e6957a1a..b6f4eb6bb 100644 --- a/user_data_manager.py +++ b/user_data_manager.py @@ -10,6 +10,16 @@ def insert_new_user(cursor, submission_time, username, h_password, user_reputati {'submission_time':submission_time,'username': username, 'h_password': h_password, 'user_reputation':user_reputation}) +@connection.connection_handler +def find_user(cursor, username): + cursor.execute(""" + select user_name + from "user" + where user_name=%(username)s""", + {'username' : username}) + result = cursor.fetchone() + return result + @connection.connection_handler def get_user_id(cursor, username): @@ -29,7 +39,7 @@ def get_hashed_password(cursor, user_name): WHERE user_name = %(user_name)s """, {'user_name' : user_name}) - result = cursor.fetchall() + result = cursor.fetchone() return result From 35c85e2e02d196e6e851d2dd9030cc8e510eb891 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Mar 2019 13:51:44 +0100 Subject: [PATCH 089/101] bind comment to user merged --- comment_data_manager.py | 8 ++++---- server.py | 7 +++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/comment_data_manager.py b/comment_data_manager.py index 74cffc0ac..cc07e6c5f 100644 --- a/comment_data_manager.py +++ b/comment_data_manager.py @@ -22,13 +22,13 @@ def update_vote_number(cursor, vote, q_id): @connection.connection_handler -def add_comment_to_question(cursor, q_id, comment_message): +def add_comment_to_question(cursor, q_id, comment_message, u_id,s_time): cursor.execute(""" - insert into comment(question_id, message) - values (%(q_id)s,%(comment_message)s) + insert into comment(question_id, message, user_id, submission_time) + values (%(q_id)s,%(comment_message)s,%(u_id)s,%(s_time)s) """, - {'q_id': q_id, 'comment_message': comment_message}) + {'q_id': q_id, 'comment_message': comment_message, 'u_id': u_id, 's_time': s_time}) @connection.connection_handler diff --git a/server.py b/server.py index dcf314aba..3a31f1514 100644 --- a/server.py +++ b/server.py @@ -148,7 +148,7 @@ def registration(): username, password = get_registration_data() submission_time = util.submission_time_generator() reputation=0 - user_data_manager.insert_new_user(submission_time= submission_time, username=username, h_password=password, user_reputation = reputation) + user_data_manager.insert_new_user(submission_time=submission_time, username=username, h_password=password, user_reputation = reputation) return redirect('/') return render_template('registration.html') @@ -256,8 +256,11 @@ def create_question(message, image, title): def add_comment_to_question(question_id): comment = 'question' if request.method == 'POST': + user_name=session['username'] + user_id=user_data_manager.get_user_id(username=user_name) message = request.form['message'] - comment_data_manager.add_comment_to_question(q_id=question_id, comment_message=message) + time = util.submission_time_generator() + comment_data_manager.add_comment_to_question(q_id=question_id, comment_message=message, u_id=user_id['id'], s_time=time) return show_question(question_id) return render_template('add_comment.html', question_id=question_id, comment=comment) From fd25b061530d33376527cff316d3cbaf05617c23 Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 13 Mar 2019 14:08:38 +0100 Subject: [PATCH 090/101] now you can login and stay login, if you try to use an invalid username or password you'll get an invalid message, and you can logout --- templates/navbar.html | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 templates/navbar.html diff --git a/templates/navbar.html b/templates/navbar.html new file mode 100644 index 000000000..4dc17a733 --- /dev/null +++ b/templates/navbar.html @@ -0,0 +1,10 @@ + + + + + Navbar + + + + + \ No newline at end of file From 6fdc3a04272393b16868cdbbd0d6e49336f98180 Mon Sep 17 00:00:00 2001 From: Zollli Date: Wed, 13 Mar 2019 14:14:56 +0100 Subject: [PATCH 091/101] reputation answer, question vote up,down ready --- answer_data_manager.py | 35 ++++++++++++++++++++++++++++++++++- question_data_manager.py | 32 ++++++++++++++++++++++++++++++++ server.py | 16 ++++++++++++++-- templates/all_users.html | 3 +-- user_data_manager.py | 1 + util.py | 2 -- 6 files changed, 82 insertions(+), 7 deletions(-) diff --git a/answer_data_manager.py b/answer_data_manager.py index 2d22a48ac..e75e1e3a5 100644 --- a/answer_data_manager.py +++ b/answer_data_manager.py @@ -78,4 +78,37 @@ def update_view_number(cursor, q_id): set view_number = view_number+1 where id = %(q_id)s """, - {'q_id': q_id}) \ No newline at end of file + {'q_id': q_id}) + + +@connection.connection_handler +def update_reputation(cursor,user_id,new_reputation): + cursor.execute(""" + UPDATE "user" + SET reputation = %(new_reputation)s + WHERE id = %(user_id)s + """, + {'user_id':user_id, 'new_reputation':new_reputation}) + + +@connection.connection_handler +def get_userid_used_answer(cursor,a_id): + cursor.execute(""" + SELECT user_id FROM answer + WHERE id = %(a_id)s + """, + {'a_id':a_id}) + + result = cursor.fetchall() + return result + + +@connection.connection_handler +def get_reputation(cursor,user_id): + cursor.execute(""" + SELECT reputation FROM "user" + WHERE id = %(user_id)s + """, + {'user_id':user_id}) + result = cursor.fetchone() + return result \ No newline at end of file diff --git a/question_data_manager.py b/question_data_manager.py index e8d7cdb64..4bbe66633 100644 --- a/question_data_manager.py +++ b/question_data_manager.py @@ -110,3 +110,35 @@ def update_vote_number_question(cursor, vote, q_id): """, {'vote': vote, 'q_id': q_id}) + +@connection.connection_handler +def update_reputation(cursor,user_id,new_reputation): + cursor.execute(""" + UPDATE "user" + SET reputation = %(new_reputation)s + WHERE id = %(user_id)s + """, + {'user_id':user_id, 'new_reputation':new_reputation}) + + +@connection.connection_handler +def get_userid_used_question(cursor,q_id): + cursor.execute(""" + SELECT user_id FROM question + WHERE id = %(q_id)s + """, + {'q_id':q_id}) + + result = cursor.fetchall() + return result + + +@connection.connection_handler +def get_reputation(cursor,user_id): + cursor.execute(""" + SELECT reputation FROM "user" + WHERE id = %(user_id)s + """, + {'user_id':user_id}) + result = cursor.fetchone() + return result \ No newline at end of file diff --git a/server.py b/server.py index 97cce92bb..1cb35710f 100644 --- a/server.py +++ b/server.py @@ -76,10 +76,16 @@ def vote_question(): vote_up = request.form.get('vote_up') vote_down = request.form.get('vote_down') q_id = request.form.get('q_id') + id = question_data_manager.get_userid_used_question(q_id) + reputation = question_data_manager.get_reputation(id[0]['user_id']) if request.method == 'POST': if vote_up == 'up': + reputation = reputation['reputation'] + 5 + question_data_manager.update_reputation(id[0]['user_id'], reputation) vote += 1 elif vote_down == 'down': + reputation = reputation['reputation'] - 2 + question_data_manager.update_reputation(id[0]['user_id'], reputation) vote -= 1 question_data_manager.update_vote_number_question(vote=vote, q_id=q_id) return redirect('/') @@ -91,11 +97,17 @@ def vote_answer(): vote_up = request.form.get('vote_up') vote_down = request.form.get('vote_down') a_id = request.form.get('a_id') + id = answer_data_manager.get_userid_used_answer(a_id) + reputation = answer_data_manager.get_reputation(id[0]['user_id']) if request.method == 'POST': if vote_up == 'up': - vote += 1 + reputation = reputation['reputation'] + 10 + answer_data_manager.update_reputation(id[0]['user_id'], reputation) + vote += 1 elif vote_down == 'down': - vote -= 1 + reputation = reputation['reputation'] -2 + answer_data_manager.update_reputation(id[0]['user_id'], reputation) + vote -= 1 answer_data_manager.update_vote_number_answer(vote=vote, a_id=a_id) return redirect('/') diff --git a/templates/all_users.html b/templates/all_users.html index f1ae9ca15..3a254c7c6 100644 --- a/templates/all_users.html +++ b/templates/all_users.html @@ -22,8 +22,7 @@

All User

- - +
{{ user['id'] }} {{ user['user_name'] }} {{ user['reputation'] }}{{ user['submission_time']}}{{ user['submission_time']}}
diff --git a/user_data_manager.py b/user_data_manager.py index 3e6957a1a..3e423db79 100644 --- a/user_data_manager.py +++ b/user_data_manager.py @@ -39,6 +39,7 @@ def get_hashed_password(cursor, user_name): def select_all_user(cursor): cursor.execute(""" select * from "user" + ORDER BY id """) result=cursor.fetchall() return result diff --git a/util.py b/util.py index aa5cb9b7b..e82686ed5 100644 --- a/util.py +++ b/util.py @@ -1,8 +1,6 @@ import datetime - - def submission_time_generator(): submission_time = datetime.datetime.now() return submission_time From 140b49bea0247e08a4fe5ca539d1d9da7530e87f Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Mar 2019 15:32:59 +0100 Subject: [PATCH 092/101] save progress --- TODO | 9 ++++++++- answer_data_manager.py | 13 ++++++++++++- comment_data_manager.py | 17 ++++++++++++++--- question_data_manager.py | 11 +++++++++++ server.py | 6 ++++++ 5 files changed, 51 insertions(+), 5 deletions(-) diff --git a/TODO b/TODO index 778d56d71..5b70bca79 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,10 @@ #TODO redirect #TODO login/logout -#TODO CSS \ No newline at end of file +#TODO CSS + +USER PAGE: +#TODO querry find all questions from user +#TODO querry find all answers from user +#TODO querry find all comment from user +#TODO server function use this and send the datas to the html +#TODO user page html \ No newline at end of file diff --git a/answer_data_manager.py b/answer_data_manager.py index e743b09cb..65cac0c70 100644 --- a/answer_data_manager.py +++ b/answer_data_manager.py @@ -120,4 +120,15 @@ def get_reputation(cursor,user_id): """, {'user_id':user_id}) result = cursor.fetchone() - return result \ No newline at end of file + return result + + +@connection.connection_handler +def get_all_answes_form_user(cursor, u_id): + cursor.execute("""Select question.title as question_title, answer.message as answer from answer + join question on question_id=question.id + where answer.user_id= %(u_id)s + """, + {'u_id':u_id}) + result=cursor.fetchall() + return result diff --git a/comment_data_manager.py b/comment_data_manager.py index cc07e6c5f..691abd488 100644 --- a/comment_data_manager.py +++ b/comment_data_manager.py @@ -22,7 +22,7 @@ def update_vote_number(cursor, vote, q_id): @connection.connection_handler -def add_comment_to_question(cursor, q_id, comment_message, u_id,s_time): +def add_comment_to_question(cursor, q_id, comment_message, u_id, s_time): cursor.execute(""" insert into comment(question_id, message, user_id, submission_time) values (%(q_id)s,%(comment_message)s,%(u_id)s,%(s_time)s) @@ -38,7 +38,7 @@ def add_comment_to_answer(cursor, a_id, comment_message): values (%(a_id)s,%(comment_message)s) """, - {'a_id': a_id, 'comment_message': comment_message}) + {'a_id': a_id, 'comment_message': comment_message}) @connection.connection_handler @@ -51,6 +51,7 @@ def collect_comment_to_question(cursor, q_id): result = cursor.fetchall() return result + @connection.connection_handler def collect_comment_to_answer(cursor, a_id): cursor.execute(""" @@ -62,4 +63,14 @@ def collect_comment_to_answer(cursor, a_id): return result - +@connection.connection_handler +def get_all_comments_from_user(cursor, u_id): + cursor.execute(""" + Select comment.message as comment, question.title as question, answer.message as answer from comment + full join answer on comment.answer_id = answer.id + full join question on comment.question_id = question.id + where comment.user_id = %(u_id)s + """, + {'u_id': u_id}) + result = cursor.fetchall() + return result diff --git a/question_data_manager.py b/question_data_manager.py index 4bbe66633..cb986b38c 100644 --- a/question_data_manager.py +++ b/question_data_manager.py @@ -141,4 +141,15 @@ def get_reputation(cursor,user_id): """, {'user_id':user_id}) result = cursor.fetchone() + return result + + +@connection.connection_handler +def get_all_quesrion_by_user(cursor,u_id): + cursor.execute(""" + select title from question + where user_id = %(u_id)s + """, + {'q_id':u_id}) + result=cursor.fetchall() return result \ No newline at end of file diff --git a/server.py b/server.py index 659b5595f..2c2714012 100644 --- a/server.py +++ b/server.py @@ -293,6 +293,12 @@ def list_all_user(): result = user_data_manager.select_all_user() return render_template('all_users.html', users=result) +@app.route('/user_page/') +def show_user_page(user_id): + questions_by_user=question_data_manager.get_all_quesrion_by_user(u_id=user_id) + answers_by_user=answer_data_manager.get_all_answes_form_user(u_id=user_id) + comments_by_user='' + if __name__ == "__main__": app.run( From 0c7f5f4a0d0dc806a80c7a5acf6102025d240774 Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 13 Mar 2019 15:55:23 +0100 Subject: [PATCH 093/101] now its ugly but its working --- server.py | 6 ++++-- templates/login.html | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/server.py b/server.py index 2c2714012..1e2b4337c 100644 --- a/server.py +++ b/server.py @@ -13,9 +13,8 @@ @app.route('/') def render_index(): - login_message = 'You are not logged in' questions = question_data_manager.collect_latest_5_question() - return render_template('index.html', questions=questions, login_message=login_message) + return render_template('index.html', questions=questions) @app.route('/login', methods=['GET', 'POST']) @@ -33,13 +32,16 @@ def login(): session['verify'] = verify session['username'] = username login_message = 'Logged in as ' + username + session['login_message'] = login_message return render_template('index.html', verify=verify, login_message=login_message, questions=questions) else: session['verify'] = verify login_message = 'Invalid username or password' + session['login_message'] = login_message return render_template('index.html', login_message=login_message, questions=questions) else: login_message = 'Invalid username or password' + session['login_message'] = login_message return render_template('index.html', login_message=login_message, questions=questions) return redirect(url_for("render_index")) diff --git a/templates/login.html b/templates/login.html index 8926d2b87..0de23d461 100644 --- a/templates/login.html +++ b/templates/login.html @@ -6,7 +6,7 @@
- + From fd0213f152fc107701070cec5d16ecf0c895112b Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 13 Mar 2019 16:20:13 +0100 Subject: [PATCH 094/101] css table are looking superb >.< --- static/css/main.css | 10 ++++++++++ templates/registration.html | 1 + 2 files changed, 11 insertions(+) diff --git a/static/css/main.css b/static/css/main.css index 04ce14d54..c70bcf3fa 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -100,4 +100,14 @@ textarea{ right: 10px; } +table, th, td{ + padding: 15px; + text-align: left; + +} + +th, td{ + border-bottom: 1px solid #000000; +} + diff --git a/templates/registration.html b/templates/registration.html index 885bd7dfa..74a8bf695 100644 --- a/templates/registration.html +++ b/templates/registration.html @@ -3,6 +3,7 @@ registration +

registration

From fc0433d13ced8a9a3b6421d384417f6fc58db21d Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Mar 2019 17:05:42 +0100 Subject: [PATCH 095/101] save progress2 --- answer_data_manager.py | 2 +- comment_data_manager.py | 2 +- question_data_manager.py | 4 +-- server.py | 11 ++++-- static/css/main.css | 4 +++ templates/index.html | 3 ++ templates/user_page.html | 74 ++++++++++++++++++++++++++++++++++++++++ user_data_manager.py | 12 +++++-- 8 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 templates/user_page.html diff --git a/answer_data_manager.py b/answer_data_manager.py index 65cac0c70..b30d27455 100644 --- a/answer_data_manager.py +++ b/answer_data_manager.py @@ -125,7 +125,7 @@ def get_reputation(cursor,user_id): @connection.connection_handler def get_all_answes_form_user(cursor, u_id): - cursor.execute("""Select question.title as question_title, answer.message as answer from answer + cursor.execute("""Select question_id, question.title as question_title, answer.message as answer, answer.vote_number as vote_number from answer join question on question_id=question.id where answer.user_id= %(u_id)s """, diff --git a/comment_data_manager.py b/comment_data_manager.py index 691abd488..e2e71142e 100644 --- a/comment_data_manager.py +++ b/comment_data_manager.py @@ -66,7 +66,7 @@ def collect_comment_to_answer(cursor, a_id): @connection.connection_handler def get_all_comments_from_user(cursor, u_id): cursor.execute(""" - Select comment.message as comment, question.title as question, answer.message as answer from comment + Select comment.message as comment, question.title as question, question.id as question_id, answer.question_id as question_id, answer.message as answer from comment full join answer on comment.answer_id = answer.id full join question on comment.question_id = question.id where comment.user_id = %(u_id)s diff --git a/question_data_manager.py b/question_data_manager.py index cb986b38c..8f2c5be05 100644 --- a/question_data_manager.py +++ b/question_data_manager.py @@ -147,9 +147,9 @@ def get_reputation(cursor,user_id): @connection.connection_handler def get_all_quesrion_by_user(cursor,u_id): cursor.execute(""" - select title from question + select id, title, message, vote_number, view_number from question where user_id = %(u_id)s """, - {'q_id':u_id}) + {'u_id':u_id}) result=cursor.fetchall() return result \ No newline at end of file diff --git a/server.py b/server.py index 2c2714012..6f76cf28d 100644 --- a/server.py +++ b/server.py @@ -15,7 +15,12 @@ def render_index(): login_message = 'You are not logged in' questions = question_data_manager.collect_latest_5_question() - return render_template('index.html', questions=questions, login_message=login_message) + if 'username' in session: + user_data = user_data_manager.get_user_id(username=session['username']) + user_id=user_data['id'] + else: + user_id='' + return render_template('index.html', questions=questions, login_message=login_message, user_id=user_id) @app.route('/login', methods=['GET', 'POST']) @@ -297,7 +302,9 @@ def list_all_user(): def show_user_page(user_id): questions_by_user=question_data_manager.get_all_quesrion_by_user(u_id=user_id) answers_by_user=answer_data_manager.get_all_answes_form_user(u_id=user_id) - comments_by_user='' + comments_by_user= comment_data_manager.get_all_comments_from_user(u_id=user_id) + user_data = user_data_manager.get_user_data(u_id=user_id) + return render_template('user_page.html', questions=questions_by_user, answers=answers_by_user, comments=comments_by_user, user_data=user_data) if __name__ == "__main__": diff --git a/static/css/main.css b/static/css/main.css index 04ce14d54..639918ddd 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -100,4 +100,8 @@ textarea{ right: 10px; } +.user_questions, table{ + +} + diff --git a/templates/index.html b/templates/index.html index 68d8b5378..1b562f260 100644 --- a/templates/index.html +++ b/templates/index.html @@ -14,6 +14,9 @@
{% include 'home_button.html' %}

ASK MATE

+{% if user_id != '' %} +User Page + {% endif %} All User Add new Question Show All Question diff --git a/templates/user_page.html b/templates/user_page.html new file mode 100644 index 000000000..5edcbfee4 --- /dev/null +++ b/templates/user_page.html @@ -0,0 +1,74 @@ + + + + + User Page + + + +
{% include 'home_button.html' %}
+

{{ user_data['user_name'] }}

+Reputation: {{ user_data['reputation'] }} +
+ID: {{ user_data['id'] }} +
+

QUESTIONS:

+ + + + + + + + + {% for question in questions %} + + + + + + + {% endfor %} + +
TitleMessageView NumberVote Number
{{ question['title'] }}{{ question['message'] }}{{ question['view_number'] }}{{ question['vote_number'] }}
+
+
+

ANSWERS:

+ + + + + + + + {% for answer in answers%} + + + + + + {% endfor %} + +
QuestionAnswerVote Number
{{ answer['question_title'] }} {{ answer['message'] }}{{ answer['vote_number'] }}
+
+
+

Comments:

+ + + + + + + + {% for comment in comments %} + + + + + + {% endfor %} + +
QuestionAnswerComment
{{comment['question']}}{{comment['answer']}}{{comment['comment']}}
+
+ + \ No newline at end of file diff --git a/user_data_manager.py b/user_data_manager.py index dbb4a97f2..96ee499d8 100644 --- a/user_data_manager.py +++ b/user_data_manager.py @@ -43,8 +43,6 @@ def get_hashed_password(cursor, user_name): return result - - @connection.connection_handler def select_all_user(cursor): cursor.execute(""" @@ -54,3 +52,13 @@ def select_all_user(cursor): result=cursor.fetchall() return result + +@connection.connection_handler +def get_user_data(cursor, u_id): + cursor.execute(""" + select id, user_name, submission_time, reputation from "user" + where id = %(u_id)s + """, + {'u_id': u_id}) + result= cursor.fetchone() + return result From 5282ce6efab27bf726af113655a8bee15bfa9d56 Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 13 Mar 2019 17:26:01 +0100 Subject: [PATCH 096/101] asdasdasd --- server.py | 8 +++++--- static/css/main.css | 3 +-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/server.py b/server.py index 1e2b4337c..f639c9b81 100644 --- a/server.py +++ b/server.py @@ -20,6 +20,8 @@ def render_index(): @app.route('/login', methods=['GET', 'POST']) def login(): questions = question_data_manager.collect_latest_5_question() + login_message = 'You are not logged in' + session['login_message'] = login_message if request.method == 'POST': username = request.form['username'] password = request.form['password'] @@ -33,16 +35,16 @@ def login(): session['username'] = username login_message = 'Logged in as ' + username session['login_message'] = login_message - return render_template('index.html', verify=verify, login_message=login_message, questions=questions) + return redirect(url_for('render_index', verify=verify, login_message=login_message, questions=questions)) else: session['verify'] = verify login_message = 'Invalid username or password' session['login_message'] = login_message - return render_template('index.html', login_message=login_message, questions=questions) + return redirect(url_for('render_index', login_message=login_message, questions=questions)) else: login_message = 'Invalid username or password' session['login_message'] = login_message - return render_template('index.html', login_message=login_message, questions=questions) + return redirect(url_for('render_index', login_message=login_message, questions=questions)) return redirect(url_for("render_index")) diff --git a/static/css/main.css b/static/css/main.css index c70bcf3fa..c725deba9 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -39,7 +39,7 @@ body { font-max-size: small; } .accepted_answer{ - background-color: lawngreen; + background-color: #c38005; width: 80px; } @@ -103,7 +103,6 @@ textarea{ table, th, td{ padding: 15px; text-align: left; - } th, td{ From edc007263a3e1be6244b5e11ab47fcbf47029342 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Mar 2019 17:26:39 +0100 Subject: [PATCH 097/101] save progress3 --- server.py | 2 +- templates/question_page.html | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server.py b/server.py index 6cb87b466..14d89e7df 100644 --- a/server.py +++ b/server.py @@ -19,7 +19,7 @@ def render_index(): user_id=user_data['id'] else: user_id='' - return render_template('index.html', questions=questions, login_message=login_message, user_id=user_id) + return render_template('index.html', questions=questions, user_id=user_id) @app.route('/login', methods=['GET', 'POST']) diff --git a/templates/question_page.html b/templates/question_page.html index bfd0766f1..052aa084d 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -24,7 +24,7 @@

{{ question[0]['title'] }}

Message:

{{ question[0]['message'] }}


-Image:
+Image:
@@ -51,7 +51,7 @@

Comments:

Answers:

{% for answer in answers %}
{{ answer['message'] }}

- +

Vote Number: {{ answer['vote_number'] }}

From e95e4ab4e209577ce6c173517962fb259442ddb7 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Mar 2019 17:35:55 +0100 Subject: [PATCH 098/101] save progress4, minor bugfixes --- templates/all_users.html | 3 ++- templates/index.html | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/templates/all_users.html b/templates/all_users.html index a232c08cf..24e603703 100644 --- a/templates/all_users.html +++ b/templates/all_users.html @@ -28,8 +28,9 @@

All User

{{ user['reputation'] }} {{ user['submission_time']}}
+ {% endfor %} -{% endfor %} + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 1b562f260..9a3562823 100644 --- a/templates/index.html +++ b/templates/index.html @@ -18,7 +18,11 @@

ASK MATE

User Page {% endif %} All User -Add new Question +{% if user_id != '' %} + Add new Question +{% else %} +Add new Question +{% endif %} Show All Question

LATEST 5 QUESTION:

From 91241f78de5ad2513694c0e6310bbf5d3c4a2370 Mon Sep 17 00:00:00 2001 From: LibLev Date: Wed, 13 Mar 2019 17:51:11 +0100 Subject: [PATCH 099/101] logout burn in user page, defaultbutton has been created --- static/css/main.css | 11 +++++++++++ templates/index.html | 2 +- templates/user_page.html | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/static/css/main.css b/static/css/main.css index c725deba9..056e262a9 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -56,6 +56,17 @@ body { } +.defaultbutton{ + background-color: #040404; + border: none; + color: rgba(87, 87, 87, 0.71); + padding: 10px 24px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 20px; + border-radius: 4px; +} h1 { color: black; diff --git a/templates/index.html b/templates/index.html index 9a3562823..c504b1990 100644 --- a/templates/index.html +++ b/templates/index.html @@ -21,7 +21,7 @@

ASK MATE

{% if user_id != '' %} Add new Question {% else %} -Add new Question +Add new Question {% endif %} Show All Question

LATEST 5 QUESTION:

diff --git a/templates/user_page.html b/templates/user_page.html index 5edcbfee4..f18cb88b5 100644 --- a/templates/user_page.html +++ b/templates/user_page.html @@ -6,6 +6,7 @@ +
{% include 'logout.html' %}
{% include 'home_button.html' %}

{{ user_data['user_name'] }}

Reputation: {{ user_data['reputation'] }} From d73c99f792f0b099a263815ad3fc7e892891cfea Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Mar 2019 17:58:16 +0100 Subject: [PATCH 100/101] done --- comment_data_manager.py | 2 +- templates/user_page.html | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/comment_data_manager.py b/comment_data_manager.py index e2e71142e..fa2bf8702 100644 --- a/comment_data_manager.py +++ b/comment_data_manager.py @@ -66,7 +66,7 @@ def collect_comment_to_answer(cursor, a_id): @connection.connection_handler def get_all_comments_from_user(cursor, u_id): cursor.execute(""" - Select comment.message as comment, question.title as question, question.id as question_id, answer.question_id as question_id, answer.message as answer from comment + Select comment.message as comment, question.title as question, question.id as q_id, answer.question_id as question_id, answer.message as answer from comment full join answer on comment.answer_id = answer.id full join question on comment.question_id = question.id where comment.user_id = %(u_id)s diff --git a/templates/user_page.html b/templates/user_page.html index 5edcbfee4..b7b370163 100644 --- a/templates/user_page.html +++ b/templates/user_page.html @@ -23,7 +23,7 @@

QUESTIONS:

{% for question in questions %} - + @@ -43,7 +43,7 @@

ANSWERS:

{% for answer in answers%} - + @@ -62,8 +62,16 @@

Comments:

{% for comment in comments %} - - + {% if comment['question'] != None %} + + {% else %} + + {% endif %} + {% if comment['answer'] != None %} + + {% else %} + + {% endif %} {% endfor %} From 2b0de6eb63e6c29fd0139309daf928e625249a47 Mon Sep 17 00:00:00 2001 From: borosTamas Date: Wed, 13 Mar 2019 18:10:57 +0100 Subject: [PATCH 101/101] bugfix on redirect --- server.py | 7 ++++--- templates/question_page.html | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/server.py b/server.py index a809ddf16..75cfbbe7e 100644 --- a/server.py +++ b/server.py @@ -97,11 +97,12 @@ def vote_question(): question_data_manager.update_reputation(id[0]['user_id'], reputation) vote -= 1 question_data_manager.update_vote_number_question(vote=vote, q_id=q_id) - return redirect('/') + return redirect(url_for('show_question', question_id=q_id)) @app.route('/question_page/vote_answer',methods=['GET','POST']) def vote_answer(): + q_id= request.form.get('question_id') vote = int(request.form.get('vote_num')) vote_up = request.form.get('vote_up') vote_down = request.form.get('vote_down') @@ -118,7 +119,7 @@ def vote_answer(): answer_data_manager.update_reputation(id[0]['user_id'], reputation) vote -= 1 answer_data_manager.update_vote_number_answer(vote=vote, a_id=a_id) - return redirect('/') + return redirect(url_for('show_question',question_id=q_id)) @app.route('/question_page//delete') @@ -202,7 +203,7 @@ def post_an_answer(question_id): if request.method == 'POST': new_answer = create_answer(question_id, request.form['message'], request.form['image']) answer_data_manager.add_answer(form_data=new_answer) - return redirect('/') + return redirect(url_for('show_question', question_id=question_id)) question = question_data_manager.find_question(question_id) return render_template('new_answer.html', question=question, result=result, message=message) diff --git a/templates/question_page.html b/templates/question_page.html index 052aa084d..12b6096bc 100644 --- a/templates/question_page.html +++ b/templates/question_page.html @@ -54,6 +54,7 @@

Answers:

Vote Number: {{ answer['vote_number'] }}

+ Vote Up Answer
{{ question['title'] }} {{ question['title'] }} {{ question['message'] }} {{ question['view_number'] }} {{ question['vote_number'] }}
{{ answer['question_title'] }}{{ answer['question_title'] }} {{ answer['message'] }} {{ answer['vote_number'] }}
{{comment['question']}}{{comment['answer']}}{{comment['question']}}{{comment['answer']}}{{comment['comment']}}