From 4f44a93af1a3dc61bfdaec56ad72bade8026779b Mon Sep 17 00:00:00 2001 From: michalkandybowicz Date: Mon, 25 Mar 2019 11:18:43 +0100 Subject: [PATCH 001/111] TEST --- sample_data/answer.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/sample_data/answer.csv b/sample_data/answer.csv index 3ddfa1ffb..4032211e9 100644 --- a/sample_data/answer.csv +++ b/sample_data/answer.csv @@ -1,3 +1,4 @@ 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", +TEST 321 \ No newline at end of file From 09eb49aa845cd72ba0ef7f6e256bab75f3d564d4 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Mon, 25 Mar 2019 11:46:19 +0100 Subject: [PATCH 002/111] Add project file and folder structure --- connection.py | 0 data_manager.py | 0 server.py | 0 templates/static | 0 util.py | 0 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 connection.py create mode 100644 data_manager.py create mode 100644 server.py create mode 100644 templates/static create mode 100644 util.py 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..e69de29bb diff --git a/server.py b/server.py new file mode 100644 index 000000000..e69de29bb diff --git a/templates/static b/templates/static new file mode 100644 index 000000000..e69de29bb diff --git a/util.py b/util.py new file mode 100644 index 000000000..e69de29bb From 1af35f8b3aba5ce7aee85daf25dbaa223f52ac67 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Mon, 25 Mar 2019 11:51:01 +0100 Subject: [PATCH 003/111] Remove static folder from templates to root --- templates/static | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 templates/static diff --git a/templates/static b/templates/static deleted file mode 100644 index e69de29bb..000000000 From c68a162370b39c544c51205cf10819b0093c9a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Szadkowski?= Date: Tue, 26 Mar 2019 12:14:58 +0100 Subject: [PATCH 004/111] data_manager --- connection.py | 17 +++++++++++++++++ data/answers.csv | 0 data/questions.csv | 14 ++++++++++++++ data_manager.py | 8 ++++++++ server.py | 33 +++++++++++++++++++++++++++++++++ templates/form.html | 8 ++++++++ templates/index.html | 4 ++++ templates/layout.html | 31 +++++++++++++++++++++++++++++++ templates/list.html | 33 +++++++++++++++++++++++++++++++++ templates/qd.html | 4 ++++ 10 files changed, 152 insertions(+) create mode 100644 data/answers.csv create mode 100644 data/questions.csv create mode 100644 templates/form.html create mode 100644 templates/index.html create mode 100644 templates/layout.html create mode 100644 templates/list.html create mode 100644 templates/qd.html diff --git a/connection.py b/connection.py index e69de29bb..5db4181da 100644 --- a/connection.py +++ b/connection.py @@ -0,0 +1,17 @@ +import csv + + +def read_file(filename="data/questions.csv"): + with open(filename, 'r') as f: + reader = csv.DictReader(f) + data = list(reader) + return data + + +def write_file(dict_list, filename="questions.csv"): + keys = dict_list[0].keys() + filedirectory = 'data/' + filename + with open(filedirectory, 'w') as f: + writer = csv.DictWriter(f, keys) + writer.writeheader() + writer.writerows(dict_list) diff --git a/data/answers.csv b/data/answers.csv new file mode 100644 index 000000000..e69de29bb diff --git a/data/questions.csv b/data/questions.csv new file mode 100644 index 000000000..e65825dc3 --- /dev/null +++ b/data/questions.csv @@ -0,0 +1,14 @@ +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(); + +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,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)", diff --git a/data_manager.py b/data_manager.py index e69de29bb..af1d3f54b 100644 --- a/data_manager.py +++ b/data_manager.py @@ -0,0 +1,8 @@ +import connection + + +def get_all_questions(): + q_list = sorted(connection.read_file(), key=lambda k: k['submission_time'], reverse=True) + return q_list + + diff --git a/server.py b/server.py index e69de29bb..3b4fc9379 100644 --- a/server.py +++ b/server.py @@ -0,0 +1,33 @@ +from flask import Flask, render_template, request, redirect +import data_manager + +app = Flask(__name__) + + +@app.route('/') +def route_home(): + return render_template('index.html') + + +@app.route('/list') +def route_list(): + stories = data_manager.get_all_questions() + return render_template('list.html', stories=stories) + + +@app.route('/add') +def route_add(): + return render_template('form.html') + + +@app.route('/story/') +def route_edit(id): + cokolwiek = 'hello world' + id + return cokolwiek + + +if __name__ == "__main__": + app.run( + debug=True, + port=5004 +) diff --git a/templates/form.html b/templates/form.html new file mode 100644 index 000000000..09c676cb5 --- /dev/null +++ b/templates/form.html @@ -0,0 +1,8 @@ +{% extends "layout.html" %} +{% block contents %} +
+
+ +
+
+{% endblock %} \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 000000000..03c5cc583 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,4 @@ +{% extends "layout.html" %} +{% block contents %} + +{% endblock %} \ No newline at end of file diff --git a/templates/layout.html b/templates/layout.html new file mode 100644 index 000000000..18cd4a8ba --- /dev/null +++ b/templates/layout.html @@ -0,0 +1,31 @@ + + + + + Title + + + + + + +
+ {% block contents %} + {% endblock contents %} +
+ + + \ No newline at end of file diff --git a/templates/list.html b/templates/list.html new file mode 100644 index 000000000..d3e7dd1ee --- /dev/null +++ b/templates/list.html @@ -0,0 +1,33 @@ +{% extends "layout.html" %} +{% block contents %} + +
+
+
+
+ + + + + + + + + + + {% for story in stories %} + + + + + + + + + + {% endfor %} +
IDTitleMessageSubmission TimeView NumberVote NumberImage
{{ story['id'] }} {{ story['title'] }} {{ story['message'] }} {{ story['submission_time'] }} {{ story['view_number'] }} {{ story['vote_number'] }} {{ story['image'] }}
+
+{% endblock %} \ No newline at end of file diff --git a/templates/qd.html b/templates/qd.html new file mode 100644 index 000000000..03c5cc583 --- /dev/null +++ b/templates/qd.html @@ -0,0 +1,4 @@ +{% extends "layout.html" %} +{% block contents %} + +{% endblock %} \ No newline at end of file From bdd60af027aae129f411aab1e29bc64d3a40dc01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Szadkowski?= Date: Tue, 26 Mar 2019 12:39:02 +0100 Subject: [PATCH 005/111] list and add --- server.py | 2 +- templates/form.html | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/server.py b/server.py index 3b4fc9379..7264c0a41 100644 --- a/server.py +++ b/server.py @@ -20,7 +20,7 @@ def route_add(): return render_template('form.html') -@app.route('/story/') +@app.route('/add-question/') def route_edit(id): cokolwiek = 'hello world' + id return cokolwiek diff --git a/templates/form.html b/templates/form.html index 09c676cb5..c21b29f0c 100644 --- a/templates/form.html +++ b/templates/form.html @@ -1,8 +1,23 @@ {% extends "layout.html" %} {% block contents %} -
-
- -
+
+
+
+
+
+

Add new Question


+
+
+ + +
+
+ + +
+ +
+
+
{% endblock %} \ No newline at end of file From 724c330a5a4951b3cd889626c7d12dea9e29369f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Szadkowski?= Date: Tue, 26 Mar 2019 13:43:10 +0100 Subject: [PATCH 006/111] data manager updated --- connection.py | 9 +++++---- data/questions.csv | 8 ++++---- data_manager.py | 9 +++++++++ server.py | 27 ++++++++++++++++++++++++--- templates/answer.html | 0 templates/form.html | 4 ++-- templates/index.html | 10 +++++++++- templates/layout.html | 2 +- templates/list.html | 2 +- templates/qd.html | 36 +++++++++++++++++++++++++++++++++++- 10 files changed, 90 insertions(+), 17 deletions(-) create mode 100644 templates/answer.html diff --git a/connection.py b/connection.py index 5db4181da..7abfb0824 100644 --- a/connection.py +++ b/connection.py @@ -1,8 +1,9 @@ import csv -def read_file(filename="data/questions.csv"): - with open(filename, 'r') as f: +def read_file(filename="questions.csv"): + file_directory = 'data/' + filename + with open(file_directory, 'r') as f: reader = csv.DictReader(f) data = list(reader) return data @@ -10,8 +11,8 @@ def read_file(filename="data/questions.csv"): def write_file(dict_list, filename="questions.csv"): keys = dict_list[0].keys() - filedirectory = 'data/' + filename - with open(filedirectory, 'w') as f: + file_directory = 'data/' + filename + with open(file_directory, 'w') as f: writer = csv.DictWriter(f, keys) writer.writeheader() writer.writerows(dict_list) diff --git a/data/questions.csv b/data/questions.csv index e65825dc3..6fe2e2beb 100644 --- a/data/questions.csv +++ b/data/questions.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,7 @@ 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)", diff --git a/data_manager.py b/data_manager.py index af1d3f54b..8a16bd3f2 100644 --- a/data_manager.py +++ b/data_manager.py @@ -6,3 +6,12 @@ def get_all_questions(): return q_list +def save_new_question(record): + connection.write_file(record, 'questions.csv') + + +def get_question_by_id(id): + q_list = connection.read_file('questions.csv') + for element in q_list: + if element['id'] == id: + return element diff --git a/server.py b/server.py index 7264c0a41..c1d9c494b 100644 --- a/server.py +++ b/server.py @@ -20,10 +20,31 @@ def route_add(): return render_template('form.html') +@app.route('/add', methods=['GET', 'POST']) +def route_edit(): + if request.method == 'POST': + current_file = data_manager.get_all_questions() + new_dict = {} + new_dict['id'] = str(int(current_file[0]['id']) + 1) + new_dict['title'] = request.form['title'] + new_dict['message'] = request.form['description'] + new_dict['submission_time'] = 'now' + new_dict['view_number'] = '1' + new_dict['vote_number'] = '1' + new_dict['image'] = '' + current_file.append(new_dict) + data_manager.save_new_question(current_file) + return redirect('/') + return render_template('form.html') + + @app.route('/add-question/') -def route_edit(id): - cokolwiek = 'hello world' + id - return cokolwiek +def route_display_question(id): + try: + element = data_manager.get_question_by_id(id) + return render_template('qd.html', element=element) + except ValueError: + return redirect('/') if __name__ == "__main__": diff --git a/templates/answer.html b/templates/answer.html new file mode 100644 index 000000000..e69de29bb diff --git a/templates/form.html b/templates/form.html index c21b29f0c..c06ffc6a8 100644 --- a/templates/form.html +++ b/templates/form.html @@ -9,11 +9,11 @@

Add new Question


- +
- +
diff --git a/templates/index.html b/templates/index.html index 03c5cc583..c69a41856 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,4 +1,12 @@ {% extends "layout.html" %} {% block contents %} - +
+

Welcome to your Ask M8!

+

In order to start, choose option from menu

+
+
+ +
{% endblock %} \ No newline at end of file diff --git a/templates/layout.html b/templates/layout.html index 18cd4a8ba..bbc949b93 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -16,7 +16,7 @@ - + + + + + + + + + + + +
+ +
+ + +
+ + +

Why is it so great?

+ +

Lorem ipsum dolor sit amet, consectetur + adipisicing elit. Fugit, error amet numquam iure provident voluptate esse quasi, veritatis totam voluptas + nostrum quisquam eum porro a pariatur accusamus veniam.

+ + +
+ + +
+ + +
+
+ +
+
+
International
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reprehenderit maiores + nam, aperiam minima assumenda.

+
+
+ + + +
+
+ +
+
+
Experimental
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reprehenderit maiores + nam, aperiam minima assumenda.

+
+
+ + + +
+
+ +
+
+
Relaxing
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reprehenderit maiores + nam, aperiam minima assumenda.

+
+
+ + +
+ + + +
+ +
+ + + +
+ + +
+
+ +
+
+
Beloved
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reprehenderit maiores + nam, aperiam minima assumenda.

+
+
+ + + +
+
+ +
+
+
Rapid
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reprehenderit maiores + nam, aperiam minima assumenda.

+
+
+ + + +
+
+ +
+
+
Magical
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reprehenderit maiores + nam, aperiam minima assumenda.

+
+
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +

Testimonials

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing + elit. Fugit, error amet numquam iure provident voluptate esse quasi, veritatis totam voluptas nostrum + quisquam eum porro a pariatur accusamus veniam.

+ + +
+ + +
+ +
+ +
+ +
+ + +

Anna Deynah

+
Web Designer
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quod eos + id officiis hic tenetur quae quaerat ad velit ab hic tenetur.

