13 Commits

Author SHA1 Message Date
Leon Noe Jovan
ce03a21ad7 fixes 2023-01-14 13:56:03 +01:00
Leon Noe Jovan
e6c87bb3f6 fixes 2023-01-14 13:45:33 +01:00
mihasinkec
10e8116d83 Added route prefix support. 2022-11-06 13:51:12 +01:00
Leon Noe Jovan
f671c365a3 reverted menu 2022-02-14 21:56:10 +01:00
Leon Noe Jovan
b19cfa6d48 added check if empty 2022-02-14 17:37:41 +01:00
msinkec
f898ee8d31 Finished manage institution site. Redone how cooperation history works. 2022-02-14 15:01:03 +01:00
Leon Noe Jovan
87f067b077 new menu, manage instutution reorganized 2022-02-13 15:47:19 +01:00
Leon Noe Jovan
e1b1d194fd new menu, manage instutution reorganized 2022-02-13 15:20:20 +01:00
Leon Noe Jovan
ab842809c7 Merge branch 'leon-redesign' of https://gitea.cjvt.si/webapps/portal-oddajanje-solar into leon-redesign 2022-02-12 16:38:37 +01:00
Leon Noe Jovan
e909ee8405 changes in history 2022-02-12 16:38:34 +01:00
msinkec
9ce19a34a7 Merge branch 'leon-redesign' of https://gitea.cjvt.si/mihasinkec/portal-oddajanje-solar into leon-redesign 2022-02-10 10:25:39 +01:00
msinkec
710abf74df endpoint permission updates for institutions, threw out add user from manage institution menu 2022-02-10 10:25:27 +01:00
Leon Noe Jovan
2de5727ea2 api for top upload graph 2022-01-23 22:53:11 +01:00
27 changed files with 1070 additions and 431 deletions

View File

@@ -13,6 +13,5 @@ WORKDIR /usr/src/portal-webapp
RUN apt-get update && apt-get -y install wkhtmltopdf && \ RUN apt-get update && apt-get -y install wkhtmltopdf && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
RUN pip3 install --no-cache-dir pdfkit flask==1.1.4 flask-dropzone flask-log-request-id flask-login Flask-SQLAlchemy alembic flask-migrate==2.7.0 Flask-script psycopg2 gunicorn pdfkit Werkzeug==1.0.1 PyJWT RUN pip3 install --no-cache-dir pdfkit markupsafe==2.0.1 flask==1.1.4 flask-dropzone flask-log-request-id flask-login Flask-SQLAlchemy==2.5.1 alembic flask-migrate==2.7.0 Flask-script psycopg2 gunicorn pdfkit Werkzeug==1.0.1 PyJWT
ENTRYPOINT ["./entrypoint.sh"] ENTRYPOINT ["./entrypoint.sh"]

422
app.py
View File

