Skip to content

Commit

Permalink
Merge pull request #111 from iceljc/features/refine-chat-window
Browse files Browse the repository at this point in the history
Features/refine chat window
  • Loading branch information
Oceania2018 authored Apr 12, 2024
2 parents 1a2518c + 1d67dc6 commit 3cbaca0
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 74 deletions.
4 changes: 2 additions & 2 deletions src/lib/common/LoadingToComplete.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@

{#if isComplete}
<div class="alert-container">
<Alert class="success">
<Alert color="success">
<div>{successText}</div>
</Alert>
</div>
{/if}

{#if isError}
<div class="alert-container">
<Alert class="error">
<Alert color="danger">
<div>{errorText}</div>
</Alert>
</div>
Expand Down
1 change: 0 additions & 1 deletion src/lib/scss/custom/components/_alert.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
z-index: 8888;

.alert {
color: white;
text-align: center;
}

Expand Down
52 changes: 29 additions & 23 deletions src/lib/scss/custom/pages/_chat.scss
Original file line number Diff line number Diff line change
Expand Up @@ -169,15 +169,15 @@
flex-direction: column;
width: 80%;

.video-group-container {
.video-option-container {
display: flex;
flex-wrap: wrap;
gap: 5px;

.video-element-card {
border: none;
box-shadow: none;
flex: 1 1 400px;
flex: 1 1 300px;

.card-body {
padding: 0 !important;
Expand Down Expand Up @@ -207,7 +207,7 @@
}
}

.button-group-container {
.plain-option-container {
display: flex;
flex-wrap: wrap;

Expand All @@ -230,7 +230,7 @@
}
}

.card-group-container {
.complex-option-container {
display: flex;
flex-wrap: wrap;
gap: 5px;
Expand All @@ -248,26 +248,32 @@
max-width: 100%;
}

.card-element-title {
font-size: 0.8rem;
font-weight: 700;
height: 30%;
}

.card-element-subtitle {
font-size: 0.7rem;
font-weight: 500;
height: 8%;
}

.card-option-group {
margin-top: 5px;
.card-element-body {
display: flex;
flex-direction: column;
justify-content: space-evenly;
gap: 5px;
padding: 10px 15px;

.btn {
display: block;
margin-left: 0px !important;
text-align: left;
border-radius: 10px;
.card-element-title {
font-size: 0.8rem;
font-weight: 700;
}

.card-element-subtitle {
font-size: 0.7rem;
font-weight: 500;
}

.card-option-group {
margin-top: 5px;

.btn {
display: block;
margin-left: 0px !important;
text-align: left;
border-radius: 10px;
}
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions src/routes/chat/[agentId]/[conversationId]/chat-box.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import 'overlayscrollbars/overlayscrollbars.css';
import { OverlayScrollbars } from 'overlayscrollbars';
import { page } from '$app/stores';
import { onMount, tick } from 'svelte';
import { onMount, setContext, tick } from 'svelte';
import Viewport from 'svelte-viewport-info';
import { PUBLIC_LIVECHAT_ENTRY_ICON } from '$env/static/public';
import { USER_SENDERS } from '$lib/helpers/constants';
Expand Down Expand Up @@ -107,6 +107,10 @@
let isThinking = false;
let isLite = false;
let isFrame = false;
setContext('chat-window-context', {
autoScrollToBottom: autoScrollToBottom
});
onMount(async () => {
dialogs = await GetDialogs(params.conversationId);
Expand Down Expand Up @@ -903,9 +907,8 @@
<div class="msg-container">
<RichContent
message={message}
displayExtraElements={message.message_id === lastBotMsg?.message_id && !isSendingMsg && !isThinking}
displayOptionElements={message.message_id === lastBotMsg?.message_id && !isSendingMsg && !isThinking}
disableOption={isSendingMsg || isThinking}
refresh={autoScrollToBottom}
onConfirm={confirmSelectedOption}
/>
<ChatAttachment
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script>
import { Card, CardBody } from "@sveltestrap/sveltestrap";
import { onMount } from "svelte";
import { getContext, onMount } from "svelte";
/** @type {boolean} */
export let disableOption = false;
Expand All @@ -11,26 +11,29 @@
/** @type {(args0: string, args1: string) => any} */
export let onConfirm;
/** @type {() => any} */
export let refresh = () => {};
/** @type {any[]} */
let cards = [];
/** @type {any[]} */
let buttons = [];
const { autoScrollToBottom } = getContext('chat-window-context');
onMount(() => {
reset();
collectOptions(options);
refresh && refresh();
collectOptions(options)
autoScrollToBottom?.();
});
/** @param {any[]} options */
function collectOptions(options) {
cards = options?.map(op => {
cards = options?.filter(op => !!op.title || !!op.subtitle)?.map(op => {
// @ts-ignore
const options = op.buttons?.filter(op => !!op.title && !!op.payload)?.map(x => {
const options = op.buttons?.filter(x => !!x.title && !!x.payload)?.map(x => {
return {
title: x.title,
payload: x.payload
payload: x.payload,
is_primary: x.is_primary,
is_secondary: x.is_secondary,
};
}) || [];
Expand All @@ -40,6 +43,18 @@
options: options
};
}) || [];
buttons = options?.filter(op => !!!op.title && !!!op.subtitle)?.flatMap(op => {
// @ts-ignore
return op.buttons?.filter(x => !!x.title && !!x.payload)?.map(x => {
return {
title: x.title,
payload: x.payload,
is_primary: x.is_primary,
is_secondary: x.is_secondary,
};
}) || [];;
}) || [];
}
/**
Expand All @@ -66,21 +81,21 @@
</script>
{#if cards.length > 0}
<div class="card-group-container">
<div class="complex-option-container">
{#each cards as card, idx (idx)}
<Card class="card-element">
<CardBody>
<CardBody class="card-element-body">
{#if !!card.title}
<div class="card-element-title mb-3">{card.title}</div>
<div class="card-element-title hide-text">{card.title}</div>
{/if}
{#if !!card.subtitle}
<div class="card-element-subtitle mb-3">{card.subtitle}</div>
<div class="card-element-subtitle hide-text">{card.subtitle}</div>
{/if}
{#if card.options?.length > 0}
<div class="card-option-group">
{#each card.options as option, i (i)}
<button
class="btn btn-outline-primary btn-sm m-1"
class={`btn btn-sm m-1 ${option.is_secondary ? 'btn-outline-secondary': 'btn-outline-primary'}`}
disabled={disableOption}
on:click={(e) => handleClickOption(e, option)}
>
Expand All @@ -94,3 +109,17 @@
{/each}
</div>
{/if}
{#if buttons.length > 0}
<div class="plain-option-container" style="margin-top: 5px;">
{#each buttons as option, index}
<button
class={`btn btn-sm m-1 ${option.is_secondary ? 'btn-outline-secondary': 'btn-outline-primary'}`}
disabled={disableOption}
on:click={(e) => handleClickOption(e, option)}
>
{option.title}
</button>
{/each}
</div>
{/if}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
import { onMount } from "svelte";
import { getContext, onMount } from "svelte";
import SveltePlayer from "svelte-player";
import { Card, CardBody } from "@sveltestrap/sveltestrap";
import { ElementType } from "$lib/helpers/enums";
Expand All @@ -14,10 +14,7 @@
export let options = [];
/** @type {(args0: string, args1: string) => any} */
export let onConfirm;
/** @type {() => any} */
export let refresh = () => {};
export let onConfirm = () => {};
/** @type {string} */
export let confirmBtnText = 'Continue';
Expand All @@ -33,10 +30,12 @@
/** @type {any[]} */
let videoOptions = [];
const { autoScrollToBottom } = getContext('chat-window-context');
onMount(() => {
reset();
collectOptions(options);
refresh && refresh();
autoScrollToBottom?.();
});
/** @param {any[]} options */
Expand Down Expand Up @@ -113,7 +112,7 @@
{#if videoOptions.length > 0}
<div>
<div class="video-group-container">
<div class="video-option-container">
{#each videoOptions as video, index}
<Card class="video-element-card">
<CardBody>
Expand All @@ -131,7 +130,7 @@
{/if}
{#if plainOptions.length > 0}
<div class="button-group-container">
<div class="plain-option-container">
{#each plainOptions as option, index}
<button
class={`btn btn-sm m-1 ${option.is_secondary ? 'btn-outline-secondary': 'btn-outline-primary'}`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,38 @@
export let message;
/** @type {boolean} */
export let displayExtraElements = false;
export let displayOptionElements = false;
/** @type {boolean} */
export let disableOption = false;
/** @type {(args0: string, args1: string) => any} */
export let onConfirm = () => {};
/** @type {() => any} */
export let refresh = () => {};
/** @type {boolean} */
let isComplexElement = false;
let isMultiSelect = false;
/** @type {any[]} */
let options = [];
$: {
const isGeneric = message?.rich_content?.message?.rich_type === RichType.Generic;
// @ts-ignore
const hasSuboptions = message?.rich_content?.message?.elements?.some(x => x.buttons?.length > 0) || false;
isComplexElement = isGeneric && hasSuboptions;
if (displayOptionElements) {
const richType = message?.rich_content?.message?.rich_type;
if (richType === RichType.QuickReply) {
options = message?.rich_content?.message?.quick_replies;
} else if (richType === RichType.Button) {
options = message?.rich_content?.message?.buttons;
} else if (richType === RichType.MultiSelect) {
options = message?.rich_content?.message?.options;
isMultiSelect = true;
} else if (richType === RichType.Generic) {
options = message?.rich_content?.message?.elements;
// @ts-ignore
isComplexElement = message?.rich_content?.message?.elements?.some(x => x.buttons?.length > 0) || false;
}
}
}
/**
Expand All @@ -44,18 +57,10 @@
</div>
</div>
{#if displayExtraElements}
{#if message?.rich_content?.message?.rich_type === RichType.QuickReply}
<RcPlainOptions options={message?.rich_content?.message?.quick_replies} disableOption={disableOption} onConfirm={handleConfirm} refresh={refresh} />
{:else if message?.rich_content?.message?.rich_type === RichType.Button}
<RcPlainOptions options={message?.rich_content?.message?.buttons} disableOption={disableOption} onConfirm={handleConfirm} refresh={refresh} />
{:else if message?.rich_content?.message?.rich_type === RichType.MultiSelect}
<RcPlainOptions options={message?.rich_content?.message?.options} isMultiSelect disableOption={disableOption} onConfirm={handleConfirm} refresh={refresh} />
{:else if message?.rich_content?.message?.rich_type === RichType.Generic}
{#if isComplexElement}
<RcComplexOptions options={message?.rich_content?.message?.elements} disableOption={disableOption} onConfirm={handleConfirm} refresh={refresh} />
{:else}
<RcPlainOptions options={message?.rich_content?.message?.elements} disableOption={disableOption} onConfirm={handleConfirm} refresh={refresh} />
{/if}
{#if displayOptionElements}
{#if !isComplexElement}
<RcPlainOptions options={options} isMultiSelect={isMultiSelect} disableOption={disableOption} onConfirm={handleConfirm} />
{:else}
<RcComplexOptions options={options} disableOption={disableOption} onConfirm={handleConfirm} />
{/if}
{/if}
Loading

0 comments on commit 3cbaca0

Please sign in to comment.