+ + +
+ + + + + +
+
+
+ + + +
+
+ +
+ +
+ + +

John Doe

+
Web Developer
+

Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis + suscipit laboriosam, nisi ut aliquid ex ea commodi.

+ + +
+ + + + + +
+
+
+ + + +
+
+ +
+ +
+ +

Maria Kate

+
Photographer
+

At vero eos et accusamus et iusto odio dignissimos ducimus qui + blanditiis praesentium voluptatum deleniti atque corrupti.

+ + +
+ + + + + +
+ +
+
+ + +
+ + +
+ + +
+ + +
+ + +

Our pricing plans

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing + elit. Fugit, error amet numquam iure provident voluptate esse quasi, veritatis totam voluptas nostrum + quisquam eum porro a pariatur veniam.

+ + +
+ + +
+ + +
+ + +
+ + +
Basic plan
+
+
+ +
+
+ + +

59$

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Culpa pariatur id nobis + accusamus deleniti cumque hic laborum.

+ Buy now + +
+ + +
+ + +
+ + + +
+ + +
+ + +
+ + +
Premium plan
+
+
+ +
+
+ + +

79$

+

Esse corporis saepe laudantium velit adipisci cumque iste ratione facere non distinctio cupiditate + sequi atque.

+ Buy now + +
+ + +
+ + +
+ + + +
+ + +
+ + +
+ + +
Advanced plan
+
+
+ +
+
+ + +

99$

+

At ab ea a molestiae corrupti numquam quo beatae minima ratione magni accusantium + repellat eveniet quia vitae.

+ Buy now + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +

Contact us

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing + elit. Fugit, error amet numquam iure provident voluptate esse quasi, veritatis totam voluptas nostrum + quisquam eum porro a pariatur accusamus veniam. Quia, minima?

+ +
+ + +
+
+ + +
+ + +
+
+ + +
+
+ + + +
+
+ + +
+
+ + +
+ + + +
+
+
+ + +
+
+
+ + + +
+ + +
+ +
+ + +
+ +
+
+ + +
+ +
+ Send +
+
+ + + +
+
    +
  • +

    San Francisco, CA 94126, USA

    +
  • + +
  • +

    + 01 234 567 89

    +
  • + +
  • +

    contact@mdbootstrap.com

    +
  • +
+
+ + +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/static/templates/login-page.html b/static/templates/login-page.html new file mode 100755 index 000000000..45df2002c --- /dev/null +++ b/static/templates/login-page.html @@ -0,0 +1,209 @@ + + + + + + + + + Material Design Bootstrap Template + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+
+ + +
+
+ + +
+

Log in:

+
+ + +
+ + + +
+
+ + + +
+ +
+ + + +
+ +
+ +
+
+ + + +
+
+ +
+
+ + +
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + diff --git a/static/templates/pricing.html b/static/templates/pricing.html new file mode 100755 index 000000000..d64edea52 --- /dev/null +++ b/static/templates/pricing.html @@ -0,0 +1,448 @@ + + + + + + + + + Material Design Bootstrap Template + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+
+
+
+

Make purchases with our + app

+
+
Lorem ipsum dolor sit amet, consectetur adipisicing + elit. Rem repellendus quasi fuga nesciunt dolorum nulla magnam veniam sapiente, fugiat! Commodi sequi + non animi ea dolor molestiae iste.
+
+ Learn more + Download + + + + +
+
+ +
+ +
+
+
+ +
+ +
+ + + + +
+ +
+ + +
+ + +

Why is it so great?

+ +

Lorem ipsum dolor sit amet, consectetur + adipisicing elit. Fugit, error amet numquam iure provident voluptate esse quasi, veritatis totam voluptas + nostrum quisquam eum.

+ + +
+ + +
+
+ +
+
+

Marketing

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reprehenderit maiores nam, + aperiam minima assumenda.

+ Learn more +
+
+ + + +
+
+ +
+
+

Customization

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reprehenderit maiores nam, + aperiam minima assumenda.

+ Learn more +
+
+ + + +
+
+ +
+
+

Support

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reprehenderit maiores nam, + aperiam minima assumenda.

+ Learn more +
+
+ + +
+ + +
+ + +
+ + + +
+ + +

Our pricing plans

+ +

Lorem ipsum dolor sit amet, consectetur adipisicing + elit. Fugit, error amet numquam iure provident voluptate esse quasi, veritatis totam voluptas nostrum + quisquam eum porro a pariatur veniam.

+ + +
+ + +
+ + +
+ + +
+

BASIC

+
+ + +
+ +

20$

+
    +
  • +

    1 project

    +
  • +
  • +

    100 components

    +
  • +
  • +

    150 features

    +
  • +
  • +

    200 members

    +
  • +
+ + +
+ + +
+ + + +
+ + + +
+ + +
+ + +
+

PRO

+
+ + +
+ +

80$

+
    +
  • +

    1 project

    +
  • +
  • +

    100 components

    +
  • +
  • +

    150 features

    +
  • +
  • +

    200 members

    +
  • +
+ + +
+ + +
+ + +
+ + + +
+ + +
+ + +
+

ENTERPRISE

+
+ + +
+ +

100$

+
    +
  • +

    1 project

    +
  • +
  • +

    100 components

    +
  • +
  • +

    150 features

    +
  • +
  • +

    200 members

    +
  • +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + + +
+ + +
+ + + +
+ + +
+ + +
+ + +
+
MDBootstrap
+
+ + +
+ +
+
    +
  • +

    about

    +
  • +
  • +

    contact

    +
  • +
  • +

    blog

    +
  • +
  • +

    team

    +
  • +
+
+ +
+ + +
+
    +
  • +
  • +
  • +
  • +
+
+ + +
+ + +
+ + + + + + +
+ + + + + + + + + + + + + + + diff --git a/static/templates/profile-page.html b/static/templates/profile-page.html new file mode 100755 index 000000000..e2fd18a70 --- /dev/null +++ b/static/templates/profile-page.html @@ -0,0 +1,592 @@ + + + + + + + + + Material Design Bootstrap Template + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+
+
+
+

ABOUT + ME +

+
Lorem + ipsum dolor sit amet
+
+
+
+
+
+
+ +
+ + + +
+ +
+ + +
+ + +
+ + +
+ +
+ First sample avatar image +
+

+ Anna Deynah +

+
Web Designer
+ + + + + + + + + + + + + + +

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt + ut labore et dolore + magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea + commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. + Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim.

+ +
+ + +
+ + +
+ + + +
+ + + + +
+ + +
+
+ + +
+ + +
+ + +
+ + +
+ + +
+
+ + +
+
+

+ Project title +

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellat fugiat, laboriosam, + voluptatem, + optio vero odio nam sit officia accusamus minus error nisi architecto nulla ipsum + dignissimos. + Odit sed qui, dolorum!.

+ + View project +
+
+
+
+ + + +
+
+ + +
+
+

+ Project title +

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellat fugiat, laboriosam, + voluptatem, + optio vero odio nam sit officia accusamus minus error nisi architecto nulla ipsum + dignissimos. + Odit sed qui, dolorum!.

+ + View project +
+
+
+
+ + +
+ + + +
+ + +
+
+ + +
+
+

+ Project title +

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellat fugiat, laboriosam, + voluptatem, + optio vero odio nam sit officia accusamus minus error nisi architecto nulla ipsum + dignissimos. + Odit sed qui, dolorum!.

+ + View project +
+
+
+
+ + + +
+
+ + +
+
+

+ Project title +

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellat fugiat, laboriosam, + voluptatem, + optio vero odio nam sit officia accusamus minus error nisi architecto nulla ipsum + dignissimos. + Odit sed qui, dolorum!.

+ + View project +
+
+
+
+ + +
+ + +
+ + +
+ + +
+ + +
+ + + +
+
+ + +
+ + +

Our amazing team

+ +

Lorem ipsum dolor sit amet, consectetur + adipisicing elit. Fugit, error amet numquam iure provident voluptate esse quasi, veritatis totam + voluptas nostrum quisquam eum porro a pariatur accusamus veniam.

+ + +
+ + +
+ +
+
+ First sample avatar image +
+
+ +
+

John Doe

+
Web Designer
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quod eos id officiis + hic tenetur.

+ + + + + + + +
+ +
+ + + +
+ +
+
+ Second sample avatar image +
+
+ +
+

Maria Kate

+
Photographer
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quod eos id officiis + hic tenetur.

+ + + + + + + +
+ +
+ + +
+ + + +
+ + +
+ +
+
+ Fourth sample avatar image +
+
+ +
+

Anna Deynah

+
Web Developer
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quod eos id officiis + hic tenetur.

+ + + + + + + +
+ +
+ + + +
+
+
+ Fifth sample avatar image +
+
+ +
+

Sarah Melyah

+
Front-end Developer
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quod eos id officiis + hic tenetur.

+ + + + + + + +
+ +
+ + +
+ + +
+ +
+ + + +
+
+ +
+
+ +
+ +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ +
+
+ +
+ + + +
+
+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nihil odit magnam minima, soluta doloribus + reiciendis + molestiae placeat unde eos molestias. Quisquam aperiam, pariatur. Tempora, placeat ratione porro + voluptate + odit minima.

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nihil odit magnam minima, soluta doloribus + reiciendis + molestiae placeat unde eos molestias. Quisquam aperiam, pariatur. Tempora, placeat ratione porro + voluptate + odit minima.

+ +
+ + +
+ +
+ + +
+ +
+ + + +
+ + +
+ + +
+
+ +
If you want to cooperate with me just send me a message at + office@mdbootstrap.com
+
+
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + diff --git a/static/templates/signup-page.html b/static/templates/signup-page.html new file mode 100755 index 000000000..1f04ac918 --- /dev/null +++ b/static/templates/signup-page.html @@ -0,0 +1,308 @@ + + + + + + + + + Material Design Bootstrap Template + + + + + + + + + + + + + + + +
+ + + + + + +
+
+
+ + +
+ + +
+ +
+
+ +

+ REGISTER +

+
+ + +
+ + +
+ + +
+
+ +
+
+

+ Safety +

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reprehenderit maiores + nam, aperiam + minima assumenda deleniti hic.

+
+
+ + + +
+
+ +
+
+

+ Technology +

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reprehenderit maiores + nam, aperiam + minima assumenda deleniti hic.

+
+
+ + + +
+
+ +
+
+

+ Finance +

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reprehenderit maiores + nam, aperiam + minima assumenda deleniti hic.

+
+
+ + +
+ + + +
+ + +
+ +

+ Login with +

+ + + +

+ or: +

