420 lines
19 KiB
Python
420 lines
19 KiB
Python
from flask import Blueprint, render_template, request, redirect, url_for, current_app
|
|
from flask_security import current_user, auth_required
|
|
from werkzeug.utils import secure_filename
|
|
from airtable import Airtable
|
|
from dotenv import load_dotenv
|
|
import requests
|
|
import os
|
|
from base64 import b64encode
|
|
import json
|
|
|
|
basedir = os.path.abspath(os.path.dirname(__file__))
|
|
load_dotenv(os.path.join(os.path.dirname(basedir), '.env'))
|
|
|
|
api_key = os.environ.get("AIRTABLE_API_KEY" or '')
|
|
base_id = os.environ.get("AIRTABLE_BASE_ID" or '')
|
|
|
|
airtable_bp = Blueprint("airtable", __name__, template_folder="templates/airtable")
|
|
|
|
table_call = {
|
|
'participants': "Participants",
|
|
'structures': "Structures",
|
|
'formations': "Formations",
|
|
'sessions': "Sessions",
|
|
'modules_base': "Modules",
|
|
'modules': "Modules par session",
|
|
'intervenants': "Intervenants",
|
|
'workshops': "Séances",
|
|
'workshop_individual_reports': "Bulletins individuels par Séance",
|
|
'specialites': "Spécialités",
|
|
'bulletins_par_session': "Bulletins individuels par session de formation"
|
|
}
|
|
|
|
def fetch_api(table):
|
|
data = Airtable(base_id, table_call[table], api_key)
|
|
return data
|
|
|
|
def upload_files(files):
|
|
urls = []
|
|
for filename, storage in files:
|
|
filename = secure_filename(filename)
|
|
filepath = os.path.join(current_app.static_folder, filename)
|
|
if os.path.exists(filepath):
|
|
os.remove(filepath)
|
|
storage.save(filepath)
|
|
file_url = request.url_root.rstrip('/') + url_for('static', filename=filename)
|
|
attachment = {'url': file_url, 'filename': filename}
|
|
urls.append(attachment)
|
|
print("urls uploaded: " + str(urls))
|
|
return urls
|
|
|
|
def update_airtable_attachment_field(request, record, field_name, airtable_column_name=None):
|
|
airtable_column_name = airtable_column_name or field_name
|
|
uploaded_files = list(request.files.items()) or []
|
|
print("==================================")
|
|
print("uploaded_files: " + str(uploaded_files))
|
|
print("==================================")
|
|
|
|
|
|
# set of files sent via input fields
|
|
set_input = set(file_id[len(field_name) + 1:] for file_id, file_storage in uploaded_files if file_id.startswith(field_name))
|
|
if record.get('fields').get(airtable_column_name):
|
|
# set of airtable attachments ids
|
|
set_airtable = set(file['id'] for file in record['fields'][airtable_column_name])
|
|
else:
|
|
set_airtable = set()
|
|
print("set_airtable: " + str(set_airtable))
|
|
print("set_input: " + str(set_input))
|
|
|
|
# Éléments présents dans set_airtable mais pas dans set_input
|
|
to_remove = list(set_airtable - set_input)
|
|
print("Éléments dans airtable mais pas dans le formulaire:", to_remove)
|
|
|
|
# Éléments présents dans set_input mais pas dans set_airtable
|
|
to_add = list(set_input - set_airtable)
|
|
print("Éléments dans le formulaire mais pas dans airtable:", to_add, "(len: ", len(to_add), " )")
|
|
|
|
base_data = [ attachment for attachment in record['fields'].get(airtable_column_name, [])]
|
|
print("base_data in " + field_name + " : " + str(base_data))
|
|
data = [ attachment for attachment in record['fields'].get(airtable_column_name, []) if attachment['id'] not in to_remove]
|
|
print(" ")
|
|
print("======================================")
|
|
print("base_data after filter in " + field_name + " : " + str(base_data))
|
|
if len(to_add) > 0:
|
|
files = [file for file in uploaded_files if file[0][len(field_name) + 1:] in to_add]
|
|
new_attachments = upload_files(files)
|
|
data.extend(new_attachments)
|
|
|
|
print("======================================")
|
|
print("data + " + airtable_column_name + " : " + str(data))
|
|
|
|
return data
|
|
|
|
@airtable_bp.route('/dashboard', methods=['GET'])
|
|
@auth_required()
|
|
def airtable_dashboard():
|
|
return render_template('dashboard.html')
|
|
|
|
@airtable_bp.route('/participants', methods=['GET'])
|
|
@auth_required()
|
|
def display_participants():
|
|
participants = fetch_api('participants')
|
|
intervenants = fetch_api('intervenants')
|
|
|
|
records = []
|
|
if current_user.has_role("gestionnaire"):
|
|
for participant in participants.get_all():
|
|
records.append(participant)
|
|
elif current_user.has_role("prof"):
|
|
for participant in participants.get_all():
|
|
mes_intervenants = [ intervenants.get(intervenant_id)['fields'].get('email') for intervenant_id in (participant['fields'].get('Intervenants') or [])]
|
|
if current_user.email in mes_intervenants:
|
|
records.append(participant)
|
|
return render_template('participants/participants_list.html', records=records)
|
|
|
|
@airtable_bp.route("/participants/<participant_id>/dashboard", methods=['GET'])
|
|
@auth_required()
|
|
def participant_dashboard(participant_id):
|
|
participant = fetch_api('participants').get(participant_id)
|
|
sessions_ids = participant['fields']['Sessions']
|
|
sessions = fetch_api('sessions')
|
|
sessions = [ sessions.get(session_id) for session_id in sessions_ids ]
|
|
|
|
formation_ids = [ session['fields']['Formations'][0] for session in sessions ]
|
|
formations = fetch_api('formations')
|
|
formations = [ formations.get(formation_id) for formation_id in formation_ids]
|
|
|
|
return render_template('participants/participant_dashboard.html', participant=participant, sessions=sessions, formations=formations)
|
|
|
|
@airtable_bp.route("/participants/<participant_id>/profile", methods=['GET', 'POST'])
|
|
@auth_required()
|
|
def participant_profile(participant_id):
|
|
participants = fetch_api('participants')
|
|
participant = participants.get(participant_id)
|
|
|
|
if request.method == 'POST':
|
|
data = {}
|
|
if request.form['first_name'] != participant['fields']['Prénom']:
|
|
data['Prénom'] = request.form['first_name']
|
|
if request.form['family_name'] != participant['fields']['Nom de famille']:
|
|
data['Nom de famille'] = request.form['family_name']
|
|
data['CNI'] = update_airtable_attachment_field(request, participant, "CNI")
|
|
data["Attestation Pôle Emploi"] = update_airtable_attachment_field(request, participant, "Attestation", "Attestation Pôle Emploi")
|
|
|
|
if data:
|
|
participants.update(participant_id, data)
|
|
return redirect(url_for('airtable.participant_profile', participant_id=participant_id))
|
|
else:
|
|
return render_template('participants/participant_profile.html', record = participant)
|
|
|
|
def is_session_active(sessions, formations):
|
|
formation_id = request.args.get('formation_id')
|
|
active_sessions = []
|
|
|
|
for session in sessions.get_all():
|
|
if not formation_id or session['fields'].get('Formation', [])[0] == formation_id:
|
|
active_sessions.append(session)
|
|
return active_sessions
|
|
|
|
def list_modules_for_session(sessions, modules):
|
|
sessions_records = sessions.get_all()
|
|
for session in sessions_records:
|
|
print("Session: " + str(session))
|
|
print("Spécialités : " + str(session['fields'].get('Spécialités')))
|
|
|
|
modules_for_session = []
|
|
for module in modules:
|
|
print(" Module " + str(module['fields'].get('Name')) + " - spécialité : " + str(module['fields'].get('Spécialité')) + " - Formation: " + str(module['fields'].get('Formation')))
|
|
|
|
if session['fields'].get('Formation')[0] == module['fields'].get('Formation')[0] and module['fields'].get('Spécialité')[0] in session['fields'].get('Spécialités'):
|
|
modules_for_session.append(module['id'])
|
|
|
|
print("modules listed for session " + session['fields'].get('Name') + " : " + str(modules_for_session))
|
|
sessions.update(session['id'], {'Modules': modules_for_session})
|
|
|
|
# recuperation des sessions et affichage des session en fonction des formation
|
|
@airtable_bp.route('/sessions', methods=['GET'])
|
|
@auth_required()
|
|
def sessions():
|
|
sessions = fetch_api('sessions')
|
|
formations = fetch_api('formations').get_all()
|
|
modules = fetch_api('modules').get_all()
|
|
list_modules_for_session(sessions=sessions, modules=modules)
|
|
active_sessions = is_session_active(sessions=sessions, formations=formations)
|
|
return render_template('/airtable/sessions/sessions_list.html', sessions=active_sessions, formations=formations)
|
|
|
|
|
|
""" @airtable_bp.route('/my_modules', methods=['GET'])
|
|
@auth_required()
|
|
def display_records():
|
|
profs = fetch_api('profs')
|
|
all_modules = fetch_api('log_modules')
|
|
|
|
# Get the mentor's email from the current user
|
|
user_email = current_user.email
|
|
for prof in profs.get_all():
|
|
if prof['fields'].get('email') and prof['fields']['email'] == user_email:
|
|
print("prof found: " + prof['fields']['email'] + " - id : "+ prof['id'])
|
|
records = [record for record in all_modules.get_all() if record['fields'].get('Professeur') and record['fields']['Professeur'][0] == prof['id']]
|
|
break
|
|
else:
|
|
records = []
|
|
|
|
return render_template('/airtable/modules/my_modules.html', records=records, profs=profs) """
|
|
|
|
@airtable_bp.route('/edit_module/<record_id>', methods=['GET', 'POST'])
|
|
def edit_module(module_id):
|
|
module_id = airtable.get(module_id)
|
|
if request.method == 'POST':
|
|
data = {}
|
|
|
|
if request.form['name'] != record['fields']['Name']:
|
|
data['Name'] = request.form['name']
|
|
if request.form['notes'] != record['fields']['Notes']:
|
|
data['Notes'] = request.form['notes']
|
|
if request.form['status'] != record['fields']['Status']:
|
|
data['Status'] = request.form['status']
|
|
if request.form['atelier'] != record['fields']['atelier'][0]:
|
|
data['atelier'] = [request.form['atelier']]
|
|
if set(request.form.getlist('mentors')) != set(record['fields'].get('mentors', [])):
|
|
data['mentors'] = request.form.getlist('mentors')
|
|
|
|
if data:
|
|
airtable.update(record_id, data)
|
|
return redirect(url_for('airtable.display_records'))
|
|
else:
|
|
record = airtable.get(record_id)
|
|
|
|
return render_template('edit_record.html', record=record, field_options=field_options)
|
|
|
|
########### Affichage des séances
|
|
@airtable_bp.route('/modules/<module_id>/workshops', methods=['GET'])
|
|
def show_workshops(module_id):
|
|
workshops = fetch_api('workshops')
|
|
modules = fetch_api('modules')
|
|
intervenants = fetch_api('intervenants')
|
|
participants = fetch_api('participants')
|
|
|
|
module = modules.get(module_id)
|
|
print("Module : " + str(module))
|
|
|
|
if modules.get(module_id)['fields'].get('Séances', []):
|
|
workshops = [workshop for workshop in workshops.get_all() if workshop['id'] in modules.get(module_id)['fields']['Séances']]
|
|
|
|
if modules.get(module_id)['fields'].get('Intervenants', []):
|
|
intervenants = [intervenant for intervenant in intervenants.get_all() if intervenant['id'] in modules.get(module_id)['fields']['Intervenants']]
|
|
|
|
participants_prevus = []
|
|
if modules.get(module_id)['fields'].get("Participants", []):
|
|
participants_prevus = [ participant for participant in participants.get_all() if participant['id'] in modules.get(module_id)['fields']['Participants']]
|
|
|
|
return render_template('/airtable/workshops/workshops.html', module = module, workshops = workshops, intervenants = intervenants, participants = participants_prevus)
|
|
|
|
|
|
######### Affichage de la fiche d'une séance
|
|
@airtable_bp.route('/modules/<module_id>/workshops/<workshop_id>', methods=['GET', 'POST'])
|
|
def show_workshop(module_id, workshop_id):
|
|
workshops = fetch_api('workshops')
|
|
modules = fetch_api('modules')
|
|
modules_base = fetch_api('modules_base')
|
|
participants = fetch_api('participants')
|
|
participants_prevus = []
|
|
|
|
workshop = workshops.get(workshop_id)
|
|
print("Workshop : " + str(workshop))
|
|
|
|
module = modules.get(workshop['fields']['Modules par session'][0])
|
|
|
|
module_base = modules_base.get(module['fields']['Module'][0])
|
|
participants_prevus = [participants.get(participant_id) for participant_id in workshop['fields']['Participants prévus']]
|
|
|
|
if request.method == 'POST':
|
|
data = {}
|
|
if not workshop['fields'].get('Date') or request.form['Date'] != workshop['fields']['Date']:
|
|
data['Date'] = request.form['Date']
|
|
if not workshop['fields'].get('Commentaire') or request.form['Commentaire'] != workshop['fields']['Commentaire']:
|
|
data['Commentaire'] = request.form['Commentaire']
|
|
if data:
|
|
workshops.update(workshop['id'], data)
|
|
|
|
return redirect(url_for('airtable.show_workshop', module_id=module_id, workshop_id=workshop_id))
|
|
else:
|
|
return render_template('/airtable/workshops/workshop.html', workshop = workshop, module = module, module_base = module_base, participants = participants_prevus)
|
|
|
|
####### Evaluations individuelles pour une séance
|
|
@airtable_bp.route('/modules/<module_id>/workshops/<workshop_id>/<participant_id>', methods=['GET', 'POST'])
|
|
def show_workshop_individual_report(module_id, workshop_id, participant_id):
|
|
workshop_reports = fetch_api('workshop_individual_reports')
|
|
print("this are all reports: " + str(workshop_reports.get_all()))
|
|
report_formula = "AND({{Seance_Id}}='{}',{{Participant_Id}}='{}')".format(str(workshop_id), str(participant_id))
|
|
print(report_formula)
|
|
report = workshop_reports.get_all(formula=report_formula)
|
|
print("Report found : " + str(report))
|
|
new_report = True
|
|
if len(report) > 0:
|
|
print('we have a record')
|
|
new_report = False
|
|
report = report[0]
|
|
else:
|
|
print('lets create one')
|
|
report = {
|
|
'fields':
|
|
{
|
|
'Commentaire': "default comment",
|
|
'Note': 5
|
|
}
|
|
}
|
|
|
|
participants = fetch_api('participants')
|
|
participant = participants.get(participant_id)
|
|
|
|
workshops = fetch_api('workshops')
|
|
workshop = workshops.get(workshop_id)
|
|
|
|
modules = fetch_api('modules')
|
|
module = modules.get(module_id)
|
|
|
|
modules_base = fetch_api('modules_base')
|
|
module_base_id = module['fields']['Module'][0]
|
|
module_base = modules_base.get(module_base_id)
|
|
|
|
|
|
if request.method == 'POST':
|
|
|
|
data = {}
|
|
data['Commentaire'] = request.form['Commentaire']
|
|
data['Participant'] = [participant_id]
|
|
data['Seance'] = [workshop_id]
|
|
if data:
|
|
print("we have data")
|
|
if new_report == False:
|
|
print("its an old record we update")
|
|
workshop_reports.update(report['id'], data)
|
|
else:
|
|
print("its a new record to create")
|
|
workshop_reports.insert(data)
|
|
return redirect(url_for('airtable.show_workshop_individual_report', module_id = module_id, workshop_id = workshop_id, participant_id = participant_id ))
|
|
else:
|
|
print("Report found or 'created': " + str(report))
|
|
return render_template('/airtable/workshops/individual_report.html', report = report, participant = participant, workshop = workshop, module = module, module_base = module_base)
|
|
|
|
######## Liste d'appel pour une séance
|
|
@airtable_bp.route('/modules/<module_id>/workshops/<workshop_id>/presences', methods=['GET', 'POST'])
|
|
def presences_workshop(module_id, workshop_id):
|
|
workshops = fetch_api('workshops')
|
|
modules = fetch_api('modules')
|
|
modules_base = fetch_api('modules_base')
|
|
participants = fetch_api('participants')
|
|
|
|
workshop = workshops.get(workshop_id)
|
|
module = modules.get(workshop['fields']['Modules par session'][0])
|
|
module_base = modules_base.get(module['fields']['Module'][0])
|
|
|
|
participants_prevus = [ participants.get(participant) for participant in workshop['fields']['Participants prévus']]
|
|
participants_presents = [ participants.get(participant) for participant in workshop['fields']['Participants présents']]
|
|
participants_presents_ids = [ participant['id'] for participant in participants_presents ]
|
|
|
|
if request.method == 'POST':
|
|
participants_presents_ids = request.form['presentParticipants'].split(',')
|
|
workshops.update(workshop['id'], {"Participants présents": participants_presents_ids})
|
|
return redirect(url_for('airtable.show_workshop', module_id=module_id, workshop_id=workshop_id))
|
|
else:
|
|
return render_template('/airtable/workshops/presences.html', workshop = workshop, module_base = module_base, module = module, participants_prevus = participants_prevus, participants_presents = participants_presents, participants_presents_ids = participants_presents_ids)
|
|
|
|
|
|
########### affichage des modules
|
|
@airtable_bp.route('/modules', methods=['GET'])
|
|
def show_module():
|
|
modules = fetch_api('modules')
|
|
sessions = fetch_api('sessions')
|
|
intervenants = fetch_api('intervenants')
|
|
participants = fetch_api('participants')
|
|
|
|
data_module = []
|
|
for module in modules.get_all():
|
|
if current_user.has_role("gestionnaire"):
|
|
data_module.append(module)
|
|
elif current_user.has_role("prof"):
|
|
if module['fields'].get('Intervenants'):
|
|
for intervenant in module['fields']['Intervenants']:
|
|
intervenant = intervenants.get(intervenant)
|
|
print("intervenant testé : " + str(intervenant))
|
|
print("current user email : " + current_user.email)
|
|
if intervenant['fields'].get('email') and intervenant['fields']['email'] == current_user.email:
|
|
data_module.append(module)
|
|
break
|
|
return render_template('/airtable/modules/modules.html' , records = data_module, sessions = sessions, intervenants = intervenants, participants = participants )
|
|
|
|
|
|
|
|
|
|
|
|
##### Old code
|
|
@airtable_bp.route('/create_record', methods=['GET', 'POST'])
|
|
def create_record():
|
|
field_options = {}
|
|
for field, table_name in ext_fields.items():
|
|
field_options[field.capitalize()] = get_field_options(base_id, table_name)
|
|
|
|
if request.method == 'POST':
|
|
data = {
|
|
'Name': request.form['name'],
|
|
'Notes': request.form['notes'],
|
|
'Status': request.form['status'],
|
|
'atelier': [request.form['atelier']],
|
|
'mentors': [request.form['mentors']]
|
|
#'Date et heure de la fin du Passe Numérique': request.form['date_time'],
|
|
#'As-tu terminé le Passe Numérique jusqu\'au bout?': request.form['completed'],
|
|
#'Résultat à la sortie de l\'opération': request.form['result'],
|
|
#'Choisi le niveau que tu penses avoir atteint à la fin du Passe Numérique': request.form['level'],
|
|
#'Peux-tu me parler de ton parcours?': request.form['story']
|
|
}
|
|
airtable.insert(data)
|
|
return redirect(url_for('airtable.submitted'))
|
|
return render_template('form.html', field_options=field_options)
|
|
|
|
@airtable_bp.route('/submitted')
|
|
def submitted():
|
|
return render_template('submitted.html')
|
|
|