From dbdb2402414d737dfd5963988c4567b3950d2fdb Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Tue, 21 Jan 2025 17:13:13 +0100 Subject: [PATCH 01/24] feat(jinja): webpack_optional global helper --- oarepo_ui/ext.py | 14 +++++++++++++- oarepo_ui/proxies.py | 3 +++ oarepo_ui/templates/oarepo_ui/javascript.html | 5 ++--- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/oarepo_ui/ext.py b/oarepo_ui/ext.py index 90920cbe..56d98910 100644 --- a/oarepo_ui/ext.py +++ b/oarepo_ui/ext.py @@ -3,9 +3,14 @@ from pathlib import Path from flask import Response, current_app +from flask_webpackext import current_manifest +from flask_webpackext.errors import ManifestKeyNotFoundError from importlib_metadata import entry_points from invenio_base.utils import obj_or_import_string from flask_login import user_logged_in, user_logged_out +from markupsafe import Markup + +from .proxies import current_optional_manifest from .utils import clear_view_deposit_page_permission_from_session @@ -20,12 +25,18 @@ def __init__(self, app): self.init_builder_plugin() self._catalog = None + def optional_manifest(self, key): + try: + return current_manifest[key] + except ManifestKeyNotFoundError as e: + return Markup(f"") + def reinitialize_catalog(self): self._catalog = None try: del self.catalog # noqa - this is a documented method of clearing the cache except ( - AttributeError + AttributeError ): # but does not work if the cache is not initialized yet, thus the try/except pass @@ -95,6 +106,7 @@ def init_app(self, app): app.extensions["oarepo_ui"] = OARepoUIState(app) user_logged_in.connect(clear_view_deposit_page_permission_from_session) user_logged_out.connect(clear_view_deposit_page_permission_from_session) + app.add_template_global(current_optional_manifest, name="webpack_optional") def init_config(self, app): """Initialize configuration.""" diff --git a/oarepo_ui/proxies.py b/oarepo_ui/proxies.py index c0a34008..a9bc8d1a 100644 --- a/oarepo_ui/proxies.py +++ b/oarepo_ui/proxies.py @@ -3,3 +3,6 @@ current_oarepo_ui = LocalProxy(lambda: current_app.extensions["oarepo_ui"]) """Proxy to the oarepo_ui state.""" + +current_optional_manifest = LocalProxy(lambda: current_oarepo_ui.optional_manifest) +"""Proxy to current optional webpack manifest.""" diff --git a/oarepo_ui/templates/oarepo_ui/javascript.html b/oarepo_ui/templates/oarepo_ui/javascript.html index b47fe1a4..464e2654 100644 --- a/oarepo_ui/templates/oarepo_ui/javascript.html +++ b/oarepo_ui/templates/oarepo_ui/javascript.html @@ -1,7 +1,6 @@ {% include "invenio_theme/javascript.html" %} - +{{ webpack['oarepo-overridable-registry.js'] }} {{ webpack['oarepo_ui_theme.js'] }} {{ webpack['oarepo_ui_components.js'] }} -{{ webpack['oarepo-overridable-registry.js'] }} - +{{ webpack_optional('overrides-' ~ request.endpoint ~ '.js') }} From 271dbd096a869b172794b2e10090f6fbc199aa59 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Tue, 21 Jan 2025 17:17:34 +0100 Subject: [PATCH 02/24] chore: fix indent --- oarepo_ui/ext.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oarepo_ui/ext.py b/oarepo_ui/ext.py index 56d98910..2bc03740 100644 --- a/oarepo_ui/ext.py +++ b/oarepo_ui/ext.py @@ -36,7 +36,7 @@ def reinitialize_catalog(self): try: del self.catalog # noqa - this is a documented method of clearing the cache except ( - AttributeError + AttributeError ): # but does not work if the cache is not initialized yet, thus the try/except pass From 9208b1df0d21021927c0333f87cb9c6cd107c935 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Tue, 21 Jan 2025 19:02:52 +0100 Subject: [PATCH 03/24] feat(webpack): OverridableBundleProject wip --- oarepo_ui/webpack.py | 78 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 oarepo_ui/webpack.py diff --git a/oarepo_ui/webpack.py b/oarepo_ui/webpack.py new file mode 100644 index 00000000..1a5d880c --- /dev/null +++ b/oarepo_ui/webpack.py @@ -0,0 +1,78 @@ +import os + +from flask import current_app +from flask_webpackext import WebpackBundleProject +from pywebpack import bundles_from_entry_point +from pywebpack.helpers import cached + + +class OverridableBundleProject(WebpackBundleProject): + def __init__( + self, import_name, project_folder=None, bundles=None, + config=None, config_path=None, overrides_bundle_path="_overrides" + ): + """Initialize templated folder. + + :param import_name: Name of the module where the WebpackBundleProject + class is instantiated. It is used to determine the absolute path + to the ``project_folder``. + :param project_folder: Relative path to the Webpack project which is + going to aggregate all the ``bundles``. + :param bundles: List of + :class:`flask_webpackext.bundle.WebpackBundle`. This list can be + statically defined if the bundles are known before hand, or + dinamically generated using + :func:`pywebpack.helpers.bundles_from_entry_point` so the bundles + are discovered from the defined Webpack entrypoints exposed by + other modules. + :param config: Dictionary which overrides the ``config.json`` file + generated by Flask-WebpackExt. Use carefuly and only if you know + what you are doing since ``config.json`` is the file that holds the + key information to integrate Flask with Webpack. + :param config_path: Path where Flask-WebpackExt is going to write the + ``config.json``, this file is generated by + :func:`flask_webpackext.project.flask_config`. + :param overrides_bundle_path: Path where special bundle for UI overrides + if going to be generated. + """ + super(OverridableBundleProject, self).__init__( + import_name, + project_folder=project_folder, bundles=bundles, config=config, config_path=config_path) + self.overrides_bundle_path = overrides_bundle_path + + @property + @cached + def entry(self): + """Get webpack entry points.""" + bundle_entries = super().entry + if 'UI_OVERRIDES' in current_app.config: + for bp_name, overrides in current_app.config['UI_OVERRIDES'].items(): + # TODO: actually generate the js file with overrides data + bundle_entries[f"overrides-{bp_name}"] = f"./js/{self.overrides_bundle_path}/{bp_name}.js" + return bundle_entries + + def create(self, force=None): + """Create webpack project from a template. + + This command collects all asset files from the bundles. + It generates a new package.json by merging the package.json + dependencies of each bundle. Additionally, it generates a special + bundle for any UI overrides. + """ + super().create(force) + + # Generate special bundle for configured UI overrides + overrides_bundle_path = os.path.join(self.project_path, f'js/{self.overrides_bundle_path}') + self.storage_cls(overrides_bundle_path, self.project_path).run(force=force) + + # TODO: iterate over overrides entries & render mapping templates to bundle path + + raise AttributeError(self.project_path, os.listdir(os.path.join(self.project_path, 'js/'))) + + +project = OverridableBundleProject( + __name__, + project_folder="assets", + config_path="build/config.json", + bundles=bundles_from_entry_point("invenio_assets.webpack"), +) \ No newline at end of file From 9a72ba4e6fc88dc82c252dc2cc79ba0a6e6738e0 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Wed, 22 Jan 2025 09:11:56 +0100 Subject: [PATCH 04/24] fix(webpack): fix assets project path resolution --- oarepo_ui/webpack.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/oarepo_ui/webpack.py b/oarepo_ui/webpack.py index 1a5d880c..fab2b50f 100644 --- a/oarepo_ui/webpack.py +++ b/oarepo_ui/webpack.py @@ -4,6 +4,7 @@ from flask_webpackext import WebpackBundleProject from pywebpack import bundles_from_entry_point from pywebpack.helpers import cached +from flask.helpers import get_root_path class OverridableBundleProject(WebpackBundleProject): @@ -35,6 +36,8 @@ class is instantiated. It is used to determine the absolute path :param overrides_bundle_path: Path where special bundle for UI overrides if going to be generated. """ + # Following is needed to correctly resolve paths to etc. source package.json from invenio_assets + import_name = 'invenio_assets.webpack' super(OverridableBundleProject, self).__init__( import_name, project_folder=project_folder, bundles=bundles, config=config, config_path=config_path) @@ -70,6 +73,12 @@ def create(self, force=None): raise AttributeError(self.project_path, os.listdir(os.path.join(self.project_path, 'js/'))) + # @property + # def package_json_source_path(self): + # """Full path to the source package.json.""" + # raise AttributeError(self._project_template_dir, 'package.json') + + project = OverridableBundleProject( __name__, project_folder="assets", From f02c5b9348f95201afd86897d9ad9c6bffa16688 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Wed, 22 Jan 2025 12:39:45 +0100 Subject: [PATCH 05/24] feat(webpack): generate overrides js mappings --- oarepo_ui/webpack.py | 38 +++++++++++++++++----------- tests/conftest.py | 2 ++ tests/test_ui_webpack.py | 54 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 tests/test_ui_webpack.py diff --git a/oarepo_ui/webpack.py b/oarepo_ui/webpack.py index fab2b50f..c176a6a5 100644 --- a/oarepo_ui/webpack.py +++ b/oarepo_ui/webpack.py @@ -4,7 +4,18 @@ from flask_webpackext import WebpackBundleProject from pywebpack import bundles_from_entry_point from pywebpack.helpers import cached -from flask.helpers import get_root_path + +overrides_js_template = ''' +import { overrideStore } from 'react-overridable'; + +{% for key, import_spec in overrides.items() -%} +import {{ import_spec[0] }} from '{{ import_spec[1] }}'; +{%- endfor %} + +{% for key, import_spec in overrides.items() -%} +overrideStore.add('{{ key }}', {{ import_spec[0] }}); +{%- endfor %} +''' class OverridableBundleProject(WebpackBundleProject): @@ -50,7 +61,6 @@ def entry(self): bundle_entries = super().entry if 'UI_OVERRIDES' in current_app.config: for bp_name, overrides in current_app.config['UI_OVERRIDES'].items(): - # TODO: actually generate the js file with overrides data bundle_entries[f"overrides-{bp_name}"] = f"./js/{self.overrides_bundle_path}/{bp_name}.js" return bundle_entries @@ -63,20 +73,20 @@ def create(self, force=None): bundle for any UI overrides. """ super().create(force) - - # Generate special bundle for configured UI overrides - overrides_bundle_path = os.path.join(self.project_path, f'js/{self.overrides_bundle_path}') - self.storage_cls(overrides_bundle_path, self.project_path).run(force=force) - # TODO: iterate over overrides entries & render mapping templates to bundle path - - raise AttributeError(self.project_path, os.listdir(os.path.join(self.project_path, 'js/'))) + if 'UI_OVERRIDES' in current_app.config: + # Generate special bundle for configured UI overrides + overrides_bundle_path = os.path.join(self.project_path, f'js/{self.overrides_bundle_path}') + if not os.path.exists(overrides_bundle_path): + os.mkdir(overrides_bundle_path) + self.storage_cls(overrides_bundle_path, self.project_path).run(force=force) - # @property - # def package_json_source_path(self): - # """Full path to the source package.json.""" - # raise AttributeError(self._project_template_dir, 'package.json') + for bp_name, overrides in current_app.config['UI_OVERRIDES'].items(): + _overrides_js_template = current_app.jinja_env.from_string(overrides_js_template) + overrides_js_content = _overrides_js_template.render({'overrides': overrides}) + with open(os.path.join(overrides_bundle_path, f'{bp_name}.js'), 'w+') as f: + f.write(overrides_js_content) project = OverridableBundleProject( @@ -84,4 +94,4 @@ def create(self, force=None): project_folder="assets", config_path="build/config.json", bundles=bundles_from_entry_point("invenio_assets.webpack"), -) \ No newline at end of file +) diff --git a/tests/conftest.py b/tests/conftest.py index 87675d51..55fbe3d1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -61,6 +61,8 @@ def app_config(app_config): {"section": "B", "fields": [{"field": "bbb", "ui_widget": "Input"}]} ] + app_config["WEBPACKEXT_PROJECT"] = "oarepo_ui.webpack:project" + return app_config diff --git a/tests/test_ui_webpack.py b/tests/test_ui_webpack.py new file mode 100644 index 00000000..48d88129 --- /dev/null +++ b/tests/test_ui_webpack.py @@ -0,0 +1,54 @@ +import os +import pytest +from flask import Flask +from oarepo_ui.webpack import OverridableBundleProject, overrides_js_template, project + + +def test_overridable_bundle_project_init(): + proj = OverridableBundleProject( + import_name='test_app', + project_folder='test_assets', + config_path='test_build/config.json', + bundles=[] + ) + assert proj.import_name == 'invenio_assets.webpack' + assert proj.project_folder == 'test_assets' + assert proj.config_path == 'test_build/config.json' + assert proj.overrides_bundle_path == '_overrides' + + +def test_overridable_bundle_project_entry(app): + app.config['UI_OVERRIDES'] = { + 'test_bp': {'componentA': ['ComponentA', 'components/ComponentA']} + } + with app.app_context(): + entry_points = project.entry + assert 'overrides-test_bp' in entry_points + assert entry_points['overrides-test_bp'] == './js/_overrides/test_bp.js' + + +def test_create_overrides_bundle(app, fake_manifest): + app.config['UI_OVERRIDES'] = { + 'test_bp': {'componentA': ['ComponentA', 'components/ComponentA']} + } + with app.app_context(): + project.create() + # TODO: check assets folder + + +def test_create_writes_override_files(app, fake_manifest): + app.config['UI_OVERRIDES'] = { + 'test_bp': {'componentA': ['ComponentA', 'components/ComponentA']} + } + with app.app_context(): + project.create() + # mock_open.assert_called_once_with(os.path.join(project.project_path, 'js/_overrides/test_bp.js'), 'w+') + # written_content = mock_open().write.call_args[0][0] + # assert 'overrideStore.add' in written_content + + +@pytest.fixture +def app(): + app = Flask(__name__) + app.config['UI_OVERRIDES'] = {} + return app From c85c9fc420cc280bda93372423018afd0bd9527f Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Wed, 22 Jan 2025 12:43:20 +0100 Subject: [PATCH 06/24] chore(tests): remove junk --- tests/test_ui_webpack.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tests/test_ui_webpack.py b/tests/test_ui_webpack.py index 48d88129..ed3a6388 100644 --- a/tests/test_ui_webpack.py +++ b/tests/test_ui_webpack.py @@ -1,7 +1,7 @@ import os import pytest from flask import Flask -from oarepo_ui.webpack import OverridableBundleProject, overrides_js_template, project +from oarepo_ui.webpack import OverridableBundleProject, project def test_overridable_bundle_project_init(): @@ -45,10 +45,3 @@ def test_create_writes_override_files(app, fake_manifest): # mock_open.assert_called_once_with(os.path.join(project.project_path, 'js/_overrides/test_bp.js'), 'w+') # written_content = mock_open().write.call_args[0][0] # assert 'overrideStore.add' in written_content - - -@pytest.fixture -def app(): - app = Flask(__name__) - app.config['UI_OVERRIDES'] = {} - return app From 21a8a3a67a4adfe57852969178cd42f94c8cc230 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Wed, 22 Jan 2025 12:44:54 +0100 Subject: [PATCH 07/24] chore(tests): fix sonar --- oarepo_ui/webpack.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oarepo_ui/webpack.py b/oarepo_ui/webpack.py index c176a6a5..1399ec6d 100644 --- a/oarepo_ui/webpack.py +++ b/oarepo_ui/webpack.py @@ -48,9 +48,9 @@ class is instantiated. It is used to determine the absolute path if going to be generated. """ # Following is needed to correctly resolve paths to etc. source package.json from invenio_assets - import_name = 'invenio_assets.webpack' + _import_name = 'invenio_assets.webpack' super(OverridableBundleProject, self).__init__( - import_name, + _import_name, project_folder=project_folder, bundles=bundles, config=config, config_path=config_path) self.overrides_bundle_path = overrides_bundle_path From 9afe95618b8513944a063af7385ce2759dda4f98 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Wed, 22 Jan 2025 14:29:20 +0100 Subject: [PATCH 08/24] chore(tests): make webpack tests pass --- oarepo_ui/webpack.py | 10 ++++----- tests/test_ui_webpack.py | 45 ++++++++++++++++++++-------------------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/oarepo_ui/webpack.py b/oarepo_ui/webpack.py index 1399ec6d..8aff6bc7 100644 --- a/oarepo_ui/webpack.py +++ b/oarepo_ui/webpack.py @@ -76,16 +76,14 @@ def create(self, force=None): if 'UI_OVERRIDES' in current_app.config: # Generate special bundle for configured UI overrides - overrides_bundle_path = os.path.join(self.project_path, f'js/{self.overrides_bundle_path}') - if not os.path.exists(overrides_bundle_path): - os.mkdir(overrides_bundle_path) - - self.storage_cls(overrides_bundle_path, self.project_path).run(force=force) + overrides_bundle_dir = os.path.join(self.project_path, f'js/{self.overrides_bundle_path}') + if not os.path.exists(overrides_bundle_dir): + os.mkdir(overrides_bundle_dir) for bp_name, overrides in current_app.config['UI_OVERRIDES'].items(): _overrides_js_template = current_app.jinja_env.from_string(overrides_js_template) overrides_js_content = _overrides_js_template.render({'overrides': overrides}) - with open(os.path.join(overrides_bundle_path, f'{bp_name}.js'), 'w+') as f: + with open(os.path.join(overrides_bundle_dir, f'{bp_name}.js'), 'w+') as f: f.write(overrides_js_content) diff --git a/tests/test_ui_webpack.py b/tests/test_ui_webpack.py index ed3a6388..e1492a6c 100644 --- a/tests/test_ui_webpack.py +++ b/tests/test_ui_webpack.py @@ -1,23 +1,21 @@ import os -import pytest -from flask import Flask from oarepo_ui.webpack import OverridableBundleProject, project -def test_overridable_bundle_project_init(): +def test_overridable_bundle_project_init(app): proj = OverridableBundleProject( import_name='test_app', - project_folder='test_assets', + project_folder='assets', config_path='test_build/config.json', bundles=[] ) - assert proj.import_name == 'invenio_assets.webpack' - assert proj.project_folder == 'test_assets' - assert proj.config_path == 'test_build/config.json' - assert proj.overrides_bundle_path == '_overrides' - + with app.app_context(): + assert proj._project_template_dir.endswith('invenio_assets/assets') + assert proj.config_path.endswith('test_build/config.json') + assert proj.overrides_bundle_path == '_overrides' + assert os.path.exists(proj.package_json_source_path) -def test_overridable_bundle_project_entry(app): +def test_overridable_project_entry(app): app.config['UI_OVERRIDES'] = { 'test_bp': {'componentA': ['ComponentA', 'components/ComponentA']} } @@ -27,21 +25,24 @@ def test_overridable_bundle_project_entry(app): assert entry_points['overrides-test_bp'] == './js/_overrides/test_bp.js' -def test_create_overrides_bundle(app, fake_manifest): +def test_overridable_project_entry_file(app, fake_manifest): app.config['UI_OVERRIDES'] = { - 'test_bp': {'componentA': ['ComponentA', 'components/ComponentA']} + 'test_bp': {'componentA.item': ['ComponentA', 'components/ComponentA']} } with app.app_context(): project.create() - # TODO: check assets folder + assert os.path.exists(project.package_json_source_path) + overrides_bundle_dir = os.path.join(project.project_path, f'js/{project.overrides_bundle_path}') + assert os.path.isdir(overrides_bundle_dir) -def test_create_writes_override_files(app, fake_manifest): - app.config['UI_OVERRIDES'] = { - 'test_bp': {'componentA': ['ComponentA', 'components/ComponentA']} - } - with app.app_context(): - project.create() - # mock_open.assert_called_once_with(os.path.join(project.project_path, 'js/_overrides/test_bp.js'), 'w+') - # written_content = mock_open().write.call_args[0][0] - # assert 'overrideStore.add' in written_content + overrides_file_path = os.path.join(overrides_bundle_dir, 'test_bp.js') + assert os.path.exists(overrides_file_path) + with open(overrides_file_path) as f: + overrides_file_path_content = f.read() + assert overrides_file_path_content == ''' +import { overrideStore } from 'react-overridable'; + +import ComponentA from 'components/ComponentA'; + +overrideStore.add('componentA.item', ComponentA);''' From 521cf83b610448780978b10c11a7f1ed2bad7de8 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Wed, 22 Jan 2025 15:17:36 +0100 Subject: [PATCH 09/24] feat(webpack): add generated_paths prop to webpack project --- oarepo_ui/webpack.py | 42 ++++++++++++++++++++++++++++++++-------- tests/test_ui_webpack.py | 29 +++++++++++++++++++++------ 2 files changed, 57 insertions(+), 14 deletions(-) diff --git a/oarepo_ui/webpack.py b/oarepo_ui/webpack.py index 8aff6bc7..7d30c005 100644 --- a/oarepo_ui/webpack.py +++ b/oarepo_ui/webpack.py @@ -52,7 +52,20 @@ class is instantiated. It is used to determine the absolute path super(OverridableBundleProject, self).__init__( _import_name, project_folder=project_folder, bundles=bundles, config=config, config_path=config_path) - self.overrides_bundle_path = overrides_bundle_path + self._overrides_bundle_path = overrides_bundle_path + self._generated_paths = [] + + @property + def overrides_bundle_asset_path(self): + return f'js/{self._overrides_bundle_path}' + + @property + def overrides_bundle_path(self): + return os.path.join(self.project_path, self.overrides_bundle_asset_path) + + @property + def generated_paths(self): + return self._generated_paths @property @cached @@ -61,7 +74,7 @@ def entry(self): bundle_entries = super().entry if 'UI_OVERRIDES' in current_app.config: for bp_name, overrides in current_app.config['UI_OVERRIDES'].items(): - bundle_entries[f"overrides-{bp_name}"] = f"./js/{self.overrides_bundle_path}/{bp_name}.js" + bundle_entries[f"overrides-{bp_name}"] = f"./{self.overrides_bundle_asset_path}/{bp_name}.js" return bundle_entries def create(self, force=None): @@ -76,16 +89,29 @@ def create(self, force=None): if 'UI_OVERRIDES' in current_app.config: # Generate special bundle for configured UI overrides - overrides_bundle_dir = os.path.join(self.project_path, f'js/{self.overrides_bundle_path}') - if not os.path.exists(overrides_bundle_dir): - os.mkdir(overrides_bundle_dir) + if not os.path.exists(self.overrides_bundle_path): + os.mkdir(self.overrides_bundle_path) + + if self.overrides_bundle_path not in self.generated_paths: + self.generated_paths.append(self.overrides_bundle_path) for bp_name, overrides in current_app.config['UI_OVERRIDES'].items(): - _overrides_js_template = current_app.jinja_env.from_string(overrides_js_template) - overrides_js_content = _overrides_js_template.render({'overrides': overrides}) - with open(os.path.join(overrides_bundle_dir, f'{bp_name}.js'), 'w+') as f: + template = current_app.jinja_env.from_string(overrides_js_template) + overrides_js_content = template.render({'overrides': overrides}) + overrides_js_path = os.path.join(self.overrides_bundle_path, f'{bp_name}.js') + + with open(overrides_js_path, 'w+') as f: f.write(overrides_js_content) + if overrides_js_path not in self.generated_paths: + self.generated_paths.append(overrides_js_path) + + + def clean(self): + """Clean created webpack project.""" + super().clean() + self.generated_paths.clear() + project = OverridableBundleProject( __name__, diff --git a/tests/test_ui_webpack.py b/tests/test_ui_webpack.py index e1492a6c..c75bed66 100644 --- a/tests/test_ui_webpack.py +++ b/tests/test_ui_webpack.py @@ -12,10 +12,11 @@ def test_overridable_bundle_project_init(app): with app.app_context(): assert proj._project_template_dir.endswith('invenio_assets/assets') assert proj.config_path.endswith('test_build/config.json') - assert proj.overrides_bundle_path == '_overrides' + assert proj.overrides_bundle_path == os.path.join(proj.project_path, 'js/_overrides') assert os.path.exists(proj.package_json_source_path) -def test_overridable_project_entry(app): + +def test_overridable_bundle_project_entry(app): app.config['UI_OVERRIDES'] = { 'test_bp': {'componentA': ['ComponentA', 'components/ComponentA']} } @@ -25,7 +26,7 @@ def test_overridable_project_entry(app): assert entry_points['overrides-test_bp'] == './js/_overrides/test_bp.js' -def test_overridable_project_entry_file(app, fake_manifest): +def test_overridable_bundle_project_entry_file(app, fake_manifest): app.config['UI_OVERRIDES'] = { 'test_bp': {'componentA.item': ['ComponentA', 'components/ComponentA']} } @@ -33,10 +34,9 @@ def test_overridable_project_entry_file(app, fake_manifest): project.create() assert os.path.exists(project.package_json_source_path) - overrides_bundle_dir = os.path.join(project.project_path, f'js/{project.overrides_bundle_path}') - assert os.path.isdir(overrides_bundle_dir) + assert os.path.isdir(project.overrides_bundle_path) - overrides_file_path = os.path.join(overrides_bundle_dir, 'test_bp.js') + overrides_file_path = os.path.join(project.overrides_bundle_path, 'test_bp.js') assert os.path.exists(overrides_file_path) with open(overrides_file_path) as f: overrides_file_path_content = f.read() @@ -46,3 +46,20 @@ def test_overridable_project_entry_file(app, fake_manifest): import ComponentA from 'components/ComponentA'; overrideStore.add('componentA.item', ComponentA);''' + + +def test_overridable_bundle_project_generated_paths(app, fake_manifest): + app.config['UI_OVERRIDES'] = { + 'test_bp1': {'componentA.item': ['ComponentA', 'components/ComponentA']}, + 'test_bp2': {'componentA.item': ['ComponentB', 'components/ComponentB']} + } + + project.clean() + project.create() + + assert len(project.generated_paths) == 3 + assert all([ + os.path.join(project.overrides_bundle_path, path) in project.generated_paths + for path in ['test_bp1.js', 'test_bp2.js'] + ]) + From e8fc38aa6db80f98da3bae1ca7401697959cd9a1 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Wed, 22 Jan 2025 15:22:13 +0100 Subject: [PATCH 10/24] feat(tests): add missing generated_path --- tests/test_ui_webpack.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_ui_webpack.py b/tests/test_ui_webpack.py index c75bed66..18cc2bf7 100644 --- a/tests/test_ui_webpack.py +++ b/tests/test_ui_webpack.py @@ -60,6 +60,6 @@ def test_overridable_bundle_project_generated_paths(app, fake_manifest): assert len(project.generated_paths) == 3 assert all([ os.path.join(project.overrides_bundle_path, path) in project.generated_paths - for path in ['test_bp1.js', 'test_bp2.js'] + for path in ['test_bp1.js', 'test_bp2.js', ''] ]) From 0a65d5e7d5b765751012a037da95e49fd4cbe4bd Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Wed, 22 Jan 2025 15:46:53 +0100 Subject: [PATCH 11/24] feat(webpack): only single generate_path suffices --- oarepo_ui/webpack.py | 5 +---- tests/test_ui_webpack.py | 8 ++------ 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/oarepo_ui/webpack.py b/oarepo_ui/webpack.py index 7d30c005..2136be37 100644 --- a/oarepo_ui/webpack.py +++ b/oarepo_ui/webpack.py @@ -93,6 +93,7 @@ def create(self, force=None): os.mkdir(self.overrides_bundle_path) if self.overrides_bundle_path not in self.generated_paths: + # Mark everything under overrides_bundle_path as generated by us self.generated_paths.append(self.overrides_bundle_path) for bp_name, overrides in current_app.config['UI_OVERRIDES'].items(): @@ -103,10 +104,6 @@ def create(self, force=None): with open(overrides_js_path, 'w+') as f: f.write(overrides_js_content) - if overrides_js_path not in self.generated_paths: - self.generated_paths.append(overrides_js_path) - - def clean(self): """Clean created webpack project.""" super().clean() diff --git a/tests/test_ui_webpack.py b/tests/test_ui_webpack.py index 18cc2bf7..5237643a 100644 --- a/tests/test_ui_webpack.py +++ b/tests/test_ui_webpack.py @@ -57,9 +57,5 @@ def test_overridable_bundle_project_generated_paths(app, fake_manifest): project.clean() project.create() - assert len(project.generated_paths) == 3 - assert all([ - os.path.join(project.overrides_bundle_path, path) in project.generated_paths - for path in ['test_bp1.js', 'test_bp2.js', ''] - ]) - + assert len(project.generated_paths) == 1 + assert project.overrides_bundle_path in project.generated_paths From 5b9af0e6e53f7f616a300e41c0e09c5e0e07e4e5 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Thu, 23 Jan 2025 09:22:52 +0100 Subject: [PATCH 12/24] fix(webpack): generated paths needs to be set sooner --- oarepo_ui/webpack.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/oarepo_ui/webpack.py b/oarepo_ui/webpack.py index 2136be37..14370be6 100644 --- a/oarepo_ui/webpack.py +++ b/oarepo_ui/webpack.py @@ -65,7 +65,8 @@ def overrides_bundle_path(self): @property def generated_paths(self): - return self._generated_paths + # Mark everything under overrides_bundle_path as generated & managed by this bundle project + return [self.overrides_bundle_path] @property @cached @@ -92,10 +93,6 @@ def create(self, force=None): if not os.path.exists(self.overrides_bundle_path): os.mkdir(self.overrides_bundle_path) - if self.overrides_bundle_path not in self.generated_paths: - # Mark everything under overrides_bundle_path as generated by us - self.generated_paths.append(self.overrides_bundle_path) - for bp_name, overrides in current_app.config['UI_OVERRIDES'].items(): template = current_app.jinja_env.from_string(overrides_js_template) overrides_js_content = template.render({'overrides': overrides}) From b2b83099a7e65aec9775428ab2207319b34c6ae1 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Thu, 23 Jan 2025 10:12:00 +0100 Subject: [PATCH 13/24] feat(webpack): add newlines after each import in generated overrides js --- oarepo_ui/webpack.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oarepo_ui/webpack.py b/oarepo_ui/webpack.py index 14370be6..95594be4 100644 --- a/oarepo_ui/webpack.py +++ b/oarepo_ui/webpack.py @@ -10,11 +10,11 @@ {% for key, import_spec in overrides.items() -%} import {{ import_spec[0] }} from '{{ import_spec[1] }}'; -{%- endfor %} +{% endfor %} {% for key, import_spec in overrides.items() -%} overrideStore.add('{{ key }}', {{ import_spec[0] }}); -{%- endfor %} +{% endfor %} ''' From 56191c5901067e1f7f9b2ceceb4fd1ca010a1095 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Thu, 23 Jan 2025 10:39:47 +0100 Subject: [PATCH 14/24] feat(webpack): support named imports in overrides spec --- oarepo_ui/webpack.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/oarepo_ui/webpack.py b/oarepo_ui/webpack.py index 95594be4..746f7b9c 100644 --- a/oarepo_ui/webpack.py +++ b/oarepo_ui/webpack.py @@ -9,8 +9,19 @@ import { overrideStore } from 'react-overridable'; {% for key, import_spec in overrides.items() -%} + +{% if import_spec|length == 3 -%} +{%- set import_type = import_spec[2] -%} +{%- else -%} +{%- set import_type = 'named' -%} +{%- endif -%} + +{%- if import_type == 'default' -%} import {{ import_spec[0] }} from '{{ import_spec[1] }}'; -{% endfor %} +{%- else -%} +import { {{ import_spec[0] }} } from '{{ import_spec[1] }}'; +{%- endif %} +{% endfor -%} {% for key, import_spec in overrides.items() -%} overrideStore.add('{{ key }}', {{ import_spec[0] }}); From 31471a25358473538ae827bc17398dfa44aba3e3 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Thu, 23 Jan 2025 12:09:59 +0100 Subject: [PATCH 15/24] chore(tests): update webpack tests --- tests/test_ui_webpack.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/test_ui_webpack.py b/tests/test_ui_webpack.py index 5237643a..d4342636 100644 --- a/tests/test_ui_webpack.py +++ b/tests/test_ui_webpack.py @@ -28,7 +28,8 @@ def test_overridable_bundle_project_entry(app): def test_overridable_bundle_project_entry_file(app, fake_manifest): app.config['UI_OVERRIDES'] = { - 'test_bp': {'componentA.item': ['ComponentA', 'components/ComponentA']} + 'test_bp': {'componentA.item': ['ComponentA', 'components/ComponentA'], + 'componentB.item': ['DefaultComponent', 'components/DefaultComponent', 'default']} } with app.app_context(): project.create() @@ -43,9 +44,11 @@ def test_overridable_bundle_project_entry_file(app, fake_manifest): assert overrides_file_path_content == ''' import { overrideStore } from 'react-overridable'; -import ComponentA from 'components/ComponentA'; +import { ComponentA } from 'components/ComponentA'; +import DefaultComponent from 'components/DefaultComponent'; -overrideStore.add('componentA.item', ComponentA);''' +overrideStore.add('componentA.item', ComponentA); +overrideStore.add('componentB.item', DefaultComponent);''' def test_overridable_bundle_project_generated_paths(app, fake_manifest): From 520811e2f0b1e148f2a098e4ce511c24605d9df1 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Thu, 23 Jan 2025 12:37:33 +0100 Subject: [PATCH 16/24] fix(tests): fix webpack tests --- tests/test_ui_webpack.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_ui_webpack.py b/tests/test_ui_webpack.py index d4342636..8d1f8de5 100644 --- a/tests/test_ui_webpack.py +++ b/tests/test_ui_webpack.py @@ -46,9 +46,9 @@ def test_overridable_bundle_project_entry_file(app, fake_manifest): import { ComponentA } from 'components/ComponentA'; import DefaultComponent from 'components/DefaultComponent'; - overrideStore.add('componentA.item', ComponentA); -overrideStore.add('componentB.item', DefaultComponent);''' +overrideStore.add('componentB.item', DefaultComponent); +''' def test_overridable_bundle_project_generated_paths(app, fake_manifest): From d2b7e77de214e54f00e430beabfccb31a62a693f Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Fri, 24 Jan 2025 19:28:27 +0100 Subject: [PATCH 17/24] feat(components): add disabled noop component --- .../assets/semantic-ui/js/oarepo_ui/components/Disabled.jsx | 5 +++++ .../assets/semantic-ui/js/oarepo_ui/components/index.js | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/components/Disabled.jsx diff --git a/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/components/Disabled.jsx b/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/components/Disabled.jsx new file mode 100644 index 00000000..60254c22 --- /dev/null +++ b/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/components/Disabled.jsx @@ -0,0 +1,5 @@ +import * as React from 'react'; + +export const Disabled = () => null; + +export default Disabled; diff --git a/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/components/index.js b/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/components/index.js index f11433fc..e3591d58 100644 --- a/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/components/index.js +++ b/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/components/index.js @@ -1,3 +1,4 @@ import "./burgermenu"; import "./clipboard"; -import "./filepreview"; \ No newline at end of file +import "./filepreview"; +export * from "./Disabled"; \ No newline at end of file From 5785890496527036b552a73796e9313c7018c762 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Mon, 27 Jan 2025 10:24:12 +0100 Subject: [PATCH 18/24] feat(components): refactor using UIComponent class --- oarepo_ui/ui/component.py | 50 +++++++++++++++++++++++++++++++++++++++ oarepo_ui/webpack.py | 25 +++++++------------- 2 files changed, 59 insertions(+), 16 deletions(-) create mode 100644 oarepo_ui/ui/component.py diff --git a/oarepo_ui/ui/component.py b/oarepo_ui/ui/component.py new file mode 100644 index 00000000..dbd01f95 --- /dev/null +++ b/oarepo_ui/ui/component.py @@ -0,0 +1,50 @@ +from typing import Optional, Dict + + +class UIComponent: + """Represents a UI component specification used to override existing UI components. + + Attributes: + import_name (str): + The name of the component. + import_path (str): + JS module path where the component is imported from. + import_mode (str): + The mode of import, either 'default' or 'named'. + props (dict, optional): + Additional key-value string properties used to parametrize + the component before registering it to overrides store. + """ + + def __init__(self, import_name: str, import_path: str, import_mode: str = 'named', + props: Optional[Dict[str, str]] = None): + """Initialize a UIComponentOverride instance.""" + self.import_name = import_name + self.import_path = import_path + self.import_mode = import_mode + self.props = props + + @property + def name(self) -> str: + """Name of the component.""" + if self.props: + return f"{self.import_name}WithProps" + + return self.import_name + + @property + def import_statement(self) -> str: + """JS import statement string to import the component.""" + import_name = self.import_name if self.import_mode == 'default' else f"{{ {self.import_name} }}" + + return f"import {import_name} from '{self.import_path}';" + + @property + def parametrize_statement(self) -> str | None: + """JS statement to parametrize the component with props.""" + if self.props: + js_props = ", ".join(f"{key}: {repr(value)}" for key, value in self.props.items()) + return f"const {self.name} = parametrize({self.import_name}, {{ {js_props} }});" + + +DisabledComponent = UIComponent("Disabled", "@js/oarepo_ui/components/Disabled") diff --git a/oarepo_ui/webpack.py b/oarepo_ui/webpack.py index 746f7b9c..21e7441f 100644 --- a/oarepo_ui/webpack.py +++ b/oarepo_ui/webpack.py @@ -6,25 +6,18 @@ from pywebpack.helpers import cached overrides_js_template = ''' -import { overrideStore } from 'react-overridable'; +import { overrideStore, parametrize } from 'react-overridable'; -{% for key, import_spec in overrides.items() -%} - -{% if import_spec|length == 3 -%} -{%- set import_type = import_spec[2] -%} -{%- else -%} -{%- set import_type = 'named' -%} -{%- endif -%} +{% for key, component in overrides.items() -%} +{{ component.import_statement | safe }} +{% endfor %} -{%- if import_type == 'default' -%} -import {{ import_spec[0] }} from '{{ import_spec[1] }}'; -{%- else -%} -import { {{ import_spec[0] }} } from '{{ import_spec[1] }}'; -{%- endif %} -{% endfor -%} +{%- for key, component in overrides.items() -%} +{%- if component.props -%}{{ component.parametrize_statement | safe }}{%- endif -%} +{%- endfor %} -{% for key, import_spec in overrides.items() -%} -overrideStore.add('{{ key }}', {{ import_spec[0] }}); +{% for key, component in overrides.items() -%} +overrideStore.add('{{ key }}', {{ component.name }}); {% endfor %} ''' From 550e28d36a470f3ae361ff503920cdf2a3f49b01 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Mon, 27 Jan 2025 10:30:38 +0100 Subject: [PATCH 19/24] fix(tests): update tests with UIComponent --- tests/test_ui_webpack.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_ui_webpack.py b/tests/test_ui_webpack.py index 8d1f8de5..7201a539 100644 --- a/tests/test_ui_webpack.py +++ b/tests/test_ui_webpack.py @@ -1,4 +1,6 @@ import os + +from oarepo_ui.ui.component import UIComponent from oarepo_ui.webpack import OverridableBundleProject, project @@ -53,8 +55,8 @@ def test_overridable_bundle_project_entry_file(app, fake_manifest): def test_overridable_bundle_project_generated_paths(app, fake_manifest): app.config['UI_OVERRIDES'] = { - 'test_bp1': {'componentA.item': ['ComponentA', 'components/ComponentA']}, - 'test_bp2': {'componentA.item': ['ComponentB', 'components/ComponentB']} + 'test_bp1': {'componentA.item': UIComponent('ComponentA', 'components/ComponentA')}, + 'test_bp2': {'componentA.item': UIComponent('ComponentB', 'components/ComponentB')} } project.clean() From 99c23681e0db1b57ff1d8354951df3c61c81ca9e Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Mon, 27 Jan 2025 10:31:47 +0100 Subject: [PATCH 20/24] fix(tests): update tests with UIComponent --- tests/test_ui_webpack.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_ui_webpack.py b/tests/test_ui_webpack.py index 7201a539..500cb00e 100644 --- a/tests/test_ui_webpack.py +++ b/tests/test_ui_webpack.py @@ -20,7 +20,7 @@ def test_overridable_bundle_project_init(app): def test_overridable_bundle_project_entry(app): app.config['UI_OVERRIDES'] = { - 'test_bp': {'componentA': ['ComponentA', 'components/ComponentA']} + 'test_bp': {'componentA': UIComponent('ComponentA', 'components/ComponentA')} } with app.app_context(): entry_points = project.entry @@ -30,8 +30,8 @@ def test_overridable_bundle_project_entry(app): def test_overridable_bundle_project_entry_file(app, fake_manifest): app.config['UI_OVERRIDES'] = { - 'test_bp': {'componentA.item': ['ComponentA', 'components/ComponentA'], - 'componentB.item': ['DefaultComponent', 'components/DefaultComponent', 'default']} + 'test_bp': {'componentA.item': UIComponent('ComponentA', 'components/ComponentA'), + 'componentB.item': UIComponent('DefaultComponent', 'components/DefaultComponent', 'default')} } with app.app_context(): project.create() From c86b3b8de7d0ef3567122b247f23ec8fedb7b8ea Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Mon, 27 Jan 2025 10:59:34 +0100 Subject: [PATCH 21/24] fix(tests): add missing import --- tests/test_ui_webpack.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_ui_webpack.py b/tests/test_ui_webpack.py index 500cb00e..49a3e52a 100644 --- a/tests/test_ui_webpack.py +++ b/tests/test_ui_webpack.py @@ -44,10 +44,12 @@ def test_overridable_bundle_project_entry_file(app, fake_manifest): with open(overrides_file_path) as f: overrides_file_path_content = f.read() assert overrides_file_path_content == ''' -import { overrideStore } from 'react-overridable'; +import { overrideStore, parametrize } from 'react-overridable'; import { ComponentA } from 'components/ComponentA'; import DefaultComponent from 'components/DefaultComponent'; + + overrideStore.add('componentA.item', ComponentA); overrideStore.add('componentB.item', DefaultComponent); ''' From 6dbec303e324d2debb30befe4b2a0afdbbd4f09a Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Wed, 29 Jan 2025 10:25:31 +0100 Subject: [PATCH 22/24] chore(cleanup): remove now deprecated overridable-registry --- oarepo_ui/templates/oarepo_ui/javascript.html | 1 - .../js/oarepo_ui/overridable-registry.js | 33 ------------------- 2 files changed, 34 deletions(-) delete mode 100644 oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/overridable-registry.js diff --git a/oarepo_ui/templates/oarepo_ui/javascript.html b/oarepo_ui/templates/oarepo_ui/javascript.html index 464e2654..23cddd27 100644 --- a/oarepo_ui/templates/oarepo_ui/javascript.html +++ b/oarepo_ui/templates/oarepo_ui/javascript.html @@ -1,5 +1,4 @@ {% include "invenio_theme/javascript.html" %} -{{ webpack['oarepo-overridable-registry.js'] }} {{ webpack['oarepo_ui_theme.js'] }} {{ webpack['oarepo_ui_components.js'] }} diff --git a/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/overridable-registry.js b/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/overridable-registry.js deleted file mode 100644 index 73406867..00000000 --- a/oarepo_ui/theme/assets/semantic-ui/js/oarepo_ui/overridable-registry.js +++ /dev/null @@ -1,33 +0,0 @@ -import { overrideStore } from "react-overridable"; - -// get all files below /templates/overridableRegistry that end with mapping.js. -// The files shall be in a subfolder, in order to prevent clashing between mapping.js -// from different libraries. each mapping.js file shall have a default export -// that is an object with signature {"component-id": Component} the files -// will be prioritized by leading prefix (e.g. 10-mapping.js will be processed -// before 20-mapping.js). mapping.js without prefix will have lowest priority. - -const requireMappingFiles = require.context( - "/templates/overridableRegistry/", - true, - /mapping.js$/ -); - -requireMappingFiles - .keys() - .map((fileName) => { - const match = fileName.match(/\/(\d+)-mapping.js$/); - const priority = match ? parseInt(match[1], 10) : 0; - return { fileName, priority }; - }) - .sort((a, b) => a.priority - b.priority) - .forEach(({ fileName }) => { - const module = requireMappingFiles(fileName); - if (!module.default) { - console.error(`Mapping file ${fileName} does not have a default export.`); - } else { - for (const [key, value] of Object.entries(module.default)) { - overrideStore.add(key, value); - } - } - }); From c9807c55f30fd25092ad7cded3c7c5e4363f2647 Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Wed, 29 Jan 2025 14:24:18 +0100 Subject: [PATCH 23/24] refactor(components): json dumps instead of repr --- oarepo_ui/ui/component.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oarepo_ui/ui/component.py b/oarepo_ui/ui/component.py index dbd01f95..1bad98c7 100644 --- a/oarepo_ui/ui/component.py +++ b/oarepo_ui/ui/component.py @@ -1,3 +1,4 @@ +import json from typing import Optional, Dict @@ -43,7 +44,7 @@ def import_statement(self) -> str: def parametrize_statement(self) -> str | None: """JS statement to parametrize the component with props.""" if self.props: - js_props = ", ".join(f"{key}: {repr(value)}" for key, value in self.props.items()) + js_props = ", ".join(f"{key}: {json.dumps(value)}" for key, value in self.props.items()) return f"const {self.name} = parametrize({self.import_name}, {{ {js_props} }});" From 8860504b2fef14cc036f423b7a6093a58405974b Mon Sep 17 00:00:00 2001 From: Miroslav Bauer Date: Wed, 29 Jan 2025 19:36:21 +0100 Subject: [PATCH 24/24] fix: remove overridable registry entry --- oarepo_ui/theme/webpack.py | 4 ---- oarepo_ui/ui/__init__.py | 6 ++++++ setup.cfg | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 oarepo_ui/ui/__init__.py diff --git a/oarepo_ui/theme/webpack.py b/oarepo_ui/theme/webpack.py index da93a3bd..82b9cf85 100644 --- a/oarepo_ui/theme/webpack.py +++ b/oarepo_ui/theme/webpack.py @@ -78,10 +78,6 @@ "oarepo_ui_components": "./js/oarepo_ui/custom-components.js", "copy_to_clipboard": "./js/oarepo_ui/components/clipboard.js", "record_export": "./js/oarepo_ui/components/record-export.js", - # there is already overridable-registry entry point in RDM which - # we are inheriting after installing RDM as a dependency - # so this avoids name clash - "oarepo-overridable-registry": "./js/oarepo_ui/overridable-registry.js", }, dependencies=dependencies, devDependencies={"eslint-plugin-i18next": "^6.0.3"}, diff --git a/oarepo_ui/ui/__init__.py b/oarepo_ui/ui/__init__.py new file mode 100644 index 00000000..2d5e4ad8 --- /dev/null +++ b/oarepo_ui/ui/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) 2025 CESNET +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +"""OARepo UI package.""" diff --git a/setup.cfg b/setup.cfg index 144b7687..9d66cc24 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = oarepo-ui -version = 5.2.32 +version = 5.2.33 description = UI module for invenio 3.5+ long_description = file: README.md long_description_content_type = text/markdown