diff --git a/modules/weko-gridlayout/tests/test_admin.py b/modules/weko-gridlayout/tests/test_admin.py index 35beaa050a..8255c61044 100644 --- a/modules/weko-gridlayout/tests/test_admin.py +++ b/modules/weko-gridlayout/tests/test_admin.py @@ -212,6 +212,31 @@ def test_index_WidgetDesign(i18n_app, view_instance): pass +# WidgetDesign.preview_view +def test_preview_view_WidgetDesign(i18n_app, view_instance): + test = WidgetDesign() + test.admin = MagicMock() + i18n_app.config["WEKO_THEME_DEFAULT_COMMUNITY"] = "0" + i18n_app.config["WEKO_THEME_PREVIEW_WIDGET_DESIGN"] = ( + "weko_theme/preview_widget_design.html" + ) + return_data = { + "community_id": "", + "detail_condition": "", + "width": "3", + "height": "", + "index_link_list": [], + "index_link_enabled": False, + "community": None, + "display_facet_search": False, + "display_index_tree": True, + "display_community": True, + } + with patch("weko_gridlayout.admin.get_weko_contents", return_value=return_data): + with patch("flask_admin.base.render_template", return_value="dummy"): + assert test.preview_view() + + # WidgetSettingView.index_view ~ ERROR def test_index_view_WidgetSettingView(i18n_app, view_instance): assert view_instance.index_view() != None diff --git a/modules/weko-gridlayout/tests/test_services.py b/modules/weko-gridlayout/tests/test_services.py index ea5a88aaa6..374ae519f0 100644 --- a/modules/weko-gridlayout/tests/test_services.py +++ b/modules/weko-gridlayout/tests/test_services.py @@ -287,6 +287,85 @@ def test_get_widget_list(i18n_app, widget_items): assert WidgetDesignServices.get_widget_list(repository_id, default_language) +# def get_widget_item_list(cls, repository_id): +def test_get_widget_item_list(i18n_app, widget_items): + repository_id = "Root Index" + WEKO_GRIDLAYOUT_ACCESS_COUNTER_TYPE = "Access counter" + WEKO_GRIDLAYOUT_NOTICE_TYPE = "Notice" + return_data1 = { + "widget_id": 1, + "repository_id": "Root Index", + "widget_type": WEKO_GRIDLAYOUT_ACCESS_COUNTER_TYPE, + "is_enabled": True, + "is_deleted": False, + "updated": 1772664727.379901, + "settings": { + "background_color": "test", + "label_enable": True, + "theme": "default", + "frame_border_color": "test", + "border_style": "double", + "label_text_color": "test", + "label_color": "test", + "access_counter": "0", + "following_message": "test", + "other_message": "test", + "preceding_message": "test", + "count_start_date": "test", + "multiLangSetting": { + "ja": "ja" + } + } + } + return_data2 = { + "widget_id":2, + "repository_id": "Root Index", + "widget_type": WEKO_GRIDLAYOUT_NOTICE_TYPE, + "is_enabled": True, + "is_deleted": False, + "updated": 1772664727.379901, + "settings": { + "background_color": "test", + "border_style": "double", + "frame_border_color": "test", + "hide_the_rest": "None", + "label_color": "test", + "label_enable": True, + "label_text_color": "test", + "read_more": "None", + "theme": "default", + "multiLangSetting": { + "ja": "ja" + } + } + } + with patch( + "weko_gridlayout.services.WidgetItemServices.get_widget_data_by_widget_id", + return_value=return_data1, + ): + assert WidgetDesignServices.get_widget_item_list(repository_id) + + return_data1["settings"]["multiLangSetting"] = {"en": "en"} + assert WidgetDesignServices.get_widget_item_list(repository_id) + + return_data1["settings"]["multiLangSetting"] = {"xx": "xx"} + assert WidgetDesignServices.get_widget_item_list(repository_id) + + return_data1["settings"]["multiLangSetting"] = None + assert WidgetDesignServices.get_widget_item_list(repository_id) + + with patch('weko_gridlayout.services.isinstance', side_effect=Exception('')): + assert WidgetDesignServices.get_widget_item_list(repository_id) + with patch( + "weko_gridlayout.services.WidgetItemServices.get_widget_data_by_widget_id", + return_value=return_data2, + ): + assert WidgetDesignServices.get_widget_item_list(repository_id) + with patch("weko_gridlayout.services.WidgetItem.query") as mock_query: + mock_query.return_value.filter_by.return_value.all.return_value = None + assert WidgetDesignServices.get_widget_item_list(repository_id) + + # def get_widget_preview(cls, repository_id, default_language, def test_get_widget_preview(i18n_app, widget_item): repository_id = "Root Index" diff --git a/modules/weko-gridlayout/tests/test_views.py b/modules/weko-gridlayout/tests/test_views.py index 678f3b494e..3e6fc30585 100644 --- a/modules/weko-gridlayout/tests/test_views.py +++ b/modules/weko-gridlayout/tests/test_views.py @@ -485,6 +485,16 @@ def test_delete_widget_item(client, users): assert res.status_code == 200 +# def get_widget_item_list() +def test_get_widget_item_list(client, users): + login_user_via_session(client=client, email=users[2]['obj'].email) + res = client.get( + url_for("weko_gridlayout_api.get_widget_item_list"), + headers={"Content-Type": "application/json"} + ) + assert res.status_code == 200 + + # def get_account_role(): def test_get_account_role(client, users): login_user_via_session(client=client, email=users[2]['obj'].email) diff --git a/modules/weko-gridlayout/weko_gridlayout/admin.py b/modules/weko-gridlayout/weko_gridlayout/admin.py index e212543682..18b51edc54 100644 --- a/modules/weko-gridlayout/weko_gridlayout/admin.py +++ b/modules/weko-gridlayout/weko_gridlayout/admin.py @@ -40,6 +40,9 @@ from jinja2 import contextfunction from sqlalchemy import func from wtforms.fields import StringField +from weko_theme.utils import get_design_layout, \ + get_weko_contents, has_widget_design +from invenio_i18n.ext import current_i18n from . import config from .models import WidgetItem, WidgetMultiLangData @@ -56,6 +59,23 @@ def index(self): current_app.config["WEKO_GRIDLAYOUT_ADMIN_WIDGET_DESIGN"] ) + @expose('/preview/') + def preview_view(self): + # For preview page, always use main layout + page, render_widgets = get_design_layout( + current_app.config['WEKO_THEME_DEFAULT_COMMUNITY']) + render_header_footer = has_widget_design( + current_app.config['WEKO_THEME_DEFAULT_COMMUNITY'], + current_i18n.language) + page = None + + return self.render( + current_app.config["WEKO_THEME_PREVIEW_WIDGET_DESIGN"], + page=page, + render_widgets=render_widgets, + render_header_footer=render_header_footer, + **get_weko_contents(request.args)) + class WidgetSettingView(ModelView): """Widget Setting admin view.""" diff --git a/modules/weko-gridlayout/weko_gridlayout/services.py b/modules/weko-gridlayout/weko_gridlayout/services.py index 29cd59ef48..7923778146 100644 --- a/modules/weko-gridlayout/weko_gridlayout/services.py +++ b/modules/weko-gridlayout/weko_gridlayout/services.py @@ -501,6 +501,60 @@ def get_widget_list(cls, repository_id, default_language): return result + @classmethod + def get_widget_item_list(cls, repository_id): + """Get Widget Item list. + + :param repository_id: Identifier of the repository. + :return: Widget Item list. + """ + result = { + "data": {}, + "error": "" + } + try: + with db.session.no_autoflush: + widget_item_list = WidgetItem.query.filter_by( + repository_id=str(repository_id), is_enabled=True, + is_deleted=False + ).all() + current_lang = current_i18n.language + if isinstance(widget_item_list, list): + for widget_item in widget_item_list: + data = dict() + data_display = dict() + widget_item_data = \ + WidgetItemServices.get_widget_data_by_widget_id( + widget_item.widget_id) + settings = widget_item_data.get('settings') + settings["widget_id"] = widget_item_data.get('widget_id') + settings["id"] = widget_item_data.get('repository_id') + settings["type"] = widget_item_data.get('widget_type') + if settings.get('type') == WEKO_GRIDLAYOUT_ACCESS_COUNTER_TYPE: + today = date.today().strftime("%Y-%m-%d") + settings['created_date'] = today + languages = settings.get("multiLangSetting") + if (isinstance(languages, dict) + and current_lang is not None): + if languages.get(current_lang): + data_display = languages[current_lang] + elif languages.get('en'): + data_display = languages['en'] + else: + data_display["label"] = \ + WEKO_GRIDLAYOUT_DEFAULT_WIDGET_LABEL + else: + data_display["label"] = \ + WEKO_GRIDLAYOUT_DEFAULT_WIDGET_LABEL + settings["multiLangSetting"] = data_display + settings["name"] = data_display.get('label') + data["widget-settings"] = settings + result["data"][str(widget_item_data.get('widget_id'))] = data + except Exception as e: + result["error"] = str(e) + + return result + # TODO: Change to allow specifying which model to retrieve from @classmethod def get_widget_preview(cls, repository_id, default_language, diff --git a/modules/weko-gridlayout/weko_gridlayout/static/js/weko_gridlayout/widget.design.js b/modules/weko-gridlayout/weko_gridlayout/static/js/weko_gridlayout/widget.design.js index 2c98a162d6..478ccb4a9c 100644 --- a/modules/weko-gridlayout/weko_gridlayout/static/js/weko_gridlayout/widget.design.js +++ b/modules/weko-gridlayout/weko_gridlayout/static/js/weko_gridlayout/widget.design.js @@ -22,6 +22,8 @@ const GET_SYSTEM_LANG_URL = '/api/admin/get_system_lang'; const SAVE_WIDGET_LAYOUT_SETTING_URL = "/api/admin/save_widget_layout_setting"; const LOAD_WIDGET_DESIGN_SETTING_URL = "/api/admin/load_widget_design_setting"; const LOAD_WIDGET_DESIGN_PAGE_SETTING_URL = '/api/admin/load_widget_design_page_setting/'; +const WIDGET_DESIGN_PREVIEW_URL = '/admin/widgetdesign/preview/'; +const GET_WIDGET_DETAIL = '/api/admin/get_widget_item_list' let windowObjectReference = null; let previousUrl; /* global variable that will store the @@ -870,8 +872,12 @@ class ButtonLayout extends React.Component { "margin-left": "-15px" }; + this.previewStyle = { + "margin-right": "10px" + }; this.handleSave = this.handleSave.bind(this); this.handleCancel = this.handleCancel.bind(this); + this.handlePreview = this.handlePreview.bind(this); } handleSave() { @@ -913,6 +919,86 @@ class ButtonLayout extends React.Component { }); } + handlePreview() { + console.log(this.props.repositoryId) + $.ajax({ + url: GET_WIDGET_DETAIL, + type: 'GET', + dataType: "json", + contentType: 'application/json', + data: { + repository_id: this.props.repositoryId + }, + success: function (res) { + let widgetDetails = res.data + this.serializedData = _.map($('.grid-stack > .grid-stack-item:visible'), function (el) { + el = $(el); + let node = el.data('_gridstack_node'); + let id = el.data("id"); + let type = el.data("type"); + let widget_id = el.data("widget_id"); + let created_date = el.data("created_date"); + if (!id) { + return; + } else if (MAIN_CONTENT_TYPE === type) { + isHasMainContent = true; + } + + let settingWidgetDetail = {} + if (widget_id) { + const widgetDetail = widgetDetails[widget_id]["widget-settings"] + settingWidgetDetail = { + ...widgetDetail + } + } + + let result = { + x: node.x, + y: node.y, + width: node.width, + height: node.height, + ...settingWidgetDetail + }; + if (created_date) { + result.created_date = created_date; + } + return result; + }, this); + var widgetDesignData = this.serializedData.filter(function (el) { + return el != null; + }); + let repositoryId = document.getElementById("repository-id").value; + let pageListSelectElement = document.getElementById("pages-list-select"); + let pageId = "0"; + let isMainLayout = true; + if (pageListSelectElement && pageListSelectElement.options) { + pageId = pageListSelectElement.value; + let option = pageListSelectElement.options[pageListSelectElement.selectedIndex]; + if (option.dataset) { + isMainLayout = (String(option.dataset.isMainLayout) === "true"); + } + } + if (String(repositoryId) === "0") { + alertModal("Please select the Repository."); + return false; + } else if (!widgetDesignData) { + //alert('Please add Widget to Preview panel.'); + alertModal("Please add Widget to Preview panel."); + return false; + } + + localStorage.setItem("widget_setting_data", JSON.stringify({ + "widget-settings": widgetDesignData, + error: "" + })); + window.open(WIDGET_DESIGN_PREVIEW_URL, '_blank'); + }, + error: function (error) { + console.log(error); + } + }); + } + render() { return (
@@ -921,6 +1007,12 @@ class ButtonLayout extends React.Component {