Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor messages #13

Merged
merged 6 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions apps/storybook/stories/public/orama-chat-box.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
import type { StoryObj, Meta } from '@storybook/web-components'
import type { Components } from '@orama/wc-components'

const demoIndexes = {
orama: {
api_key: '6kHcoevr3zkbBmC2hHqlcNQrOgejS4ds',
endpoint: 'https://cloud.orama.run/v1/indexes/orama-docs-pgjign',
},
recipes: {
api_key: 'yl2JSnjLNBV6FVfUWEyadpjFr6KzPiDR',
endpoint: 'https://cloud.orama.run/v1/indexes/recipes-m7w9mm',
},
videogames: {
api_key: 'WL7pKdEqCTPf3G2412x8ecneqVbnkklr',
endpoint: 'https://cloud.orama.foo/v1/indexes/videogames-rk139h',
},
}
const meta: Meta<Components.OramaChatBox> = {
title: 'Public/ChatBox',
component: 'orama-chat-box',
argTypes: {
index: {
options: Object.keys(demoIndexes),
mapping: demoIndexes,
control: { type: 'select' },
},
},
} satisfies Meta

export default meta
Expand All @@ -12,8 +33,8 @@ type Story = StoryObj<Components.OramaChatBox>
export const ChatBox: Story = {
args: {
index: {
api_key: '6kHcoevr3zkbBmC2hHqlcNQrOgejS4ds',
endpoint: 'https://cloud.orama.run/v1/indexes/orama-docs-pgjign',
api_key: demoIndexes.orama.api_key,
endpoint: demoIndexes.orama.endpoint,
},
},
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"build": "turbo run build",
"build:storybook": "turbo run build --filter=storybook",
"clean": "turbo run clean",
"dev": "turbo run dev --filter=ui-stencil --filter=storybook",
"dev": "turbo run dev --filter=@orama/wc-components --filter=storybook",
"dev:demo": "turbo run dev --filter=demo-react --filter=demo-vue --filter=demo-angular",
"dev:all": "turbo run dev",
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
Expand Down
4 changes: 2 additions & 2 deletions packages/ui-stencil-vue/lib/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const OramaChat = /*@__PURE__*/ defineContainer<JSX.OramaChat>('orama-cha


export const OramaChatAssistentMessage = /*@__PURE__*/ defineContainer<JSX.OramaChatAssistentMessage>('orama-chat-assistent-message', undefined, [
'message'
'interaction'
]);


Expand All @@ -41,7 +41,7 @@ export const OramaChatSuggestions = /*@__PURE__*/ defineContainer<JSX.OramaChatS


export const OramaChatUserMessage = /*@__PURE__*/ defineContainer<JSX.OramaChatUserMessage>('orama-chat-user-message', undefined, [
'message'
'interaction'
]);


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 @@ -24,7 +24,7 @@
},
"types": "dist/types/index.d.ts",
"dependencies": {
"@oramacloud/client": "1.3.8",
"@oramacloud/client": "1.3.9",
"@phosphor-icons/webcomponents": "^2.1.5",
"@stencil/core": "^4.19.0",
"@stencil/store": "^2.0.16",
Expand Down
12 changes: 6 additions & 6 deletions packages/ui-stencil/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
*/
import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
import { ButtonProps } from "./components/internal/orama-button/orama-button";
import { TChatMessage } from "./context/chatContext";
import { TChatInteraction } from "./context/chatContext";
import { CloudIndexConfig, ResultMap, SearchResult, SearchResultBySection } from "./types/index";
import { Facet } from "./components/internal/orama-facets/orama-facets";
import { InputProps } from "./components/internal/orama-input/orama-input";
import { TThemeOverrides } from "./config/theme";
import { SearchResultsProps } from "./components/internal/orama-search-results/orama-search-results";
import { TextProps } from "./components/internal/orama-text/orama-text";
export { ButtonProps } from "./components/internal/orama-button/orama-button";
export { TChatMessage } from "./context/chatContext";
export { TChatInteraction } from "./context/chatContext";
export { CloudIndexConfig, ResultMap, SearchResult, SearchResultBySection } from "./types/index";
export { Facet } from "./components/internal/orama-facets/orama-facets";
export { InputProps } from "./components/internal/orama-input/orama-input";
Expand All @@ -33,7 +33,7 @@ export namespace Components {
interface OramaChat {
}
interface OramaChatAssistentMessage {
"message": TChatMessage;
"interaction": TChatInteraction;
}
interface OramaChatBox {
"index": CloudIndexConfig;
Expand All @@ -45,7 +45,7 @@ export namespace Components {
"suggestions": string[];
}
interface OramaChatUserMessage {
"message": TChatMessage;
"interaction": TChatInteraction;
}
interface OramaDotsLoader {
}
Expand Down Expand Up @@ -308,7 +308,7 @@ declare namespace LocalJSX {
interface OramaChat {
}
interface OramaChatAssistentMessage {
"message"?: TChatMessage;
"interaction"?: TChatInteraction;
}
interface OramaChatBox {
"index"?: CloudIndexConfig;
Expand All @@ -320,7 +320,7 @@ declare namespace LocalJSX {
"suggestions"?: string[];
}
interface OramaChatUserMessage {
"message"?: TChatMessage;
"interaction"?: TChatInteraction;
}
interface OramaDotsLoader {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ orama-chat-assistent-message {
margin: 0 var(--spacing-l, $spacing-l);
}

.message-error {
text-align: center;
padding: var(--spacing-l, $spacing-l) var(--spacing-s, $spacing-s);
background: var(--background-color-secondary, background-color('secondary'));
border-radius: var(--radius-m, $radius-m);
margin: 0 var(--spacing-l, $spacing-l);

ph-warning {
display: block;
color: var(--text-color-inactive, text-color('inactive'));
}
}

.message-actions {
display: flex;
margin-top: var(--spacing-xl, $spacing-xl);
Expand All @@ -19,10 +32,6 @@ orama-chat-assistent-message {

.sources-wrapper {
display: flex;

// TODO: Remove None display when the time comes
display: none;

margin-top: var(--spacing-s, $spacing-s);
padding: 0 var(--spacing-l, $spacing-l);
gap: var(--spacing-s, $spacing-s);
Expand All @@ -36,6 +45,7 @@ orama-chat-assistent-message {
width: 180px;
flex-grow: 0;
flex-shrink: 0;
text-decoration: none;

& ::after {
content: '';
Expand Down Expand Up @@ -64,6 +74,10 @@ orama-chat-assistent-message {
animation: rotate360 2s ease-in-out 1;
}

.sr-only {
@include screen-reader-only();
}

@keyframes rotate360 {
0% {
transform: rotate(0deg);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Component, Host, Listen, Prop, State, h } from '@stencil/core'
import type { TChatMessage } from '@/context/chatContext'
import { Component, Host, Prop, State, h } from '@stencil/core'
import type { TChatInteraction } from '@/context/chatContext'
import '@phosphor-icons/webcomponents/dist/icons/PhCopy.mjs'
import '@phosphor-icons/webcomponents/dist/icons/PhArrowsClockwise.mjs'
import '@phosphor-icons/webcomponents/dist/icons/PhThumbsDown.mjs'
import '@phosphor-icons/webcomponents/dist/icons/PhWarning.mjs'
import { chatContext } from '@/context/chatContext'
import { copyToClipboard } from '@/utils/utils'

@Component({
Expand All @@ -11,20 +13,20 @@ import { copyToClipboard } from '@/utils/utils'
shadow: true,
})
export class OramaChatAssistentMessage {
@Prop() message: TChatMessage
@Prop() interaction: TChatInteraction

@State() isCopied = false
handleCopyToClipboard = () => {
this.isCopied = true
setTimeout(() => (this.isCopied = false), 1000)
copyToClipboard(this.message.content)
copyToClipboard(this.interaction.response)
}

@State() isRetrying = false
handleRetryMessage = () => {
// todo: replace with actual retry logic
setTimeout(() => (this.isRetrying = false), 2000)
this.isRetrying = !this.isRetrying
chatContext.chatService?.regenerateLatest()
}

@State() isDisliked = false
Expand All @@ -34,78 +36,88 @@ export class OramaChatAssistentMessage {
}

render() {
const isLastInteraction =
this.interaction.interactionId === chatContext.interactions[chatContext.interactions.length - 1].interactionId

if (this.interaction.status === 'loading') {
return (
<div class="message-wrapper">
<orama-dots-loader />
</div>
)
}
if (this.interaction.status === 'error') {
return (
<div class="message-error">
<ph-warning size={16} />
<orama-text styledAs="span" inactive>
An error occurred while trying to search. Please try again.
</orama-text>
</div>
)
}

if (!this.interaction.response) {
return
}

return (
<Host>
<div class="message-wrapper">
<orama-markdown content={this.message.content} />
<div class="message-actions">
<orama-button
type="button"
variant="icon"
onClick={this.handleCopyToClipboard}
onKeyDown={this.handleCopyToClipboard}
withTooltip={this.isCopied ? 'Copied!' : undefined}
aria-label="Copy message"
>
<ph-copy />
</orama-button>
<orama-button
type="button"
variant="icon"
onClick={this.handleRetryMessage}
onKeyDown={this.handleRetryMessage}
aria-label="Retry message"
>
<span class={this.isRetrying ? 'retrying' : ''}>
{this.isRetrying ? <ph-arrows-clockwise weight="fill" /> : <ph-arrows-clockwise />}
</span>
</orama-button>
<orama-button
type="button"
variant="icon"
onClick={this.handleDislikeMessage}
onKeyDown={this.handleDislikeMessage}
aria-label="Dislike message"
>
{this.isDisliked ? <ph-thumbs-down weight="fill" /> : <ph-thumbs-down />}
</orama-button>
</div>
<orama-markdown content={this.interaction.response} />
{this.interaction.status === 'done' && (
<div class="message-actions">
<orama-button
type="button"
variant="icon"
onClick={this.handleCopyToClipboard}
onKeyDown={this.handleCopyToClipboard}
withTooltip={this.isCopied ? 'Copied!' : undefined}
aria-label="Copy message"
>
<ph-copy />
</orama-button>
{isLastInteraction && (
<orama-button
type="button"
variant="icon"
onClick={this.handleRetryMessage}
onKeyDown={this.handleRetryMessage}
aria-label="Retry message"
>
<span class={this.isRetrying ? 'retrying' : ''}>
{this.isRetrying ? <ph-arrows-clockwise weight="fill" /> : <ph-arrows-clockwise />}
</span>
</orama-button>
)}
<orama-button
type="button"
variant="icon"
onClick={this.handleDislikeMessage}
onKeyDown={this.handleDislikeMessage}
aria-label="Dislike message"
>
{this.isDisliked ? <ph-thumbs-down weight="fill" /> : <ph-thumbs-down />}
</orama-button>
</div>
)}
</div>
<div class="sources-wrapper">
<h2 class="sr-only">Sources</h2>
<div class="source">
<orama-text as="h3" styledAs="span" class="source-title">
Title title title
</orama-text>
<orama-text as="p" styledAs="span" class="source-subtitle">
Subtitle subtitle subtitle
</orama-text>
</div>
<div class="source">
<orama-text as="h3" styledAs="span" class="source-title">
Title title title
</orama-text>
<orama-text as="p" styledAs="span" class="source-subtitle">
Subtitle subtitle subtitle
</orama-text>
</div>
<div class="source">
<orama-text as="h3" styledAs="span" class="source-title">
Title title title
</orama-text>
<orama-text as="p" styledAs="span" class="source-subtitle">
Subtitle subtitle subtitle
</orama-text>
{!!this.interaction.sources?.length && this.interaction.status === 'done' && (
<div class="sources-wrapper">
<h2 class="sr-only">Sources</h2>
{this.interaction.sources.map((source, index) => (
// biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
<a href={source.path} class="source" key={`source-${index}`} target="_blank" rel="noopener noreferrer">
<orama-text as="h3" styledAs="span" class="source-title">
{source.title}
</orama-text>
<orama-text as="p" styledAs="span" class="source-subtitle">
{source.description}
</orama-text>
</a>
))}
</div>
<div class="source">
<orama-text as="h3" styledAs="span" class="source-title">
Title title title
</orama-text>
<orama-text as="p" styledAs="span" class="source-subtitle">
Subtitle subtitle subtitle
</orama-text>
</div>
</div>
)}
</Host>
)
}
Expand Down
Loading
Loading