diff --git a/app.py b/app.py index bd48562..136d603 100644 --- a/app.py +++ b/app.py @@ -163,6 +163,7 @@ def index_corpus(corpus_name): if corpus_name not in ENABLED_CORPUSES: return 'Korpus "{}" ne obstaja.'.format(corpus_name), 404 + description = "" if corpus_name == 'prevodi': description = DESC_PREVODI elif corpus_name == 'gigafida': @@ -253,19 +254,22 @@ def solar_register_post(): flash('Predolgo geslo.') return redirect('/solar/register') - 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') + if not institution: + institution_id = portal.base.add_institution(institution_name, "") + portal.base.grant_institution_corpus_access(institution_id, "solar") + else: + institution_id = institution.id user_id = portal.base.register_new_user(name, email, password, active=False) - portal.base.add_user_to_institution(user_id, institution.id, institution_role) + portal.base.add_user_to_institution(user_id, institution_id, institution_role) + + portal.base.send_admins_new_user_notification_mail(user_id, upload_handler_solar.config) - flash('Uspešna registracija.') + flash('Podatki so bili poslani v potrditev. Ko bo registracija potrjena, boste o tem obveščeni po e-mailu, ki ste ga posredovali zgoraj.') return redirect('/solar/login') @@ -300,11 +304,13 @@ def solar(text): 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) + upload_items = [] + if current_user_institution: + upload_items = portal.solar.get_institution_upload_history(current_user_institution.id, n=1000) uploader_names = [] institution_names = [] for item in upload_items: - uploader_names.append(portal.base.get_user_obj(current_user.id).name) + uploader_names.append(portal.base.get_user_obj(item.upload_user).name) institution = portal.base.get_institution_obj(item.institution) if not institution: institution_names.append(None) @@ -358,6 +364,7 @@ def solar(text): show_upload_form=show_upload_form, collaborators=collaborators, cooperation_history=cooperation_history, + user_id=current_user.id, is_admin=is_admin, is_institution_coordinator=current_user_institution_coordinator) elif text.startswith('admin/') or text == 'admin': users = portal.base.get_all_users_join_institutions() @@ -378,7 +385,9 @@ def solar(text): @app.route('/solar/pogodbe', methods=['POST']) @login_required def solar_upload_contract(): - return 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) + return redirect(redirect_url()) @app.route('/solar/adduser', methods=['POST']) @@ -416,6 +425,12 @@ def solar_add_user(): flash('Predolgo geslo.') return redirect(redirect_url()) + user = portal.base.get_user_obj_by_email(email) + if user: + #portal.base.undo_remove_user(user.id) + flash('Uporabnik s tem emailom je že vnešen v sistem.') + return redirect(redirect_url()) + portal.base.register_new_user(name, email, password) flash('Uporabnik je bil uspešno dodan.') @@ -437,6 +452,8 @@ def solar_activate_user(): if rowcount == 0: return '', 404 + portal.base.send_user_activation_mail(user_id, upload_handler_solar.config) + flash('Uporabnik je bil aktiviran.') return redirect(redirect_url()) @@ -494,23 +511,21 @@ def solar_del_user(): if not portal.base.is_admin(current_user.id): return '', 404 user_id = request.form.get('user_id') - portal.base.del_user(user_id) + portal.base.remove_user(user_id) flash('Uporabnik je bil odstranjen.') return redirect(redirect_url()) -@app.route('//addinstitution', methods=['POST']) +@app.route('/solar/addinstitution', methods=['POST']) @login_required -def add_institution(corpus_name): +def add_institution(): if not portal.base.is_admin(current_user.id): return '', 404 - if not corpus_name in ENABLED_CORPUSES: - return '', 404 name = request.form.get('name') region = request.form.get('region') if not name: - flash('Prazno polje za ime.') + flash('Prazno polje za naziv.') return redirect(redirect_url()) if len(name) > 100: flash('Predolgo ime.') @@ -521,10 +536,142 @@ def add_institution(corpus_name): return redirect(redirect_url()) institution_id = portal.base.add_institution(name, region) - portal.base.grant_institution_corpus_access(institution_id, corpus_name) + portal.base.grant_institution_corpus_access(institution_id, "solar") # TODO: throw out flash('Institucija je bila dodana.') return redirect(redirect_url()) +@app.route('/solar/mergeinstitutions', methods=['POST']) +@login_required +def merge_institutions(): + if not portal.base.is_admin(current_user.id): + return '', 404 + + id_from = request.form.get('id-from') + id_to = request.form.get('id-to') + + if not id_from or not id_to: + flash('Prazno polje.') + return redirect(redirect_url()) + + institution_from = portal.base.get_institution_obj(id_from) + institution_to = portal.base.get_institution_obj(id_to) + + if not institution_from: + flash('Institucija z ID "{}" ne obstaja.'.format(id_from)) + return redirect(redirect_url()) + + if not institution_to: + flash('Institucija z ID "{}" ne obstaja.'.format(id_to)) + return redirect(redirect_url()) + + + portal.base.transfer_users_institution(institution_from.id, institution_to.id) + portal.base.transfer_uploads_institution(institution_from.id, institution_to.id) + portal.base.transfer_contracts_institution(institution_from.id, institution_to.id) + portal.base.remove_institution(institution_from.id) + + flash('Instituciji uspešno združeni') + return redirect(redirect_url()) + +@app.route('/solar/addcooperationhistoryitem', methods=['POST']) +@login_required +def add_cooperation_history_item(): + if not portal.base.is_admin(current_user.id): + 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.base.get_user_obj(user_id) + institution = portal.base.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.base.add_cooperation_history_item(user_id, institution_id, role, school_year, badge_text) + + flash('Vnos dodan.') + return redirect(redirect_url()) + +@app.route('/solar/delcooperationhistoryitem', methods=['POST']) +@login_required +def del_cooperation_history_item(): + if not portal.base.is_admin(current_user.id): + return '', 404 + + entry_id = request.form.get('entry-id') + portal.base.del_cooperation_history_item(entry_id) + + flash('Vnos odstranjen.') + return redirect(redirect_url()) + +@app.route('/solar/changeuseremail', methods=['POST']) +@login_required +def change_user_email(): + if not portal.base.is_admin(current_user.id): + return '', 404 + + user_id = request.form.get('user-id') + email = request.form.get('email') + + if not re.search(portal.base.REGEX_EMAIL, email): + flash('Email napačnega formata.') + return redirect(redirect_url()) + + portal.base.update_user_email(user_id, email) + + flash('Email spremenjen.') + return redirect(redirect_url()) + + +@app.route('/solar/changeuserrole', methods=['POST']) +@login_required +def change_user_role(): + if not portal.base.is_admin(current_user.id): + return '', 404 + + user_id = request.form.get('user-id') + role = request.form.get('role') + + if not role in ['admin', 'user']: + flash('Neveljavna vloga.') + return redirect(redirect_url()) + + portal.base.update_user_role(user_id, role) + + flash('Vloga spremenjena.') + return redirect(redirect_url()) + +@app.route('/solar/changeusername', methods=['POST']) +@login_required +def change_user_name(): + if not portal.base.is_admin(current_user.id): + return '', 404 + + user_id = request.form.get('user-id') + name = request.form.get('name') + + portal.base.update_user_name(user_id, name) + + flash('Ime in priimek spremenjena.') + return redirect(redirect_url()) + @app.route('//addusertoinstitution', methods=['POST']) @login_required def add_user_institution_mapping(corpus_name): diff --git a/migrations/versions/84168f439c55_added_is_removed_column_to_users_and_.py b/migrations/versions/84168f439c55_added_is_removed_column_to_users_and_.py new file mode 100644 index 0000000..31eb8fb --- /dev/null +++ b/migrations/versions/84168f439c55_added_is_removed_column_to_users_and_.py @@ -0,0 +1,30 @@ +"""Added is_removed column to users and institutions. + +Revision ID: 84168f439c55 +Revises: c60b7bfaaf85 +Create Date: 2021-09-06 10:55:40.303790 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '84168f439c55' +down_revision = 'c60b7bfaaf85' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('institution', sa.Column('is_removed', sa.Boolean(), server_default='true', nullable=False)) + op.add_column('registered_user', sa.Column('is_removed', sa.Boolean(), server_default='true', nullable=False)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('registered_user', 'is_removed') + op.drop_column('institution', 'is_removed') + # ### end Alembic commands ### diff --git a/portal/base.py b/portal/base.py index 384dd59..4a0fd18 100644 --- a/portal/base.py +++ b/portal/base.py @@ -68,7 +68,7 @@ class ContractCreator: class UploadHandler: - ENABLED_FILETYPES = ['txt', 'csv', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'xml', 'mxliff', 'tmx'] + ENABLED_FILETYPES = ['txt', 'csv', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'xml', 'mxliff', 'tmx', 'jpg', 'jpeg', 'png'] def __init__(self, **kwargs): self.config = kwargs @@ -210,7 +210,7 @@ class UploadHandler: for key, f in files.items(): if key.startswith('file'): suffix = f.filename.split('.')[-1] - if self.ENABLED_FILETYPES and suffix not in self.ENABLED_FILETYPES: + if self.ENABLED_FILETYPES and suffix.lower() not in self.ENABLED_FILETYPES: return 'Datoteka "{}" ni pravilnega formata.'.format(f.filename) return None @@ -263,10 +263,10 @@ def get_institution_cooperation_history(institution_id): if row.user not in res: res[row.user] = { 'coordinator': [], - 'moderator': [], + 'mentor': [], 'other': [] } - res[row.user][row.role].append(row.school_year) + res[row.user][row.role].append((row.school_year, row.badge_text)) return res @@ -275,6 +275,22 @@ def get_cooperation_history(): return UserCooperationHistory.query.all() +def add_cooperation_history_item(user_id, institution_id, role, school_year, badge_text): + model_obj = UserCooperationHistory( + user=user_id, + institution=institution_id, + role=role, + school_year=school_year, + badge_text=badge_text + ) + db.session.add(model_obj) + db.session.commit() + return model_obj.id + +def del_cooperation_history_item(entry_id): + db.session.query(UserCooperationHistory).filter_by(id=entry_id).delete() + db.session.commit() + def has_user_corpus_access(user_id, corpus_name): user = RegisteredUser.query.filter_by(id=user_id).first() @@ -303,6 +319,8 @@ def is_admin(user_id): def get_user_obj(user_id): return RegisteredUser.query.filter_by(id=user_id).first() +def get_user_obj_by_email(email): + return RegisteredUser.query.filter_by(email=email).first() def get_institution_obj(institution_id): return Institution.query.filter_by(id=institution_id).first() @@ -370,10 +388,38 @@ def update_user_password(user_id, new_password): 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() +def update_user_role(user_id, role): + rowcount = db.session.query(RegisteredUser).filter_by(id=user_id).update({'role': role}) + db.session.commit() + return rowcount + + +def update_user_email(user_id, new_email): + rowcount = db.session.query(RegisteredUser).filter_by(id=user_id).update({'email': new_email}) + db.session.commit() + return rowcount + + +def update_user_name(user_id, new_name): + rowcount = db.session.query(RegisteredUser).filter_by(id=user_id).update({'name': new_name}) + db.session.commit() + return rowcount + + +def remove_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() + db.session.query(RegisteredUser).filter(RegisteredUser.id == user_id).update({'is_removed': True}) + db.session.commit() + +def undo_remove_user(user_id): + db.session.query(RegisteredUser).filter(RegisteredUser.id == user_id).update({'is_removed': False}) + db.session.commit() + +def remove_institution(institution_id): + db.session.query(Institution).filter(Institution.id == institution_id).update({'is_removed': True}) db.session.commit() @@ -383,22 +429,22 @@ 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() + return RegisteredUser.query.filter_by(is_removed=False).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() + return RegisteredUser.query.filter_by(is_removed=False).filter_by(active=False).order_by(RegisteredUser.id).all() 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, + return db.session.query(RegisteredUser, UserInstitutionMapping).filter(RegisteredUser.is_removed==False).outerjoin(UserInstitutionMapping, 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, + return RegisteredUser.query.filter_by(is_removed=False).filter_by(active=True).join(UserInstitutionMapping, RegisteredUser.id == UserInstitutionMapping.user).filter(UserInstitutionMapping.institution == institution_id).all() @@ -437,6 +483,28 @@ def get_password_reset_token(email, key, expires=600): 'exp': int(time.time()) + expires}, key=key, algorithm='HS256') + +def transfer_users_institution(institution_id_from, institution_id_to): + rowcount = db.session.query(UserInstitutionMapping).filter_by(institution=institution_id_from).update( + {'institution': institution_id_to}) + db.session.commit() + return rowcount + + +def transfer_uploads_institution(institution_id_from, institution_id_to): + rowcount = db.session.query(UploadSolar).filter_by(institution=institution_id_from).update( + {'institution': institution_id_to}) + db.session.commit() + return rowcount + + +def transfer_contracts_institution(institution_id_from, institution_id_to): + rowcount = db.session.query(ContractsSolar).filter_by(institution=institution_id_from).update( + {'institution': institution_id_to}) + db.session.commit() + return rowcount + + def verify_reset_token(token, key): try: message = jwt.decode(token, @@ -455,11 +523,18 @@ def verify_reset_token(token, key): def send_resetpass_mail(email, config): jwt_token = get_password_reset_token(email, config['APP_SECRET_KEY']) - text = ''' + body = ''' Zahtevali ste ponastavitev gesla vašega uporabniškega računa. Geslo lahko ponastavite na naslednji povezavi: https://zbiranje.slovenscina.eu/solar/resetpass/{}'''.format(jwt_token) + message = MIMEMultipart() + message['From'] = config['MAIL_LOGIN'] + message['To'] = email + message['Subject'] = 'Ponastavitev gesla' + message.attach(MIMEText(body, "plain")) + text = message.as_string() + # Create a secure SSL context context = ssl.create_default_context() @@ -469,3 +544,53 @@ def send_resetpass_mail(email, config): server.sendmail(config['MAIL_LOGIN'], email, text) except Exception: traceback.print_exc() + + +def send_admins_new_user_notification_mail(user_id, config): + user = RegisteredUser.query.filter_by(id=user_id).first() + body = ''' + Nov uporabnik "{}" je ustvaril uporabniški račun na portalu za oddajanje besedil Šolar in čaka na odobritev. + '''.format(user.name) + + message = MIMEMultipart() + message['From'] = config['MAIL_LOGIN'] + message['To'] = email + message['Subject'] = 'Ponastavitev gesla' + message.attach(MIMEText(body, "plain")) + text = message.as_string() + + admins = RegisteredUser.query.filter_by(role="admin").all() + + # Create a secure SSL context + context = ssl.create_default_context() + + for admin in admins: + 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'], admin.email, text) + except Exception: + traceback.print_exc() + + +def send_user_activation_mail(user_id, config): + user = RegisteredUser.query.filter_by(id=user_id).first() + body = '''Vaš uporabniški račun "{}" na portalu Šolar je bil odobren.'''.format(user.name) + + message = MIMEMultipart() + message['From'] = config['MAIL_LOGIN'] + message['To'] = email + message['Subject'] = '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'], user.email, text) + except Exception: + traceback.print_exc() + diff --git a/portal/model.py b/portal/model.py index 30f7a11..3df8374 100644 --- a/portal/model.py +++ b/portal/model.py @@ -67,6 +67,7 @@ class RegisteredUser(UserMixin, db.Model): active = db.Column(db.Boolean, nullable=True) last_login = db.Column(db.DateTime, nullable=True) registered = db.Column(db.DateTime, nullable=True) + is_removed = db.Column(db.Boolean, nullable=False, default=False, server_default="false") class UserInstitutionMapping(db.Model): @@ -104,6 +105,7 @@ class Institution(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String, nullable=False, unique=True) region = db.Column(db.String, nullable=False) + is_removed = db.Column(db.Boolean, nullable=False, default=False, server_default="false") class CorpusAccess(db.Model): diff --git a/portal/solar.py b/portal/solar.py index 5e92d07..b1337d0 100644 --- a/portal/solar.py +++ b/portal/solar.py @@ -79,62 +79,58 @@ class UploadHandlerSolar(UploadHandler): if contract_type not in ['sola', 'ucenci-starsi']: return 'Neveljaven tip pogodbe.' - f_obj = None - for key, f in request.files.items(): - if key.startswith('file'): - mimetype = f.content_type - if mimetype != 'application/pdf': - return 'Datoteka "{}" ni formata PDF.'.format(f.filename) - else: - f_obj = f - break - - if not f_obj: - return 'Niste naložili nobene datoteke.' - - base = self.get_uploads_subdir('contracts') - f_hash = hashlib.md5(f_obj.read()).hexdigest() - f_obj.seek(0, 0) - - # First byte used for indexing, similarly like git does for example. - sub_dir = base / f_hash[:2] - if not sub_dir.exists(): - sub_dir.mkdir() - - path = sub_dir / (f_hash[2:] + '.pdf') - f_obj.save(path) - - timestamp = datetime.now() - user_obj = RegisteredUser.query.filter_by(id=user_id).one() - user_institution_mapping = UserInstitutionMapping.query.filter_by(user=user_id).first() - if user_institution_mapping is None: - return 'Vaš uporabnik ni dodeljen nobeni inštituciji.' - institution_id = user_institution_mapping.institution - is_institution_coordinator = True if user_institution_mapping.role == 'coordinator' else False - - if contract_type == 'sola': - 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, - original_filename=f_obj.filename - ) - self.store_model(model_obj) - else: - model_obj = ContractsSolar( - institution=institution_id, - upload_user=user_id, - timestamp=timestamp, - file_contract=f_hash, - contract_type=contract_type, - original_filename=f_obj.filename - ) - - self.store_model(model_obj) + #for key, f in request.files.items(): + for f in request.files.getlist("file[]"): + + mimetype = f.content_type + if mimetype != 'application/pdf': + return 'Datoteka "{}" ni formata PDF.'.format(f.filename) + + if not f: + return 'Niste naložili nobene datoteke.' + + base = self.get_uploads_subdir('contracts') + f_hash = hashlib.md5(f.read()).hexdigest() + f.seek(0, 0) + + # First byte used for indexing, similarly like git does for example. + sub_dir = base / f_hash[:2] + if not sub_dir.exists(): + sub_dir.mkdir() + + path = sub_dir / (f_hash[2:] + '.pdf') + f.save(path) + + timestamp = datetime.now() + user_institution_mapping = UserInstitutionMapping.query.filter_by(user=user_id).first() + if user_institution_mapping is None: + return 'Vaš uporabnik ni dodeljen nobeni inštituciji.' + institution_id = user_institution_mapping.institution + is_institution_coordinator = True if user_institution_mapping.role == 'coordinator' else False + + if contract_type == 'sola': + 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, + original_filename=f.filename + ) + self.store_model(model_obj) + else: + model_obj = ContractsSolar( + institution=institution_id, + upload_user=user_id, + timestamp=timestamp, + file_contract=f_hash, + contract_type=contract_type, + original_filename=f.filename + ) + + self.store_model(model_obj) return 'Nalaganje pogodbe je bilo uspešno.' @staticmethod @@ -168,10 +164,14 @@ def get_upload_history(user_id, n=20): return UploadSolar.query.filter_by(upload_user=user_id).order_by(desc(UploadSolar.timestamp)).limit(n).all() +def get_institution_upload_history(institution_id, n=20): + return UploadSolar.query.filter_by(institution=institution_id).order_by(desc(UploadSolar.timestamp)).limit(n).all() + + def get_all_institutions(): # TODO: do filtering purely within an SQL query res = [] - for institution in Institution.query.all(): + for institution in Institution.query.filter_by(is_removed=False).all(): row = CorpusAccess.query.filter_by(institution=institution.id, corpus='solar').first() if row: res.append(institution) diff --git a/static/style.css b/static/style.css index 83addb0..a9c6d5f 100644 --- a/static/style.css +++ b/static/style.css @@ -197,10 +197,12 @@ label { } .collaborators-item { - height: 30px; + height: fit-content; + width: 97%; margin: 5px; border: 0px; border-bottom: 2px solid #c4c4c4; + display: inline-block; } .collaborators-item-name { @@ -209,6 +211,17 @@ label { font-weight: normal; font-size: 16px; color: #46535b; + float: left; +} + +.collaborators-item-years { + font-family: Roboto; + font-style: normal; + font-weight: normal; + font-size: 16px; + float: right; + width: 180px; + max-width: 180px; } #awards-container { diff --git a/templates/solar-admin.html b/templates/solar-admin.html index e5185da..eb89e58 100644 --- a/templates/solar-admin.html +++ b/templates/solar-admin.html @@ -38,22 +38,6 @@ {% endif %} {% endwith %}

