invenio-administration 6.0.2__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.
Files changed (199) hide show
  1. invenio_administration/__init__.py +12 -0
  2. invenio_administration/admin.py +124 -0
  3. invenio_administration/assets/semantic-ui/js/invenio_administration/.eslintrc.yml +6 -0
  4. invenio_administration/assets/semantic-ui/js/invenio_administration/.prettierrc +1 -0
  5. invenio_administration/assets/semantic-ui/js/invenio_administration/index.js +6 -0
  6. invenio_administration/assets/semantic-ui/js/invenio_administration/package.json +25 -0
  7. invenio_administration/assets/semantic-ui/js/invenio_administration/src/actions/ActionModal.js +44 -0
  8. invenio_administration/assets/semantic-ui/js/invenio_administration/src/actions/Actions.js +118 -0
  9. invenio_administration/assets/semantic-ui/js/invenio_administration/src/actions/Delete.js +67 -0
  10. invenio_administration/assets/semantic-ui/js/invenio_administration/src/actions/DeleteModal.js +118 -0
  11. invenio_administration/assets/semantic-ui/js/invenio_administration/src/actions/DeleteModalTrigger.js +97 -0
  12. invenio_administration/assets/semantic-ui/js/invenio_administration/src/actions/Edit.js +52 -0
  13. invenio_administration/assets/semantic-ui/js/invenio_administration/src/actions/ResourceActions.js +117 -0
  14. invenio_administration/assets/semantic-ui/js/invenio_administration/src/actions/index.js +12 -0
  15. invenio_administration/assets/semantic-ui/js/invenio_administration/src/api/actions.js +41 -0
  16. invenio_administration/assets/semantic-ui/js/invenio_administration/src/api/index.js +6 -0
  17. invenio_administration/assets/semantic-ui/js/invenio_administration/src/api/routes.js +19 -0
  18. invenio_administration/assets/semantic-ui/js/invenio_administration/src/api/serializers.js +7 -0
  19. invenio_administration/assets/semantic-ui/js/invenio_administration/src/components/BoolFormatter.js +36 -0
  20. invenio_administration/assets/semantic-ui/js/invenio_administration/src/components/DateFormatter.js +29 -0
  21. invenio_administration/assets/semantic-ui/js/invenio_administration/src/components/ErrorPage.js +48 -0
  22. invenio_administration/assets/semantic-ui/js/invenio_administration/src/components/Formatter.js +51 -0
  23. invenio_administration/assets/semantic-ui/js/invenio_administration/src/components/Formatter.test.js +176 -0
  24. invenio_administration/assets/semantic-ui/js/invenio_administration/src/components/Loader.js +37 -0
  25. invenio_administration/assets/semantic-ui/js/invenio_administration/src/components/index.js +10 -0
  26. invenio_administration/assets/semantic-ui/js/invenio_administration/src/components/utils.js +48 -0
  27. invenio_administration/assets/semantic-ui/js/invenio_administration/src/create/CreatePage.js +45 -0
  28. invenio_administration/assets/semantic-ui/js/invenio_administration/src/create/create.js +28 -0
  29. invenio_administration/assets/semantic-ui/js/invenio_administration/src/create/index.js +6 -0
  30. invenio_administration/assets/semantic-ui/js/invenio_administration/src/details/AdminDetailsView.js +166 -0
  31. invenio_administration/assets/semantic-ui/js/invenio_administration/src/details/DetailsComponent.js +54 -0
  32. invenio_administration/assets/semantic-ui/js/invenio_administration/src/details/details.js +52 -0
  33. invenio_administration/assets/semantic-ui/js/invenio_administration/src/details/index.js +7 -0
  34. invenio_administration/assets/semantic-ui/js/invenio_administration/src/edit/EditPage.js +88 -0
  35. invenio_administration/assets/semantic-ui/js/invenio_administration/src/edit/edit.js +30 -0
  36. invenio_administration/assets/semantic-ui/js/invenio_administration/src/edit/index.js +6 -0
  37. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/ActionForm.js +205 -0
  38. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/AdminForm.js +202 -0
  39. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/GenerateForm.js +50 -0
  40. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/LazyForm.js +83 -0
  41. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/fields/array.js +106 -0
  42. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/fields/bool.js +57 -0
  43. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/fields/dropdown.js +29 -0
  44. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/fields/dynamic.js +67 -0
  45. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/fields/fields.js +119 -0
  46. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/fields/hidden.js +30 -0
  47. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/fields/index.js +12 -0
  48. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/fields/object.js +71 -0
  49. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/fields/props_generator.js +70 -0
  50. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/fields/vocabulary.js +29 -0
  51. invenio_administration/assets/semantic-ui/js/invenio_administration/src/formik/index.js +9 -0
  52. invenio_administration/assets/semantic-ui/js/invenio_administration/src/index.js +15 -0
  53. invenio_administration/assets/semantic-ui/js/invenio_administration/src/routes.js +19 -0
  54. invenio_administration/assets/semantic-ui/js/invenio_administration/src/search/SearchBar.js +28 -0
  55. invenio_administration/assets/semantic-ui/js/invenio_administration/src/search/SearchBarElement.js +63 -0
  56. invenio_administration/assets/semantic-ui/js/invenio_administration/src/search/SearchBulkActionContext.js +24 -0
  57. invenio_administration/assets/semantic-ui/js/invenio_administration/src/search/SearchComponents.js +79 -0
  58. invenio_administration/assets/semantic-ui/js/invenio_administration/src/search/SearchEmptyResults.js +64 -0
  59. invenio_administration/assets/semantic-ui/js/invenio_administration/src/search/SearchFacets.js +34 -0
  60. invenio_administration/assets/semantic-ui/js/invenio_administration/src/search/SearchResultItem.js +129 -0
  61. invenio_administration/assets/semantic-ui/js/invenio_administration/src/search/SearchResults.js +73 -0
  62. invenio_administration/assets/semantic-ui/js/invenio_administration/src/search/SearchResultsContainer.js +57 -0
  63. invenio_administration/assets/semantic-ui/js/invenio_administration/src/search/index.js +14 -0
  64. invenio_administration/assets/semantic-ui/js/invenio_administration/src/search/search.js +20 -0
  65. invenio_administration/assets/semantic-ui/js/invenio_administration/src/theme.js +89 -0
  66. invenio_administration/assets/semantic-ui/js/invenio_administration/src/ui_messages/context.js +81 -0
  67. invenio_administration/assets/semantic-ui/js/invenio_administration/src/ui_messages/index.js +7 -0
  68. invenio_administration/assets/semantic-ui/js/invenio_administration/src/ui_messages/messages.js +77 -0
  69. invenio_administration/assets/semantic-ui/translations/invenio_administration/i18next.js +36 -0
  70. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/_generatedTranslations.js +68 -0
  71. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/ar/messages.po +111 -0
  72. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/ar/translations.json +36 -0
  73. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/bg/messages.po +105 -0
  74. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/bg/translations.json +32 -0
  75. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/ca/messages.po +105 -0
  76. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/ca/translations.json +32 -0
  77. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/cs/messages.po +110 -0
  78. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/cs/translations.json +34 -0
  79. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/da/messages.po +105 -0
  80. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/da/translations.json +32 -0
  81. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/de/messages.po +111 -0
  82. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/de/translations.json +32 -0
  83. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/el/messages.po +105 -0
  84. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/el/translations.json +32 -0
  85. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/en/messages.po +99 -0
  86. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/en/translations.json +32 -0
  87. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/es/messages.po +108 -0
  88. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/es/translations.json +32 -0
  89. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/et/messages.po +106 -0
  90. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/et/translations.json +32 -0
  91. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/fa/messages.po +105 -0
  92. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/fa/translations.json +32 -0
  93. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/fi/messages.po +105 -0
  94. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/fi/translations.json +32 -0
  95. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/fr/messages.po +108 -0
  96. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/fr/translations.json +32 -0
  97. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/hr/messages.po +106 -0
  98. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/hr/translations.json +33 -0
  99. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/hu/messages.po +109 -0
  100. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/hu/translations.json +32 -0
  101. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/index.js +23 -0
  102. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/it/messages.po +107 -0
  103. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/it/translations.json +32 -0
  104. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/ja/messages.po +104 -0
  105. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/ja/translations.json +31 -0
  106. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/ka/messages.po +105 -0
  107. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/ka/translations.json +32 -0
  108. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/ko/messages.po +104 -0
  109. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/ko/translations.json +31 -0
  110. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/lt/messages.po +107 -0
  111. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/lt/translations.json +34 -0
  112. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/no/messages.po +105 -0
  113. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/no/translations.json +32 -0
  114. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/pl/messages.po +108 -0
  115. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/pl/translations.json +34 -0
  116. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/pt/messages.po +106 -0
  117. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/pt/translations.json +32 -0
  118. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/ro/messages.po +108 -0
  119. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/ro/translations.json +33 -0
  120. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/ru/messages.po +108 -0
  121. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/ru/translations.json +34 -0
  122. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/sk/messages.po +107 -0
  123. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/sk/translations.json +34 -0
  124. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/sv/messages.po +108 -0
  125. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/sv/translations.json +32 -0
  126. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/tr/messages.po +108 -0
  127. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/tr/translations.json +32 -0
  128. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/uk/messages.po +108 -0
  129. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/uk/translations.json +34 -0
  130. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/zh_CN/messages.po +106 -0
  131. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/zh_CN/translations.json +31 -0
  132. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/zh_TW/messages.po +104 -0
  133. invenio_administration/assets/semantic-ui/translations/invenio_administration/messages/zh_TW/translations.json +31 -0
  134. invenio_administration/assets/semantic-ui/translations/invenio_administration/package.json +19 -0
  135. invenio_administration/assets/semantic-ui/translations/invenio_administration/translations.pot +99 -0
  136. invenio_administration/config.py +26 -0
  137. invenio_administration/decorators.py +6 -0
  138. invenio_administration/errors.py +83 -0
  139. invenio_administration/ext.py +113 -0
  140. invenio_administration/generators.py +20 -0
  141. invenio_administration/marshmallow_utils.py +168 -0
  142. invenio_administration/menu/__init__.py +8 -0
  143. invenio_administration/menu/menu.py +201 -0
  144. invenio_administration/permissions.py +30 -0
  145. invenio_administration/static/images/dashboard.png +0 -0
  146. invenio_administration/templates/semantic-ui/invenio_administration/base.html +79 -0
  147. invenio_administration/templates/semantic-ui/invenio_administration/create.html +32 -0
  148. invenio_administration/templates/semantic-ui/invenio_administration/details.html +40 -0
  149. invenio_administration/templates/semantic-ui/invenio_administration/edit.html +32 -0
  150. invenio_administration/templates/semantic-ui/invenio_administration/header/header.html +79 -0
  151. invenio_administration/templates/semantic-ui/invenio_administration/header/header_login.html +105 -0
  152. invenio_administration/templates/semantic-ui/invenio_administration/header/side_bar_toggle.html +9 -0
  153. invenio_administration/templates/semantic-ui/invenio_administration/index.html +40 -0
  154. invenio_administration/templates/semantic-ui/invenio_administration/macros.html +15 -0
  155. invenio_administration/templates/semantic-ui/invenio_administration/search.html +67 -0
  156. invenio_administration/templates/semantic-ui/invenio_administration/sidebar/sidenav.html +33 -0
  157. invenio_administration/templates/semantic-ui/invenio_theme/header_login.html +17 -0
  158. invenio_administration/translations/ar/LC_MESSAGES/messages.po +169 -0
  159. invenio_administration/translations/bg/LC_MESSAGES/messages.po +164 -0
  160. invenio_administration/translations/ca/LC_MESSAGES/messages.po +165 -0
  161. invenio_administration/translations/cs/LC_MESSAGES/messages.po +169 -0
  162. invenio_administration/translations/da/LC_MESSAGES/messages.po +160 -0
  163. invenio_administration/translations/de/LC_MESSAGES/messages.po +175 -0
  164. invenio_administration/translations/el/LC_MESSAGES/messages.po +164 -0
  165. invenio_administration/translations/es/LC_MESSAGES/messages.po +171 -0
  166. invenio_administration/translations/et/LC_MESSAGES/messages.po +165 -0
  167. invenio_administration/translations/fa/LC_MESSAGES/messages.po +164 -0
  168. invenio_administration/translations/fi/LC_MESSAGES/messages.po +167 -0
  169. invenio_administration/translations/fr/LC_MESSAGES/messages.po +170 -0
  170. invenio_administration/translations/hr/LC_MESSAGES/messages.po +164 -0
  171. invenio_administration/translations/hu/LC_MESSAGES/messages.po +169 -0
  172. invenio_administration/translations/it/LC_MESSAGES/messages.po +165 -0
  173. invenio_administration/translations/ja/LC_MESSAGES/messages.po +164 -0
  174. invenio_administration/translations/ka/LC_MESSAGES/messages.po +164 -0
  175. invenio_administration/translations/ko/LC_MESSAGES/messages.po +164 -0
  176. invenio_administration/translations/lt/LC_MESSAGES/messages.po +164 -0
  177. invenio_administration/translations/messages.pot +159 -0
  178. invenio_administration/translations/no/LC_MESSAGES/messages.po +164 -0
  179. invenio_administration/translations/pl/LC_MESSAGES/messages.po +164 -0
  180. invenio_administration/translations/pt/LC_MESSAGES/messages.po +164 -0
  181. invenio_administration/translations/ro/LC_MESSAGES/messages.po +169 -0
  182. invenio_administration/translations/ru/LC_MESSAGES/messages.po +166 -0
  183. invenio_administration/translations/sk/LC_MESSAGES/messages.po +165 -0
  184. invenio_administration/translations/sv/LC_MESSAGES/messages.po +171 -0
  185. invenio_administration/translations/tr/LC_MESSAGES/messages.po +170 -0
  186. invenio_administration/translations/uk/LC_MESSAGES/messages.po +164 -0
  187. invenio_administration/translations/zh_CN/LC_MESSAGES/messages.po +165 -0
  188. invenio_administration/translations/zh_TW/LC_MESSAGES/messages.po +164 -0
  189. invenio_administration/views/__init__.py +9 -0
  190. invenio_administration/views/base.py +479 -0
  191. invenio_administration/views/blueprint.py +14 -0
  192. invenio_administration/views/dashboard.py +27 -0
  193. invenio_administration/webpack.py +78 -0
  194. invenio_administration-6.0.2.dist-info/METADATA +61 -0
  195. invenio_administration-6.0.2.dist-info/RECORD +199 -0
  196. invenio_administration-6.0.2.dist-info/WHEEL +4 -0
  197. invenio_administration-6.0.2.dist-info/entry_points.txt +21 -0
  198. invenio_administration-6.0.2.dist-info/licenses/AUTHORS.rst +10 -0
  199. invenio_administration-6.0.2.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,12 @@
