ositah 25.6.dev1__py3-none-any.whl → 25.9.dev2__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.

Files changed (42) hide show
  1. ositah/app.py +17 -17
  2. ositah/apps/analysis.py +785 -785
  3. ositah/apps/configuration/callbacks.py +916 -916
  4. ositah/apps/configuration/main.py +546 -546
  5. ositah/apps/configuration/parameters.py +74 -74
  6. ositah/apps/configuration/tools.py +112 -112
  7. ositah/apps/export.py +1209 -1191
  8. ositah/apps/validation/callbacks.py +240 -240
  9. ositah/apps/validation/main.py +89 -89
  10. ositah/apps/validation/parameters.py +25 -25
  11. ositah/apps/validation/tables.py +646 -646
  12. ositah/apps/validation/tools.py +552 -552
  13. ositah/assets/arrow_down_up.svg +3 -3
  14. ositah/assets/ositah.css +53 -53
  15. ositah/assets/sort_ascending.svg +4 -4
  16. ositah/assets/sort_descending.svg +5 -5
  17. ositah/assets/sorttable.js +499 -499
  18. ositah/main.py +449 -449
  19. ositah/ositah.example.cfg +229 -229
  20. ositah/static/style.css +53 -53
  21. ositah/templates/base.html +22 -22
  22. ositah/templates/bootstrap_login.html +38 -38
  23. ositah/templates/login_form.html +26 -26
  24. ositah/utils/agents.py +124 -124
  25. ositah/utils/authentication.py +287 -287
  26. ositah/utils/cache.py +19 -19
  27. ositah/utils/core.py +13 -13
  28. ositah/utils/exceptions.py +64 -64
  29. ositah/utils/hito_db.py +51 -51
  30. ositah/utils/hito_db_model.py +253 -253
  31. ositah/utils/menus.py +339 -339
  32. ositah/utils/period.py +139 -139
  33. ositah/utils/projects.py +1179 -1178
  34. ositah/utils/teams.py +42 -42
  35. ositah/utils/utils.py +474 -474
  36. {ositah-25.6.dev1.dist-info → ositah-25.9.dev2.dist-info}/METADATA +149 -150
  37. ositah-25.9.dev2.dist-info/RECORD +46 -0
  38. {ositah-25.6.dev1.dist-info → ositah-25.9.dev2.dist-info}/licenses/LICENSE +29 -29
  39. ositah-25.6.dev1.dist-info/RECORD +0 -46
  40. {ositah-25.6.dev1.dist-info → ositah-25.9.dev2.dist-info}/WHEEL +0 -0
  41. {ositah-25.6.dev1.dist-info → ositah-25.9.dev2.dist-info}/entry_points.txt +0 -0
  42. {ositah-25.6.dev1.dist-info → ositah-25.9.dev2.dist-info}/top_level.txt +0 -0
