Implement search sorting
authorAdam Dullage <redacted>
Fri, 17 May 2024 07:09:55 +0000 (08:09 +0100)
committerAdam Dullage <redacted>
Fri, 17 May 2024 07:09:55 +0000 (08:09 +0100)
client/components/CustomButton.vue
client/constants.js
client/partials/NavBar.vue
client/router.js
client/views/SearchResults.vue

index 14009cca7860ff236a833f3001779b85b3d6f631..426431252af6999d0991cfb710e8dfa49d1f1cc7 100644 (file)
@@ -1,6 +1,6 @@
 <template>
   <button
-    class="rounded px-2 py-1"
+    class="text-nowrap rounded px-2 py-1"
     :class="{
       'bg-theme-background text-theme-text-muted hover:bg-theme-background-elevated':
         style === 'subtle',
index 25f88f0bf59314108b3ea456d4d2645560ac61ce..811af42f0f9b21f69651fdcf36b372cad99df915 100644 (file)
@@ -6,37 +6,11 @@ export const params = {
   sortBy: "sortBy",
 };
 
-// Other
-export const alphabet = [
-  "A",
-  "B",
-  "C",
-  "D",
-  "E",
-  "F",
-  "G",
-  "H",
-  "I",
-  "J",
-  "K",
-  "L",
-  "M",
-  "N",
-  "O",
-  "P",
-  "Q",
-  "R",
-  "S",
-  "T",
-  "U",
-  "V",
-  "W",
-  "X",
-  "Y",
-  "Z",
-];
-
-export const searchSortOptions = { score: 0, title: 1, lastModified: 2 };
+export const searchSortOptions = {
+  score: 0,
+  title: 1,
+  lastModified: 2,
+};
 
 export const authTypes = {
   none: "none",
index 1d11709b936aeee87a69a1bbf6d08eaeb4f910b0..42f47cefa3019cb3fc393862cad027995c509f69 100644 (file)
@@ -35,7 +35,7 @@ import { RouterLink, useRouter } from "vue-router";
 import CustomButton from "../components/CustomButton.vue";\r
 import Logo from "../components/Logo.vue";\r
 import PrimeMenu from "../components/PrimeMenu.vue";\r
-import { authTypes } from "../constants.js";\r
+import { authTypes, params, searchSortOptions } from "../constants.js";\r
 import { useGlobalStore } from "../globalStore.js";\r
 import { toggleTheme } from "../helpers.js";\r
 import { clearStoredToken } from "../tokenStorage.js";\r
@@ -60,7 +60,14 @@ const menuItems = [
   {\r
     label: "All Notes",\r
     icon: mdilNoteMultiple,\r
-    command: () => router.push({ name: "search", query: { term: "*" } }),\r
+    command: () =>\r
+      router.push({\r
+        name: "search",\r
+        query: {\r
+          [params.searchTerm]: "*",\r
+          [params.sortBy]: searchSortOptions.title,\r
+        },\r
+      }),\r
   },\r
   {\r
     label: "Toggle Theme",\r
index 51211a6bd0aa1abad9c54a183da2c49356507ac0..07b6c9d38191ede73edcae595af009071c8b46ea 100644 (file)
@@ -33,6 +33,7 @@ const router = createRouter({
       component: () => import("./views/SearchResults.vue"),\r
       props: (route) => ({\r
         searchTerm: route.query[constants.params.searchTerm],\r
+        sortBy: Number(route.query[constants.params.sortBy]) || undefined,\r
       }),\r
     },\r
   ],\r
index f4df680e294d7fb0140079a88cf191f7254adc04..265061b69d4727205705c55c4b82879b272c16d8 100644 (file)
@@ -1,13 +1,21 @@
 <template>
-  <div class="flex h-full flex-col">
+  <div class="flex h-full max-w-[700px] flex-col">
     <!-- Search Input -->
-    <SearchInput
-      :initialSearchTerm="props.searchTerm"
-      class="mb-8 max-w-[700px]"
-    />
+    <SearchInput :initialSearchTerm="props.searchTerm" class="mb-2" />
+
+    <!-- Sort By -->
+    <div class="flex justify-end">
+      <CustomButton
+        :label="`Sort By: ${sortByName}`"
+        :iconPath="mdiSort"
+        class="mb-1"
+        @click="toggleSortMenu"
+      />
+      <PrimeMenu ref="sortMenu" :model="menuItems" :popup="true" />
+    </div>
 
     <!-- Search Results -->
-    <LoadingIndicator ref="loadingIndicator" class="max-w-[700px] flex-1">
+    <LoadingIndicator ref="loadingIndicator" class="flex-1">
       <div
         v-for="result in results"
         class="mb-4 cursor-pointer rounded px-2 py-1 hover:bg-theme-background-elevated"
 
 <script setup>
 import { useToast } from "primevue/usetoast";
-import { onMounted, ref, watch } from "vue";
+import { computed, onMounted, ref, watch } from "vue";
+import { useRouter } from "vue-router";
 
-import { mdiMagnify } from "@mdi/js";
-import { getNotes, apiErrorHandler } from "../api.js";
+import { mdiMagnify, mdiSort } from "@mdi/js";
+import { apiErrorHandler, getNotes } from "../api.js";
+import CustomButton from "../components/CustomButton.vue";
 import LoadingIndicator from "../components/LoadingIndicator.vue";
+import PrimeMenu from "../components/PrimeMenu.vue";
 import Tag from "../components/Tag.vue";
+import { params, searchSortOptions } from "../constants.js";
 import SearchInput from "../partials/SearchInput.vue";
 
-const props = defineProps({ searchTerm: String });
+const props = defineProps({
+  searchTerm: String,
+  sortBy: {
+    type: Number,
+    default: searchSortOptions.score,
+  },
+});
 
 const loadingIndicator = ref();
 const results = ref([]);
+const router = useRouter();
+const sortMenu = ref();
 const toast = useToast();
 
+const sortByName = computed(() => {
+  const sortOptionNames = {
+    [searchSortOptions.title]: "Title",
+    [searchSortOptions.lastModified]: "Last Modified",
+    [searchSortOptions.score]: "Score",
+  };
+  return sortOptionNames[props.sortBy];
+});
+
 function init() {
   loadingIndicator.value.setLoading();
   getNotes(props.searchTerm)
     .then((data) => {
-      results.value = data;
+      results.value = sortResults(data);
       if (results.value.length > 0) {
         loadingIndicator.value.setLoaded();
       } else {
@@ -68,7 +97,58 @@ function init() {
     });
 }
 
+function sortResults(results) {
+  if (props.sortBy === searchSortOptions.title) {
+    return results.sort((a, b) => a.title.localeCompare(b.title));
+  } else if (props.sortBy === searchSortOptions.lastModified) {
+    return results.sort((a, b) => b.lastModified - a.lastModified);
+  } else {
+    return results.sort((a, b) => b.score - a.score);
+  }
+}
+
+function reSortResults() {
+  results.value = sortResults(results.value);
+}
+
+function updateSortByParam(sortBy) {
+  router.push({
+    name: "search",
+    query: {
+      [params.searchTerm]: props.searchTerm,
+      [params.sortBy]: sortBy,
+    },
+  });
+}
+
+const menuItems = [
+  {
+    label: "Sort By: Score",
+    command: () => {
+      updateSortByParam(searchSortOptions.score);
+    },
+  },
+
+  {
+    label: "Sort By: Title",
+    command: () => {
+      updateSortByParam(searchSortOptions.title);
+    },
+  },
+  {
+    label: "Sort By: Last Modified",
+    command: () => {
+      updateSortByParam(searchSortOptions.lastModified);
+    },
+  },
+];
+
+function toggleSortMenu(event) {
+  sortMenu.value.toggle(event);
+}
+
 watch(() => props.searchTerm, init);
+watch(() => props.sortBy, reSortResults);
 onMounted(init);
 </script>
 
git clone https://git.99rst.org/PROJECT