diff --git a/openedx/core/djangoapps/content/search/documents.py b/openedx/core/djangoapps/content/search/documents.py index 0dd02683ceea..f18ae660328a 100644 --- a/openedx/core/djangoapps/content/search/documents.py +++ b/openedx/core/djangoapps/content/search/documents.py @@ -76,6 +76,12 @@ class Fields: # Structural XBlocks may use this one day to indicate how many child blocks they ocntain. num_children = "num_children" + # Publish status can be on of: + # "published", + # "modified" (for blocks that were published but have been modified since), + # "never" (for never-published blocks). + publish_status = "publish_status" + # Published data (dictionary) of this object published = "published" published_display_name = "display_name" @@ -96,6 +102,15 @@ class DocType: collection = "collection" +class PublishStatus: + """ + Values for the 'publish_status' field on each doc in the search index + """ + never = "never" + published = "published" + modified = "modified" + + def meili_id_from_opaque_key(usage_key: UsageKey) -> str: """ Meilisearch requires each document to have a primary key that's either an @@ -376,11 +391,15 @@ def searchable_doc_for_library_block(xblock_metadata: lib_api.LibraryXBlockMetad library_name = lib_api.get_library(xblock_metadata.usage_key.context_key).title block = xblock_api.load_block(xblock_metadata.usage_key, user=None) + publish_status = PublishStatus.published try: block_published = xblock_api.load_block(xblock_metadata.usage_key, user=None, version=LatestVersion.PUBLISHED) + if xblock_metadata.last_published and xblock_metadata.last_published < xblock_metadata.modified: + publish_status = PublishStatus.modified except NotFound: # Never published block_published = None + publish_status = PublishStatus.never doc = searchable_doc_for_usage_key(xblock_metadata.usage_key) doc.update({ @@ -389,6 +408,7 @@ def searchable_doc_for_library_block(xblock_metadata: lib_api.LibraryXBlockMetad Fields.created: xblock_metadata.created.timestamp(), Fields.modified: xblock_metadata.modified.timestamp(), Fields.last_published: xblock_metadata.last_published.timestamp() if xblock_metadata.last_published else None, + Fields.publish_status: publish_status, }) doc.update(_fields_from_block(block)) diff --git a/openedx/core/djangoapps/content/search/index_config.py b/openedx/core/djangoapps/content/search/index_config.py index 9570956e425e..f0a6eb9ca30a 100644 --- a/openedx/core/djangoapps/content/search/index_config.py +++ b/openedx/core/djangoapps/content/search/index_config.py @@ -25,6 +25,7 @@ Fields.access_id, Fields.last_published, Fields.content + "." + Fields.problem_types, + Fields.publish_status, ] # Mark which attributes are used for keyword search, in order of importance: diff --git a/openedx/core/djangoapps/content/search/tests/test_api.py b/openedx/core/djangoapps/content/search/tests/test_api.py index c9c2b2589a31..8063307d61e9 100644 --- a/openedx/core/djangoapps/content/search/tests/test_api.py +++ b/openedx/core/djangoapps/content/search/tests/test_api.py @@ -148,6 +148,7 @@ def setUp(self): "last_published": None, "created": created_date.timestamp(), "modified": modified_date.timestamp(), + "publish_status": "never", } self.doc_problem2 = { "id": "lborg1libproblemp2-b2f65e29", @@ -164,6 +165,7 @@ def setUp(self): "last_published": None, "created": created_date.timestamp(), "modified": created_date.timestamp(), + "publish_status": "never", } # Create a couple of taxonomies with tags diff --git a/openedx/core/djangoapps/content/search/tests/test_documents.py b/openedx/core/djangoapps/content/search/tests/test_documents.py index 603cc8d92f5e..b8067a106db1 100644 --- a/openedx/core/djangoapps/content/search/tests/test_documents.py +++ b/openedx/core/djangoapps/content/search/tests/test_documents.py @@ -298,6 +298,7 @@ def test_html_library_block(self): "taxonomy": ["Difficulty"], "level0": ["Difficulty > Normal"], }, + "publish_status": "never", } def test_html_published_library_block(self): @@ -337,6 +338,7 @@ def test_html_published_library_block(self): "level0": ["Difficulty > Normal"], }, 'published': {'display_name': 'Text'}, + "publish_status": "published", } # Update library block to create a draft @@ -378,6 +380,7 @@ def test_html_published_library_block(self): "level0": ["Difficulty > Normal"], }, "published": {"display_name": "Text"}, + "publish_status": "published", } # Publish new changes @@ -420,6 +423,7 @@ def test_html_published_library_block(self): "display_name": "Text 2", "description": "This is a Test", }, + "publish_status": "published", } def test_collection_with_library(self): diff --git a/openedx/core/djangoapps/content/search/tests/test_handlers.py b/openedx/core/djangoapps/content/search/tests/test_handlers.py index 3577cbfc5692..b3bd272497c1 100644 --- a/openedx/core/djangoapps/content/search/tests/test_handlers.py +++ b/openedx/core/djangoapps/content/search/tests/test_handlers.py @@ -153,6 +153,7 @@ def test_create_delete_library_block(self, meilisearch_client): "last_published": None, "created": created_date.timestamp(), "modified": created_date.timestamp(), + "publish_status": "never", } meilisearch_client.return_value.index.return_value.update_documents.assert_called_with([doc_problem]) @@ -177,6 +178,7 @@ def test_create_delete_library_block(self, meilisearch_client): library_api.publish_changes(library.key) doc_problem["last_published"] = published_date.timestamp() doc_problem["published"] = {"display_name": "Blank Problem"} + doc_problem["publish_status"] = "published" meilisearch_client.return_value.index.return_value.update_documents.assert_called_with([doc_problem]) # Delete the Library Block