Uporabniki

-

Dodaj uporabnika

-
-
-
-
-
-
-
- -
-

Odstrani uporabnika

-
-
-
- -

Aktivni uporabniki

@@ -62,6 +46,7 @@ + @@ -72,11 +57,44 @@ + {% endfor %}
ID Ime in priimek EmailVloga ID institucije Vloga v instituciji
{{item[0].id}} {{item[0].name}} {{item[0].email}}{{item[0].role}} {{item[1].institution}} {{item[1].role}}
+

Dodaj uporabnika

+
+
+
+
+
+
+
+ +
+

Spremeni email uporabnika

+
+
+
+
+
+ +
+

Spremeni ime in priimek uporabnika

+
+
+
+
+
+ +
+

Odstrani uporabnika

+
+
+
+ +

Dodeli uporabnika instituciji

@@ -97,6 +115,47 @@
+

Spremeni vlogo uporabniškega računa

+
+ +
+ + + +
+

Čakajoči uporabniki

+
+ + + + + + + + + + + + {% for item in inactive_users %} + + + + + + + + {% endfor %} +
IDIme in priimekEmailInstitucijaVloga v instituciji
{{item[0].id}}{{item[0].name}}{{item[0].email}}{{item[1].institution}}{{item[1].role}}
+
+

Aktiviraj uporabnika

