model changes, user institution history, style changes, forgot passowrd functionality, etc.
This commit is contained in:
parent
7da73f7d6a
commit
788f3bc3eb
|
@ -13,6 +13,6 @@ WORKDIR /usr/src/portal-webapp
|
|||
RUN apt-get update && apt-get -y install wkhtmltopdf && \
|
||||
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 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
|
||||
|
||||
ENTRYPOINT ["./entrypoint.sh"]
|
||||
|
|
136
app.py
136
app.py
|
@ -123,7 +123,8 @@ upload_handler_regular = portal.regular.UploadHandlerRegular(
|
|||
MAIL_SUBJECT=MAIL_SUBJECT,
|
||||
MAIL_BODY=MAIL_BODY,
|
||||
CONTRACT_CLIENT_CONTACT=CONTRACT_CLIENT_CONTACT,
|
||||
MAX_FILES_PER_UPLOAD=MAX_FILES_PER_UPLOAD
|
||||
MAX_FILES_PER_UPLOAD=MAX_FILES_PER_UPLOAD,
|
||||
APP_SECRET_KEY=APP_SECRET_KEY
|
||||
)
|
||||
|
||||
upload_handler_solar = portal.solar.UploadHandlerSolar(
|
||||
|
@ -136,7 +137,8 @@ upload_handler_solar = portal.solar.UploadHandlerSolar(
|
|||
MAIL_SUBJECT=MAIL_SUBJECT,
|
||||
MAIL_BODY=MAIL_BODY,
|
||||
CONTRACT_CLIENT_CONTACT=CONTRACT_CLIENT_CONTACT,
|
||||
MAX_FILES_PER_UPLOAD=MAX_FILES_PER_UPLOAD
|
||||
MAX_FILES_PER_UPLOAD=MAX_FILES_PER_UPLOAD,
|
||||
APP_SECRET_KEY=APP_SECRET_KEY
|
||||
)
|
||||
|
||||
|
||||
|
@ -217,6 +219,9 @@ def solar_register_post():
|
|||
name = request.form.get('name')
|
||||
email = request.form.get('email')
|
||||
password = request.form.get('password')
|
||||
institution_name = request.form.get('institution')
|
||||
institution_role = request.form.get('role')
|
||||
institution = portal.base.get_institution_obj_by_name(institution_name)
|
||||
|
||||
user = RegisteredUser.query.filter_by(email=email).first()
|
||||
|
||||
|
@ -248,7 +253,17 @@ def solar_register_post():
|
|||
flash('Predolgo geslo.')
|
||||
return redirect('/solar/register')
|
||||
|
||||
portal.base.register_new_user(name, email, password, active=False)
|
||||
if not institution:
|
||||
flash('Institucija ne obstaja.')
|
||||
return redirect('/solar/register')
|
||||
|
||||
if institution_role not in ['coordinator', 'mentor', 'other']:
|
||||
flash('Neveljavna vloga v instituciji.')
|
||||
return redirect('/solar/register')
|
||||
|
||||
|
||||
user_id = portal.base.register_new_user(name, email, password, active=False)
|
||||
portal.base.add_user_to_institution(user_id, institution.id, institution_role)
|
||||
|
||||
flash('Uspešna registracija.')
|
||||
return redirect('/solar/login')
|
||||
|
@ -270,13 +285,20 @@ def logout():
|
|||
def solar(text):
|
||||
is_admin = current_user.role == 'admin'
|
||||
current_user_institution = portal.base.get_user_institution(current_user.id)
|
||||
current_user_obj = portal.base.get_user_obj(current_user.get_id())
|
||||
institution_contract = None
|
||||
if current_user_institution:
|
||||
current_user_institution_moderator = portal.base.is_institution_moderator(current_user.id, current_user_institution.id)
|
||||
current_user_institution_coordinator = portal.base.is_institution_coordinator(current_user.id, current_user_institution.id)
|
||||
institution_contract = portal.base.get_institution_contract(current_user_institution.id)
|
||||
else:
|
||||
current_user_institution_moderator = False
|
||||
current_user_institution_coordinator = False
|
||||
|
||||
if text.startswith('oddaja/') or text == 'oddaja':
|
||||
return render_template('solar-oddaja.html', is_admin=is_admin, is_institution_moderator=current_user_institution_moderator)
|
||||
return render_template('solar-oddaja.html',
|
||||
is_admin=is_admin,
|
||||
institution=current_user_institution,
|
||||
institution_contract=institution_contract,
|
||||
is_institution_coordinator=current_user_institution_coordinator)
|
||||
elif text.startswith('zgodovina/') or text == 'zgodovina':
|
||||
upload_items = portal.solar.get_upload_history(current_user.id)
|
||||
uploader_names = []
|
||||
|
@ -289,58 +311,66 @@ def solar(text):
|
|||
else:
|
||||
institution_names.append(institution.name)
|
||||
return render_template('solar-zgodovina.html', upload_history=upload_items, uploader_names=uploader_names,
|
||||
institution_names=institution_names, is_admin=is_admin, is_institution_moderator=current_user_institution_moderator)
|
||||
elif text.startswith('pogodbe/') or text == 'pogodbe':
|
||||
institution_names=institution_names, is_admin=is_admin, is_institution_coordinator=current_user_institution_coordinator)
|
||||
elif text.startswith('pogodbe-institucije/') or text.startswith('pogodbe-ucencistarsi/'):
|
||||
# Check for ownload contract request.
|
||||
match = re.match('^pogodbe/([a-z0-9_]+\.pdf)$', text)
|
||||
match = re.match('^pogodbe-(institucije|ucencistarsi)/([a-z0-9_]+\.pdf)$', text)
|
||||
if match:
|
||||
filename = match.group(1)
|
||||
contract_type = match.group(1)
|
||||
filename = match.group(2)
|
||||
if len(filename) < 10:
|
||||
return '', 404
|
||||
prefix = filename[:2]
|
||||
suffix = filename[2:]
|
||||
f_hash = filename.split('.')[0]
|
||||
|
||||
if contract_type == 'institucije':
|
||||
actual_filename = portal.base.get_actual_institution_contract_filename(f_hash)
|
||||
else:
|
||||
actual_filename = portal.base.get_actual_studentparent_contract_filename(f_hash)
|
||||
|
||||
safe_path = safe_join(str(upload_handler_solar.get_uploads_subdir('contracts')), prefix, suffix)
|
||||
try:
|
||||
return send_file(safe_path, as_attachment=True)
|
||||
return send_file(safe_path, attachment_filename=actual_filename, as_attachment=True)
|
||||
except FileNotFoundError:
|
||||
return '', 404
|
||||
|
||||
user_obj = portal.base.get_user_obj(current_user.get_id())
|
||||
institution = portal.base.get_user_institution(user_obj.id)
|
||||
elif text.startswith('pogodbe/') or text == 'pogodbe':
|
||||
contracts_students = []
|
||||
contract_school = []
|
||||
enable_upload_school_contract = False
|
||||
show_upload_form = False
|
||||
collaborators = []
|
||||
if institution:
|
||||
collaborators = portal.base.get_all_active_institution_users(institution.id)
|
||||
cooperation_history = dict()
|
||||
if current_user_institution:
|
||||
collaborators = portal.base.get_all_active_institution_users(current_user_institution.id)
|
||||
show_upload_form = True
|
||||
contract_school = portal.solar.get_institution_contract(institution.id)
|
||||
if portal.base.is_institution_moderator(user_obj.id, institution.id):
|
||||
contracts_students = portal.solar.get_institution_student_contracts(institution.id)
|
||||
contract_school = portal.solar.get_institution_contract(current_user_institution.id)
|
||||
cooperation_history = portal.base.get_institution_cooperation_history(current_user_institution.id)
|
||||
if portal.base.is_institution_coordinator(current_user_obj.id, current_user_institution.id):
|
||||
contracts_students = portal.solar.get_institution_student_contracts(current_user_institution.id)
|
||||
enable_upload_school_contract = True
|
||||
else:
|
||||
contracts_students = portal.solar.get_institution_student_contracts(institution.id, 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,
|
||||
contract_school=contract_school,
|
||||
enable_upload_school_contract=enable_upload_school_contract,
|
||||
show_upload_form=show_upload_form,
|
||||
collaborators=collaborators,
|
||||
is_admin=is_admin, is_institution_moderator=current_user_institution_moderator)
|
||||
cooperation_history=cooperation_history,
|
||||
is_admin=is_admin, is_institution_coordinator=current_user_institution_coordinator)
|
||||
elif text.startswith('admin/') or text == 'admin':
|
||||
users = portal.base.get_all_active_users_join_institutions()
|
||||
inactive_users = portal.base.get_all_inactive_users()
|
||||
users = portal.base.get_all_users_join_institutions()
|
||||
inactive_users = portal.base.get_all_users_join_institutions(active=False)
|
||||
solar_institutions = portal.solar.get_all_institutions()
|
||||
cooperation_history = portal.base.get_cooperation_history()
|
||||
if is_admin:
|
||||
return render_template('solar-admin.html', users=users,
|
||||
return render_template('solar-admin.html', users=users, user_cooperation_history=cooperation_history,
|
||||
institutions=solar_institutions, inactive_users=inactive_users)
|
||||
elif text.startswith('manage-institution/') or text == 'manage-institution':
|
||||
institution = portal.base.get_user_institution(current_user.id)
|
||||
if portal.base.is_institution_moderator(current_user.id, institution.id):
|
||||
if portal.base.is_institution_coordinator(current_user.id, current_user_institution.id):
|
||||
solar_users = portal.base.get_all_active_users()
|
||||
institution_users = portal.base.get_all_active_institution_users(institution.id)
|
||||
institution_users = portal.base.get_all_active_institution_users(current_user_institution.id)
|
||||
return render_template('solar-manage-institution.html', users=solar_users,
|
||||
institution_users=institution_users)
|
||||
return '', 404
|
||||
|
@ -420,7 +450,7 @@ def solar_forgotpass():
|
|||
def solar_sendresetpass():
|
||||
email = request.form.get('email')
|
||||
|
||||
portal.base.send_resetpass_mail(email, upload_handler_regular.config)
|
||||
portal.base.send_resetpass_mail(email, upload_handler_solar.config)
|
||||
|
||||
flash('Povezava za ponastavitev gesla je bila poslana na vpisan email naslov.')
|
||||
return redirect(redirect_url())
|
||||
|
@ -428,7 +458,7 @@ def solar_sendresetpass():
|
|||
|
||||
@app.route('/solar/resetpass/<token>')
|
||||
def solar_resetpass(token):
|
||||
user = portal.base.verify_reset_token(token)
|
||||
user = portal.base.verify_reset_token(token, upload_handler_solar.config['APP_SECRET_KEY'])
|
||||
|
||||
if not user:
|
||||
return '', 404
|
||||
|
@ -439,7 +469,7 @@ def solar_resetpass(token):
|
|||
@app.route('/solar/resetpass/<token>', methods=['POST'])
|
||||
def solar_resetpass_post(token):
|
||||
new_password = request.form.get('new_password')
|
||||
user = portal.base.verify_reset_token(token)
|
||||
user = portal.base.verify_reset_token(token, upload_handler_solar.config['APP_SECRET_KEY'])
|
||||
|
||||
if not user:
|
||||
return '', 404
|
||||
|
@ -448,7 +478,8 @@ def solar_resetpass_post(token):
|
|||
if rowcount == 0:
|
||||
return '', 404
|
||||
|
||||
return 'Ponastavitev gesla uspešna.'
|
||||
flash('Ponastavitev gesla je bila uspešna.')
|
||||
return redirect('/solar/login')
|
||||
|
||||
|
||||
@app.route('/solar/topuploads')
|
||||
|
@ -460,9 +491,12 @@ def solar_topuploads_srednje():
|
|||
@app.route('/solar/deluser', methods=['POST'])
|
||||
@login_required
|
||||
def solar_del_user():
|
||||
# TODO: check if user is institution moderator for the added users institution or is an admin
|
||||
# TODO: delete from "user", "user_institution_mapping", update "institution_contract" set user to NULL
|
||||
return '', 404
|
||||
if not portal.base.is_admin(current_user.id):
|
||||
return '', 404
|
||||
user_id = request.form.get('user_id')
|
||||
portal.base.del_user(user_id)
|
||||
flash('Uporabnik je bil odstranjen.')
|
||||
return redirect(redirect_url())
|
||||
|
||||
@app.route('/<corpus_name>/addinstitution', methods=['POST'])
|
||||
@login_required
|
||||
|
@ -482,11 +516,8 @@ def add_institution(corpus_name):
|
|||
flash('Predolgo ime.')
|
||||
return redirect(redirect_url())
|
||||
|
||||
if not region:
|
||||
flash('Prazno polje za regijo.')
|
||||
return redirect(redirect_url())
|
||||
if len(region) > 100:
|
||||
flash('Predolgi niz za regijo.')
|
||||
if not region in portal.solar.VALID_REGIONS:
|
||||
flash('Neveljavna vrednost za regijo.')
|
||||
return redirect(redirect_url())
|
||||
|
||||
institution_id = portal.base.add_institution(name, region)
|
||||
|
@ -506,37 +537,34 @@ def add_user_institution_mapping(corpus_name):
|
|||
if institution:
|
||||
institution_id = institution.id
|
||||
|
||||
if not (portal.base.is_admin(current_user.id) or portal.base.is_institution_moderator(current_user.id, institution_id)):
|
||||
if not (portal.base.is_admin(current_user.id) or portal.base.is_institution_coordinator(current_user.id, institution_id)):
|
||||
return '', 404
|
||||
|
||||
user_id = request.form['user_id']
|
||||
role = request.form['role']
|
||||
if role not in ['moderator', 'user']:
|
||||
if role not in ['coordinator', 'mentor', 'other']:
|
||||
return '', 404
|
||||
|
||||
if portal.base.get_user_institution(user_id):
|
||||
flash('Uporabnik je že dodeljen instituciji. Dodeljevanje večim institucijam '\
|
||||
'zaenkrat ni implementirano.')
|
||||
flash('Uporabnik je že dodeljen instituciji.')
|
||||
return redirect(redirect_url())
|
||||
|
||||
portal.base.add_user_to_institution(user_id, institution_id, role)
|
||||
flash('Uporabnik je bil dodeljen instituciji.')
|
||||
return redirect(redirect_url())
|
||||
|
||||
@app.route('/<corpus_name>/deluserfrominstitution', methods=['POST'])
|
||||
@app.route('/solar/deluserfrominstitution', methods=['POST'])
|
||||
@login_required
|
||||
def del_user_institution_mapping(corpus_name):
|
||||
institution = portal.base.get_user_institution(current_user.id)
|
||||
if not portal.base.is_admin(current_user.id) \
|
||||
and not portal.base.is_institution_moderator(current_user.id, institution.id):
|
||||
return '', 404
|
||||
if not corpus_name in ENABLED_CORPUSES:
|
||||
return '', 404
|
||||
|
||||
def del_user_institution_mapping():
|
||||
user_id = request.form['user_id']
|
||||
institution = portal.base.get_user_institution(user_id)
|
||||
if not institution:
|
||||
flash('Uporabnik ni član nobene institucije.')
|
||||
return redirect(redirect_url())
|
||||
|
||||
if not portal.base.is_institution_member(user_id, institution.id):
|
||||
flash('Uporabnik ni član vaše institucije.')
|
||||
if not portal.base.is_admin(current_user.id) \
|
||||
and not portal.base.is_institution_coordinator(current_user.id, institution.id):
|
||||
flash('Nimate ustreznih pravic za odstranitev uporabnika iz institucije.')
|
||||
return redirect(redirect_url())
|
||||
|
||||
portal.base.del_user_from_institution(user_id, institution.id)
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
"""Added UserCooperationHistory.
|
||||
|
||||
Revision ID: 4c132220432f
|
||||
Revises: ff356b1ef661
|
||||
Create Date: 2021-09-01 09:25:43.144096
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '4c132220432f'
|
||||
down_revision = 'ff356b1ef661'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('user_cooperation',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user', sa.Integer(), nullable=False),
|
||||
sa.Column('institution', sa.Integer(), nullable=False),
|
||||
sa.Column('role', sa.String(), nullable=False),
|
||||
sa.Column('badge_text', sa.String(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['institution'], ['institution.id'], ),
|
||||
sa.ForeignKeyConstraint(['user'], ['registered_user.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('user_cooperation')
|
||||
# ### end Alembic commands ###
|
|
@ -0,0 +1,28 @@
|
|||
"""Added school year column to user history.
|
||||
|
||||
Revision ID: c60b7bfaaf85
|
||||
Revises: 4c132220432f
|
||||
Create Date: 2021-09-02 08:36:41.711040
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'c60b7bfaaf85'
|
||||
down_revision = '4c132220432f'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('user_cooperation', sa.Column('school_year', sa.String(), nullable=False))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('user_cooperation', 'school_year')
|
||||
# ### end Alembic commands ###
|
|
@ -0,0 +1,58 @@
|
|||
"""Dropped out predavanje stuff, added contract initial file name.
|
||||
|
||||
Revision ID: ff356b1ef661
|
||||
Revises: 5ba116fc7f06
|
||||
Create Date: 2021-08-26 12:45:56.036966
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'ff356b1ef661'
|
||||
down_revision = '5ba116fc7f06'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('stamps_solar')
|
||||
op.drop_table('upload_predavanja')
|
||||
op.add_column('contracts_solar', sa.Column('original_filename', sa.String(), nullable=True))
|
||||
op.add_column('institution_contract', sa.Column('original_filename', sa.String(), nullable=True))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('institution_contract', 'original_filename')
|
||||
op.drop_column('contracts_solar', 'original_filename')
|
||||
op.create_table('upload_predavanja',
|
||||
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
|
||||
sa.Column('upload_hash', sa.VARCHAR(), autoincrement=False, nullable=False),
|
||||
sa.Column('timestamp', postgresql.TIMESTAMP(), autoincrement=False, nullable=False),
|
||||
sa.Column('name', sa.VARCHAR(), autoincrement=False, nullable=False),
|
||||
sa.Column('address', sa.VARCHAR(), autoincrement=False, nullable=False),
|
||||
sa.Column('subject', sa.VARCHAR(), autoincrement=False, nullable=False),
|
||||
sa.Column('faculty', sa.VARCHAR(), autoincrement=False, nullable=False),
|
||||
sa.Column('email', sa.VARCHAR(), autoincrement=False, nullable=False),
|
||||
sa.Column('phone', sa.VARCHAR(), autoincrement=False, nullable=True),
|
||||
sa.Column('keywords', sa.VARCHAR(), autoincrement=False, nullable=False),
|
||||
sa.Column('file_contract', sa.VARCHAR(), autoincrement=False, nullable=True),
|
||||
sa.Column('upload_file_hashes', postgresql.ARRAY(sa.VARCHAR()), autoincrement=False, nullable=True),
|
||||
sa.Column('agree_publish_future', sa.TEXT(), autoincrement=False, nullable=False),
|
||||
sa.Column('agree_machine_translation', sa.BOOLEAN(), autoincrement=False, nullable=False),
|
||||
sa.Column('agree_news_cjvt', sa.BOOLEAN(), autoincrement=False, nullable=False),
|
||||
sa.PrimaryKeyConstraint('id', name='upload_predavanja_pkey')
|
||||
)
|
||||
op.create_table('stamps_solar',
|
||||
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
|
||||
sa.Column('institution', sa.INTEGER(), autoincrement=False, nullable=True),
|
||||
sa.Column('name', sa.TEXT(), autoincrement=False, nullable=False),
|
||||
sa.Column('file_logo', sa.TEXT(), autoincrement=False, nullable=True),
|
||||
sa.ForeignKeyConstraint(['institution'], ['institution.id'], name='stamps_institution_fkey'),
|
||||
sa.PrimaryKeyConstraint('id', name='stamps_pkey')
|
||||
)
|
||||
# ### end Alembic commands ###
|
|
@ -25,7 +25,7 @@ import jwt
|
|||
|
||||
from werkzeug.security import generate_password_hash
|
||||
|
||||
from . model import db, UploadRegular, UploadSolar, RegisteredUser, UserInstitutionMapping, Institution, InstitutionContract, CorpusAccess
|
||||
from . model import *
|
||||
|
||||
|
||||
#REGEX_EMAIL = re.compile('^[a-z0-9]+[\._]?[a-z0-9]+[@]\w+[.]\w{2,3}$')
|
||||
|
@ -248,6 +248,33 @@ def get_user_institution(user_id):
|
|||
return None
|
||||
|
||||
|
||||
def get_institution_contract(institution_id):
|
||||
return InstitutionContract.query.filter_by(institution=institution_id).first()
|
||||
|
||||
|
||||
def get_institution_cooperation_history(institution_id):
|
||||
#return CooperationToken.query.join(UserCooperationTokenMapping,
|
||||
# UserCooperationTokenMapping.cooperation_token == CooperationToken.id).filter(UserCooperationTokenMapping.user == user_id).all()
|
||||
#
|
||||
res = dict()
|
||||
|
||||
uch_rows = UserCooperationHistory.query.filter_by(institution=institution_id).order_by(UserCooperationHistory.school_year.desc()).all()
|
||||
for row in uch_rows:
|
||||
if row.user not in res:
|
||||
res[row.user] = {
|
||||
'coordinator': [],
|
||||
'moderator': [],
|
||||
'other': []
|
||||
}
|
||||
res[row.user][row.role].append(row.school_year)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def get_cooperation_history():
|
||||
return UserCooperationHistory.query.all()
|
||||
|
||||
|
||||
def has_user_corpus_access(user_id, corpus_name):
|
||||
user = RegisteredUser.query.filter_by(id=user_id).first()
|
||||
|
||||
|
@ -281,6 +308,10 @@ def get_institution_obj(institution_id):
|
|||
return Institution.query.filter_by(id=institution_id).first()
|
||||
|
||||
|
||||
def get_institution_obj_by_name(institution_name):
|
||||
return Institution.query.filter_by(name=institution_name).first()
|
||||
|
||||
|
||||
def register_new_user(name, email, password, active=True, admin=False):
|
||||
model_obj = RegisteredUser(
|
||||
name=name,
|
||||
|
@ -334,11 +365,18 @@ def activate_user(user_id):
|
|||
|
||||
def update_user_password(user_id, new_password):
|
||||
phash = generate_password_hash(new_password)
|
||||
rowcount = db.session.query(RegisteredUser).filter_by(id=user_id).update({'pass_hash': pass_hash})
|
||||
rowcount = db.session.query(RegisteredUser).filter_by(id=user_id).update({'pass_hash': phash})
|
||||
db.session.commit()
|
||||
return rowcount
|
||||
|
||||
|
||||
def del_user(user_id):
|
||||
db.session.query(UserCooperationHistory).filter(UserCooperationHistory.user == user_id).delete()
|
||||
db.session.query(UserInstitutionMapping).filter(UserInstitutionMapping.user == user_id).delete()
|
||||
db.session.query(RegisteredUser).filter(RegisteredUser.id == user_id).delete()
|
||||
db.session.commit()
|
||||
|
||||
|
||||
def del_user_from_institution(user_id, institution_id):
|
||||
db.session.query(UserInstitutionMapping).filter(UserInstitutionMapping.institution == institution_id).filter(UserInstitutionMapping.user == user_id).delete()
|
||||
db.session.commit()
|
||||
|
@ -347,24 +385,28 @@ def del_user_from_institution(user_id, institution_id):
|
|||
def get_all_active_users():
|
||||
return RegisteredUser.query.filter_by(active=True).order_by(RegisteredUser.id).all()
|
||||
|
||||
|
||||
def get_all_inactive_users():
|
||||
return RegisteredUser.query.filter_by(active=False).order_by(RegisteredUser.id).all()
|
||||
|
||||
def get_all_active_users_join_institutions():
|
||||
|
||||
def get_all_users_join_institutions(active=True):
|
||||
#return RegisteredUser.query.filter_by(active=True).order_by(RegisteredUser.id).all()
|
||||
return db.session.query(RegisteredUser, UserInstitutionMapping).outerjoin(UserInstitutionMapping,
|
||||
RegisteredUser.id == UserInstitutionMapping.user).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):
|
||||
return RegisteredUser.query.filter_by(active=True).join(UserInstitutionMapping,
|
||||
RegisteredUser.id == UserInstitutionMapping.user).filter(UserInstitutionMapping.institution == institution_id).all()
|
||||
|
||||
|
||||
def is_institution_moderator(user_id, institution_id):
|
||||
def is_institution_coordinator(user_id, institution_id):
|
||||
user_inst_mapping = UserInstitutionMapping.query.filter_by(user=user_id).filter_by(institution=institution_id).first()
|
||||
if not user_inst_mapping:
|
||||
return False
|
||||
if user_inst_mapping.role != 'moderator':
|
||||
if user_inst_mapping.role != 'coordinator':
|
||||
return False
|
||||
return True
|
||||
|
||||
|
@ -376,15 +418,34 @@ def is_institution_member(user_id, institution_id):
|
|||
return True
|
||||
|
||||
|
||||
def get_password_reset_token(email, expires=500):
|
||||
return jwt.encode({'reset_password': email,
|
||||
'exp': time() + expires},
|
||||
key=os.getenv('APP_SECRET_KEY'), algorithm='HS256')
|
||||
def get_actual_institution_contract_filename(f_hash):
|
||||
contract = InstitutionContract.query.filter_by(file_contract=f_hash).first()
|
||||
if contract:
|
||||
return contract.original_filename
|
||||
return None
|
||||
|
||||
def verify_reset_token(token):
|
||||
|
||||
def get_actual_studentparent_contract_filename(f_hash):
|
||||
contract = ContractsSolar.query.filter_by(file_contract=f_hash).first()
|
||||
if contract:
|
||||
return contract.original_filename
|
||||
return None
|
||||
|
||||
|
||||
def get_password_reset_token(email, key, expires=600):
|
||||
return jwt.encode({'reset_password': email,
|
||||
'exp': int(time.time()) + expires},
|
||||
key=key, algorithm='HS256')
|
||||
|
||||
def verify_reset_token(token, key):
|
||||
try:
|
||||
email = jwt.decode(token,
|
||||
key=os.getenv('APP_SECRET_KEY'), algorithms=["HS256"])['reset_password']
|
||||
message = jwt.decode(token,
|
||||
key=key, algorithms=["HS256"])
|
||||
email = message['reset_password']
|
||||
exp = message['exp']
|
||||
if int(time.time()) >= exp:
|
||||
# Token timed out
|
||||
return None
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
return
|
||||
|
@ -392,13 +453,12 @@ def verify_reset_token(token):
|
|||
|
||||
|
||||
def send_resetpass_mail(email, config):
|
||||
jwt_token = get_password_reset_token(email)
|
||||
jwt_token = get_password_reset_token(email, config['APP_SECRET_KEY'])
|
||||
|
||||
text = '''
|
||||
Zahtevali ste ponastavitev gesla vašega uporabniškega računa.
|
||||
|
||||
Geslo lahko ponastavite na naslednji povezavi: https://zbiranje.slovenscina.eu/solar/resetpass/{}'''.format(
|
||||
'https://zbiranje.slovenscina.eu/solar/resetpass/{}'.format(jwt_token))
|
||||
Geslo lahko ponastavite na naslednji povezavi: https://zbiranje.slovenscina.eu/solar/resetpass/{}'''.format(jwt_token)
|
||||
|
||||
# Create a secure SSL context
|
||||
context = ssl.create_default_context()
|
||||
|
|
|
@ -28,25 +28,6 @@ class UploadRegular(db.Model):
|
|||
corpus_name = db.Column(db.String, nullable=False)
|
||||
|
||||
|
||||
class UploadPredavanja(db.Model):
|
||||
__tablename__ = 'upload_predavanja'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
upload_hash = db.Column(db.String, nullable=False)
|
||||
timestamp = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
||||
name = db.Column(db.String, nullable=False)
|
||||
address = db.Column(db.String, nullable=False)
|
||||
subject = db.Column(db.String, nullable=False)
|
||||
faculty = db.Column(db.String, nullable=False)
|
||||
email = db.Column(db.String, nullable=False)
|
||||
phone = db.Column(db.String, nullable=True)
|
||||
keywords = db.Column(db.String, nullable=False)
|
||||
agree_publish_future = db.Column(db.String, nullable=False)
|
||||
agree_machine_translation = db.Column(db.Boolean, default=False, nullable=False)
|
||||
agree_news_cjvt = db.Column(db.Boolean, default=False, nullable=False)
|
||||
file_contract = db.Column(db.String, nullable=True)
|
||||
upload_file_hashes = db.Column(sqlalchemy.types.ARRAY(db.String), nullable=True)
|
||||
|
||||
|
||||
class UploadSolar(db.Model):
|
||||
__tablename__ = 'upload_solar'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
@ -65,14 +46,6 @@ class UploadSolar(db.Model):
|
|||
upload_file_hashes = db.Column(sqlalchemy.types.ARRAY(db.String), nullable=True)
|
||||
|
||||
|
||||
class StampsSolar(db.Model):
|
||||
__tablename__ = 'stamps_solar'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
institution = db.Column(db.Integer, sqlalchemy.ForeignKey('institution.id'), nullable=True)
|
||||
name = db.Column(db.String, nullable=False)
|
||||
file_logo = db.Column(db.String, nullable=True)
|
||||
|
||||
|
||||
class ContractsSolar(db.Model):
|
||||
__tablename__ = 'contracts_solar'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
@ -80,6 +53,7 @@ class ContractsSolar(db.Model):
|
|||
upload_user = db.Column(db.Integer, sqlalchemy.ForeignKey('registered_user.id'), nullable=True)
|
||||
timestamp = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
||||
file_contract = db.Column(db.String, nullable=False)
|
||||
original_filename = db.Column(db.String, nullable=True)
|
||||
contract_type = db.Column(db.String, nullable=False)
|
||||
|
||||
|
||||
|
@ -100,7 +74,29 @@ class UserInstitutionMapping(db.Model):
|
|||
id = db.Column(db.Integer, primary_key=True)
|
||||
user = db.Column(db.Integer, sqlalchemy.ForeignKey('registered_user.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)
|
||||
|
||||
|
||||
#class CooperationToken(db.Model):
|
||||
# __tablename__ = 'cooperation_token'
|
||||
# id = db.Column(db.Integer, primary_key=True)
|
||||
# name = db.Column(db.String, nullable=False)
|
||||
#
|
||||
#
|
||||
#class UserCooperationTokenMapping(db.Model):
|
||||
# __tablename__ = 'user_cooperation_token_mapping'
|
||||
# id = db.Column(db.Integer, primary_key=True)
|
||||
# user = db.Column(db.Integer, sqlalchemy.ForeignKey('registered_user.id'), nullable=False)
|
||||
# cooperation_token = db.Column(db.Integer, sqlalchemy.ForeignKey('cooperation_token.id'), nullable=False)
|
||||
|
||||
class UserCooperationHistory(db.Model):
|
||||
__tablename__ = 'user_cooperation'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
user = db.Column(db.Integer, sqlalchemy.ForeignKey('registered_user.id'), nullable=False)
|
||||
institution = db.Column(db.Integer, sqlalchemy.ForeignKey('institution.id'), nullable=False)
|
||||
role = db.Column(db.String, nullable=False)
|
||||
school_year = db.Column(db.String, nullable=False)
|
||||
badge_text = db.Column(db.String, nullable=True)
|
||||
|
||||
|
||||
class Institution(db.Model):
|
||||
|
@ -124,4 +120,5 @@ class InstitutionContract(db.Model):
|
|||
corpus = db.Column(db.String, nullable=False)
|
||||
timestamp = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
||||
file_contract = db.Column(db.String, nullable=True)
|
||||
original_filename = db.Column(db.String, nullable=True)
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ VALID_PROGRAMS = {'OS', 'SSG', 'MGP', 'ZG', 'NPI', 'SPI', 'SSI', 'PTI'}
|
|||
VALID_SUBJECTS = {'slo', 'drug-jez', 'drug-druz', 'drug-narav', 'drug-strok', 'drug-izb'}
|
||||
VALID_TEXT_TYPES = {'esej-spis', 'prakticno', 'solski-test', 'delo-v-razredu'}
|
||||
VALID_GRAMMAR_CORRECTIONS = {'popr-ne', 'brez-popr', 'popr-da'}
|
||||
VALID_REGIONS = {'CE', 'GO', 'KK', 'KP', 'KR', 'LJ', 'MB', 'MS', 'NM', 'PO', 'SG'}
|
||||
|
||||
MAXLEN_FORM = 150
|
||||
|
||||
|
@ -109,17 +110,18 @@ class UploadHandlerSolar(UploadHandler):
|
|||
if user_institution_mapping is None:
|
||||
return 'Vaš uporabnik ni dodeljen nobeni inštituciji.'
|
||||
institution_id = user_institution_mapping.institution
|
||||
is_institution_moderator = True if user_institution_mapping.role == 'moderator' else False
|
||||
is_institution_coordinator = True if user_institution_mapping.role == 'coordinator' else False
|
||||
|
||||
if contract_type == 'sola':
|
||||
if not is_institution_moderator:
|
||||
if not is_institution_coordinator:
|
||||
return 'Vaš uporabnik nima pravic za nalaganje pogodbe s šolo.'
|
||||
# TODO: insert institution contract
|
||||
model_obj = InstitutionContract(
|
||||
institution=institution_id,
|
||||
corpus='solar',
|
||||
timestamp=timestamp,
|
||||
file_contract=f_hash
|
||||
file_contract=f_hash,
|
||||
original_filename=f_obj.filename
|
||||
)
|
||||
self.store_model(model_obj)
|
||||
else:
|
||||
|
@ -129,6 +131,7 @@ class UploadHandlerSolar(UploadHandler):
|
|||
timestamp=timestamp,
|
||||
file_contract=f_hash,
|
||||
contract_type=contract_type,
|
||||
original_filename=f_obj.filename
|
||||
)
|
||||
|
||||
self.store_model(model_obj)
|
||||
|
|
BIN
static/image/contract.png
Normal file
BIN
static/image/contract.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
BIN
static/image/password.png
Normal file
BIN
static/image/password.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
static/image/register.png
Normal file
BIN
static/image/register.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
BIN
static/image/showpass.png
Normal file
BIN
static/image/showpass.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
static/image/star.png
Normal file
BIN
static/image/star.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
BIN
static/image/user.png
Normal file
BIN
static/image/user.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -142,33 +142,50 @@ label {
|
|||
}
|
||||
|
||||
.contract-item {
|
||||
height: 50px;
|
||||
height: 65px;
|
||||
margin: 5px;
|
||||
border: 0px;
|
||||
border-bottom: 2px solid #c4c4c4;
|
||||
}
|
||||
|
||||
.contract-item-icon {
|
||||
height: 50%;
|
||||
margin-top: 15px;
|
||||
margin-left: 15px;
|
||||
margin-right: 15px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.contract-item-title {
|
||||
font-family: Roboto;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
color: #46535b;
|
||||
padding-top: 10px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.contract-item-button {
|
||||
font-family: Roboto;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
float: right;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
.contract-item-date {
|
||||
.contract-item-data {
|
||||
font-family: Roboto;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 10px;
|
||||
color: #46535b;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
#collaborators-container {
|
||||
|
@ -200,6 +217,33 @@ label {
|
|||
margin: 25px;
|
||||
padding:5px;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.warning {
|
||||
background: #ffcc00;
|
||||
border-radius: 15px;
|
||||
border: 0px;
|
||||
font-family: Roboto;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
margin: 20px;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.message-notification {
|
||||
background: #99cc33;
|
||||
border-radius: 15px;
|
||||
border: 0px;
|
||||
font-family: Roboto;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
margin: 20px;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#button-submit {
|
||||
|
@ -554,6 +598,10 @@ select {
|
|||
left: 25% !important;
|
||||
}
|
||||
|
||||
.history-item {
|
||||
border-bottom: 1px solid grey;
|
||||
}
|
||||
|
||||
.history-item-date {
|
||||
font-family: Roboto;
|
||||
font-style: normal;
|
||||
|
@ -598,6 +646,7 @@ select {
|
|||
font-weight: normal;
|
||||
font-size: 12px;
|
||||
line-height: 14px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
color: #848C91;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
<label for="telefon">Telefon:</label>
|
||||
<input type="text" id="telefon" name="telefon"/>
|
||||
|
||||
<div class="form-text">*Po kliku na gumb “Oddaj” se bo prikazala vsebina pogodobe o odstopu avtorskih pravic. Če se z vsebino strinjate, kliknite gumb “Pošlji”, da podatke posredujete v korpus, po e-pošti pa boste prejeli svoj izvod pogodbe.</div>
|
||||
<div class="form-text">*Po kliku na gumb “Oddaj” se bo prikazala vsebina pogodbe o odstopu avtorskih pravic. Če se z vsebino strinjate, kliknite gumb “Pošlji”, da podatke posredujete v korpus, po e-pošti pa boste prejeli svoj izvod pogodbe.</div>
|
||||
|
||||
<button id="button-submit" type="submit">Oddaj</button>
|
||||
</div>
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<title>Admin panel - Šolar</title>
|
||||
<style>
|
||||
.tableFixHead {
|
||||
overflow-y: auto;
|
||||
height: 306px;
|
||||
overflow-y: scroll;
|
||||
max-height: 306px;
|
||||
}
|
||||
.tableFixHead thead th {
|
||||
position: sticky;
|
||||
|
@ -24,6 +24,9 @@
|
|||
th {
|
||||
background: #eee;
|
||||
}
|
||||
h2 {
|
||||
color: blue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -45,13 +48,13 @@
|
|||
<input type="password" id="password" name="password"><br>
|
||||
<input type="submit" value="Dodaj">
|
||||
</form>
|
||||
<!--<h3>Odstrani uporabnika</h3>
|
||||
<h3>Odstrani uporabnika</h3>
|
||||
<form action="/solar/deluser" method="post">
|
||||
<label for="user_id">ID uporabnika:</label><br>
|
||||
<input type="text" id="user_id" name="user_id"><br>
|
||||
<input type="submit" value="Odstrani">
|
||||
</form>-->
|
||||
<h3>Seznam vseh aktivnih uporabnikov</h3>
|
||||
</form>
|
||||
<h3>Aktivni uporabniki</h3>
|
||||
<div class="tableFixHead">
|
||||
<table>
|
||||
<thead>
|
||||
|
@ -60,6 +63,7 @@
|
|||
<th>Ime in priimek</th>
|
||||
<th>Email</th>
|
||||
<th>ID institucije</th>
|
||||
<th>Vloga v instituciji</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -69,6 +73,7 @@
|
|||
<td>{{item[0].name}}</td>
|
||||
<td>{{item[0].email}}</td>
|
||||
<td>{{item[1].institution}}</td>
|
||||
<td>{{item[1].role}}</td>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
|
@ -80,11 +85,18 @@
|
|||
<input type="text" id="institution_id" name="institution_id"><br>
|
||||
<label for="role">Vloga v instituciji:</label>
|
||||
<select name="role" id="role">
|
||||
<option value="moderator">Moderator</option>
|
||||
<option value="user">Uporabnik</option>
|
||||
<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="/solar/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>
|
||||
<h2>Institucije</h2>
|
||||
<h3>Dodaj institucijo</h3>
|
||||
|
@ -92,7 +104,19 @@
|
|||
<label for="name">Naziv:</label>
|
||||
<input type="text" id="name" name="name"><br>
|
||||
<label for="region">Regija:</label>
|
||||
<input type="text" id="region" name="region"><br>
|
||||
<select name="region" id="region">
|
||||
<option value="CE">Celje</option>
|
||||
<option value="GO">Nova Gorica</option>
|
||||
<option value="KK">Krško</option>
|
||||
<option value="KP">Koper</option>
|
||||
<option value="KR">Kranj</option>
|
||||
<option value="LJ">Ljubljana</option>
|
||||
<option value="MB">Maribor</option>
|
||||
<option value="MS">Murska Sobota</option>
|
||||
<option value="NM">Novo mesto</option>
|
||||
<option value="PO">Postojna</option>
|
||||
<option value="SG">Slovenj Gradec</option>
|
||||
</select>
|
||||
<input type="submit" value="Dodaj">
|
||||
</form>
|
||||
<h3>Seznam vseh instituticij</h3>
|
||||
|
@ -115,7 +139,7 @@
|
|||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
<h3>Seznam uporabnikov, ki niso aktivirani</h3>
|
||||
<h3>Čakajoči uporabniki</h3>
|
||||
<div class="tableFixHead">
|
||||
<table>
|
||||
<thead>
|
||||
|
@ -123,14 +147,18 @@
|
|||
<th>ID</th>
|
||||
<th>Ime in priimek</th>
|
||||
<th>Email</th>
|
||||
<th>Institucija</th>
|
||||
<th>Vloga v instituciji</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in inactive_users %}
|
||||
<tr>
|
||||
<td>{{item.id}}</td>
|
||||
<td>{{item.name}}</td>
|
||||
<td>{{item.email}}</td>
|
||||
<td>{{item[0].id}}</td>
|
||||
<td>{{item[0].name}}</td>
|
||||
<td>{{item[0].email}}</td>
|
||||
<td>{{item[1].institution}}</td>
|
||||
<td>{{item[1].role}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
@ -141,4 +169,30 @@
|
|||
<input type="text" id="id" name="id"><br>
|
||||
<input type="submit" value="Aktiviraj">
|
||||
</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>
|
||||
</body>
|
||||
|
|
|
@ -28,9 +28,8 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<button class="button-general" style="margin-top: 20px;">Pošlji povezavo za ponastavitev geslo</button>
|
||||
<button class="button-general" style="margin-top: 20px;">Pošlji</button>
|
||||
</form>
|
||||
<a href="/solar/register" class="contract-item-button">Registracija</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -8,11 +8,17 @@
|
|||
<body>
|
||||
<div id="main-window">
|
||||
<div id="rect1">
|
||||
<div style="padding: 50px;">
|
||||
<div style="padding: 25px;">
|
||||
<div id="logo-container">
|
||||
<img src="/static/image/logo.svg" alt="logo"/>
|
||||
</div>
|
||||
<h3 id="title" style="font-size: 27px; text-align: left;">Prijava - ŠOLAR</h3>
|
||||
<h1 id="title">Portal za oddajanje besedil</h1>
|
||||
<h2 id="subtitle">Korpus Šolar</h2>
|
||||
|
||||
<div class="form-text"><em>Zbiranje besedil za korpus Šolar poteka po naslednjem postopku, ki prinaša tudi točke za napredovanje.</em></div>
|
||||
|
||||
<h3 id="title" style="font-size: 27px; text-align: left;">Prijava</h3>
|
||||
|
||||
<div>
|
||||
{% with messages = get_flashed_messages() %}
|
||||
{% if messages %}
|
||||
|
@ -24,22 +30,32 @@
|
|||
<form method="POST" action="/solar/login">
|
||||
<div>
|
||||
<div>
|
||||
<input type="email" name="email" placeholder="Email" autofocus="">
|
||||
<img src="/static/image/user.png" alt="user" style="float: left; width: 10%;"/>
|
||||
<input type="email" name="email" placeholder="Email" autofocus=""
|
||||
style="float: right; width: 85%; margin-bottom: 20px; margin-top: 10px;">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<input type="password" name="password" placeholder="Geslo">
|
||||
<img src="/static/image/password.png" alt="user" style="float: left; width: 10%; margin-top: 20px;"/>
|
||||
<input type="password" name="password" placeholder="Geslo"
|
||||
style="float: right; width: 85%; margin-bottom: 20px; margin-top: 10px;">
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex; flex-direction: row; justify-content: left; align-items: center">
|
||||
<label>Zapomni prijavo</label>
|
||||
<input style="width: 10%;" type="checkbox">
|
||||
</div>
|
||||
<button class="button-general" style="margin-top: 20px;">PRIJAVA</button>
|
||||
<button class="button-general" style="margin-top: 30px; margin-bottom: 20px;">PRIJAVA</button>
|
||||
</form>
|
||||
<a href="/solar/register" class="contract-item-button">Registracija</a>
|
||||
<a href="/solar/forgotpass" class="contract-item-button">Pozabljeno geslo</a>
|
||||
<a href="/solar/register" class="contract-item-button"
|
||||
style="-webkit-appearance: button;
|
||||
-moz-appearance: button;
|
||||
appearance: button;
|
||||
margin-top: 80px;
|
||||
text-decoration: none;
|
||||
color: #46535b;
|
||||
width: 100%;"
|
||||
><img src="/static/image/register.png" alt="user" style="float: left; width: 15%; margin-right: 25px;"/>
|
||||
Registracija<br><div style="font-size: 11px; margin-top: 10px;">Še nimate uporabniškega računa? Registrirajte se!</div></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<title>Upravljanje institucije - Šolar</title>
|
||||
<style>
|
||||
.tableFixHead {
|
||||
overflow-y: auto;
|
||||
height: 206px;
|
||||
overflow-y: scroll;
|
||||
max-height: 306px;
|
||||
}
|
||||
.tableFixHead thead th {
|
||||
position: sticky;
|
||||
|
@ -24,12 +24,15 @@
|
|||
th {
|
||||
background: #eee;
|
||||
}
|
||||
h2 {
|
||||
color: blue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{% with messages = get_flashed_messages() %}
|
||||
{% if messages %}
|
||||
<div>
|
||||
<div style="background: blue;">
|
||||
{{ messages[0] }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -76,14 +79,15 @@
|
|||
</table>
|
||||
</div>
|
||||
<br>
|
||||
<h3>Dodeli uporabnika instituciji</h3>
|
||||
<h3>Dodaj uporabnika instituciji</h3>
|
||||
<form action="/solar/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="moderator">Moderator</option>
|
||||
<option value="user">Uporabnik</option>
|
||||
<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>
|
||||
|
|
|
@ -19,12 +19,13 @@
|
|||
</head>
|
||||
<body>
|
||||
<a href="/solar/logout">Odjavi se</a>
|
||||
{% if is_institution_moderator %}
|
||||
{% if is_institution_coordinator %}
|
||||
<br><a href="/solar/manage-institution">Upravljaj z institucijo</a>
|
||||
{% endif %}
|
||||
{% if is_admin %}
|
||||
<br><a href="/solar/admin">Administracijski meni</a>
|
||||
{% endif %}
|
||||
<br><a href="mailto:email@example.com">Pomoč</a>
|
||||
<div class="bg"></div>
|
||||
<div id="main-window">
|
||||
<div id="rect1">
|
||||
|
@ -41,6 +42,13 @@
|
|||
<button id="button-pogodbe" class="selection-tab-button">POGODBE</button>
|
||||
</div>
|
||||
|
||||
{% if not institution %}
|
||||
<div class="warning">Niste član nobene institucije!</div>
|
||||
{% elif not institution_contract %}
|
||||
<div class="warning">Pogodba s šolo še ni naložena!</div>
|
||||
{% endif %}
|
||||
<div id="data-confirm-notification" class="message-notification" style="display: none;">Prosimo, preverite in potrdite vnešene podatke.</div>
|
||||
|
||||
<label for="program">PROGRAM</label>
|
||||
<select id="program" name="program">
|
||||
<option value="OS" selected="selected">Osnovnošolski (OŠ)</option>
|
||||
|
@ -109,7 +117,8 @@
|
|||
<button id="button-submit" type="submit">Oddaj</button>
|
||||
</div>
|
||||
|
||||
<div class="dropzone-previews"></div>
|
||||
<div class="dropzone-previews">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
@ -236,6 +245,7 @@ zagotovili vse potrebne informacije v skladu s predpisi o varstvu osebnih podatk
|
|||
var btnPogodbe = document.getElementById("button-pogodbe");
|
||||
var elemTermsPopup = document.getElementById("popup-terms");
|
||||
var termsScrollbox = document.getElementById("popup-terms-text");
|
||||
var dataConfirmNotification = document.getElementById("data-confirm-notification");
|
||||
var scrollboxTriggered = false;
|
||||
var form = document.forms["my-dropzone"];
|
||||
|
||||
|
@ -307,6 +317,9 @@ zagotovili vse potrebne informacije v skladu s predpisi o varstvu osebnih podatk
|
|||
alert("Polje za predmet ne more biti prazno!");
|
||||
} else if (vrsta === "delo-v-razredu" && isEmptyOrSpaces(vrstaCustom)) {
|
||||
alert("Polje za vrsto besedila ne more biti prazno!");
|
||||
} else if (dataConfirmNotification.style.display == "none") {
|
||||
dataConfirmNotification.style.display = "inherit";
|
||||
btnSubmit.textContent = "Potrdi";
|
||||
} else {
|
||||
// Then make terms popup visible
|
||||
btnSubmit.disabled = true;
|
||||
|
@ -325,6 +338,8 @@ zagotovili vse potrebne informacije v skladu s predpisi o varstvu osebnih podatk
|
|||
// Clear fields and hide popup agian
|
||||
btnSubmit.disabled = false;
|
||||
elemTermsPopup.style.display = "none";
|
||||
dataConfirmNotification.style.display = "none";
|
||||
btnSubmit.textContent = "Oddaj";
|
||||
form.reset();
|
||||
scrollboxTriggered = false;
|
||||
});
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
</head>
|
||||
<body>
|
||||
<a href="/solar/logout">Odjavi se</a>
|
||||
{% if is_institution_moderator %}
|
||||
{% if is_institution_coordinator %}
|
||||
<br><a href="/solar/manage-institution">Upravljaj z institucijo</a>
|
||||
{% endif %}
|
||||
{% if is_admin %}
|
||||