From 75cceef27f36b6199d5e1d680d503ed2d0e03d46 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Fri, 13 Dec 2024 14:39:16 -0500 Subject: [PATCH 1/8] feat: Send message when cancel button is clicked on xblock_v2 iframe --- common/templates/xblock_v2/xblock_iframe.html | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/common/templates/xblock_v2/xblock_iframe.html b/common/templates/xblock_v2/xblock_iframe.html index 8b733373bd82..bf3326eb1986 100644 --- a/common/templates/xblock_v2/xblock_iframe.html +++ b/common/templates/xblock_v2/xblock_iframe.html @@ -322,5 +322,12 @@ window.addEventListener('load', blockFrameJS); + From be646dfe9b40b4efc7111c2237a8bc07c8215b65 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Mon, 16 Dec 2024 12:23:01 -0500 Subject: [PATCH 2/8] fix: add notify() to render in xblock_v2 to fix save block --- common/templates/xblock_v2/xblock_iframe.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/common/templates/xblock_v2/xblock_iframe.html b/common/templates/xblock_v2/xblock_iframe.html index bf3326eb1986..853c05605344 100644 --- a/common/templates/xblock_v2/xblock_iframe.html +++ b/common/templates/xblock_v2/xblock_iframe.html @@ -215,6 +215,13 @@ } return url; }, + notify: () => { + /** + * Used in `studio_view` + * + * TODO: Do nothing for now + * **/ + } }; /** @@ -328,6 +335,10 @@ event.preventDefault(); window.parent.postMessage('cancel-clicked', '*'); }); + document.querySelector('.save-button').addEventListener('click', function() { + event.preventDefault(); + window.parent.postMessage('save-clicked', '*'); + }); From 0025c19848ba3f6ec5393825a95650078158edff Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Thu, 9 Jan 2025 18:03:48 -0500 Subject: [PATCH 3/8] refactor: Update xblock_iframe.html to intercep save/canel button events on block render --- common/templates/xblock_v2/xblock_iframe.html | 23 ++++++++++--------- .../core/djangoapps/xblock/rest_api/views.py | 1 + 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/common/templates/xblock_v2/xblock_iframe.html b/common/templates/xblock_v2/xblock_iframe.html index 853c05605344..5a3cd54446a8 100644 --- a/common/templates/xblock_v2/xblock_iframe.html +++ b/common/templates/xblock_v2/xblock_iframe.html @@ -265,6 +265,18 @@ const blockJS = { element }; callback(blockJS); } + + if ('{{ view_name | safe }}' === 'studio_view') { + // Used when rendering the `studio_view`, in order to intercept and handle the cancel/save button event + document.querySelector('.cancel-button').addEventListener('click', function() { + event.preventDefault(); + window.parent.postMessage('cancel-clicked', '*'); + }); + document.querySelector('.save-button').addEventListener('click', function() { + event.preventDefault(); + window.parent.postMessage('save-clicked', '*'); + }); + } } // Recursively initialize the JavaScript code of each XBlock: @@ -329,16 +341,5 @@ window.addEventListener('load', blockFrameJS); - diff --git a/openedx/core/djangoapps/xblock/rest_api/views.py b/openedx/core/djangoapps/xblock/rest_api/views.py index edcbf22e0d3d..36764dda0030 100644 --- a/openedx/core/djangoapps/xblock/rest_api/views.py +++ b/openedx/core/djangoapps/xblock/rest_api/views.py @@ -122,6 +122,7 @@ def embed_block_view(request, usage_key: UsageKeyV2, view_name: str): 'fragment': fragment, 'handler_urls_json': json.dumps(handler_urls), 'lms_root_url': lms_root_url, + 'view_name': view_name, 'is_development': settings.DEBUG, } response = render(request, 'xblock_v2/xblock_iframe.html', context, content_type='text/html') From f365c512175c7c2c35870c3dad4b4bb5880ec3b8 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Fri, 10 Jan 2025 11:38:14 -0500 Subject: [PATCH 4/8] feat: Send block updated event on xblock_handler when is studio_submit --- openedx/core/djangoapps/xblock/rest_api/views.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openedx/core/djangoapps/xblock/rest_api/views.py b/openedx/core/djangoapps/xblock/rest_api/views.py index 36764dda0030..0df4b4c2ca82 100644 --- a/openedx/core/djangoapps/xblock/rest_api/views.py +++ b/openedx/core/djangoapps/xblock/rest_api/views.py @@ -212,6 +212,12 @@ def xblock_handler( block = load_block(usage_key, user, version=version) # Run the handler, and save any resulting XBlock field value changes: response_webob = block.handle(handler_name, request_webob, suffix) + + if handler_name == "studio_submit": + # Signal that we've modified this block + context_impl = get_learning_context_impl(usage_key) + context_impl.send_block_updated_event(usage_key) + response = webob_to_django_response(response_webob) return response From 57c76fa852958fb3d01ba71b6d178864cc533fc3 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Fri, 10 Jan 2025 11:55:00 -0500 Subject: [PATCH 5/8] feat: Update notify function to send save-end event and error event --- common/templates/xblock_v2/xblock_iframe.html | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/common/templates/xblock_v2/xblock_iframe.html b/common/templates/xblock_v2/xblock_iframe.html index 5a3cd54446a8..43ba1ff07eb8 100644 --- a/common/templates/xblock_v2/xblock_iframe.html +++ b/common/templates/xblock_v2/xblock_iframe.html @@ -215,12 +215,15 @@ } return url; }, - notify: () => { - /** - * Used in `studio_view` - * - * TODO: Do nothing for now - * **/ + notify: (eventName, data) => { + /** + * Used in `studio_view` to notify events and errors + **/ + if (eventName == 'save' && data.state == 'end') { + window.parent.postMessage('save-end', '*'); + } else if (eventName == 'error') { + window.parent.postMessage('error', '*'); + } } }; @@ -267,15 +270,11 @@ } if ('{{ view_name | safe }}' === 'studio_view') { - // Used when rendering the `studio_view`, in order to intercept and handle the cancel/save button event + // Used when rendering the `studio_view`, in order to intercept and handle the cancel button event document.querySelector('.cancel-button').addEventListener('click', function() { event.preventDefault(); window.parent.postMessage('cancel-clicked', '*'); }); - document.querySelector('.save-button').addEventListener('click', function() { - event.preventDefault(); - window.parent.postMessage('save-clicked', '*'); - }); } } From 3b2268d0d9eec75960fc615ea9faeafbe2fc3a88 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Tue, 14 Jan 2025 12:51:06 -0500 Subject: [PATCH 6/8] refactor: Added send_block_updated_event in save_block --- openedx/core/djangoapps/xblock/rest_api/views.py | 10 ---------- .../djangoapps/xblock/runtime/learning_core_runtime.py | 4 ++++ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/openedx/core/djangoapps/xblock/rest_api/views.py b/openedx/core/djangoapps/xblock/rest_api/views.py index 0df4b4c2ca82..a1fbd1e062a6 100644 --- a/openedx/core/djangoapps/xblock/rest_api/views.py +++ b/openedx/core/djangoapps/xblock/rest_api/views.py @@ -212,12 +212,6 @@ def xblock_handler( block = load_block(usage_key, user, version=version) # Run the handler, and save any resulting XBlock field value changes: response_webob = block.handle(handler_name, request_webob, suffix) - - if handler_name == "studio_submit": - # Signal that we've modified this block - context_impl = get_learning_context_impl(usage_key) - context_impl.send_block_updated_event(usage_key) - response = webob_to_django_response(response_webob) return response @@ -329,10 +323,6 @@ def post(self, request, usage_key, version: LatestVersion | int = LatestVersion. # Save after the callback so any changes made in the callback will get persisted. block.save() - # Signal that we've modified this block - context_impl = get_learning_context_impl(usage_key) - context_impl.send_block_updated_event(usage_key) - block_dict = { "id": str(block.usage_key), "display_name": get_block_display_name(block), # note this is also present in metadata diff --git a/openedx/core/djangoapps/xblock/runtime/learning_core_runtime.py b/openedx/core/djangoapps/xblock/runtime/learning_core_runtime.py index 44dedcf42874..c3885fbf11cc 100644 --- a/openedx/core/djangoapps/xblock/runtime/learning_core_runtime.py +++ b/openedx/core/djangoapps/xblock/runtime/learning_core_runtime.py @@ -314,6 +314,10 @@ def save_block(self, block): ) self.authored_data_store.mark_unchanged(block) + # Signal that we've modified this block + learning_context = get_learning_context_impl(usage_key) + learning_context.send_block_updated_event(usage_key) + def _get_component_from_usage_key(self, usage_key): """ Note that Components aren't ever really truly deleted, so this will From c05755cee09b3517a839c77f6858909ae17c5e58 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Tue, 14 Jan 2025 13:34:20 -0500 Subject: [PATCH 7/8] refactor: Update code to send all events in notify using xblock-event message --- common/templates/xblock_v2/xblock_iframe.html | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/common/templates/xblock_v2/xblock_iframe.html b/common/templates/xblock_v2/xblock_iframe.html index 43ba1ff07eb8..5e3aac965e2e 100644 --- a/common/templates/xblock_v2/xblock_iframe.html +++ b/common/templates/xblock_v2/xblock_iframe.html @@ -219,11 +219,11 @@ /** * Used in `studio_view` to notify events and errors **/ - if (eventName == 'save' && data.state == 'end') { - window.parent.postMessage('save-end', '*'); - } else if (eventName == 'error') { - window.parent.postMessage('error', '*'); - } + window.parent.postMessage({ + type: 'xblock-event', + eventName, + data, + }, '*'); } }; @@ -273,7 +273,10 @@ // Used when rendering the `studio_view`, in order to intercept and handle the cancel button event document.querySelector('.cancel-button').addEventListener('click', function() { event.preventDefault(); - window.parent.postMessage('cancel-clicked', '*'); + window.parent.postMessage({ + type: 'xblock-event', + eventName: 'cancel-clicked', + }, '*'); }); } } From 9f86ddc38a76b96d59eeddb3d436e6245eeaf33c Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Tue, 14 Jan 2025 14:40:08 -0500 Subject: [PATCH 8/8] refactor: Update preventDefault of events of cancel and save buttons --- common/templates/xblock_v2/xblock_iframe.html | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/common/templates/xblock_v2/xblock_iframe.html b/common/templates/xblock_v2/xblock_iframe.html index 5e3aac965e2e..07d81b962a65 100644 --- a/common/templates/xblock_v2/xblock_iframe.html +++ b/common/templates/xblock_v2/xblock_iframe.html @@ -270,14 +270,22 @@ } if ('{{ view_name | safe }}' === 'studio_view') { - // Used when rendering the `studio_view`, in order to intercept and handle the cancel button event - document.querySelector('.cancel-button').addEventListener('click', function() { - event.preventDefault(); - window.parent.postMessage({ - type: 'xblock-event', - eventName: 'cancel-clicked', - }, '*'); - }); + // Used when rendering the `studio_view`, in order to avoid open a new tab on click cancel or save + const selectors = [ + '.cancel-button', + '.save-button', + '.action-cancel', + '.action-save', + ]; + + for (const selector of selectors) { + const queryObject = document.querySelector(selector); + if (queryObject) { + queryObject.addEventListener('click', function() { + event.preventDefault(); + }); + } + } } }