Skip to content

Commit

Permalink
Merge pull request #62 from oramasearch/feature/orm-1814
Browse files Browse the repository at this point in the history
Feature/orm 1814 - Events
  • Loading branch information
rjborba authored Nov 24, 2024
2 parents 08d053a + 8953071 commit b5ed276
Show file tree
Hide file tree
Showing 24 changed files with 424 additions and 121 deletions.
18 changes: 14 additions & 4 deletions apps/demo-react/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import React from 'react'
import { OramaChatBox, OramaSearchBox, OramaSearchButton } from '@orama/react-components'
import './App.css'

function App() {
const [open, setOpen] = React.useState(false)
return (
<>
<main>
Expand All @@ -29,6 +27,8 @@ function App() {
endpoint: 'https://cloud.orama.run/v1/indexes/recipes-m7w9mm',
}}
style={{ height: '600px' }}
onAnswerSourceClick={(e: Event) => console.log(e)}
onAnswerGenerated={(e: Event) => console.log(e)}
/>
</div>
</section>
Expand Down Expand Up @@ -59,13 +59,23 @@ function App() {
<section>
<div className="component-row">
<OramaSearchBox
open={open}
colorScheme="system"
onSearchboxClosed={() => setOpen(false)}
index={{
api_key: 'LerNlbp6379jVKaPs4wt2nZT4MJZbU1J',
endpoint: 'https://cloud.orama.run/v1/indexes/docs-orama-b3f5xd',
}}
onSearchCompleted={(e: Event) => console.log(e)}
onSearchResultClick={(e: Event) => {
console.log(e)
e.preventDefault()

console.log('Prevented')
}}
onAnswerGenerated={(e: Event) => console.log(e)}
onAnswerSourceClick={(e: Event) => {
console.log(e)
e.preventDefault()
}}
/>
</div>
</section>
Expand Down
23 changes: 16 additions & 7 deletions packages/ui-stencil-vue/lib/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export const OramaChat = /*@__PURE__*/ defineContainer<JSX.OramaChat>('orama-cha
'defaultTerm',
'focusInput',
'suggestions',
'systemPrompts'
'systemPrompts',
'answerGenerated'
]);


Expand All @@ -48,7 +49,9 @@ export const OramaChatBox = /*@__PURE__*/ defineContainer<JSX.OramaChatBox>('ora
'sourcesMap',
'suggestions',
'autoFocus',
'systemPrompts'
'systemPrompts',
'answerGenerated',
'answerSourceClick'
]);


Expand All @@ -61,7 +64,8 @@ export const OramaChatButton = /*@__PURE__*/ defineContainer<JSX.OramaChatButton


export const OramaChatMessagesContainer = /*@__PURE__*/ defineContainer<JSX.OramaChatMessagesContainer>('orama-chat-messages-container', undefined, [
'interactions'
'interactions',
'answerGenerated'
]);


Expand Down Expand Up @@ -137,7 +141,9 @@ export const OramaSearch = /*@__PURE__*/ defineContainer<JSX.OramaSearch>('orama
'linksRel',
'disableChat',
'highlightTitle',
'highlightDescription'
'highlightDescription',
'searchCompleted',
'answerGenerated'
]);


Expand All @@ -162,7 +168,10 @@ export const OramaSearchBox = /*@__PURE__*/ defineContainer<JSX.OramaSearchBox>(
'searchPlaceholder',
'suggestions',
'searchParams',
'searchboxClosed'
'searchCompleted',
'searchResultClick',
'answerGenerated',
'answerSourceClick'
]);


Expand All @@ -185,7 +194,7 @@ export const OramaSearchResults = /*@__PURE__*/ defineContainer<JSX.OramaSearchR
'error',
'highlightTitle',
'highlightDescription',
'oramaItemClick'
'searchResultClick'
]);


Expand All @@ -202,7 +211,7 @@ export const OramaSources = /*@__PURE__*/ defineContainer<JSX.OramaSources>('ora
'linksTarget',
'linksRel',
'sourcesMap',
'sourceItemClick'
'answerSourceClick'
]);


