diff --git a/arches_lingo/src/arches_lingo/App.vue b/arches_lingo/src/arches_lingo/App.vue
index 262bc710..4c8ad376 100644
--- a/arches_lingo/src/arches_lingo/App.vue
+++ b/arches_lingo/src/arches_lingo/App.vue
@@ -77,6 +77,7 @@ main {
font-family: sans-serif;
height: 100vh;
width: 100vw;
+ overflow-x: hidden;
display: flex;
flex-direction: column;
}
diff --git a/arches_lingo/src/arches_lingo/api.ts b/arches_lingo/src/arches_lingo/api.ts
index f6b9f3d2..657efbe4 100644
--- a/arches_lingo/src/arches_lingo/api.ts
+++ b/arches_lingo/src/arches_lingo/api.ts
@@ -54,3 +54,28 @@ export const fetchUser = async () => {
throw new Error((error as Error).message || response.statusText);
}
};
+
+export const fetchSearchResults = async (
+ searchTerm: string,
+ items: number,
+ page: number,
+) => {
+ const params = new URLSearchParams({
+ term: searchTerm,
+ items: items.toString(),
+ page: page.toString(),
+ });
+
+ const url = `${arches.urls.api_search}?${params.toString()}`;
+
+ const response = await fetch(url);
+ try {
+ const responseJson = await response.json();
+ if (response.ok) {
+ return responseJson;
+ }
+ throw new Error(responseJson.message);
+ } catch (error) {
+ throw new Error((error as Error).message || response.statusText);
+ }
+};
diff --git a/arches_lingo/src/arches_lingo/components/basic-search/BasicSearch.vue b/arches_lingo/src/arches_lingo/components/basic-search/BasicSearch.vue
new file mode 100644
index 00000000..5a8f46da
--- /dev/null
+++ b/arches_lingo/src/arches_lingo/components/basic-search/BasicSearch.vue
@@ -0,0 +1,313 @@
+
+
+
+
+
+
+
+
{
+ autoCompleteInstance?.hide();
+ fetchData(query, props.searchResultsPerPage, 1);
+ }
+ "
+ @option-select="navigateToReport"
+ @before-hide="keepOverlayVisible"
+ @update:model-value="
+ (value) => {
+ if (!value) {
+ shouldShowClearInputButton = false;
+ }
+ }
+ "
+ >
+
+
+ {{ $gettext("No search results found") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/arches_lingo/src/arches_lingo/components/basic-search/SearchResult.vue b/arches_lingo/src/arches_lingo/components/basic-search/SearchResult.vue
new file mode 100644
index 00000000..166a0892
--- /dev/null
+++ b/arches_lingo/src/arches_lingo/components/basic-search/SearchResult.vue
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+ {{ getItemLabel(searchResult.option, "en-US", "en-US").value }}
+
+
+
+ [ {{ getParentLabels(searchResult.option, "en-US") }} ]
+
+
+
+
+
diff --git a/arches_lingo/src/arches_lingo/components/basic-search/SortAndFilterControls.vue b/arches_lingo/src/arches_lingo/components/basic-search/SortAndFilterControls.vue
new file mode 100644
index 00000000..fcad02fb
--- /dev/null
+++ b/arches_lingo/src/arches_lingo/components/basic-search/SortAndFilterControls.vue
@@ -0,0 +1,130 @@
+
+
+
+
+
+
Placeholder Sorting:
+
+
+
+
+
+
+
+
+
Placeholder Include:
+
+
+
+
+
+
+
+
+
+
diff --git a/arches_lingo/src/arches_lingo/components/header/PageHeader.vue b/arches_lingo/src/arches_lingo/components/header/PageHeader.vue
index c653ff50..c5d4a0cd 100644
--- a/arches_lingo/src/arches_lingo/components/header/PageHeader.vue
+++ b/arches_lingo/src/arches_lingo/components/header/PageHeader.vue
@@ -6,15 +6,11 @@ import Menubar from "primevue/menubar";
import { routeNames } from "@/arches_lingo/routes.ts";
import UserInteraction from "@/arches_lingo/components/user/UserInteraction.vue";
+import SearchDialog from "@/arches_lingo/components/header/SearchDialog.vue";
const { $gettext } = useGettext();
const items = ref([
- {
- label: $gettext("Search"),
- icon: "fa fa-search",
- name: routeNames.search,
- },
{
label: $gettext("Advanced Search"),
icon: "fa fa-file",
@@ -35,6 +31,7 @@ const items = ref([
>
{{ $gettext("Arches Lingo") }}
+
+import { ref } from "vue";
+import { useGettext } from "vue3-gettext";
+
+import Button from "primevue/button";
+import Dialog from "primevue/dialog";
+
+import BasicSearch from "@/arches_lingo/components/basic-search/BasicSearch.vue";
+
+import {
+ SEARCH_RESULTS_PER_PAGE,
+ SEARCH_RESULT_ITEM_SIZE,
+} from "@/arches_lingo/constants.ts";
+
+const { $gettext } = useGettext();
+
+const visible = ref(false);
+
+
+
+
+
+
+
+
+
+
diff --git a/arches_lingo/src/arches_lingo/components/sidenav/SideNav.vue b/arches_lingo/src/arches_lingo/components/sidenav/SideNav.vue
index 3606f916..3422bae2 100644
--- a/arches_lingo/src/arches_lingo/components/sidenav/SideNav.vue
+++ b/arches_lingo/src/arches_lingo/components/sidenav/SideNav.vue
@@ -12,11 +12,6 @@ const items = ref([
routeName: routeNames.root,
linkName: $gettext("Home"),
},
- {
- icon: "fa fa-search",
- routeName: routeNames.search,
- linkName: $gettext("Search"),
- },
]);
diff --git a/arches_lingo/src/arches_lingo/constants.ts b/arches_lingo/src/arches_lingo/constants.ts
index 534204aa..701063dc 100644
--- a/arches_lingo/src/arches_lingo/constants.ts
+++ b/arches_lingo/src/arches_lingo/constants.ts
@@ -4,6 +4,9 @@ import type { UserRefAndSetter } from "@/arches_lingo/types.ts";
export const ANONYMOUS = "anonymous";
export const ERROR = "error";
+
export const DEFAULT_ERROR_TOAST_LIFE = 8000;
+export const SEARCH_RESULTS_PER_PAGE = 25;
+export const SEARCH_RESULT_ITEM_SIZE = 38;
export const USER_KEY = Symbol() as InjectionKey;
diff --git a/arches_lingo/src/arches_lingo/pages/BasicSearch.vue b/arches_lingo/src/arches_lingo/pages/BasicSearch.vue
deleted file mode 100644
index fd68eb55..00000000
--- a/arches_lingo/src/arches_lingo/pages/BasicSearch.vue
+++ /dev/null
@@ -1 +0,0 @@
-Basic Search placeholder
diff --git a/arches_lingo/src/arches_lingo/routes.ts b/arches_lingo/src/arches_lingo/routes.ts
index 1a49968b..17bd747d 100644
--- a/arches_lingo/src/arches_lingo/routes.ts
+++ b/arches_lingo/src/arches_lingo/routes.ts
@@ -17,15 +17,6 @@ export const routes = [
requiresAuthentication: false,
},
},
- {
- path: "/search",
- name: "search",
- component: () => import("@/arches_lingo/pages/BasicSearch.vue"),
- meta: {
- shouldShowNavigation: true,
- requiresAuthentication: true,
- },
- },
{
path: "/advanced-search",
name: "advanced-search",
diff --git a/arches_lingo/src/arches_lingo/types.ts b/arches_lingo/src/arches_lingo/types.ts
index f9a2e309..e791e762 100644
--- a/arches_lingo/src/arches_lingo/types.ts
+++ b/arches_lingo/src/arches_lingo/types.ts
@@ -1,5 +1,7 @@
import type { Ref } from "vue";
+import type { Label } from "@/arches_vue_utils/types";
+
export interface User {
first_name: string;
last_name: string;
@@ -11,3 +13,13 @@ export interface UserRefAndSetter {
user: Ref;
setUser: (userToSet: User | null) => void;
}
+
+export interface Concept {
+ id: string;
+ labels: Label[];
+ parents: {
+ id: string;
+ labels: Label[];
+ }[];
+ polyhierarchical: boolean;
+}
diff --git a/arches_lingo/templates/arches_urls.htm b/arches_lingo/templates/arches_urls.htm
new file mode 100644
index 00000000..36fc2df2
--- /dev/null
+++ b/arches_lingo/templates/arches_urls.htm
@@ -0,0 +1,12 @@
+{% extends "arches_urls.htm" %}
+
+{% load static %}
+{% load l10n %}
+{% load i18n %}
+
+{% block arches_urls %}
+{{ block.super }}
+
+{% endblock arches_urls %}
\ No newline at end of file
diff --git a/arches_lingo/urls.py b/arches_lingo/urls.py
index a8899f36..2f3df8ec 100644
--- a/arches_lingo/urls.py
+++ b/arches_lingo/urls.py
@@ -9,7 +9,6 @@
urlpatterns = [
path("", LingoRootView.as_view(), name="root"),
path("login", LingoRootView.as_view(), name="login"),
- path("search", LingoRootView.as_view(), name="search"),
path("advanced-search", LingoRootView.as_view(), name="advanced-search"),
path("schemes", LingoRootView.as_view(), name="schemes"),
path("api/concepts", ConceptTreeView.as_view(), name="api-concepts"),
diff --git a/arches_lingo/utils/concept_builder.py b/arches_lingo/utils/concept_builder.py
index cd702be7..231dae34 100644
--- a/arches_lingo/utils/concept_builder.py
+++ b/arches_lingo/utils/concept_builder.py
@@ -22,8 +22,10 @@
SCHEME_NAME_LANGUAGE_NODE,
SCHEME_NAME_TYPE_NODE,
)
+
from arches_lingo.utils.query_expressions import JsonbArrayElements
+
TOP_CONCEPT_OF_LOOKUP = f"data__{TOP_CONCEPT_OF_NODE_AND_NODEGROUP}"
BROADER_LOOKUP = f"data__{CLASSIFICATION_STATUS_ASCRIBED_CLASSIFICATION_NODEID}"
@@ -212,6 +214,7 @@ def add_broader_concept_recursive(self, working_parent_list, conceptid):
schemes = sorted(self.schemes_by_top_concept[conceptid])
working_parent_list.insert(0, schemes[0])
return working_parent_list
+
working_parent_list.insert(0, first_broader_conceptid)
return self.add_broader_concept_recursive(
working_parent_list, first_broader_conceptid
diff --git a/arches_lingo/views/api/concepts.py b/arches_lingo/views/api/concepts.py
index 41e0dc71..6d868f5a 100644
--- a/arches_lingo/views/api/concepts.py
+++ b/arches_lingo/views/api/concepts.py
@@ -57,17 +57,26 @@ def get(self, request):
concept_query = VwLabelValue.objects.all().order_by("concept_id")
concept_ids = concept_query.values_list("concept_id", flat=True).distinct()
+ data = []
paginator = Paginator(concept_ids, items_per_page)
- if not paginator.count:
- return JSONResponse([])
-
- builder = ConceptBuilder()
- data = [
- builder.serialize_concept(str(concept_uuid), parents=True, children=False)
- for concept_uuid in paginator.get_page(page_number)
- ]
+ if paginator.count:
+ builder = ConceptBuilder()
+ data = [
+ builder.serialize_concept(
+ str(concept_uuid), parents=True, children=False
+ )
+ for concept_uuid in paginator.get_page(page_number)
+ ]
- return JSONResponse(data)
+ return JSONResponse(
+ {
+ "current_page": paginator.get_page(page_number).number,
+ "total_pages": paginator.num_pages,
+ "results_per_page": paginator.per_page,
+ "total_results": paginator.count,
+ "data": data,
+ }
+ )
@staticmethod
def default_sensitivity():
diff --git a/tests/tests.py b/tests/tests.py
index 987e5077..9808e303 100644
--- a/tests/tests.py
+++ b/tests/tests.py
@@ -247,7 +247,7 @@ def test_search(self):
with self.subTest(query=query):
response = self.client.get(reverse("api-search"), QUERY_STRING=query)
result = json.loads(response.content)
- self.assertEqual(len(result), expected_result_count, result)
+ self.assertEqual(len(result["data"]), expected_result_count, result)
def test_invalid_search_term(self):
self.client.force_login(self.admin)
diff --git a/tsconfig.json b/tsconfig.json
index 34902ec7..c223f2c6 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -15,6 +15,7 @@
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
+ "types": ["vitest/globals"],
"allowImportingTsExtensions": true
}
}