1
+ # SPDX-FileCopyrightText: 2022-2024 CERN.
2
+ # SPDX-FileCopyrightText: 2024-2026 Graz University of Technology.
3
+ # SPDX-FileCopyrightText: 2024-2025 KTH Royal Institute of Technology.
4
+ # SPDX-License-Identifier: MIT
5
+
6
+ """Invenio module providing extensible administration panel."""
7
+
8
+ from .ext import InvenioAdministration
9
+
10
+ __version__ = "6.0.2"
11
+
12
+ __all__ = ["InvenioAdministration"]
@@ -0,0 +1,124 @@
1
+ # SPDX-FileCopyrightText: 2022-2024 CERN.
2
+ # SPDX-FileCopyrightText: 2023-2024 Graz University of Technology.
3
+ # SPDX-FileCopyrightText: 2024 KTH Royal Institute of Technology.
4
+ # SPDX-License-Identifier: MIT
5
+
6
+ """Invenio Administration core admin module."""
7
+
8
+ from flask import Blueprint
9
+ from flask_menu import current_menu
10
+ from invenio_i18n import lazy_gettext as _
11
+ from werkzeug.utils import import_string
12
+
13
+ from invenio_administration.menu import AdminMenu
14
+
15
+ from .views.base import AdminFormView, AdminResourceDetailView, AdminView
16
+
17
+
18
+ class Administration:
19
+ """Admin views core manager."""
20
+
21
+ def __init__(
22
+ self,
23
+ app=None,
24
+ name=None,
25
+ url=None,
26
+ ui_endpoint=None,
27
+ base_template=None,
28
+ ):
29
+ """Constructor.
30
+
31
+ :param app: flask application
32
+ :param name: application name, defaults to "Admin"
33
+ :param url: base admin url to register the dashboard view and subviews
34
+ :param dashboard_view: home page view
35
+ :param ui_endpoint: base UI endpoint,
36
+ leaves flexibility to implement two different admin apps,
37
+ or to provide custom endpoint
38
+ :param base_template: base admin template.
39
+ Defaults to "admin/base.html"
40
+ """
41
+ super().__init__()
42
+
43
+ self.app = app
44
+ self._views = []
45
+ self._menu = AdminMenu()
46
+ self._menu_key = "admin_navigation"
47
+ self.blueprint = None
48
+
49
+ if name is None:
50
+ name = _("Administration")
51
+ self.name = name
52
+
53
+ self.dashboard_view_class = self.load_admin_dashboard(app)
54
+ self.endpoint = ui_endpoint or "administration"
55
+ self.url = url or "/administration"
56
+ self.base_template = base_template or "invenio_administration/base.html"
57
+
58
+ self.create_blueprint()
59
+
60
+ if self.dashboard_view_class is not None:
61
+ self._add_dashboard_view()
62
+
63
+ def init_menu(self):
64
+ """Finalize app.
65
+
66
+ This method will be called within the finalize_app entrypoint.
67
+ """
68
+ self._menu.register_menu_entries(current_menu, self._menu_key)
69
+ self._menu.register_admin_entry(current_menu, self.endpoint)
70
+
71
+ def load_admin_dashboard(self, app):
72
+ """Load dashboard view configuration."""
73
+ dashboard_config = app.config["ADMINISTRATION_DASHBOARD_VIEW"]
74
+ dashboard_class = import_string(dashboard_config)
75
+ return dashboard_class
76
+
77
+ def create_blueprint(self):
78
+ """Create Flask blueprint."""
79
+ # Create blueprint and register rules
80
+ self.blueprint = Blueprint(
81
+ self.endpoint,
82
+ __name__,
83
+ url_prefix=self.url,
84
+ template_folder="templates",
85
+ static_folder="static",
86
+ )
87
+
88
+ @property
89
+ def views(self):
90
+ """Registered admin views."""
91
+ return self._views
92
+
93
+ def add_view(self, view, view_instance, *args, **kwargs):
94
+ """Add a view to admin views."""
95
+ # Validate view's class and name's uniqueness.
96
+ if not issubclass(view.view_class, AdminView):
97
+ raise TypeError(f"View class must be of type {AdminView.__name__}")
98
+ if any(v.view_class.name == view.view_class.name for v in self.views):
99
+ raise ValueError(f"View name already registered: {view.view_class.name}")
100
+
101
+ self.views.append(view)
102
+
103
+ self.blueprint.add_url_rule(
104
+ rule=view_instance.url,
105
+ view_func=view,
106
+ )
107
+
108
+ if not isinstance(view_instance, AdminResourceDetailView) and not isinstance(
109
+ view_instance, AdminFormView
110
+ ):
111
+ self._menu.add_view_to_menu(view_instance)
112
+
113
+ def _add_dashboard_view(self):
114
+ """Add the admin dashboard view."""
115
+ dashboard_instance = self.dashboard_view_class(
116
+ admin=self, extension_name="invenio-administration"
117
+ )
118
+ dashboard_view = self.dashboard_view_class.as_view(
119
+ self.dashboard_view_class.name,
120
+ admin=self,
121
+ extension_name="invenio-administration",
122
+ )
123
+
124
+ self.add_view(dashboard_view, dashboard_instance)
@@ -0,0 +1,6 @@
1
+ # SPDX-FileCopyrightText: 2022 CERN.
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ extends:
5
+ - '@inveniosoftware/eslint-config-invenio'
6
+ - '@inveniosoftware/eslint-config-invenio/prettier'
@@ -0,0 +1 @@
1
+ "@inveniosoftware/eslint-config-invenio/prettier-config.js"
@@ -0,0 +1,6 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2022 CERN.
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ export * from "./src";
@@ -0,0 +1,25 @@
1
+ {
2
+ "@comment": [
3
+ "This package.json is needed to run the JS tests, locally and CI."
4
+ ],
5
+ "scripts": {
6
+ "test": "react-scripts test"
7
+ },
8
+ "devDependencies": {
9
+ "@testing-library/jest-dom": "^4.2.0",
10
+ "@testing-library/react": "^9.5.0",
11
+ "@testing-library/user-event": "^7.2.0",
12
+ "axios": "^1.7.7",
13
+ "coveralls": "^3.0.0",
14
+ "enzyme": "^3.10.0",
15
+ "enzyme-adapter-react-16": "^1.15.0",
16
+ "expect": "^26.0.0",
17
+ "lodash": "^4.17.0",
18
+ "luxon": "^1.23.0",
19
+ "react": "^16.13.0",
20
+ "react-dom": "^16.13.0",
21
+ "react-scripts": "^5.0.1",
22
+ "semantic-ui-react": "^2.1.0",
23
+ "react-overridable": "^0.0.3"
24
+ }
25
+ }
@@ -0,0 +1,44 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2022 CERN.
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import PropTypes from "prop-types";
7
+ import React, { Component } from "react";
8
+ import { Modal } from "semantic-ui-react";
9
+ import Overridable from "react-overridable";
10
+
11
+ class ActionModal extends Component {
12
+ render() {
13
+ const { children, modalOpen, modalProps, resource } = this.props;
14
+
15
+ return (
16
+ <Overridable
17
+ id="InvenioAdministration.ActionModal.layout"
18
+ modalOpen={modalOpen}
19
+ // eslint-disable-next-line react/no-children-prop
20
+ children={children}
21
+ resource={resource}
22
+ >
23
+ <Modal role="dialog" open={modalOpen} {...modalProps}>
24
+ {children}
25
+ </Modal>
26
+ </Overridable>
27
+ );
28
+ }
29
+ }
30
+
31
+ ActionModal.propTypes = {
32
+ children: PropTypes.object,
33
+ modalOpen: PropTypes.bool,
34
+ modalProps: PropTypes.object,
35
+ resource: PropTypes.object.isRequired,
36
+ };
37
+
38
+ ActionModal.defaultProps = {
39
+ modalOpen: false,
40
+ modalProps: {},
41
+ children: null,
42
+ };
43
+
44
+ export default Overridable.component("InvenioAdministration.ActionModal", ActionModal);
@@ -0,0 +1,118 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2022-2024 CERN.
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import Edit from "./Edit";
7
+ import Delete from "./Delete";
8
+ import { DeleteModalTrigger } from "./DeleteModalTrigger";
9
+ import React, { Component } from "react";
10
+ import PropTypes from "prop-types";
11
+ import isEmpty from "lodash/isEmpty";
12
+ import ResourceActions from "./ResourceActions";
13
+ import { Button, Dropdown } from "semantic-ui-react";
14
+ import { i18next } from "@translations/invenio_administration/i18next";
15
+ import _get from "lodash/get";
16
+
17
+ export class Actions extends Component {
18
+ render() {
19
+ const {
20
+ title,
21
+ resourceName,
22
+ actions,
23
+ resource,
24
+ successCallback,
25
+ idKeyPath,
26
+ editUrl,
27
+ displayEdit,
28
+ displayDelete,
29
+ displayAsDropdown,
30
+ } = this.props;
31
+
32
+ // if number of actions is greater than 3, we display all in a dropdown
33
+ const _displayAsDropdown =
34
+ displayAsDropdown ||
35
+ (displayEdit && displayDelete && Object.keys(actions).length > 1);
36
+
37
+ if (_displayAsDropdown) {
38
+ return (
39
+ <Dropdown
40
+ trigger={
41
+ <Button
42
+ icon="cog"
43
+ size="tiny"
44
+ className="transparent rel-ml-1"
45
+ aria-label={i18next.t("Open list of actions")}
46
+ />
47
+ }
48
+ >
49
+ <Dropdown.Menu>
50
+ {!isEmpty(actions) && (
51
+ <ResourceActions
52
+ resource={resource}
53
+ successCallback={successCallback}
54
+ idKeyPath={idKeyPath}
55
+ actions={actions}
56
+ Element={Dropdown.Item}
57
+ />
58
+ )}
59
+ {displayEdit && <Edit editUrl={editUrl} resource={resource} />}
60
+ {displayDelete && (
61
+ <DeleteModalTrigger
62
+ title={title}
63
+ resourceName={resourceName}
64
+ apiEndpoint={_get(resource, "links.self")}
65
+ resource={resource}
66
+ successCallback={successCallback}
67
+ idKeyPath={idKeyPath}
68
+ Element={Dropdown.Item}
69
+ />
70
+ )}
71
+ </Dropdown.Menu>
72
+ </Dropdown>
73
+ );
74
+ } else {
75
+ return (
76
+ <>
77
+ {!isEmpty(actions) && (
78
+ <ResourceActions
79
+ resource={resource}
80
+ successCallback={successCallback}
81
+ idKeyPath={idKeyPath}
82
+ actions={actions}
83
+ />
84
+ )}
85
+ {displayEdit && <Edit editUrl={editUrl} resource={resource} />}
86
+ {displayDelete && (
87
+ <Delete
88
+ successCallback={successCallback}
89
+ resource={resource}
90
+ resourceName={resourceName}
91
+ title={title}
92
+ />
93
+ )}
94
+ </>
95
+ );
96
+ }
97
+ }
98
+ }
99
+
100
+ Actions.propTypes = {
101
+ title: PropTypes.string.isRequired,
102
+ resourceName: PropTypes.string.isRequired,
103
+ displayEdit: PropTypes.bool,
104
+ displayDelete: PropTypes.bool,
105
+ displayAsDropdown: PropTypes.bool,
106
+ resource: PropTypes.object.isRequired,
107
+ successCallback: PropTypes.func.isRequired,
108
+ idKeyPath: PropTypes.string,
109
+ actions: PropTypes.object.isRequired,
110
+ editUrl: PropTypes.string.isRequired,
111
+ };
112
+
113
+ Actions.defaultProps = {
114
+ displayEdit: true,
115
+ displayDelete: true,
116
+ displayAsDropdown: false,
117
+ idKeyPath: "pid",
118
+ };
@@ -0,0 +1,67 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2022-2024 CERN.
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { DeleteModalTrigger } from "./DeleteModalTrigger";
7
+ import React, { Component } from "react";
8
+ import PropTypes from "prop-types";
9
+ import { Popup } from "semantic-ui-react";
10
+ import { i18next } from "@translations/invenio_administration/i18next";
11
+ import _get from "lodash/get";
12
+ import Overridable from "react-overridable";
13
+
14
+ class DeleteCmp extends Component {
15
+ render() {
16
+ const {
17
+ disabledMessage,
18
+ disable,
19
+ title,
20
+ resourceName,
21
+ successCallback,
22
+ idKeyPath,
23
+ resource,
24
+ } = this.props;
25
+
26
+ const disabled = disable(resource);
27
+
28
+ return (
29
+ <Popup
30
+ content={disabledMessage}
31
+ disabled={!disabled}
32
+ trigger={
33
+ <span>
34
+ <DeleteModalTrigger
35
+ title={title}
36
+ resourceName={resourceName}
37
+ resource={resource}
38
+ successCallback={successCallback}
39
+ idKeyPath={idKeyPath}
40
+ disabled={disabled}
41
+ apiEndpoint={_get(resource, "links.self")}
42
+ disabledDeleteMessage={disabledMessage}
43
+ />
44
+ </span>
45
+ }
46
+ />
47
+ );
48
+ }
49
+ }
50
+
51
+ DeleteCmp.propTypes = {
52
+ disabledMessage: PropTypes.string,
53
+ title: PropTypes.string.isRequired,
54
+ resourceName: PropTypes.string.isRequired,
55
+ successCallback: PropTypes.func.isRequired,
56
+ idKeyPath: PropTypes.string,
57
+ disable: PropTypes.func,
58
+ resource: PropTypes.object.isRequired,
59
+ };
60
+
61
+ DeleteCmp.defaultProps = {
62
+ disabledMessage: i18next.t("Resource is not deletable."),
63
+ idKeyPath: "pid",
64
+ disable: () => false,
65
+ };
66
+
67
+ export default Overridable.component("InvenioAdministration.DeleteAction", DeleteCmp);
@@ -0,0 +1,118 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2022 CERN.
3
+ * SPDX-FileCopyrightText: 2024 KTH Royal Institute of Technology.
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ import React, { Component } from "react";
8
+ import PropTypes from "prop-types";
9
+ import { Button, Icon } from "semantic-ui-react";
10
+ import { i18next } from "@translations/invenio_administration/i18next";
11
+ import { Modal } from "semantic-ui-react";
12
+ import isEmpty from "lodash/isEmpty";
13
+ import { ErrorMessage } from "../ui_messages/messages";
14
+ import { NotificationContext } from "../ui_messages/context";
15
+ import Overridable from "react-overridable";
16
+ import { InvenioAdministrationActionsApi } from "../api/actions";
17
+
18
+ class DeleteModal extends Component {
19
+ constructor(props) {
20
+ super(props);
21
+ this.state = { loading: false, error: undefined };
22
+ this.cancelButton = React.createRef();
23
+ }
24
+
25
+ componentDidUpdate() {
26
+ this.cancelButton.current?.focus();
27
+ }
28
+
29
+ static contextType = NotificationContext;
30
+
31
+ cleanError = () => {
32
+ this.setState({ error: undefined });
33
+ };
34
+
35
+ handleOnButtonClick = async () => {
36
+ const { successCallback, apiEndpoint, toggleModal } = this.props;
37
+ const { addNotification } = this.context;
38
+ try {
39
+ await InvenioAdministrationActionsApi.deleteResource(apiEndpoint);
40
+ toggleModal(false);
41
+ addNotification({
42
+ title: i18next.t("Success"),
43
+ content: i18next.t("Resource was successfully deleted."),
44
+ type: "success",
45
+ });
46
+ successCallback();
47
+ } catch (e) {
48
+ this.setState({
49
+ error: { header: i18next.t("Action error"), content: e.message, id: e.code },
50
+ });
51
+ }
52
+ };
53
+
54
+ resetErrorState = () => {
55
+ this.setState({ error: undefined });
56
+ };
57
+
58
+ render() {
59
+ const { loading, error } = this.state;
60
+ const { modalOpen, toggleModal, children, title } = this.props;
61
+ return (
62
+ <Overridable
63
+ id="DeleteModal.layout"
64
+ {...this.props}
65
+ handleOnButtonClick={this.handleOnButtonClick}
66
+ cleanError={this.cleanError}
67
+ resetErrorState={this.resetErrorState}
68
+ >
69
+ <Modal role="dialog" open={modalOpen}>
70
+ <Modal.Header as="h2">
71
+ {i18next.t("Delete {{title}}", { title: title })}
72
+ </Modal.Header>
73
+ <Modal.Content>
74
+ <Modal.Description>
75
+ {children}
76
+ {!isEmpty(error) && (
77
+ <ErrorMessage {...error} removeNotification={this.resetErrorState} />
78
+ )}
79
+ </Modal.Description>
80
+ </Modal.Content>
81
+ <Modal.Actions>
82
+ <Button
83
+ ref={this.cancelButton}
84
+ icon="cancel"
85
+ onClick={() => {
86
+ this.cleanError();
87
+ toggleModal(false);
88
+ }}
89
+ loading={loading}
90
+ content={i18next.t("Cancel")}
91
+ floated="left"
92
+ size="medium"
93
+ />
94
+ <Button negative onClick={this.handleOnButtonClick} loading={loading}>
95
+ <Icon name="trash alternate" />
96
+ {i18next.t("Delete")}
97
+ </Button>
98
+ </Modal.Actions>
99
+ </Modal>
100
+ </Overridable>
101
+ );
102
+ }
103
+ }
104
+
105
+ DeleteModal.propTypes = {
106
+ title: PropTypes.string.isRequired,
107
+ apiEndpoint: PropTypes.string.isRequired,
108
+ successCallback: PropTypes.func.isRequired,
109
+ toggleModal: PropTypes.func.isRequired,
110
+ modalOpen: PropTypes.bool.isRequired,
111
+ children: PropTypes.node,
112
+ };
113
+
114
+ DeleteModal.defaultProps = {
115
+ children: null,
116
+ };
117
+
118
+ export default Overridable.component("DeleteModal", DeleteModal);
@@ -0,0 +1,97 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2022 CERN.
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import React, { Component } from "react";
7
+ import PropTypes from "prop-types";
8
+ import { i18next } from "@translations/invenio_administration/i18next";
9
+ import { Button, Icon } from "semantic-ui-react";
10
+ import DeleteModal from "./DeleteModal";
11
+ import { Modal } from "semantic-ui-react";
12
+ import _get from "lodash/get";
13
+ import Overridable from "react-overridable";
14
+
15
+ export class DeleteModalTrigger extends Component {
16
+ constructor(props) {
17
+ super(props);
18
+ this.state = { modalOpen: false };
19
+ }
20
+
21
+ toggleModal = (open) => {
22
+ this.setState({ modalOpen: open });
23
+ };
24
+
25
+ render() {
26
+ const {
27
+ title,
28
+ resourceName,
29
+ apiEndpoint,
30
+ resource,
31
+ successCallback,
32
+ idKeyPath,
33
+ Element,
34
+ disabled,
35
+ disabledDeleteMessage,
36
+ } = this.props;
37
+ const { modalOpen } = this.state;
38
+ const triggerId = `delete-modal-trigger-${resource.id}`;
39
+ return (
40
+ <Overridable id="InvenioAdministration.DeleteModalTrigger">
41
+ <>
42
+ <Element
43
+ id={triggerId}
44
+ disabled={disabled}
45
+ icon
46
+ negative
47
+ onClick={() => this.toggleModal(true)}
48
+ aria-label={i18next.t("Delete")}
49
+ aria-controls="delete-modal"
50
+ aria-expanded={modalOpen}
51
+ aria-haspopup="dialog"
52
+ title={disabledDeleteMessage}
53
+ >
54
+ <Icon name="trash alternate" />
55
+ </Element>
56
+ <DeleteModal
57
+ id="delete-modal"
58
+ aria-labelledby={triggerId}
59
+ title={title}
60
+ apiEndpoint={apiEndpoint}
61
+ resource={resource}
62
+ successCallback={successCallback}
63
+ idKeyPath={idKeyPath}
64
+ toggleModal={this.toggleModal}
65
+ modalOpen={modalOpen}
66
+ >
67
+ <Modal.Content>
68
+ <Modal.Description>
69
+ {i18next.t("Are you sure you want to delete {{resourceName}}?", {
70
+ resourceName: _get(resource, resourceName),
71
+ })}
72
+ </Modal.Description>
73
+ </Modal.Content>
74
+ </DeleteModal>
75
+ </>
76
+ </Overridable>
77
+ );
78
+ }
79
+ }
80
+
81
+ DeleteModalTrigger.propTypes = {
82
+ title: PropTypes.string.isRequired,
83
+ resourceName: PropTypes.string.isRequired,
84
+ apiEndpoint: PropTypes.string.isRequired,
85
+ resource: PropTypes.object.isRequired,
86
+ successCallback: PropTypes.func.isRequired,
87
+ Element: PropTypes.object,
88
+ idKeyPath: PropTypes.string.isRequired,
89
+ disabled: PropTypes.bool,
90
+ disabledDeleteMessage: PropTypes.string,
91
+ };
92
+
93
+ DeleteModalTrigger.defaultProps = {
94
+ Element: Button,
95
+ disabled: false,
96
+ disabledDeleteMessage: "",
97
+ };
@@ -0,0 +1,52 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2022 CERN.
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import PropTypes from "prop-types";
7
+ import React, { Component } from "react";
8
+ import { i18next } from "@translations/invenio_administration/i18next";
9
+ import { Button, Popup, Icon } from "semantic-ui-react";
10
+ import Overridable from "react-overridable";
11
+
12
+ class EditCmp extends Component {
13
+ render() {
14
+ const { display, editUrl, disable, disabledMessage, resource } = this.props;
15
+ if (!display) {
16
+ return null;
17
+ }
18
+ const disabled = disable(resource);
19
+
20
+ return (
21
+ <Popup
22
+ content={disabledMessage}
23
+ disabled={!disabled}
24
+ trigger={
25
+ <span className="mr-5">
26
+ <Button as="a" disabled={disabled} href={editUrl} icon labelPosition="left">
27
+ <Icon name="pencil" />
28
+ {i18next.t("Edit")}
29
+ </Button>
30
+ </span>
31
+ }
32
+ />
33
+ );
34
+ }
35
+ }
36
+
37
+ EditCmp.propTypes = {
38
+ display: PropTypes.bool,
39
+ editUrl: PropTypes.string.isRequired,
40
+ disable: PropTypes.func,
41
+ disabledMessage: PropTypes.string,
42
+ resource: PropTypes.object,
43
+ };
44
+
45
+ EditCmp.defaultProps = {
46
+ display: true,
47
+ disable: () => false,
48
+ disabledMessage: i18next.t("Resource is not editable."),
49
+ resource: undefined,
50
+ };
51
+
52
+ export default Overridable.component("InvenioAdministration.EditAction", EditCmp);