Expand Down
2 changes: 1 addition & 1 deletion packages/ui-stencil/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"dependencies": {
"@orama/highlight": "^0.1.6",
"@orama/orama": "^2.0.23",
"@oramacloud/client": "1.3.17",
"@oramacloud/client": "^2.1.0",
"@phosphor-icons/webcomponents": "^2.1.5",
"@stencil/core": "^4.19.0",
"@stencil/store": "^2.0.16",
Expand Down
114 changes: 100 additions & 14 deletions packages/ui-stencil/src/components.d.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class OramaSources {
@State() isCarouselScrollAtEnd = false
@State() isCarouselScrollAtStart = false

@Event() sourceItemClick: EventEmitter<SearchResult>
@Event({ bubbles: true, composed: true, cancelable: true }) answerSourceClick: EventEmitter<SearchResult>

// TODO: Move this to utils
private buildUrl(path: string): string {
Expand Down Expand Up @@ -90,6 +90,11 @@ export class OramaSources {

private handleCarouselMove(direction: 'forward' | 'backwards') {
const carousel = this.carouselSourceRef

if (!carousel) {
return
}

const items = carousel.getElementsByClassName('source-inner-wrapper')

if (direction === 'forward') {
Expand Down Expand Up @@ -117,16 +122,26 @@ export class OramaSources {
this.computeCarouselArrowsVisibility()
}

handleItemClick = (item: SearchResult) => {
if (item?.path) {
this.sourceItemClick.emit(item)
} else {
handleItemClick = (originalOnClickEvent: MouseEvent, item: SearchResult) => {
const answerSourceClick = this.answerSourceClick.emit(item)

if (answerSourceClick.defaultPrevented) {
originalOnClickEvent.preventDefault()
return
}

if (!item?.path) {
throw new Error('No path found')
}
}

computeCarouselArrowsVisibility() {
const carousel = this.carouselSourceRef

if (!carousel) {
return
}

const items = carousel.getElementsByClassName('source-inner-wrapper')

this.isCarouselScrollAtEnd = !this.getNextItemCarousel(carousel, items)
Expand All @@ -138,9 +153,12 @@ export class OramaSources {
})

componentDidLoad() {
this.carouselSourceRef.addEventListener('scroll', this.handleCarouselScroll)
this.carouselSourceRef?.addEventListener('scroll', this.handleCarouselScroll)
this.computeCarouselArrowsVisibility()
this.resizeObserver.observe(this.carouselSourceRef)

if (this.carouselSourceRef) {
this.resizeObserver.observe(this.carouselSourceRef)
}
}

disconnectedCallback() {
Expand Down Expand Up @@ -214,7 +232,7 @@ export class OramaSources {
target={this.linksTarget}
rel={this.linksRel}
id={`source-${index}`}
onClick={() => this.handleItemClick(source)}
onClick={(onClickEvent) => this.handleItemClick(onClickEvent, source)}
>
<orama-text as="h3" styledAs="span" class="source-title">
{source[this.sourcesMap.title]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@

## Events

| Event | Description | Type |
| ----------------- | ----------- | -------------------------------------------------------------------------------- |
| `sourceItemClick` | | `CustomEvent<{ id: string; title: string; description: string; path: string; }>` |
| Event | Description | Type |
| ------------------- | ----------- | -------------------------------------------------------------------------------- |
| `answerSourceClick` | | `CustomEvent<{ id: string; title: string; description: string; path: string; }>` |


## Dependencies
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component, Host, Prop, h, Element, State } from '@stencil/core'
import { Component, Host, Prop, h, Element, State, type EventEmitter, Event } from '@stencil/core'
import { chatContext, type TChatInteraction } from '@/context/chatContext'
import type { OnSearchCompletedCallbackProps } from '@/types'

@Component({
tag: 'orama-chat-messages-container',
Expand All @@ -8,13 +9,20 @@ import { chatContext, type TChatInteraction } from '@/context/chatContext'
})
export class OramaChatMessagesContainer {
@Prop() interactions: TChatInteraction[]

@Event({ bubbles: true, composed: true }) answerGenerated: EventEmitter<OnSearchCompletedCallbackProps>

@Element() el: HTMLElement

@State() latestInteractionMinHeight = 0

// TODO: I'm not sure about having this here as we're breaking our rule of maintain service access only to the very top level component
onSuggestionClick = (suggestion: string) => {
chatContext.chatService?.sendQuestion(suggestion)
chatContext.chatService?.sendQuestion(suggestion, undefined, {
onAnswerGeneratedCallback(onAnswerGeneratedCallbackProps) {
this.answerGenerated.emit(onAnswerGeneratedCallbackProps)
},
})
}

resizeObserver = new ResizeObserver((entries) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
| `interactions` | -- | | `TChatInteraction[]` | `undefined` |


## Events

| Event | Description | Type |
| ----------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `answerGenerated` | | `CustomEvent<{ clientSearchParams: ClientSearchParams; result: { results: SearchResultBySection[]; resultsCount: number; facets: Facet[]; }; }>` |


## Dependencies

### Used by
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Component, Fragment, Listen, Host, Prop, State, Watch, h } from '@stencil/core'
import { Component, Fragment, Listen, Host, Prop, State, Watch, h, type EventEmitter, Event } from '@stencil/core'
import { chatContext, chatStore, TAnswerStatus } from '@/context/chatContext'
import type { SearchResult, SourcesMap } from '@/types'
import type { OnAnswerGeneratedCallbackProps, SearchResult, SourcesMap } from '@/types'
import '@phosphor-icons/webcomponents/dist/icons/PhPaperPlaneTilt.mjs'
import '@phosphor-icons/webcomponents/dist/icons/PhStopCircle.mjs'
import '@phosphor-icons/webcomponents/dist/icons/PhArrowDown.mjs'
Expand All @@ -23,6 +23,8 @@ export class OramaChat {
@Prop() suggestions?: string[]
@Prop() systemPrompts?: string[]

@Event({ bubbles: true, composed: true }) answerGenerated: EventEmitter<OnAnswerGeneratedCallbackProps>

@State() inputValue = ''
@State() showGoToBottomButton = false

Expand All @@ -34,7 +36,9 @@ export class OramaChat {
@Watch('defaultTerm')
handleDefaultTermChange() {
if (this.defaultTerm) {
chatContext.chatService?.sendQuestion(this.defaultTerm, this.systemPrompts)
chatContext.chatService?.sendQuestion(this.defaultTerm, this.systemPrompts, {
onAnswerGeneratedCallback: (params) => this.answerGenerated.emit(params),
})
}
}

Expand Down Expand Up @@ -229,7 +233,9 @@ export class OramaChat {
throw new Error('Chat Service is not initialized')
}

chatContext.chatService.sendQuestion(this.inputValue, this.systemPrompts)
chatContext.chatService.sendQuestion(this.inputValue, this.systemPrompts, {
onAnswerGeneratedCallback: (params) => this.answerGenerated.emit(params),
})
this.inputValue = ''
}

Expand All @@ -242,7 +248,9 @@ export class OramaChat {
throw new Error('Chat Service is not initialized')
}

chatContext.chatService.sendQuestion(suggestion)
chatContext.chatService.sendQuestion(suggestion, undefined, {
onAnswerGeneratedCallback: (params) => this.answerGenerated.emit(params),
})
this.inputValue = ''
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
| `systemPrompts` | -- | | `string[]` | `undefined` |


## Events

| Event | Description | Type |
| ----------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `answerGenerated` | | `CustomEvent<{ askParams: AskParams; query: string; sources: Results<unknown>; answer: string; segment: string; trigger: string; }>` |


## Dependencies

### Used by
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import type { Facet } from '@/types'
import { Component, h, Prop } from '@stencil/core'

// TODO: fix type
export type Facet = { name: string; count: number }

@Component({
tag: 'orama-facets',
styleUrl: 'orama-facets.scss',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export type SearchResultsProps = {
})
export class SearchResults {
@Element() el: HTMLUListElement
@Event() oramaItemClick: EventEmitter<SearchResult>
@Prop() sourceBaseUrl?: string
@Prop() linksTarget?: string = '_blank'
@Prop() linksRel?: string = 'noopener noreferrer'
Expand All @@ -30,6 +29,8 @@ export class SearchResults {
@Prop() highlightTitle?: HighlightOptions | false = false
@Prop() highlightDescription?: HighlightOptions | false = false

@Event({ bubbles: true, composed: true, cancelable: true }) searchResultClick: EventEmitter<SearchResult>

private highlighterTitle?: Highlight
private highlighterDescription?: Highlight

Expand All @@ -52,10 +53,15 @@ export class SearchResults {
return path
}

handleItemClick = (item: SearchResult) => {
if (item?.path) {
this.oramaItemClick.emit(item)
} else {
handleItemClick = (originalOnClickEvent: MouseEvent, item: SearchResult) => {
const searchResultClick = this.searchResultClick.emit(item)

if (searchResultClick.defaultPrevented) {
originalOnClickEvent.preventDefault()
return
}

if (!item?.path) {
throw new Error('No path found')
}
}
Expand Down Expand Up @@ -143,7 +149,7 @@ export class SearchResults {
target={this.linksTarget}
rel={this.linksRel}
id={`search-result-${result.id}`}
onClick={() => this.handleItemClick(result)}
onClick={(onClickEvent) => this.handleItemClick(onClickEvent, result)}
>
<div style={{ flexShrink: '0' }}>
<ph-files size="20px" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@

## Events

| Event | Description | Type |
| ---------------- | ----------- | -------------------------------------------------------------------------------- |
| `oramaItemClick` | | `CustomEvent<{ id: string; title: string; description: string; path: string; }>` |
| Event | Description | Type |
| ------------------- | ----------- | -------------------------------------------------------------------------------- |
| `searchResultClick` | | `CustomEvent<{ id: string; title: string; description: string; path: string; }>` |


## Dependencies
Expand Down
Loading

0 comments on commit b5ed276

Please sign in to comment.