+ +
+ + + +
+ + + +
+
+ + + +
+ +
+ + + +
+ +
+ +
+ +
+ + +
+ + +
+
+ +
+ + +
+ + +
+
+
+ + +
+ + + + + + + + + + + + + + + From 7f307acbd115bbee686d964d24591b672e298cec Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Wed, 10 Apr 2019 18:29:18 +0200 Subject: [PATCH 071/111] Fixed deleting pictures on deleting answer/question --- data_manager/dm_general.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/data_manager/dm_general.py b/data_manager/dm_general.py index 7d9efe8d0..038f17406 100644 --- a/data_manager/dm_general.py +++ b/data_manager/dm_general.py @@ -1,5 +1,7 @@ from connection import connection_handler import os +from psycopg2 import sql +from flask import url_for @connection_handler @@ -11,18 +13,13 @@ def update_image_path(cursor, table, filename, id): @connection_handler -def remove_image(cursor, table, id): - file_path = cursor.execute( - # todo > check why file_path is returning None even though question has image path - # todo > check why query does not work without f strings - # "select image from %(table)s where id=%(id)s", {"table": table, "id": id} - # sql.SQL("select image from {table} WHERE id={id}").format(table=sql.Identifier(table), id=sql.Identifier(id)) - f"SELECT image FROM {table} WHERE id={id}" +def remove_image(cursor, table_name, resource_id): + cursor.execute( + sql.SQL('select image from {} WHERE id=%s').format(sql.Identifier(table_name)), [resource_id] ) + file_path = cursor.fetchone() if file_path: - # todo > check if it will work with url_for() - # os.remove(f"static/{file_path}")f"static/{file_path}" - os.remove(f"../static/{file_path}") + os.remove(f"./static/{file_path['image']}") @connection_handler From 9c7f5f3fbf3b9698ca5497e9cfa76847c20736e8 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Wed, 10 Apr 2019 18:30:38 +0200 Subject: [PATCH 072/111] refactor dm_answer --- data_manager/dm_answers.py | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/data_manager/dm_answers.py b/data_manager/dm_answers.py index 7d6712b78..8fb5538e4 100644 --- a/data_manager/dm_answers.py +++ b/data_manager/dm_answers.py @@ -19,12 +19,8 @@ def qet_answer_by_id(cursor, answer_id): SELECT * FROM answer WHERE id=%(answer_id)s """, {"answer_id": answer_id}) - answer_in_list = cursor.fetchall() - if answer_in_list: - return answer_in_list[0] - else: - return None - + answer = cursor.fetchone() + return answer @connection_handler @@ -37,18 +33,19 @@ def add_sql_answer(cursor, form_data, question_id): @connection_handler -def delete_answer(cursor, id): +def delete_answer(cursor, answer_id): # delete answer image if exists - dm_general.remove_image('answer', id) + dm_general.remove_image('answer', answer_id) # delete answer and all related comments cursor.execute( - f""" - DELETE FROM comment WHERE answer_id={id}; - DELETE FROM answer WHERE id={id}; """ + DELETE FROM comment WHERE answer_id=%(answer_id)s; + DELETE FROM answer WHERE id=%(answer_id)s; + """, {'answer_id': answer_id} ) + @connection_handler def update_answer(cursor, answer_id, form_data): cursor.execute( @@ -60,13 +57,13 @@ def update_answer(cursor, answer_id, form_data): @connection_handler def change_answer_vote(cursor, answer_id, value_to_change_vote): - cursor.execute(f""" + cursor.execute(""" UPDATE answer - SET vote_number = vote_number + {value_to_change_vote} - WHERE id = {answer_id} - """) - cursor.execute(f""" - SELECT vote_number FROM answer WHERE id={answer_id} - """) + SET vote_number = vote_number + %(value_to_change_vote)s + WHERE id = %(answer_id)s + """, {'value_to_change_vote': value_to_change_vote, 'answer_id': answer_id}) + cursor.execute(""" + SELECT vote_number FROM answer WHERE id=%(answer_id)s + """, {'answer_id': answer_id}) new_vote_number = cursor.fetchone() - return new_vote_number \ No newline at end of file + return new_vote_number From 17cd6c1b31725e833279859361da340c6df7ff09 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Wed, 10 Apr 2019 18:32:32 +0200 Subject: [PATCH 073/111] Delete dm_archive --- data_manager/dm_archive.py | 141 ------------------------------------- 1 file changed, 141 deletions(-) delete mode 100644 data_manager/dm_archive.py diff --git a/data_manager/dm_archive.py b/data_manager/dm_archive.py deleted file mode 100644 index f1340e0d8..000000000 --- a/data_manager/dm_archive.py +++ /dev/null @@ -1,141 +0,0 @@ -import connection -import uuid -import time -import util - - -def add_question(form_data): - questions = connection.read_file() - new_question = { - 'id': uuid.uuid4(), - 'title': form_data['title'], - 'message': form_data['description'], - 'submission_time': time.time(), - 'view_number': 0, - 'vote_number': 0, - 'image': None - } - questions.append(new_question) - connection.write_file(questions, 'questions.csv') - - -def get_all_questions(): - questions = connection.read_file() - sorted_questions = sorted(questions, key=lambda k: k['submission_time'], reverse=True) - questions_with_proper_date_format = map(util.convert_time_value_to_formatted_string, sorted_questions) - return questions_with_proper_date_format - - -def get_question_by_id(id): - questions = connection.read_file() - for question in questions: - if question['id'] == id: - formatted_question = util.convert_time_value_to_formatted_string(question) - return formatted_question - - -def update_question(id, form_data): - questions = connection.read_file() - for question in questions: - if question['id'] == id: - question['title'] = form_data['title'] - question['message'] = form_data['description'] - connection.write_file(questions) - - -def sort_questions(order_by, order_direction): - questions = connection.read_file() - sort_type = True if order_direction == 'asc' else False - sorted_questions = sorted(questions, key=lambda k: k[order_by], reverse=sort_type) - questions_with_proper_date_format = map(util.convert_time_value_to_formatted_string, sorted_questions) - return questions_with_proper_date_format - - -def question_view_count_increase(id): - questions = connection.read_file() - for question in questions: - if question['id'] == id: - question['view_number'] = str(int(question['view_number']) + 1) - connection.write_file(questions) - - -def get_all_answers(): - a_list = connection.read_file('answers.csv') - return a_list - - -def get_answers_by_question_id(id): - answers = connection.read_file('answers.csv') - answers_to_question = [] - for answer in answers: - if answer['question_id'] == id: - answer_with_proper_date_format = util.convert_time_value_to_formatted_string(answer) - answers_to_question.append(answer_with_proper_date_format) - return answers_to_question - - - - -def add_answer(form_data, id): - answers = connection.read_file('answers.csv') - new_answer = { - 'id': uuid.uuid4(), - 'submission_time': time.time(), - 'vote_number': 0, - 'question_id': id, - 'message': form_data['answer'], - 'image': None - } - answers.append(new_answer) - connection.write_file(answers, 'answers.csv') - - -@connection_handler -def delete_element_sql(element_type, element_id): - pass - - -# todo > delete element in SQL -def delete_element(element_type, element_id): - # delete file if exists - data = connection.read_file(f'{element_type}.csv') - try: - deleted_element_img_path = [element['image'] for element in data if element['id'] == element_id][0] - file_name = deleted_element_img_path.split("/")[1] - if file_name: - os.remove(f"static/images/{file_name}") - except IndexError: - pass - - # delete element - updated_data = [data_element for data_element in data if data_element['id'] != element_id] - connection.write_file(updated_data, f'{element_type}.csv') - - # if question is deleted - also delete corresponding answers - if element_type == "questions": - answers = connection.read_file('answers.csv') - - # delete answer's image - img_paths_of_deleted_answers = [answer['image'] for answer in answers if answer['question_id'] == element_id] - for img_path in img_paths_of_deleted_answers: - try: - file_name = img_path.split("/")[1] - if file_name: - os.remove(f"static/images/{file_name}") - except IndexError: - pass - - # delete answer - updated_answers = [answer for answer in answers if answer['question_id'] != element_id] - connection.write_file(updated_answers, 'answers.csv') - - -# todo > saving images and updating -def update_image(file_type, filename, id): - data = connection.read_file(f"{file_type}.csv") - for element in data: - if element['id'] == id: - element['image'] = 'images/' + filename - connection.write_file(data, f"{file_type}.csv") - - From 5e1e052a1de2331edb6f021178c6718ab35d8386 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Wed, 10 Apr 2019 22:09:29 +0200 Subject: [PATCH 074/111] Refactor comments functionality --- data_manager/dm_comments.py | 69 ++++++++++++---------- server_python/sv_comments.py | 46 ++++++++------- server_python/sv_questions.py | 21 +++---- templates/comment.html | 12 +++- templates/qd.html | 108 ++++++++++++++++++---------------- 5 files changed, 137 insertions(+), 119 deletions(-) diff --git a/data_manager/dm_comments.py b/data_manager/dm_comments.py index 8d87448fb..ce6928202 100644 --- a/data_manager/dm_comments.py +++ b/data_manager/dm_comments.py @@ -5,70 +5,77 @@ @connection_handler def add_comment_to_question(cursor, form_data, question_id): time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") - cursor.execute(f""" + cursor.execute(""" INSERT INTO comment (edited_count, message, question_id, submission_time) - VALUES (0, '{form_data['message']}', '{question_id}', '{time}') -""") + VALUES (0, %(message)s, %(question_id)s, %(time)s) + """, + {'message': form_data['message'], 'question_id': question_id, 'time': time}) @connection_handler def add_comment_to_answer(cursor, form_data, answer_id, question_id): time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") - cursor.execute(f""" + cursor.execute(""" INSERT INTO comment (edited_count, message, answer_id, submission_time, question_id) - VALUES (0, '{form_data['message']}', '{answer_id}', '{time}', '{question_id}') -""") + VALUES (0, %(message)s, %(answer_id)s, %(time)s, %(question_id)s) + """, + {'message': form_data['message'], 'answer_id': answer_id, 'time': time, 'question_id': question_id}) @connection_handler -def show_question_comments_by_id(cursor, id): - cursor.execute(f""" +def show_question_comments_by_id(cursor, question_id): + cursor.execute(""" SELECT * FROM comment - WHERE question_id = '{id}'; -""") + WHERE question_id = %(question_id)s AND answer_id IS NULL + """, + {'question_id': question_id}) comments = cursor.fetchall() return comments @connection_handler -def show_answer_comments_by_id(cursor, id): - cursor.execute(f""" +def show_answer_comments_by_id(cursor, question_id): + cursor.execute(""" SELECT * FROM comment - WHERE question_id = '{id}'; -""") + WHERE question_id = %(question_id)s; + """, + {'question_id': question_id}) comments = cursor.fetchall() return comments @connection_handler -def get_comment_by_id(cursor, id): - cursor.execute(f""" +def get_comment_by_id(cursor, comment_id): + cursor.execute(""" SELECT * FROM comment - WHERE id = '{id}'; -""") - comment = cursor.fetchall() + WHERE id = %(comment_id)s; + """, + {'comment_id': comment_id}) + comment = cursor.fetchone() return comment @connection_handler -def update_comment_by_id(cursor, form_data, id): +def update_comment_by_id(cursor, form_data, comment_id): time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") - cursor.execute(f""" + cursor.execute(""" UPDATE comment - SET message = '{form_data['message']}', edited_count = edited_count + 1, submission_time = '{time}' - WHERE id = '{id}'; - SELECT question_id, answer_id FROM comment - WHERE id = '{id}' -""") - question_id = cursor.fetchall() + SET message = %(message)s, edited_count = edited_count + 1, submission_time = %(time)s + WHERE id = %(comment_id)s; + SELECT question_id FROM comment + WHERE id = %(comment_id)s; + """, + {'message': form_data['message'], 'time': time, 'comment_id': comment_id}) + question_id = cursor.fetchone() return question_id @connection_handler -def delete_comment_by_id(cursor, id): - cursor.execute(f""" +def delete_comment_by_id(cursor, comment_id): + cursor.execute(""" DELETE FROM comment - WHERE id = '{id}'; -""") + WHERE id = %(comment_id)s; + """, + {'comment_id': comment_id}) diff --git a/server_python/sv_comments.py b/server_python/sv_comments.py index 59dcaf74c..4df0349c6 100644 --- a/server_python/sv_comments.py +++ b/server_python/sv_comments.py @@ -1,15 +1,17 @@ from server_python.config import app -from data_manager import dm_answers, dm_comments +from data_manager import dm_comments from flask import request, redirect, render_template -@app.route('/question//new-comment', methods=['GET', 'POST']) -def route_add_comment(id): - action = '/question/' + id + '/new-comment' +@app.route('/question/new-comment', methods=['GET', 'POST']) +def route_add_comment_to_question(): + question_id = request.args.get('question_id') if request.method == 'POST': - dm_comments.add_comment_to_question(request.form, id) - return redirect(f'/question_detail/{id}') - return render_template('comment.html', id=id, action=action) + dm_comments.add_comment_to_question(request.form, question_id) + return redirect(f'/question_detail/{question_id}') + return render_template('comment.html', + question_id=question_id, + is_add_comment_to_question=True) @app.route('/answer/new-comment', methods=['GET', 'POST']) @@ -19,21 +21,25 @@ def route_add_comment_to_answer(): if request.method == 'POST': dm_comments.add_comment_to_answer(request.form, answer_id, question_id) return redirect(f"/question_detail/{question_id}") - return render_template('comment.html', question_id=question_id, answer_id=answer_id) + return render_template('comment.html', + question_id=question_id, + answer_id=answer_id, + is_add_comment_to_answer=True) -@app.route('/comments//edit', methods=['GET', 'POST']) -def route_edit_comment(id): - action = '/comments/' + id + '/edit' - comment = dm_comments.get_comment_by_id(id)[0] +@app.route('/comment/edit', methods=['GET', 'POST']) +def route_edit_comment(): + comment_id = request.args.get('comment_id') + comment = dm_comments.get_comment_by_id(comment_id) if request.method == 'POST': - result = dm_comments.update_comment_by_id(request.form, id)[0] - return redirect(f"/question_detail/{result['question_id']}") - return render_template('comment.html', comment=comment, action=action) + question_id = dm_comments.update_comment_by_id(request.form, comment_id) + return redirect(f"/question_detail/{question_id['question_id']}") + return render_template('comment.html', comment=comment) -@app.route('/comments//delete', methods=['GET']) -def route_delete_comment(id): - directory = dm_comments.get_comment_by_id(id)[0] - dm_comments.delete_comment_by_id(id) - return redirect(f"/question_detail/{directory['question_id']}") +@app.route('/comment/delete', methods=['GET']) +def route_delete_comment(): + comment_id = request.args.get('comment_id') + question_id = request.args.get('question_id') + dm_comments.delete_comment_by_id(comment_id) + return redirect(f"/question_detail/{question_id}") diff --git a/server_python/sv_questions.py b/server_python/sv_questions.py index 08bb44d73..f86f66bcb 100644 --- a/server_python/sv_questions.py +++ b/server_python/sv_questions.py @@ -48,10 +48,15 @@ def route_question_detail(id): dm_questions.update_question_view_increase_count(id) question = dm_questions.get_question_sql_by_id(id) answers = dm_answers.get_all_sql_answers_by_question_id(id) - comments = dm_comments.show_question_comments_by_id(id) + question_comments = dm_comments.show_question_comments_by_id(id) answer_comments = dm_comments.show_answer_comments_by_id(id) tags = dm_tags.get_tags_of_question_by_id(id) - return render_template('qd.html', question=question, id=id, answers=answers, count=len(answers), comments=comments, answer_comments=answer_comments, tags=tags) + return render_template('qd.html', question=question, + id=id, answers=answers, + count=len(answers), + question_comments=question_comments, + answer_comments=answer_comments, + tags=tags) except ValueError: return redirect('/') @@ -66,18 +71,6 @@ def route_question_edit(): return render_template('form.html', question=question) -# @app.route('/question//vote-down') -# def question_vote_down(question_id): -# dm_general.change_vote("question", question_id, -1) -# return redirect('/question_detail/' + question_id) -# -# -# @app.route('/question//vote-up') -# def question_vote_up(question_id): -# dm_general.change_vote("question", question_id, 1) -# return redirect('/question_detail/' + question_id) - - @app.route('/question//vote', methods=['PUT']) def question_change_vote(question_id): value_to_change_vote = request.get_json()['voteValue'] diff --git a/templates/comment.html b/templates/comment.html index eecfd55d2..9dbc505f8 100644 --- a/templates/comment.html +++ b/templates/comment.html @@ -5,10 +5,18 @@
-
+ {% if is_add_comment_to_question %} + + {% elif is_add_comment_to_answer %} + + {% else %} + + {% endif %}
-

{% if comment %}Edit comment {% else %}Add new comment{% endif %}

+

+ {% if comment %}Edit comment {% else %}Add new comment{% endif %} +

diff --git a/templates/qd.html b/templates/qd.html index 4f5a981bf..31af0b7d7 100644 --- a/templates/qd.html +++ b/templates/qd.html @@ -2,7 +2,7 @@ {% block contents %}
-

Question detail

+

Question detail

@@ -40,31 +40,6 @@

{{ question['title'] }}

Viewed: {{ question['view_number'] }} times -
-
-
Comments
- {% for comment in comments %} - {% if comment['answer_id'] == None %} -
-
-

-
-
-

{{ comment['message'] }}
comment by [] on {{ comment['submission_time']}} - {% if comment['edited_count'] != None %} - {% if comment['edited_count'] > 0 %} - edited {{ comment['edited_count'] }} times. - {% endif %} - {% endif %} edit delete -

-
-
-
- {% endif %} - {% endfor %} - Add comment -
-
@@ -75,6 +50,36 @@
Comments
Votes: {{ question['vote_number'] }}
+
+
+
+

Comments:

+
+
    + {% for comment in question_comments %} +
  • +

    {{ comment['message'] }}

    +
    + + Posted on: {{ comment['submission_time'] }} + + {% if comment['edited_count'] > 0 %} + + Edited {{ comment['edited_count'] }} times + + {% endif %} +
    + + +
    +
    +
  • + {% endfor %} +
+
+
+ Add comment +
@@ -120,40 +125,39 @@
Answer # {{ loop.index }}
-
-
-
-
-
-
-
-
-
-
- {% for comment in answer_comments %} +
+
+
+

Comments:

+
+
    + {% for comment in answer_comments %} {% if comment['answer_id'] == answer['id'] %} -
    -
    -

    {{ comment['message'] }}
    comment by [] on {{ comment['submission_time']}} - {% if comment['edited_count'] != None %} +

  • +

    {{ comment['message'] }}

    +
    + + Posted on: {{ comment['submission_time'] }} + {% if comment['edited_count'] > 0 %} - edited {{ comment['edited_count'] }} times. + + Edited {{ comment['edited_count'] }} times + {% endif %} - {% endif %}edit delete -

    -
    -
    -
  • +
    + + +
    +
    + {% endif %} - {% endfor %} - Add comment -
-
+ {% endfor %} +
+ Add comment
- {% endfor %}
From c08708a979ebbd040cb4541d22532a2184d70f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Szadkowski?= Date: Wed, 10 Apr 2019 22:53:55 +0200 Subject: [PATCH 075/111] new bootstrap md head updated --- templates/layout.html | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/templates/layout.html b/templates/layout.html index 68eb9c03d..936635066 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -4,9 +4,22 @@ Title + + + + + + + + + + + +
-
+
{% block contents %} {% endblock contents %}
diff --git a/templates/list.html b/templates/list.html index 4e5833e97..7971a4003 100644 --- a/templates/list.html +++ b/templates/list.html @@ -1,12 +1,7 @@ {% extends "layout.html" %} {% block contents %} - -
-
-
-
+ +
@@ -45,9 +40,9 @@ {% if question['image'] %} - + {% else %} - + {% endif %} From 6762b74577856b94b8833db65d9e8bc08c1f96d7 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Thu, 11 Apr 2019 19:23:02 +0200 Subject: [PATCH 081/111] Add truncating functionality for question display --- server_python/sv_questions.py | 6 +++--- templates/form.html | 6 +++--- templates/index.html | 2 +- templates/list.html | 2 +- util.py | 8 ++++++++ 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/server_python/sv_questions.py b/server_python/sv_questions.py index 4db0a6d04..04590795d 100644 --- a/server_python/sv_questions.py +++ b/server_python/sv_questions.py @@ -1,19 +1,19 @@ from server_python.config import app from data_manager import dm_questions, dm_answers, dm_comments, dm_tags from flask import request, redirect, render_template, jsonify -from util import check_referer_url +from util import check_referer_url, truncate_question @app.route('/') def route_home(): questions = dm_questions.get_5_questions_sql_sorted_by_submission_time() - return render_template('index.html', questions=questions) + return render_template('index.html', questions=questions, truncate_fn=truncate_question) @app.route('/list') def route_list(): questions = dm_questions.get_all_questions_sql_sorted_by_submission_time() - return render_template('list.html', questions=questions) + return render_template('list.html', questions=questions, truncate_fn=truncate_question) @app.route('/sort') diff --git a/templates/form.html b/templates/form.html index 70cf241dd..c27984b6a 100644 --- a/templates/form.html +++ b/templates/form.html @@ -2,7 +2,7 @@ {% block contents %}
-
+
{% if question %} @@ -31,7 +31,7 @@

Add a new Question

value="{{ question['title'] }}" {% endif %} placeholder="Enter Title" - maxlength="50"> + maxlength="80">
@@ -40,7 +40,7 @@

Add a new Question

class="form-control" id="message" placeholder="Enter the description" rows="8" - maxlength="500">{% if question %}{{ question['message'] }}{% endif %} + maxlength="2000">{% if question %}{{ question['message'] }}{% endif %}
diff --git a/templates/index.html b/templates/index.html index 137127446..8a835a99a 100644 --- a/templates/index.html +++ b/templates/index.html @@ -32,7 +32,7 @@

Welcome to Ask M8!

- + diff --git a/templates/list.html b/templates/list.html index 7971a4003..2e5f414c1 100644 --- a/templates/list.html +++ b/templates/list.html @@ -35,7 +35,7 @@ - + diff --git a/util.py b/util.py index d3bea3d6c..94cfb55ab 100644 --- a/util.py +++ b/util.py @@ -18,3 +18,11 @@ def replace_string(matchobj): def highlight_search_term(searched_term, sequence): new_sequence = re.sub(searched_term, replace_string, sequence, flags=re.I) return new_sequence + + +def truncate_question(question_message, list_type): + max_length = 250 if list_type == 'home' else 500 + if len(question_message) > max_length: + return question_message[:max_length] + ' (...)' + else: + return question_message From e1fb3d4abb34d70db208085e27d92176f7a04ff9 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Thu, 11 Apr 2019 19:36:04 +0200 Subject: [PATCH 082/111] Redesign home page --- templates/index.html | 12 ++++++------ templates/layout.html | 2 +- templates/qd.html | 3 --- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/templates/index.html b/templates/index.html index 8a835a99a..961d11392 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,19 +1,19 @@ {% extends "layout.html" %} {% block contents %} -
- +
-

Welcome to Ask M8!

-

Ask questions and get your answers! On whatever topic!

+

Welcome to AskMate!

+

Ask questions - get answers! On whatever topic!

-
-
+
+

Latest questions:

+
{{ question['view_number'] }} {{ question['vote_number'] }} Example imageExample imageExample imageExample image
{{ loop.index }} {{ question['title'] }} {{ question['message'] }} {{ truncate_fn(question['message'], 'home') }} {{ question['submission_time'] }} {{ question['view_number'] }} {{ question['vote_number'] }}
{{ loop.index }} {{ question['title'] }} {{ question['message'] }} {{ truncate_fn(question['message'], 'list') }} {{ question['submission_time'] }} {{ question['view_number'] }} {{ question['vote_number'] }}
diff --git a/templates/layout.html b/templates/layout.html index 730b0505d..3ff19bae2 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -36,7 +36,7 @@ -
+
{% block contents %} {% endblock contents %}
diff --git a/templates/qd.html b/templates/qd.html index b865fbc16..5871c5874 100644 --- a/templates/qd.html +++ b/templates/qd.html @@ -32,9 +32,6 @@

{{ question['title'] }}

-{#
#} -{#

{{ question['message'] }}

#} -{#
#} Posted on: {{ question['submission_time'] }} From 342f6d241a0ff2468ed6283fbf2d6c4e49b6c693 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Thu, 11 Apr 2019 19:44:15 +0200 Subject: [PATCH 083/111] Add top margin to all templates --- templates/answer.html | 2 +- templates/comment.html | 2 +- templates/form.html | 2 +- templates/index.html | 2 +- templates/layout.html | 2 +- templates/list.html | 100 +++++++++++++++++----------------- templates/qd.html | 2 +- templates/search_results.html | 2 +- templates/tag.html | 2 +- 9 files changed, 59 insertions(+), 57 deletions(-) diff --git a/templates/answer.html b/templates/answer.html index be4341ed6..b7e0552e8 100644 --- a/templates/answer.html +++ b/templates/answer.html @@ -1,6 +1,6 @@ {% extends "layout.html" %} {% block contents %} -
+
{% if answer %}
{% else %} diff --git a/templates/comment.html b/templates/comment.html index 9dbc505f8..5f2b4c549 100644 --- a/templates/comment.html +++ b/templates/comment.html @@ -1,6 +1,6 @@ {% extends "layout.html" %} {% block contents %} -
+
diff --git a/templates/form.html b/templates/form.html index c27984b6a..878143dc9 100644 --- a/templates/form.html +++ b/templates/form.html @@ -1,6 +1,6 @@ {% extends "layout.html" %} {% block contents %} -
+
diff --git a/templates/index.html b/templates/index.html index 961d11392..e22573df5 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,6 +1,6 @@ {% extends "layout.html" %} {% block contents %} -
+
diff --git a/templates/layout.html b/templates/layout.html index 3ff19bae2..21edc1b83 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -36,7 +36,7 @@
-
+
{% block contents %} {% endblock contents %}
diff --git a/templates/list.html b/templates/list.html index 2e5f414c1..489224b36 100644 --- a/templates/list.html +++ b/templates/list.html @@ -1,53 +1,55 @@ {% extends "layout.html" %} {% block contents %} - -
-
- - - - - - - - - - - - - - {% for question in questions %} - - - - - - - - {% if question['image'] %} - - {% else %} - - {% endif %} - - - {% endfor %} - -
No.
Title
- - -
Message
- - -
Submission Time
- - -
View Number
- - -
Vote Number
- - -
Image
{{ loop.index }} {{ question['title'] }} {{ truncate_fn(question['message'], 'list') }} {{ question['submission_time'] }} {{ question['view_number'] }} {{ question['vote_number'] }} Example imageExample image
+
+ +
+ + + + + + + + + + + + + + + {% for question in questions %} + + + + + + + + {% if question['image'] %} + + {% else %} + + {% endif %} + + + {% endfor %} + +
No.
Title
+ + +
Message
+ + +
Submission Time
+ + +
View Number
+ + +
Vote Number
+ + +
Image
{{ loop.index }} {{ question['title'] }} {{ truncate_fn(question['message'], 'list') }} {{ question['submission_time'] }} {{ question['view_number'] }} {{ question['vote_number'] }} Example imageExample image
+
{% endblock %} \ No newline at end of file diff --git a/templates/qd.html b/templates/qd.html index 5871c5874..f03423a03 100644 --- a/templates/qd.html +++ b/templates/qd.html @@ -1,6 +1,6 @@ {% extends "layout.html" %} {% block contents %} -
+

{{ question['title'] }}

diff --git a/templates/search_results.html b/templates/search_results.html index f54236f0e..2a2dee3f8 100644 --- a/templates/search_results.html +++ b/templates/search_results.html @@ -1,7 +1,7 @@ {% extends "layout.html" %} {% block contents %} -
+
Search results diff --git a/templates/tag.html b/templates/tag.html index 2d7d231bf..81a37b456 100644 --- a/templates/tag.html +++ b/templates/tag.html @@ -1,6 +1,6 @@ {% extends "layout.html" %} {% block contents %} -
+
From 5e8e99e401c4ba6c1f349a53b6f4b42c6d105d45 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Thu, 11 Apr 2019 20:41:07 +0200 Subject: [PATCH 084/111] Redesign answer section --- static/style.css | 4 ++++ templates/answer.html | 7 ++++++- templates/comment.html | 2 +- templates/qd.html | 16 ++++++++-------- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/static/style.css b/static/style.css index a9e7c2fca..284a0e210 100644 --- a/static/style.css +++ b/static/style.css @@ -34,4 +34,8 @@ height: 100%; object-fit: cover; display: block; +} + +.thumb-icon { + cursor: pointer; } \ No newline at end of file diff --git a/templates/answer.html b/templates/answer.html index b7e0552e8..b83613c80 100644 --- a/templates/answer.html +++ b/templates/answer.html @@ -16,7 +16,12 @@

Add new answer

- +
diff --git a/templates/comment.html b/templates/comment.html index 5f2b4c549..41956954c 100644 --- a/templates/comment.html +++ b/templates/comment.html @@ -26,7 +26,7 @@

id="message" rows="8" cols="50" - maxlength="700" + maxlength="1000" >{% if comment %}{{ comment['message'] }}{% endif %}

diff --git a/templates/qd.html b/templates/qd.html index f03423a03..455220d13 100644 --- a/templates/qd.html +++ b/templates/qd.html @@ -52,8 +52,8 @@

{{ question['title'] }}

Add tag Delete question
- - + + Votes: {{ question['vote_number'] }}
@@ -94,14 +94,14 @@

{{ question['title'] }}

Answers - {{ count }} + {{ count }}
{% for answer in answers %}
-
+
{% if answer['image'] %} User image @@ -122,17 +122,17 @@

{{ question['title'] }}

-
+
- +
Answer # {{ loop.index }}

{{ answer['message'] }}

Posted on: {{ answer['submission_time'] }}
- - + + Votes: {{ answer['vote_number'] }}
From d3b78740b0a411d9dd76a3f55563fbca0709ff20 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Thu, 11 Apr 2019 20:44:52 +0200 Subject: [PATCH 085/111] Minor redisign of search results --- templates/search_results.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/search_results.html b/templates/search_results.html index 2a2dee3f8..c09cc226e 100644 --- a/templates/search_results.html +++ b/templates/search_results.html @@ -5,11 +5,11 @@
Search results - {{ questions_count }} + {{ questions_count }}
{% for question in searched_questions %} -
+
Q: {{ markup(highlight_search_term_fn(question['title'])) }}
From 9668bf534a6a7c500402a7e4b52f788aef1f9754 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Thu, 11 Apr 2019 21:39:32 +0200 Subject: [PATCH 086/111] Fix minor bug with deleting images --- data_manager/dm_general.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_manager/dm_general.py b/data_manager/dm_general.py index 038f17406..1ac6d1bd6 100644 --- a/data_manager/dm_general.py +++ b/data_manager/dm_general.py @@ -18,7 +18,7 @@ def remove_image(cursor, table_name, resource_id): sql.SQL('select image from {} WHERE id=%s').format(sql.Identifier(table_name)), [resource_id] ) file_path = cursor.fetchone() - if file_path: + if file_path and file_path['image'] != None: os.remove(f"./static/{file_path['image']}") From 080a5d5c07876867e2ede0785e18bf2d7b329106 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Thu, 11 Apr 2019 22:26:09 +0200 Subject: [PATCH 087/111] Minor change in answer display --- templates/qd.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/qd.html b/templates/qd.html index 455220d13..5d0305f2c 100644 --- a/templates/qd.html +++ b/templates/qd.html @@ -98,7 +98,7 @@

