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

Draft: Chat #27814

Closed
wants to merge 36 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
64c982c
feat(chat): Add items into defaultOption tests
Jul 15, 2024
33fe445
revert(chat): Remove items from default checking
Jul 15, 2024
5a102f2
dirty
Jul 15, 2024
aa8c38e
feat(chat): Prepare types
Jul 15, 2024
02a38f3
feat(chat): Update && Regenerate dx
Jul 15, 2024
1f68853
types: empty docid
mpreyskurantov Jul 16, 2024
1aff707
types: excessive @type tags
mpreyskurantov Jul 16, 2024
06cb801
types: @namespace for dx.all
mpreyskurantov Jul 16, 2024
10108f3
types: interface -> type
mpreyskurantov Jul 16, 2024
82a3f49
types: members @docid + @public
mpreyskurantov Jul 16, 2024
dea0d38
formatting: split types
mpreyskurantov Jul 16, 2024
58624d8
regenerate-all
mpreyskurantov Jul 16, 2024
7ddb951
lint
mpreyskurantov Jul 16, 2024
72d30a1
fix(chat): Remove STYLE comment
Jul 16, 2024
b22964d
doc comments in js: sort options
mpreyskurantov Jul 16, 2024
b13e775
component refer to public props type
mpreyskurantov Jul 16, 2024
dca40ec
refactor(chat): Remove ContentReady
Jul 17, 2024
e33397f
refactor(chat): Get rid of ContentReady, step 2
Jul 17, 2024
cefeed1
fix(chat): Add ContentReady into filter
Jul 17, 2024
3bfec0b
feat(chat): Add default values && Set not required
Jul 17, 2024
9e6a94a
refactor(chat): Remove focus from hidden
Jul 17, 2024
b04a383
refactor(chat)
Jul 17, 2024
0301c27
Chat: Render UI
Jul 17, 2024
a7c73bf
draft
Jul 17, 2024
9f0624d
feat(chat): Add messages
Jul 17, 2024
36a753d
dirt
Jul 18, 2024
e955436
rebase(24_2)
Jul 18, 2024
d7339ae
feat(chat): Add main styles && Add all components
Jul 18, 2024
f5523a9
pnpm i
Jul 19, 2024
0f0faa5
feat(chat): Make widget from ChatHeader
Jul 19, 2024
4dc374e
feat(chat): Make MessageBox as Widget
Jul 19, 2024
94ade39
feat(chat): Make MessageList as Widget
Jul 19, 2024
d90b6e1
feat(chat): Make MessageList as Widget
Jul 19, 2024
e907be6
feat(chat): Make MessageBubble as Widget
Jul 19, 2024
37e39fa
feat(chat): Add stiles for bubble && Move styles to dx-scss package
Jul 22, 2024
e217fdf
feat(chat): Regenerate all
Jul 22, 2024
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
21 changes: 21 additions & 0 deletions packages/devextreme-angular/src/ui/chat/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,19 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges
}


/**
* [descr:dxChatOptions.title]

*/
@Input()
get title(): string {
return this._getOption('title');
}
set title(value: string) {
this._setOption('title', value);
}


/**
* [descr:WidgetOptions.visible]

Expand Down Expand Up @@ -238,6 +251,13 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges
*/
@Output() rtlEnabledChange: EventEmitter<boolean>;

/**

* This member supports the internal infrastructure and is not intended to be used directly from your code.

*/
@Output() titleChange: EventEmitter<string>;

