diff --git a/arches/app/media/js/views/components/search/advanced-search.js b/arches/app/media/js/views/components/search/advanced-search.js index 8ba012a3d57..1d2ac7cb275 100644 --- a/arches/app/media/js/views/components/search/advanced-search.js +++ b/arches/app/media/js/views/components/search/advanced-search.js @@ -194,7 +194,7 @@ define([ }); queryObj[componentName] = JSON.stringify(advanced); - if (this.getFilterByType('term-filter').hasTag(this.tagId) === false) { + if (this.getFilter('term-filter').hasTag(this.tagId) === false) { this.getFilterByType('term-filter').addTag(this.tagId, this.name, ko.observable(false)); } } else { diff --git a/arches/app/media/js/views/components/search/base-search-logic.js b/arches/app/media/js/views/components/search/base-search-view.js similarity index 99% rename from arches/app/media/js/views/components/search/base-search-logic.js rename to arches/app/media/js/views/components/search/base-search-view.js index a9603b21004..d3b0cddf0b6 100644 --- a/arches/app/media/js/views/components/search/base-search-logic.js +++ b/arches/app/media/js/views/components/search/base-search-view.js @@ -8,7 +8,7 @@ define([ ], function($, _, ko, BackBone, arches, AlertViewModel) { return Backbone.View.extend({ constructor: function() { - this.name = 'Base Search Logic'; + this.name = 'Base Search View'; this.filter = {}; this.requiredFilters = []; Backbone.View.apply(this, arguments); diff --git a/arches/app/media/js/views/components/search/standard-search-logic.js b/arches/app/media/js/views/components/search/standard-search-view.js similarity index 79% rename from arches/app/media/js/views/components/search/standard-search-logic.js rename to arches/app/media/js/views/components/search/standard-search-view.js index a05a2eb77b6..30d5739de8b 100644 --- a/arches/app/media/js/views/components/search/standard-search-logic.js +++ b/arches/app/media/js/views/components/search/standard-search-view.js @@ -4,16 +4,16 @@ define([ 'knockout', 'arches', 'viewmodels/alert', - 'views/components/search/base-search-logic', - 'templates/views/components/search/standard-search-logic.htm', -], function($, _, ko, arches, AlertViewModel, BaseSearchLogicComponent, standardSearchLogicTemplate) { - const componentName = 'standard-search-logic'; - const viewModel = BaseSearchLogicComponent.extend({ + 'views/components/search/base-search-view', + 'templates/views/components/search/standard-search-view.htm', +], function($, _, ko, arches, AlertViewModel, BaseSearchViewComponent, standardSearchViewTemplate) { + const componentName = 'standard-search-view'; + const viewModel = BaseSearchViewComponent.extend({ initialize: function(sharedStateObject) { const self = this; sharedStateObject.componentName = componentName; - BaseSearchLogicComponent.prototype.initialize.call(this, sharedStateObject); - this.defaultQuery = {"paging-filter": "1", "search-logic":"standard-search-logic", tiles: "true"}; + BaseSearchViewComponent.prototype.initialize.call(this, sharedStateObject); + this.defaultQuery = {"paging-filter": "1", "search-view":"standard-search-view", tiles: "true"}; this.selectedPopup = ko.observable(''); this.sharedStateObject.selectedPopup = this.selectedPopup; @@ -57,6 +57,6 @@ define([ return ko.components.register(componentName, { viewModel: viewModel, - template: standardSearchLogicTemplate, + template: standardSearchViewTemplate, }); }); diff --git a/arches/app/media/js/views/search.js b/arches/app/media/js/views/search.js index d6650c23aa1..f1fdff2ee77 100644 --- a/arches/app/media/js/views/search.js +++ b/arches/app/media/js/views/search.js @@ -45,8 +45,8 @@ define([ var CommonSearchViewModel = function() { this.searchComponentVms = {}; this.filtersList = Object.values(SearchComponents); - this.defaultSearchLogicComponent = this.filtersList.find(component => component.type == "search-logic" && component.config.default == true); // approach: let the backend decide - this.searchLogicComponentName = ko.observable(false); + this.defaultSearchViewComponent = this.filtersList.find(component => component.type == "search-view" && component.config.default == true); // approach: let the backend decide + this.searchViewComponentName = ko.observable(false); this.requiredFiltersLookup = this.filtersList.reduce((lookup, item) => { if (item.config.availableComponents && item.config.availableComponents.length > 0) { lookup[item.componentname] = item.config.availableComponents.map(filter => filter.searchcomponentid); @@ -77,10 +77,10 @@ define([ this.searchComponentVms[component.componentname] = ko.observable(null); }, this); this.query = ko.observable(getQueryObject()); - if (this.query()["search-logic"] !== undefined) { - this.searchLogicComponentName(this.query()["search-logic"]); + if (this.query()["search-view"] !== undefined) { + this.searchViewComponentName(this.query()["search-view"]); } else { - this.searchLogicComponentName(this.defaultSearchLogicComponent.componentname); + this.searchViewComponentName(this.defaultSearchViewComponent.componentname); } this.queryString = ko.computed(function() { return JSON.stringify(this.query()); diff --git a/arches/app/models/migrations/10804_core_search_filters.py b/arches/app/models/migrations/10804_core_search_filters.py index 467613c182c..7437519672a 100644 --- a/arches/app/models/migrations/10804_core_search_filters.py +++ b/arches/app/models/migrations/10804_core_search_filters.py @@ -23,13 +23,13 @@ class Migration(migrations.Migration): config ) VALUES ( '69695d63-6f03-4536-8da9-841b07116381', - 'Standard Search Logic', + 'Standard Search View', '', - 'standard_search_logic.py', - 'StandardSearchLogic', - 'search-logic', - 'views/components/search/standard-search-logic', - 'standard-search-logic', + 'standard_search_view.py', + 'StandardSearchView', + 'search-view', + 'views/components/search/standard-search-view', + 'standard-search-view', 0, true, '{"default":true,"requiredComponents":[{"componentname":"paging-filter","searchcomponentid":"7aff5819-651c-4390-9b9a-a61221ba52c6","sortorder":1},{"componentname":"search-results","searchcomponentid":"00673743-8c1c-4cc0-bd85-c073a52e03ec","sortorder":2}],"availableComponents":[{"componentname":"map-filter","searchcomponentid":"09d97fc6-8c83-4319-9cef-3aaa08c3fbec","sortorder":1},{"componentname":"advanced-search","searchcomponentid":"f0e56205-acb5-475b-9c98-f5e44f1dbd2c","sortorder":2},{"componentname":"related-resources-filter","searchcomponentid":"59f28272-d1f1-4805-af51-227771739aed","sortorder":3},{"componentname":"provisional-filter","searchcomponentid":"073406ed-93e5-4b5b-9418-b61c26b3640f","sortorder":4},{"componentname":"resource-type-filter","searchcomponentid":"f1c46b7d-0132-421b-b1f3-95d67f9b3980","sortorder":5},{"componentname":"saved-searches","searchcomponentid":"6dc29637-43a1-4fba-adae-8d9956dcd3b9","sortorder":6},{"componentname":"search-export","searchcomponentid":"9c6a5a9c-a7ec-48d2-8a25-501b55b8eff6","sortorder":7},{"componentname":"search-result-details","searchcomponentid":"f5986dae-8b01-11ea-b65a-77903936669c","sortorder":8},{"componentname":"sort-results","searchcomponentid":"6a2fe122-de54-4e44-8e93-b6a0cda7955c","sortorder":9},{"componentname":"term-filter","searchcomponentid":"1f42f501-ed70-48c5-bae1-6ff7d0d187da","sortorder":10},{"componentname":"time-filter","searchcomponentid":"7497ed4f-2085-40da-bee5-52076a48bcb1","sortorder":11},{"componentname":"paging-filter","searchcomponentid":"7aff5819-651c-4390-9b9a-a61221ba52c6","sortorder":12},{"componentname":"search-results","searchcomponentid":"00673743-8c1c-4cc0-bd85-c073a52e03ec","sortorder":13}]}' @@ -49,7 +49,7 @@ class Migration(migrations.Migration): """ reverse_sql = """ delete from search_component where searchcomponentid = '69695d63-6f03-4536-8da9-841b07116381'; - UPDATE search_component SET enabled = true, sortorder = 2 where type != 'search-logic'; + UPDATE search_component SET enabled = true, sortorder = 2 where type != 'search-view'; UPDATE search_component SET type = 'filter', sortorder = 1 where componentname = 'map-filter'; UPDATE search_component SET type = 'results-list' where componentname = 'search-results'; UPDATE search_component SET type = 'text-input' where componentname = 'term-filter'; diff --git a/arches/app/models/models.py b/arches/app/models/models.py index 8e66c2fc373..5464a16f4c6 100644 --- a/arches/app/models/models.py +++ b/arches/app/models/models.py @@ -1232,10 +1232,10 @@ def toJSON(self): @receiver(pre_save, sender=SearchComponent) -def ensure_single_default_search_logic(sender, instance, **kwargs): - if instance.config.get("default", False) and instance.type == "search-logic": +def ensure_single_default_searchview(sender, instance, **kwargs): + if instance.config.get("default", False) and instance.type == "search-view": existing_default = SearchComponent.objects.filter( - config__default=True, type="search-logic" + config__default=True, type="search-view" ).exclude(searchcomponentid=instance.searchcomponentid) if existing_default.exists(): raise ValidationError( diff --git a/arches/app/search/components/base.py b/arches/app/search/components/base.py index 95b3f9db13c..633cb5244a2 100644 --- a/arches/app/search/components/base.py +++ b/arches/app/search/components/base.py @@ -98,35 +98,35 @@ def get_filter(self, componentname): else: return None - def get_search_logic_component_name(self): + def get_searchview_component_name(self): if not self.request: - search_logic_component_name = None + searchview_component_name = None elif self.request.method == "POST": - search_logic_component_name = self.request.POST.get("search-logic", None) + searchview_component_name = self.request.POST.get("search-view", None) else: - search_logic_component_name = self.request.GET.get("search-logic", None) + searchview_component_name = self.request.GET.get("search-view", None) - if not search_logic_component_name: - # get default search_logic component - search_logic_component = list( + if not searchview_component_name: + # get default search_view component + searchview_component = list( filter( lambda x: x.config.get("default", False) - and x.type == "search-logic", + and x.type == "search-view", list(self.search_filters.values()), ) )[0] - search_logic_component_name = search_logic_component.componentname + searchview_component_name = searchview_component.componentname - return search_logic_component_name + return searchview_component_name - def get_search_logic_instance(self): - search_logic_component_name = self.get_search_logic_component_name() - return self.get_filter(search_logic_component_name) + def get_searchview_component_instance(self): + searchview_component_name = self.get_searchview_component_name() + return self.get_filter(searchview_component_name) - def get_sorted_query_dict(self, query_dict, search_logic_component): + def get_sorted_query_dict(self, query_dict, searchview_component): component_sort_order = { item["componentname"]: int(item["sortorder"]) - for item in search_logic_component.config["requiredComponents"] + for item in searchview_component.config["requiredComponents"] } # Sort the query_dict items based on the requiredComponent's sortorder sorted_items = sorted( @@ -136,26 +136,26 @@ def get_sorted_query_dict(self, query_dict, search_logic_component): return dict(sorted_items) - def get_query_dict_with_search_logic_component(self, query_dict: Dict[str, Any]): + def get_query_dict_with_searchview_component(self, query_dict: Dict[str, Any]): """ - Set search-logic=arches-search-logic on query_dict to arches-search-logic=True + Set search-view=arches-search-view on query_dict to arches-search-view=True """ ret = dict(query_dict) - search_logic_component_name = self.get_search_logic_component_name() - ret[search_logic_component_name] = True + searchview_component_name = self.get_searchview_component_name() + ret[searchview_component_name] = True # check that all core-search component requiredComponents are present - for required_component in self.search_filters[ - search_logic_component_name - ].config["requiredComponents"]: + for required_component in self.search_filters[searchview_component_name].config[ + "requiredComponents" + ]: if required_component["componentname"] not in ret: ret[required_component["componentname"]] = {} - return ret, self.search_filters[search_logic_component_name] + return ret, self.search_filters[searchview_component_name] def create_search_query_dict(self, key_value_pairs: List[Tuple[str, Any]]): # handles list of key,value tuples so that dict-like data from POST and GET # requests can be concatenated into single method call - query_dict, search_logic_component = ( - self.get_query_dict_with_search_logic_component(dict(key_value_pairs)) + query_dict, searchview_component = ( + self.get_query_dict_with_searchview_component(dict(key_value_pairs)) ) - return self.get_sorted_query_dict(query_dict, search_logic_component) + return self.get_sorted_query_dict(query_dict, searchview_component) diff --git a/arches/app/search/components/base_search_logic.py b/arches/app/search/components/base_search_view.py similarity index 87% rename from arches/app/search/components/base_search_logic.py rename to arches/app/search/components/base_search_view.py index bee445e0460..a1c21ae95cd 100644 --- a/arches/app/search/components/base_search_logic.py +++ b/arches/app/search/components/base_search_view.py @@ -6,13 +6,13 @@ # "searchcomponentid": "", # leave blank for the system to generate a uuid # "name": "", # the name that shows up in the UI # "icon": "", # the icon class to use -# "modulename": "custom_search_logic.py", # the name of this file -# "classname": "BaseSearchLogic", # the classname below", -# "type": "search-logic", # 'search-logic' if you want this to govern the search +# "modulename": "custom_search_view.py", # the name of this file +# "classname": "BaseSearchView", # the classname below", +# "type": "search-view", # 'search-view' if you want this to govern the search # "componentpath": "views/components/search/...", # path to ko component -# "componentname": "custom-search-logic", # lowercase unique name +# "componentname": "custom-search-view", # lowercase unique name # "config": { -# "default": True, # set for search logic components; only 1 can be the default +# "default": True, # set for search-view components; only 1 can be the default # "availableComponents": [ # search components available to the frontend and permitted to be executed on the backend # { # "componentname":"map-filter","searchcomponentid":"09d97fc6-8c83-4319-9cef-3aaa08c3fbec","sortorder":1 @@ -57,7 +57,7 @@ # } -class BaseSearchLogic(BaseSearchFilter): +class BaseSearchView(BaseSearchFilter): """ Special type of component that specifies which other components to be used, how to execute a search in the search_results method @@ -65,18 +65,18 @@ class BaseSearchLogic(BaseSearchFilter): def __init__(self, request=None, user=None, componentname=None): super().__init__(request=request, user=user, componentname=componentname) - self.search_logic_component = models.SearchComponent.objects.get( + self.searchview_component = models.SearchComponent.objects.get( componentname=componentname ) required_component_sort_order = { item["componentname"]: int(item["sortorder"]) - for item in self.search_logic_component.config["requiredComponents"] + for item in self.searchview_component.config["requiredComponents"] } self._required_search_components = list( models.SearchComponent.objects.filter( searchcomponentid__in=[ required_component["searchcomponentid"] - for required_component in self.search_logic_component.config[ + for required_component in self.searchview_component.config[ "requiredComponents" ] ] @@ -90,13 +90,13 @@ def __init__(self, request=None, user=None, componentname=None): ) available_component_sort_order = { item["componentname"]: int(item["sortorder"]) - for item in self.search_logic_component.config["availableComponents"] + for item in self.searchview_component.config["availableComponents"] } self._available_search_components = list( models.SearchComponent.objects.filter( searchcomponentid__in=[ available_component["searchcomponentid"] - for available_component in self.search_logic_component.config[ + for available_component in self.searchview_component.config[ "availableComponents" ] ] @@ -118,7 +118,7 @@ def available_search_components(self): return self._available_search_components def get_searchview_components(self): - return self._available_search_components + [self.search_logic_component] + return self._available_search_components + [self.searchview_component] def handle_search_results_query( self, search_query_object, response_object, search_filter_factory, returnDsl diff --git a/arches/app/search/components/standard_search_logic.py b/arches/app/search/components/standard_search_view.py similarity index 95% rename from arches/app/search/components/standard_search_logic.py rename to arches/app/search/components/standard_search_view.py index 39c206b0f0a..2d5c1220520 100644 --- a/arches/app/search/components/standard_search_logic.py +++ b/arches/app/search/components/standard_search_view.py @@ -1,5 +1,5 @@ from arches.app.models.system_settings import settings -from arches.app.search.components.base_search_logic import BaseSearchLogic +from arches.app.search.components.base_search_view import BaseSearchView from arches.app.search.mappings import RESOURCES_INDEX from arches.app.views.search import ( append_instance_permission_filter_dsl, @@ -18,13 +18,13 @@ details = { "searchcomponentid": "69695d63-6f03-4536-8da9-841b07116381", - "name": "Standard Search Logic", + "name": "Standard Search View", "icon": "", - "modulename": "standard_search_logic.py", - "classname": "StandardSearchLogic", - "type": "search-logic", - "componentpath": "views/components/search/standard-search-logic", - "componentname": "standard-search-logic", + "modulename": "standard_search_view.py", + "classname": "StandardSearchView", + "type": "search-view", + "componentpath": "views/components/search/standard-search-view", + "componentname": "standard-search-view", "config": { "default": True, "requiredComponents": [ @@ -116,7 +116,7 @@ logger = logging.getLogger(__name__) -class StandardSearchLogic(BaseSearchLogic): +class StandardSearchView(BaseSearchView): def append_dsl(self, search_query_object, **kwargs): search_query_object["query"].include("graph_id") @@ -184,7 +184,7 @@ def get_searchview_components(self): ] ) - search_components.append(self.search_logic_component) + search_components.append(self.searchview_component) return search_components diff --git a/arches/app/templates/views/components/search/standard-search-logic.htm b/arches/app/templates/views/components/search/standard-search-view.htm similarity index 100% rename from arches/app/templates/views/components/search/standard-search-logic.htm rename to arches/app/templates/views/components/search/standard-search-view.htm diff --git a/arches/app/templates/views/search.htm b/arches/app/templates/views/search.htm index 539f9533c22..5c6abbdc2e4 100644 --- a/arches/app/templates/views/search.htm +++ b/arches/app/templates/views/search.htm @@ -6,9 +6,9 @@ {% block title %} {{ block.super }} {% trans "Search" %} {% endblock title %} {% block main_content %} - +
diff --git a/arches/app/views/search.py b/arches/app/views/search.py index bf1e5b5320d..f82577c89c5 100644 --- a/arches/app/views/search.py +++ b/arches/app/views/search.py @@ -76,8 +76,10 @@ def get(self, request): ) geocoding_providers = models.Geocoder.objects.all() search_component_factory = SearchFilterFactory(request) - search_logic_instance = search_component_factory.get_search_logic_instance() - search_components = search_logic_instance.get_searchview_components() + searchview_component_instance = ( + search_component_factory.get_searchview_component_instance() + ) + search_components = searchview_component_instance.get_searchview_components() datatypes = models.DDataType.objects.all() widgets = models.Widget.objects.all() @@ -342,9 +344,11 @@ def get_dsl_from_search_string(request): def search_results(request, returnDsl=False): se = SearchEngineFactory().create() search_filter_factory = SearchFilterFactory(request) - search_logic_instance = search_filter_factory.get_search_logic_instance() - if not search_logic_instance: - unavailable_core_name = search_filter_factory.get_search_logic_component_name() + searchview_component_instance = ( + search_filter_factory.get_searchview_component_instance() + ) + if not searchview_component_instance: + unavailable_core_name = search_filter_factory.get_searchview_component_name() ret = { "success": False, "message": _("No core-search component named {0}").format( @@ -357,7 +361,7 @@ def search_results(request, returnDsl=False): response_object = {"results": None} response_object, search_query_object = ( - search_logic_instance.handle_search_results_query( + searchview_component_instance.handle_search_results_query( search_query_object, response_object, search_filter_factory, returnDsl ) ) diff --git a/releases/7.6.0.md b/releases/7.6.0.md index c2b0c6c5b32..383af81cb67 100644 --- a/releases/7.6.0.md +++ b/releases/7.6.0.md @@ -17,7 +17,7 @@ Arches 7.6.0 Release Notes - Plugins now support the configuration boolean `is_standalone`. Standalone plugins do not appear in the sidebar, and do not display the sidebar or application header. -- 10804 Search has been re-architected to be totally component-based, now governed by `search-logic` components. See [docs](https://arches.readthedocs.io/en/latest/developing/reference/search-components/) for more details. +- 10804 Search has been re-architected to be totally component-based, now governed by `search-view` components. See [docs](https://arches.readthedocs.io/en/latest/developing/reference/search-components/) for more details. - 10862 JSON-LD bulk import module diff --git a/tests/views/search_tests.py b/tests/views/search_tests.py index 4e6b5bc0b7c..5c21f58b78f 100644 --- a/tests/views/search_tests.py +++ b/tests/views/search_tests.py @@ -761,46 +761,50 @@ def test_temporal_and_permission_search_2(self): ], ) - def test_search_without_search_logic(self): + def test_search_without_searchview(self): """ - Execute a search without setting a search-logic component on the query + Execute a search without setting a search-view component on the query """ response_json = get_response_json(self.client) self.assertTrue(response_json["results"]["hits"]["total"]["value"] > 0) - def test_search_with_bad_search_logic(self): + def test_search_with_bad_searchview(self): """ - Execute a search with a search-logic component name that does not exist + Execute a search with a search-view component name that does not exist """ - query = {"search-logic": "unavailable-search-logic"} + query = {"search-view": "unavailable-search-view"} response_json = get_response_json(self.client, query=query) self.assertFalse(response_json["success"]) - def test_searchview_search_logic_component_from_admin(self): + def test_searchview_searchview_component_from_admin(self): request = HttpRequest() request.method = "GET" request.user = User.objects.get(username="admin") search_component_factory = SearchFilterFactory(request) - search_logic_instance = search_component_factory.get_search_logic_instance() - self.assertTrue(search_logic_instance is not None) + searchview_component_instance = ( + search_component_factory.get_searchview_component_instance() + ) + self.assertTrue(searchview_component_instance is not None) - search_components = search_logic_instance.get_searchview_components() - # 13 available components + search-logic component + search_components = searchview_component_instance.get_searchview_components() + # 13 available components + search-view component self.assertEqual(len(search_components), 14) - def test_searchview_search_logic_component_from_anonymous(self): + def test_searchview_searchview_component_from_anonymous(self): request = HttpRequest() request.method = "GET" request.user = User.objects.get(username="anonymous") search_component_factory = SearchFilterFactory(request) - search_logic_instance = search_component_factory.get_search_logic_instance() - self.assertTrue(search_logic_instance is not None) + searchview_component_instance = ( + search_component_factory.get_searchview_component_instance() + ) + self.assertTrue(searchview_component_instance is not None) - search_components = search_logic_instance.get_searchview_components() - # 13 available components + search-logic component + search_components = searchview_component_instance.get_searchview_components() + # 13 available components + search-view component self.assertEqual(len(search_components), 14)