clean up frontend
This commit is contained in:
9
app/components/chat/new-conversation.hbs
Normal file
9
app/components/chat/new-conversation.hbs
Normal file
@@ -0,0 +1,9 @@
|
||||
<AuButton
|
||||
@icon="add"
|
||||
@size={{if @large "large"}}
|
||||
@loading={{this.create.isRunning}}
|
||||
...attributes
|
||||
{{on "click" (perform this.create)}}
|
||||
>
|
||||
Nieuw gesprek
|
||||
</AuButton>
|
||||
@@ -1,8 +1,8 @@
|
||||
import Controller from '@ember/controller';
|
||||
import Component from '@glimmer/component';
|
||||
import { service } from '@ember/service';
|
||||
import { task } from 'ember-concurrency';
|
||||
|
||||
export default class ConversationsController extends Controller {
|
||||
export default class ChatNewConversation extends Component {
|
||||
@service store;
|
||||
@service router;
|
||||
@service currentSession;
|
||||
29
app/components/chat/sidebar.hbs
Normal file
29
app/components/chat/sidebar.hbs
Normal file
@@ -0,0 +1,29 @@
|
||||
<div class="au-c-sidebar">
|
||||
<div class="au-c-sidebar__header">
|
||||
<AuHeading @level="2" @skin="3">Gesprekken</AuHeading>
|
||||
</div>
|
||||
<div class="au-c-sidebar__content">
|
||||
<ul class="au-c-list-navigation chat-sidebar__list">
|
||||
{{#each @conversations as |conversation|}}
|
||||
<li class="au-c-list-navigation__item">
|
||||
<AuNavigationLink
|
||||
@route="conversation"
|
||||
@model={{conversation.id}}
|
||||
class="chat-sidebar__link"
|
||||
>
|
||||
<span class="chat-sidebar__title">
|
||||
{{if conversation.title conversation.title "Nieuw gesprek"}}
|
||||
</span>
|
||||
<span class="chat-sidebar__meta">
|
||||
{{format-datetime conversation.lastActivity}}
|
||||
</span>
|
||||
</AuNavigationLink>
|
||||
</li>
|
||||
{{else}}
|
||||
<li class="au-c-list-navigation__item">
|
||||
<p class="au-u-muted chat-sidebar__empty">Nog geen gesprekken.</p>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,6 +1,9 @@
|
||||
{{! The list, the composer, the poll loop }}
|
||||
<div class="chat-window">
|
||||
<div class="chat-window__messages">
|
||||
<div
|
||||
class="chat-window__messages"
|
||||
{{chat-scroll-bottom this.conversation.id this.messages.length}}
|
||||
>
|
||||
{{#unless this.messages.length}}
|
||||
<p class="au-u-muted">{{@assistant.description}}</p>
|
||||
{{/unless}}
|
||||
|
||||
16
app/helpers/format-datetime.js
Normal file
16
app/helpers/format-datetime.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import { helper } from '@ember/component/helper';
|
||||
|
||||
const DATE = new Intl.DateTimeFormat('nl-BE', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
});
|
||||
const TIME = new Intl.DateTimeFormat('nl-BE', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
});
|
||||
|
||||
export default helper(([date]) => {
|
||||
if (!date) return '';
|
||||
return `${DATE.format(date)} ${TIME.format(date)}`;
|
||||
});
|
||||
17
app/modifiers/chat-scroll-bottom.js
Normal file
17
app/modifiers/chat-scroll-bottom.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import Modifier from 'ember-modifier';
|
||||
|
||||
// Keeps the chat scrolled to the bottom: on insert, when another
|
||||
// conversation is opened, and when the number of messages changes. The same
|
||||
// conversation and count (e.g. a poll reload) leaves the scroll position
|
||||
// alone, so reading history is not interrupted.
|
||||
export default class ChatScrollBottom extends Modifier {
|
||||
lastKey = null;
|
||||
|
||||
modify(element, positional) {
|
||||
const [id, count] = positional;
|
||||
const key = `${id}:${count}`;
|
||||
if (key === this.lastKey) return;
|
||||
this.lastKey = key;
|
||||
element.scrollTop = element.scrollHeight;
|
||||
}
|
||||
}
|
||||
@@ -10,13 +10,17 @@ export default class ConversationRoute extends Route {
|
||||
}
|
||||
|
||||
async model({ id }) {
|
||||
const [conversation, agents] = await Promise.all([
|
||||
const [conversation, agents, conversations] = await Promise.all([
|
||||
this.store.findRecord('chat-conversation', id, {
|
||||
include: 'messages.attachments',
|
||||
reload: true,
|
||||
}),
|
||||
this.store.query('chat-agent', { 'page[size]': 1 }),
|
||||
this.store.query('chat-conversation', {
|
||||
sort: '-last-activity',
|
||||
'page[size]': 50,
|
||||
}),
|
||||
]);
|
||||
return { conversation, assistant: agents[0] };
|
||||
return { conversation, assistant: agents[0], conversations };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,10 +27,97 @@
|
||||
@import "@appuniversum/ember-appuniversum/styles/a-utilities";
|
||||
|
||||
// CHAT
|
||||
|
||||
/* ==================================
|
||||
#CHAT LAYOUT
|
||||
Sidebar with the conversation overview (1/5 of the screen) next to a
|
||||
content area that fills the rest of the screen under the main header.
|
||||
================================== */
|
||||
.chat-sidebar {
|
||||
@include mq(medium) {
|
||||
flex-basis: 20%;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
/* The conversations are listed as navigation: title on top, date + time in
|
||||
subscript. Titles are truncated when they do not fit. */
|
||||
.chat-sidebar__list {
|
||||
display: block;
|
||||
}
|
||||
.chat-sidebar__link {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 0.1rem;
|
||||
}
|
||||
.chat-sidebar__title {
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.chat-sidebar__meta {
|
||||
font-size: var(--au-tiny);
|
||||
color: var(--au-gray-600);
|
||||
text-decoration: none;
|
||||
}
|
||||
.chat-sidebar__empty {
|
||||
margin: 0;
|
||||
padding: $au-unit-tiny * 1.5 $au-unit-small;
|
||||
|
||||
@include mq(medium) {
|
||||
padding: $au-unit-small $au-unit-small + $au-unit-tiny;
|
||||
}
|
||||
}
|
||||
|
||||
.chat-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* Bar above the chat: the conversation title, truncated, and a button to
|
||||
start a new conversation. */
|
||||
.chat-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
padding: 0.6rem 1rem;
|
||||
border-bottom: 1px solid var(--au-gray-200);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.chat-toolbar__title {
|
||||
margin: 0;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* The conversations overview: a big button to start a conversation. */
|
||||
.chat-start {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: calc(100vh - 8rem);
|
||||
|
||||
@include mq(medium) {
|
||||
min-height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.chat-window {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
height: calc(100vh - 8rem);
|
||||
|
||||
@include mq(medium) {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
.chat-window__messages {
|
||||
flex: 1;
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
<AuBodyContainer>
|
||||
<div class="au-c-main-container__sidebar chat-sidebar">
|
||||
<Chat::Sidebar @conversations={{@model.conversations}} />
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="content"
|
||||
class="au-c-main-container__content chat-content"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div class="chat-toolbar">
|
||||
<AuHeading @level="1" @skin="3" class="chat-toolbar__title">
|
||||
{{if @model.conversation.title @model.conversation.title "Nieuw gesprek"}}
|
||||
</AuHeading>
|
||||
<Chat::NewConversation />
|
||||
</div>
|
||||
|
||||
<Chat::Window
|
||||
@conversation={{@model.conversation}}
|
||||
@assistant={{@model.assistant}}
|
||||
/>
|
||||
</AuBodyContainer>
|
||||
</div>
|
||||
@@ -1,22 +1,13 @@
|
||||
<AuBodyContainer @scroll={{true}}>
|
||||
<div class="au-o-region au-o-layout au-o-layout--small">
|
||||
<AuHeading @level="1" @skin="2">Gesprekken</AuHeading>
|
||||
<AuButton
|
||||
@loading={{this.create.isRunning}}
|
||||
{{on "click" (perform this.create)}}
|
||||
>
|
||||
Nieuw gesprek
|
||||
</AuButton>
|
||||
<AuList class="au-u-margin-top" as |Item|>
|
||||
{{#each @model as |conversation|}}
|
||||
<Item>
|
||||
<AuLink @route="conversation" @model={{conversation.id}}>
|
||||
{{if conversation.title conversation.title "Nieuw gesprek"}}
|
||||
</AuLink>
|
||||
</Item>
|
||||
{{else}}
|
||||
<p class="au-u-muted">Nog geen gesprekken.</p>
|
||||
{{/each}}
|
||||
</AuList>
|
||||
<div class="au-c-main-container__sidebar chat-sidebar">
|
||||
<Chat::Sidebar @conversations={{@model}} />
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="content"
|
||||
class="au-c-main-container__content chat-content"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div class="chat-start">
|
||||
<Chat::NewConversation @large={{true}} />
|
||||
</div>
|
||||
</AuBodyContainer>
|
||||
</div>
|
||||
Reference in New Issue
Block a user