{{ question['title'] }}

{% for answer in answers %} -
+
From 41dd1440f5a7f6b3bdd8bef80488390cd3f2138f Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Thu, 11 Apr 2019 22:26:38 +0200 Subject: [PATCH 088/111] Minor bug fix of question display --- server_python/sv_questions.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server_python/sv_questions.py b/server_python/sv_questions.py index 04590795d..59891089e 100644 --- a/server_python/sv_questions.py +++ b/server_python/sv_questions.py @@ -24,7 +24,9 @@ def route_sort_questions(): # return 'Error: wrong parameter' order_direction = request.args.get('order_direction', default='asc', type=str) questions = dm_questions.get_questions_sorted(feature_to_order_by, order_direction) - return render_template('list.html', questions=questions) + return render_template('list.html', + questions=questions, + truncate_fn=truncate_question) @app.route('/add', methods=['GET', 'POST']) From d882c632403daec057270c4d2d3ee5414a9ebd64 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Fri, 12 Apr 2019 13:40:22 +0200 Subject: [PATCH 089/111] Fix bug with editing question --- data_manager/dm_questions.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/data_manager/dm_questions.py b/data_manager/dm_questions.py index 8be8f0854..3a97908bc 100644 --- a/data_manager/dm_questions.py +++ b/data_manager/dm_questions.py @@ -55,11 +55,12 @@ def add_question_sql(cursor, form_data): @connection_handler def update_question_sql(cursor, id, form_data): - cursor.execute(f""" + cursor.execute(""" UPDATE question - SET title = '{form_data['title']}', message = '{form_data['message']}' - WHERE id = '{id}' - """) + SET title = %(title)s, message = %(message)s + WHERE id = %(id)s + """, + {'title': form_data['title'], 'message': form_data['message'], 'id': id}) @connection_handler From fe13a5a24d0ddbb2edb426eb5e30b028ba70396d Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Tue, 23 Apr 2019 10:08:13 +0200 Subject: [PATCH 090/111] Remove unnecessary commets --- data_manager/dm_general.py | 1 - server.py | 1 - 2 files changed, 2 deletions(-) diff --git a/data_manager/dm_general.py b/data_manager/dm_general.py index 1ac6d1bd6..4e7c95735 100644 --- a/data_manager/dm_general.py +++ b/data_manager/dm_general.py @@ -1,7 +1,6 @@ from connection import connection_handler import os from psycopg2 import sql -from flask import url_for @connection_handler diff --git a/server.py b/server.py index 85e01bdf3..46b2ed01a 100644 --- a/server.py +++ b/server.py @@ -1,5 +1,4 @@ from server_python import config -# todo > check why the app doesn't work without the statements below from server_python import sv_questions from server_python import sv_general from server_python import sv_answers From a8c33c3aff056b9983a8564275e5ccaefe5d3d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Szadkowski?= Date: Tue, 23 Apr 2019 10:23:26 +0200 Subject: [PATCH 091/111] sql database users --- sample_data/askmatepart2-sample-data.sql | 11 +++++++++++ server.py | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index 369355a65..c901d537e 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -64,6 +64,17 @@ CREATE TABLE tag ( name text ); +DROP TABLE IF EXISTS public.users: +DROP SEQUENCE IF EXITST public.user_id_seq; +CREATE TABLE users ( + id serial NOT NULL, + username text NOT NULL, + email text, + full_name text, + password text NOT NULL, + reputation integer +) + ALTER TABLE ONLY answer ADD CONSTRAINT pk_answer_id PRIMARY KEY (id); diff --git a/server.py b/server.py index 85e01bdf3..3540dd032 100644 --- a/server.py +++ b/server.py @@ -10,5 +10,6 @@ if __name__ == "__main__": config.app.run( debug=True, - port=5004 + port=5004, + host='0.0.0.0' ) \ No newline at end of file From 9f1a0d374f6dfc6d9c35bb71ded4486a1ba85bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Szadkowski?= Date: Tue, 23 Apr 2019 10:45:52 +0200 Subject: [PATCH 092/111] sql user examples --- sample_data/askmatepart2-sample-data.sql | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index c901d537e..cc17d0691 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -64,8 +64,7 @@ CREATE TABLE tag ( name text ); -DROP TABLE IF EXISTS public.users: -DROP SEQUENCE IF EXITST public.user_id_seq; +DROP TABLE IF EXISTS public.users; CREATE TABLE users ( id serial NOT NULL, username text NOT NULL, @@ -73,7 +72,7 @@ CREATE TABLE users ( full_name text, password text NOT NULL, reputation integer -) +); ALTER TABLE ONLY answer @@ -136,3 +135,6 @@ 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); + +INSERT INTO users VALUES (1, 'test', 'test@test.pl', 'Testowy Tescik', '$2b$12$4wLEAbDLP6Ab0Q4M4CyZOe/xSuYcRDi5yHKe6i1nf0dZBo7HJ5h5W', 0); +INSERT INTO users VALUES (2, 'seba', 'seba@test.pl', 'Sebowski Seba', '$2b$12$yGHK2Vl/I9htIakbQSETxecYmhYAPjPXWEsC6TUcNysCzum2bZHwu', 1); From 83507b3ca837ad729f3497acc9b07a3ab037158c Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Tue, 23 Apr 2019 11:26:58 +0200 Subject: [PATCH 093/111] Modified sql sample data file --- sample_data/askmatepart2-sample-data.sql | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index cc17d0691..cba1315a4 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -15,6 +15,7 @@ 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.users DROP CONSTRAINT IF EXISTS pk_users_id CASCADE; DROP TABLE IF EXISTS public.question; DROP SEQUENCE IF EXISTS public.question_id_seq; @@ -65,13 +66,14 @@ CREATE TABLE tag ( ); DROP TABLE IF EXISTS public.users; +DROP SEQUENCE IF EXISTS public.users_id_seq; CREATE TABLE users ( id serial NOT NULL, username text NOT NULL, - email text, - full_name text, + name text NOT NULL, + email text NOT NULL, password text NOT NULL, - reputation integer + reputation integer DEFAULT 0 ); @@ -90,6 +92,9 @@ ALTER TABLE ONLY question_tag ALTER TABLE ONLY tag ADD CONSTRAINT pk_tag_id PRIMARY KEY (id); +ALTER TABLE ONLY users + ADD CONSTRAINT pk_users_id PRIMARY KEY (id); + ALTER TABLE ONLY comment ADD CONSTRAINT fk_answer_id FOREIGN KEY (answer_id) REFERENCES answer(id); @@ -136,5 +141,6 @@ INSERT INTO question_tag VALUES (0, 1); INSERT INTO question_tag VALUES (1, 3); INSERT INTO question_tag VALUES (2, 3); -INSERT INTO users VALUES (1, 'test', 'test@test.pl', 'Testowy Tescik', '$2b$12$4wLEAbDLP6Ab0Q4M4CyZOe/xSuYcRDi5yHKe6i1nf0dZBo7HJ5h5W', 0); -INSERT INTO users VALUES (2, 'seba', 'seba@test.pl', 'Sebowski Seba', '$2b$12$yGHK2Vl/I9htIakbQSETxecYmhYAPjPXWEsC6TUcNysCzum2bZHwu', 1); +INSERT INTO users VALUES (0, 'test', 'Testowy Tescik', 'test@test.pl', '$2b$12$4wLEAbDLP6Ab0Q4M4CyZOe/xSuYcRDi5yHKe6i1nf0dZBo7HJ5h5W', 0); +INSERT INTO users VALUES (1, 'seba', 'Sebowski Seba', 'seba@test.pl', '$2b$12$yGHK2Vl/I9htIakbQSETxecYmhYAPjPXWEsC6TUcNysCzum2bZHwu', 0); +SELECT pg_catalog.setval('users_id_seq', 1, true); From 172a927f5e3f429079dbde83bd67cdb500c8a676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Szadkowski?= Date: Tue, 23 Apr 2019 14:04:12 +0200 Subject: [PATCH 094/111] credentials and layout login / logout --- server.py | 1 + server_python/sv_credentials.py | 32 +++++++++++++++++++++++++++++++- templates/layout.html | 7 +++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/server.py b/server.py index 537661fa5..89512d502 100644 --- a/server.py +++ b/server.py @@ -4,6 +4,7 @@ from server_python import sv_answers from server_python import sv_comments from server_python import sv_tags +from server_python import sv_credentials if __name__ == "__main__": diff --git a/server_python/sv_credentials.py b/server_python/sv_credentials.py index b59db3663..81fa3cc56 100644 --- a/server_python/sv_credentials.py +++ b/server_python/sv_credentials.py @@ -1,3 +1,33 @@ from server_python.config import app from data_manager import dm_general -from flask import request, redirect, render_template \ No newline at end of file +from flask import Flask, session, redirect, url_for, escape, request + +app.secret_key = b'_5#y2L"F4Q8z\n\xec]/' + + +@app.route('/') +def index(): + if 'username' in session: + return 'Logged in as %s' % escape(session['username']) + return 'You are not logged in' + + +@app.route('/login', methods=['GET', 'POST']) +def login(): + if request.method == 'POST': + session['username'] = request.form['username'] + return redirect(url_for('index')) + return ''' +
+