@@ -2,6 +2,8 @@ import logging
import os import os
import re import re
import configparser import configparser
import random
import string
from pathlib import Path from pathlib import Path
from werkzeug.security import check_password_hash from werkzeug.security import check_password_hash
@@ -12,6 +14,10 @@ from flask_script import Manager
from flask_login import LoginManager, login_required, login_user, current_user, logout_user from flask_login import LoginManager, login_required, login_user, current_user, logout_user
from portal.model import db, RegisteredUser from portal.model import db, RegisteredUser
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
import portal.solar import portal.solar
# TODO: Integrate Shibboleth login. # TODO: Integrate Shibboleth login.
@@ -27,6 +33,7 @@ config.read('config.ini')
config = config['DEFAULT'] config = config['DEFAULT']
SERVER_NAME = config['SERVER_NAME'] SERVER_NAME = config['SERVER_NAME']
ROUTE_PREFIX = config['ROUTE_PREFIX']
MAIL_HOST = config['MAIL_HOST'] MAIL_HOST = config['MAIL_HOST']
MAIL_LOGIN = config['MAIL_LOGIN'] MAIL_LOGIN = config['MAIL_LOGIN']
MAIL_PASS = config['MAIL_PASS'] MAIL_PASS = config['MAIL_PASS']
@@ -50,6 +57,8 @@ if not UPLOADS_DIR.exists:
# Override configs with environment variables, if set # Override configs with environment variables, if set
if 'PORTALDS4DS1_SERVER_NAME' in os.environ: if 'PORTALDS4DS1_SERVER_NAME' in os.environ:
SERVER_NAME = os.environ['PORTALDS4DS1_SERVER_NAME'] SERVER_NAME = os.environ['PORTALDS4DS1_SERVER_NAME']
if 'PORTALDS4DS1_ROUTE_PREFIX' in os.environ:
ROUTE_PREFIX = os.environ['PORTALDS4DS1_ROUTE_PREFIX']
if 'PORTALDS4DS1_MAIL_HOST' in os.environ: if 'PORTALDS4DS1_MAIL_HOST' in os.environ:
MAIL_HOST = os.environ['PORTALDS4DS1_MAIL_HOST'] MAIL_HOST = os.environ['PORTALDS4DS1_MAIL_HOST']
if 'PORTALDS4DS1_MAIL_LOGIN' in os.environ: if 'PORTALDS4DS1_MAIL_LOGIN' in os.environ:
@@ -80,7 +89,8 @@ if 'PORTALDS4DS1_SQL_CONN_STR' in os.environ:
###################### ######################
app = Flask(__name__) app = Flask(__name__, static_url_path = ROUTE_PREFIX + '/static')
#app = Flask(__name__)
app.config.update( app.config.update(
SERVER_NAME = SERVER_NAME, SERVER_NAME = SERVER_NAME,
@@ -129,11 +139,11 @@ def redirect_url(default='/'):
url_for(default) url_for(default)
@app.route('/') @app.route(ROUTE_PREFIX + '/')
def index(): def index():
if current_user.is_authenticated: if current_user.is_authenticated:
return redirect('/oddaja') return redirect(ROUTE_PREFIX + '/oddaja/')
return redirect('/login') return redirect(ROUTE_PREFIX + '/login/')
@login_manager.user_loader @login_manager.user_loader
@@ -142,17 +152,17 @@ def load_user(user_id):
return user return user
@app.route('/login') @app.route(ROUTE_PREFIX + '/login')
def solar_login_get(): def solar_login_get():
return render_template('solar-login.html') return render_template('solar-login.html', ROUTE_PREFIX=ROUTE_PREFIX)
@app.route('/register') @app.route(ROUTE_PREFIX + '/register')
def solar_register_get(): def solar_register_get():
return render_template('solar-register.html') return render_template('solar-register.html', ROUTE_PREFIX=ROUTE_PREFIX)
@app.route('/login', methods=['POST']) @app.route(ROUTE_PREFIX + '/login', methods=['POST'])
def solar_login_post(): def solar_login_post():
email = request.form.get('email') email = request.form.get('email')
password = request.form.get('password') password = request.form.get('password')
@@ -162,19 +172,19 @@ def solar_login_post():
if not user or not check_password_hash(user.pass_hash, password): if not user or not check_password_hash(user.pass_hash, password):
flash('Napačni podatki za prijavo. Poskusite ponovno.') flash('Napačni podatki za prijavo. Poskusite ponovno.')
return redirect('/login') return redirect(ROUTE_PREFIX + '/login/')
if not user.active: if not user.active:
flash('Vaš uporabniški račun še ni bil aktiviran.') flash('Vaš uporabniški račun še ni bil aktiviran.')
return redirect('/login') return redirect(ROUTE_PREFIX + '/login/')
#portal.solar.add_user_session(user.id) #portal.solar.add_user_session(user.id)
login_user(user, remember=remember) login_user(user, remember=remember)
return redirect('/oddaja') return redirect(ROUTE_PREFIX + '/oddaja/')
@app.route('/register', methods=['POST']) @app.route(ROUTE_PREFIX + '/register', methods=['POST'])
def solar_register_post(): def solar_register_post():
name = request.form.get('name') name = request.form.get('name')
email = request.form.get('email') email = request.form.get('email')
@@ -187,38 +197,38 @@ def solar_register_post():
if user: if user:
flash('Uporabniški račun s tem emailom je že registriran.') flash('Uporabniški račun s tem emailom je že registriran.')
return redirect('/register') return redirect(ROUTE_PREFIX + '/register/')
if not name: if not name:
flash('Prazno polje za ime.') flash('Prazno polje za ime.')
return redirect('/register') return redirect(ROUTE_PREFIX + '/register/')
if len(name) > 100: if len(name) > 100:
flash('Predolgo ime.') flash('Predolgo ime.')
return redirect('/register') return redirect(ROUTE_PREFIX + '/register/')
if not email: if not email:
flash('Prazno polje za elektronsko pošto.') flash('Prazno polje za elektronsko pošto.')
return redirect('/register') return redirect(ROUTE_PREFIX + '/register/')
if len(email) > 100: if len(email) > 100:
flash('Predolgi email naslov') flash('Predolgi email naslov')
return redirect('/register') return redirect(ROUTE_PREFIX + '/register/')
elif not re.search(portal.solar.REGEX_EMAIL, email): elif not re.search(portal.solar.REGEX_EMAIL, email):
flash('Email napačnega formata.') flash('Email napačnega formata.')
return redirect('/register') return redirect(ROUTE_PREFIX + '/register/')
if not password: if not password:
flash('Prazno polje za geslo.') flash('Prazno polje za geslo.')
return redirect('/register') return redirect(ROUTE_PREFIX + '/register/')
if len(password) < 8: if len(password) < 8:
flash('Geslo mora biti vsaj 8 znakov dolgo.') flash('Geslo mora biti vsaj 8 znakov dolgo.')
return redirect('/register') return redirect(ROUTE_PREFIX + '/register/')
if len(password) > 100: if len(password) > 100:
flash('Predolgo geslo.') flash('Predolgo geslo.')
return redirect('/register') return redirect(ROUTE_PREFIX + '/register/')
if institution_role not in ['coordinator', 'mentor', 'other']: if institution_role not in ['coordinator', 'mentor', 'other']:
flash('Neveljavna vloga v instituciji.') flash('Neveljavna vloga v instituciji.')
return redirect('/register') return redirect(ROUTE_PREFIX + '/register/')
if not institution: if not institution:
institution_id = portal.solar.add_institution(institution_name, "") institution_id = portal.solar.add_institution(institution_name, "")
@@ -229,20 +239,22 @@ def solar_register_post():
user_id = portal.solar.register_new_user(name, email, password, active=False) user_id = portal.solar.register_new_user(name, email, password, active=False)
portal.solar.add_user_to_institution(user_id, institution_id, institution_role) portal.solar.add_user_to_institution(user_id, institution_id, institution_role)
portal.solar.add_cooperation_history_item(user_id, institution_id, institution_role)
portal.solar.send_admins_new_user_notification_mail(user_id, upload_handler_solar.config) portal.solar.send_admins_new_user_notification_mail(user_id, upload_handler_solar.config)
flash('Podatki so bili poslani v potrditev. Ko bo registracija potrjena, boste o tem obveščeni po e-mailu, ki ste ga posredovali zgoraj.') flash('Podatki so bili poslani v potrditev. Ko bo registracija potrjena, boste o tem obveščeni po e-mailu.')
return redirect('/login') return redirect(ROUTE_PREFIX + '/login/')
@app.route('/logout') @app.route(ROUTE_PREFIX + '/logout')
@login_required @login_required
def logout(): def logout():
logout_user() logout_user()
return redirect('/login') return redirect(ROUTE_PREFIX + '/login/')
@app.route('/<path:text>') @app.route(ROUTE_PREFIX + '/<path:text>')
@login_required @login_required
def solar(text): def solar(text):
is_admin = current_user.role == 'admin' is_admin = current_user.role == 'admin'
@@ -257,6 +269,7 @@ def solar(text):
if text.startswith('oddaja/') or text == 'oddaja': if text.startswith('oddaja/') or text == 'oddaja':
return render_template('solar-oddaja.html', return render_template('solar-oddaja.html',
ROUTE_PREFIX=ROUTE_PREFIX,
is_admin=is_admin, is_admin=is_admin,
institution=current_user_institution, institution=current_user_institution,
institution_contract=institution_contract, institution_contract=institution_contract,
@@ -275,7 +288,8 @@ def solar(text):
else: else:
institution_names.append(institution.name) institution_names.append(institution.name)
return render_template('solar-zgodovina.html', upload_history=upload_items, uploader_names=uploader_names, return render_template('solar-zgodovina.html', upload_history=upload_items, uploader_names=uploader_names,
institution_names=institution_names, is_admin=is_admin, is_institution_coordinator=current_user_institution_coordinator) institution_names=institution_names, is_admin=is_admin, is_institution_coordinator=current_user_institution_coordinator,
ROUTE_PREFIX=ROUTE_PREFIX)
elif text.startswith('pogodbe-institucije/') or text.startswith('pogodbe-ucencistarsi/'): elif text.startswith('pogodbe-institucije/') or text.startswith('pogodbe-ucencistarsi/'):
# Check for download contract request. # Check for download contract request.
match = re.match('^pogodbe-(institucije|ucencistarsi)/([a-z0-9_]+\.pdf)$', text) match = re.match('^pogodbe-(institucije|ucencistarsi)/([a-z0-9_]+\.pdf)$', text)
@@ -304,52 +318,66 @@ def solar(text):
enable_upload_school_contract = False enable_upload_school_contract = False
show_upload_form = False show_upload_form = False
collaborators = [] collaborators = []
institution_id = ""
cooperation_history = dict() cooperation_history = dict()
if current_user_institution: if current_user_institution:
collaborators = portal.solar.get_all_active_institution_users(current_user_institution.id) collaborators = portal.solar.get_all_active_institution_users(current_user_institution.id)
show_upload_form = True show_upload_form = True
contract_school = portal.solar.get_institution_contract(current_user_institution.id) contract_school = portal.solar.get_institution_contract(current_user_institution.id)
cooperation_history = portal.solar.get_institution_cooperation_history(current_user_institution.id) cooperation_history = portal.solar.get_institution_cooperation_history(current_user_institution.id)
institution_id = current_user_institution.id
if portal.solar.is_institution_coordinator(current_user_obj.id, current_user_institution.id): if portal.solar.is_institution_coordinator(current_user_obj.id, current_user_institution.id):
contracts_students = portal.solar.get_institution_student_contracts(current_user_institution.id) contracts_students = portal.solar.get_institution_student_contracts(current_user_institution.id)
enable_upload_school_contract = True enable_upload_school_contract = True
else: else:
contracts_students = portal.solar.get_institution_student_contracts(current_user_institution.id, current_user_obj.id) contracts_students = portal.solar.get_institution_student_contracts(current_user_institution.id, current_user_obj.id)
return render_template('solar-pogodbe.html', contracts_students=contracts_students, return render_template('solar-pogodbe.html',
ROUTE_PREFIX=ROUTE_PREFIX,
contracts_students=contracts_students,
contract_school=contract_school, contract_school=contract_school,
enable_upload_school_contract=enable_upload_school_contract, enable_upload_school_contract=enable_upload_school_contract,
show_upload_form=show_upload_form, show_upload_form=show_upload_form,
collaborators=collaborators, collaborators=collaborators,
cooperation_history=cooperation_history, cooperation_history=cooperation_history,
user_id=current_user.id, user_id=current_user.id,
institution_id=institution_id,
is_admin=is_admin, is_institution_coordinator=current_user_institution_coordinator) is_admin=is_admin, is_institution_coordinator=current_user_institution_coordinator)
elif text.startswith('admin/') or text == 'admin': elif text.startswith('admin/') or text == 'admin':
users = portal.solar.get_all_users_join_institutions() users = portal.solar.get_all_users_join_institutions()
inactive_users = portal.solar.get_all_users_join_institutions(active=False) inactive_users = portal.solar.get_all_users_join_institutions(active=False)
solar_institutions = portal.solar.get_all_institutions() solar_institutions = portal.solar.get_all_institutions()
cooperation_history = portal.solar.get_cooperation_history()
uploads = portal.solar.get_all_upload_history(-1) uploads = portal.solar.get_all_upload_history(-1)
if is_admin: if is_admin:
return render_template('solar-admin.html', users=users, user_cooperation_history=cooperation_history, return render_template('solar-admin.html', ROUTE_PREFIX=ROUTE_PREFIX, users=users,
institutions=solar_institutions, inactive_users=inactive_users, uploads=uploads) institutions=solar_institutions, inactive_users=inactive_users, uploads=uploads)
elif text.startswith('manage-institution/') or text == 'manage-institution': elif text.startswith('manage-institution/') or text == 'manage-institution':
if portal.solar.is_institution_coordinator(current_user.id, current_user_institution.id): if portal.solar.is_institution_coordinator(current_user.id, current_user_institution.id):
solar_users = portal.solar.get_all_active_users() solar_users = portal.solar.get_all_active_users()
institution_users = portal.solar.get_all_active_institution_users(current_user_institution.id) institution_users = portal.solar.get_all_active_institution_users(current_user_institution.id)
return render_template('solar-manage-institution.html', users=solar_users,
institution_users=institution_users) role_map = dict()
for institution_user in institution_users:
role_map[institution_user.id] = portal.solar.get_user_institution_role_str(institution_user.id, current_user_institution.id)
return render_template('solar-manage-institution.html',
ROUTE_PREFIX=ROUTE_PREFIX,
institution=current_user_institution,
users=solar_users,
institution_users=institution_users,
role_map=role_map)
return '', 404 return '', 404
@app.route('/pogodbe', methods=['POST']) @app.route(ROUTE_PREFIX + '/pogodbe', methods=['POST'])
@login_required @login_required
def solar_upload_contract(): def solar_upload_contract():
msg = upload_handler_solar.handle_contract_upload(request, current_user.get_id()) msg = upload_handler_solar.handle_contract_upload(request, current_user.get_id())
flash(msg) flash(msg)
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
@app.route('/adduser', methods=['POST']) @app.route(ROUTE_PREFIX + '/adduser', methods=['POST'])
@login_required @login_required
def solar_add_user(): def solar_add_user():
@@ -362,41 +390,41 @@ def solar_add_user():
if not name: if not name:
flash('Prazno polje za ime.') flash('Prazno polje za ime.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
if len(name) > 100: if len(name) > 100:
flash('Predolgo ime.') flash('Predolgo ime.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
if not email: if not email:
flash('Prazno polje za elektronsko pošto.') flash('Prazno polje za elektronsko pošto.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
if len(email) > 100: if len(email) > 100:
flash('Predolg email naslov.') flash('Predolg email naslov.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
elif not re.search(portal.solar.REGEX_EMAIL, email): elif not re.search(portal.solar.REGEX_EMAIL, email):
flash('Email napačnega formata.') flash('Email napačnega formata.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
if not password: if not password:
flash('Prazno polje za geslo.') flash('Prazno polje za geslo.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
if len(password) > 100: if len(password) > 100:
flash('Predolgo geslo.') flash('Predolgo geslo.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
user = portal.solar.get_user_obj_by_email(email) user = portal.solar.get_user_obj_by_email(email)
if user: if user:
#portal.solar.undo_remove_user(user.id) #portal.solar.undo_remove_user(user.id)
flash('Uporabnik s tem emailom je že vnešen v sistem.') flash('Uporabnik s tem emailom je že vnešen v sistem.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
portal.solar.register_new_user(name, email, password) portal.solar.register_new_user(name, email, password)
flash('Uporabnik je bil uspešno dodan.') flash('Uporabnik je bil uspešno dodan.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
@app.route('/activateuser', methods=['POST']) @app.route(ROUTE_PREFIX + '/activateuser', methods=['POST'])
@login_required @login_required
def solar_activate_user(): def solar_activate_user():
if not portal.solar.is_admin(current_user.id): if not portal.solar.is_admin(current_user.id):
@@ -405,7 +433,7 @@ def solar_activate_user():
user_id = request.form.get('id') user_id = request.form.get('id')
if not user_id: if not user_id:
flash('Prazno polje za ID uporabnika.') flash('Prazno polje za ID uporabnika.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
rowcount = portal.solar.activate_user(user_id) rowcount = portal.solar.activate_user(user_id)
if rowcount == 0: if rowcount == 0:
@@ -414,35 +442,35 @@ def solar_activate_user():
portal.solar.send_user_activation_mail(user_id, upload_handler_solar.config) portal.solar.send_user_activation_mail(user_id, upload_handler_solar.config)
flash('Uporabnik je bil aktiviran.') flash('Uporabnik je bil aktiviran.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
@app.route('/forgotpass') @app.route(ROUTE_PREFIX + '/forgotpass')
def solar_forgotpass(): def solar_forgotpass():
return render_template('solar-forgotpass.html') return render_template('solar-forgotpass.html', ROUTE_PREFIX=ROUTE_PREFIX)
@app.route('/sendresetpass', methods=['POST']) @app.route(ROUTE_PREFIX + '/sendresetpass', methods=['POST'])
def solar_sendresetpass(): def solar_sendresetpass():
email = request.form.get('email') email = request.form.get('email')
portal.solar.send_resetpass_mail(email, upload_handler_solar.config) portal.solar.send_resetpass_mail(email, upload_handler_solar.config)
flash('Povezava za ponastavitev gesla je bila poslana na vpisani e-naslov.') flash('Povezava za ponastavitev gesla je bila poslana na vpisani e-naslov.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
@app.route('/resetpass/<token>') @app.route(ROUTE_PREFIX + '/resetpass/<token>')
def solar_resetpass(token): def solar_resetpass(token):
user = portal.solar.verify_reset_token(token, upload_handler_solar.config['APP_SECRET_KEY']) user = portal.solar.verify_reset_token(token, upload_handler_solar.config['APP_SECRET_KEY'])
if not user: if not user:
return '', 404 return '', 404
return render_template('solar-resetpass.html', user=user, token=token) return render_template('solar-resetpass.html',ROUTE_PREFIX=ROUTE_PREFIX, user=user, token=token)
@app.route('/resetpass/<token>', methods=['POST']) @app.route(ROUTE_PREFIX + '/resetpass/<token>', methods=['POST'])
def solar_resetpass_post(token): def solar_resetpass_post(token):
new_password = request.form.get('new_password') new_password = request.form.get('new_password')
user = portal.solar.verify_reset_token(token, upload_handler_solar.config['APP_SECRET_KEY']) user = portal.solar.verify_reset_token(token, upload_handler_solar.config['APP_SECRET_KEY'])
@@ -455,28 +483,33 @@ def solar_resetpass_post(token):
return '', 404 return '', 404
flash('Ponastavitev gesla je bila uspešna.') flash('Ponastavitev gesla je bila uspešna.')
return redirect('/login') return redirect(ROUTE_PREFIX + '/login/')
@app.route('/topuploads') @app.route(ROUTE_PREFIX + '/topuploads')
@login_required @login_required
def solar_topuploads(): def solar_topuploads():
return jsonify(portal.solar.get_top_uploading_institutions()) return jsonify(portal.solar.get_top_uploading_institutions())
@app.route('/topuploads-institution/<institution_id>') @app.route(ROUTE_PREFIX + '/topuploads-institution/<institution_id>')
@login_required @login_required
def solar_topuploads_institution(institution_id): def solar_topuploads_institution(institution_id):
return jsonify(portal.solar.get_top_uploading_users(institution_id)) return jsonify(portal.solar.get_top_uploading_users(institution_id))
@app.route('/uploadstats-institution/<institution_id>') @app.route(ROUTE_PREFIX + '/uploadstats-institution/<institution_id>')
@login_required @login_required
def solar_uploadstats_institution(institution_id): def solar_uploadstats_institution(institution_id):
return jsonify(portal.solar.get_institution_upload_stats(institution_id)) return jsonify(portal.solar.get_institution_upload_stats(institution_id))
@app.route(ROUTE_PREFIX + '/uploadstats-per-region')
@login_required
def solar_uploadstats_per_region():
return jsonify(portal.solar.get_region_stats())
@app.route('/deluser', methods=['POST'])
@app.route(ROUTE_PREFIX + '/deluser', methods=['POST'])
@login_required @login_required
def solar_del_user(): def solar_del_user():
if not portal.solar.is_admin(current_user.id): if not portal.solar.is_admin(current_user.id):
@@ -484,9 +517,9 @@ def solar_del_user():
user_id = request.form.get('user_id') user_id = request.form.get('user_id')
portal.solar.remove_user(user_id) portal.solar.remove_user(user_id)
flash('Uporabnik je bil odstranjen.') flash('Uporabnik je bil odstranjen.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
@app.route('/addinstitution', methods=['POST']) @app.route(ROUTE_PREFIX + '/addinstitution', methods=['POST'])
@login_required @login_required
def add_institution(): def add_institution():
if not portal.solar.is_admin(current_user.id): if not portal.solar.is_admin(current_user.id):
@@ -497,21 +530,21 @@ def add_institution():
if not name: if not name:
flash('Prazno polje za naziv.') flash('Prazno polje za naziv.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
if len(name) > 100: if len(name) > 100:
flash('Predolgo ime.') flash('Predolgo ime.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
if not region in portal.solar.VALID_REGIONS: if not region in portal.solar.VALID_REGIONS:
flash('Neveljavna vrednost za regijo.') flash('Neveljavna vrednost za regijo.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
institution_id = portal.solar.add_institution(name, region) institution_id = portal.solar.add_institution(name, region)
portal.solar.grant_institution_corpus_access(institution_id, "solar") # TODO: throw out portal.solar.grant_institution_corpus_access(institution_id, "solar") # TODO: throw out
flash('Institucija je bila dodana.') flash('Institucija je bila dodana.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
@app.route('/mergeinstitutions', methods=['POST']) @app.route(ROUTE_PREFIX + '/mergeinstitutions', methods=['POST'])
@login_required @login_required
def merge_institutions(): def merge_institutions():
if not portal.solar.is_admin(current_user.id): if not portal.solar.is_admin(current_user.id):
@@ -522,18 +555,18 @@ def merge_institutions():
if not id_from or not id_to: if not id_from or not id_to:
flash('Prazno polje.') flash('Prazno polje.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
institution_from = portal.solar.get_institution_obj(id_from) institution_from = portal.solar.get_institution_obj(id_from)
institution_to = portal.solar.get_institution_obj(id_to) institution_to = portal.solar.get_institution_obj(id_to)
if not institution_from: if not institution_from:
flash('Institucija z ID "{}" ne obstaja.'.format(id_from)) flash('Institucija z ID "{}" ne obstaja.'.format(id_from))
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
if not institution_to: if not institution_to:
flash('Institucija z ID "{}" ne obstaja.'.format(id_to)) flash('Institucija z ID "{}" ne obstaja.'.format(id_to))
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
portal.solar.transfer_users_institution(institution_from.id, institution_to.id) portal.solar.transfer_users_institution(institution_from.id, institution_to.id)
@@ -542,45 +575,45 @@ def merge_institutions():
portal.solar.remove_institution(institution_from.id) portal.solar.remove_institution(institution_from.id)
flash('Instituciji uspešno združeni') flash('Instituciji uspešno združeni')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
@app.route('/addcooperationhistoryitem', methods=['POST']) #@app.route(ROUTE_PREFIX + '/addcooperationhistoryitem', methods=['POST'])
@login_required #@login_required
def add_cooperation_history_item(): #def add_cooperation_history_item():
if not portal.solar.is_admin(current_user.id): # if not portal.solar.is_admin(current_user.id):
return '', 404 # return '', 404
#
# user_id = request.form.get('user')
# institution_id = request.form.get('institution')
# role = request.form.get('role')
# school_year = request.form.get('school-year')
# badge_text = request.form.get('badge-text')
#
# user = portal.solar.get_user_obj(user_id)
# institution = portal.solar.get_institution_obj(institution_id)
#
# if not user:
# flash('Uporabnik s tem ID-jem ne obstaja.')
# return redirect(ROUTE_PREFIX + redirect_url())
#
# if not institution:
# flash('Institucija s tem ID-jem ne obstaja.')
# return redirect(ROUTE_PREFIX + redirect_url())
#
# if not role in ['coordinator', 'mentor', 'other']:
# flash('Neveljavna vloga "{}".'.format(role))
# return redirect(ROUTE_PREFIX + redirect_url())
#
# if not school_year or not re.match('[0-9]{4}/[0-9]{2}', school_year):
# flash('Šolsko leto mora biti formata "2021/22".')
# return redirect(ROUTE_PREFIX + redirect_url())
#
# portal.solar.add_cooperation_history_item(user_id, institution_id, role, school_year, badge_text)
#
# flash('Vnos dodan.')
# return redirect(ROUTE_PREFIX + redirect_url())
user_id = request.form.get('user') @app.route(ROUTE_PREFIX + '/updateuploaditem', methods=['POST'])
institution_id = request.form.get('institution')
role = request.form.get('role')
school_year = request.form.get('school-year')
badge_text = request.form.get('badge-text')
user = portal.solar.get_user_obj(user_id)
institution = portal.solar.get_institution_obj(institution_id)
if not user:
flash('Uporabnik s tem ID-jem ne obstaja.')
return redirect(redirect_url())
if not institution:
flash('Institucija s tem ID-jem ne obstaja.')
return redirect(redirect_url())
if not role in ['coordinator', 'mentor', 'other']:
flash('Neveljavna vloga "{}".'.format(role))
return redirect(redirect_url())
if not school_year or not re.match('[0-9]{4}/[0-9]{2}', school_year):
flash('Šolsko leto mora biti formata "2021/22".')
return redirect(redirect_url())
portal.solar.add_cooperation_history_item(user_id, institution_id, role, school_year, badge_text)
flash('Vnos dodan.')
return redirect(redirect_url())
@app.route('/updateuploaditem', methods=['POST'])
@login_required @login_required
def update_upload_item(): def update_upload_item():
if not portal.solar.is_admin(current_user.id): if not portal.solar.is_admin(current_user.id):
@@ -589,7 +622,7 @@ def update_upload_item():
err_msg = portal.solar.UploadHandlerSolar.check_form(request.form) err_msg = portal.solar.UploadHandlerSolar.check_form(request.form)
if err_msg: if err_msg:
flash(err_msg) flash(err_msg)
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
item_id = request.form.get('item-id') item_id = request.form.get('item-id')
program = request.form.get('program') program = request.form.get('program')
@@ -616,22 +649,22 @@ def update_upload_item():
return '', 404 return '', 404
flash('Vnos spremenjen.') flash('Vnos spremenjen.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
@app.route('/delcooperationhistoryitem', methods=['POST']) #@app.route(ROUTE_PREFIX + '/delcooperationhistoryitem', methods=['POST'])
@login_required #@login_required
def del_cooperation_history_item(): #def del_cooperation_history_item():
if not portal.solar.is_admin(current_user.id): # if not portal.solar.is_admin(current_user.id):
return '', 404 # return '', 404
#
# entry_id = request.form.get('entry-id')
# portal.solar.del_cooperation_history_item(entry_id)
#
# flash('Vnos odstranjen.')
# return redirect(ROUTE_PREFIX + redirect_url())
entry_id = request.form.get('entry-id') @app.route(ROUTE_PREFIX + '/changeinstitutiondata', methods=['POST'])
portal.solar.del_cooperation_history_item(entry_id)
flash('Vnos odstranjen.')
return redirect(redirect_url())
@app.route('/changeinstitutiondata', methods=['POST'])
@login_required @login_required
def change_institution_data(): def change_institution_data():
if not portal.solar.is_admin(current_user.id): if not portal.solar.is_admin(current_user.id):
@@ -643,21 +676,21 @@ def change_institution_data():
if not new_name: if not new_name:
flash('Prazno polje za naziv.') flash('Prazno polje za naziv.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
if len(new_name) > 100: if len(new_name) > 100:
flash('Predolgo ime.') flash('Predolgo ime.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
if not new_region in portal.solar.VALID_REGIONS: if not new_region in portal.solar.VALID_REGIONS:
flash('Neveljavna vrednost za regijo.') flash('Neveljavna vrednost za regijo.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
portal.solar.update_institution_data(institution_id, new_name, new_region) portal.solar.update_institution_data(institution_id, new_name, new_region)
flash('Podatki institucije so bili spremenjeni.') flash('Podatki institucije so bili spremenjeni.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
@app.route('/changeuseremail', methods=['POST']) @app.route(ROUTE_PREFIX + '/changeuseremail', methods=['POST'])
@login_required @login_required
def change_user_email(): def change_user_email():
if not portal.solar.is_admin(current_user.id): if not portal.solar.is_admin(current_user.id):
@@ -668,17 +701,43 @@ def change_user_email():
if not re.search(portal.solar.REGEX_EMAIL, email): if not re.search(portal.solar.REGEX_EMAIL, email):
flash('Email napačnega formata.') flash('Email napačnega formata.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
portal.solar.update_user_email(user_id, email) portal.solar.update_user_email(user_id, email)
flash('Email spremenjen.') flash('Email spremenjen.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
@app.route(ROUTE_PREFIX + '/changeuserrole-institution', methods=['POST'])
@login_required
def change_user_role_institution():
institution = portal.solar.get_user_institution(current_user.id)
if not portal.solar.is_admin(current_user.id):
# Institution coordinators can only assign roles of users in their own
# institution.
if institution and portal.solar.is_institution_coordinator(current_user.id, institution.id):
pass
else:
return '', 404
user_id = request.form.get('user-id')
role = request.form.get('role')
if role not in ['coordinator', 'mentor', 'other']:
flash('Neveljavna vloga.')
return redirect(ROUTE_PREFIX + redirect_url())
portal.solar.update_user_institution_role(user_id, institution.id, role)
portal.solar.add_cooperation_history_item(user_id, institution.id, role)
flash('Vloga v instituciji spremenjena.')
return redirect(ROUTE_PREFIX + redirect_url())
@app.route('/changeuserrole', methods=['POST']) @app.route(ROUTE_PREFIX + '/changeuserrole', methods=['POST'])
@login_required @login_required
def change_user_role(): def change_user_role():
institution = portal.solar.get_user_institution(current_user.id)
if not portal.solar.is_admin(current_user.id): if not portal.solar.is_admin(current_user.id):
return '', 404 return '', 404
@@ -687,14 +746,14 @@ def change_user_role():
if not role in ['admin', 'user']: if not role in ['admin', 'user']:
flash('Neveljavna vloga.') flash('Neveljavna vloga.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
portal.solar.update_user_role(user_id, role) portal.solar.update_user_role(user_id, role)
flash('Vloga spremenjena.') flash('Vloga spremenjena.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
@app.route('/changeusername', methods=['POST']) @app.route(ROUTE_PREFIX + '/changeusername', methods=['POST'])
@login_required @login_required
def change_user_name(): def change_user_name():
if not portal.solar.is_admin(current_user.id): if not portal.solar.is_admin(current_user.id):
@@ -706,9 +765,9 @@ def change_user_name():
portal.solar.update_user_name(user_id, name) portal.solar.update_user_name(user_id, name)
flash('Ime in priimek spremenjena.') flash('Ime in priimek spremenjena.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
@app.route('/addusertoinstitution', methods=['POST']) @app.route(ROUTE_PREFIX + '/addusertoinstitution', methods=['POST'])
@login_required @login_required
def add_user_institution_mapping(): def add_user_institution_mapping():
institution_id = request.form.get('institution_id') institution_id = request.form.get('institution_id')
@@ -717,7 +776,7 @@ def add_user_institution_mapping():
if institution: if institution:
institution_id = institution.id institution_id = institution.id
if not (portal.solar.is_admin(current_user.id) or portal.solar.is_institution_coordinator(current_user.id, institution_id)): if not portal.solar.is_admin(current_user.id):
return '', 404 return '', 404
user_id = request.form['user_id'] user_id = request.form['user_id']
@@ -727,38 +786,39 @@ def add_user_institution_mapping():
if portal.solar.get_user_institution(user_id): if portal.solar.get_user_institution(user_id):
flash('Uporabnik je že dodeljen instituciji.') flash('Uporabnik je že dodeljen instituciji.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
portal.solar.add_user_to_institution(user_id, institution_id, role) portal.solar.add_user_to_institution(user_id, institution_id, role)
portal.solar.add_cooperation_history_item(user_id, institution_id, role)
flash('Uporabnik je bil dodeljen instituciji.') flash('Uporabnik je bil dodeljen instituciji.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
@app.route('/deluserfrominstitution', methods=['POST']) @app.route(ROUTE_PREFIX + '/deluserfrominstitution', methods=['POST'])
@login_required @login_required
def del_user_institution_mapping(): def del_user_institution_mapping():
user_id = request.form['user_id'] user_id = request.form['user_id']
institution = portal.solar.get_user_institution(user_id) institution = portal.solar.get_user_institution(user_id)
if not institution: if not institution:
flash('Uporabnik ni član nobene institucije.') flash('Uporabnik ni član nobene institucije.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
if not portal.solar.is_admin(current_user.id) \ if not portal.solar.is_admin(current_user.id) \
and not portal.solar.is_institution_coordinator(current_user.id, institution.id): and not portal.solar.is_institution_coordinator(current_user.id, institution.id):
flash('Nimate ustreznih pravic za odstranitev uporabnika iz institucije.') flash('Nimate ustreznih pravic za odstranitev uporabnika iz institucije.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
portal.solar.del_user_from_institution(user_id, institution.id) portal.solar.del_user_from_institution(user_id, institution.id)
flash('Uporabnik je bil odstranjen iz institucije.') flash('Uporabnik je bil odstranjen iz institucije.')
return redirect(redirect_url()) return redirect(ROUTE_PREFIX + redirect_url())
@app.route('/upload', methods=['POST']) @app.route(ROUTE_PREFIX + '/upload', methods=['POST'])
def handle_upload(): def handle_upload():
if not current_user.is_authenticated: if not current_user.is_authenticated:
return '', 404 return '', 404
return upload_handler_solar.handle_upload(request, current_user.get_id()) return upload_handler_solar.handle_upload(request, current_user.get_id())
@app.route('/getuploadfile/<upload_id>/<file_hash>', methods=['GET']) @app.route(ROUTE_PREFIX + '/getuploadfile/<upload_id>/<file_hash>', methods=['GET'])
@login_required @login_required
def get_upload_file(upload_id, file_hash): def get_upload_file(upload_id, file_hash):
is_admin = current_user.role == 'admin' is_admin = current_user.role == 'admin'
@@ -789,6 +849,80 @@ def get_upload_file(upload_id, file_hash):
except FileNotFoundError: except FileNotFoundError:
return '', 404 return '', 404
@app.route(ROUTE_PREFIX + '/institutionadduser', methods=['POST'])
@login_required
def solar_institution_add_user():
current_user_institution = portal.solar.get_user_institution(current_user.id)
if not portal.solar.is_institution_coordinator(current_user.id, current_user_institution.id):
return '', 404
name = request.form.get('name')
email = request.form.get('email')
role = request.form.get('role')
password=''.join(random.choices(string.ascii_lowercase, k=8))
if not name:
flash('Prazno polje za ime.')
return redirect(ROUTE_PREFIX + redirect_url())
if len(name) > 100:
flash('Predolgo ime.')
return redirect(ROUTE_PREFIX + redirect_url())
if not email:
flash('Prazno polje za elektronsko pošto.')
return redirect(ROUTE_PREFIX + redirect_url())
if len(email) > 100:
flash('Predolg email naslov.')
return redirect(ROUTE_PREFIX + redirect_url())
elif not re.search(portal.solar.REGEX_EMAIL, email):
flash('Email napačnega formata.')
return redirect(ROUTE_PREFIX + redirect_url())
if not password:
flash('Prazno polje za geslo.')
return redirect(ROUTE_PREFIX + redirect_url())
if len(password) > 100:
flash('Predolgo geslo.')
return redirect(ROUTE_PREFIX + redirect_url())
user = portal.solar.get_user_obj_by_email(email)
if user:
#portal.solar.undo_remove_user(user.id)
flash('Uporabnik s tem emailom je že vnešen v sistem.')
return redirect(ROUTE_PREFIX + redirect_url())
new_user_id = portal.solar.register_new_user(name, email, password)
portal.solar.add_user_to_institution(new_user_id, current_user_institution.id, role)
portal.solar.activate_user(new_user_id)
#token za nastaviti geslo
jwt_token = portal.solar.get_password_reset_token(email, config['APP_SECRET_KEY'])
#pošlji email uporabniku
body = '''
Ustvarjen je bil uporabniški račun na Portalu Šolar.
Geslo lahko nastavite na naslednji povezavi: https://{}/resetpass/{}'''.format(config['SERVER_NAME'], jwt_token)
message = MIMEMultipart()
message['From'] = config['MAIL_LOGIN']
message['To'] = email
message['Subject'] = 'Portal Šolar: Ponastavitev gesla'
message.attach(MIMEText(body, "plain"))
text = message.as_string()
# Create a secure SSL context
context = ssl.create_default_context()
try:
with SMTP_SSL(config['MAIL_HOST'], config['SMTP_PORT'], context=context) as server:
server.login(config['MAIL_LOGIN'], config['MAIL_PASS'])
server.sendmail(config['MAIL_LOGIN'], email, text)
except Exception:
traceback.print_exc()
flash('Uporabnik je bil uspešno dodan.')
return redirect(ROUTE_PREFIX + redirect_url())
if __name__ == '__main__': if __name__ == '__main__':
app.run(debug=True) app.run(debug=True)

View File

@@ -1,5 +1,6 @@
[DEFAULT] [DEFAULT]
SERVER_NAME=localhost:5000 SERVER_NAME=localhost:5000
ROUTE_PREFIX=
SQL_CONN_STR=postgresql://portal:randompass123@localhost/portal SQL_CONN_STR=postgresql://portal:randompass123@localhost/portal
MAIL_HOST=posta.cjvt.si MAIL_HOST=posta.cjvt.si
MAIL_LOGIN=oddaja-besedil@cjvt.si MAIL_LOGIN=oddaja-besedil@cjvt.si

View File

@@ -0,0 +1,36 @@
"""Altered cooperation history structure.
Revision ID: 0cf2d8f74766
Revises: c7bb822adf9f
Create Date: 2022-02-14 13:04:01.143637
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '0cf2d8f74766'
down_revision = 'c7bb822adf9f'
branch_labels = None
depends_on = None
def upgrade():
# Delete all rows
query = 'DELETE FROM user_cooperation;'
op.execute(query)
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('user_cooperation', sa.Column('timestamp', sa.DateTime(), nullable=False))
op.drop_column('user_cooperation', 'badge_text')
op.drop_column('user_cooperation', 'school_year')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('user_cooperation', sa.Column('school_year', sa.VARCHAR(), autoincrement=False, nullable=False))
op.add_column('user_cooperation', sa.Column('badge_text', sa.VARCHAR(), autoincrement=False, nullable=True))
op.drop_column('user_cooperation', 'timestamp')
# ### end Alembic commands ###

View File

@@ -71,8 +71,7 @@ class UserCooperationHistory(db.Model):
user = db.Column(db.Integer, sqlalchemy.ForeignKey('registered_user.id'), nullable=False) user = db.Column(db.Integer, sqlalchemy.ForeignKey('registered_user.id'), nullable=False)
institution = db.Column(db.Integer, sqlalchemy.ForeignKey('institution.id'), nullable=False) institution = db.Column(db.Integer, sqlalchemy.ForeignKey('institution.id'), nullable=False)
role = db.Column(db.String, nullable=False) role = db.Column(db.String, nullable=False)
school_year = db.Column(db.String, nullable=False) timestamp = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
badge_text = db.Column(db.String, nullable=True)
class Institution(db.Model): class Institution(db.Model):

View File

@@ -6,6 +6,7 @@ import traceback
import ssl import ssl
from datetime import datetime from datetime import datetime
from sqlalchemy import desc from sqlalchemy import desc
from sqlalchemy import func
from pathlib import Path from pathlib import Path
from smtplib import SMTP_SSL from smtplib import SMTP_SSL
@@ -24,6 +25,7 @@ from werkzeug.security import generate_password_hash
from . model import * from . model import *
VALID_PROGRAMS = {'OS', 'SSG', 'MGP', 'ZG', 'NPI', 'SPI', 'SSI', 'PTI'} VALID_PROGRAMS = {'OS', 'SSG', 'MGP', 'ZG', 'NPI', 'SPI', 'SSI', 'PTI'}
VALID_SUBJECTS = {'SLO', 'DJP', 'DDP', 'DNP', 'DSP', 'DIP'} VALID_SUBJECTS = {'SLO', 'DJP', 'DDP', 'DNP', 'DSP', 'DIP'}
VALID_TEXT_TYPES = {'E', 'PB', 'T', 'R'} VALID_TEXT_TYPES = {'E', 'PB', 'T', 'R'}
@@ -300,7 +302,6 @@ class UploadHandlerSolar():
@staticmethod @staticmethod
def check_form(form): def check_form(form):
logging.info(form)
region = form['regija'] region = form['regija']
program = form['program'] program = form['program']
predmet = form['predmet'] predmet = form['predmet']
@@ -492,6 +493,24 @@ def get_institution_upload_stats(institution_id):
return res return res
def get_region_stats():
ret = {'CE': [0,0], 'GO': [0,0], 'KK': [0,0], 'KP': [0,0], 'KR': [0,0], 'LJ': [0,0], 'MB': [0,0], 'MS': [0,0], 'NM': [0,0], 'PO': [0,0], 'SG': [0,0]}
os = db.session.query(UploadSolar.region, func.count(UploadSolar.id)).filter_by(program="OS").group_by(UploadSolar.region).all()
neos = db.session.query(UploadSolar.region, func.count(UploadSolar.id)).filter(sqlalchemy.not_(UploadSolar.program.contains("OS"))).group_by(UploadSolar.region).all()
#logging.error(os)
#logging.error(neos)
for key, val in os if key in VALID_REGIONS:
ret[key][0] = val
for key, val in neos if key in VALID_REGIONS:
ret[key][1] = val
logging.error(ret)
return ret
def get_all_active_users(): def get_all_active_users():
# TODO: do filtering purely within an SQL query # TODO: do filtering purely within an SQL query
@@ -529,10 +548,10 @@ def get_institution_contract(institution_id):
def get_institution_cooperation_history(institution_id): def get_institution_cooperation_history(institution_id):
return db.session.query(UserCooperationHistory.role, items = db.session.query(UserCooperationHistory.role,
UserCooperationHistory.school_year, UserCooperationHistory.timestamp,
UserCooperationHistory.badge_text, RegisteredUser.id,
RegisteredUser.name, RegisteredUser.name
).select_from( ).select_from(
UserCooperationHistory, UserCooperationHistory,
).join( ).join(
@@ -540,28 +559,59 @@ def get_institution_cooperation_history(institution_id):
UserCooperationHistory.user == RegisteredUser.id, UserCooperationHistory.user == RegisteredUser.id,
).filter( ).filter(
UserCooperationHistory.institution == institution_id, UserCooperationHistory.institution == institution_id,
).order_by(UserCooperationHistory.school_year.desc()).all() ).order_by(UserCooperationHistory.timestamp.desc()).all()
res = []
prev_schoolyear = None
item_buff = []
users_seen = set()
for item in items:
timestamp = item.timestamp
year = timestamp.year
month = timestamp.month
if month >= 9 :
school_year = '{}/{}'.format(year, str(year+1)[-2:])
else:
school_year = '{}/{}'.format(year-1, str(year)[-2:])
if school_year != prev_schoolyear:
if len(item_buff) > 0:
res.append((prev_schoolyear, item_buff))
prev_schoolyear = school_year
item_buff = []
users_seen = set()
if not item.id in users_seen:
users_seen.add(item.id)
item_buff.append(item)
if len(item_buff) > 0:
res.append((prev_schoolyear, item_buff))
return res
def get_cooperation_history(): def get_cooperation_history():
return UserCooperationHistory.query.all() return UserCooperationHistory.query.all()
def add_cooperation_history_item(user_id, institution_id, role, school_year, badge_text): def add_cooperation_history_item(user_id, institution_id, role):
model_obj = UserCooperationHistory( model_obj = UserCooperationHistory(
user=user_id, user=user_id,
institution=institution_id, institution=institution_id,
role=role, role=role,
school_year=school_year, timestamp=datetime.now()
badge_text=badge_text
) )
db.session.add(model_obj) db.session.add(model_obj)
db.session.commit() db.session.commit()
return model_obj.id return model_obj.id
def del_cooperation_history_item(entry_id): #def del_cooperation_history_item(entry_id):
db.session.query(UserCooperationHistory).filter_by(id=entry_id).delete() # db.session.query(UserCooperationHistory).filter_by(id=entry_id).delete()
db.session.commit() # db.session.commit()
def has_user_corpus_access(user_id, corpus_name): def has_user_corpus_access(user_id, corpus_name):
user = RegisteredUser.query.filter_by(id=user_id).first() user = RegisteredUser.query.filter_by(id=user_id).first()
@@ -597,7 +647,6 @@ def get_user_obj_by_email(email):
def get_institution_obj(institution_id): def get_institution_obj(institution_id):
return Institution.query.filter_by(id=institution_id).first() return Institution.query.filter_by(id=institution_id).first()
def get_institution_obj_by_name(institution_name): def get_institution_obj_by_name(institution_name):
return Institution.query.filter_by(name=institution_name).first() return Institution.query.filter_by(name=institution_name).first()
@@ -666,6 +715,12 @@ def update_user_role(user_id, role):
return rowcount return rowcount
def update_user_institution_role(user_id, institution_id, role):
rowcount = db.session.query(UserInstitutionMapping).filter_by(user=user_id, institution=institution_id).update({'role': role})
db.session.commit()
return rowcount
def update_user_email(user_id, new_email): def update_user_email(user_id, new_email):
rowcount = db.session.query(RegisteredUser).filter_by(id=user_id).update({'email': new_email}) rowcount = db.session.query(RegisteredUser).filter_by(id=user_id).update({'email': new_email})
db.session.commit() db.session.commit()
@@ -708,6 +763,22 @@ def del_user_from_institution(user_id, institution_id):
db.session.commit() db.session.commit()
def get_user_institution_role_str(user_id, institution_id):
res = UserInstitutionMapping.query.filter_by(
user=user_id
).filter_by(
institution=institution_id
).first()
if not res:
return ''
role_str_map = {
'coordinator': 'Koordinator/-ka',
'mentor': 'Mentor/-ica',
'other': 'Druga vloga'
}
return role_str_map[res.role]
def get_all_active_users(): def get_all_active_users():
return RegisteredUser.query.filter_by(active=True).order_by(RegisteredUser.id).all() return RegisteredUser.query.filter_by(active=True).order_by(RegisteredUser.id).all()
@@ -722,7 +793,6 @@ def get_all_users_join_institutions(active=True):
RegisteredUser.id == UserInstitutionMapping.user).filter(RegisteredUser.active == active).order_by(RegisteredUser.id).all() RegisteredUser.id == UserInstitutionMapping.user).filter(RegisteredUser.active == active).order_by(RegisteredUser.id).all()
def get_all_active_institution_users(institution_id): def get_all_active_institution_users(institution_id):
return RegisteredUser.query.filter_by(active=True).join(UserInstitutionMapping, return RegisteredUser.query.filter_by(active=True).join(UserInstitutionMapping,
RegisteredUser.id == UserInstitutionMapping.user).filter(UserInstitutionMapping.institution == institution_id).all() RegisteredUser.id == UserInstitutionMapping.user).filter(UserInstitutionMapping.institution == institution_id).all()
@@ -759,9 +829,11 @@ def get_actual_studentparent_contract_filename(f_hash):
def get_password_reset_token(email, key, expires=600): def get_password_reset_token(email, key, expires=600):
return jwt.encode({'reset_password': email, token = jwt.encode({'reset_password': email,
'exp': int(time.time()) + expires}, 'exp': int(time.time()) + expires},
key=key, algorithm='HS256') key=key, algorithm='HS256')
logging.error(token)
return token
def transfer_users_institution(institution_id_from, institution_id_to): def transfer_users_institution(institution_id_from, institution_id_to):
@@ -810,7 +882,7 @@ def send_resetpass_mail(email, config):
message = MIMEMultipart() message = MIMEMultipart()
message['From'] = config['MAIL_LOGIN'] message['From'] = config['MAIL_LOGIN']
message['To'] = email message['To'] = email
message['Subject'] = 'Ponastavitev gesla' message['Subject'] = 'Portal Šolar: Ponastavitev gesla'
message.attach(MIMEText(body, "plain")) message.attach(MIMEText(body, "plain"))
text = message.as_string() text = message.as_string()
@@ -859,7 +931,7 @@ def send_user_activation_mail(user_id, config):
message = MIMEMultipart() message = MIMEMultipart()
message['From'] = config['MAIL_LOGIN'] message['From'] = config['MAIL_LOGIN']
message['To'] = user.email message['To'] = user.email
message['Subject'] = 'Ponastavitev gesla' message['Subject'] = 'Portal Šolar: Vaš uporabniški račun je odobren'
message.attach(MIMEText(body, "plain")) message.attach(MIMEText(body, "plain"))
text = message.as_string() text = message.as_string()

View File

@@ -171,4 +171,55 @@ p.subtitle {
line-height: 150%; line-height: 150%;
margin-top: 0.5rem; } margin-top: 0.5rem; }
/* Style The Dropdown Button */
.dropbtn {
color: white;
line-height: 4rem;
border: none;
cursor: pointer;
background: none;
padding: 0 1rem; }
.dropbtn img {
position: relative;
top: 0.75rem; }
/* The container <div> - needed to position the dropdown content */
.dropdown {
margin-right: 1rem;
float: right;
display: inline-block;
position: relative; }
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display: none;
position: absolute;
right: 0;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1; }
/* Links inside the dropdown */
.dropdown-content a {
color: #848C90;
padding: 0.5rem 1rem;
text-decoration: none;
display: block; }
.dropdown-content a:hover {
background-color: #f1f1f1;
cursor: pointer; }
.dropdown-content hr {
margin-top: 0;
margin-bottom: 0;
border-top: 1px solid #B6BEC3; }
/* Show the dropdown menu on hover */
.dropdown:hover .dropdown-content {
display: block; }
/* Change the background color of the dropdown button when the dropdown content is shown */
.dropdown:hover .dropbtn {
background: rgba(0, 0, 0, 0.2); }
/*# sourceMappingURL=header.css.map */ /*# sourceMappingURL=header.css.map */

View File

@@ -1,6 +1,6 @@
{ {
"version": 3, "version": 3,
"mappings": "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", "mappings": "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",
"sources": ["slovenscina-theme.scss","slovenscina-elements.scss","header.scss"], "sources": ["slovenscina-theme.scss","slovenscina-elements.scss","header.scss"],
"names": [], "names": [],
"file": "header.css" "file": "header.css"

View File

@@ -68,3 +68,67 @@ p.subtitle {
line-height: 150%; line-height: 150%;
margin-top:0.5rem; margin-top:0.5rem;
} }
/* Style The Dropdown Button */
.dropbtn {
color: white;
line-height:4rem;
border: none;
cursor: pointer;
background:none;
padding:0 1rem;
img {
position:relative;
top:0.75rem;
}
}
/* The container <div> - needed to position the dropdown content */
.dropdown {
margin-right:1rem;
float:right;
display: inline-block;
position:relative;
}
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display: none;
position: absolute;
right:0;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
/* Links inside the dropdown */
.dropdown-content {
a {
color: $grey-dark;
padding: 0.5rem 1rem;
text-decoration: none;
display: block;
&:hover {
background-color: #f1f1f1;
cursor:pointer;
}
}
hr {
margin-top:0;
margin-bottom:0;
border-top: 1px solid $grey-border;
}
}
/* Show the dropdown menu on hover */
.dropdown:hover .dropdown-content {
display: block;
}
/* Change the background color of the dropdown button when the dropdown content is shown */
.dropdown:hover .dropbtn {
background:rgba(0,0,0,0.2);
}

View File

@@ -168,6 +168,8 @@ em {
position: relative; position: relative;
height: 3.125rem; height: 3.125rem;
border-bottom: 1px solid #848C90; } border-bottom: 1px solid #848C90; }
.history-item .history-item-files-full .file-item:last-child {
border-bottom: none; }
.history-item .history-item-files-full .file-item .file-icon { .history-item .history-item-files-full .file-item .file-icon {
position: absolute; position: absolute;
width: 1.5rem; width: 1.5rem;

View File

@@ -1,6 +1,6 @@
{ {
"version": 3, "version": 3,
"mappings": "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", "mappings": "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",
"sources": ["slovenscina-theme.scss","slovenscina-elements.scss","history.scss"], "sources": ["slovenscina-theme.scss","slovenscina-elements.scss","history.scss"],
"names": [], "names": [],
"file": "history.css" "file": "history.css"

View File

@@ -60,6 +60,9 @@
position:relative; position:relative;
height:3.125rem; height:3.125rem;
border-bottom: 1px solid $grey-dark; border-bottom: 1px solid $grey-dark;
&:last-child {
border-bottom:none;
}
.file-icon { .file-icon {
position:absolute; position:absolute;
width:1.5rem; width:1.5rem;

View File

@@ -0,0 +1,144 @@
@import url(https://fonts.googleapis.com/css?family=Roboto:400,400italic,500,500italic,700,700italic,900,900italic,300italic,300,100italic,100);
html {
font-family: 'Roboto', sans-serif;
font-size: 16px;
color: #46535B; }
body {
font-size: 16px;
padding: 0;
margin: 0; }
h1 {
font-size: 30px;
font-style: normal;
font-weight: 300;
line-height: 35px;
color: #006CB7; }
h2 {
font-size: 18px;
font-style: normal;
font-weight: 300;
line-height: 21px;
text-transform: uppercase;
color: #006CB7; }
h3 {
font-size: 18px;
font-style: normal;
font-weight: 300;
line-height: 21px; }
em {
font-weight: 300; }
.btn {
border: none;
line-height: 2.5rem;
padding: 0 2.5rem;
color: white;
background: #006CB7;
border-radius: 20px;
font-size: 1.125rem;
font-weight: 400;
cursor: pointer;
transition: opacity 0.3s ease-out; }
.btn:hover {
opacity: 0.8; }
.btn:disabled {
cursor: default;
opacity: 0.5; }
.panel {
background: #F5F5F5;
padding: 40px 60px;
border-radius: 20px;
max-width: 30rem; }
.panel .panel-logo {
position: absolute;
top: -60px;
left: 0;
right: 0;
display: block;
margin: auto;
background: #F5F5F5;
padding: 20px 30px;
width: 100px;
border-radius: 100%;
text-align: center; }
.line {
background: #C4C4C4;
height: 2px;
width: 200px;
margin: auto; }
.a-right {
display: block;
text-align: right;
font-size: 10px;
text-decoration: none;
color: #006CB7;
text-transform: uppercase; }
.alert {
position: relative;
color: #8D3D3D;
margin-bottom: 2rem; }
.alert.alert-success {
color: #88B52F; }
.alert img {
position: relative;
top: 0.25rem;
width: 1.8rem; }
.alert p {
position: absolute;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 2rem;
left: 3rem;
top: 0;
margin: 0;
text-transform: uppercase; }
.submit-alert {
background: white;
border: 2px solid #B7DB70;
box-sizing: border-box;
border-radius: 8px; }
.submit-alert .btn {
margin-top: 0.5rem;
background: #88B52F;
border-radius: 4px; }
.tableFixHead {
overflow-y: scroll;
max-height: 306px; }
.tableFixHead thead th {
position: sticky;
top: 0; }
table {
border-collapse: collapse;
width: 100%; }
table th, table td {
padding: 8px 16px;
border: 1px solid #ccc; }
table th {
background: #eee; }
table input[type=submit], table a {
font-size: 0.8rem;
background: none;
outline: none;
border: none;
cursor: pointer;
text-decoration: none;
color: #006CB7; }
table input[type=submit]:hover, table a:hover {
text-decoration: underline; }
/*# sourceMappingURL=slovenscina-admin.css.map */

View File

@@ -0,0 +1,7 @@
{
"version": 3,
"mappings": "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",
"sources": ["slovenscina-theme.scss","slovenscina-elements.scss","slovenscina-admin.scss"],
"names": [],
"file": "slovenscina-admin.css"
}

View File

@@ -0,0 +1,33 @@
@import "slovenscina-elements.scss";
.tableFixHead {
overflow-y: scroll;
max-height: 306px;
}
.tableFixHead thead th {
position: sticky;
top: 0;
}
table {
border-collapse: collapse;
width: 100%;
th,td {
padding: 8px 16px;
border: 1px solid #ccc;
}
th {
background: #eee;
}
input[type=submit],a {
font-size: 0.8rem;
background:none;
outline:none;
border:none;
cursor:pointer;
text-decoration: none;
color:$blue;
&:hover {
text-decoration: underline;
}
}
}

BIN
static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

10
static/favicon.svg Normal file
View File

@@ -0,0 +1,10 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<rect fill="#006CB7" width="512" height="512"/>
<path fill="#fff" d="M409.26,145.32V69.5l-46.06,55.16c-5.06-1.88-10.5-3.99-16.1-5.71c-16.12-4.52-32.56-7.82-49.17-9.86
c-5.37-0.47-11.2-0.47-17.04-0.47c-64.88,0-87.21,25.27-87.21,51.25c0,29.89,32.44,46.95,107.28,66.27
c89.47,22.07,117.94,63.93,117.94,114.79c0.04,6.77-0.59,13.54-1.87,20.19c41.39-26.92,66.98-64.24,66.98-105.48
c0-43.74-28.79-83.02-74.61-110.33"/>
<path fill="#fff" d="M241.92,278.65c-84.49-19.95-124.47-61.66-124.47-112.6c-0.13-10.68,1.69-21.29,5.37-31.3
c-57.41,27.07-94.76,71.13-94.76,120.89c0,42.02,26.61,79.89,69.32,107.04v79.81l47.38-56.73c23.89,8.63,48.73,14.33,73.98,16.98
c8.56,0.7,17.35,1.17,26.53,1.17c65.66,0,96.39-23.47,96.39-58.45c0-29.26-28.32-50-99.81-66.82"/>
</svg>

After

Width:  |  Height:  |  Size: 852 B

5
static/image/menu.svg Normal file
View File

@@ -0,0 +1,5 @@
<svg width="7" height="27" viewBox="0 0 7 27" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="3.5" cy="3.5" r="2.5" stroke="#F5F5F5" stroke-width="2"/>
<circle cx="3.5" cy="13.5" r="2.5" stroke="#F5F5F5" stroke-width="2"/>
<circle cx="3.5" cy="23.5" r="2.5" stroke="#F5F5F5" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 325 B

View File

@@ -3,10 +3,12 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Admin panel - Šolar</title> <title>Admin panel - Šolar</title>
<link rel="stylesheet" href="../static/css/header.css" type="text/css"> <link rel="icon" href="/static/favicon.ico" type="image/x-icon" >
<link rel="stylesheet" href="../static/css/form.css" type="text/css"> <link rel="icon" href="static/favicon.svg" sizes="any" type="image/svg+xml">
<link rel="stylesheet" href="../static/css/simple-grid.css" type="text/css"> <link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/header.css" type="text/css">
<link rel="stylesheet" href="../static/css/manage-institution.css" type="text/css"> <link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/form.css" type="text/css">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/simple-grid.css" type="text/css">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/manage-institution.css" type="text/css">
<style> <style>
.tableFixHead { .tableFixHead {
overflow-y: scroll; overflow-y: scroll;
@@ -35,17 +37,17 @@
</head> </head>
<body> <body>
<header> <header>
<div class="logo"><a href="../"><img src="../static/image/logo-white.svg"/></a></div> <div class="logo"><a href="{{ROUTE_PREFIX}}/"><img src="{{ROUTE_PREFIX}}/static/image/logo-white.svg"/></a></div>
<div class="menu-items"> <div class="menu-items">
<a href="../logout">Odjava</a> <a href="{{ROUTE_PREFIX}}/oddaja">Oddaja besedil</a>
{% if is_institution_coordinator %} {% if is_institution_coordinator %}
<a href="../manage-institution">Upravljaj z institucijo</a> <a href="{{ROUTE_PREFIX}}/manage-institution">Upravljaj z ekipo</a>
{% endif %} {% endif %}
{% if is_admin %} {% if is_admin %}
<a href="../admin">Administracijski meni</a> <a href="{{ROUTE_PREFIX}}/admin">Administracijski meni</a>
{% endif %} {% endif %}
<a href="../oddaja">Oddaja</a> <a href="https://slovenscina.eu/" target="_blank">Več informacij o sodelovanju</a>
<a href="https://slovenscina.eu/" target="_blank">Več informacij</a> <a href="{{ROUTE_PREFIX}}/logout">Odjava</a>
</div> </div>
</header> </header>
<div class="container" style="margin-top:8rem;"> <div class="container" style="margin-top:8rem;">
@@ -83,7 +85,7 @@
</table> </table>
</div> </div>
<h3>Dodaj uporabnika</h3> <h3>Dodaj uporabnika</h3>
<form action="../adduser" method="post"> <form action="{{ROUTE_PREFIX}}/adduser" method="post">
<label for="name">Ime in priimek:</label><br> <label for="name">Ime in priimek:</label><br>
<input type="text" id="name" name="name"><br> <input type="text" id="name" name="name"><br>
<label for="email">Email:</label><br> <label for="email">Email:</label><br>
@@ -93,7 +95,7 @@
<input type="submit" value="Dodaj"> <input type="submit" value="Dodaj">
</form> </form>
<h3>Spremeni email uporabnika</h3> <h3>Spremeni email uporabnika</h3>
<form action="../changeuseremail" method="post"> <form action="{{ROUTE_PREFIX}}/changeuseremail" method="post">
<label for="user-id">ID uporabnika:</label><br> <label for="user-id">ID uporabnika:</label><br>
<input type="text" id="user-id" name="user-id"><br> <input type="text" id="user-id" name="user-id"><br>
<label for="email">Nov email:</label><br> <label for="email">Nov email:</label><br>
@@ -101,7 +103,7 @@
<input type="submit" value="Spremeni"> <input type="submit" value="Spremeni">
</form> </form>
<h3>Spremeni ime in priimek uporabnika</h3> <h3>Spremeni ime in priimek uporabnika</h3>
<form action="../changeusername" method="post"> <form action="{{ROUTE_PREFIX}}/changeusername" method="post">
<label for="user-id">ID uporabnika:</label><br> <label for="user-id">ID uporabnika:</label><br>
<input type="text" id="user-id" name="user-id"><br> <input type="text" id="user-id" name="user-id"><br>
<label for="name">Ime in priimek:</label><br> <label for="name">Ime in priimek:</label><br>
@@ -109,13 +111,13 @@
<input type="submit" value="Spremeni"> <input type="submit" value="Spremeni">
</form> </form>
<h3>Odstrani uporabnika</h3> <h3>Odstrani uporabnika</h3>
<form action="../deluser" method="post"> <form action="{{ROUTE_PREFIX}}/deluser" method="post">
<label for="user_id">ID uporabnika:</label><br> <label for="user_id">ID uporabnika:</label><br>
<input type="text" id="user_id" name="user_id"><br> <input type="text" id="user_id" name="user_id"><br>
<input type="submit" value="Odstrani"> <input type="submit" value="Odstrani">
</form> </form>
<h3>Dodeli uporabnika instituciji</h3> <h3>Dodeli uporabnika instituciji</h3>
<form action="../addusertoinstitution" method="post"> <form action="{{ROUTE_PREFIX}}/addusertoinstitution" method="post">
<label for="user_id">ID uporabnika:</label> <label for="user_id">ID uporabnika:</label>
<input type="text" id="user_id" name="user_id"><br> <input type="text" id="user_id" name="user_id"><br>
<label for="institution_id">ID institucije:</label> <label for="institution_id">ID institucije:</label>
@@ -129,13 +131,13 @@
<input type="submit" value="Dodeli"> <input type="submit" value="Dodeli">
</form> </form>
<h3>Odstrani uporabnika iz institucije</h3> <h3>Odstrani uporabnika iz institucije</h3>
<form action="../deluserfrominstitution" method="post"> <form action="{{ROUTE_PREFIX}}/deluserfrominstitution" method="post">
<label for="user_id">ID uporabnika:</label> <label for="user_id">ID uporabnika:</label>
<input type="text" id="user_id" name="user_id"><br> <input type="text" id="user_id" name="user_id"><br>
<input type="submit" value="Odstrani"> <input type="submit" value="Odstrani">
</form> </form>
<h3>Spremeni vlogo uporabniškega računa</h3> <h3>Spremeni vlogo uporabniškega računa</h3>
<form action="../changeuserrole" method="post"> <form action="{{ROUTE_PREFIX}}/changeuserrole" method="post">
<label for="user-id">ID uporabnika:</label> <label for="user-id">ID uporabnika:</label>
<input type="text" id="user-id" name="user-id"><br> <input type="text" id="user-id" name="user-id"><br>
<label for="role">Vloga:</label> <label for="role">Vloga:</label>
@@ -155,6 +157,7 @@
<th>Email</th> <th>Email</th>
<th>Institucija</th> <th>Institucija</th>
<th>Vloga v instituciji</th> <th>Vloga v instituciji</th>
<th>Akcije</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -165,20 +168,21 @@
<td>{{item[0].email}}</td> <td>{{item[0].email}}</td>
<td>{{item[1].institution}}</td> <td>{{item[1].institution}}</td>
<td>{{item[1].role}}</td> <td>{{item[1].role}}</td>
<td>
<form action="{{ROUTE_PREFIX}}/activateuser" method="post">
<input type="hidden" id="id" name="id" value="{{item[0].id}}">
<input type="submit" value="Aktiviraj">
</form>
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
</div> </div>
<h3>Aktiviraj uporabnika</h3>
<form action="../activateuser" method="post">
<label for="id">ID uporabnika:</label>
<input type="text" id="id" name="id"><br>
<input type="submit" value="Aktiviraj">
</form>
<div> </div> <div> </div>
<h2>Institucije</h2> <h2>Institucije</h2>
<h3>Dodaj institucijo</h3> <h3>Dodaj institucijo</h3>
<form action="../addinstitution" method="post"> <form action="{{ROUTE_PREFIX}}/addinstitution" method="post">
<label for="name">Naziv:</label> <label for="name">Naziv:</label>
<input type="text" id="name" name="name"><br> <input type="text" id="name" name="name"><br>
<label for="region">Regija:</label> <label for="region">Regija:</label>
@@ -218,7 +222,7 @@
</table> </table>
</div> </div>
<h3>Združi instituciji</h3> <h3>Združi instituciji</h3>
<form action="../mergeinstitutions" method="post"> <form action="{{ROUTE_PREFIX}}/mergeinstitutions" method="post">
<label for="id-from">Institucijo z ID</label> <label for="id-from">Institucijo z ID</label>
<input type="text" id="id-from" name="id-from"> <input type="text" id="id-from" name="id-from">
<label for="id-to">združi v institucijo z ID</label> <label for="id-to">združi v institucijo z ID</label>
@@ -226,7 +230,7 @@
<input type="submit" value="Združi"> <input type="submit" value="Združi">
</form> </form>
<h3>Spremeni podatke institucije</h3> <h3>Spremeni podatke institucije</h3>
<form action="../changeinstitutiondata" method="post"> <form action="{{ROUTE_PREFIX}}/changeinstitutiondata" method="post">
<label for="id">ID institucije</label> <label for="id">ID institucije</label>
<input type="text" id="id" name="id"><br> <input type="text" id="id" name="id"><br>
<label for="name">Nov naziv:</label> <label for="name">Nov naziv:</label>
@@ -247,52 +251,8 @@
</select> </select>
<input type="submit" value="Spremeni"> <input type="submit" value="Spremeni">
</form> </form>
<h2>Zgodovina sodelovanja</h2>
<div class="tableFixHead">
<table>
<thead>
<tr>
<th>ID</th>
<th>ID uporabnika</th>
<th>ID institucije</th>
<th>Vloga</th>
<th>Šolsko leto</th>
<th>Besedilo značke</th>
</tr>
</thead>
<tbody>
{% for item in user_cooperation_history %}
<tr>
<td>{{item.id}}</td>
<td>{{item.user}}</td>
<td>{{item.institution}}</td>
<td>{{item.role}}</td>
<td>{{item.school_year}}</td>
<td>{{item.badge_text}}</td>
</tr>
{% endfor %}
</table>
</div>
<h3>Dodaj vnos</h3>
<form action="../addcooperationhistoryitem" method="post">
<label for="user">ID uporabnika</label>
<input type="text" id="user" name="user"><br>
<label for="institution">ID institucije</label>
<input type="text" id="institution" name="institution"><br>
<label for="role">Vloga</label>
<select name="role" id="role">
<option value="coordinator">Koordinator/-ka</option>
<option value="mentor">Mentor/-ica</option>
<option value="other">Druga vloga</option>
</select><br>
<label for="school-year">Šolsko leto (npr. "2021/22")</label>
<input type="text" id="school-year" name="school-year"><br>
<label for="badge-text">Besedilo značke</label>
<input type="text" id="badge-text" name="badge-text"><br>
<input type="submit" value="Dodaj">
</form>
<h3>Odstrani vnos</h3> <h3>Odstrani vnos</h3>
<form action="../delcooperationhistoryitem" method="post"> <form action="{{ROUTE_PREFIX}}/delcooperationhistoryitem" method="post">
<label for="entry-id">ID vnosa</label> <label for="entry-id">ID vnosa</label>
<input type="text" id="entry-id" name="entry-id"><br> <input type="text" id="entry-id" name="entry-id"><br>
<input type="submit" value="Odstrani"> <input type="submit" value="Odstrani">
@@ -338,7 +298,7 @@
</table> </table>
</div> </div>
<h3>Posodobi podatke nalaganja</h3> <h3>Posodobi podatke nalaganja</h3>
<form action="../updateuploaditem" method="post"> <form action="{{ROUTE_PREFIX}}/updateuploaditem" method="post">
<label for="item-id">ID nalaganja</label> <label for="item-id">ID nalaganja</label>
<input type="text" id="item-id" name="item-id"/><br> <input type="text" id="item-id" name="item-id"/><br>
<label for="program">Program</label> <label for="program">Program</label>

View File

@@ -3,20 +3,22 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Portal ŠOLAR</title> <title>Portal ŠOLAR</title>
<link rel="stylesheet" href="../static/css/login-styles.css" type="text/css"> <link rel="icon" href="/static/favicon.ico" type="image/x-icon" >
<link rel="stylesheet" href="../static/css/utils.css" type="text/css"> <link rel="icon" href="static/favicon.svg" sizes="any" type="image/svg+xml">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/login-styles.css" type="text/css">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/utils.css" type="text/css">
</head> </head>
<body> <body>
<div class="background"> <div class="background">
<div class="panel login-panel"> <div class="panel login-panel">
<div class="panel-logo"> <div class="panel-logo">
<img src="../static/image/logo.svg" alt="logo"/> <img src="{{ROUTE_PREFIX}}/static/image/logo.svg" alt="logo"/>
</div> </div>
<h1 class="m-b-3">Pozabljeno geslo - ŠOLAR</h1> <h1 class="m-b-3">Pozabljeno geslo - ŠOLAR</h1>
<div> <div>
<form method="POST" action="../sendresetpass" class="m-b-2"> <form method="POST" action="{{ROUTE_PREFIX}}/sendresetpass" class="m-b-2">
<div class="input-wrapper"> <div class="input-wrapper">
<img src="../static/image/user.svg" alt="user" class="input-icon"/> <img src="{{ROUTE_PREFIX}}/static/image/user.svg" alt="user" class="input-icon"/>
<div class="input-floating-label"> <div class="input-floating-label">
<label>E-mail</label> <label>E-mail</label>
<input type="text" name="email"> <input type="text" name="email">
@@ -28,15 +30,15 @@
{% with messages = get_flashed_messages() %} {% with messages = get_flashed_messages() %}
{% if messages %} {% if messages %}
<div class="alert alert-success"> <div class="alert alert-success">
<img src="../static/image/success.svg" alt="alert"/> <img src="{{ROUTE_PREFIX}}/static/image/success.svg" alt="alert"/>
<p>{{ messages[0] }}</p> <p>{{ messages[0] }}</p>
</div> </div>
{% endif %} {% endif %}
{% endwith %} {% endwith %}
<div class="back-to-login"> <div class="back-to-login">
<img src="../static/image/chevron-left.svg"/> <img src="{{ROUTE_PREFIX}}/static/image/chevron-left.svg"/>
<a href="../login">Nazaj na prijavo</a> <a href="{{ROUTE_PREFIX}}/login">Nazaj na prijavo</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -3,14 +3,16 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Portal ŠOLAR</title> <title>Portal ŠOLAR</title>
<link rel="stylesheet" href="../static/css/login-styles.css" type="text/css"> <link rel="icon" href="/static/favicon.ico" type="image/x-icon" >
<link rel="stylesheet" href="../static/css/utils.css" type="text/css"> <link rel="icon" href="static/favicon.svg" sizes="any" type="image/svg+xml">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/login-styles.css" type="text/css">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/utils.css" type="text/css">
</head> </head>
<body> <body>
<div class="background"> <div class="background">
<div class="panel login-panel"> <div class="panel login-panel">
<div class="panel-logo"> <div class="panel-logo">
<img src="../static/image/logo.svg" alt="logo"/> <img src="{{ROUTE_PREFIX}}/static/image/logo.svg" alt="logo"/>
</div> </div>
<h2 class="text-center">Portal za oddajanje besedil</h2> <h2 class="text-center">Portal za oddajanje besedil</h2>
<div class="line"></div> <div class="line"></div>
@@ -23,41 +25,41 @@
{% if messages %} {% if messages %}
{% if "potrditev" in messages[0] or "uspešna" in messages[0] %} {% if "potrditev" in messages[0] or "uspešna" in messages[0] %}
<div class="alert alert-success"> <div class="alert alert-success">
<img src="../static/image/success.svg" alt="alert"/> <img src="{{ROUTE_PREFIX}}/static/image/success.svg" alt="alert"/>
<p>{{ messages[0] }}</p> <p>{{ messages[0] }}</p>
</div> </div>
{% else %} {% else %}
<div class="alert"> <div class="alert">
<img src="../static/image/alert.svg" alt="alert"/> <img src="{{ROUTE_PREFIX}}/static/image/alert.svg" alt="alert"/>
<p>{{ messages[0] }}</p> <p>{{ messages[0] }}</p>
</div> </div>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% endwith %} {% endwith %}
<div> <div>
<form method="POST" action="../login" class="m-b-2"> <form method="POST" action="{{ROUTE_PREFIX}}/login" class="m-b-2">
<div class="input-wrapper"> <div class="input-wrapper">
<img src="../static/image/user.svg" alt="user" class="input-icon"/> <img src="{{ROUTE_PREFIX}}/static/image/user.svg" alt="user" class="input-icon"/>
<div class="input-floating-label"> <div class="input-floating-label">
<label>E-mail</label> <label>E-mail</label>
<input type="text" name="email"> <input type="text" name="email">
</div> </div>
</div> </div>
<div class="input-wrapper"> <div class="input-wrapper">
<img src="../static/image/password.svg" alt="user" class="input-icon"/> <img src="{{ROUTE_PREFIX}}/static/image/password.svg" alt="user" class="input-icon"/>
<div class="input-floating-label"> <div class="input-floating-label">
<label>Geslo</label> <label>Geslo</label>
<input type="password" name="password"> <input type="password" name="password">
</div> </div>
</div> </div>
<a href="../forgotpass" class="a-right m-b-1">Pozabljeno geslo</a> <a href="{{ROUTE_PREFIX}}/forgotpass" class="a-right m-b-1">Pozabljeno geslo</a>
<button class="btn" style="margin-left: 46px;">PRIJAVA</button> <button class="btn" style="margin-left: 46px;">PRIJAVA</button>
</form> </form>
</div> </div>
<a href="../register" class="register-button"> <a href="{{ROUTE_PREFIX}}/register" class="register-button">
<img src="../static/image/register.svg" alt="register"/> <img src="{{ROUTE_PREFIX}}/static/image/register.svg" alt="register"/>
<h3>Registracija</h3> <h3>Registracija</h3>
<p>Še nimate uporabniškega računa? Registrirajte se!</p> <p>Še nimate uporabniškega računa? Registrirajte se!</p>
</a> </a>

View File

@@ -3,119 +3,126 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Upravljanje institucije - Šolar</title> <title>Upravljanje institucije - Šolar</title>
<link rel="stylesheet" href="../static/css/header.css" type="text/css"> <link rel="icon" href="/static/favicon.ico" type="image/x-icon" >
<link rel="stylesheet" href="../static/css/form.css" type="text/css"> <link rel="icon" href="static/favicon.svg" sizes="any" type="image/svg+xml">
<link rel="stylesheet" href="../static/css/simple-grid.css" type="text/css"> <link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/header.css" type="text/css">
<link rel="stylesheet" href="../static/css/manage-institution.css" type="text/css"> <link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/form.css" type="text/css">
<style> <link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/simple-grid.css" type="text/css">
.tableFixHead { <link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/slovenscina-admin.css" type="text/css">
overflow-y: scroll; <link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/manage-institution.css" type="text/css">
max-height: 306px;
}
.tableFixHead thead th {
position: sticky;
top: 0;
}
table {
border-collapse: collapse;
width: 100%;
}
th,
td {
padding: 8px 16px;
border: 1px solid #ccc;
}
th {
background: #eee;
}
h2 {
color: blue;
}
</style>
</head> </head>
<body> <body>
<header> <header>
<div class="logo"><a href="../"><img src="../static/image/logo-white.svg"/></a></div> <div class="logo"><a href="{{ROUTE_PREFIX}}/"><img src="{{ROUTE_PREFIX}}/static/image/logo-white.svg"/></a></div>
<div class="menu-items"> <div class="menu-items">
<a href="../logout">Odjava</a> <a href="{{ROUTE_PREFIX}}/oddaja">Oddaja besedil</a>
{% if is_institution_coordinator %} {% if is_institution_coordinator %}
<a href="../manage-institution">Upravljaj z institucijo</a> <a href="{{ROUTE_PREFIX}}/manage-institution">Upravljaj z ekipo</a>
{% endif %} {% endif %}
{% if is_admin %} {% if is_admin %}
<a href="../admin">Administracijski meni</a> <a href="{{ROUTE_PREFIX}}/admin">Administracijski meni</a>
{% endif %} {% endif %}
<a href="../oddaja">Oddaja</a> <a href="https://slovenscina.eu/" target="_blank">Več informacij o sodelovanju</a>
<a href="https://slovenscina.eu/" target="_blank">Več informacij</a> <a href="{{ROUTE_PREFIX}}/logout">Odjava</a>
</div> </div>
</header> </header>
<div class="container" style="margin-top:8rem;"> <div class="container" style="margin-top:8rem;">
{% with messages = get_flashed_messages() %} {% with messages = get_flashed_messages() %}
{% if messages %} {% if messages %}
<div style="background: blue;"> <div>
{{ messages[0] }} {{ messages[0] }}
</div> </div>
{% endif %} {% endif %}
{% endwith %} {% endwith %}
<h3>Seznam vseh aktivnih uporabnikov</h3>
<div class="tableFixHead"> <div class="row">
<table> <div class="col-12">
<thead> <h1>{{institution.name}}</h1>
<tr> <h3>Seznam uporabnikov v vaši instituciji</h3>
<th>ID</th> <table class="tableFixHead">
<th>Ime in priimek</th> <thead>
<th>Email</th> <tr>
</tr> <th>Ime in priimek</th>
</thead> <th>Email</th>
<tbody> <th>Vloga</th>
{% for item in users %} <th>Akcije</th>
<tr> </tr>
<td>{{item.id}}</td> </thead>
<td>{{item.name}}</td> <tbody>
<td>{{item.email}}</td> {% for item in institution_users %}
</tr> <tr>
{% endfor %} <td>{{item.name}}</td>
</table> <td>{{item.email}}</td>
<td>
<div>
<a href="javascript:void(0);" onclick="toggleEditForm(this)" class="toggle-edit-role">Spremeni</a>
{{role_map[item.id]}}
</div>
<form action="{{ROUTE_PREFIX}}/changeuserrole-institution" method="post" style="display:none;">
<input type="hidden" id="user-id" name="user-id" value="{{item.id}}"/>
<select class="role" name="role">
<option value="coordinator">Koordinator/-ka</option>
<option value="mentor">Mentor/-ica</option>
<option value="other">Druga vloga</option>
</select>
<input type="submit" value="Shrani"/>
</form>
</td>
<td>
<form action="{{ROUTE_PREFIX}}/deluserfrominstitution" method="post">
<input type="hidden" id="user_id" name="user_id" value="{{item.id}}">
<input type="submit" value="Odstrani uporabnika">
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div> </div>
<h3>Seznam uporabnikov v vaši instituciji</h3>
<div class="tableFixHead"> <form action="/institutionadduser" method="POST">
<table> <div class="row">
<thead> <div class="col-6">
<tr> <h1>Dodaj uporabnika</h1>
<th>ID</th> <div class="form-wrapper">
<th>Ime in priimek</th> <label for="regija">Ime</label>
<th>Email</th> <input type="text" name="name" />
</tr> </div>
</thead> <div class="form-wrapper">
<tbody> <label for="regija">Email</label>
{% for item in institution_users %} <input type="text" name="email" />
<tr> </div>
<td>{{item.id}}</td> <div class="form-wrapper">
<td>{{item.name}}</td> <label for="regija">Vloga</label>
<td>{{item.email}}</td> <select class="role" name="role">
</tr> <option value="coordinator">Koordinator/-ka</option>
{% endfor %} <option value="mentor">Mentor/-ica</option>
</table> <option value="other">Druga vloga</option>
</div> </select>
</div>
<input type="submit" class="btn" value="Dodaj"/>
</div>
</div>
</form>
<br> <br>
<h3>Dodaj uporabnika instituciji</h3>
<form action="../addusertoinstitution" method="post">
<label for="user_id">ID uporabnika:</label>
<input type="text" id="user_id" name="user_id"><br>
<label for="role">Vloga v instituciji:</label>
<select name="role" id="role">
<option value="coordinator">Koordinator/-ka</option>
<option value="mentor">Mentor/-ica</option>
<option value="other">Druga vloga</option>
</select>
<input type="submit" value="Dodeli">
</form>
<h3>Odstrani uporabnika iz institucije</h3>
<form action="../deluserfrominstitution" method="post">
<label for="user_id">ID uporabnika:</label>
<input type="text" id="user_id" name="user_id"><br>
<input type="submit" value="Odstrani">
</form>
<div> </div>
</div> </div>
</body> </body>
<script>
var toggleEditForm = function(el) {
var td = el.closest("td");
el.closest("div").style.display = "none";
td.querySelector("form").style.display = "block";
};
</script>
</html>

View File

@@ -3,23 +3,25 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Portal za oddajanje besedil</title> <title>Portal za oddajanje besedil</title>
<link rel="stylesheet" href="../static/css/header.css" type="text/css"> <link rel="icon" href="/static/favicon.ico" type="image/x-icon" >
<link rel="stylesheet" href="../static/css/form.css" type="text/css"> <link rel="icon" href="static/favicon.svg" sizes="any" type="image/svg+xml">
<link rel="stylesheet" href="../static/css/simple-grid.css" type="text/css"> <link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/header.css" type="text/css">
<link rel="stylesheet" href="../static/css/utils.css" type="text/css"> <link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/form.css" type="text/css">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/simple-grid.css" type="text/css">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/utils.css" type="text/css">
</head> </head>
<body> <body>
<header> <header>
<div class="logo"><a href="../"><img src="../static/image/logo-white.svg"/></a></div> <div class="logo"><a href="{{ROUTE_PREFIX}}/"><img src="{{ROUTE_PREFIX}}/static/image/logo-white.svg"/></a></div>
<div class="menu-items"> <div class="menu-items">
<a href="../logout">Odjava</a>
{% if is_institution_coordinator %} {% if is_institution_coordinator %}
<a href="../manage-institution">Upravljaj z institucijo</a> <a href="{{ROUTE_PREFIX}}/manage-institution">Upravljaj z ekipo</a>
{% endif %} {% endif %}
{% if is_admin %} {% if is_admin %}
<a href="../admin">Administracijski meni</a> <a href="{{ROUTE_PREFIX}}/admin">Administracijski meni</a>
{% endif %} {% endif %}
<a href="https://slovenscina.eu/" target="_blank">Več informacij</a> <a href="https://slovenscina.eu/" target="_blank">Več informacij o sodelovanju</a>
<a href="{{ROUTE_PREFIX}}/logout">Odjava</a>
</div> </div>
</header> </header>
<div class="container" style="margin-top:8rem;"> <div class="container" style="margin-top:8rem;">
@@ -30,9 +32,9 @@
<div class="tab-nav"> <div class="tab-nav">
<a href="../oddaja" class="active">Oddaja besedil</a> <a href="{{ROUTE_PREFIX}}/oddaja" class="active">Oddaja besedil</a>
<a href="../zgodovina">Zgodovina sodelovanja</a> <a href="{{ROUTE_PREFIX}}/zgodovina">Zgodovina sodelovanja</a>
<a href="../pogodbe">Ekipa</a> <a href="{{ROUTE_PREFIX}}/pogodbe">Ekipa</a>
</div> </div>
</div> </div>
</div> </div>
@@ -43,21 +45,21 @@
<div class="col-6"> <div class="col-6">
{% if not institution %} {% if not institution %}
<div class="alert"> <div class="alert">
<img src="../static/image/alert.svg" alt="alert"/> <img src="{{ROUTE_PREFIX}}/static/image/alert.svg" alt="alert"/>
<p>Niste član nobene institucije!</p> <p>Niste član nobene institucije!</p>
</div> </div>
{% elif not institution_contract %} {% elif not institution_contract %}
<!--<div class="alert"> <!--<div class="alert">
<img src="../static/image/alert.svg" alt="alert"/> <img src="{{ROUTE_PREFIX}}/static/image/alert.svg" alt="alert"/>
<p>Pogodba s šolo še ni naložena!</p> <p>Pogodba s šolo še ni naložena!</p>
</div>--> </div>-->
{% endif %} {% endif %}
<div class="alert" id="error-message"> <div class="alert" id="error-message">
<img src="../static/image/alert.svg" alt="alert"/> <img src="{{ROUTE_PREFIX}}/static/image/alert.svg" alt="alert"/>
<p></p> <p></p>
</div> </div>
<div class="alert alert-success" id="success-message"> <div class="alert alert-success" id="success-message">
<img src="../static/image/success.svg" alt="alert"/> <img src="{{ROUTE_PREFIX}}/static/image/success.svg" alt="alert"/>
<p></p> <p></p>
</div> </div>
</div> </div>
@@ -142,7 +144,7 @@
<div class="row"> <div class="row">
<div class="col-6"> <div class="col-6">
<div class="form-wrapper"> <div class="form-wrapper">
<label for="letnik">Letnik</label> <label for="letnik">Razred/Letnik</label>
<select id="letnik" name="letnik"> <select id="letnik" name="letnik">
<option value="1" selected="selected">1</option> <option value="1" selected="selected">1</option>
<option value="2">2</option> <option value="2">2</option>
@@ -167,7 +169,7 @@
<label for="vrsta">Vrsta besedila</label> <label for="vrsta">Vrsta besedila</label>
<select id="vrsta" name="vrsta"> <select id="vrsta" name="vrsta">
<option value="E" selected="selected">Esej ali spis (E)</option> <option value="E" selected="selected">Esej ali spis (E)</option>
<option value="PB">Praktično besedilo (npr. vabila, prošnje ipd. pri pouku slovenščine), napisano za oceno (PB)</option> <option value="PB">Praktično besedilo, napisano za oceno - npr. vabilo, prošnja ali podobno (PE)</option>
<option value="T">Šolski test (T)</option> <option value="T">Šolski test (T)</option>
<option value="R">Delo v razredu, ne za oceno (vtipkajte besedilo vrsto) (R)</option> <option value="R">Delo v razredu, ne za oceno (vtipkajte besedilo vrsto) (R)</option>
</select> </select>
@@ -271,7 +273,7 @@
<!--{{ dropzone.load_js() }}--> <!--{{ dropzone.load_js() }}-->
<script src="../static/dropzone.js"></script> <script src="{{ROUTE_PREFIX}}/static/dropzone.js"></script>
<script> <script>
///////////////////////// /////////////////////////
// Dropzone // // Dropzone //
@@ -340,7 +342,7 @@
Dropzone.options.myDropzone = { // The camelized version of the ID of the form element Dropzone.options.myDropzone = { // The camelized version of the ID of the form element
url: "../upload", url: "{{ROUTE_PREFIX}}/upload",
autoProcessQueue: false, autoProcessQueue: false,
uploadMultiple: true, uploadMultiple: true,
parallelUploads: 20, parallelUploads: 20,

View File

@@ -3,23 +3,25 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Portal za oddajanje besedil</title> <title>Portal za oddajanje besedil</title>
<link rel="stylesheet" href="../static/css/header.css" type="text/css"> <link rel="icon" href="/static/favicon.ico" type="image/x-icon" >
<link rel="stylesheet" href="../static/css/form.css" type="text/css"> <link rel="icon" href="static/favicon.svg" sizes="any" type="image/svg+xml">
<link rel="stylesheet" href="../static/css/simple-grid.css" type="text/css"> <link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/header.css" type="text/css">
<link rel="stylesheet" href="../static/css/contracts.css" type="text/css"> <link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/form.css" type="text/css">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/simple-grid.css" type="text/css">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/contracts.css" type="text/css">
</head> </head>
<body> <body>
<header> <header>
<div class="logo"><a href="../"><img src="../static/image/logo-white.svg"/></a></div> <div class="logo"><a href="{{ROUTE_PREFIX}}/"><img src="{{ROUTE_PREFIX}}/static/image/logo-white.svg"/></a></div>
<div class="menu-items"> <div class="menu-items">
<a href="../logout">Odjava</a>
{% if is_institution_coordinator %} {% if is_institution_coordinator %}
<a href="../manage-institution">Upravljaj z institucijo</a> <a href="{{ROUTE_PREFIX}}/manage-institution">Upravljaj z ekipo</a>
{% endif %} {% endif %}
{% if is_admin %} {% if is_admin %}
<a href="../admin">Administracijski meni</a> <a href="{{ROUTE_PREFIX}}/admin">Administracijski meni</a>
{% endif %} {% endif %}
<a href="https://slovenscina.eu/" target="_blank">Več informacij</a> <a href="https://slovenscina.eu/" target="_blank">Več informacij o sodelovanju</a>
<a href="{{ROUTE_PREFIX}}/logout">Odjava</a>
</div> </div>
</header> </header>
<div class="container" style="margin-top:8rem;"> <div class="container" style="margin-top:8rem;">
@@ -29,9 +31,9 @@
<p class="subtitle"></p> <p class="subtitle"></p>
<div class="tab-nav"> <div class="tab-nav">
<a href="../oddaja">Oddaja besedil</a> <a href="{{ROUTE_PREFIX}}/oddaja">Oddaja besedil</a>
<a href="../zgodovina">Zgodovina sodelovanja</a> <a href="{{ROUTE_PREFIX}}/zgodovina">Zgodovina sodelovanja</a>
<a href="../pogodbe" class="active">Ekipa</a> <a href="{{ROUTE_PREFIX}}/pogodbe" class="active">Ekipa</a>
</div> </div>
</div> </div>
</div> </div>
@@ -45,7 +47,7 @@
<h2>Sodelujoči</h2> <h2>Sodelujoči</h2>
</div> </div>
</div>--> </div>-->
<div class="row"> <div class="row" id="my_dataviz_title">
<div class="col-12"> <div class="col-12">
<h2>Število oddaj na uporabnika</h2> <h2>Število oddaj na uporabnika</h2>
</div> </div>
@@ -59,26 +61,48 @@
</div> </div>
{% set vars = {'prev_schoolyear': ''} %} {% set vars = {'prev_schoolyear': ''} %}
{% for item in cooperation_history %} {% for item in cooperation_history %}
{% if item.school_year != vars.prev_schoolyear %} {% if item[0] != vars.prev_schoolyear %}
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h2>Šolsko leto {{item.school_year}}</h2> <h2>Šolsko leto {{item[0]}}</h2>
</div> </div>
</div> </div>
{% if vars.update({'prev_schoolyear': item.school_year}) %} {% endif %} {% if vars.update({'prev_schoolyear': item[0]}) %} {% endif %}
{% endif %} {% endif %}
{% for entry in item[1] %}
<div class="row"> <div class="row">
<div class="col-6"> <div class="col-6">
<div class="team-item"> <div class="team-item">
<div class="team-item-name">{{item.name}} <span class="team-item-role">{{item.badge_text}}</span></div> <div class="team-item-name">{{entry.name}} <span class="team-item-role">{%if entry.role == "mentor" %}Mentor/-ica{%elif entry.role == "coordinator" %}Koordinator/-ica{%elif entry.role == "other" %}Druga vloga{%endif%}</span></div>
</div> </div>
</div> </div>
</div> </div>
{% endfor %}
{% endfor %} {% endfor %}
<div class="row" id="my_dataviz__region_title">
<div class="col-12">
<h2>Število vseh oddaj po regijah</h2>
</div>
</div>
<div class="row">
<div class="col-6">
<div id="my_dataviz_region">
</div>
<div>
<div style="display:inline-block;width:12px;height:12px;background:#006CB7"></div>
<p style="display:inline-block">Osnovne šole</p>
<div style="margin-left:32px;display:inline-block;width:12px;height:12px;background:#B86D00"></div>
<p style="display:inline-block">Sredje šole</p>
</div>
</div>
</div>
</div> </div>
@@ -94,17 +118,19 @@
#my_dataviz path.domain{ #my_dataviz path.domain{
visibility:hidden; visibility:hidden;
} }
#my_dataviz_region .tick line{
visibility:hidden;
}
#my_dataviz_region path.domain{
visibility:hidden;
}
</style> </style>
<script> <script>
// set the dimensions and margins of the graph
// append the svg object to the body of the page
var data; var data;
// Parse the Data // Parse the Data
d3.json("/topuploads-by-user/").then(function(jsondata) { d3.json("/topuploads-institution/{{institution_id}}").then(function(jsondata) {
if(Object.keys(jsondata).length < 1) { if(Object.keys(jsondata).length < 1) {
document.getElementById("my_dataviz_title").remove();
return; return;
} }
data = []; data = [];
@@ -131,6 +157,7 @@
var x = d3.scaleLinear() var x = d3.scaleLinear()
.domain([0,d3.max(data, function (d) { return d.value})]) .domain([0,d3.max(data, function (d) { return d.value})])
.range([ 0, width]); .range([ 0, width]);
svg.append("g") svg.append("g")
.attr("transform", "translate(0," + height + ")") .attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x)) .call(d3.axisBottom(x))
@@ -159,10 +186,77 @@
.attr("width", function(d) { return x(d.value); }) .attr("width", function(d) { return x(d.value); })
.attr("height", 32 ) .attr("height", 32 )
.attr("fill", "#006CB7"); .attr("fill", "#006CB7");
})
</script>
<script>
var data;
// Parse the Data
d3.json("/uploadstats-per-region").then(function(jsondata) {
data = [];
console.log(Object.keys(jsondata).length);
var margin = {top: 20, right: 0, bottom: 40, left: 0};
var width = document.getElementById("my_dataviz_region").clientWidth - margin.left - margin.right;
var height = Object.keys(jsondata).length * 56;
var svg = d3.select("#my_dataviz_region")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.style("overflow","visible")
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
for(var key in jsondata) {
data.push({'name': key, 'value':jsondata[key]});
}
console.log(data);
// Add X axis
var x = d3.scaleLinear()
.domain([0,d3.max(data, function (d) { return Math.max(...d.value)})])
.range([ 0, width]);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.style("text-anchor", "center");
// Y axis
var y = d3.scaleBand()
.range([ 0, data.length*56 ])
.domain(data.map(function(d) { return d.name; }))
.padding(0);
svg.append("g")
.call(d3.axisLeft(y))
.selectAll("text")
.style("text-anchor", "start")
.style("font-size", "14px")
.attr("transform", "translate(8,-36)");
//Bars
svg.selectAll("myRect")
.data(data)
.enter()
.append("rect")
.attr("x", x(0) )
.attr("y", function(d) { return y(d.name); })
.attr("width", function(d) { return x(d.value[0]); })
.attr("height", 16 )
.attr("fill", "#006CB7");
svg.selectAll("myRect")
.data(data)
.enter()
.append("rect")
.attr("x", x(0) )
.attr("y", function(d) { return y(d.name); })
.attr("width", function(d) { return x(d.value[1]); })
.attr("height", 16 )
.attr("transform", "translate(0,16)")
.attr("fill", "#B86D00");
}) })
</script> </script>

View File

@@ -3,15 +3,17 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Portal ŠOLAR</title> <title>Portal ŠOLAR</title>
<link rel="stylesheet" href="../static/css/login-styles.css" type="text/css"> <link rel="icon" href="/static/favicon.ico" type="image/x-icon" >
<link rel="stylesheet" href="../static/css/utils.css" type="text/css"> <link rel="icon" href="static/favicon.svg" sizes="any" type="image/svg+xml">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/login-styles.css" type="text/css">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/utils.css" type="text/css">
</head> </head>
<body> <body>
<div class="background"> <div class="background">
<div class="panel login-panel"> <div class="panel login-panel">
<div class="panel-logo"> <div class="panel-logo">
<img src="../static/image/logo.svg" alt="logo"/> <img src="{{ROUTE_PREFIX}}/static/image/logo.svg" alt="logo"/>
</div> </div>
<h2 class="text-center">Portal za oddajanje besedil</h2> <h2 class="text-center">Portal za oddajanje besedil</h2>
<div class="line"></div> <div class="line"></div>
@@ -23,29 +25,29 @@
{% with messages = get_flashed_messages() %} {% with messages = get_flashed_messages() %}
{% if messages %} {% if messages %}
<div class="alert"> <div class="alert">
<img src="../static/image/alert.svg" alt="alert"/> <img src="{{ROUTE_PREFIX}}/static/image/alert.svg" alt="alert"/>
<p>{{ messages[0] }}</p> <p>{{ messages[0] }}</p>
</div> </div>
{% endif %} {% endif %}
{% endwith %} {% endwith %}
<div> <div>
<form method="POST" action="../register" class="m-b-2"> <form method="POST" action="{{ROUTE_PREFIX}}/register" class="m-b-2">
<div class="input-wrapper"> <div class="input-wrapper">
<img src="../static/image/user.svg" alt="user" class="input-icon"/> <img src="{{ROUTE_PREFIX}}/static/image/user.svg" alt="user" class="input-icon"/>
<div class="input-floating-label"> <div class="input-floating-label">
<label>Ime in priimek</label> <label>Ime in priimek</label>
<input type="name" name="name" autofocus=""> <input type="name" name="name" autofocus="">
</div> </div>
</div> </div>
<div class="input-wrapper"> <div class="input-wrapper">
<img src="../static/image/user.svg" alt="user" class="input-icon"/> <img src="{{ROUTE_PREFIX}}/static/image/user.svg" alt="user" class="input-icon"/>
<div class="input-floating-label"> <div class="input-floating-label">
<label>Email</label> <label>Email</label>
<input type="email" name="email"> <input type="email" name="email">
</div> </div>
</div> </div>
<div class="input-wrapper"> <div class="input-wrapper">
<img src="../static/image/password.svg" alt="user" class="input-icon"/> <img src="{{ROUTE_PREFIX}}/static/image/password.svg" alt="user" class="input-icon"/>
<div class="input-floating-label"> <div class="input-floating-label">
<label>Geslo</label> <label>Geslo</label>
<input type="password" name="password"> <input type="password" name="password">
@@ -53,14 +55,14 @@
</div> </div>
</div> </div>
<div class="input-wrapper"> <div class="input-wrapper">
<img src="../static/image/user.svg" alt="user" class="input-icon"/> <img src="{{ROUTE_PREFIX}}/static/image/user.svg" alt="user" class="input-icon"/>
<div class="input-floating-label"> <div class="input-floating-label">
<label>Naziv institucije</label> <label>Naziv institucije</label>
<input type="institution" name="institution"> <input type="institution" name="institution">
</div> </div>
</div> </div>
<div class="input-wrapper"> <div class="input-wrapper">
<img src="../static/image/password.svg" alt="user" class="input-icon"/> <img src="{{ROUTE_PREFIX}}/static/image/password.svg" alt="user" class="input-icon"/>
<div class="input-floating-label"> <div class="input-floating-label">
<label>Vloga v instituciji</label> <label>Vloga v instituciji</label>
<select id="role" name="role" > <select id="role" name="role" >
@@ -75,8 +77,8 @@
</div> </div>
<div class="back-to-login"> <div class="back-to-login">
<img src="../static/image/chevron-left.svg"/> <img src="{{ROUTE_PREFIX}}/static/image/chevron-left.svg"/>
<a href="../login">Nazaj na prijavo</a> <a href="{{ROUTE_PREFIX}}/login">Nazaj na prijavo</a>
</div> </div>

View File

@@ -3,20 +3,22 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Portal ŠOLAR</title> <title>Portal ŠOLAR</title>
<link rel="stylesheet" href="../static/css/login-styles.css" type="text/css"> <link rel="icon" href="/static/favicon.ico" type="image/x-icon" >
<link rel="stylesheet" href="../static/css/utils.css" type="text/css"> <link rel="icon" href="static/favicon.svg" sizes="any" type="image/svg+xml">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/login-styles.css" type="text/css">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/utils.css" type="text/css">
</head> </head>
<body> <body>
<div class="background"> <div class="background">
<div class="panel login-panel"> <div class="panel login-panel">
<div class="panel-logo"> <div class="panel-logo">
<img src="../static/image/logo.svg" alt="logo"/> <img src="{{ROUTE_PREFIX}}/static/image/logo.svg" alt="logo"/>
</div> </div>
<h1 class="m-b-3">Ponastavitev gesla - ŠOLAR</h1> <h1 class="m-b-3">Ponastavitev gesla - ŠOLAR</h1>
<div> <div>
<form method="POST" action="" class="m-b-2"> <form method="POST" action="" class="m-b-2">
<div class="input-wrapper"> <div class="input-wrapper">
<img src="../static/image/password.svg" alt="user" class="input-icon"/> <img src="{{ROUTE_PREFIX}}/static/image/password.svg" alt="user" class="input-icon"/>
<div class="input-floating-label"> <div class="input-floating-label">
<label>Novo geslo</label> <label>Novo geslo</label>
<input type="password" name="new_password"> <input type="password" name="new_password">
@@ -29,7 +31,7 @@
{% with messages = get_flashed_messages() %} {% with messages = get_flashed_messages() %}
{% if messages %} {% if messages %}
<div class="alert"> <div class="alert">
<img src="../static/image/alert.svg" alt="alert"/> <img src="{{ROUTE_PREFIX}}/static/image/alert.svg" alt="alert"/>
<p>{{ messages[0] }}</p> <p>{{ messages[0] }}</p>
</div> </div>
{% endif %} {% endif %}

View File

@@ -3,25 +3,27 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Portal za oddajanje besedil</title> <title>Portal za oddajanje besedil</title>
<!--<link rel="stylesheet" href="../static/style.css" type="text/css">--> <!--<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/style.css" type="text/css">-->
<script src="../static/chart.js"></script> <script src="{{ROUTE_PREFIX}}/static/chart.js"></script>
<link rel="stylesheet" href="../static/css/header.css" type="text/css"> <link rel="icon" href="/static/favicon.ico" type="image/x-icon" >
<link rel="stylesheet" href="../static/css/form.css" type="text/css"> <link rel="icon" href="static/favicon.svg" sizes="any" type="image/svg+xml">
<link rel="stylesheet" href="../static/css/simple-grid.css" type="text/css"> <link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/header.css" type="text/css">
<link rel="stylesheet" href="../static/css/history.css" type="text/css"> <link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/form.css" type="text/css">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/simple-grid.css" type="text/css">
<link rel="stylesheet" href="{{ROUTE_PREFIX}}/static/css/history.css" type="text/css">
</head> </head>
<body> <body>
<header> <header>
<div class="logo"><a href="../"><img src="../static/image/logo-white.svg"/></a></div> <div class="logo"><a href="{{ROUTE_PREFIX}}/"><img src="{{ROUTE_PREFIX}}/static/image/logo-white.svg"/></a></div>
<div class="menu-items"> <div class="menu-items">
<a href="../logout">Odjava</a>
{% if is_institution_coordinator %} {% if is_institution_coordinator %}
<a href="../manage-institution">Upravljaj z institucijo</a> <a href="{{ROUTE_PREFIX}}/manage-institution">Upravljaj z ekipo</a>
{% endif %} {% endif %}
{% if is_admin %} {% if is_admin %}
<a href="../admin">Administracijski meni</a> <a href="{{ROUTE_PREFIX}}/admin">Administracijski meni</a>
{% endif %} {% endif %}
<a href="https://slovenscina.eu/" target="_blank">Več informacij</a> <a href="https://slovenscina.eu/" target="_blank">Več informacij o sodelovanju</a>
<a href="{{ROUTE_PREFIX}}/logout">Odjava</a>
</div> </div>
</header> </header>
<div class="container" style="margin-top:8rem;"> <div class="container" style="margin-top:8rem;">
@@ -32,9 +34,9 @@
<div class="tab-nav"> <div class="tab-nav">
<a href="../oddaja">Oddaja besedil</a> <a href="{{ROUTE_PREFIX}}/oddaja">Oddaja besedil</a>
<a href="../zgodovina" class="active">Zgodovina sodelovanja</a> <a href="{{ROUTE_PREFIX}}/zgodovina" class="active">Zgodovina sodelovanja</a>
<a href="../pogodbe">Ekipa</a> <a href="{{ROUTE_PREFIX}}/pogodbe">Ekipa</a>
</div> </div>
</div> </div>
</div> </div>
@@ -88,7 +90,13 @@
}%} }%}
{% if upload_history|length == 0 %}
<div class="row">
<div class="col-6">
<p>Zgodovina sodelovanja je trenutno še prazna.</p>
</div>
</div>
{% endif %}
{% for item in upload_history %} {% for item in upload_history %}
{% set item_values = [] %} {% set item_values = [] %}
{% if institution_names[loop.index - 1] %} {% if institution_names[loop.index - 1] %}
@@ -127,7 +135,7 @@
<div class="history-item-date">Dodano {{ item.timestamp.strftime('%d. %m. %Y') }}</div> <div class="history-item-date">Dodano {{ item.timestamp.strftime('%d. %m. %Y') }}</div>
<div class="history-item-uploader">{{ uploader_names[loop.index - 1] }}</div> <div class="history-item-uploader">{{ uploader_names[loop.index - 1] }}</div>
<div class="history-item-filecount">Št. datotek: {{ item.upload_file_hashes|length }}</div> <div class="history-item-filecount">Št. datotek: {{ item.upload_file_hashes|length }}</div>
<div class="history-item-chevron"><img src="../static/image/chevron-down.svg"/></div> <div class="history-item-chevron"><img src="{{ROUTE_PREFIX}}/static/image/chevron-down.svg"/></div>
<div class="history-item-desc"> <div class="history-item-desc">
{{ item_values | join(" | ") |truncate(120) }} {{ item_values | join(" | ") |truncate(120) }}
</div> </div>
@@ -144,7 +152,7 @@
{% if item.upload_file_names != None %} {% if item.upload_file_names != None %}
{% for f_name in item.upload_file_names %} {% for f_name in item.upload_file_names %}
<div class="file-item"> <div class="file-item">
<div class="file-icon"><img src="../static/image/file.svg"/></div> <div class="file-icon"><img src="{{ROUTE_PREFIX}}/static/image/file.svg"/></div>
<a href="getuploadfile/{{item.id}}/{{item.upload_file_hashes[loop.index - 1]}}" class="file-name" {% if item.upload_file_codes != None %}download="{{item.upload_file_codes[loop.index - 1]}}.{{f_name.split('.')[1]}}"{%endif%}> <a href="getuploadfile/{{item.id}}/{{item.upload_file_hashes[loop.index - 1]}}" class="file-name" {% if item.upload_file_codes != None %}download="{{item.upload_file_codes[loop.index - 1]}}.{{f_name.split('.')[1]}}"{%endif%}>
{% if item.upload_file_codes != None %} {% if item.upload_file_codes != None %}
{{item.upload_file_codes[loop.index - 1]}}.{{f_name.split('.')[1]}} {{item.upload_file_codes[loop.index - 1]}}.{{f_name.split('.')[1]}}
@@ -161,7 +169,7 @@
{% else %} {% else %}
{% for f_hash in item.upload_file_hashes %} {% for f_hash in item.upload_file_hashes %}
<div class="file-item"> <div class="file-item">
<div class="file-icon"><img src="../static/image/file.svg"/></div> <div class="file-icon"><img src="{{ROUTE_PREFIX}}/static/image/file.svg"/></div>
<a href="getuploadfile/{{item.id}}/{{f_hash}}" class="file-name">{{f_hash}}</a> <a href="getuploadfile/{{item.id}}/{{f_hash}}" class="file-name">{{f_hash}}</a>
</div> </div>
{% endfor %} {% endfor %}