Skip to content

Commit

Permalink
Added first draft of the search component
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianrudnik committed Oct 28, 2023
1 parent 32d26ae commit d79da3d
Show file tree
Hide file tree
Showing 24 changed files with 314 additions and 123 deletions.
51 changes: 51 additions & 0 deletions frontend/src/components/parts/QueryInput.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<template>
<div>
<div class="p-inputgroup flex-1">
<span class="p-inputgroup-addon">
<i class="pi pi-search"></i>
</span>
<InputText
@update:model-value="search"
type="search"
v-model="query"
class="w-full"
:placeholder="t('query-input-component.placeholder')"
/>
</div>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import InputText from 'primevue/inputtext'
import { useI18n } from 'vue-i18n'
import { executeQuerySearch } from '@/plugins/search'
import { useSearchResultStore } from '@/stores/results'
import { useStatStore } from '@/stores/stats'
const { t } = useI18n()
const search = async (query: string) => {
useStatStore().isSearching = true
try {
const result = await executeQuerySearch({
size: 10,
query: {
query: query
},
fields: ['*']
})
useSearchResultStore().overwrite(
result.hits.map((h) => {
h.fields.id = h.id
return h.fields
})
)
} finally {
useStatStore().isSearching = false
}
}
const query = ref('')
</script>
31 changes: 31 additions & 0 deletions frontend/src/components/parts/search/LiveSetResultItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<template>
<div>
<SearchResultCard :title="result.displayName">
<div class="tags" v-if="tags">
<SearchTag :tag="tag" v-for="tag in tags" :key="tag.id" />
</div>
</SearchResultCard>
</div>
</template>

<script setup lang="ts">
import type { LiveSetResult } from '@/plugins/search/result/result_live_set'
import SearchResultCard from '@/components/parts/search/SearchResultCard.vue'
import { useTagStore } from '@/stores/tags'
import { computed } from 'vue'
import SearchTag from '@/components/structure/SearchTag.vue'
import type {Tag} from "@/stores/tags";
const props = defineProps<{
result: LiveSetResult
}>()
const tags = computed(() => {
const rawTags = props.result.tags?.filter(t => useTagStore().entries.find((tt) => tt.id === t)) ?? [];
return rawTags.map(t => useTagStore().entries.find((tt) => tt.id === t)) as Tag[]
})
</script>

<style scoped lang="scss"></style>

<i18n lang="yaml"></i18n>
31 changes: 31 additions & 0 deletions frontend/src/components/parts/search/SearchResultCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<template>
<div class="surface-card p-4 shadow-2 border-round">
<div class="mb-3 flex flex-column md:flex-row md:align-items-center md:justify-content-between">
<div class="mb-3 md:mb-0">
<div class="text-3xl font-medium text-900 mb-3" v-if="title">{{ title }}</div>
<div class="font-medium text-500 mb-3" v-if="!!$slots.subtitle">
<slot name="subtitle" />
</div>
</div>

<div
class="flex align-items-center justify-content-between mt-3 md:mt-0"
v-if="!!$slots.actions"
>
<slot name="actions" />
</div>
</div>

<slot />
</div>
</template>

<script setup lang="ts">
const props = defineProps<{
title?: string
}>()
</script>

<style scoped lang="scss"></style>

<i18n lang="yaml"></i18n>
7 changes: 7 additions & 0 deletions frontend/src/components/parts/search/SearchResultList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<template>
<div>
<ul class="list-none p-0 m-0">
<slot />
</ul>
</div>
</template>
21 changes: 21 additions & 0 deletions frontend/src/components/parts/search/SearchResultListItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<template>
<li class="p-0 mb-3">
<component
:is="resultTypeComponentMap[props.result.type] ?? UnknownResultItem"
:result="props.result"
/>
</li>
</template>

<script setup lang="ts">
import type { HitFieldset } from '@/plugins/search/result'
import LiveSetResultItem from '@/components/parts/search/LiveSetResultItem.vue'
import UnknownResultItem from '@/components/parts/search/UnknownResultItem.vue'
const resultTypeComponentMap = {
LiveSet: LiveSetResultItem
}
const props = defineProps<{
result: HitFieldset
}>()
</script>
9 changes: 9 additions & 0 deletions frontend/src/components/parts/search/UnknownResultItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<template>
<div>Unknown item</div>
</template>