/**

* This member supports the internal infrastructure and is not intended to be used directly from your code.
Expand Down Expand Up @@ -286,6 +306,7 @@ export class DxChatComponent extends DxComponent implements OnDestroy, OnChanges
{ emit: 'hoverStateEnabledChange' },
{ emit: 'itemsChange' },
{ emit: 'rtlEnabledChange' },
{ emit: 'titleChange' },
{ emit: 'visibleChange' },
{ emit: 'widthChange' }
]);
Expand Down
166 changes: 166 additions & 0 deletions packages/devextreme-scss/scss/widgets/base/chat/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// adduse

$chat-box-shadow: 0 0 2px 0 #0000001F, 0 4px 8px 0 #00000014;
$chat-width: 480px;
$chat-height: 660px;
$chat-padding: 20px;
$chat-border-radius: 24px;
$chat-information-font-size: 12px;
$chat-information-color: #707070;
$chat-avatar-size: 32px;
$chat-bubble-background-color-primary: #EBF3FC;
$chat-bubble-background-color-socondary: #F5F5F5;
$chat-bubble-border-radius: 12px;
$chat-textarea-height: 40px;

.dx-chat {
display: flex;
flex-direction: column;
width: $chat-width;
height: $chat-height;
padding: $chat-padding;
border-radius: $chat-border-radius;
box-shadow: $chat-box-shadow;
}

.dx-chat-header {
box-sizing: border-box;
display: flex;
align-items: center;
padding-bottom: 4px;
}

.dx-chat-header-text {
margin: 0;
}

.dx-chat-message-list {
box-sizing: border-box;
flex: 1;
overflow: auto;
}

.dx-chat-message-list-content {
display: flex;
flex-direction: column;
padding: 0;
margin: 0;
overflow-y: auto;
}

.dx-chat-message-group {
display: grid;
align-items: start;
row-gap: 4px;
margin: 24px 0;
}

.dx-chat-message-group-alignment-start {
justify-items: start;
grid-template-columns: 44px 1fr;
}

.dx-chat-message-group-alignment-end {
justify-items: end;
}

.dx-chat-message-group-information {
display: flex;
grid-row: 1;
}

.dx-chat-message-group-alignment-start .dx-chat-message-group-information {
grid-column: 2;
}

.dx-chat-message-time,
.dx-chat-message-name {
font-size: $chat-information-font-size;
color: $chat-information-color;
}

.dx-chat-message-name {
margin-right: 8px;
}

.dx-chat-message-avatar {
grid-row: span 3;
display: flex;
align-items: center;
justify-content: center;
width: $chat-avatar-size;
height: $chat-avatar-size;
border-radius: 50%;
background-color: #878787;
}

.dx-chat-message-bubble {
padding: 8px 12px;
max-width: 90%;
border-radius: $chat-bubble-border-radius;
background-color: $chat-bubble-background-color-socondary;
}

.dx-chat-message-group-alignment-start .dx-chat-message-bubble.dx-chat-message-bubble-first {
border-bottom-left-radius: 0;
}

.dx-chat-message-group-alignment-start .dx-chat-message-bubble.dx-chat-message-bubble-last {
border-top-left-radius: 0;
}

.dx-chat-message-group-alignment-start .dx-chat-message-bubble-first.dx-chat-message-bubble-last {
border-bottom-left-radius: $chat-bubble-border-radius;
border-top-left-radius: $chat-bubble-border-radius;
}

.dx-chat-message-group-alignment-start .dx-chat-message-bubble:not(
.dx-chat-message-bubble-first.dx-chat-message-bubble-last,
.dx-chat-message-bubble-first,
.dx-chat-message-bubble-last) {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
}

.dx-chat-message-group-alignment-end .dx-chat-message-bubble.dx-chat-message-bubble-first {
border-bottom-right-radius: 0;
}

.dx-chat-message-group-alignment-end .dx-chat-message-bubble.dx-chat-message-bubble-last {
border-top-right-radius: 0;
}

.dx-chat-message-group-alignment-end .dx-chat-message-bubble-first.dx-chat-message-bubble-last {
border-bottom-right-radius: $chat-bubble-border-radius;
border-top-right-radius: $chat-bubble-border-radius;
}

.dx-chat-message-group-alignment-end .dx-chat-message-bubble:not(
.dx-chat-message-bubble-first.dx-chat-message-bubble-last,
.dx-chat-message-bubble-first,
.dx-chat-message-bubble-last) {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}

.dx-chat-message-group-alignment-start .dx-chat-message-bubble {
grid-column: 2;
}

.dx-chat-message-group-alignment-end .dx-chat-message-bubble {
background-color: $chat-bubble-background-color-primary;
}

.dx-chat-message-box {
display: flex;
align-items: center;
}

.dx-chat-message-box-text-area {
flex-grow: 1;
height: $chat-textarea-height;
}

.dx-chat-message-box-button {
margin-left: 8px;
}
1 change: 1 addition & 0 deletions packages/devextreme-scss/scss/widgets/fluent/_index.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// public widgets
@use "./box";
@use "./chat";
@use "./responsiveBox";
@use "./button";
@use "./buttonGroup";
Expand Down
3 changes: 3 additions & 0 deletions packages/devextreme-scss/scss/widgets/fluent/chat/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@use "../../base/chat";

// adduse
1 change: 1 addition & 0 deletions packages/devextreme-scss/scss/widgets/generic/_index.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// public widgets
@use "./box";
@use "./chat";
@use "./responsiveBox";
@use "./button";
@use "./buttonGroup";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@use "../../base/chat";

// adduse
1 change: 1 addition & 0 deletions packages/devextreme-scss/scss/widgets/material/_index.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// public widgets
@use "./box";
@use "./chat";
@use "./responsiveBox";
@use "./button";
@use "./buttonGroup";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@use "../../base/chat";

// adduse
3 changes: 3 additions & 0 deletions packages/devextreme-vue/src/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type AccessibleOptions = Pick<Properties,
"onMessageSend" |
"onOptionChanged" |
"rtlEnabled" |
"title" |
"visible" |
"width"
>;
Expand All @@ -32,6 +33,7 @@ const DxChat = createComponent({
onMessageSend: Function,
onOptionChanged: Function,
rtlEnabled: Boolean,
title: String,
visible: Boolean,
width: [Function, Number, String]
},
Expand All @@ -48,6 +50,7 @@ const DxChat = createComponent({
"update:onMessageSend": null,
"update:onOptionChanged": null,
"update:rtlEnabled": null,
"update:title": null,
"update:visible": null,
"update:width": null,
},
Expand Down
46 changes: 45 additions & 1 deletion packages/devextreme/js/__internal/ui/chat/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,26 @@ import $ from '@js/core/renderer';
import type { Properties } from '@js/ui/chat';

import Widget from '../widget';
import ChatHeader from './chat_header';
import MessageBox from './chat_message_box';
import MessageList from './chat_message_list';

const CHAT_CLASS = 'dx-chat';

const MOCK_CURRENT_USER_ID = 'CURRENT_USER_ID';

class Chat extends Widget<Properties> {
_chatHeader?: ChatHeader;

_messageBox?: MessageBox;

_messageList?: MessageList;

_getDefaultOptions(): Properties {
return {
...super._getDefaultOptions(),
...{
title: '',
items: [],
onMessageSend: undefined,
},
Expand All @@ -21,12 +33,44 @@ class Chat extends Widget<Properties> {
$(this.element()).addClass(CHAT_CLASS);

super._initMarkup();

this._renderHeader();
this._renderMessageList();
this._renderMessageBox();
}

_renderHeader(): void {
const { title } = this.option();

this._chatHeader = this._createComponent($('<div>'), ChatHeader, { title });

$(this._chatHeader.element()).appendTo(this.element());
}

_renderMessageList(): void {
const { items } = this.option();

this._messageList = this._createComponent($('<div>'), MessageList, {
items,
currentUserId: MOCK_CURRENT_USER_ID,
});

$(this._messageList.element()).appendTo(this.element());
}

_renderMessageBox(): void {
this._messageBox = this._createComponent($('<div>'), MessageBox, {});

$(this._messageBox.element()).appendTo(this.element());
}

_optionChanged(args: Record<string, unknown>): void {
const { name } = args;
const { name, value } = args;

switch (name) {
case 'title':
this._chatHeader?.option(name, (value as string));
break;
case 'items':
break;
case 'onMessageSend':
Expand Down
55 changes: 55 additions & 0 deletions packages/devextreme/js/__internal/ui/chat/chat_header.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable @typescript-eslint/no-explicit-any */
import $ from '@js/core/renderer';
import type { WidgetOptions } from '@js/ui/widget/ui.widget';

import Widget from '../widget';

const CHAT_HEADER_CLASS = 'dx-chat-header';
const CHAT_HEADER_TEXT_CLASS = 'dx-chat-header-text';

export interface ChatHeaderOptions extends WidgetOptions<ChatHeader> {
title?: string;
}

class ChatHeader extends Widget<ChatHeaderOptions> {
_getDefaultOptions(): ChatHeaderOptions {
return {
...super._getDefaultOptions(),
...{
title: '',
},
};
}

_initMarkup(): void {
$(this.element()).addClass(CHAT_HEADER_CLASS);

super._initMarkup();

const { title } = this.option();

$('<p>')
.addClass(CHAT_HEADER_TEXT_CLASS)
.text((title as any))
.appendTo(this.element());
}

_updateTitle(value: any): void {
$(`.${CHAT_HEADER_TEXT_CLASS}`).text(value);
}

_optionChanged(args: Record<string, unknown>): void {
const { name, value } = args;

switch (name) {
case 'title':
this._updateTitle(value);
break;
default:
super._optionChanged(args);
}
}
}

export default ChatHeader;
Loading
Loading