@@ -1,74 +1,74 @@
1
- """
2
- Parameters related to Dash components in the Configuration sub-application
3
- """
4
-
5
- CONFIGURATION_TAB_MENU_ID = "configuration-tabs"
6
- TAB_ID_NSIP_PROJECT_SYNC = "nsip-project-sync-tab"
7
- TAB_ID_ACTIVITY_TEAMS = "config-activity-teams-tab"
8
- TAB_ID_DECLARATION_PERIODS = "config-validation-period-tab"
9
- TAB_ID_PROJECT_MGT = "config-project-mgt-tab"
10
-
11
- ACTIVITY_TEAMS_MASTERPROJECTS_ID = "config-activity-teams-masterprojects"
12
- ACTIVITY_TEAMS_PROJECTS_ID = "config-activity-teams-projects"
13
- ACTIVITY_TEAMS_LAB_TEAMS_ID = "config-activity-teams-lab-teams"
14
- ACTIVITY_TEAMS_SELECTED_TEAMS_ID = "config-activity-teams-selected-teams"
15
- ACTIVITY_TEAMS_BUTTON_ADD_ID = "config-activity-teams-add-team"
16
- ACTIVITY_TEAMS_BUTTON_CANCEL_ID = "config-activity-teams-cancel-team"
17
- ACTIVITY_TEAMS_BUTTON_REMOVE_ID = "config-activity-teams-remove-team"
18
- ACTIVITY_TEAMS_BUTTON_UPDATE_ID = "config-activity-teams-update-button"
19
- ACTIVITY_TEAMS_PROJECT_ACTIVITY_ID = "config-activity-teams-is-project"
20
- ACTIVITY_TEAMS_ADDED_TEAMS_ID = "config-activity-teams-added-teams"
21
- ACTIVITY_TEAMS_REMOVED_TEAMS_ID = "config-activity-teams-removed-teams"
22
- ACTIVITY_TEAMS_STATUS_ID = "config-activity-teams-status-msg"
23
- ACTIVITY_TEAMS_RESET_INDICATOR_ID = "config-activity-teams-reset-indicator"
24
- ACTIVITY_TEAMS_LIST_MAX_SIZE = 10
25
- ACTIVITY_TEAMS_LIST_BOX_WIDTH = 5
26
- # Attempt to reduce list box width on very large display (2500+px) but unfortunately
27
- # Bootstrap xxl is 1400+px thus including full HD. Not clear how to tune mediaclass definitions.
28
- ACTIVITY_TEAMS_LIST_BOX_WIDTH_XXL = 5
29
- ACTIVITY_TEAMS_LIST_BOX_INTERVAL = 1
30
-
31
- DECLARATION_PERIOD_END_DATE_ID = "config-declaration-period-end"
32
- DECLARATION_PERIOD_NAME_ID = "config-declaration-period-name"
33
- DECLARATION_PERIOD_PARAMS_ID = "config-declaration-period-params"
34
- DECLARATION_PERIOD_START_DATE_ID = "config-declaration-period-start"
35
- DECLARATION_PERIOD_VALIDATION_DATE_ID = "config-declaration-period-validation"
36
- DECLARATION_PERIODS_ID = "config-declaration-periods"
37
- DECLARATION_PERIODS_CREATE_NEW_ID = "config-declaration-periods-create-new"
38
- DECLARATION_PERIODS_CREATE_DIV_ID = "config-declaration-periods-create-div"
39
- DECLARATION_PERIODS_CREATE_CLICK_ID = "config-declaration-periods-create-click-saved"
40
- DECLARATION_PERIODS_SAVE_NEW_ID = "config-declaration-periods-save-new"
41
- DECLARATION_PERIODS_SAVE_DIV_ID = "config-declaration-periods-save-div"
42
- DECLARATION_PERIODS_STATUS_ID = "config-declaration-periods-status"
43
- DECLARATION_PERIODS_STATUS_HIDDEN_ID = "config-declaration-periods-status-hidden"
44
- DECLARATION_PERIODS_STATUS_VISIBLE_ID = "config-declaration-periods-status-visible"
45
- DECLARATION_PERIODS_VALIDATION_ID = "config-declaration-periods-validation"
46
- DECLARATION_PERIODS_LIST_MAX_SIZE = 10
47
-
48
- NSIP_SYNC_SHOW_DIFF_ID = "nsip-sync-show-diff-button"
49
- NSIP_SYNC_APPLY_DIFF_ID = "nsip-sync-apply-diff-button"
50
- NSIP_SYNC_CONTENT_ID = "nsip-project-sync-content"
51
- NSIP_SYNC_ACTIVITY_TYPE_ID = "nsip-sync-activity-type"
52
- NSIP_SYNC_ACTIVITY_TYPE_PROJECT = 1
53
- NSIP_SYNC_ACTIVITY_TYPE_OTHER = 2
54
-
55
- PROJECT_MGT_MASTERPROJECT_LIST_ID = "project-mgt-masterproject-list"
56
- PROJECT_MGT_PROJECT_LIST_ID = "project-mgt-project-list"
57
- PROJECT_MGT_PROJECT_ACTIVITY_ID = "project-mgt-is-project"
58
- PROJECT_MGT_PROJECT_TYPE_ID = "project-mgt-project-type"
59
- PROJECT_MGT_ACTION_BUTTON_ID = "project-mgt-action-button"
60
- PROJECT_MGT_ACTION_BUTTON_DISABLE = "Désactiver"
61
- PROJECT_MGT_ACTION_BUTTON_ENABLE = "Réactiver"
62
- PROJECT_MGT_STATUS_ID = "project-mgt-status"
63
- PROJECT_MGT_PROJECT_TYPE_NSIP = 0
64
- PROJECT_MGT_PROJECT_TYPE_LOCAL = 1
65
- PROJECT_MGT_PROJECT_TYPE_DISABLED = 2
66
- PROJECT_MGT_LIST_MAX_SIZE = 10
67
- PROJECT_MGT_LIST_BOX_WIDTH = 5
68
- PROJECT_MGT_LIST_BOX_WIDTH_XXL = 5
69
-
70
- TABLE_NSIP_PROJECT_SYNC_ID = "nsip-project-sync"
71
-
72
- PROJECT_CHANGE_ADDED = "Ajouté"
73
- PROJECT_CHANGE_CHANGED = "Modifié"
74
- PROJECT_CHANGE_REMOVED = "Supprimé"
1
+ """
2
+ Parameters related to Dash components in the Configuration sub-application
3
+ """
4
+
5
+ CONFIGURATION_TAB_MENU_ID = "configuration-tabs"
6
+ TAB_ID_NSIP_PROJECT_SYNC = "nsip-project-sync-tab"
7
+ TAB_ID_ACTIVITY_TEAMS = "config-activity-teams-tab"
8
+ TAB_ID_DECLARATION_PERIODS = "config-validation-period-tab"
9
+ TAB_ID_PROJECT_MGT = "config-project-mgt-tab"
10
+
11
+ ACTIVITY_TEAMS_MASTERPROJECTS_ID = "config-activity-teams-masterprojects"
12
+ ACTIVITY_TEAMS_PROJECTS_ID = "config-activity-teams-projects"
13
+ ACTIVITY_TEAMS_LAB_TEAMS_ID = "config-activity-teams-lab-teams"
14
+ ACTIVITY_TEAMS_SELECTED_TEAMS_ID = "config-activity-teams-selected-teams"
15
+ ACTIVITY_TEAMS_BUTTON_ADD_ID = "config-activity-teams-add-team"
16
+ ACTIVITY_TEAMS_BUTTON_CANCEL_ID = "config-activity-teams-cancel-team"
17
+ ACTIVITY_TEAMS_BUTTON_REMOVE_ID = "config-activity-teams-remove-team"
18
+ ACTIVITY_TEAMS_BUTTON_UPDATE_ID = "config-activity-teams-update-button"
19
+ ACTIVITY_TEAMS_PROJECT_ACTIVITY_ID = "config-activity-teams-is-project"
20
+ ACTIVITY_TEAMS_ADDED_TEAMS_ID = "config-activity-teams-added-teams"
21
+ ACTIVITY_TEAMS_REMOVED_TEAMS_ID = "config-activity-teams-removed-teams"
22
+ ACTIVITY_TEAMS_STATUS_ID = "config-activity-teams-status-msg"
23
+ ACTIVITY_TEAMS_RESET_INDICATOR_ID = "config-activity-teams-reset-indicator"
24
+ ACTIVITY_TEAMS_LIST_MAX_SIZE = 10
25
+ ACTIVITY_TEAMS_LIST_BOX_WIDTH = 5
26
+ # Attempt to reduce list box width on very large display (2500+px) but unfortunately
27
+ # Bootstrap xxl is 1400+px thus including full HD. Not clear how to tune mediaclass definitions.
28
+ ACTIVITY_TEAMS_LIST_BOX_WIDTH_XXL = 5
29
+ ACTIVITY_TEAMS_LIST_BOX_INTERVAL = 1
30
+
31
+ DECLARATION_PERIOD_END_DATE_ID = "config-declaration-period-end"
32
+ DECLARATION_PERIOD_NAME_ID = "config-declaration-period-name"
33
+ DECLARATION_PERIOD_PARAMS_ID = "config-declaration-period-params"
34
+ DECLARATION_PERIOD_START_DATE_ID = "config-declaration-period-start"
35
+ DECLARATION_PERIOD_VALIDATION_DATE_ID = "config-declaration-period-validation"
36
+ DECLARATION_PERIODS_ID = "config-declaration-periods"
37
+ DECLARATION_PERIODS_CREATE_NEW_ID = "config-declaration-periods-create-new"
38
+ DECLARATION_PERIODS_CREATE_DIV_ID = "config-declaration-periods-create-div"
39
+ DECLARATION_PERIODS_CREATE_CLICK_ID = "config-declaration-periods-create-click-saved"
40
+ DECLARATION_PERIODS_SAVE_NEW_ID = "config-declaration-periods-save-new"
41
+ DECLARATION_PERIODS_SAVE_DIV_ID = "config-declaration-periods-save-div"
42
+ DECLARATION_PERIODS_STATUS_ID = "config-declaration-periods-status"
43
+ DECLARATION_PERIODS_STATUS_HIDDEN_ID = "config-declaration-periods-status-hidden"
44
+ DECLARATION_PERIODS_STATUS_VISIBLE_ID = "config-declaration-periods-status-visible"
45
+ DECLARATION_PERIODS_VALIDATION_ID = "config-declaration-periods-validation"
46
+ DECLARATION_PERIODS_LIST_MAX_SIZE = 10
47
+
48
+ NSIP_SYNC_SHOW_DIFF_ID = "nsip-sync-show-diff-button"
49
+ NSIP_SYNC_APPLY_DIFF_ID = "nsip-sync-apply-diff-button"
50
+ NSIP_SYNC_CONTENT_ID = "nsip-project-sync-content"
51
+ NSIP_SYNC_ACTIVITY_TYPE_ID = "nsip-sync-activity-type"
52
+ NSIP_SYNC_ACTIVITY_TYPE_PROJECT = 1
53
+ NSIP_SYNC_ACTIVITY_TYPE_OTHER = 2
54
+
55
+ PROJECT_MGT_MASTERPROJECT_LIST_ID = "project-mgt-masterproject-list"
56
+ PROJECT_MGT_PROJECT_LIST_ID = "project-mgt-project-list"
57
+ PROJECT_MGT_PROJECT_ACTIVITY_ID = "project-mgt-is-project"
58
+ PROJECT_MGT_PROJECT_TYPE_ID = "project-mgt-project-type"
59
+ PROJECT_MGT_ACTION_BUTTON_ID = "project-mgt-action-button"
60
+ PROJECT_MGT_ACTION_BUTTON_DISABLE = "Désactiver"
61
+ PROJECT_MGT_ACTION_BUTTON_ENABLE = "Réactiver"
62
+ PROJECT_MGT_STATUS_ID = "project-mgt-status"
63
+ PROJECT_MGT_PROJECT_TYPE_NSIP = 0
64
+ PROJECT_MGT_PROJECT_TYPE_LOCAL = 1
65
+ PROJECT_MGT_PROJECT_TYPE_DISABLED = 2
66
+ PROJECT_MGT_LIST_MAX_SIZE = 10
67
+ PROJECT_MGT_LIST_BOX_WIDTH = 5
68
+ PROJECT_MGT_LIST_BOX_WIDTH_XXL = 5
69
+
70
+ TABLE_NSIP_PROJECT_SYNC_ID = "nsip-project-sync"
71
+
72
+ PROJECT_CHANGE_ADDED = "Ajouté"
73
+ PROJECT_CHANGE_CHANGED = "Modifié"
74
+ PROJECT_CHANGE_REMOVED = "Supprimé"
@@ -1,112 +1,112 @@
1
- """
2
- Various functions used by Configure sub-application
3
- """
4
-
5
- import re
6
-
7
- import pandas as pd
8
-
9
- from ositah.apps.configuration.parameters import (
10
- PROJECT_MGT_PROJECT_TYPE_DISABLED,
11
- PROJECT_MGT_PROJECT_TYPE_LOCAL,
12
- )
13
- from ositah.utils.projects import (
14
- MASTERPROJECT_DELETED_ACTIVITY,
15
- MASTERPROJECT_LOCAL_PROJECT,
16
- get_all_hito_activities,
17
- )
18
-
19
-
20
- def list_box_empty(list_options):
21
- """
22
- Check if the options of the list box contains only one entry corresponding to a
23
- placeholder item.
24
-
25
- :param team_list_items: options of a list box
26
- :return: boolean (true if only a placeholder entry is present)
27
- """
28
-
29
- if (
30
- len(list_options) == 1
31
- and list_options[0]["label"] is None
32
- and list_options[0]["value"] is None
33
- ):
34
- return True
35
- else:
36
- return False
37
-
38
-
39
- def get_masterprojects_items(project_activity, category: int = None) -> list:
40
- """
41
- Build the item list for masterprojects to be displayed in a select compoenent
42
-
43
- :param project_activity: True if it is a project rather than a Hito activity
44
- :param category: one of PROJECT_MGT_PROJECT_TYPE_xxx values or None. If None, menas
45
- all active (non disabled) projects/activities
46
- :return: list of projects/activities
47
- """
48
-
49
- if category == PROJECT_MGT_PROJECT_TYPE_LOCAL:
50
- # Local projects have no masterproject
51
- return []
52
-
53
- activities = get_all_hito_activities(project_activity)
54
- masterproject_items = []
55
- if category == PROJECT_MGT_PROJECT_TYPE_DISABLED:
56
- disabled = pd.DataFrame()
57
- disabled[["masterproject_real", "project_real"]] = activities[
58
- activities.masterproject == MASTERPROJECT_DELETED_ACTIVITY
59
- ]["project"].str.split(" / ", n=1, expand=True)
60
- for masterproject in sorted(
61
- disabled["masterproject_real"].unique(),
62
- key=lambda x: x.upper(),
63
- ):
64
- masterproject_items.append({"label": masterproject, "value": masterproject})
65
- else:
66
- masterproject_items = sorted(
67
- activities[
68
- (activities.masterproject != MASTERPROJECT_DELETED_ACTIVITY)
69
- & (activities.masterproject != MASTERPROJECT_LOCAL_PROJECT)
70
- ]["masterproject"].unique(),
71
- key=lambda x: x.upper(),
72
- )
73
-
74
- return masterproject_items
75
-
76
-
77
- def get_projects_items(masterproject, project_activity, category: int = None) -> list:
78
- """
79
- Build the item list for projects to be displayed in a select compoenent
80
-
81
- :param masterproject: selected master project
82
- :param project_activity: True if it is a project rather than a Hito activity
83
- :param category: one of PROJECT_MGT_PROJECT_TYPE_xxx values or None. If None, menas
84
- all active (non disabled) projects/activities
85
- :return: list of projects/activities
86
- """
87
-
88
- if category == PROJECT_MGT_PROJECT_TYPE_LOCAL:
89
- project_prefix = masterproject
90
- masterproject = MASTERPROJECT_LOCAL_PROJECT
91
- elif category == PROJECT_MGT_PROJECT_TYPE_DISABLED:
92
- project_prefix = masterproject
93
- masterproject = MASTERPROJECT_DELETED_ACTIVITY
94
- else:
95
- project_prefix = None
96
-
97
- if masterproject:
98
- activities = get_all_hito_activities(project_activity)
99
- project_items = []
100
- for project in sorted(
101
- activities[activities.masterproject == masterproject]["project"].unique(),
102
- key=lambda x: x.upper(),
103
- ):
104
- if project_prefix is None or re.match(rf"{project_prefix}", project):
105
- if category == PROJECT_MGT_PROJECT_TYPE_DISABLED:
106
- project_name = project.split("/")[1]
107
- else:
108
- project_name = project
109
- project_items.append({"label": project_name, "value": project})
110
- return project_items
111
- else:
112
- return []
1
+ """
2
+ Various functions used by Configure sub-application
3
+ """
4
+
5
+ import re
6
+
7
+ import pandas as pd
8
+
9
+ from ositah.apps.configuration.parameters import (
10
+ PROJECT_MGT_PROJECT_TYPE_DISABLED,
11
+ PROJECT_MGT_PROJECT_TYPE_LOCAL,
12
+ )
13
+ from ositah.utils.projects import (
14
+ MASTERPROJECT_DELETED_ACTIVITY,
15
+ MASTERPROJECT_LOCAL_PROJECT,
16
+ get_all_hito_activities,
17
+ )
18
+
19
+
20
+ def list_box_empty(list_options):
21
+ """
22
+ Check if the options of the list box contains only one entry corresponding to a
23
+ placeholder item.
24
+
25
+ :param team_list_items: options of a list box
26
+ :return: boolean (true if only a placeholder entry is present)
27
+ """
28
+
29
+ if (
30
+ len(list_options) == 1
31
+ and list_options[0]["label"] is None
32
+ and list_options[0]["value"] is None
33
+ ):
34
+ return True
35
+ else:
36
+ return False
37
+
38
+
39
+ def get_masterprojects_items(project_activity, category: int = None) -> list:
40
+ """
41
+ Build the item list for masterprojects to be displayed in a select compoenent
42
+
43
+ :param project_activity: True if it is a project rather than a Hito activity
44
+ :param category: one of PROJECT_MGT_PROJECT_TYPE_xxx values or None. If None, menas
45
+ all active (non disabled) projects/activities
46
+ :return: list of projects/activities
47
+ """
48
+
49
+ if category == PROJECT_MGT_PROJECT_TYPE_LOCAL:
50
+ # Local projects have no masterproject
51
+ return []
52
+
53
+ activities = get_all_hito_activities(project_activity)
54
+ masterproject_items = []
55
+ if category == PROJECT_MGT_PROJECT_TYPE_DISABLED:
56
+ disabled = pd.DataFrame()
57
+ disabled[["masterproject_real", "project_real"]] = activities[
58
+ activities.masterproject == MASTERPROJECT_DELETED_ACTIVITY
59
+ ]["project"].str.split(" / ", n=1, expand=True)
60
+ for masterproject in sorted(
61
+ disabled["masterproject_real"].unique(),
62
+ key=lambda x: x.upper(),
63
+ ):
64
+ masterproject_items.append({"label": masterproject, "value": masterproject})
65
+ else:
66
+ masterproject_items = sorted(
67
+ activities[
68
+ (activities.masterproject != MASTERPROJECT_DELETED_ACTIVITY)
69
+ & (activities.masterproject != MASTERPROJECT_LOCAL_PROJECT)
70
+ ]["masterproject"].unique(),
71
+ key=lambda x: x.upper(),
72
+ )
73
+
74
+ return masterproject_items
75
+
76
+
77
+ def get_projects_items(masterproject, project_activity, category: int = None) -> list:
78
+ """
79
+ Build the item list for projects to be displayed in a select compoenent
80
+
81
+ :param masterproject: selected master project
82
+ :param project_activity: True if it is a project rather than a Hito activity
83
+ :param category: one of PROJECT_MGT_PROJECT_TYPE_xxx values or None. If None, menas
84
+ all active (non disabled) projects/activities
85
+ :return: list of projects/activities
86
+ """
87
+
88
+ if category == PROJECT_MGT_PROJECT_TYPE_LOCAL:
89
+ project_prefix = masterproject
90
+ masterproject = MASTERPROJECT_LOCAL_PROJECT
91
+ elif category == PROJECT_MGT_PROJECT_TYPE_DISABLED:
92
+ project_prefix = masterproject
93
+ masterproject = MASTERPROJECT_DELETED_ACTIVITY
94
+ else:
95
+ project_prefix = None
96
+
97
+ if masterproject:
98
+ activities = get_all_hito_activities(project_activity)
99
+ project_items = []
100
+ for project in sorted(
101
+ activities[activities.masterproject == masterproject]["project"].unique(),
102
+ key=lambda x: x.upper(),
103
+ ):
104
+ if project_prefix is None or re.match(rf"{project_prefix}", project):
105
+ if category == PROJECT_MGT_PROJECT_TYPE_DISABLED:
106
+ project_name = project.split("/")[1]
107
+ else:
108
+ project_name = project
109
+ project_items.append({"label": project_name, "value": project})
110
+ return project_items
111
+ else:
112
+ return []