summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJani Peter Karhunen <jkarhun2@local>2023-11-25 03:32:29 +0200
committerJani Peter Karhunen <jkarhun2@local>2023-11-25 03:32:29 +0200
commitd2de3ae10b6f5314bd4b8243218212d2004f35b0 (patch)
tree2ab448e0c2ec361478851dbcb43bcd176d17b584
parentc059696450d301b99956d643c21b0e46b4fc39dc (diff)
MEGA Commit. Rework of routing. Visuals. Answer analysis and much more.
-rw-r--r--README.md38
-rw-r--r--SCHEMA.sql47
-rw-r--r--app.py10
-rw-r--r--db_actions.py80
-rw-r--r--routes/analyse.py50
-rw-r--r--routes/answer.py100
-rw-r--r--routes/base.py97
-rw-r--r--routes/create.py55
-rw-r--r--routes/get/quiz.py18
-rw-r--r--routes/question.py49
-rw-r--r--routes/set/answers.py32
-rw-r--r--routes/set/nick.py28
-rw-r--r--routes/set/question.py40
-rw-r--r--routes/set/quiz.py13
-rw-r--r--routes/tools.py46
-rw-r--r--static/alert-timeout.js5
-rw-r--r--static/answer.js68
-rw-r--r--static/create.js62
-rw-r--r--static/icons/cel-rings-love-svgrepo-com.svg31
-rw-r--r--static/icons/cld-server-svgrepo-com.svg64
-rw-r--r--static/icons/cle-spraycan-svgrepo-com.svg70
-rw-r--r--static/icons/con-ruler-pencil-svgrepo-com.svg91
-rw-r--r--static/icons/gen-heart-rate-svgrepo-com.svg28
-rw-r--r--static/kyselma.css66
-rw-r--r--static/menu.css2
-rw-r--r--static/menu.js6
-rw-r--r--static/pages.json26
-rw-r--r--templates/analyse.html75
-rw-r--r--templates/answer.html26
-rw-r--r--templates/base.html7
-rw-r--r--templates/create.html32
-rw-r--r--templates/info.html13
-rw-r--r--templates/moderate.html2
-rw-r--r--templates/new_answer.html7
-rw-r--r--templates/nick.html4
-rw-r--r--templates/question.html2
-rw-r--r--templates/quiz.html2
37 files changed, 1017 insertions, 375 deletions
diff --git a/README.md b/README.md
index 2914010..f42950e 100644
--- a/README.md
+++ b/README.md
@@ -3,21 +3,36 @@
TO GET IT RUNNING:
-Install postgresql for local user & get it running
+Install postgresql for local user & get it running (as in course material)
- $ wget https://github.com/hy-tsoha/local-pg/raw/master/pg-install.sh
- $ bash pg-install.sh
- $ postrgres &
-
+
+Install poetry if nessesary. (refer your distro)
+- $ pip install --user poetry
+- $ pipx install poetry
+
Clone the source, get tables ready & install poetry dependencies
- $ git clone https://github.com/triionhe/kyselma.git
- $ cd kyselma
-- $ psql < SCHEMA.sql
-- $ poetry install
+- $ psql < SCHEMA.sql (BE CAREFUL! This drops some tables.)
+- $ poetry install --no-root
Start the app in poetry virtual environment
-- $ SQLALCHEMY_DATABASE_URI="postgresql:///$USER" SECRET_KEY=923987295 poetry run flask run
+- $ SQLALCHEMY_DATABASE_URI="postgresql:///$USER" SECRET_KEY=29347884 poetry run flask run
+
+Surf to the webpage and start two sessions for better testing
+- $ firefox http://localhost:5000/ http://127.0.0.1:5000/
+
+
DONE:
+- Vastausten anto
+- Vastausten tarkistelu
+- Kyselyn luomisen näyttö
+- Kyselyn lukitseminen vastattavaksi
+- Kysymyksen näyttö
+- Ulkoasu
- Voi lisätä kyselyn
- Kysymyksen mukana lisätään vastaus
- Kysymyksen lisäys
@@ -31,13 +46,11 @@ DONE:
- Nettisivurunko
TODO:
-- Kyselyn luomisen näyttö
-- Kyselyn lukitseminen vastattavaksi
-- Kysymyksen näyttö
-- Ulkoasu
- Moderointi
-- Vastausten anto
-- Vastausten tarkistelu
+- Parempi ulkoasu
+- Vastauksen ja luomisen aloittamisen yksinkertaistaminen
+- Tietoturvaseikat?
+- Eniten ja vähiten yhdenmukaiset vastaajat
...
Tarkoitus on luoda sivu jossa voi luoda kysymyksiä ja kyselyitä, joita
@@ -92,3 +105,6 @@ Kysymykset, kyselyt, vastaukset tallennetaan asianmukaisiin tauluihin.
Ominaisuuksia joiden tekemistä voi harkita:
- Jokaisella kyselyllä on elinikä jonka jälkeen ne siivotaan.
- Kysymyksiin voi liittää kuvia
+
+Ikonit (CC) pixellove:
+https://www.svgrepo.com/collection/pixellove-bordered-vectors/
diff --git a/SCHEMA.sql b/SCHEMA.sql
index 6832923..b88215a 100644
--- a/SCHEMA.sql
+++ b/SCHEMA.sql
@@ -1,3 +1,4 @@
+DROP TABLE users, questions, answers, questionaires, quiz_links;
CREATE TABLE users (
id SERIAL PRIMARY KEY,
nick TEXT,
@@ -21,6 +22,50 @@ CREATE TABLE questionaires (
id SERIAL PRIMARY KEY,
questionset INT[] DEFAULT '{}',
creator_id INT,
- ready BOOLEAN DEFAULT FALSE,
created INT
);
+CREATE TABLE quiz_links (
+ id SERIAL PRIMARY KEY,
+ quiz_id INT,
+ link TEXT,
+ created INT
+);
+INSERT INTO users (nick, created) VALUES ('Raili Niemi', 57 );
+INSERT INTO users (nick, created) VALUES ('Tea Jalava', 36 );
+INSERT INTO users (nick, created) VALUES ('Eero Metsäranta', 47 );
+INSERT INTO questions (question, neg_answer, pos_answer, created)
+ VALUES ('Mikä ikä?', '0', '100', 99 );
+INSERT INTO questions (question, neg_answer, pos_answer, created)
+ VALUES ('Mikä vointi?', 'huono', 'hyvä', 99 );
+INSERT INTO questions (question, neg_answer, pos_answer, created)
+ VALUES ('Ulkoiletko?', 'viime vuonna', 'joka päivä', 99 );
+INSERT INTO questions (question, neg_answer, pos_answer, created)
+ VALUES ('kys?', 'ei vielä', 'ei koskaan', 99 );
+INSERT INTO answers (user_id, question_id, answer, created)
+ VALUES (1, 1, 570, 99 );
+INSERT INTO answers (user_id, question_id, answer, created)
+ VALUES (1, 2, 670, 99 );
+INSERT INTO answers (user_id, question_id, answer, created)
+ VALUES (1, 3, 888, 99 );
+INSERT INTO answers (user_id, question_id, answer, created)
+ VALUES (1, 4, 999, 99 );
+INSERT INTO answers (user_id, question_id, answer, created)
+ VALUES (2, 1, 360, 99 );
+INSERT INTO answers (user_id, question_id, answer, created)
+ VALUES (2, 2, 230, 99 );
+INSERT INTO answers (user_id, question_id, answer, created)
+ VALUES (2, 3, 120, 99 );
+INSERT INTO answers (user_id, question_id, answer, created)
+ VALUES (2, 4, 123, 99 );
+INSERT INTO answers (user_id, question_id, answer, created)
+ VALUES (3, 1, 470, 99 );
+INSERT INTO answers (user_id, question_id, answer, created)
+ VALUES (3, 2, 570, 99 );
+INSERT INTO answers (user_id, question_id, answer, created)
+ VALUES (3, 3, 321, 99 );
+INSERT INTO answers (user_id, question_id, answer, created)
+ VALUES (3, 4, 785, 99 );
+INSERT INTO questionaires (questionset, creator_id, created)
+ VALUES ('{1,2,3,4}', 1, 666);
+INSERT INTO quiz_links (quiz_id, link, created)
+ VALUES (1, 'kyselama', 666);
diff --git a/app.py b/app.py
index b01f013..2f3b965 100644
--- a/app.py
+++ b/app.py
@@ -8,8 +8,8 @@ app.config["SQLALCHEMY_DATABASE_URI"] = getenv("SQLALCHEMY_DATABASE_URI")
db.init_app(app)
import routes.base
-import routes.set.nick
-import routes.set.quiz
-import routes.set.question
-import routes.set.answers
-import routes.get.quiz
+import routes.answer
+import routes.create
+import routes.analyse
+import routes.question
+
diff --git a/db_actions.py b/db_actions.py
index 5a76b00..5f793fc 100644
--- a/db_actions.py
+++ b/db_actions.py
@@ -65,6 +65,32 @@ def quiz_add( quiz_id, question_id ):
})
db.session.commit()
+
+def set_quiz_link( quiz_id, link ):
+ sql = "INSERT \
+ INTO quiz_links (quiz_id, link, created) \
+ VALUES (:quiz_id, :link, :created)"
+ result = db.session.execute( text(sql),
+ { "quiz_id":quiz_id, "link":link, "created":int(time()) } )
+ db.session.commit()
+
+
+def find_quiz_by_link( link ):
+ sql = "SELECT quiz_id \
+ FROM quiz_links \
+ WHERE link=:link;"
+ result = db.session.execute(text(sql), { "link":link }).fetchone()
+ return result[0] if result else result
+
+
+def get_quiz_link( quiz_id ):
+ sql = "SELECT link \
+ FROM quiz_links \
+ WHERE quiz_id=:quiz_id;"
+ result = db.session.execute(text(sql), { "quiz_id":quiz_id }).fetchone()
+ return result[0] if result else result
+
+
def answer_new(user_id, question_id, answer):
sql = "INSERT \
INTO answers (user_id, question_id, answer, created) \
@@ -77,6 +103,7 @@ def answer_new(user_id, question_id, answer):
} )
db.session.commit()
+
def get_questions(quiz_id):
sql = "SELECT q.id, q.question, q.neg_answer, q.pos_answer, a.answer \
FROM questionaires quiz \
@@ -85,15 +112,62 @@ def get_questions(quiz_id):
WHERE a.question_id = q.id AND quiz.id = (:quiz_id);"
return db.session.execute( text(sql), { "quiz_id":quiz_id } ).fetchall()
+def get_comparable(quiz_id,user1,user2):
+ sql = "SELECT q.question, q.neg_answer, q.pos_answer, \
+ a1.answer, a2.answer, \
+ 100 - ABS( a1.answer - a2.answer ) / 10 \
+ FROM questionaires quiz \
+ JOIN questions q ON q.id = ANY(quiz.questionset) \
+ JOIN answers a1 ON a1.user_id = (:user1) \
+ JOIN answers a2 ON a2.user_id = (:user2) \
+ WHERE a1.question_id = q.id \
+ AND a2.question_id = q.id \
+ AND quiz.id = (:quiz_id);"
+ return db.session.execute( text(sql), {
+ "quiz_id":quiz_id,
+ "user1":user1,
+ "user2":user2
+ } ).fetchall()
+
def get_user_answer(user_id, question_id):
sql = "SELECT answer \
- FROM answers \
- WHERE question_id = (:question_id) AND user_id = (:user_id);"
+ FROM answers \
+ WHERE question_id = (:question_id) AND user_id = (:user_id);"
result = db.session.execute( text(sql), {
'question_id': question_id,
'user_id': user_id
} ).fetchone()
return result[0] if result else result
- \ No newline at end of file
+
+def get_user_answers_for_quiz(quiz_id, user_id):
+ sql = "SELECT a.question_id, a.answer \
+ FROM questionaires quiz \
+ JOIN answers a ON a.question_id = ANY(quiz.questionset) \
+ WHERE a.user_id = (:user_id) AND quiz.id = (:quiz_id);"
+ return db.session.execute( text(sql), {
+ 'user_id': user_id,
+ 'quiz_id': quiz_id
+ } ).fetchall()
+
+def get_users_answered(quiz_id):
+ sql = "SELECT DISTINCT a.user_id, u.nick \
+ FROM questionaires quiz \
+ JOIN answers a ON a.question_id = quiz.questionset[1] \
+ JOIN users u ON u.id = a.user_id \
+ WHERE quiz.id = (:quiz_id);"
+ return db.session.execute( text(sql), {
+ 'quiz_id': quiz_id
+ } ).fetchall()
+
+def is_user_answered(quiz_id, user_id):
+ sql = "SELECT a.answer \
+ FROM questionaires quiz \
+ JOIN answers a ON a.question_id = quiz.questionset[1] \
+ WHERE quiz.id = (:quiz_id) AND a.user_id = (:user_id);"
+ results = db.session.execute( text(sql), {
+ 'quiz_id': quiz_id,
+ 'user_id': user_id
+ } ).fetchone()
+ return results[0] if results else results
diff --git a/routes/analyse.py b/routes/analyse.py
new file mode 100644
index 0000000..b333e70
--- /dev/null
+++ b/routes/analyse.py
@@ -0,0 +1,50 @@
+from app import app
+from flask import render_template,session,request,redirect
+import db_actions as D
+from routes.tools import rows2dicts, get_alert, get_nick, red
+
+@app.route("/pages/analyse.html")
+def analyse():
+ if "id" in session:
+ sid = session["id"]
+ else:
+ return red["nick"]
+
+ if "answer_id" in session and D.is_user_answered(session["answer_id"],sid):
+ aid = session["answer_id"]
+ else:
+ return render_template("analyse.html",
+ alert=get_alert(),
+ nick=get_nick()
+ )
+
+ uid1 = session["anal_user1"] if "anal_user1" in session else sid
+ uid1 = sid if uid1 != sid and not D.is_user_answered(aid,uid1) else uid1
+
+ uid2 = session["anal_user2"] if "anal_user2" in session else sid
+ uid2 = sid if uid2 != sid and not D.is_user_answered(aid,uid2) else uid2
+
+ comparable = D.get_comparable( aid, uid1, uid2 )
+ avg=0
+ for i in range(len(comparable)):
+ avg += comparable[i][5]
+ avg//=len(comparable)
+
+
+ return render_template("analyse.html",
+ alert=get_alert(),
+ nick=get_nick(),
+ code=D.get_quiz_link(aid),
+ questions = rows2dicts( comparable, ['q','n','p','a1','a2','c'] ),
+ users = rows2dicts( D.get_users_answered(aid), ['id','nick'] ),
+ user1=int(uid1),
+ user2=int(uid2),
+ avg = avg
+ )
+
+@app.route("/set/compare",methods=["POST"])
+def set_compare():
+ session["anal_user1"] = request.form["user1"]
+ session["anal_user2"] = request.form["user2"]
+ return redirect("/#analyse")
+
diff --git a/routes/answer.py b/routes/answer.py
new file mode 100644
index 0000000..fa3d138
--- /dev/null
+++ b/routes/answer.py
@@ -0,0 +1,100 @@
+from app import app
+from flask import render_template, session, request, redirect
+import db_actions as D
+from routes.tools import rows2dicts, get_alert, get_nick, red
+
+
+@app.route("/pages/new_answer.html")
+def new_answer():
+ if "id" not in session:
+ return red["nick"]
+ return render_template("new_answer.html",
+ alert=get_alert(),
+ nick=get_nick()
+ )
+
+@app.route("/kys/<link>")
+def kys_link(link):
+ if aid := D.find_quiz_by_link( link ):
+ session["answer_id"] = aid
+ return redirect("/#answer")
+ return redirect("/")
+
+@app.route("/set/answer_id",methods=["POST"])
+def answer_id():
+ if "id" not in session:
+ session["alert"] = "Nimimerkkiä ei ole asetettu."
+ return redirect("/#nick")
+ else:
+ sid = session["id"]
+
+ if "next" not in request.form:
+ next = "/#answer"
+ else:
+ next = "/#"+request.form["next"]
+
+ if "link" not in request.form or request.form["link"]=="":
+ session["alert"] = "Kyselmän nimeä ei ole annettu."
+ return redirect(next)
+
+ if aid := D.find_quiz_by_link( request.form["link"] ):
+ session["answer_id"] = aid
+ else:
+ session["alert"] = "Koodilla ei löytynyt kyselmää"
+ return redirect(next)
+
+ if next == "/#analyse" and not D.is_user_answered( aid, sid ):
+ session["alert"] = "Et ole vielä vastannut tähän kyselmään. \
+ Voit tutkia vastaksia vastattuasi."
+ return redirect("/#answer")
+
+ return redirect( next )
+
+@app.route("/pages/answer.html")
+def answer():
+ if "id" in session:
+ sid = session["id"]
+ else:
+ return red["nick"]
+
+ if "answer_id" in session:
+ aid = session["answer_id"]
+ else:
+ return red["new_answer"]
+
+ if D.is_user_answered(aid, sid):
+ return red["new_answer"]
+
+ return render_template("answer.html",
+ alert = get_alert(),
+ nick = get_nick(),
+ questions = rows2dicts( D.get_questions(aid), ['i','q','n','p'] ),
+ link = D.get_quiz_link( aid )
+ )
+
+@app.route("/set/answers",methods=["POST"])
+def set_answers():
+ if "id" not in session:
+ session["alert"]="Nimimerkkiä ei ole vielä valittu!"
+ return redirect( "/#nick" )
+ if "answer_id" not in session:
+ session["alert"]="Kyselyä ei ole valittu vastaamista varten!"
+ return redirect( "/#answer" )
+
+ sid = session["id"]
+ for qid, answer in request.form.items():
+ try:
+ if int(answer) < 0 or int(answer) > 999:
+ session["alert"]="Luvattoman pieniä tai suuria lukuja!"
+ return redirect( "/#answer" )
+ elif D.get_user_answer(sid, int(qid) ):
+ session["alert"]="Kyselyyn olikin jo saatu vastauksia."
+ return redirect( "/#answer" )
+ except ValueError:
+ session["alert"] = "Vastaukset ei ole lukuja!"
+ return redirect( "/#answer" )
+
+ for qid, answer in request.form.items():
+ D.answer_new(sid, int(qid), int(answer))
+
+ return redirect("/#analyse")
diff --git a/routes/base.py b/routes/base.py
index 144eeef..695388b 100644
--- a/routes/base.py
+++ b/routes/base.py
@@ -1,24 +1,7 @@
from app import app
-from flask import render_template,session
+from flask import render_template,session,request,redirect
import db_actions as D
-
-def get_alert():
- if "alert" in session:
- alert = session["alert"]
- del session["alert"]
- return f"{alert}"
- return ""
-
-def get_nick():
- while "id" in session.keys():
- nick = D.user_get_nick(session["id"])
- if not nick:
- del session['id']
- if "quiz_id" in session.keys():
- del session['quiz_id']
- break
- return nick
- return "(ei nimimerkkiä)"
+from routes.tools import rows2dicts, get_alert, get_nick
@app.route("/")
def index():
@@ -29,50 +12,40 @@ def info():
return render_template("info.html",
alert=get_alert()
)
-
-@app.route("/pages/create.html")
-def create():
- if "id" not in session.keys():
- return "redirect = #nick"
- if "quiz_id" not in session.keys():
- return "redirect = #quiz"
- return render_template("create.html",
- alert=get_alert(),
- nick=get_nick()
- )
-
-@app.route("/pages/answer.html")
-def answer():
- if "id" not in session.keys():
- return "redirect = #nick"
- return render_template("answer.html",
- alert=get_alert(),
- nick=get_nick()
- )
-
-@app.route("/pages/analyse.html")
-def analyse():
- if "id" not in session.keys():
- return "redirect = #nick"
- return render_template("analyse.html",
- alert=get_alert(),
- nick=get_nick()
- )
-
-@app.route("/pages/moderate.html")
-def moderate():
- return render_template("moderate.html",
- alert=get_alert()
- )
-
+
@app.route("/pages/nick.html")
def nick():
- return render_template("nick.html", alert=get_alert() )
+ return render_template("nick.html",
+ alert=get_alert()
+ )
-@app.route("/pages/question.html")
-def question():
- return render_template("question.html", alert=get_alert() )
+@app.route("/set/nick",methods=["POST"])
+def new_nick():
+ if "id" in session.keys():
+ session["alert"]="Sinulla on jo nimimerkki. Käytä sitä."
+ return redirect("/")
+ if "nick" not in request.form or request.form["nick"]=="":
+ session["alert"]="Nimimerkkiä ei voi asettaa ilman nimimerkkiä."
+ return redirect("/#nick")
+ else:
+ nick = request.form["nick"]
+ if len(nick) < 4:
+ session["alert"]="Nimimerkki on liian lyhyt"
+ return redirect("/#nick")
+ if not nick.isalnum():
+ session["alert"]="Nimimerkissä saa olla vain kirjaimia ja numeroita."
+ return redirect("/#nick")
+ if D.user_exists(nick):
+ session["alert"]="Nimimerkki jonka olet ottamassa on jo varattu."
+ return redirect("/#nick")
+ session["id"] = D.user_new(nick)
+ return redirect("/")
+
+
+
+#@app.route("/pages/moderate.html")
+#def moderate():
+# return render_template("moderate.html",
+# alert=get_alert()
+# )
-@app.route("/pages/quiz.html")
-def build():
- return render_template("quiz.html", alert=get_alert() )
diff --git a/routes/create.py b/routes/create.py
new file mode 100644
index 0000000..0a2a343
--- /dev/null
+++ b/routes/create.py
@@ -0,0 +1,55 @@
+from app import app
+from flask import render_template,session,request,redirect
+import db_actions as D
+from routes.tools import rows2dicts, get_alert, get_nick, generate_link, red
+
+
+@app.route("/pages/create.html")
+def create():
+ if "id" not in session:
+ return red["nick"]
+ if "quiz_id" not in session:
+ return red["quiz"]
+ if D.get_quiz_link(session["quiz_id"]):
+ return red["quiz"]
+
+ return render_template("create.html",
+ alert=get_alert(),
+ nick=get_nick(),
+ questions=rows2dicts(
+ D.get_questions(session["quiz_id"]),
+ ['i','q','n','p','a']
+ )
+ )
+
+@app.route("/pages/quiz.html")
+def build():
+ if "id" not in session:
+ return red["nick"]
+ return render_template("quiz.html",
+ alert=get_alert(),
+ nick=get_nick()
+ )
+
+@app.route("/set/quiz",methods=["POST"])
+def new_quiz():
+ if not "id" in session.keys():
+ session["alert"]="Tarvitset nimimerkin loudaksesi"
+ return redirect("/#nick")
+ user_id = session["id"]
+ session["quiz_id"] = D.quiz_new( user_id )
+ return redirect("/#create")
+
+
+@app.route("/set/quiz_ready",methods=["POST"])
+def quiz_ready():
+ if "quiz_id" not in session.keys():
+ return "KUOLETTAVA: kyselyä ei ole"
+ if not D.is_user_answered(session["quiz_id"], session["id"]):
+ session["alert"] = "Tyhjän kyselmän luominen ei käy päinsä!"
+ return redirect("/#create")
+ quiz_id = session["quiz_id"]
+ session["answer_id"] = session["quiz_id"]
+ D.set_quiz_link(session["quiz_id"], generate_link())
+ return redirect("/#analyse")
+
diff --git a/routes/get/quiz.py b/routes/get/quiz.py
deleted file mode 100644
index 69e2613..0000000
--- a/routes/get/quiz.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from app import app
-from flask import render_template, session, request, redirect, jsonify
-import db_actions as D
-
-
-@app.route("/get/quiz_creator",methods=["GET"])
-def get_questions_by_id():
- if "quiz_id" not in session.keys():
- return "KUOLETTAVA: Sessiota / kyselmä id:tä ei ole"
-
- results = D.get_questions(session['quiz_id'])
- r={}
- names=['i','q','n','p','a']
- for i in range(len(results)):
- r[i]={}
- for j in range(len(results[i])):
- r[i][names[j]]=results[i][j]
- return (jsonify(r))
diff --git a/routes/question.py b/routes/question.py
new file mode 100644
index 0000000..02261ca
--- /dev/null
+++ b/routes/question.py
@@ -0,0 +1,49 @@
+from app import app
+from flask import render_template,session,request,redirect
+import db_actions as D
+from routes.tools import rows2dicts, get_alert, get_nick
+
+@app.route("/pages/question.html")
+def question():
+ return render_template("question.html",
+ alert=get_alert(),
+ nick=get_nick()
+ )
+
+@app.route("/set/question",methods=["POST"])
+def new_question():
+ try:
+ question = request.form["question"]
+ neg_ans = request.form["neg_ans"]
+ pos_ans = request.form["pos_ans"]
+ answer = int(request.form["answer"])
+ except (KeyError, ValueError):
+ session["alert"] = "Nyt kaikkea ei tullut perille tai jotain outoa."
+ return redirect("/#question")
+
+ try:
+ sid = session["id"]
+ except (KeyError):
+ session["alert"] = "Nimimerkki puuttuukin."
+ return redirect("/#nick")
+
+ try:
+ qid = session["quiz_id"]
+ except (KeyError):
+ session["alert"] = "Kyselmän luonti ei ollutkaan kesken."
+ return redirect("/#quiz")
+
+ for entry in [question, neg_ans, pos_ans]:
+ if len(entry) < 2 or len(entry) > 80:
+ session["alert"] = "Syötteiden tulee olla 2-80 merkkiä pitkiä"
+ return redirect("/#question")
+
+ if answer < 0 or answer > 999:
+ session["alert"] = "Vastauksessasi on nyt jotain häikkää."
+ return redirect("/#question")
+
+ question_id = D.question_new( question, neg_ans, pos_ans )
+ D.quiz_add(qid, question_id)
+ D.answer_new(sid, question_id, answer)
+ return redirect("/#create")
+
diff --git a/routes/set/answers.py b/routes/set/answers.py
deleted file mode 100644
index 859d65c..0000000
--- a/routes/set/answers.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from app import app
-from flask import render_template, session, request, redirect
-import db_actions as D
-
-def validate_answer(ans):
- if len(ans)<1:
- return False
- try:
- value=int(ans)
- if value<0 or value>1000:
- return False
- except ValueError:
- return False
- return True
-
-@app.route("/set/answers",methods=["POST"])
-def set_answers():
- if "id" not in session.keys():
- return "KUOLETTAVA: Nimimerkkiä ei ole vielä valittu!"
- if "quiz_id" not in session.keys():
- return "KUOLETTAVA: Yrität vastata kyselyyn ilman sen valintaa!"
-
- user_id = session["id"]
- for id, answer in request.form.items():
- question_id = int(id)
- if not validate_answer(answer):
- return "KUOLETTAVA: Epäkelpo vastaus!"
- if D.get_user_answer(user_id,question_id):
- return "KUOLETTAVA: On jo vastattu!"
- D.answer_new(user_id, question_id, answer)
-
- return redirect("/#analyse")
diff --git a/routes/set/nick.py b/routes/set/nick.py
deleted file mode 100644
index 67ddeea..0000000
--- a/routes/set/nick.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from app import app
-from flask import render_template, session, request, redirect
-import db_actions as D
-
-
-@app.route("/set/nick",methods=["POST"])
-def new_nick():
- nick = request.form["nick"]
- if "id" in session.keys():
- msg = "You already have a nick."
- elif D.user_exists(nick):
- msg = "Nick is already reserved."
- elif msg := invalid_nick(nick):
- pass
- else:
- session["id"] = D.user_new(nick)
- return redirect("/")
- session["alert"]="Nick in not created: "+msg
- return redirect("/#nick")
-
-
-def invalid_nick(nick):
- if len(nick)<4:
- return "Nick is too short"
- if not nick.isalnum():
- return "Only letters and numbers are allowed"
- return 0
- \ No newline at end of file
diff --git a/routes/set/question.py b/routes/set/question.py
deleted file mode 100644
index deaf9be..0000000
--- a/routes/set/question.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from app import app
-from flask import render_template, session, request, redirect
-import db_actions as D
-
-
-def validate_answer(ans):
- if len(ans)<1:
- return False
- return True
-
-def validate_question(question):
- if len(question)<2:
- return False
- return True
-
-@app.route("/set/question",methods=["POST"])
-def new_question():
- question = request.form["question"]
- neg_ans = request.form["neg_ans"]
- pos_ans = request.form["pos_ans"]
- answer = request.form["answer"]
- if not validate_question(question):
- msg = "Kysymys on virheellinen"
- elif not validate_answer(neg_ans):
- msg = "Vasen selite on virheellinen"
- elif not validate_answer(pos_ans):
- msg = "Oikea selite on virheellinen"
- elif "id" not in session.keys():
- msg = "Tarvitaan nimimerkki"
- elif "quiz_id" not in session.keys():
- msg = "Ei voi lisätä kysymystä ilman kyselmää"
- else:
- quiz_id = session["quiz_id"]
- user_id = session["id"]
- question_id = D.question_new( question, neg_ans, pos_ans )
- D.quiz_add(quiz_id, question_id)
- D.answer_new(user_id, question_id, answer)
- return redirect("/#create")
- session["alert"]="Kysymystä ei luotu: "+msg
- return redirect("/#create")
diff --git a/routes/set/quiz.py b/routes/set/quiz.py
deleted file mode 100644
index 9ad13da..0000000
--- a/routes/set/quiz.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from app import app
-from flask import render_template, session, request, redirect
-import db_actions as D
-
-
-@app.route("/set/quiz",methods=["POST"])
-def new_quiz():
- if not "id" in session.keys():
- session["alert"]="Tarvitset nimimerkin loudaksesi"
- return redirect("/#nick")
- user_id = session["id"]
- session["quiz_id"] = D.quiz_new( user_id )
- return redirect("/#create")
diff --git a/routes/tools.py b/routes/tools.py
new file mode 100644
index 0000000..69e6fef
--- /dev/null
+++ b/routes/tools.py
@@ -0,0 +1,46 @@
+from random import randint
+from flask import session
+import db_actions as D
+
+red = {
+ "nick": "<script>window.location.hash=\"nick\"</script>",
+ "new_answer": "<script>window.location.hash=\"new_answer\"</script>",
+ "quiz": "<script>window.location.hash=\"quiz\"</script>"
+}
+
+
+def rows2dicts( rows, names ):
+ dlist=[]
+ for i in range(len(rows)):
+ row={}
+ for j in range(len(names)):
+ row[names[j]]=rows[i][j]
+ dlist.append(row)
+ return dlist
+
+def get_alert():
+ if "alert" in session:
+ alert = session["alert"]
+ del session["alert"]
+ return f"{alert}"
+ return ""
+
+def get_nick():
+ while "id" in session.keys():
+ nick = D.user_get_nick(session["id"])
+ if not nick:
+ del session['id']
+ if "quiz_id" in session.keys():
+ del session['quiz_id']
+ break
+ return nick
+ return "(ei nimimerkkiä)"
+
+def generate_link():
+ konso="rtpshjklvnm"
+ vocal="eyuioa"
+ str=""
+ for i in range(4):
+ str+=konso[randint(0,len(konso)-1)]
+ str+=vocal[randint(0,len(vocal)-1)]
+ return str
diff --git a/static/alert-timeout.js b/static/alert-timeout.js
new file mode 100644
index 0000000..01bd260
--- /dev/null
+++ b/static/alert-timeout.js
@@ -0,0 +1,5 @@
+Array.from(document.getElementsByClassName('kysAlert')).forEach( (a) => {
+ a.addEventListener('click', (event) => {
+ event.target.remove();
+ })
+ })
diff --git a/static/answer.js b/static/answer.js
deleted file mode 100644
index 61882a8..0000000
--- a/static/answer.js
+++ /dev/null
@@ -1,68 +0,0 @@
-var questions = {}
-
-createQuestionDiv = ( question ) => {
- const questionDiv = document.createElement('div')
- questionDiv.className = 'kysQuestion'
-
- const qDiv = document.createElement('div')
- qDiv.appendChild( document.createTextNode( question.q ) )
- qDiv.className = 'kysText'
- questionDiv.appendChild( qDiv )
-
- const npDiv = document.createElement('div')
- npDiv.className = 'kysScale'
-
- const nDiv = document.createElement('div')
- nDiv.appendChild( document.createTextNode( question.n ) )
- nDiv.className = 'kysNegative'
- npDiv.appendChild( nDiv )
-
- const sDiv = document.createElement('div')
- sDiv.className = 'kysScaleSpacer'
- npDiv.appendChild( sDiv )
-
- const pDiv = document.createElement('div')
- pDiv.appendChild( document.createTextNode( question.p ) )
- pDiv.className = 'kysPositive'
- npDiv.appendChild( pDiv )
-
- questionDiv.appendChild( npDiv )
-
- const aInput = document.createElement('input')
- aInput.className = 'kysAnswer'
- aInput.type = 'range'
- aInput.min = 0
- aInput.max = 999
- aInput.value = 500
- aInput.name = question.i
- questionDiv.appendChild( aInput )
-
- return questionDiv
-}
-
-createQuestions = () => {
- const kysForm = document.getElementById('questionForm')
- const questionsDiv = document.createElement('div')
- Object.keys(questions).forEach(k => {
- questionsDiv.appendChild( createQuestionDiv( questions[k] ) )
- })
- kysForm.appendChild( questionsDiv )
- const submitInput = document.createElement('input')
- submitInput.type='submit'
- submitInput.value='Vastaa kyselyyn'
- submitInput.className = 'kysSubmitAnswers'
- kysForm.appendChild( submitInput )
-}
-
-loadQuestions = async() => {
- await fetch( 'get/quiz_creator' )
- .then( response => response.json() )
- .then( json => questions = json )
- .catch( error => {
- alert("dkd")
- } )
-
- createQuestions()
-}
-
-loadQuestions()
diff --git a/static/create.js b/static/create.js
deleted file mode 100644
index d34a2da..0000000
--- a/static/create.js
+++ /dev/null
@@ -1,62 +0,0 @@
-var questions = {}
-
-createQuestionDiv = ( question ) => {
- const questionDiv = document.createElement('div')
- questionDiv.className = 'kysQuestion'
-
- const qDiv = document.createElement('div')
- qDiv.appendChild( document.createTextNode( question.q ) )
- qDiv.className = 'kysText'
- questionDiv.appendChild( qDiv )
-
- const npDiv = document.createElement('div')
- npDiv.className = 'kysScale'
-
- const nDiv = document.createElement('div')
- nDiv.appendChild( document.createTextNode( question.n ) )
- nDiv.className = 'kysNegative'
- npDiv.appendChild( nDiv )
-
- const sDiv = document.createElement('div')
- sDiv.className = 'kysScaleSpacer'
- npDiv.appendChild( sDiv )
-
- const pDiv = document.createElement('div')
- pDiv.appendChild( document.createTextNode( question.p ) )
- pDiv.className = 'kysPositive'
- npDiv.appendChild( pDiv )
-
- questionDiv.appendChild( npDiv )
-
- const aDiv = document.createElement('input')
- aDiv.className = 'kysAnswer'
- aDiv.type = 'range'
- aDiv.min = 0
- aDiv.max = 999
- aDiv.disabled = true
- aDiv.value = question.a
- questionDiv.appendChild( aDiv )
-
- return questionDiv
-}
-
-createQuestions = () => {
- const questionsDiv = document.getElementById('questions')
- questionsDiv.className = 'kysQuestions'
- Object.keys(questions).forEach(k => {
- questionsDiv.appendChild( createQuestionDiv( questions[k] ) )
- })
-}
-
-loadQuestions = async() => {
- await fetch( 'get/quiz_creator' )
- .then( response => response.json() )
- .then( json => questions = json )
- .catch( error => {
- alert("dkd")
- } )
-
- createQuestions()
-}
-
-loadQuestions()
diff --git a/static/icons/cel-rings-love-svgrepo-com.svg b/static/icons/cel-rings-love-svgrepo-com.svg
new file mode 100644
index 0000000..2e49668
--- /dev/null
+++ b/static/icons/cel-rings-love-svgrepo-com.svg
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg width="800px" height="800px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+ <title>cel-rings-love</title>
+ <desc>Created with Sketch.</desc>
+ <defs>
+
+</defs>
+ <g id="General" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="SLICES-64px" transform="translate(-630.000000, 0.000000)">
+
+</g>
+ <g id="ICONS" transform="translate(-625.000000, 5.000000)">
+ <g id="cel-rings-love" transform="translate(630.000000, 2.000000)">
+ <path d="M34.4229,9.3516 C36.5259,7.2126 36.5259,3.7446 34.4229,1.6046 C32.3199,-0.5354 28.9109,-0.5344 26.8079,1.6046 L25.9999,2.3476 L25.1929,1.6046 C23.0899,-0.5344 19.6799,-0.5344 17.5769,1.6046 C15.4739,3.7446 15.4749,7.2126 17.5769,9.3516 L25.9999,17.9996 L34.4229,9.3516 Z" id="Fill-747" fill="#F16963">
+
+</path>
+ <path d="M34.4229,9.3516 C36.5259,7.2126 36.5259,3.7446 34.4229,1.6046 C32.3199,-0.5354 28.9109,-0.5344 26.8079,1.6046 L25.9999,2.3476 L25.1929,1.6046 C23.0899,-0.5344 19.6799,-0.5344 17.5769,1.6046 C15.4739,3.7446 15.4749,7.2126 17.5769,9.3516 L25.9999,17.9996 L34.4229,9.3516 Z" id="Stroke-748" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M28.8071,26.4072 C30.8121,29.0802 32.0001,32.4012 32.0001,36.0002 C32.0001,44.8372 24.8361,52.0002 16.0001,52.0002 C7.1631,52.0002 0.0001,44.8372 0.0001,36.0002 C0.0001,27.1632 7.1631,20.0002 16.0001,20.0002 C18.2091,20.0002 20.3131,20.4472 22.2281,21.2582" id="Stroke-749" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M23.1929,45.5928 C21.1879,42.9198 19.9999,39.5988 19.9999,35.9998 C19.9999,27.1628 27.1639,19.9998 35.9999,19.9998 C44.8369,19.9998 51.9999,27.1628 51.9999,35.9998 C51.9999,44.8368 44.8369,51.9998 35.9999,51.9998 C33.5979,51.9998 31.3199,51.4708 29.2759,50.5228" id="Stroke-750" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ </g>
+ </g>
+ </g>
+</svg> \ No newline at end of file
diff --git a/static/icons/cld-server-svgrepo-com.svg b/static/icons/cld-server-svgrepo-com.svg
new file mode 100644
index 0000000..b484198
--- /dev/null
+++ b/static/icons/cld-server-svgrepo-com.svg
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg width="800px" height="800px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+ <title>cld-server</title>
+ <desc>Created with Sketch.</desc>
+ <defs>
+
+</defs>
+ <g id="General" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="SLICES-64px" transform="translate(-810.000000, -200.000000)">
+
+</g>
+ <g id="ICONS" transform="translate(-805.000000, -195.000000)">
+ <g id="cld-server" transform="translate(810.000000, 204.000000)">
+ <path d="M48,12 C51.313,12 54,9.313 54,6 C54,2.687 51.313,0 48,0 L6,0 C2.687,0 0,2.687 0,6 C0,9.313 2.687,12 6,12 L48,12 Z" id="Fill-424" fill="#969CE3">
+
+</path>
+ <path d="M10,6 C10,7.104 9.104,8 8,8 C6.896,8 6,7.104 6,6 C6,4.896 6.896,4 8,4 C9.104,4 10,4.896 10,6" id="Fill-425" fill="#7BBDEC">
+
+</path>
+ <path d="M48,30 C51.313,30 54,27.313 54,24 C54,20.687 51.313,18 48,18 L6,18 C2.687,18 0,20.687 0,24 C0,27.313 2.687,30 6,30 L48,30 Z" id="Fill-426" fill="#969CE3">
+
+</path>
+ <path d="M10,24 C10,25.104 9.104,26 8,26 C6.896,26 6,25.104 6,24 C6,22.896 6.896,22 8,22 C9.104,22 10,22.896 10,24" id="Fill-427" fill="#7BBDEC">
+
+</path>
+ <path d="M48,48 C51.313,48 54,45.313 54,42 C54,38.687 51.313,36 48,36 L6,36 C2.687,36 0,38.687 0,42 C0,45.313 2.687,48 6,48 L48,48 Z" id="Fill-428" fill="#969CE3">
+
+</path>
+ <path d="M10,42 C10,43.104 9.104,44 8,44 C6.896,44 6,43.104 6,42 C6,40.896 6.896,40 8,40 C9.104,40 10,40.896 10,42" id="Fill-429" fill="#7BBDEC">
+
+</path>
+ <path d="M48,12 C51.313,12 54,9.313 54,6 C54,2.687 51.313,0 48,0 L6,0 C2.687,0 0,2.687 0,6 C0,9.313 2.687,12 6,12 L48,12 Z" id="Stroke-430" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M10,6 C10,7.104 9.104,8 8,8 C6.896,8 6,7.104 6,6 C6,4.896 6.896,4 8,4 C9.104,4 10,4.896 10,6 Z" id="Stroke-431" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M48,6 L36,6" id="Stroke-432" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M48,30 C51.313,30 54,27.313 54,24 C54,20.687 51.313,18 48,18 L6,18 C2.687,18 0,20.687 0,24 C0,27.313 2.687,30 6,30 L48,30 Z" id="Stroke-433" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M10,24 C10,25.104 9.104,26 8,26 C6.896,26 6,25.104 6,24 C6,22.896 6.896,22 8,22 C9.104,22 10,22.896 10,24 Z" id="Stroke-434" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M48,24 L36,24" id="Stroke-435" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M48,48 C51.313,48 54,45.313 54,42 C54,38.687 51.313,36 48,36 L6,36 C2.687,36 0,38.687 0,42 C0,45.313 2.687,48 6,48 L48,48 Z" id="Stroke-436" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M10,42 C10,43.104 9.104,44 8,44 C6.896,44 6,43.104 6,42 C6,40.896 6.896,40 8,40 C9.104,40 10,40.896 10,42 Z" id="Stroke-437" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M48,42 L36,42" id="Stroke-438" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ </g>
+ </g>
+ </g>
+</svg> \ No newline at end of file
diff --git a/static/icons/cle-spraycan-svgrepo-com.svg b/static/icons/cle-spraycan-svgrepo-com.svg
new file mode 100644
index 0000000..86e3c64
--- /dev/null
+++ b/static/icons/cle-spraycan-svgrepo-com.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg width="800px" height="800px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+ <title>cle-spraycan</title>
+ <desc>Created with Sketch.</desc>
+ <defs>
+
+</defs>
+ <g id="General" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="SLICES-64px" transform="translate(-720.000000, -100.000000)">
+
+</g>
+ <g id="ICONS" transform="translate(-715.000000, -95.000000)">
+ <g id="cle-spraycan" transform="translate(728.000000, 100.000000)">
+ <path d="M3,54 L25,54 C26.657,54 28,52.657 28,51 L28,20 L0,20 L0,51 C0,52.657 1.343,54 3,54" id="Fill-295" fill="#F16963">
+
+</path>
+ <polygon id="Fill-296" fill="#E9EFFA" points="18 12 10 12 0 20 28 20">
+
+</polygon>
+ <polygon id="Fill-297" fill="#E9EFFA" points="10 12 18 12 18 4 10 4">
+
+</polygon>
+ <polygon id="Fill-298" fill="#F1F0E2" points="16 46 28 46 28 26 16 26">
+
+</polygon>
+ <polyline id="Stroke-299" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" points="0 20 10 12 18 12 28 20">
+
+</polyline>
+ <polyline id="Stroke-300" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" points="10 12 10 4 18 4 18 12">
+
+</polyline>
+ <polyline id="Stroke-301" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" points="28 46 16 46 16 26 28 26">
+
+</polyline>
+ <path d="M3,54 L25,54 C26.657,54 28,52.657 28,51 L28,20 L0,20 L0,51 C0,52.657 1.343,54 3,54 Z" id="Stroke-302" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M22,8 L24.5,8" id="Stroke-303" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M28.5527,8 L33.4737,8" id="Stroke-304" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="2.895,4.053">
+
+</path>
+ <path d="M35.5,8 L38,8" id="Stroke-305" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M22,5 L24.354,4.159" id="Stroke-306" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M27.7773,2.9365 L31.9333,1.4525" id="Stroke-307" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="2.596,3.635">
+
+</path>
+ <path d="M33.6455,0.8408 L35.9995,-0.0002" id="Stroke-308" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M22,11 L24.354,11.841" id="Stroke-309" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M27.7773,13.0635 L31.9333,14.5475" id="Stroke-310" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="2.596,3.635">
+
+</path>
+ <path d="M33.6455,15.1592 L35.9995,16.0002" id="Stroke-311" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ </g>
+ </g>
+ </g>
+</svg> \ No newline at end of file
diff --git a/static/icons/con-ruler-pencil-svgrepo-com.svg b/static/icons/con-ruler-pencil-svgrepo-com.svg
new file mode 100644
index 0000000..2d3d484
--- /dev/null
+++ b/static/icons/con-ruler-pencil-svgrepo-com.svg
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg width="800px" height="800px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+ <title>con-ruler-pencil</title>
+ <desc>Created with Sketch.</desc>
+ <defs>
+
+</defs>
+ <g id="General" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="SLICES-64px" transform="translate(-540.000000, -300.000000)">
+
+</g>
+ <g id="ICONS" transform="translate(-535.000000, -295.000000)">
+ <g id="con-ruler-pencil" transform="translate(548.000000, 298.000000)">
+ <polygon id="Fill-501" fill="#EEC261" points="0 58 14 58 14 0 0 0">
+
+</polygon>
+ <path d="M33,0 L27,0 C25.344,0 24,1.344 24,3 L24,8 L36,8 L36,3 C36,1.344 34.656,0 33,0" id="Fill-502" fill="#F16963">
+
+</path>
+ <polygon id="Fill-503" fill="#99A5B7" points="32.0371 52 27.9631 52 30.0001 58">
+
+</polygon>
+ <polygon id="Fill-504" fill="#F3E777" points="24.375 41.3662 28 38.0002 32 42.0002 36 38.0002 36 8.0002 24 8.0002 24 40.3262 24.355 41.3732">
+
+</polygon>
+ <polygon id="Fill-505" fill="#F1F0E2" points="36 38 32 42 28 38 24.375 41.366 24.355 41.373 27.963 52 32.037 52 36 40.326">
+
+</polygon>
+ <path d="M27.9629,52 L24.3559,41.372" id="Stroke-506" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <polyline id="Stroke-507" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" points="36 37.9995 36 40.3265 32.037 52.0005">
+
+</polyline>
+ <polyline id="Stroke-508" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" points="24.375 41.3662 28 38.0002 32 42.0002 36 38.0002">
+
+</polyline>
+ <path d="M27.9629,52 L32.0369,52" id="Stroke-509" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M28,34 L28,12" id="Stroke-510" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <polyline id="Stroke-511" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" points="32.0371 52.0005 30.0001 58.0005 27.9631 52.0005">
+
+</polyline>
+ <polyline id="Stroke-512" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" points="24.3555 41.3721 24.0005 40.3261 24.0005 8.0001">
+
+</polyline>
+ <path d="M36,8 L36,38" id="Stroke-513" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <polygon id="Stroke-514" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" points="0 58 14 58 14 0 0 0">
+
+</polygon>
+ <path d="M6,32 L14,32" id="Stroke-515" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M10,26 L14,26" id="Stroke-516" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M6,20 L14,20" id="Stroke-517" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M6,8 L14,8" id="Stroke-518" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M10,14 L14,14" id="Stroke-519" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M8,50 L14,50" id="Stroke-520" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M6,44 L14,44" id="Stroke-521" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M10,38 L14,38" id="Stroke-522" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M24,8 L36,8" id="Stroke-523" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <path d="M24,8 L24,3 C24,1.344 25.344,0 27,0 L33,0 C34.656,0 36,1.344 36,3 L36,8" id="Stroke-524" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ </g>
+ </g>
+ </g>
+</svg> \ No newline at end of file
diff --git a/static/icons/gen-heart-rate-svgrepo-com.svg b/static/icons/gen-heart-rate-svgrepo-com.svg
new file mode 100644
index 0000000..8880970
--- /dev/null
+++ b/static/icons/gen-heart-rate-svgrepo-com.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg width="800px" height="800px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+ <title>gen-heart-rate</title>
+ <desc>Created with Sketch.</desc>
+ <defs>
+
+</defs>
+ <g id="General" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="SLICES-64px" transform="translate(-180.000000, 0.000000)">
+
+</g>
+ <g id="ICONS" transform="translate(-175.000000, 5.000000)">
+ <g id="gen-heart-rate" transform="translate(180.000000, 6.000000)">
+ <path d="M26.0001,5.9995 L28.1011,4.1005 C33.5671,-1.3665 42.4331,-1.3665 47.8991,4.1005 C53.3671,9.5685 53.3661,18.4325 47.8991,23.8985 L26.0001,45.9995 L4.1011,23.8985 C-1.3659,18.4325 -1.3669,9.5685 4.1011,4.1005 C9.5671,-1.3665 18.4331,-1.3665 23.8991,4.1005 L26.0001,5.9995 Z" id="Fill-249" fill="#F16963">
+
+</path>
+ <path d="M26.0001,5.9995 L28.1011,4.1005 C33.5671,-1.3665 42.4331,-1.3665 47.8991,4.1005 C53.3671,9.5685 53.3661,18.4325 47.8991,23.8985 L26.0001,45.9995 L4.1011,23.8985 C-1.3659,18.4325 -1.3669,9.5685 4.1011,4.1005 C9.5671,-1.3665 18.4331,-1.3665 23.8991,4.1005 L26.0001,5.9995 Z" id="Stroke-250" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+
+</path>
+ <polyline id="Stroke-251" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" points="16.0001 23.9995 23.0001 23.9995 26.0001 11.9995 31.0001 33.9995 35.0001 19.9995 37.0001 23.9995 52.0001 23.9995">
+
+</polyline>
+ </g>
+ </g>
+ </g>
+</svg> \ No newline at end of file
diff --git a/static/kyselma.css b/static/kyselma.css
index a7a60db..14c7653 100644
--- a/static/kyselma.css
+++ b/static/kyselma.css
@@ -2,13 +2,17 @@
.kysQuestion {
display: flex;
flex-direction: column;
- max-width: 25em;
+ max-width: 25em;
+ padding: 0.5em;
+ border: 0.15em #fed solid;
}
.kysText {
align-self: center;
}
.kysScale {
display: flex;
+ width: 100%;
+ resize: horizontal;
}
.kysScaleSpacer {
flex-grow: 1;
@@ -26,3 +30,63 @@
.kysCreateText {
width: 100%;
}
+
+.kysNick::before {
+ content: "Olet:";
+ padding-right: 0.4em;
+}
+
+.kysNick {
+ border: 0.1em solid;
+ padding: 0.4em;
+ position: fixed;
+ top: 100vh;
+ left: 100vw;
+ transform: translate(-100%, -100%);
+ display: block;
+ background-color: #DAF;
+}
+
+.kysAlert {
+ border: 0.4em solid;
+ padding: 0.8em;
+ display: block;
+ background-color: #F55;
+ border-top-color: #F97;
+ border-left-color: #F96;
+ border-right-color: #F13;
+ border-bottom-color: #F14;
+ position: fixed;
+ top: 50vh;
+ left: 50vw;
+ transform: translate(-50%, -50%);
+}
+
+.kysTotal {
+ align-self: center;
+ font-size: xxx-large;
+}
+
+.kysSelectU1 {
+ background: #faa;
+}
+
+.kysSelectU2 {
+ background: #aaf;
+}
+
+.kysUser1::-webkit-slider-runnable-track, .kysUser1::-moz-range-track {
+ background: #faa;
+}
+
+.kysUser2::-webkit-slider-runnable-track, .kysUser2::-moz-range-track {
+ background: #aaf;
+}
+
+.kysUser1::-webkit-slider-thumb, .kysUser1::-moz-range-thumb {
+ background: #c00;
+}
+
+.kysUser2::-webkit-slider-thumb, .kysUser2::-moz-range-thumb {
+ background: #00c;
+}
diff --git a/static/menu.css b/static/menu.css
index 04127ae..4cf7c5f 100644
--- a/static/menu.css
+++ b/static/menu.css
@@ -93,7 +93,7 @@
.menuHidden, .menuSpacer, .menuTitle { display: flex !important }
.menuSpacer { flex-grow: 2; }
.menuText {
- padding-left: calc(var(--menuHeight)/2);
+ padding-left: calc(var(--menuHeight)/8);
padding-right: calc(var(--menuHeight)/2);
}
}
diff --git a/static/menu.js b/static/menu.js
index 5256ef2..8d0baee 100644
--- a/static/menu.js
+++ b/static/menu.js
@@ -132,7 +132,7 @@ hashToPage = async () => {
else document.getElementById(`${currentPage}_page`).className = 'page'
pageElement.className = 'page pageActive'
- if ( !pageElement.loaded ) await fetch( pages[p].URL )
+ if ( pages[p].dynamic || !pageElement.loaded ) await fetch( pages[p].URL )
.then( response => {
if (!response.ok) return `ERROR loading "${pages[p].URL}"!`
return response.text()
@@ -141,10 +141,10 @@ hashToPage = async () => {
pageElement.innerHTML = text;
pageElement.loaded = true;
} )
- if ( pageElement.innerHTML.startsWith("redirect = ") ) {
+/* if ( pageElement.innerHTML.startsWith("redirect = ") ) {
pageElement.loaded = false;
window.location.assign( pageElement.innerHTML.slice( 11 ) );
- }
+ }*/
// https://plnkr.co/edit/MMegiu by Allen Kim
Array.from(pageElement.querySelectorAll("script")).forEach(oldScript => {
diff --git a/static/pages.json b/static/pages.json
index 618bc7a..37e59e4 100644
--- a/static/pages.json
+++ b/static/pages.json
@@ -3,7 +3,7 @@
"pages": {
"info": {
"URL": "pages/info.html",
- "menuIcon": "kyselma.svg",
+ "menuIcon": "icons/gen-heart-rate-svgrepo-com.svg",
"menuName": "Kyselmä"
},
"spacer-1": {
@@ -11,27 +11,36 @@
"create": {
"pageTitle": "Luo kysely",
"URL": "pages/create.html",
- "menuName": "Luo"
+ "menuIcon": "icons/con-ruler-pencil-svgrepo-com.svg",
+ "menuName": "Luo",
+ "dynamic": "yes"
},
"answer": {
"pageTitle": "Vastaa kyselyyn",
"URL": "pages/answer.html",
- "menuName": "Vastaa"
+ "menuIcon": "icons/cld-server-svgrepo-com.svg",
+ "menuName": "Vastaa",
+ "dynamic": "yes"
},
"analyse": {
"pageTitle": "Tutki vastauksia",
"URL": "pages/analyse.html",
- "menuName": "Tutki"
+ "menuIcon": "icons/cel-rings-love-svgrepo-com.svg",
+ "menuName": "Tutki",
+ "dynamic": "yes"
},
"moderate": {
"pageTitle": "Moderoi sivustoa",
"URL": "pages/moderate.html",
+ "menuIcon": "icons/cle-spraycan-svgrepo-com.svg",
+ "hidden": "yes",
"menuName": "Moderoi"
},
"nick": {
"pageTitle": "Anna nimimerkki",
"URL": "pages/nick.html",
- "hidden": "yes"
+ "hidden": "yes",
+ "dynamic": "yes"
},
"question": {
"pageTitle": "Lisää kysymys",
@@ -39,9 +48,14 @@
"hidden": "yes"
},
"quiz": {
- "pageTitle": "Rakenna kysely",
+ "pageTitle": "Luodaanko uusi kyselmä?",
"URL": "pages/quiz.html",
"hidden": "yes"
+ },
+ "new_answer": {
+ "pageTitle": "Anna kyselyn koodi",
+ "URL": "pages/new_answer.html",
+ "hidden": "yes"
}
}
}
diff --git a/templates/analyse.html b/templates/analyse.html
index 6970764..70fb98e 100644
--- a/templates/analyse.html
+++ b/templates/analyse.html
@@ -1,4 +1,73 @@
-<div id="nickbox">{{ nick }}</div>
-<div id="alertbox">{{ alert }}</div>
-<h1>analyse</h1>
+{% include 'base.html' %}
+
+{% if users %}
+
+Tutkit kyselyä: {{ code }}
+
+
+<div class="kysQuestion"><div class="kysScale">
+<form action="/set/compare" method="POST">
+<input type="submit" value="Vertaa" class="kysButton">
+<select class="kysSelectU1 kysSelect" name="user1">
+{% for user in users %}
+ {% if user1==user.id %}
+ <option value="{{ user.id }}" selected>{{ user.nick }}</option>
+ {% else %}
+ <option value="{{ user.id }}">{{ user.nick }}</option>
+ {% endif %}
+{% endfor %}
+</select>
+<select class="kysSelectU2 kysSelect" name="user2">
+{% for user in users %}
+ {% if user2==user.id %}
+ <option value="{{ user.id }}" selected>{{ user.nick }}</option>
+ {% else %}
+ <option value="{{ user.id }}">{{ user.nick }}</option>
+ {% endif %}
+{% endfor %}
+</select>
+<div class="kysScaleSpacer"></div>
+</form>
+</div></div>
+
+{% endif %}
+
+{% if code %}
+
+<div id="questions" class="kysQuestions">
+ <div class="kysQuestion">
+ <div class="kysTotal">{{ avg }}%</div>
+ </div>
+{% for q in questions %}
+<div class="kysQuestion">
+ <div class="kysText">{{ q.q }} ({{ q.c }}%)</div>
+ <input class="kysAnswer kysUser1" type="range" min="0" max="999"
+ value="{{ q.a1 }}" disabled="">
+ <input class="kysAnswer kysUser2" type="range" min="0" max="999"
+ value="{{ q.a2 }}" disabled="">
+ <div class="kysScale">
+ <div class="kysNegative">{{ q.n }}</div>
+ <div class="kysScaleSpacer"></div>
+ <div class="kysPositive">{{ q.p }}</div>
+ </div>
+</div>
+{% endfor %}
+
+</div>
+
+{% endif %}
+
+<form action="/set/answer_id" method="POST">
+Vaihda kyselyn koodia:
+<input type="text" name="link">
+<input type="text" name="next" value="analyse" hidden="true">
+<input type="submit" value="Vaihda">
+</form>
+
+{% if code %}
+Linkki tähän kyselyyn:
+<a href="http://anal.fi:5000/kys/{{ code }}">
+ http://anal.fi:5000/kys/{{ code }}
+</a>
+{% endif %}
diff --git a/templates/answer.html b/templates/answer.html
index 0ed0a05..eb49ff8 100644
--- a/templates/answer.html
+++ b/templates/answer.html
@@ -1,5 +1,21 @@
-<script src="answer.js"></script>
-<div id="nickbox">{{ nick }}</div>
-<div id="alertbox">{{ alert }}</div>
-<h1>answer NOW!</h1>
-<form id=questionForm action="/set/answers" method="POST"></form>
+{% include 'base.html' %}
+
+Vastaa kyselmään "{{ link }}":
+
+<form class="kysQuestionaire" action="/set/answers" method="POST">
+<div id="questions" class="kysQuestions">
+{% for q in questions %}
+<div class="kysQuestion">
+<div class="kysText">{{ q.q }}</div>
+<div class="kysScale">
+ <div class="kysNegative">{{ q.n }}</div>
+ <div class="kysScaleSpacer"></div>
+ <div class="kysPositive">{{ q.p }}</div>
+</div>
+<input class="kysAnswer" type="range" min="0" max="999" name="{{ q.i }}">
+</div>
+{% endfor %}
+<input class="kysSubmitAnswers" type="submit" value="Vastaa kyselyyn">
+</div>
+</form>
+
diff --git a/templates/base.html b/templates/base.html
new file mode 100644
index 0000000..839cc88
--- /dev/null
+++ b/templates/base.html
@@ -0,0 +1,7 @@
+{% if nick %}
+ <div class="kysNick">{{ nick }}</div>
+{% endif %}
+{% if alert %}
+ <div class="kysAlert">{{ alert }}</div>
+ <script src="alert-timeout.js"></script>
+{% endif %}
diff --git a/templates/create.html b/templates/create.html
index fe2aa24..b369ae8 100644
--- a/templates/create.html
+++ b/templates/create.html
@@ -1,9 +1,29 @@
-<script src="create.js"></script>
-<div id="nickbox">{{ nick }}</div>
-<div id="alertbox">{{ alert }}</div>
-<h1>create</h1>
+{% include 'base.html' %}
-<div id=questions></div>
-<a href="#question">Lisää kysymys</a>
+<div id="questions" class="kysQuestions">
+{% for q in questions %}
+<div class="kysQuestion">
+<div class="kysText">{{ q.q }}</div>
+<div class="kysScale">
+ <div class="kysNegative">{{ q.n }}</div>
+ <div class="kysScaleSpacer"></div>
+ <div class="kysPositive">{{ q.p }}</div>
+</div>
+<input class="kysAnswer" type="range" min="0" max="999"
+ value="{{ q.a }}" disabled=""></div>
+{% endfor %}
+
+<div class="kysQuestion">
+<div class="kysScale">
+<a href="#question">
+ <input type="button" value="Lisää kysymys" class="kysButton">
+</a>
+<div class="kysScaleSpacer"></div>
+<form action="/set/quiz_ready" method="POST">
+<input type="text" name="ok" hidden=true>
+<input type="submit" value="Valmis" class="kysButton">
</form>
+<div class="kysScale">
+</div>
+</div> \ No newline at end of file
diff --git a/templates/info.html b/templates/info.html
index 3f984a6..30e84e2 100644
--- a/templates/info.html
+++ b/templates/info.html
@@ -1,2 +1,11 @@
-<div id="alertbox">{{ alert }}</div>
-<h1>info</h1>
+{% include 'base.html' %}
+<h1>Kyselmä</h1>
+
+Tervetuloa kyselmien ihmeelliseen maailmaan. Täällä laadit ikioman kyselmän
+ja vastailet kavereidesi luomiin kyselmiin. Vastattuasi pääset vertailemaan
+vastauksiasi muiden vatausten kassa. Alkuun pääset painamalla ylhäätä "Luo"
+ja tekemällä uuden kyselmän. Tämän jälkeen vain lisäät niin monta kysymystä
+vastausvaihtoehtoineen kuin haluat ja lopuksi painat valmis, jonka jälkeen
+muutkin pääsee vastaamaan kyselmään koodilla. Tarkastelussa voit valita
+mitkä tahansa kaksi vastaaja ja tutkia vastausten samankaltaisuutta ja
+kaiken huipuksi vastauksista lasketaan yhtäläisyys prosentti.
diff --git a/templates/moderate.html b/templates/moderate.html
index 116f2ff..118c8d4 100644
--- a/templates/moderate.html
+++ b/templates/moderate.html
@@ -1,2 +1,2 @@
-<div id="alertbox">{{ alert }}</div>
+{% include 'base.html' %}
<h1>moderate</h1>
diff --git a/templates/new_answer.html b/templates/new_answer.html
new file mode 100644
index 0000000..0d690d4
--- /dev/null
+++ b/templates/new_answer.html
@@ -0,0 +1,7 @@
+{% include 'base.html' %}
+<form action="/set/answer_id" method="POST">
+Vastaa kyselyyn koodilla:
+<input type="text" name="link">
+<input type="submit" value="Kyselmään">
+</form>
+Saatoit myös päätyä tänne mikäli olet jo vastannut.
diff --git a/templates/nick.html b/templates/nick.html
index fe4a50a..92e166f 100644
--- a/templates/nick.html
+++ b/templates/nick.html
@@ -1,6 +1,6 @@
-<div id="alertbox">{{ alert }}</div>
+{% include 'base.html' %}
<form action="/set/nick" method="POST">
Anna itsellesi nimimerkki ensin:
-<input type="text" name="nick" rows="1" cols="40"></textarea>
+<input type="text" name="nick">
<input type="submit" value="Lähetä">
</form>
diff --git a/templates/question.html b/templates/question.html
index 016a1ac..62afaaf 100644
--- a/templates/question.html
+++ b/templates/question.html
@@ -1,4 +1,4 @@
-<div id="kysAlert">{{ alert }}</div>
+{% include 'base.html' %}
<form action="/set/question" method="POST">
<div class="kysQuestion">
<div class="kysCreateText">Kysymys:</div>
diff --git a/templates/quiz.html b/templates/quiz.html
index b2083ae..9e356c3 100644
--- a/templates/quiz.html
+++ b/templates/quiz.html
@@ -1,4 +1,4 @@
-<div id="alertbox">{{ alert }}</div>
+{% include 'base.html' %}
<form action="/set/quiz" method="POST">
<input type="submit" value="Aloita uusi kyselmä">
</form>