+
+ +
+ +

Institucije

Dodaj institucijo

@@ -139,35 +198,13 @@ {% endfor %} -

Čakajoči uporabniki

-
- - - - - - - - - - - - {% for item in inactive_users %} - - - - - - - - {% endfor %} -
IDIme in priimekEmailInstitucijaVloga v instituciji
{{item[0].id}}{{item[0].name}}{{item[0].email}}{{item[1].institution}}{{item[1].role}}
-
-

Aktiviraj uporabnika

-
- -
- +

Združi instituciji

+ + + + +
+

Zgodovina sodelovanja

@@ -195,4 +232,28 @@ {% endfor %}
+

Dodaj vnos

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

Odstrani vnos

+
+ +
+ +
diff --git a/templates/solar-oddaja.html b/templates/solar-oddaja.html index a507840..43a1c8d 100644 --- a/templates/solar-oddaja.html +++ b/templates/solar-oddaja.html @@ -126,105 +126,6 @@ + {% with messages = get_flashed_messages() %} + {% if messages %} +
+ {{ messages[0] }} +
+
+ {% else %}
+ {% endif %} + {% endwith %} + {% if contract_school %}
contract @@ -71,7 +81,7 @@
- +
@@ -84,11 +94,26 @@ {% for collaborator in collaborators %}
{{collaborator.name}}
- {% for history_item in cooperation_history %} - {% if collaborator.id == history_item.user %} -
{{history_item.badge_text}}
- {% endif %} - {% endfor %} + {% if collaborator.id in cooperation_history %} + {% if cooperation_history[collaborator.id]["coordinator"]|length > 0 %} +
Vodenje: {% for item in cooperation_history[collaborator.id]["coordinator"] %} + {% if loop.index != 1 %}, {% endif %} + {{item[0]}} + {% endfor %}
+ {% endif %} + {% if cooperation_history[collaborator.id]["mentor"]|length > 0 %} +
Mentorstvo: {% for item in cooperation_history[collaborator.id]["mentor"] %} + {% if loop.index != 1 %}, {% endif %} + {{item[0]}} + {% endfor %}
+ {% endif %} + {% if cooperation_history[collaborator.id]["other"]|length > 0 %} +
Drugo: {% for item in cooperation_history[collaborator.id]["other"] %} + {% if loop.index != 1 %}, {% endif %} + {{item[0]}} + {% endfor %}
+ {% endif %} + {% endif %}
{% endfor %}
@@ -96,13 +121,49 @@
Sodelovanje v letih
- {% for item in cooperation_history %} -
- star -
{{item.badge_text}}
-
- {% endfor %} + {% if cooperation_history.keys()|length > 0 %} + {% if user_id in cooperation_history %} + {% for item in cooperation_history[user_id]['coordinator'] %} +
+ star +
+ {{item[1]}} +
+
+ {{item[0]}} +
+
+ {% endfor %} + {% for item in cooperation_history[user_id]['mentor'] %} +
+ star +
+ {{item[1]}} +
+
+ {{item[0]}} +
+
+ {% endfor %} + {% for item in cooperation_history[user_id]['other'] %} +
+ star +
+ {{item[1]}} +
+
+ {{item[0]}} +
+
+ {% endfor %} + {% endif %} + {% endif %}