\ No newline at end of file
diff --git a/app/components/chat/window.hbs b/app/components/chat/window.hbs
index 7502c06..764ea45 100644
--- a/app/components/chat/window.hbs
+++ b/app/components/chat/window.hbs
@@ -1,6 +1,9 @@
{{! The list, the composer, the poll loop }}
-
+
{{#unless this.messages.length}}
{{@assistant.description}}
{{/unless}}
diff --git a/app/helpers/format-datetime.js b/app/helpers/format-datetime.js
new file mode 100644
index 0000000..f749483
--- /dev/null
+++ b/app/helpers/format-datetime.js
@@ -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)}`;
+});
diff --git a/app/modifiers/chat-scroll-bottom.js b/app/modifiers/chat-scroll-bottom.js
new file mode 100644
index 0000000..06b48a3
--- /dev/null
+++ b/app/modifiers/chat-scroll-bottom.js
@@ -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;
+ }
+}
diff --git a/app/routes/conversation.js b/app/routes/conversation.js
index c087d55..a6a41f9 100644
--- a/app/routes/conversation.js
+++ b/app/routes/conversation.js
@@ -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 };
}
}
diff --git a/app/styles/app.scss b/app/styles/app.scss
index dbf3dbe..03821cd 100644
--- a/app/styles/app.scss
+++ b/app/styles/app.scss
@@ -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;
diff --git a/app/templates/conversation.hbs b/app/templates/conversation.hbs
index 5cf0061..13036ff 100644
--- a/app/templates/conversation.hbs
+++ b/app/templates/conversation.hbs
@@ -1,6 +1,21 @@
-
+
\ No newline at end of file
diff --git a/app/templates/conversations.hbs b/app/templates/conversations.hbs
index a48b1fc..a632fd3 100644
--- a/app/templates/conversations.hbs
+++ b/app/templates/conversations.hbs
@@ -1,22 +1,13 @@
-
-