+

+

+ ''' + + +@app.route('/logout', methods=['GET', 'POST']) +def logout(): + # remove the username from the session if it's there + if request.method == 'POST': + session.pop('username', None) + return redirect(url_for('index')) diff --git a/templates/layout.html b/templates/layout.html index 21edc1b83..d0bc3e11d 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -34,6 +34,13 @@ + {% if session %} +
+ +
+ {% else %} + + {% endif %}
From 323bf71650f3c5b13ed94f37d1ad273a17139e05 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Tue, 23 Apr 2019 13:19:46 +0200 Subject: [PATCH 095/111] Add registration and login form file --- Forms/forms.py | 18 ++++++++++++++++++ templates/register.html | 10 ++++++++++ 2 files changed, 28 insertions(+) create mode 100644 Forms/forms.py create mode 100644 templates/register.html diff --git a/Forms/forms.py b/Forms/forms.py new file mode 100644 index 000000000..2b1516415 --- /dev/null +++ b/Forms/forms.py @@ -0,0 +1,18 @@ +from flask_wtf import FlaskForm +from wtforms import StringField, PasswordField, SubmitField, BooleanField +from wtforms.validators import DataRequired, Email, Length, EqualTo + +class RegistrationForm(FlaskForm): + username = StringField('Username', validators=[DataRequired(), Length(min=2, max=30)]) + name = StringField('Name', validators=[DataRequired(), Length(min=2, max=50)]) + email = StringField('Email', validators=[DataRequired(), Email()]) + password = PasswordField('Password', validators=[DataRequired()]) + confirmed_password = PasswordField('Confirm password', validators=[DataRequired(), EqualTo('password')]) + submit = SubmitField('Register') + + +class LoginForm(FlaskForm): + email = StringField('Email', validators=[DataRequired(), Email()]) + password = PasswordField('Password', validators=[DataRequired()]) + remember_me = BooleanField('Remember me') + submit = SubmitField('Login') \ No newline at end of file diff --git a/templates/register.html b/templates/register.html new file mode 100644 index 000000000..f7e588482 --- /dev/null +++ b/templates/register.html @@ -0,0 +1,10 @@ + + + + + $Title$ + + +$END$ + + \ No newline at end of file From 6a7f6cf4b146cc8ab5a9205b3e1d321263a72b0b Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Tue, 23 Apr 2019 14:37:06 +0200 Subject: [PATCH 096/111] Add sv_credentials to server --- server.py | 1 + 1 file changed, 1 insertion(+) diff --git a/server.py b/server.py index 537661fa5..89512d502 100644 --- a/server.py +++ b/server.py @@ -4,6 +4,7 @@ from server_python import sv_answers from server_python import sv_comments from server_python import sv_tags +from server_python import sv_credentials if __name__ == "__main__": From 21c7e1e52c93fcdf9f9d8b892e9797226926c121 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Tue, 23 Apr 2019 14:37:50 +0200 Subject: [PATCH 097/111] Add secret key --- server_python/config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/server_python/config.py b/server_python/config.py index 66b567342..cb97986d1 100644 --- a/server_python/config.py +++ b/server_python/config.py @@ -6,6 +6,7 @@ base_url = 'http://127.0.0.1:5004' app.config['UPLOADED_PHOTOS_DEST'] = 'static/images' +app.config['SECRET_KEY'] = '0b95219177b86d8db3fbde38daf944f0' # prevent catching files in browser: app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0 configure_uploads(app, photos) From 72a0813c33c0146c37729e49fd13d0703f454b7b Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Tue, 23 Apr 2019 14:38:27 +0200 Subject: [PATCH 098/111] Add registration form in html --- templates/register.html | 107 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 10 deletions(-) diff --git a/templates/register.html b/templates/register.html index f7e588482..1ede912e2 100644 --- a/templates/register.html +++ b/templates/register.html @@ -1,10 +1,97 @@ - - - - - $Title$ - - -$END$ - - \ No newline at end of file +{% extends "layout.html" %} +{% block contents %} +
+
+
+
+
+
+ {{ form.hidden_tag() }} +
+ {{ title }} +
+ {{ form.username.label(class="form-control-label") }} + + {% if form.username.errors %} + {{ form.username(class='form-control form-control-lg is-invalid') }} +
+ {% for error in form.username.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + {{ form.username(class='form-control form-control-lg') }} + {% endif %} +
+
+ {{ form.name.label(class="form-control-label") }} + + {% if form.name.errors %} + {{ form.name(class='form-control form-control-lg is-invalid') }} +
+ {% for error in form.name.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + {{ form.name(class='form-control form-control-lg') }} + {% endif %} +
+
+ {{ form.email.label(class="form-control-label") }} + + {% if form.email.errors %} + {{ form.email(class='form-control form-control-lg is-invalid') }} +
+ {% for error in form.email.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + {{ form.email(class='form-control form-control-lg') }} + {% endif %} +
+
+ {{ form.password.label(class="form-control-label") }} + + {% if form.password.errors %} + {{ form.password(class='form-control form-control-lg is-invalid') }} +
+ {% for error in form.password.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + {{ form.password(class='form-control form-control-lg') }} + {% endif %} +
+
+ {{ form.confirmed_password.label(class="form-control-label") }} + + {% if form.confirmed_password.errors %} + {{ form.confirmed_password(class='form-control form-control-lg is-invalid') }} +
+ {% for error in form.confirmed_password.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + {{ form.confirmed_password(class='form-control form-control-lg') }} + {% endif %} +
+
+
+ {{ form.submit(class="btn btn-outline-info") }} +
+
+{#
#} +{# #} +{# Already have an account? #} +{# #} +{#
#} +
+
+
+
+
+{% endblock %} \ No newline at end of file From dae287adc2a9961c1fcab94572dec98c4100f025 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Tue, 23 Apr 2019 14:40:40 +0200 Subject: [PATCH 099/111] Add registration route --- server_python/sv_credentials.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/server_python/sv_credentials.py b/server_python/sv_credentials.py index b59db3663..d06ee8c07 100644 --- a/server_python/sv_credentials.py +++ b/server_python/sv_credentials.py @@ -1,3 +1,13 @@ from server_python.config import app -from data_manager import dm_general -from flask import request, redirect, render_template \ No newline at end of file +from flask import flash, render_template, redirect +from Forms import forms + + +@app.route('/register', methods=['GET', 'POST']) +def register(): + form = forms.RegistrationForm() + if form.validate_on_submit(): + print('works') + flash(f'Account created for {form.name.data}!', 'success') + return redirect('/') + return render_template('register.html', form=form, title='Register') From 280f2c518fc7a174faee5e194f42a8282bfc5de0 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Tue, 23 Apr 2019 14:41:07 +0200 Subject: [PATCH 100/111] Add handling of flash messages --- templates/layout.html | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/templates/layout.html b/templates/layout.html index 21edc1b83..c42138ead 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -37,6 +37,15 @@
+ {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} +
+ {{ message }} +
+ {% endfor %} + {% endif %} + {% endwith %} {% block contents %} {% endblock contents %}
From 177473fa75e95d619d6246062c19c8ff409f1180 Mon Sep 17 00:00:00 2001 From: Michal Wagrodzki Date: Wed, 24 Apr 2019 12:05:51 +0200 Subject: [PATCH 101/111] users binding to questions for index.html and list.html --- data_manager/dm_questions.py | 19 +++++++++------- sample_data/askmatepart2-sample-data.sql | 12 +++++++--- server_python/sv_questions.py | 11 ++++++--- templates/index.html | 6 +++++ templates/list.html | 29 ++++++++++++++++-------- 5 files changed, 53 insertions(+), 24 deletions(-) diff --git a/data_manager/dm_questions.py b/data_manager/dm_questions.py index 3a97908bc..10ebcd96e 100644 --- a/data_manager/dm_questions.py +++ b/data_manager/dm_questions.py @@ -4,9 +4,10 @@ @connection_handler -def get_all_questions_sql_sorted_by_submission_time(cursor): +def get_all_questions_sql_sorted_by_submission_time(cursor): #SELECT * FROM question ORDER BY submission_time DESC cursor.execute(""" - SELECT * FROM question ORDER BY submission_time DESC + SELECT q.*, u.username FROM question as q + LEFT JOIN users as u ON q.users_id = u.id ORDER BY submission_time DESC """) questions = cursor.fetchall() return questions @@ -15,7 +16,8 @@ def get_all_questions_sql_sorted_by_submission_time(cursor): @connection_handler def get_5_questions_sql_sorted_by_submission_time(cursor): cursor.execute(""" - SELECT * FROM question ORDER BY submission_time DESC LIMIT 5 + SELECT q.*, u.username FROM question as q + LEFT JOIN users as u ON q.users_id = u.id ORDER BY submission_time DESC LIMIT 5 """) questions = cursor.fetchall() return questions @@ -24,7 +26,8 @@ def get_5_questions_sql_sorted_by_submission_time(cursor): @connection_handler def get_questions_sorted(cursor, order_by, order_direction): cursor.execute(f""" - SELECT * FROM question ORDER BY {order_by} {order_direction} + SELECT question.*, users.username FROM question + LEFT JOIN users ON users_id = users.id ORDER BY {order_by} {order_direction} """) questions = cursor.fetchall() return questions @@ -44,13 +47,13 @@ def get_question_sql_by_id(cursor, id): @connection_handler -def add_question_sql(cursor, form_data): +def add_question_sql(cursor, form_data, user_id): time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") # todo > in every data manager > queries need to be remade in a safe way > like below, without f strings cursor.execute(""" - INSERT INTO question (submission_time, view_number, vote_number, title, message) - VALUES (%(time)s, 0, 0, %(title)s, %(message)s) - """, {'time': time, 'title': form_data['title'], 'message': form_data['message']}) + INSERT INTO question (users_id, submission_time, view_number, vote_number, title, message) + VALUES (%(users_id)s, %(time)s, 0, 0, %(title)s, %(message)s) + """, {'time': time, 'title': form_data['title'], 'message': form_data['message'], 'users_id': user_id}) @connection_handler diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index cba1315a4..f36aa8239 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -6,6 +6,7 @@ -- 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.question DROP CONSTRAINT IF EXISTS fk_users_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; @@ -17,10 +18,12 @@ 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; ALTER TABLE IF EXISTS ONLY public.users DROP CONSTRAINT IF EXISTS pk_users_id CASCADE; + DROP TABLE IF EXISTS public.question; DROP SEQUENCE IF EXISTS public.question_id_seq; CREATE TABLE question ( id serial NOT NULL, + users_id integer, submission_time timestamp without time zone, view_number integer, vote_number integer, @@ -95,6 +98,9 @@ ALTER TABLE ONLY tag ALTER TABLE ONLY users ADD CONSTRAINT pk_users_id PRIMARY KEY (id); +ALTER TABLE ONLY question + ADD CONSTRAINT fk_users_id FOREIGN KEY (users_id) REFERENCES users(id); + ALTER TABLE ONLY comment ADD CONSTRAINT fk_answer_id FOREIGN KEY (answer_id) REFERENCES answer(id); @@ -110,8 +116,8 @@ ALTER TABLE ONLY comment 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(); +INSERT INTO question VALUES (0, NULL, '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, NULL, '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. @@ -120,7 +126,7 @@ 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'); -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. +INSERT INTO question VALUES (2, NULL, '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); diff --git a/server_python/sv_questions.py b/server_python/sv_questions.py index 59891089e..d8ec8c63e 100644 --- a/server_python/sv_questions.py +++ b/server_python/sv_questions.py @@ -1,11 +1,12 @@ from server_python.config import app from data_manager import dm_questions, dm_answers, dm_comments, dm_tags -from flask import request, redirect, render_template, jsonify +from flask import request, redirect, render_template, jsonify, session from util import check_referer_url, truncate_question @app.route('/') def route_home(): + session['user_id'] = 1 questions = dm_questions.get_5_questions_sql_sorted_by_submission_time() return render_template('index.html', questions=questions, truncate_fn=truncate_question) @@ -19,7 +20,7 @@ def route_list(): @app.route('/sort') def route_sort_questions(): feature_to_order_by = request.args.get('order_by', default='title', type=str) - # todo > everywhere we receive user input - evein in URL - make checks if parameters exist + # todo > everywhere we receive user input - even in URL - make checks if parameters exist # if feature_to_order_by not in ['title', 'message']: # return 'Error: wrong parameter' order_direction = request.args.get('order_direction', default='asc', type=str) @@ -32,7 +33,11 @@ def route_sort_questions(): @app.route('/add', methods=['GET', 'POST']) def route_add_question(): if request.method == 'POST': - dm_questions.add_question_sql(request.form) + if 'user_id' in session: + user_id = session['user_id'] + else: + user_id = None + dm_questions.add_question_sql(request.form, user_id) return redirect('/list') return render_template('form.html') diff --git a/templates/index.html b/templates/index.html index e22573df5..81d67bf4f 100644 --- a/templates/index.html +++ b/templates/index.html @@ -19,6 +19,7 @@

Latest questions:

No.
Title
+
User
Message
Submission Time
View Number
@@ -32,6 +33,11 @@

Latest questions:

{{ loop.index }} {{ question['title'] }} + {% if question['users_id'] %} + {{ question['username'] }} + {% else %} + {{ question['username'] }} + {% endif %} {{ truncate_fn(question['message'], 'home') }} {{ question['submission_time'] }} {{ question['view_number'] }} diff --git a/templates/list.html b/templates/list.html index 489224b36..e03c9cbdc 100644 --- a/templates/list.html +++ b/templates/list.html @@ -8,24 +8,28 @@
No.
Title
- - + + + +
User
+ +
Message
- - + +
Submission Time
- - + +
View Number
- - + +
Vote Number
- - + +
Image
@@ -36,6 +40,11 @@ {{ loop.index }} {{ question['title'] }} + {% if question['users_id'] %} + {{ question['username'] }} + {% else %} + {{ question['username'] }} + {% endif %} {{ truncate_fn(question['message'], 'list') }} {{ question['submission_time'] }} {{ question['view_number'] }} From ac6ae820d84d037d56bb10236a5486922195e7a4 Mon Sep 17 00:00:00 2001 From: Michal Wagrodzki Date: Wed, 24 Apr 2019 12:15:31 +0200 Subject: [PATCH 102/111] users binding to questions for qd.html --- data_manager/dm_questions.py | 5 +++-- templates/qd.html | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/data_manager/dm_questions.py b/data_manager/dm_questions.py index 10ebcd96e..decceefb2 100644 --- a/data_manager/dm_questions.py +++ b/data_manager/dm_questions.py @@ -36,8 +36,9 @@ def get_questions_sorted(cursor, order_by, order_direction): @connection_handler def get_question_sql_by_id(cursor, id): cursor.execute(f""" - SELECT * FROM question - WHERE id={id} + SELECT question.*, users.username FROM question + LEFT JOIN users ON users_id = users.id + WHERE question.id={id} """) list_with_question = cursor.fetchall() if list_with_question: diff --git a/templates/qd.html b/templates/qd.html index 5d0305f2c..96f579121 100644 --- a/templates/qd.html +++ b/templates/qd.html @@ -35,6 +35,14 @@

{{ question['title'] }}

Posted on: {{ question['submission_time'] }} + + Posted by: + {%- if question['users_id'] -%} + {{ question['username'] }} + {% else %} + {{ question['username'] }} + {% endif %} + Viewed: {{ question['view_number'] }} times From 7137835f817efac3d6658ce6fa48ebe97d9f4649 Mon Sep 17 00:00:00 2001 From: Michal Wagrodzki Date: Wed, 24 Apr 2019 12:16:25 +0200 Subject: [PATCH 103/111] removed always logged on user 1 cheat --- server_python/sv_questions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/server_python/sv_questions.py b/server_python/sv_questions.py index d8ec8c63e..ccbd43ec3 100644 --- a/server_python/sv_questions.py +++ b/server_python/sv_questions.py @@ -6,7 +6,6 @@ @app.route('/') def route_home(): - session['user_id'] = 1 questions = dm_questions.get_5_questions_sql_sorted_by_submission_time() return render_template('index.html', questions=questions, truncate_fn=truncate_question) From 382027885793c24dd8c56e5ffa16f0275af87232 Mon Sep 17 00:00:00 2001 From: Papcio Chmiel Date: Wed, 24 Apr 2019 12:19:26 +0200 Subject: [PATCH 104/111] list users added --- data_manager/dm_users.py | 21 +++++++++++++++++ server.py | 2 ++ server_python/sv_users.py | 23 ++++++++++++++++++ templates/layout.html | 13 ++++++++++- templates/users.html | 49 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 data_manager/dm_users.py create mode 100644 server_python/sv_users.py create mode 100644 templates/users.html diff --git a/data_manager/dm_users.py b/data_manager/dm_users.py new file mode 100644 index 000000000..466daec17 --- /dev/null +++ b/data_manager/dm_users.py @@ -0,0 +1,21 @@ +from connection import connection_handler +import datetime +from data_manager import dm_general + + +@connection_handler +def get_users(cursor): + cursor.execute(""" + SELECT * FROM users + """) + users = cursor.fetchall() + return users + + +@connection_handler +def get_users_sorted(cursor, order_by, order_direction): + cursor.execute(f""" + SELECT * FROM users ORDER BY {order_by} {order_direction} + """) + users = cursor.fetchall() + return users diff --git a/server.py b/server.py index 89512d502..248c8a728 100644 --- a/server.py +++ b/server.py @@ -5,6 +5,8 @@ from server_python import sv_comments from server_python import sv_tags from server_python import sv_credentials +from server_python import sv_users + if __name__ == "__main__": diff --git a/server_python/sv_users.py b/server_python/sv_users.py new file mode 100644 index 000000000..c13061cac --- /dev/null +++ b/server_python/sv_users.py @@ -0,0 +1,23 @@ +from server_python.config import app +from data_manager import dm_users +# from flask import render_template +from flask import request, redirect, render_template, jsonify + + +@app.route('/users_list', methods=['GET', 'POST']) +def route_list_users(): + users = dm_users.get_users() + print(users) + return render_template('users.html', users=users) + + +@app.route('/sort', methods=['GET', 'POST']) +def route_sort_users(): + feature_to_order_by = request.args.get('order_by', default='username', type=str) + # todo > everywhere we receive user input - evein in URL - make checks if parameters exist + # if feature_to_order_by not in ['title', 'message']: + # return 'Error: wrong parameter' + order_direction = request.args.get('order_direction', default='asc', type=str) + users = dm_users.get_users_sorted(feature_to_order_by, order_direction) + return render_template('users.html', + users=users) diff --git a/templates/layout.html b/templates/layout.html index 9415bd75c..59ba905c5 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -28,8 +28,19 @@ AskMate
+ + + + {% block menu %} + + {% endblock menu%} +
diff --git a/templates/users.html b/templates/users.html new file mode 100644 index 000000000..df569756e --- /dev/null +++ b/templates/users.html @@ -0,0 +1,49 @@ +{% extends "layout.html" %} +{#{% block menu %}#} +{#
  • Users
  • #} +{#{% endblock menu %}#} +{% block contents %} +
    +
    + + + + + + + + + + + + + + {% for user in users %} + + + + + + + + + + {% endfor %} + +
    No.
    Id
    + + +
    Username
    + + +
    Email
    + + +
    Full name
    + + +
    Password
    +
    Reputation
    {{ loop.index }} {{ user['id'] }} {{ user['username'] }} {{ user['email'] }} {{ user['full_name'] }} {{ user['password'] }} {{ user['reputation'] }}
    +
    +
    +{% endblock %} \ No newline at end of file From 705117da9b212e1c928fc6fef6421806e2b04647 Mon Sep 17 00:00:00 2001 From: Michal Wagrodzki Date: Wed, 24 Apr 2019 12:38:54 +0200 Subject: [PATCH 105/111] fixing commits --- server_python/sv_questions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/server_python/sv_questions.py b/server_python/sv_questions.py index ccbd43ec3..a9ba7cf53 100644 --- a/server_python/sv_questions.py +++ b/server_python/sv_questions.py @@ -31,6 +31,7 @@ def route_sort_questions(): @app.route('/add', methods=['GET', 'POST']) def route_add_question(): + # a if request.method == 'POST': if 'user_id' in session: user_id = session['user_id'] From 1f22c2cceb1f2724be03325d5b3f1bbb0928a840 Mon Sep 17 00:00:00 2001 From: Xareth Date: Wed, 24 Apr 2019 12:45:42 +0200 Subject: [PATCH 106/111] Update layout.html Deleted blank spaces --- templates/layout.html | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/templates/layout.html b/templates/layout.html index 59ba905c5..4654afd11 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -28,19 +28,13 @@ AskMate
    - - {% block menu %} - {% endblock menu%} - @@ -69,4 +63,4 @@
    - \ No newline at end of file + From 274f2f58a0078129cab92a017646b9bd87455b3a Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Wed, 24 Apr 2019 12:51:27 +0200 Subject: [PATCH 107/111] remove remember me field --- Forms/forms.py | 2 +- templates/login.html | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 templates/login.html diff --git a/Forms/forms.py b/Forms/forms.py index 2b1516415..e059d5103 100644 --- a/Forms/forms.py +++ b/Forms/forms.py @@ -14,5 +14,5 @@ class RegistrationForm(FlaskForm): class LoginForm(FlaskForm): email = StringField('Email', validators=[DataRequired(), Email()]) password = PasswordField('Password', validators=[DataRequired()]) - remember_me = BooleanField('Remember me') + # remember_me = BooleanField('Remember me') submit = SubmitField('Login') \ No newline at end of file diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 000000000..f7e588482 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,10 @@ + + + + + $Title$ + + +$END$ + + \ No newline at end of file From 004c941e058fe0e2cc2c307d7cbda088c95084ff Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Wed, 24 Apr 2019 12:52:08 +0200 Subject: [PATCH 108/111] Add user oriented sql functions --- data_manager/dm_credentials.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/data_manager/dm_credentials.py b/data_manager/dm_credentials.py index b27e7ddc9..9aa288de9 100644 --- a/data_manager/dm_credentials.py +++ b/data_manager/dm_credentials.py @@ -1,5 +1,24 @@ from connection import connection_handler -import uuid -import time -import util -import os + + +@connection_handler +def register_user(cursor, form_data, hashed_password): + # form_data.username.data, form_data.email.data etc... + cursor.execute(""" + INSERT INTO users (username, name, email, password) + VALUES (%(username)s, %(name)s, %(email)s, %(password)s) + """, {'username': form_data.username.data, + 'name': form_data.name.data, + 'email': form_data.email.data, + 'password': hashed_password}) + + +@connection_handler +def get_user_data(cursor, email): + cursor.execute(""" + SELECT * FROM users + WHERE email = %(email)s + """, + {'email': email}) + user_data = cursor.fetchone() + return user_data \ No newline at end of file From ad216f468529bbabfc79a86087fba564761490a8 Mon Sep 17 00:00:00 2001 From: Daniel_S Date: Wed, 24 Apr 2019 12:53:03 +0200 Subject: [PATCH 109/111] Add session and loggin feature --- server_python/config.py | 3 ++ server_python/sv_credentials.py | 59 +++++++++++++++--------------- templates/layout.html | 15 ++++---- templates/login.html | 65 ++++++++++++++++++++++++++++----- templates/register.html | 10 ++--- 5 files changed, 101 insertions(+), 51 deletions(-) diff --git a/server_python/config.py b/server_python/config.py index cb97986d1..21e4dbb8f 100644 --- a/server_python/config.py +++ b/server_python/config.py @@ -1,5 +1,6 @@ from flask import Flask from flask_uploads import UploadSet, configure_uploads, IMAGES +from flask_bcrypt import Bcrypt app = Flask(__name__, template_folder='../templates', static_folder='../static') photos = UploadSet('photos', IMAGES) @@ -10,3 +11,5 @@ # prevent catching files in browser: app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0 configure_uploads(app, photos) + +bcrypt = Bcrypt(app) diff --git a/server_python/sv_credentials.py b/server_python/sv_credentials.py index fb9d6a8a1..9485ab4ac 100644 --- a/server_python/sv_credentials.py +++ b/server_python/sv_credentials.py @@ -1,42 +1,43 @@ from server_python.config import app -from flask import flash, render_template, session, redirect, url_for, escape, request +from flask import flash, render_template, session, redirect from Forms import forms +from data_manager import dm_credentials +from server_python import config @app.route('/register', methods=['GET', 'POST']) def register(): - form = forms.RegistrationForm() - if form.validate_on_submit(): - print('works') - flash(f'Account created for {form.name.data}!', 'success') + form_data = forms.RegistrationForm() + if form_data.validate_on_submit(): + hashed_password = config.bcrypt.generate_password_hash(form_data.password.data).decode('utf-8') + dm_credentials.register_user(form_data, hashed_password) + flash(f'Account created for {form_data.name.data}!', 'success') return redirect('/') - return render_template('register.html', form=form, title='Register') - - -@app.route('/') -def index(): - if 'username' in session: - return 'Logged in as %s' % escape(session['username']) - return 'You are not logged in' + return render_template('register.html', form=form_data, title='Register') @app.route('/login', methods=['GET', 'POST']) def login(): - if request.method == 'POST': - session['username'] = request.form['username'] - return redirect(url_for('index')) - return ''' - -

    -

    - - ''' - - -@app.route('/logout', methods=['GET', 'POST']) + form = forms.LoginForm() + if form.validate_on_submit(): + user_data = dm_credentials.get_user_data(form.email.data) + is_user_email = bool(user_data['email']) + hashed_password = user_data['password'] + is_valid_password = config.bcrypt.check_password_hash(hashed_password, form.password.data) + if is_user_email and is_valid_password: + user_id = user_data['id'] + session['user_id'] = user_id + flash('You logged in!', 'success') + return redirect('/') + else: + flash('Invalid credentials!', 'danger') + return redirect('/login') + return render_template('login.html', form=form, title='Login') + + +@app.route('/logout') def logout(): - # remove the username from the session if it's there - if request.method == 'POST': - session.pop('username', None) - return redirect(url_for('index')) + flash('You\'ve logged out!', 'success') + session.pop('user_id', None) + return redirect('/') diff --git a/templates/layout.html b/templates/layout.html index 9415bd75c..ef6818210 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -34,13 +34,14 @@ - {% if session %} -

    - -
    - {% else %} - - {% endif %} +
    + {% if 'user_id' in session %} + Logout + {% else %} + Login + Register + {% endif %} +
    diff --git a/templates/login.html b/templates/login.html index f7e588482..5f52de4c4 100644 --- a/templates/login.html +++ b/templates/login.html @@ -1,10 +1,55 @@ - - - - - $Title$ - - -$END$ - - \ No newline at end of file +{% extends "layout.html" %} +{% block contents %} +
    +
    +
    +
    +
    +
    + {{ form.hidden_tag() }} +
    + {{ title }} +
    + {{ form.email.label(class="form-control-label") }} + + {% if form.email.errors %} + {{ form.email(class='form-control form-control-lg is-invalid') }} +
    + {% for error in form.email.errors %} + {{ error }} + {% endfor %} +
    + {% else %} + {{ form.email(class='form-control form-control-lg') }} + {% endif %} +
    +
    + {{ form.password.label(class="form-control-label") }} + + {% if form.password.errors %} + {{ form.password(class='form-control form-control-lg is-invalid') }} +
    + {% for error in form.password.errors %} + {{ error }} + {% endfor %} +
    + {% else %} + {{ form.password(class='form-control form-control-lg') }} + {% endif %} +
    +
    +
    + {{ form.submit(class="btn btn-outline-info") }} +
    +
    +
    + + Don't have an account yet? Register + +
    +
    +
    +
    +
    +
    +{% endblock %} \ No newline at end of file diff --git a/templates/register.html b/templates/register.html index 1ede912e2..abba3c67e 100644 --- a/templates/register.html +++ b/templates/register.html @@ -84,11 +84,11 @@ {{ form.submit(class="btn btn-outline-info") }}
    -{#
    #} -{# #} -{# Already have an account? #} -{# #} -{#
    #} +
    + + Already have an account? Login + +
    From eaa41bf44e3a245d853bd9cf537ec2ca56bd083c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Szadkowski?= Date: Wed, 24 Apr 2019 13:09:31 +0200 Subject: [PATCH 110/111] Revert "Update layout.html" This reverts commit 1f22c2cceb1f2724be03325d5b3f1bbb0928a840. --- templates/layout.html | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/templates/layout.html b/templates/layout.html index 4654afd11..59ba905c5 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -28,13 +28,19 @@ AskMate
    + + {% block menu %} + {% endblock menu%} +
    @@ -63,4 +69,4 @@
    - + \ No newline at end of file From 07655161f79378339d48cf6bd41e48a46895f531 Mon Sep 17 00:00:00 2001 From: Papcio Chmiel Date: Wed, 24 Apr 2019 22:04:24 +0200 Subject: [PATCH 111/111] comment binding done --- data_manager/dm_comments.py | 31 ++++++++++++++---------- sample_data/askmatepart2-sample-data.sql | 5 ++-- server_python/sv_comments.py | 14 ++++++++--- server_python/sv_users.py | 2 +- templates/qd.html | 17 +++++++++++++ 5 files changed, 50 insertions(+), 19 deletions(-) diff --git a/data_manager/dm_comments.py b/data_manager/dm_comments.py index ce6928202..bae91d547 100644 --- a/data_manager/dm_comments.py +++ b/data_manager/dm_comments.py @@ -3,32 +3,35 @@ @connection_handler -def add_comment_to_question(cursor, form_data, question_id): +def add_comment_to_question(cursor, form_data, question_id, users_id): time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") cursor.execute(""" INSERT INTO comment - (edited_count, message, question_id, submission_time) - VALUES (0, %(message)s, %(question_id)s, %(time)s) + (edited_count, message, question_id, submission_time, users_id) + VALUES (0, %(message)s, %(question_id)s, %(time)s, %(users_id)s) """, - {'message': form_data['message'], 'question_id': question_id, 'time': time}) + {'message': form_data['message'], 'question_id': question_id, 'time': time, + 'users_id': users_id}) @connection_handler -def add_comment_to_answer(cursor, form_data, answer_id, question_id): +def add_comment_to_answer(cursor, form_data, answer_id, question_id, users_id): time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") cursor.execute(""" INSERT INTO comment - (edited_count, message, answer_id, submission_time, question_id) - VALUES (0, %(message)s, %(answer_id)s, %(time)s, %(question_id)s) + (edited_count, message, answer_id, submission_time, question_id, users_id) + VALUES (0, %(message)s, %(answer_id)s, %(time)s, %(question_id)s, %(users_id)s) """, - {'message': form_data['message'], 'answer_id': answer_id, 'time': time, 'question_id': question_id}) + {'message': form_data['message'], 'answer_id': answer_id, + 'time': time, 'question_id': question_id, 'users_id': users_id}) @connection_handler def show_question_comments_by_id(cursor, question_id): cursor.execute(""" - SELECT * FROM comment - WHERE question_id = %(question_id)s AND answer_id IS NULL + SELECT c.*, u.username FROM comment as c + LEFT JOIN users as u ON c.users_id = u.id + WHERE question_id = %(question_id)s AND answer_id IS NULL """, {'question_id': question_id}) comments = cursor.fetchall() @@ -38,7 +41,8 @@ def show_question_comments_by_id(cursor, question_id): @connection_handler def show_answer_comments_by_id(cursor, question_id): cursor.execute(""" - SELECT * FROM comment + SELECT c.*, u.username FROM comment as c + LEFT JOIN users as u ON c.users_id = u.id WHERE question_id = %(question_id)s; """, {'question_id': question_id}) @@ -49,8 +53,9 @@ def show_answer_comments_by_id(cursor, question_id): @connection_handler def get_comment_by_id(cursor, comment_id): cursor.execute(""" - SELECT * FROM comment - WHERE id = %(comment_id)s; + SELECT c.*, u.username FROM comment as c + LEFT JOIN users as u ON c.users_id = u.id + WHERE c.id = %(comment_id)s; """, {'comment_id': comment_id}) comment = cursor.fetchone() diff --git a/sample_data/askmatepart2-sample-data.sql b/sample_data/askmatepart2-sample-data.sql index f36aa8239..1ee6bb4b8 100644 --- a/sample_data/askmatepart2-sample-data.sql +++ b/sample_data/askmatepart2-sample-data.sql @@ -49,6 +49,7 @@ CREATE TABLE comment ( id serial NOT NULL, question_id integer, answer_id integer, + users_id integer, message text, submission_time timestamp without time zone, edited_count integer @@ -134,8 +135,8 @@ INSERT INTO answer VALUES (1, '2017-04-28 16:49:00', 4, 1, 'You need to use brac 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'); +INSERT INTO comment VALUES (1, 0, NULL, Null, 'Please clarify the question as it is too vague!', '2017-05-01 05:49:00'); +INSERT INTO comment VALUES (2, NULL, 1, Null, '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'); diff --git a/server_python/sv_comments.py b/server_python/sv_comments.py index 4df0349c6..11aaee17f 100644 --- a/server_python/sv_comments.py +++ b/server_python/sv_comments.py @@ -1,13 +1,17 @@ from server_python.config import app from data_manager import dm_comments -from flask import request, redirect, render_template +from flask import request, redirect, render_template, session @app.route('/question/new-comment', methods=['GET', 'POST']) def route_add_comment_to_question(): question_id = request.args.get('question_id') if request.method == 'POST': - dm_comments.add_comment_to_question(request.form, question_id) + if 'user_id' in session: + user_id = session['user_id'] + else: + user_id = None + dm_comments.add_comment_to_question(request.form, question_id, user_id) return redirect(f'/question_detail/{question_id}') return render_template('comment.html', question_id=question_id, @@ -19,7 +23,11 @@ def route_add_comment_to_answer(): question_id = request.args.get('question_id') answer_id = request.args.get('answer_id') if request.method == 'POST': - dm_comments.add_comment_to_answer(request.form, answer_id, question_id) + if 'user_id' in session: + user_id = session['user_id'] + else: + user_id = None + dm_comments.add_comment_to_answer(request.form, answer_id, question_id, user_id) return redirect(f"/question_detail/{question_id}") return render_template('comment.html', question_id=question_id, diff --git a/server_python/sv_users.py b/server_python/sv_users.py index c13061cac..ab2b31da0 100644 --- a/server_python/sv_users.py +++ b/server_python/sv_users.py @@ -11,7 +11,7 @@ def route_list_users(): return render_template('users.html', users=users) -@app.route('/sort', methods=['GET', 'POST']) +@app.route('/sort_users', methods=['GET', 'POST']) def route_sort_users(): feature_to_order_by = request.args.get('order_by', default='username', type=str) # todo > everywhere we receive user input - evein in URL - make checks if parameters exist diff --git a/templates/qd.html b/templates/qd.html index 96f579121..02f161f67 100644 --- a/templates/qd.html +++ b/templates/qd.html @@ -78,6 +78,14 @@

    {{ question['title'] }}

    Posted on: {{ comment['submission_time'] }} + + Posted by: + {%- if comment['users_id'] -%} + {{ comment['username'] }} + {% else %} + {{ comment['username'] }} + {% endif %} + {% if comment['edited_count'] > 0 %} Edited {{ comment['edited_count'] }} times @@ -138,6 +146,7 @@
    Answer # {{ loop.index }}
    Posted on: {{ answer['submission_time'] }} +
    @@ -161,6 +170,14 @@
    Answer # {{ loop.index }}
    Posted on: {{ comment['submission_time'] }} + + Posted by: + {%- if comment['users_id'] -%} + {{ comment['username'] }} + {% else %} + {{ comment['username'] }} + {% endif %} + {% if comment['edited_count'] > 0 %} Edited {{ comment['edited_count'] }} times