Update app.py
Browse files
app.py
CHANGED
@@ -1,3 +1,4 @@
|
|
|
|
1 |
import os
|
2 |
import dash
|
3 |
import json
|
@@ -25,11 +26,13 @@ from langgraph.checkpoint.memory import MemorySaver
|
|
25 |
from langchain_openai import ChatOpenAI
|
26 |
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage
|
27 |
|
|
|
28 |
import dash
|
29 |
from dash.dependencies import Input, Output, State
|
30 |
from dash import Dash, html, dcc, callback, callback_context, ctx, Output, Input, dash_table, State, no_update, _dash_renderer, clientside_callback
|
31 |
from dash import html
|
32 |
|
|
|
33 |
import dash_bootstrap_components as dbc
|
34 |
from dash.exceptions import PreventUpdate
|
35 |
import dash_mantine_components as dmc
|
@@ -37,6 +40,7 @@ from dash_iconify import DashIconify
|
|
37 |
_dash_renderer._set_react_version("18.2.0")
|
38 |
import flask
|
39 |
from flask_login import LoginManager, UserMixin, login_user, current_user, login_required, logout_user
|
|
|
40 |
from datetime import timedelta
|
41 |
|
42 |
from IPython.display import display, HTML
|
@@ -621,48 +625,37 @@ def init_agent_state(current_url, num, pathname) -> AgentState:
|
|
621 |
if task == "load_and_preprocess":
|
622 |
if key == "current_file":
|
623 |
result += f"Traitement du fichier {taskInfo['current_file']} en cours...\n"
|
624 |
-
|
625 |
if task == "classify_teachings":
|
626 |
if key == "status":
|
627 |
for key, value in taskInfo['classified_teachings'].items():
|
628 |
result += f"\n\n-**Enseignement classé dans la catégorie '{key}'** : "
|
629 |
for enseignement in value:
|
630 |
result += f"{enseignement}, "
|
631 |
-
|
632 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
633 |
-
|
634 |
if task == "create_categories":
|
635 |
if key == "status":
|
636 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
637 |
-
|
638 |
if task == "create_learning_situations":
|
639 |
if key == "status":
|
640 |
if taskInfo['learning_situations'].items():
|
641 |
for key, value in taskInfo['learning_situations'].items():
|
642 |
result += f"\n\n-**Situation d'apprentissage créée pour la catégorie '{key}'** : {value}\n"
|
643 |
-
|
644 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
645 |
-
|
646 |
else:
|
647 |
result += f"\n\nTraitement de la tâche : pas de situations d'apprentissage créées\n"
|
648 |
-
|
649 |
if task == "create_academic_competencies":
|
650 |
if key == "dataframe":
|
651 |
df = taskInfo['dataframe']
|
652 |
if key == "status":
|
653 |
if taskInfo['academic_competencies'].items():
|
654 |
for key, value in taskInfo['academic_competencies'].items():
|
655 |
-
result += f"\n\n-**Compétence académique créée pour la catégorie '{key}'** : {value}\n"
|
656 |
-
|
657 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
658 |
-
|
659 |
else:
|
660 |
result += f"\n\nTraitement de la tâche : pas de BCC créés\n"
|
661 |
-
|
662 |
if task == "export_to_excel_2":
|
663 |
if key == "status":
|
664 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
665 |
-
|
666 |
|
667 |
except Exception as e:
|
668 |
print(f"Erreur lors de l'exécution du workflow: {e}")
|
@@ -690,6 +683,40 @@ def getGitFilesFromRepo(DIRECTORY):
|
|
690 |
})
|
691 |
return all_files
|
692 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
693 |
# Fonction pour extraire les catégories et enseignements
|
694 |
def extract_categories_enseignements(data: Dict) -> pd.DataFrame:
|
695 |
"""Extraire les catégories et enseignements associés dans un DataFrame."""
|
@@ -745,11 +772,12 @@ def extract_situations_apprentissage(data: Dict) -> pd.DataFrame:
|
|
745 |
# the exception.
|
746 |
server = flask.Flask(__name__)
|
747 |
|
748 |
-
app = dash.Dash(__name__, server=server, external_stylesheets=dmc.styles.ALL,
|
749 |
title='BCC Agent',
|
750 |
update_title='Chargement...',
|
751 |
suppress_callback_exceptions=True)
|
752 |
|
|
|
753 |
# Updating the Flask Server configuration with Secret Key to encrypt the user session cookie
|
754 |
server.config['REMEMBER_COOKIE_DURATION'] = timedelta(seconds=3600)
|
755 |
|
@@ -775,39 +803,26 @@ def load_user(username):
|
|
775 |
return User(username)
|
776 |
|
777 |
# User status management views
|
778 |
-
index_page =
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
# html.Div([dcc.Location(id='url_login', refresh=True),
|
799 |
-
# dmc.Text("BCC Agent", id='h1',style={"fontSize": 48}, fw=900),
|
800 |
-
# dmc.TextInput(placeholder="login",w=250, ml="calc(50% - 125px)", id='uname-box'),
|
801 |
-
# dmc.PasswordInput(id='pwd-box',placeholder="Mot de passe",w=250, ml="calc(50% - 125px)", mt=10),
|
802 |
-
# dmc.Button("Continuer", w=250,variant="gradient", n_clicks=0, id='login-button', mt=20, mb=20),
|
803 |
-
# html.Div(children='', id='output-state')
|
804 |
-
# ]), span=4, offset=4, style={'textAlign': 'center', 'marginTop': 'calc(50vh - 120px)','border':'1px solid #495057','border-radius':'10px'}, c='white'
|
805 |
-
# )
|
806 |
-
# ]
|
807 |
-
# )
|
808 |
-
# ]
|
809 |
-
#)]
|
810 |
-
# )
|
811 |
|
812 |
# Successful login
|
813 |
success = html.Div([html.Div([html.H2('Login successful.'),
|
@@ -868,19 +883,19 @@ app.layout = dmc.MantineProvider(
|
|
868 |
html.Div(id='user-status-div'),
|
869 |
html.Div(id='page-content')
|
870 |
])])
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
|
885 |
app_page = dmc.MantineProvider(
|
886 |
[
|
@@ -1095,7 +1110,7 @@ app_page = dmc.MantineProvider(
|
|
1095 |
className="g-0"
|
1096 |
),
|
1097 |
html.H4(id="text-enseignement-dropdown", className="mb-3 text-success", style={"font-size": "0.7rem"}),
|
1098 |
-
|
1099 |
], md=6),
|
1100 |
dbc.Col([
|
1101 |
dbc.Row(
|
@@ -1109,7 +1124,7 @@ app_page = dmc.MantineProvider(
|
|
1109 |
className="g-0"
|
1110 |
),
|
1111 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC", className="mb-3", style={"font-size": "0.7rem"}),
|
1112 |
-
|
1113 |
], md=6)
|
1114 |
]),
|
1115 |
dbc.Row([
|
@@ -1125,7 +1140,7 @@ app_page = dmc.MantineProvider(
|
|
1125 |
className="g-0"
|
1126 |
),
|
1127 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC", className="mb-3", style={"font-size": "0.7rem"}),
|
1128 |
-
|
1129 |
], md=6),
|
1130 |
dbc.Col([
|
1131 |
dbc.Row(
|
@@ -1183,7 +1198,7 @@ app_page = dmc.MantineProvider(
|
|
1183 |
className="g-0"
|
1184 |
),
|
1185 |
html.Div(id="generation-status", className="mb-3"),
|
1186 |
-
|
1187 |
html.Div(id="competence-output", className="p-3 border rounded", style={"color":"rgb(90, 242, 156)","border-color":"rgb(90, 242, 156)!important","background-color":"rgba(90, 242, 156, 0.2)"}),
|
1188 |
),
|
1189 |
], md=12),
|
@@ -1253,7 +1268,7 @@ app_page = dmc.MantineProvider(
|
|
1253 |
align="left",
|
1254 |
className="g-0"
|
1255 |
),
|
1256 |
-
|
1257 |
html.Div(id="notification_wrapper", style={"margin-top":"1rem"}),
|
1258 |
], width=12)
|
1259 |
])
|
@@ -1483,7 +1498,7 @@ app_avid_page = dmc.MantineProvider(
|
|
1483 |
className="g-0"
|
1484 |
),
|
1485 |
html.H4(id="text-enseignement-dropdown", className="mb-3 text-success", style={"font-size": "0.7rem"}),
|
1486 |
-
|
1487 |
], md=6),
|
1488 |
dbc.Col([
|
1489 |
dbc.Row(
|
@@ -1497,7 +1512,7 @@ app_avid_page = dmc.MantineProvider(
|
|
1497 |
className="g-0"
|
1498 |
),
|
1499 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC AVID", className="mb-3", style={"font-size": "0.7rem"}),
|
1500 |
-
|
1501 |
], md=6)
|
1502 |
]),
|
1503 |
dbc.Row([
|
@@ -1513,7 +1528,7 @@ app_avid_page = dmc.MantineProvider(
|
|
1513 |
className="g-0"
|
1514 |
),
|
1515 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC AVID", className="mb-3", style={"font-size": "0.7rem"}),
|
1516 |
-
|
1517 |
], md=6),
|
1518 |
dbc.Col([
|
1519 |
dbc.Row(
|
@@ -1565,7 +1580,7 @@ app_avid_page = dmc.MantineProvider(
|
|
1565 |
className="g-0"
|
1566 |
),
|
1567 |
html.Div(id="generation-status", className="mb-3"),
|
1568 |
-
|
1569 |
html.Div(id="competence-output", className="p-3 border rounded", style={"color":"rgb(90, 242, 156)","border-color":"rgb(90, 242, 156)!important","background-color":"rgba(90, 242, 156, 0.2)"}),
|
1570 |
),
|
1571 |
], md=12),
|
@@ -1635,7 +1650,7 @@ app_avid_page = dmc.MantineProvider(
|
|
1635 |
align="left",
|
1636 |
className="g-0"
|
1637 |
),
|
1638 |
-
|
1639 |
html.Div(id="notification_wrapper-avid", style={"margin-top":"1rem"}),
|
1640 |
], width=12)
|
1641 |
])
|
@@ -1764,31 +1779,28 @@ def update_skills_dropdown(categorie_selected, pathname):
|
|
1764 |
)
|
1765 |
def update_enseignements_dropdown(categorie_selected, pathname):
|
1766 |
"""Mettre à jour les options du dropdown d'enseignements en fonction de la catégorie sélectionnée."""
|
1767 |
-
|
1768 |
-
|
1769 |
-
|
1770 |
-
|
1771 |
-
|
1772 |
-
|
1773 |
-
|
1774 |
-
|
1775 |
-
default_text = "formation sélectionnée : "
|
1776 |
|
1777 |
-
|
1778 |
-
|
1779 |
-
|
1780 |
-
|
1781 |
-
|
1782 |
-
|
1783 |
-
|
1784 |
-
|
1785 |
-
|
1786 |
sort_keys = True, ensure_ascii=False), "Choisir d'abord une maquette de formation avec propositions BCC : " + default_text + jsonData.get("niveau", ""), modal_text
|
1787 |
-
|
1788 |
-
|
1789 |
-
|
1790 |
-
except:
|
1791 |
-
print("Aucun fichier chargé")
|
1792 |
|
1793 |
@app.callback(
|
1794 |
Output("classification-dropdown", "placeholder"),
|
@@ -1799,44 +1811,41 @@ def update_enseignements_dropdown(categorie_selected, pathname):
|
|
1799 |
)
|
1800 |
def update_classification_dropdown(categorie_selected, pathname):
|
1801 |
"""Mettre à jour les options du dropdown d'enseignements en fonction de la catégorie sélectionnée."""
|
1802 |
-
|
1803 |
-
|
1804 |
-
|
1805 |
-
|
1806 |
-
|
1807 |
-
|
1808 |
-
|
1809 |
-
|
1810 |
-
default_text = ""
|
1811 |
|
1812 |
-
|
1813 |
-
|
1814 |
-
|
1815 |
-
|
1816 |
-
|
1817 |
-
|
1818 |
-
|
1819 |
-
|
1820 |
-
|
1821 |
-
|
1822 |
-
|
1823 |
-
|
1824 |
-
|
1825 |
-
|
1826 |
-
|
1827 |
-
|
1828 |
-
|
1829 |
-
|
1830 |
-
|
1831 |
|
1832 |
-
|
1833 |
-
|
1834 |
sort_keys = True, ensure_ascii=False),modal_text
|
1835 |
-
|
1836 |
-
|
1837 |
sort_keys = True, ensure_ascii=False),modal_text
|
1838 |
-
except:
|
1839 |
-
print("Aucun fichier chargé")
|
1840 |
|
1841 |
@app.callback(
|
1842 |
Output("situation-dropdown", "placeholder"),
|
@@ -1847,46 +1856,43 @@ def update_classification_dropdown(categorie_selected, pathname):
|
|
1847 |
)
|
1848 |
def update_situations_dropdown(categorie_selected, pathname):
|
1849 |
"""Mettre à jour les options du dropdown d'enseignements en fonction de la catégorie sélectionnée."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1850 |
try:
|
1851 |
-
if
|
1852 |
-
|
|
|
1853 |
if pathname == "/bcc":
|
1854 |
-
|
|
|
|
|
1855 |
elif pathname == "/bcc-avid":
|
1856 |
-
|
1857 |
-
|
1858 |
-
|
1859 |
-
|
1860 |
-
|
1861 |
-
|
1862 |
-
|
1863 |
-
|
1864 |
-
jsonData = json.loads(base64.b64decode(res.json()['content']))
|
1865 |
-
modal_text = "**Description des situations d'apprentissage :**"
|
1866 |
-
if pathname == "/bcc":
|
1867 |
-
textarea_value = jsonData.get("learning_situations", [])
|
1868 |
-
for key, value in textarea_value.items():
|
1869 |
-
modal_text += f"\n\n- **{key}**: {value}"
|
1870 |
-
elif pathname == "/bcc-avid":
|
1871 |
-
textarea_value = jsonData.get("situations_apprentissage", [])
|
1872 |
-
for item in textarea_value:
|
1873 |
-
modal_text += f"\n\n- **Situation d'apprentissage**: {item['situation']}"
|
1874 |
-
if item['objectifs']:
|
1875 |
-
modal_text += f"\n\nObjectifs : "
|
1876 |
-
for objectif in item['objectifs']:
|
1877 |
-
modal_text += f"\n-{objectif}"
|
1878 |
-
modal_text += f"\n\nLien avec les thématiques ODD11 : {item['lien_odd11']}"
|
1879 |
|
1880 |
-
|
1881 |
-
|
1882 |
sort_keys = True, ensure_ascii=False), modal_text
|
1883 |
-
|
1884 |
-
|
1885 |
sort_keys = True, ensure_ascii=False), modal_text
|
1886 |
-
except:
|
1887 |
-
return "Choisir d'abord une maquette de formation avec proposition BCC", "", "**Aucune situation d'apprentissage définie pour cette maquette de formation.**"
|
1888 |
except:
|
1889 |
-
|
1890 |
|
1891 |
@app.callback(
|
1892 |
Output("selection-display", "children"),
|
@@ -2248,47 +2254,5 @@ def display_status(num, current, n_clicks, pathname):
|
|
2248 |
except:
|
2249 |
return html.Div(dcc.Markdown(f"""{agent}""", style={"color":"white","font-size":"0.75rem"})), []
|
2250 |
|
2251 |
-
clientside_callback(
|
2252 |
-
"""connected => !connected""",
|
2253 |
-
Output("submit-button", "disabled"),
|
2254 |
-
)
|
2255 |
-
|
2256 |
-
clientside_callback(
|
2257 |
-
"""(notification) => {
|
2258 |
-
if (!notification) return dash_clientside.no_update
|
2259 |
-
return notification
|
2260 |
-
}""",
|
2261 |
-
Output("notification_wrapper", "children", allow_duplicate=True),
|
2262 |
-
prevent_initial_call=True,
|
2263 |
-
)
|
2264 |
-
|
2265 |
-
clientside_callback(
|
2266 |
-
"""(word, text) => text + word""",
|
2267 |
-
Output("output-response", "children", allow_duplicate=True),
|
2268 |
-
State("output-response", "children"),
|
2269 |
-
prevent_initial_call=True,
|
2270 |
-
)
|
2271 |
-
|
2272 |
-
clientside_callback(
|
2273 |
-
"""connected => !connected""",
|
2274 |
-
Output("submit-button-avid", "disabled"),
|
2275 |
-
)
|
2276 |
-
|
2277 |
-
clientside_callback(
|
2278 |
-
"""(notification) => {
|
2279 |
-
if (!notification) return dash_clientside.no_update
|
2280 |
-
return notification
|
2281 |
-
}""",
|
2282 |
-
Output("notification_wrapper-avid", "children", allow_duplicate=True),
|
2283 |
-
prevent_initial_call=True,
|
2284 |
-
)
|
2285 |
-
|
2286 |
-
clientside_callback(
|
2287 |
-
"""(word, text) => text + word""",
|
2288 |
-
Output("output-response-avid", "children", allow_duplicate=True),
|
2289 |
-
State("output-response-avid", "children"),
|
2290 |
-
prevent_initial_call=True,
|
2291 |
-
)
|
2292 |
-
|
2293 |
if __name__ == '__main__':
|
2294 |
app.run_server(debug=True)
|
|
|
1 |
+
|
2 |
import os
|
3 |
import dash
|
4 |
import json
|
|
|
26 |
from langchain_openai import ChatOpenAI
|
27 |
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage
|
28 |
|
29 |
+
from dash_socketio import DashSocketIO
|
30 |
import dash
|
31 |
from dash.dependencies import Input, Output, State
|
32 |
from dash import Dash, html, dcc, callback, callback_context, ctx, Output, Input, dash_table, State, no_update, _dash_renderer, clientside_callback
|
33 |
from dash import html
|
34 |
|
35 |
+
import dash_bootstrap_components as dbc
|
36 |
import dash_bootstrap_components as dbc
|
37 |
from dash.exceptions import PreventUpdate
|
38 |
import dash_mantine_components as dmc
|
|
|
40 |
_dash_renderer._set_react_version("18.2.0")
|
41 |
import flask
|
42 |
from flask_login import LoginManager, UserMixin, login_user, current_user, login_required, logout_user
|
43 |
+
from flask_socketio import SocketIO, emit
|
44 |
from datetime import timedelta
|
45 |
|
46 |
from IPython.display import display, HTML
|
|
|
625 |
if task == "load_and_preprocess":
|
626 |
if key == "current_file":
|
627 |
result += f"Traitement du fichier {taskInfo['current_file']} en cours...\n"
|
|
|
628 |
if task == "classify_teachings":
|
629 |
if key == "status":
|
630 |
for key, value in taskInfo['classified_teachings'].items():
|
631 |
result += f"\n\n-**Enseignement classé dans la catégorie '{key}'** : "
|
632 |
for enseignement in value:
|
633 |
result += f"{enseignement}, "
|
|
|
634 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
|
|
635 |
if task == "create_categories":
|
636 |
if key == "status":
|
637 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
|
|
638 |
if task == "create_learning_situations":
|
639 |
if key == "status":
|
640 |
if taskInfo['learning_situations'].items():
|
641 |
for key, value in taskInfo['learning_situations'].items():
|
642 |
result += f"\n\n-**Situation d'apprentissage créée pour la catégorie '{key}'** : {value}\n"
|
|
|
643 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
|
|
644 |
else:
|
645 |
result += f"\n\nTraitement de la tâche : pas de situations d'apprentissage créées\n"
|
|
|
646 |
if task == "create_academic_competencies":
|
647 |
if key == "dataframe":
|
648 |
df = taskInfo['dataframe']
|
649 |
if key == "status":
|
650 |
if taskInfo['academic_competencies'].items():
|
651 |
for key, value in taskInfo['academic_competencies'].items():
|
652 |
+
result += f"\n\n-**Compétence académique créée pour la catégorie '{key}'** : {value}\n"
|
|
|
653 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
|
|
654 |
else:
|
655 |
result += f"\n\nTraitement de la tâche : pas de BCC créés\n"
|
|
|
656 |
if task == "export_to_excel_2":
|
657 |
if key == "status":
|
658 |
result += f"\n\nTraitement de la tâche : {taskInfo['status']}...\n"
|
|
|
659 |
|
660 |
except Exception as e:
|
661 |
print(f"Erreur lors de l'exécution du workflow: {e}")
|
|
|
683 |
})
|
684 |
return all_files
|
685 |
|
686 |
+
def load_json_files(directory_path: str = "./BCC-Application/JSON"):
|
687 |
+
if not os.path.exists(directory_path):
|
688 |
+
print(f"Erreur: Le répertoire {directory_path} n'existe pas.")
|
689 |
+
return
|
690 |
+
|
691 |
+
# Récupérer la liste des fichiers CSV dans le répertoire
|
692 |
+
json_files = glob.glob(os.path.join(directory_path, "*.json"))
|
693 |
+
|
694 |
+
if not json_files:
|
695 |
+
print(f"Aucun fichier JSON trouvé dans le répertoire {directory_path}.")
|
696 |
+
return
|
697 |
+
|
698 |
+
print(f"Fichiers JSON trouvés: {len(json_files)}")
|
699 |
+
#for file in json_files:
|
700 |
+
# print(f"- {file}")
|
701 |
+
return json_files
|
702 |
+
|
703 |
+
def load_json_AVID_files(directory_path: str = "./VD-Agent/JSON"):
|
704 |
+
if not os.path.exists(directory_path):
|
705 |
+
print(f"Erreur: Le répertoire {directory_path} n'existe pas.")
|
706 |
+
return
|
707 |
+
|
708 |
+
# Récupérer la liste des fichiers CSV dans le répertoire
|
709 |
+
json_files = glob.glob(os.path.join(directory_path, "*.json"))
|
710 |
+
|
711 |
+
if not json_files:
|
712 |
+
print(f"Aucun fichier JSON trouvé dans le répertoire {directory_path}.")
|
713 |
+
return
|
714 |
+
|
715 |
+
print(f"Fichiers JSON trouvés: {len(json_files)}")
|
716 |
+
#for file in json_files:
|
717 |
+
# print(f"- {file}")
|
718 |
+
return json_files
|
719 |
+
|
720 |
# Fonction pour extraire les catégories et enseignements
|
721 |
def extract_categories_enseignements(data: Dict) -> pd.DataFrame:
|
722 |
"""Extraire les catégories et enseignements associés dans un DataFrame."""
|
|
|
772 |
# the exception.
|
773 |
server = flask.Flask(__name__)
|
774 |
|
775 |
+
app = dash.Dash(__name__, server=server, external_stylesheets=[dmc.styles.ALL, dbc.themes.DARKLY],
|
776 |
title='BCC Agent',
|
777 |
update_title='Chargement...',
|
778 |
suppress_callback_exceptions=True)
|
779 |
|
780 |
+
#socketio = SocketIO(app.server)
|
781 |
# Updating the Flask Server configuration with Secret Key to encrypt the user session cookie
|
782 |
server.config['REMEMBER_COOKIE_DURATION'] = timedelta(seconds=3600)
|
783 |
|
|
|
803 |
return User(username)
|
804 |
|
805 |
# User status management views
|
806 |
+
index_page = dmc.MantineProvider(
|
807 |
+
[
|
808 |
+
dmc.Container(
|
809 |
+
children=[
|
810 |
+
dmc.Grid(
|
811 |
+
children=[
|
812 |
+
dmc.GridCol(
|
813 |
+
html.Div([dcc.Location(id='url_login', refresh=True),
|
814 |
+
dmc.Text("BCC Agent", id='h1',style={"fontSize": 48}, fw=900),
|
815 |
+
dmc.TextInput(placeholder="login",w=250, ml="calc(50% - 125px)", id='uname-box'),
|
816 |
+
dmc.PasswordInput(id='pwd-box',placeholder="Mot de passe",w=250, ml="calc(50% - 125px)", mt=10),
|
817 |
+
dmc.Button("Continuer", w=250,variant="gradient", n_clicks=0, id='login-button', mt=20, mb=20),
|
818 |
+
html.Div(children='', id='output-state')
|
819 |
+
]), span=4, offset=4, style={'textAlign': 'center', 'marginTop': 'calc(50vh - 120px)','border':'1px solid #495057','border-radius':'10px'}, c='white'
|
820 |
+
)
|
821 |
+
]
|
822 |
+
)
|
823 |
+
]
|
824 |
+
)],forceColorScheme="dark"
|
825 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
826 |
|
827 |
# Successful login
|
828 |
success = html.Div([html.Div([html.H2('Login successful.'),
|
|
|
883 |
html.Div(id='user-status-div'),
|
884 |
html.Div(id='page-content')
|
885 |
])])
|
886 |
+
def layout(**kwargs):
|
887 |
+
return dmc.MantineProvider(
|
888 |
+
[
|
889 |
+
html.Div([
|
890 |
+
dcc.Location(id='url', refresh=False),
|
891 |
+
dcc.Location(id='redirect', refresh=True),
|
892 |
+
dcc.Store(id='login-status', storage_type='session'),
|
893 |
+
dcc.Store(id="history-store", storage_type="session", data=[]),
|
894 |
+
dcc.Store(id="model-params-store", storage_type="session", data={"model": "mistralai/Mistral-Small-3.1-24B-Instruct-2503","temperature": 0.7,"max_tokens": 1024,"top_p": 0.9}),
|
895 |
+
html.Div(id='user-status-div'),
|
896 |
+
html.Div(id='page-content')
|
897 |
+
]),
|
898 |
+
],forceColorScheme="dark", span=12, offset=0, c='white')
|
899 |
|
900 |
app_page = dmc.MantineProvider(
|
901 |
[
|
|
|
1110 |
className="g-0"
|
1111 |
),
|
1112 |
html.H4(id="text-enseignement-dropdown", className="mb-3 text-success", style={"font-size": "0.7rem"}),
|
1113 |
+
dbc.Textarea(id="enseignement-dropdown", className="mb-3", style={"height":"200px", "max-height":"250px", "font-size": "0.75rem","color":"white","border":"border 1px solid rgb(67,167,255)!important", "background-color":"transparent"}),
|
1114 |
], md=6),
|
1115 |
dbc.Col([
|
1116 |
dbc.Row(
|
|
|
1124 |
className="g-0"
|
1125 |
),
|
1126 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC", className="mb-3", style={"font-size": "0.7rem"}),
|
1127 |
+
dbc.Textarea(id="classification-dropdown", className="mb-3", placeholder="Choisir d'abord une maquette avec propositions BCC", style={"height":"200px", "max-height":"250px", "font-size": "0.75rem","color":"white","border":"border 1px solid rgb(67,167,255)!important", "background-color":"transparent"}),
|
1128 |
], md=6)
|
1129 |
]),
|
1130 |
dbc.Row([
|
|
|
1140 |
className="g-0"
|
1141 |
),
|
1142 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC", className="mb-3", style={"font-size": "0.7rem"}),
|
1143 |
+
dbc.Textarea(id="situation-dropdown", className="mb-3", placeholder="Choisir d'abord une maquette avec propositions BCC", style={"height":"200px", "max-height":"250px", "font-size": "0.75rem","color":"white","border":"border 1px solid rgb(67,167,255)!important", "background-color":"transparent"}),
|
1144 |
], md=6),
|
1145 |
dbc.Col([
|
1146 |
dbc.Row(
|
|
|
1198 |
className="g-0"
|
1199 |
),
|
1200 |
html.Div(id="generation-status", className="mb-3"),
|
1201 |
+
dbc.Spinner(
|
1202 |
html.Div(id="competence-output", className="p-3 border rounded", style={"color":"rgb(90, 242, 156)","border-color":"rgb(90, 242, 156)!important","background-color":"rgba(90, 242, 156, 0.2)"}),
|
1203 |
),
|
1204 |
], md=12),
|
|
|
1268 |
align="left",
|
1269 |
className="g-0"
|
1270 |
),
|
1271 |
+
html.Div(id='output-response', style={"color":"rgb(90, 242, 156)","border-radius":"3px","border":"1px solid rgb(255,255,255)!important","background-color":"rgba(90, 242, 156, 0.2)","padding":"5px"}),
|
1272 |
html.Div(id="notification_wrapper", style={"margin-top":"1rem"}),
|
1273 |
], width=12)
|
1274 |
])
|
|
|
1498 |
className="g-0"
|
1499 |
),
|
1500 |
html.H4(id="text-enseignement-dropdown", className="mb-3 text-success", style={"font-size": "0.7rem"}),
|
1501 |
+
dbc.Textarea(id="enseignement-dropdown", className="mb-3", style={"height":"200px", "max-height":"250px", "font-size": "0.75rem","color":"white","border":"border 1px solid rgb(67,167,255)!important", "background-color":"transparent"}),
|
1502 |
], md=6),
|
1503 |
dbc.Col([
|
1504 |
dbc.Row(
|
|
|
1512 |
className="g-0"
|
1513 |
),
|
1514 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC AVID", className="mb-3", style={"font-size": "0.7rem"}),
|
1515 |
+
dbc.Textarea(id="classification-dropdown", className="mb-3", placeholder="Choisir d'abord une maquette avec propositions BCC AVID", style={"height":"200px", "max-height":"250px", "font-size": "0.75rem","color":"white","border":"border 1px solid rgb(67,167,255)!important", "background-color":"transparent"}),
|
1516 |
], md=6)
|
1517 |
]),
|
1518 |
dbc.Row([
|
|
|
1528 |
className="g-0"
|
1529 |
),
|
1530 |
html.H4("Choisir d'abord une maquette de formation avec propositions BCC AVID", className="mb-3", style={"font-size": "0.7rem"}),
|
1531 |
+
dbc.Textarea(id="situation-dropdown", className="mb-3", placeholder="Choisir d'abord une maquette avec propositions BCC AVID", style={"height":"200px", "max-height":"250px", "font-size": "0.75rem","color":"white","border":"border 1px solid rgb(67,167,255)!important", "background-color":"transparent"}),
|
1532 |
], md=6),
|
1533 |
dbc.Col([
|
1534 |
dbc.Row(
|
|
|
1580 |
className="g-0"
|
1581 |
),
|
1582 |
html.Div(id="generation-status", className="mb-3"),
|
1583 |
+
dbc.Spinner(
|
1584 |
html.Div(id="competence-output", className="p-3 border rounded", style={"color":"rgb(90, 242, 156)","border-color":"rgb(90, 242, 156)!important","background-color":"rgba(90, 242, 156, 0.2)"}),
|
1585 |
),
|
1586 |
], md=12),
|
|
|
1650 |
align="left",
|
1651 |
className="g-0"
|
1652 |
),
|
1653 |
+
html.Div(id='output-response-avid', style={"color":"rgb(156, 242, 242)","border-radius":"3px","border":"1px solid rgb(255,255,255)!important","background-color":"rgba(156, 242, 242, 0.2)","padding":"5px"}),
|
1654 |
html.Div(id="notification_wrapper-avid", style={"margin-top":"1rem"}),
|
1655 |
], width=12)
|
1656 |
])
|
|
|
1779 |
)
|
1780 |
def update_enseignements_dropdown(categorie_selected, pathname):
|
1781 |
"""Mettre à jour les options du dropdown d'enseignements en fonction de la catégorie sélectionnée."""
|
1782 |
+
if not categorie_selected:
|
1783 |
+
default_text = "par défaut : "
|
1784 |
+
if pathname == "/bcc":
|
1785 |
+
categorie_selected = 'JSON/L1-Anglais.json'
|
1786 |
+
elif pathname == "/bcc-avid":
|
1787 |
+
categorie_selected = 'VD/JSON/L1-Lettres-Modernes.json'
|
1788 |
+
else:
|
1789 |
+
default_text = "formation sélectionnée : "
|
|
|
1790 |
|
1791 |
+
url = f"https://api.github.com/repos/{OWNER}/{REPO}/contents/{categorie_selected}"
|
1792 |
+
res = requests.get(url, headers=headers, params=params)
|
1793 |
+
if res.status_code == 200:
|
1794 |
+
jsonData = json.loads(base64.b64decode(res.json()['content']))
|
1795 |
+
modal_text = "**Description des catégories d'enseignements : **\n\n"
|
1796 |
+
for item in jsonData.get("categories", []):
|
1797 |
+
modal_text += f"- **{item['nom']}**:\n\n{item['description']}\n\n"
|
1798 |
+
if pathname == "/bcc":
|
1799 |
+
return "Choisir d'abord une maquette de formation avec proposition BCC", json.dumps(jsonData.get("categories", []), indent = 6, separators =(",", ":"),
|
1800 |
sort_keys = True, ensure_ascii=False), "Choisir d'abord une maquette de formation avec propositions BCC : " + default_text + jsonData.get("niveau", ""), modal_text
|
1801 |
+
elif pathname == "/bcc-avid":
|
1802 |
+
return "Choisir d'abord une maquette de formation avec proposition BCC", json.dumps(jsonData.get("categories", []), indent = 6, separators =(",", ":"),
|
1803 |
+
sort_keys = True, ensure_ascii=False), "Choisir d'abord une maquette de formation avec propositions BCC : " + default_text + jsonData.get("niveau_etude", ""), modal_text
|
|
|
|
|
1804 |
|
1805 |
@app.callback(
|
1806 |
Output("classification-dropdown", "placeholder"),
|
|
|
1811 |
)
|
1812 |
def update_classification_dropdown(categorie_selected, pathname):
|
1813 |
"""Mettre à jour les options du dropdown d'enseignements en fonction de la catégorie sélectionnée."""
|
1814 |
+
if not categorie_selected:
|
1815 |
+
default_text = "par défaut : "
|
1816 |
+
if pathname == "/bcc":
|
1817 |
+
categorie_selected = 'JSON/L1-Anglais.json'
|
1818 |
+
elif pathname == "/bcc-avid":
|
1819 |
+
categorie_selected = 'VD/JSON/L1-Lettres-Modernes.json'
|
1820 |
+
else:
|
1821 |
+
default_text = ""
|
|
|
1822 |
|
1823 |
+
url = f"https://api.github.com/repos/{OWNER}/{REPO}/contents/{categorie_selected}"
|
1824 |
+
res = requests.get(url, headers=headers, params=params)
|
1825 |
+
if res.status_code == 200:
|
1826 |
+
jsonData = json.loads(base64.b64decode(res.json()['content']))
|
1827 |
+
modal_text = "**Classification des enseignements :**"
|
1828 |
+
if pathname == "/bcc":
|
1829 |
+
textarea_value = jsonData.get("classified_teachings", [])
|
1830 |
+
for key, value in textarea_value.items():
|
1831 |
+
modal_text += f"\n\n- **{key}**: "
|
1832 |
+
for i in range(0,len(value)):
|
1833 |
+
modal_text += f"{value[i]}\t"
|
1834 |
+
elif pathname == "/bcc-avid":
|
1835 |
+
textarea_value = jsonData.get("dataframe", [])
|
1836 |
+
test = " "
|
1837 |
+
for item in sorted(textarea_value, key=lambda x: x['categorie'] if x['categorie'] else ""):
|
1838 |
+
if test != item['categorie']:
|
1839 |
+
modal_text += f"\n\n- **{item['categorie']}**: "
|
1840 |
+
modal_text += f"{item['enseignements']}\t"
|
1841 |
+
test = item['categorie']
|
1842 |
|
1843 |
+
if pathname == "/bcc":
|
1844 |
+
return "Choisir d'abord une maquette de formation avec proposition BCC", json.dumps(textarea_value, indent = 6, separators =(",", ":"),
|
1845 |
sort_keys = True, ensure_ascii=False),modal_text
|
1846 |
+
elif pathname == "/bcc-avid":
|
1847 |
+
return "Choisir d'abord une maquette de formation avec proposition BCC", json.dumps(textarea_value, indent = 6, separators =(",", ":"),
|
1848 |
sort_keys = True, ensure_ascii=False),modal_text
|
|
|
|
|
1849 |
|
1850 |
@app.callback(
|
1851 |
Output("situation-dropdown", "placeholder"),
|
|
|
1856 |
)
|
1857 |
def update_situations_dropdown(categorie_selected, pathname):
|
1858 |
"""Mettre à jour les options du dropdown d'enseignements en fonction de la catégorie sélectionnée."""
|
1859 |
+
if not categorie_selected:
|
1860 |
+
default_text = "par défaut : "
|
1861 |
+
if pathname == "/bcc":
|
1862 |
+
categorie_selected = 'JSON/L1-Anglais.json'
|
1863 |
+
elif pathname == "/bcc-avid":
|
1864 |
+
categorie_selected = 'VD/JSON/L1-Lettres-Modernes.json'
|
1865 |
+
else:
|
1866 |
+
default_text = ""
|
1867 |
+
|
1868 |
+
url = f"https://api.github.com/repos/{OWNER}/{REPO}/contents/{categorie_selected}"
|
1869 |
+
res = requests.get(url, headers=headers, params=params)
|
1870 |
try:
|
1871 |
+
if res.status_code == 200:
|
1872 |
+
jsonData = json.loads(base64.b64decode(res.json()['content']))
|
1873 |
+
modal_text = "**Description des situations d'apprentissage :**"
|
1874 |
if pathname == "/bcc":
|
1875 |
+
textarea_value = jsonData.get("learning_situations", [])
|
1876 |
+
for key, value in textarea_value.items():
|
1877 |
+
modal_text += f"\n\n- **{key}**: {value}"
|
1878 |
elif pathname == "/bcc-avid":
|
1879 |
+
textarea_value = jsonData.get("situations_apprentissage", [])
|
1880 |
+
for item in textarea_value:
|
1881 |
+
modal_text += f"\n\n- **Situation d'apprentissage**: {item['situation']}"
|
1882 |
+
if item['objectifs']:
|
1883 |
+
modal_text += f"\n\nObjectifs : "
|
1884 |
+
for objectif in item['objectifs']:
|
1885 |
+
modal_text += f"\n-{objectif}"
|
1886 |
+
modal_text += f"\n\nLien avec les thématiques ODD11 : {item['lien_odd11']}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1887 |
|
1888 |
+
if pathname == "/bcc":
|
1889 |
+
return "Choisir d'abord une maquette de formation avec proposition BCC", json.dumps(textarea_value, indent = 6, separators =(",", ":"),
|
1890 |
sort_keys = True, ensure_ascii=False), modal_text
|
1891 |
+
elif pathname == "/bcc-avid":
|
1892 |
+
return "Choisir d'abord une maquette de formation avec proposition BCC", json.dumps(textarea_value, indent = 6, separators =(",", ":"),
|
1893 |
sort_keys = True, ensure_ascii=False), modal_text
|
|
|
|
|
1894 |
except:
|
1895 |
+
return "Choisir d'abord une maquette de formation avec proposition BCC", "", "**Aucune situation d'apprentissage définie pour cette maquette de formation.**"
|
1896 |
|
1897 |
@app.callback(
|
1898 |
Output("selection-display", "children"),
|
|
|
2254 |
except:
|
2255 |
return html.Div(dcc.Markdown(f"""{agent}""", style={"color":"white","font-size":"0.75rem"})), []
|
2256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2257 |
if __name__ == '__main__':
|
2258 |
app.run_server(debug=True)
|