<script setup lang="ts"></script>

<style scoped lang="scss"></style>

<i18n lang="yaml"></i18n>
6 changes: 1 addition & 5 deletions frontend/src/components/structure/SearchTag.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@
<div v-if="parts.extra" class="p-1 px-2 bg-black-alpha-50 text-white border-900">
{{ parts.extra }}
</div>
<div
v-if="showCount"
class="p-1 px-2 bg-black-alpha-30 border-900"
>
<div v-if="showCount" class="p-1 px-2 bg-black-alpha-30 border-900">
{{ props.tag.count }}
</div>
</div>
Expand All @@ -24,7 +21,6 @@
import type { Tag as TagInterface } from '@/stores/tags'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import messages from '@intlify/unplugin-vue-i18n/messages'
const { t } = useI18n()
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/locales/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,6 @@ shutdown-confirm-modal:
The service will be shut down and all locked system resources will be released.
accept: Shutdown
reject: Return

query-input-component:
placeholder: Search your files here
83 changes: 0 additions & 83 deletions frontend/src/plugins/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,86 +18,3 @@ export async function fetchApi<T>(

return r.json()
}

export interface SearchQuery {
size: number
query: SearchQueryString
facets?: SearchFacets
fields?: string[]
}

interface SearchFacets {
[key: string]: SearchFacet
}
interface SearchFacet {
field: string
size: number
}

interface SearchQueryString {
query: string
}

/**
* {
* "size": 0,
* "from": 0,
* "query": {
* "query": "*"
* },
* "facets": {
* "tags": {
* "field": "tags",
* "size": 1000
* }
* },
* "fields": [
* "*"
* ]
* }
*/
export interface SearchResult {
status: StatusNode
facets?: FacetsNode
}

interface StatusNode {
total: number
failed: number
success: number
}

interface FacetsNode {
[key: string]: FacetNode
}

interface FacetNode {
field: string
total: number
missing: number
other: number
terms: FacetTerm[]
}

interface FacetTerm {
term: string
count: number
}

export async function fetchSearch(query: SearchQuery): Promise<SearchResult> {
const r = await fetch(import.meta.env.VITE_API_URL + '/search/query', {
credentials: 'include',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(query),
method: 'POST'
})

if (!r.ok) {
throw new Error(r.statusText)
}

return r.json()
}
20 changes: 20 additions & 0 deletions frontend/src/plugins/search/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { SearchQuery } from './query'
import type { SearchResult } from './result'

export async function executeQuerySearch(query: SearchQuery): Promise<SearchResult> {
const r = await fetch(import.meta.env.VITE_API_URL + '/search/query', {
credentials: 'include',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(query),
method: 'POST'
})

if (!r.ok) {
throw new Error(r.statusText)
}

return r.json()
}
19 changes: 19 additions & 0 deletions frontend/src/plugins/search/query/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export interface SearchQuery {
size: number
query: SearchQueryString
facets?: SearchFacets
fields?: string[]
}

export interface SearchFacets {
[key: string]: SearchFacet
}

export interface SearchFacet {
field: string
size: number
}

export interface SearchQueryString {
query: string
}
40 changes: 40 additions & 0 deletions frontend/src/plugins/search/result/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { LiveSetResult } from '@/plugins/search/result/result_live_set'

export interface SearchResult {
status: StatusNode
facets?: FacetsNode
hits: Hit[]
}
export interface StatusNode {
total: number
failed: number
success: number
}
export interface FacetsNode {
[key: string]: FacetNode
}

export interface FacetNode {
field: string
total: number
missing: number
other: number
terms: FacetTerm[]
}

export interface FacetTerm {
term: string
count: number
}

export interface Hit {
id: string
score: number
fields: HitFieldset
}

export enum ResultType {
LiveSet = 'LiveSet'
}

export type HitFieldset = LiveSetResult
22 changes: 22 additions & 0 deletions frontend/src/plugins/search/result/result_live_set.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { ResultType } from '@/plugins/search/result/index'

export interface LiveSetResult {
id: string
type: ResultType.LiveSet
tags?: string[]

displayName?: string
filename?: string
path?: string
majorVersion?: string
minorVersion?: string
creator?: string
revision?: string

scaleRootNote?: string
scaleName?: string
scale?: string

inKey?: boolean
tempo?: number
}
Loading

0 comments on commit d79da3d

Please sign in to comment.