ositah 25.6.dev1__py3-none-any.whl → 25.9.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ositah might be problematic. Click here for more details.
- ositah/app.py +17 -17
- ositah/apps/analysis.py +785 -785
- ositah/apps/configuration/callbacks.py +916 -916
- ositah/apps/configuration/main.py +546 -546
- ositah/apps/configuration/parameters.py +74 -74
- ositah/apps/configuration/tools.py +112 -112
- ositah/apps/export.py +1208 -1191
- ositah/apps/validation/callbacks.py +240 -240
- ositah/apps/validation/main.py +89 -89
- ositah/apps/validation/parameters.py +25 -25
- ositah/apps/validation/tables.py +646 -646
- ositah/apps/validation/tools.py +552 -552
- ositah/assets/arrow_down_up.svg +3 -3
- ositah/assets/ositah.css +53 -53
- ositah/assets/sort_ascending.svg +4 -4
- ositah/assets/sort_descending.svg +5 -5
- ositah/assets/sorttable.js +499 -499
- ositah/main.py +449 -449
- ositah/ositah.example.cfg +229 -229
- ositah/static/style.css +53 -53
- ositah/templates/base.html +22 -22
- ositah/templates/bootstrap_login.html +38 -38
- ositah/templates/login_form.html +26 -26
- ositah/utils/agents.py +124 -124
- ositah/utils/authentication.py +287 -287
- ositah/utils/cache.py +19 -19
- ositah/utils/core.py +13 -13
- ositah/utils/exceptions.py +64 -64
- ositah/utils/hito_db.py +51 -51
- ositah/utils/hito_db_model.py +253 -253
- ositah/utils/menus.py +339 -339
- ositah/utils/period.py +139 -139
- ositah/utils/projects.py +1178 -1178
- ositah/utils/teams.py +42 -42
- ositah/utils/utils.py +474 -474
- {ositah-25.6.dev1.dist-info → ositah-25.9.dev1.dist-info}/METADATA +149 -150
- ositah-25.9.dev1.dist-info/RECORD +46 -0
- {ositah-25.6.dev1.dist-info → ositah-25.9.dev1.dist-info}/licenses/LICENSE +29 -29
- ositah-25.6.dev1.dist-info/RECORD +0 -46
- {ositah-25.6.dev1.dist-info → ositah-25.9.dev1.dist-info}/WHEEL +0 -0
- {ositah-25.6.dev1.dist-info → ositah-25.9.dev1.dist-info}/entry_points.txt +0 -0
- {ositah-25.6.dev1.dist-info → ositah-25.9.dev1.dist-info}/top_level.txt +0 -0
|
@@ -1,546 +1,546 @@
|
|
|
1
|
-
"""
|
|
2
|
-
OSITAH subapplication to manage the configuration
|
|
3
|
-
|
|
4
|
-
This file contains only the layout definitions
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from datetime import date
|
|
8
|
-
|
|
9
|
-
from dash import dcc
|
|
10
|
-
|
|
11
|
-
from ositah.apps.configuration.callbacks import *
|
|
12
|
-
from ositah.utils.menus import TABLE_TYPE_DUMMY_STORE
|
|
13
|
-
from ositah.utils.projects import MASTERPROJECT_DELETED_ACTIVITY
|
|
14
|
-
from ositah.utils.utils import AUTHORIZED_ROLES, HITO_ROLE_PROJECT_MGR
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def configuration_layout():
|
|
18
|
-
"""
|
|
19
|
-
Build the layout for this application, after reading the data if necessary.
|
|
20
|
-
|
|
21
|
-
:return: application layout
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
return html.Div(
|
|
25
|
-
[
|
|
26
|
-
html.H1("Configuration OSITAH"),
|
|
27
|
-
html.Div(
|
|
28
|
-
configuration_submenus(),
|
|
29
|
-
id="configuration-submenus",
|
|
30
|
-
style={"marginTop": "3em"},
|
|
31
|
-
),
|
|
32
|
-
# The following dcc.Store coupled with tables must be created in the layout for
|
|
33
|
-
# the callback to work
|
|
34
|
-
dcc.Store(
|
|
35
|
-
id={"type": TABLE_TYPE_DUMMY_STORE, "id": TABLE_NSIP_PROJECT_SYNC_ID},
|
|
36
|
-
data=0,
|
|
37
|
-
),
|
|
38
|
-
]
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def declaration_periods_layout():
|
|
43
|
-
"""
|
|
44
|
-
Define the layout specific to the management of declaration periods
|
|
45
|
-
|
|
46
|
-
:return: html.Div component
|
|
47
|
-
"""
|
|
48
|
-
|
|
49
|
-
declaration_periods = get_declaration_periods(descending=False)
|
|
50
|
-
declaration_period_items = []
|
|
51
|
-
i = 0
|
|
52
|
-
for period in declaration_periods:
|
|
53
|
-
declaration_period_items.append({"label": period.name, "value": i})
|
|
54
|
-
i += 1
|
|
55
|
-
|
|
56
|
-
# Disable creation of a new (next) period if the period matching the current already exists
|
|
57
|
-
today = date.today().isoformat()
|
|
58
|
-
if (
|
|
59
|
-
len(declaration_periods) > 0
|
|
60
|
-
and today >= declaration_periods[-1].start_date
|
|
61
|
-
and today <= declaration_periods[-1].end_date
|
|
62
|
-
):
|
|
63
|
-
current_period_exists = True
|
|
64
|
-
else:
|
|
65
|
-
current_period_exists = False
|
|
66
|
-
|
|
67
|
-
period_params = [
|
|
68
|
-
dbc.Row(
|
|
69
|
-
[
|
|
70
|
-
dbc.Label(
|
|
71
|
-
"Date de début",
|
|
72
|
-
html_for=DECLARATION_PERIOD_START_DATE_ID,
|
|
73
|
-
style={"fontWeight": "bold"},
|
|
74
|
-
width="5",
|
|
75
|
-
),
|
|
76
|
-
dbc.Col(
|
|
77
|
-
dcc.DatePickerSingle(
|
|
78
|
-
id=DECLARATION_PERIOD_START_DATE_ID,
|
|
79
|
-
month_format="MMMM Y",
|
|
80
|
-
placeholder="MMMM Y",
|
|
81
|
-
),
|
|
82
|
-
width="auto",
|
|
83
|
-
class_name="me-3",
|
|
84
|
-
),
|
|
85
|
-
],
|
|
86
|
-
style={"marginBottom": "10px"},
|
|
87
|
-
),
|
|
88
|
-
dbc.Row(
|
|
89
|
-
[
|
|
90
|
-
dbc.Label(
|
|
91
|
-
"Date de validation",
|
|
92
|
-
html_for=DECLARATION_PERIOD_VALIDATION_DATE_ID,
|
|
93
|
-
style={"fontWeight": "bold"},
|
|
94
|
-
width="5",
|
|
95
|
-
),
|
|
96
|
-
dbc.Col(
|
|
97
|
-
dcc.DatePickerSingle(
|
|
98
|
-
id=DECLARATION_PERIOD_VALIDATION_DATE_ID,
|
|
99
|
-
month_format="MMMM Y",
|
|
100
|
-
placeholder="MMMM Y",
|
|
101
|
-
),
|
|
102
|
-
width="auto",
|
|
103
|
-
class_name="me-3",
|
|
104
|
-
),
|
|
105
|
-
],
|
|
106
|
-
style={"marginBottom": "10px"},
|
|
107
|
-
),
|
|
108
|
-
dbc.Row(
|
|
109
|
-
[
|
|
110
|
-
dbc.Label(
|
|
111
|
-
"Date de fin",
|
|
112
|
-
html_for=DECLARATION_PERIOD_END_DATE_ID,
|
|
113
|
-
style={"fontWeight": "bold"},
|
|
114
|
-
width="5",
|
|
115
|
-
),
|
|
116
|
-
dbc.Col(
|
|
117
|
-
dcc.DatePickerSingle(
|
|
118
|
-
id=DECLARATION_PERIOD_END_DATE_ID,
|
|
119
|
-
month_format="MMMM Y",
|
|
120
|
-
placeholder="MMMM Y",
|
|
121
|
-
),
|
|
122
|
-
width="auto",
|
|
123
|
-
class_name="me-3",
|
|
124
|
-
),
|
|
125
|
-
],
|
|
126
|
-
style={"marginBottom": "10px"},
|
|
127
|
-
),
|
|
128
|
-
dbc.Row(
|
|
129
|
-
[
|
|
130
|
-
dbc.Label(
|
|
131
|
-
"Nom",
|
|
132
|
-
html_for=DECLARATION_PERIOD_NAME_ID,
|
|
133
|
-
style={"fontWeight": "bold"},
|
|
134
|
-
width="5",
|
|
135
|
-
),
|
|
136
|
-
dbc.Col(
|
|
137
|
-
dbc.Input(
|
|
138
|
-
type="start_date",
|
|
139
|
-
id=DECLARATION_PERIOD_NAME_ID,
|
|
140
|
-
placeholder="Nom de la période",
|
|
141
|
-
),
|
|
142
|
-
width="6",
|
|
143
|
-
class_name="me-3",
|
|
144
|
-
),
|
|
145
|
-
],
|
|
146
|
-
),
|
|
147
|
-
]
|
|
148
|
-
|
|
149
|
-
return html.Div(
|
|
150
|
-
[
|
|
151
|
-
html.P(),
|
|
152
|
-
dbc.Alert(id=DECLARATION_PERIODS_STATUS_ID, is_open=False),
|
|
153
|
-
dbc.Row(
|
|
154
|
-
[
|
|
155
|
-
dbc.Col(
|
|
156
|
-
[
|
|
157
|
-
dbc.Label(html.B("Périodes")),
|
|
158
|
-
dbc.Select(
|
|
159
|
-
id=DECLARATION_PERIODS_ID,
|
|
160
|
-
options=declaration_period_items,
|
|
161
|
-
html_size=DECLARATION_PERIODS_LIST_MAX_SIZE,
|
|
162
|
-
),
|
|
163
|
-
],
|
|
164
|
-
width={"offset": 1, "size": 3},
|
|
165
|
-
),
|
|
166
|
-
dbc.Col(
|
|
167
|
-
dbc.Form(period_params),
|
|
168
|
-
id=DECLARATION_PERIOD_PARAMS_ID,
|
|
169
|
-
style={
|
|
170
|
-
"border": "1px solid",
|
|
171
|
-
"borderRadius": "4px",
|
|
172
|
-
"borderSizing": "border-box",
|
|
173
|
-
"padding": "10px 10px",
|
|
174
|
-
"visibility": "hidden",
|
|
175
|
-
},
|
|
176
|
-
width={"offset": 1, "size": 4},
|
|
177
|
-
),
|
|
178
|
-
],
|
|
179
|
-
align="center",
|
|
180
|
-
justify="start",
|
|
181
|
-
),
|
|
182
|
-
dbc.Row(
|
|
183
|
-
[
|
|
184
|
-
dbc.Col(
|
|
185
|
-
html.Div(
|
|
186
|
-
dbc.Button(
|
|
187
|
-
"Nouveau semestre",
|
|
188
|
-
id=DECLARATION_PERIODS_CREATE_NEW_ID,
|
|
189
|
-
disabled=current_period_exists,
|
|
190
|
-
),
|
|
191
|
-
id=DECLARATION_PERIODS_CREATE_DIV_ID,
|
|
192
|
-
),
|
|
193
|
-
width={"size": 3, "offset": 0},
|
|
194
|
-
),
|
|
195
|
-
dbc.Col(
|
|
196
|
-
dbc.Button(
|
|
197
|
-
"Valider",
|
|
198
|
-
id=DECLARATION_PERIODS_SAVE_NEW_ID,
|
|
199
|
-
disabled=True,
|
|
200
|
-
),
|
|
201
|
-
width={"size": 3, "offset": 0},
|
|
202
|
-
),
|
|
203
|
-
dbc.Tooltip(
|
|
204
|
-
(
|
|
205
|
-
"Le semestre courant existe déjà"
|
|
206
|
-
if current_period_exists
|
|
207
|
-
else "Ajoute le semestre courant"
|
|
208
|
-
),
|
|
209
|
-
target=DECLARATION_PERIODS_CREATE_DIV_ID,
|
|
210
|
-
placement="bottom",
|
|
211
|
-
),
|
|
212
|
-
],
|
|
213
|
-
justify="evenly",
|
|
214
|
-
style={"marginTop": "3em"},
|
|
215
|
-
),
|
|
216
|
-
dcc.Store(id=DECLARATION_PERIODS_CREATE_CLICK_ID, data=0),
|
|
217
|
-
# The 2 following Stores are used to control if the status must be displayed or not.
|
|
218
|
-
# If DECLARATION_PERIODS_STATUS_VISIBLE_ID > DECLARATION_PERIODS_STATUS_HIDDEN_ID,
|
|
219
|
-
# it must be displayed else it must be hidden.
|
|
220
|
-
dcc.Store(id=DECLARATION_PERIODS_STATUS_HIDDEN_ID, data=-0),
|
|
221
|
-
dcc.Store(id=DECLARATION_PERIODS_STATUS_VISIBLE_ID, data=0),
|
|
222
|
-
]
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
def nsip_sync_layout():
|
|
227
|
-
"""
|
|
228
|
-
Define the layout specific to the NSIP project synchronisation
|
|
229
|
-
|
|
230
|
-
:return: html.Div component
|
|
231
|
-
"""
|
|
232
|
-
|
|
233
|
-
return html.Div(
|
|
234
|
-
[
|
|
235
|
-
html.P(),
|
|
236
|
-
dbc.Row(
|
|
237
|
-
[
|
|
238
|
-
dbc.Col(
|
|
239
|
-
dbc.RadioItems(
|
|
240
|
-
id=NSIP_SYNC_ACTIVITY_TYPE_ID,
|
|
241
|
-
options=[
|
|
242
|
-
{
|
|
243
|
-
"label": "Projets",
|
|
244
|
-
"value": NSIP_SYNC_ACTIVITY_TYPE_PROJECT,
|
|
245
|
-
},
|
|
246
|
-
{
|
|
247
|
-
"label": "Autres activités",
|
|
248
|
-
"value": NSIP_SYNC_ACTIVITY_TYPE_OTHER,
|
|
249
|
-
},
|
|
250
|
-
],
|
|
251
|
-
value=NSIP_SYNC_ACTIVITY_TYPE_PROJECT,
|
|
252
|
-
),
|
|
253
|
-
width={"offset": 1, "size": 2},
|
|
254
|
-
),
|
|
255
|
-
dbc.Col(
|
|
256
|
-
dbc.Button(
|
|
257
|
-
"Differences OSITAH/NSIP",
|
|
258
|
-
id=NSIP_SYNC_SHOW_DIFF_ID,
|
|
259
|
-
color="secondary",
|
|
260
|
-
className="me-1",
|
|
261
|
-
),
|
|
262
|
-
width={"offset": 1, "size": 3},
|
|
263
|
-
),
|
|
264
|
-
dbc.Col(
|
|
265
|
-
dbc.Button(
|
|
266
|
-
"Mise à jour OSITAH",
|
|
267
|
-
id=NSIP_SYNC_APPLY_DIFF_ID,
|
|
268
|
-
color="secondary",
|
|
269
|
-
className="me-1",
|
|
270
|
-
disabled=True,
|
|
271
|
-
),
|
|
272
|
-
width={"offset": 1, "size": 2},
|
|
273
|
-
),
|
|
274
|
-
]
|
|
275
|
-
),
|
|
276
|
-
html.P(),
|
|
277
|
-
html.Div(id=NSIP_SYNC_CONTENT_ID),
|
|
278
|
-
]
|
|
279
|
-
)
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
def project_teams_layout():
|
|
283
|
-
"""
|
|
284
|
-
Define the layout specific to the configuration of project teams
|
|
285
|
-
|
|
286
|
-
:return: html.Div component
|
|
287
|
-
"""
|
|
288
|
-
|
|
289
|
-
activities = get_all_hito_activities(True)
|
|
290
|
-
masterproject_items = []
|
|
291
|
-
for masterproject in sorted(activities.masterproject.unique(), key=lambda x: x.upper()):
|
|
292
|
-
if masterproject != MASTERPROJECT_DELETED_ACTIVITY:
|
|
293
|
-
masterproject_items.append({"label": masterproject, "value": masterproject})
|
|
294
|
-
|
|
295
|
-
return html.Div(
|
|
296
|
-
[
|
|
297
|
-
html.P(),
|
|
298
|
-
dbc.Alert(id=ACTIVITY_TEAMS_STATUS_ID, is_open=False),
|
|
299
|
-
dbc.Row(
|
|
300
|
-
[
|
|
301
|
-
dbc.Col(
|
|
302
|
-
[
|
|
303
|
-
dbc.Label(html.B("Masterprojet")),
|
|
304
|
-
dbc.Select(
|
|
305
|
-
id=ACTIVITY_TEAMS_MASTERPROJECTS_ID,
|
|
306
|
-
options=masterproject_items,
|
|
307
|
-
html_size=ACTIVITY_TEAMS_LIST_MAX_SIZE,
|
|
308
|
-
),
|
|
309
|
-
],
|
|
310
|
-
width={"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH, "offset": 0},
|
|
311
|
-
xxl={"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH_XXL, "offset": 0},
|
|
312
|
-
),
|
|
313
|
-
dbc.Col(
|
|
314
|
-
[
|
|
315
|
-
dbc.Label(html.B("Projet")),
|
|
316
|
-
dbc.Select(
|
|
317
|
-
id=ACTIVITY_TEAMS_PROJECTS_ID,
|
|
318
|
-
html_size=ACTIVITY_TEAMS_LIST_MAX_SIZE,
|
|
319
|
-
),
|
|
320
|
-
],
|
|
321
|
-
width={
|
|
322
|
-
"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH,
|
|
323
|
-
"offset": ACTIVITY_TEAMS_LIST_BOX_INTERVAL,
|
|
324
|
-
},
|
|
325
|
-
xxl={
|
|
326
|
-
"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH_XXL,
|
|
327
|
-
"offset": ACTIVITY_TEAMS_LIST_BOX_INTERVAL,
|
|
328
|
-
},
|
|
329
|
-
),
|
|
330
|
-
],
|
|
331
|
-
justify="start",
|
|
332
|
-
),
|
|
333
|
-
dbc.Row(
|
|
334
|
-
[
|
|
335
|
-
dbc.Col(
|
|
336
|
-
[
|
|
337
|
-
dbc.Label(html.B("Equipes IJCLab")),
|
|
338
|
-
dbc.Select(
|
|
339
|
-
id=ACTIVITY_TEAMS_LAB_TEAMS_ID,
|
|
340
|
-
html_size=ACTIVITY_TEAMS_LIST_MAX_SIZE,
|
|
341
|
-
),
|
|
342
|
-
],
|
|
343
|
-
width={"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH, "offset": 0},
|
|
344
|
-
xxl={"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH_XXL, "offset": 0},
|
|
345
|
-
),
|
|
346
|
-
dbc.Col(
|
|
347
|
-
html.Div(
|
|
348
|
-
[
|
|
349
|
-
dbc.ButtonGroup(
|
|
350
|
-
[
|
|
351
|
-
dbc.Button(
|
|
352
|
-
html.I(className="bi bi-chevron-double-right"),
|
|
353
|
-
id=ACTIVITY_TEAMS_BUTTON_ADD_ID,
|
|
354
|
-
disabled=True,
|
|
355
|
-
style={"marginTop": "1em"},
|
|
356
|
-
),
|
|
357
|
-
dbc.Button(
|
|
358
|
-
html.I(className="bi bi-chevron-double-left"),
|
|
359
|
-
id=ACTIVITY_TEAMS_BUTTON_REMOVE_ID,
|
|
360
|
-
disabled=True,
|
|
361
|
-
style={"marginTop": "2em"},
|
|
362
|
-
),
|
|
363
|
-
],
|
|
364
|
-
vertical=True,
|
|
365
|
-
),
|
|
366
|
-
],
|
|
367
|
-
style={"display": "flex", "justifyContent": "center"},
|
|
368
|
-
),
|
|
369
|
-
width=ACTIVITY_TEAMS_LIST_BOX_INTERVAL,
|
|
370
|
-
align="center",
|
|
371
|
-
),
|
|
372
|
-
dbc.Col(
|
|
373
|
-
[
|
|
374
|
-
dbc.Label(html.B("Equipes du projet")),
|
|
375
|
-
dbc.Select(
|
|
376
|
-
id=ACTIVITY_TEAMS_SELECTED_TEAMS_ID,
|
|
377
|
-
html_size=ACTIVITY_TEAMS_LIST_MAX_SIZE,
|
|
378
|
-
),
|
|
379
|
-
],
|
|
380
|
-
width={"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH, "offset": 0},
|
|
381
|
-
xxl={"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH_XXL, "offset": 0},
|
|
382
|
-
),
|
|
383
|
-
],
|
|
384
|
-
justify="start",
|
|
385
|
-
style={"marginTop": "5em"},
|
|
386
|
-
),
|
|
387
|
-
dbc.Row(
|
|
388
|
-
[
|
|
389
|
-
dbc.Col(
|
|
390
|
-
dbc.Button(
|
|
391
|
-
"Mettre à jour",
|
|
392
|
-
id=ACTIVITY_TEAMS_BUTTON_UPDATE_ID,
|
|
393
|
-
disabled=True,
|
|
394
|
-
),
|
|
395
|
-
width={"size": 3, "offset": 0},
|
|
396
|
-
),
|
|
397
|
-
dbc.Col(
|
|
398
|
-
dbc.Button(
|
|
399
|
-
"Annuler",
|
|
400
|
-
id=ACTIVITY_TEAMS_BUTTON_CANCEL_ID,
|
|
401
|
-
disabled=True,
|
|
402
|
-
),
|
|
403
|
-
width={"size": 3, "offset": 0},
|
|
404
|
-
),
|
|
405
|
-
],
|
|
406
|
-
justify="evenly",
|
|
407
|
-
style={"marginTop": "3em"},
|
|
408
|
-
),
|
|
409
|
-
dcc.Store(id=ACTIVITY_TEAMS_PROJECT_ACTIVITY_ID, data=True),
|
|
410
|
-
dcc.Store(id=ACTIVITY_TEAMS_ADDED_TEAMS_ID, data=[]),
|
|
411
|
-
dcc.Store(id=ACTIVITY_TEAMS_REMOVED_TEAMS_ID, data=[]),
|
|
412
|
-
dcc.Store(id=ACTIVITY_TEAMS_RESET_INDICATOR_ID, data=0),
|
|
413
|
-
],
|
|
414
|
-
)
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
def project_mgt_layout():
|
|
418
|
-
"""
|
|
419
|
-
Build the layout for the project management tab.
|
|
420
|
-
|
|
421
|
-
:return: html.Div component
|
|
422
|
-
"""
|
|
423
|
-
|
|
424
|
-
masterproject_list = []
|
|
425
|
-
project_list = []
|
|
426
|
-
return html.Div(
|
|
427
|
-
[
|
|
428
|
-
html.P(),
|
|
429
|
-
dbc.Alert(id=PROJECT_MGT_STATUS_ID, is_open=False),
|
|
430
|
-
dbc.Row(
|
|
431
|
-
[
|
|
432
|
-
dbc.RadioItems(
|
|
433
|
-
id=PROJECT_MGT_PROJECT_TYPE_ID,
|
|
434
|
-
options=[
|
|
435
|
-
{
|
|
436
|
-
"label": "Projets NSIP",
|
|
437
|
-
"value": PROJECT_MGT_PROJECT_TYPE_NSIP,
|
|
438
|
-
},
|
|
439
|
-
{
|
|
440
|
-
"label": "Projets locaux",
|
|
441
|
-
"value": PROJECT_MGT_PROJECT_TYPE_LOCAL,
|
|
442
|
-
},
|
|
443
|
-
{
|
|
444
|
-
"label": "Projets désactivés",
|
|
445
|
-
"value": PROJECT_MGT_PROJECT_TYPE_DISABLED,
|
|
446
|
-
},
|
|
447
|
-
],
|
|
448
|
-
inline=True,
|
|
449
|
-
),
|
|
450
|
-
],
|
|
451
|
-
justify="center",
|
|
452
|
-
style={"marginTop": "1em"},
|
|
453
|
-
),
|
|
454
|
-
dbc.Row(
|
|
455
|
-
[
|
|
456
|
-
dbc.Col(
|
|
457
|
-
[
|
|
458
|
-
dbc.Label(html.B("Masterprojets")),
|
|
459
|
-
dbc.Select(
|
|
460
|
-
id=PROJECT_MGT_MASTERPROJECT_LIST_ID,
|
|
461
|
-
options=masterproject_list,
|
|
462
|
-
html_size=PROJECT_MGT_LIST_MAX_SIZE,
|
|
463
|
-
),
|
|
464
|
-
],
|
|
465
|
-
width={"size": PROJECT_MGT_LIST_BOX_WIDTH, "offset": 0},
|
|
466
|
-
xxl={"size": PROJECT_MGT_LIST_BOX_WIDTH_XXL, "offset": 0},
|
|
467
|
-
),
|
|
468
|
-
dbc.Col(
|
|
469
|
-
[
|
|
470
|
-
dbc.Label(html.B("Projets")),
|
|
471
|
-
dbc.Select(
|
|
472
|
-
id=PROJECT_MGT_PROJECT_LIST_ID,
|
|
473
|
-
options=project_list,
|
|
474
|
-
html_size=PROJECT_MGT_LIST_MAX_SIZE,
|
|
475
|
-
),
|
|
476
|
-
],
|
|
477
|
-
width={"size": PROJECT_MGT_LIST_BOX_WIDTH, "offset": 0},
|
|
478
|
-
xxl={"size": PROJECT_MGT_LIST_BOX_WIDTH_XXL, "offset": 0},
|
|
479
|
-
),
|
|
480
|
-
],
|
|
481
|
-
style={"marginTop": "1em"},
|
|
482
|
-
),
|
|
483
|
-
dbc.Row(
|
|
484
|
-
dbc.Col(
|
|
485
|
-
dbc.Button(
|
|
486
|
-
"",
|
|
487
|
-
id=PROJECT_MGT_ACTION_BUTTON_ID,
|
|
488
|
-
disabled=True,
|
|
489
|
-
style={"visibility": "hidden"},
|
|
490
|
-
),
|
|
491
|
-
),
|
|
492
|
-
style={"marginTop": "3em"},
|
|
493
|
-
),
|
|
494
|
-
dcc.Store(id=PROJECT_MGT_PROJECT_ACTIVITY_ID, data=True),
|
|
495
|
-
],
|
|
496
|
-
)
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
def configuration_submenus():
|
|
500
|
-
"""
|
|
501
|
-
Build the tabs menus of the configuration subapplication
|
|
502
|
-
|
|
503
|
-
:return: DBC Tabs
|
|
504
|
-
"""
|
|
505
|
-
|
|
506
|
-
global_params = GlobalParams()
|
|
507
|
-
if AUTHORIZED_ROLES.index(global_params.session_data.role) > AUTHORIZED_ROLES.index(
|
|
508
|
-
HITO_ROLE_PROJECT_MGR
|
|
509
|
-
):
|
|
510
|
-
nsip_sync_disabled = True
|
|
511
|
-
declaration_period_disabled = True
|
|
512
|
-
project_mgt_disabled = True
|
|
513
|
-
else:
|
|
514
|
-
nsip_sync_disabled = False
|
|
515
|
-
declaration_period_disabled = False
|
|
516
|
-
project_mgt_disabled = False
|
|
517
|
-
|
|
518
|
-
return dbc.Tabs(
|
|
519
|
-
[
|
|
520
|
-
dbc.Tab(
|
|
521
|
-
id=TAB_ID_ACTIVITY_TEAMS,
|
|
522
|
-
tab_id=TAB_ID_ACTIVITY_TEAMS,
|
|
523
|
-
label="Equipes des projets",
|
|
524
|
-
),
|
|
525
|
-
dbc.Tab(
|
|
526
|
-
id=TAB_ID_NSIP_PROJECT_SYNC,
|
|
527
|
-
tab_id=TAB_ID_NSIP_PROJECT_SYNC,
|
|
528
|
-
label="Synchronisation NSIP",
|
|
529
|
-
disabled=nsip_sync_disabled,
|
|
530
|
-
),
|
|
531
|
-
dbc.Tab(
|
|
532
|
-
id=TAB_ID_DECLARATION_PERIODS,
|
|
533
|
-
tab_id=TAB_ID_DECLARATION_PERIODS,
|
|
534
|
-
label="Périodes de déclaration",
|
|
535
|
-
disabled=declaration_period_disabled,
|
|
536
|
-
),
|
|
537
|
-
dbc.Tab(
|
|
538
|
-
id=TAB_ID_PROJECT_MGT,
|
|
539
|
-
tab_id=TAB_ID_PROJECT_MGT,
|
|
540
|
-
label="Projets",
|
|
541
|
-
disabled=project_mgt_disabled,
|
|
542
|
-
),
|
|
543
|
-
],
|
|
544
|
-
id=CONFIGURATION_TAB_MENU_ID,
|
|
545
|
-
persistence=True,
|
|
546
|
-
)
|
|
1
|
+
"""
|
|
2
|
+
OSITAH subapplication to manage the configuration
|
|
3
|
+
|
|
4
|
+
This file contains only the layout definitions
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from datetime import date
|
|
8
|
+
|
|
9
|
+
from dash import dcc
|
|
10
|
+
|
|
11
|
+
from ositah.apps.configuration.callbacks import *
|
|
12
|
+
from ositah.utils.menus import TABLE_TYPE_DUMMY_STORE
|
|
13
|
+
from ositah.utils.projects import MASTERPROJECT_DELETED_ACTIVITY
|
|
14
|
+
from ositah.utils.utils import AUTHORIZED_ROLES, HITO_ROLE_PROJECT_MGR
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def configuration_layout():
|
|
18
|
+
"""
|
|
19
|
+
Build the layout for this application, after reading the data if necessary.
|
|
20
|
+
|
|
21
|
+
:return: application layout
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
return html.Div(
|
|
25
|
+
[
|
|
26
|
+
html.H1("Configuration OSITAH"),
|
|
27
|
+
html.Div(
|
|
28
|
+
configuration_submenus(),
|
|
29
|
+
id="configuration-submenus",
|
|
30
|
+
style={"marginTop": "3em"},
|
|
31
|
+
),
|
|
32
|
+
# The following dcc.Store coupled with tables must be created in the layout for
|
|
33
|
+
# the callback to work
|
|
34
|
+
dcc.Store(
|
|
35
|
+
id={"type": TABLE_TYPE_DUMMY_STORE, "id": TABLE_NSIP_PROJECT_SYNC_ID},
|
|
36
|
+
data=0,
|
|
37
|
+
),
|
|
38
|
+
]
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def declaration_periods_layout():
|
|
43
|
+
"""
|
|
44
|
+
Define the layout specific to the management of declaration periods
|
|
45
|
+
|
|
46
|
+
:return: html.Div component
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
declaration_periods = get_declaration_periods(descending=False)
|
|
50
|
+
declaration_period_items = []
|
|
51
|
+
i = 0
|
|
52
|
+
for period in declaration_periods:
|
|
53
|
+
declaration_period_items.append({"label": period.name, "value": i})
|
|
54
|
+
i += 1
|
|
55
|
+
|
|
56
|
+
# Disable creation of a new (next) period if the period matching the current already exists
|
|
57
|
+
today = date.today().isoformat()
|
|
58
|
+
if (
|
|
59
|
+
len(declaration_periods) > 0
|
|
60
|
+
and today >= declaration_periods[-1].start_date
|
|
61
|
+
and today <= declaration_periods[-1].end_date
|
|
62
|
+
):
|
|
63
|
+
current_period_exists = True
|
|
64
|
+
else:
|
|
65
|
+
current_period_exists = False
|
|
66
|
+
|
|
67
|
+
period_params = [
|
|
68
|
+
dbc.Row(
|
|
69
|
+
[
|
|
70
|
+
dbc.Label(
|
|
71
|
+
"Date de début",
|
|
72
|
+
html_for=DECLARATION_PERIOD_START_DATE_ID,
|
|
73
|
+
style={"fontWeight": "bold"},
|
|
74
|
+
width="5",
|
|
75
|
+
),
|
|
76
|
+
dbc.Col(
|
|
77
|
+
dcc.DatePickerSingle(
|
|
78
|
+
id=DECLARATION_PERIOD_START_DATE_ID,
|
|
79
|
+
month_format="MMMM Y",
|
|
80
|
+
placeholder="MMMM Y",
|
|
81
|
+
),
|
|
82
|
+
width="auto",
|
|
83
|
+
class_name="me-3",
|
|
84
|
+
),
|
|
85
|
+
],
|
|
86
|
+
style={"marginBottom": "10px"},
|
|
87
|
+
),
|
|
88
|
+
dbc.Row(
|
|
89
|
+
[
|
|
90
|
+
dbc.Label(
|
|
91
|
+
"Date de validation",
|
|
92
|
+
html_for=DECLARATION_PERIOD_VALIDATION_DATE_ID,
|
|
93
|
+
style={"fontWeight": "bold"},
|
|
94
|
+
width="5",
|
|
95
|
+
),
|
|
96
|
+
dbc.Col(
|
|
97
|
+
dcc.DatePickerSingle(
|
|
98
|
+
id=DECLARATION_PERIOD_VALIDATION_DATE_ID,
|
|
99
|
+
month_format="MMMM Y",
|
|
100
|
+
placeholder="MMMM Y",
|
|
101
|
+
),
|
|
102
|
+
width="auto",
|
|
103
|
+
class_name="me-3",
|
|
104
|
+
),
|
|
105
|
+
],
|
|
106
|
+
style={"marginBottom": "10px"},
|
|
107
|
+
),
|
|
108
|
+
dbc.Row(
|
|
109
|
+
[
|
|
110
|
+
dbc.Label(
|
|
111
|
+
"Date de fin",
|
|
112
|
+
html_for=DECLARATION_PERIOD_END_DATE_ID,
|
|
113
|
+
style={"fontWeight": "bold"},
|
|
114
|
+
width="5",
|
|
115
|
+
),
|
|
116
|
+
dbc.Col(
|
|
117
|
+
dcc.DatePickerSingle(
|
|
118
|
+
id=DECLARATION_PERIOD_END_DATE_ID,
|
|
119
|
+
month_format="MMMM Y",
|
|
120
|
+
placeholder="MMMM Y",
|
|
121
|
+
),
|
|
122
|
+
width="auto",
|
|
123
|
+
class_name="me-3",
|
|
124
|
+
),
|
|
125
|
+
],
|
|
126
|
+
style={"marginBottom": "10px"},
|
|
127
|
+
),
|
|
128
|
+
dbc.Row(
|
|
129
|
+
[
|
|
130
|
+
dbc.Label(
|
|
131
|
+
"Nom",
|
|
132
|
+
html_for=DECLARATION_PERIOD_NAME_ID,
|
|
133
|
+
style={"fontWeight": "bold"},
|
|
134
|
+
width="5",
|
|
135
|
+
),
|
|
136
|
+
dbc.Col(
|
|
137
|
+
dbc.Input(
|
|
138
|
+
type="start_date",
|
|
139
|
+
id=DECLARATION_PERIOD_NAME_ID,
|
|
140
|
+
placeholder="Nom de la période",
|
|
141
|
+
),
|
|
142
|
+
width="6",
|
|
143
|
+
class_name="me-3",
|
|
144
|
+
),
|
|
145
|
+
],
|
|
146
|
+
),
|
|
147
|
+
]
|
|
148
|
+
|
|
149
|
+
return html.Div(
|
|
150
|
+
[
|
|
151
|
+
html.P(),
|
|
152
|
+
dbc.Alert(id=DECLARATION_PERIODS_STATUS_ID, is_open=False),
|
|
153
|
+
dbc.Row(
|
|
154
|
+
[
|
|
155
|
+
dbc.Col(
|
|
156
|
+
[
|
|
157
|
+
dbc.Label(html.B("Périodes")),
|
|
158
|
+
dbc.Select(
|
|
159
|
+
id=DECLARATION_PERIODS_ID,
|
|
160
|
+
options=declaration_period_items,
|
|
161
|
+
html_size=DECLARATION_PERIODS_LIST_MAX_SIZE,
|
|
162
|
+
),
|
|
163
|
+
],
|
|
164
|
+
width={"offset": 1, "size": 3},
|
|
165
|
+
),
|
|
166
|
+
dbc.Col(
|
|
167
|
+
dbc.Form(period_params),
|
|
168
|
+
id=DECLARATION_PERIOD_PARAMS_ID,
|
|
169
|
+
style={
|
|
170
|
+
"border": "1px solid",
|
|
171
|
+
"borderRadius": "4px",
|
|
172
|
+
"borderSizing": "border-box",
|
|
173
|
+
"padding": "10px 10px",
|
|
174
|
+
"visibility": "hidden",
|
|
175
|
+
},
|
|
176
|
+
width={"offset": 1, "size": 4},
|
|
177
|
+
),
|
|
178
|
+
],
|
|
179
|
+
align="center",
|
|
180
|
+
justify="start",
|
|
181
|
+
),
|
|
182
|
+
dbc.Row(
|
|
183
|
+
[
|
|
184
|
+
dbc.Col(
|
|
185
|
+
html.Div(
|
|
186
|
+
dbc.Button(
|
|
187
|
+
"Nouveau semestre",
|
|
188
|
+
id=DECLARATION_PERIODS_CREATE_NEW_ID,
|
|
189
|
+
disabled=current_period_exists,
|
|
190
|
+
),
|
|
191
|
+
id=DECLARATION_PERIODS_CREATE_DIV_ID,
|
|
192
|
+
),
|
|
193
|
+
width={"size": 3, "offset": 0},
|
|
194
|
+
),
|
|
195
|
+
dbc.Col(
|
|
196
|
+
dbc.Button(
|
|
197
|
+
"Valider",
|
|
198
|
+
id=DECLARATION_PERIODS_SAVE_NEW_ID,
|
|
199
|
+
disabled=True,
|
|
200
|
+
),
|
|
201
|
+
width={"size": 3, "offset": 0},
|
|
202
|
+
),
|
|
203
|
+
dbc.Tooltip(
|
|
204
|
+
(
|
|
205
|
+
"Le semestre courant existe déjà"
|
|
206
|
+
if current_period_exists
|
|
207
|
+
else "Ajoute le semestre courant"
|
|
208
|
+
),
|
|
209
|
+
target=DECLARATION_PERIODS_CREATE_DIV_ID,
|
|
210
|
+
placement="bottom",
|
|
211
|
+
),
|
|
212
|
+
],
|
|
213
|
+
justify="evenly",
|
|
214
|
+
style={"marginTop": "3em"},
|
|
215
|
+
),
|
|
216
|
+
dcc.Store(id=DECLARATION_PERIODS_CREATE_CLICK_ID, data=0),
|
|
217
|
+
# The 2 following Stores are used to control if the status must be displayed or not.
|
|
218
|
+
# If DECLARATION_PERIODS_STATUS_VISIBLE_ID > DECLARATION_PERIODS_STATUS_HIDDEN_ID,
|
|
219
|
+
# it must be displayed else it must be hidden.
|
|
220
|
+
dcc.Store(id=DECLARATION_PERIODS_STATUS_HIDDEN_ID, data=-0),
|
|
221
|
+
dcc.Store(id=DECLARATION_PERIODS_STATUS_VISIBLE_ID, data=0),
|
|
222
|
+
]
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def nsip_sync_layout():
|
|
227
|
+
"""
|
|
228
|
+
Define the layout specific to the NSIP project synchronisation
|
|
229
|
+
|
|
230
|
+
:return: html.Div component
|
|
231
|
+
"""
|
|
232
|
+
|
|
233
|
+
return html.Div(
|
|
234
|
+
[
|
|
235
|
+
html.P(),
|
|
236
|
+
dbc.Row(
|
|
237
|
+
[
|
|
238
|
+
dbc.Col(
|
|
239
|
+
dbc.RadioItems(
|
|
240
|
+
id=NSIP_SYNC_ACTIVITY_TYPE_ID,
|
|
241
|
+
options=[
|
|
242
|
+
{
|
|
243
|
+
"label": "Projets",
|
|
244
|
+
"value": NSIP_SYNC_ACTIVITY_TYPE_PROJECT,
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"label": "Autres activités",
|
|
248
|
+
"value": NSIP_SYNC_ACTIVITY_TYPE_OTHER,
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
value=NSIP_SYNC_ACTIVITY_TYPE_PROJECT,
|
|
252
|
+
),
|
|
253
|
+
width={"offset": 1, "size": 2},
|
|
254
|
+
),
|
|
255
|
+
dbc.Col(
|
|
256
|
+
dbc.Button(
|
|
257
|
+
"Differences OSITAH/NSIP",
|
|
258
|
+
id=NSIP_SYNC_SHOW_DIFF_ID,
|
|
259
|
+
color="secondary",
|
|
260
|
+
className="me-1",
|
|
261
|
+
),
|
|
262
|
+
width={"offset": 1, "size": 3},
|
|
263
|
+
),
|
|
264
|
+
dbc.Col(
|
|
265
|
+
dbc.Button(
|
|
266
|
+
"Mise à jour OSITAH",
|
|
267
|
+
id=NSIP_SYNC_APPLY_DIFF_ID,
|
|
268
|
+
color="secondary",
|
|
269
|
+
className="me-1",
|
|
270
|
+
disabled=True,
|
|
271
|
+
),
|
|
272
|
+
width={"offset": 1, "size": 2},
|
|
273
|
+
),
|
|
274
|
+
]
|
|
275
|
+
),
|
|
276
|
+
html.P(),
|
|
277
|
+
html.Div(id=NSIP_SYNC_CONTENT_ID),
|
|
278
|
+
]
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def project_teams_layout():
|
|
283
|
+
"""
|
|
284
|
+
Define the layout specific to the configuration of project teams
|
|
285
|
+
|
|
286
|
+
:return: html.Div component
|
|
287
|
+
"""
|
|
288
|
+
|
|
289
|
+
activities = get_all_hito_activities(True)
|
|
290
|
+
masterproject_items = []
|
|
291
|
+
for masterproject in sorted(activities.masterproject.unique(), key=lambda x: x.upper()):
|
|
292
|
+
if masterproject != MASTERPROJECT_DELETED_ACTIVITY:
|
|
293
|
+
masterproject_items.append({"label": masterproject, "value": masterproject})
|
|
294
|
+
|
|
295
|
+
return html.Div(
|
|
296
|
+
[
|
|
297
|
+
html.P(),
|
|
298
|
+
dbc.Alert(id=ACTIVITY_TEAMS_STATUS_ID, is_open=False),
|
|
299
|
+
dbc.Row(
|
|
300
|
+
[
|
|
301
|
+
dbc.Col(
|
|
302
|
+
[
|
|
303
|
+
dbc.Label(html.B("Masterprojet")),
|
|
304
|
+
dbc.Select(
|
|
305
|
+
id=ACTIVITY_TEAMS_MASTERPROJECTS_ID,
|
|
306
|
+
options=masterproject_items,
|
|
307
|
+
html_size=ACTIVITY_TEAMS_LIST_MAX_SIZE,
|
|
308
|
+
),
|
|
309
|
+
],
|
|
310
|
+
width={"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH, "offset": 0},
|
|
311
|
+
xxl={"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH_XXL, "offset": 0},
|
|
312
|
+
),
|
|
313
|
+
dbc.Col(
|
|
314
|
+
[
|
|
315
|
+
dbc.Label(html.B("Projet")),
|
|
316
|
+
dbc.Select(
|
|
317
|
+
id=ACTIVITY_TEAMS_PROJECTS_ID,
|
|
318
|
+
html_size=ACTIVITY_TEAMS_LIST_MAX_SIZE,
|
|
319
|
+
),
|
|
320
|
+
],
|
|
321
|
+
width={
|
|
322
|
+
"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH,
|
|
323
|
+
"offset": ACTIVITY_TEAMS_LIST_BOX_INTERVAL,
|
|
324
|
+
},
|
|
325
|
+
xxl={
|
|
326
|
+
"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH_XXL,
|
|
327
|
+
"offset": ACTIVITY_TEAMS_LIST_BOX_INTERVAL,
|
|
328
|
+
},
|
|
329
|
+
),
|
|
330
|
+
],
|
|
331
|
+
justify="start",
|
|
332
|
+
),
|
|
333
|
+
dbc.Row(
|
|
334
|
+
[
|
|
335
|
+
dbc.Col(
|
|
336
|
+
[
|
|
337
|
+
dbc.Label(html.B("Equipes IJCLab")),
|
|
338
|
+
dbc.Select(
|
|
339
|
+
id=ACTIVITY_TEAMS_LAB_TEAMS_ID,
|
|
340
|
+
html_size=ACTIVITY_TEAMS_LIST_MAX_SIZE,
|
|
341
|
+
),
|
|
342
|
+
],
|
|
343
|
+
width={"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH, "offset": 0},
|
|
344
|
+
xxl={"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH_XXL, "offset": 0},
|
|
345
|
+
),
|
|
346
|
+
dbc.Col(
|
|
347
|
+
html.Div(
|
|
348
|
+
[
|
|
349
|
+
dbc.ButtonGroup(
|
|
350
|
+
[
|
|
351
|
+
dbc.Button(
|
|
352
|
+
html.I(className="bi bi-chevron-double-right"),
|
|
353
|
+
id=ACTIVITY_TEAMS_BUTTON_ADD_ID,
|
|
354
|
+
disabled=True,
|
|
355
|
+
style={"marginTop": "1em"},
|
|
356
|
+
),
|
|
357
|
+
dbc.Button(
|
|
358
|
+
html.I(className="bi bi-chevron-double-left"),
|
|
359
|
+
id=ACTIVITY_TEAMS_BUTTON_REMOVE_ID,
|
|
360
|
+
disabled=True,
|
|
361
|
+
style={"marginTop": "2em"},
|
|
362
|
+
),
|
|
363
|
+
],
|
|
364
|
+
vertical=True,
|
|
365
|
+
),
|
|
366
|
+
],
|
|
367
|
+
style={"display": "flex", "justifyContent": "center"},
|
|
368
|
+
),
|
|
369
|
+
width=ACTIVITY_TEAMS_LIST_BOX_INTERVAL,
|
|
370
|
+
align="center",
|
|
371
|
+
),
|
|
372
|
+
dbc.Col(
|
|
373
|
+
[
|
|
374
|
+
dbc.Label(html.B("Equipes du projet")),
|
|
375
|
+
dbc.Select(
|
|
376
|
+
id=ACTIVITY_TEAMS_SELECTED_TEAMS_ID,
|
|
377
|
+
html_size=ACTIVITY_TEAMS_LIST_MAX_SIZE,
|
|
378
|
+
),
|
|
379
|
+
],
|
|
380
|
+
width={"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH, "offset": 0},
|
|
381
|
+
xxl={"size": ACTIVITY_TEAMS_LIST_BOX_WIDTH_XXL, "offset": 0},
|
|
382
|
+
),
|
|
383
|
+
],
|
|
384
|
+
justify="start",
|
|
385
|
+
style={"marginTop": "5em"},
|
|
386
|
+
),
|
|
387
|
+
dbc.Row(
|
|
388
|
+
[
|
|
389
|
+
dbc.Col(
|
|
390
|
+
dbc.Button(
|
|
391
|
+
"Mettre à jour",
|
|
392
|
+
id=ACTIVITY_TEAMS_BUTTON_UPDATE_ID,
|
|
393
|
+
disabled=True,
|
|
394
|
+
),
|
|
395
|
+
width={"size": 3, "offset": 0},
|
|
396
|
+
),
|
|
397
|
+
dbc.Col(
|
|
398
|
+
dbc.Button(
|
|
399
|
+
"Annuler",
|
|
400
|
+
id=ACTIVITY_TEAMS_BUTTON_CANCEL_ID,
|
|
401
|
+
disabled=True,
|
|
402
|
+
),
|
|
403
|
+
width={"size": 3, "offset": 0},
|
|
404
|
+
),
|
|
405
|
+
],
|
|
406
|
+
justify="evenly",
|
|
407
|
+
style={"marginTop": "3em"},
|
|
408
|
+
),
|
|
409
|
+
dcc.Store(id=ACTIVITY_TEAMS_PROJECT_ACTIVITY_ID, data=True),
|
|
410
|
+
dcc.Store(id=ACTIVITY_TEAMS_ADDED_TEAMS_ID, data=[]),
|
|
411
|
+
dcc.Store(id=ACTIVITY_TEAMS_REMOVED_TEAMS_ID, data=[]),
|
|
412
|
+
dcc.Store(id=ACTIVITY_TEAMS_RESET_INDICATOR_ID, data=0),
|
|
413
|
+
],
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def project_mgt_layout():
|
|
418
|
+
"""
|
|
419
|
+
Build the layout for the project management tab.
|
|
420
|
+
|
|
421
|
+
:return: html.Div component
|
|
422
|
+
"""
|
|
423
|
+
|
|
424
|
+
masterproject_list = []
|
|
425
|
+
project_list = []
|
|
426
|
+
return html.Div(
|
|
427
|
+
[
|
|
428
|
+
html.P(),
|
|
429
|
+
dbc.Alert(id=PROJECT_MGT_STATUS_ID, is_open=False),
|
|
430
|
+
dbc.Row(
|
|
431
|
+
[
|
|
432
|
+
dbc.RadioItems(
|
|
433
|
+
id=PROJECT_MGT_PROJECT_TYPE_ID,
|
|
434
|
+
options=[
|
|
435
|
+
{
|
|
436
|
+
"label": "Projets NSIP",
|
|
437
|
+
"value": PROJECT_MGT_PROJECT_TYPE_NSIP,
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
"label": "Projets locaux",
|
|
441
|
+
"value": PROJECT_MGT_PROJECT_TYPE_LOCAL,
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
"label": "Projets désactivés",
|
|
445
|
+
"value": PROJECT_MGT_PROJECT_TYPE_DISABLED,
|
|
446
|
+
},
|
|
447
|
+
],
|
|
448
|
+
inline=True,
|
|
449
|
+
),
|
|
450
|
+
],
|
|
451
|
+
justify="center",
|
|
452
|
+
style={"marginTop": "1em"},
|
|
453
|
+
),
|
|
454
|
+
dbc.Row(
|
|
455
|
+
[
|
|
456
|
+
dbc.Col(
|
|
457
|
+
[
|
|
458
|
+
dbc.Label(html.B("Masterprojets")),
|
|
459
|
+
dbc.Select(
|
|
460
|
+
id=PROJECT_MGT_MASTERPROJECT_LIST_ID,
|
|
461
|
+
options=masterproject_list,
|
|
462
|
+
html_size=PROJECT_MGT_LIST_MAX_SIZE,
|
|
463
|
+
),
|
|
464
|
+
],
|
|
465
|
+
width={"size": PROJECT_MGT_LIST_BOX_WIDTH, "offset": 0},
|
|
466
|
+
xxl={"size": PROJECT_MGT_LIST_BOX_WIDTH_XXL, "offset": 0},
|
|
467
|
+
),
|
|
468
|
+
dbc.Col(
|
|
469
|
+
[
|
|
470
|
+
dbc.Label(html.B("Projets")),
|
|
471
|
+
dbc.Select(
|
|
472
|
+
id=PROJECT_MGT_PROJECT_LIST_ID,
|
|
473
|
+
options=project_list,
|
|
474
|
+
html_size=PROJECT_MGT_LIST_MAX_SIZE,
|
|
475
|
+
),
|
|
476
|
+
],
|
|
477
|
+
width={"size": PROJECT_MGT_LIST_BOX_WIDTH, "offset": 0},
|
|
478
|
+
xxl={"size": PROJECT_MGT_LIST_BOX_WIDTH_XXL, "offset": 0},
|
|
479
|
+
),
|
|
480
|
+
],
|
|
481
|
+
style={"marginTop": "1em"},
|
|
482
|
+
),
|
|
483
|
+
dbc.Row(
|
|
484
|
+
dbc.Col(
|
|
485
|
+
dbc.Button(
|
|
486
|
+
"",
|
|
487
|
+
id=PROJECT_MGT_ACTION_BUTTON_ID,
|
|
488
|
+
disabled=True,
|
|
489
|
+
style={"visibility": "hidden"},
|
|
490
|
+
),
|
|
491
|
+
),
|
|
492
|
+
style={"marginTop": "3em"},
|
|
493
|
+
),
|
|
494
|
+
dcc.Store(id=PROJECT_MGT_PROJECT_ACTIVITY_ID, data=True),
|
|
495
|
+
],
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
def configuration_submenus():
|
|
500
|
+
"""
|
|
501
|
+
Build the tabs menus of the configuration subapplication
|
|
502
|
+
|
|
503
|
+
:return: DBC Tabs
|
|
504
|
+
"""
|
|
505
|
+
|
|
506
|
+
global_params = GlobalParams()
|
|
507
|
+
if AUTHORIZED_ROLES.index(global_params.session_data.role) > AUTHORIZED_ROLES.index(
|
|
508
|
+
HITO_ROLE_PROJECT_MGR
|
|
509
|
+
):
|
|
510
|
+
nsip_sync_disabled = True
|
|
511
|
+
declaration_period_disabled = True
|
|
512
|
+
project_mgt_disabled = True
|
|
513
|
+
else:
|
|
514
|
+
nsip_sync_disabled = False
|
|
515
|
+
declaration_period_disabled = False
|
|
516
|
+
project_mgt_disabled = False
|
|
517
|
+
|
|
518
|
+
return dbc.Tabs(
|
|
519
|
+
[
|
|
520
|
+
dbc.Tab(
|
|
521
|
+
id=TAB_ID_ACTIVITY_TEAMS,
|
|
522
|
+
tab_id=TAB_ID_ACTIVITY_TEAMS,
|
|
523
|
+
label="Equipes des projets",
|
|
524
|
+
),
|
|
525
|
+
dbc.Tab(
|
|
526
|
+
id=TAB_ID_NSIP_PROJECT_SYNC,
|
|
527
|
+
tab_id=TAB_ID_NSIP_PROJECT_SYNC,
|
|
528
|
+
label="Synchronisation NSIP",
|
|
529
|
+
disabled=nsip_sync_disabled,
|
|
530
|
+
),
|
|
531
|
+
dbc.Tab(
|
|
532
|
+
id=TAB_ID_DECLARATION_PERIODS,
|
|
533
|
+
tab_id=TAB_ID_DECLARATION_PERIODS,
|
|
534
|
+
label="Périodes de déclaration",
|
|
535
|
+
disabled=declaration_period_disabled,
|
|
536
|
+
),
|
|
537
|
+
dbc.Tab(
|
|
538
|
+
id=TAB_ID_PROJECT_MGT,
|
|
539
|
+
tab_id=TAB_ID_PROJECT_MGT,
|
|
540
|
+
label="Projets",
|
|
541
|
+
disabled=project_mgt_disabled,
|
|
542
|
+
),
|
|
543
|
+
],
|
|
544
|
+
id=CONFIGURATION_TAB_MENU_ID,
|
|
545
|
+
persistence=True,
|
|
546
|
+
)
|