Skip to content

Commit

Permalink
feat(AI-130): handled close events inside the iframe (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianmusial committed Feb 7, 2024
1 parent 1d16dd9 commit 74b2d98
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 26 deletions.
2 changes: 1 addition & 1 deletion apps/spa/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ export const routes: Routes = [
},
{
path: '**',
redirectTo: '/404',
redirectTo: '/chat',
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<mat-icon class="char-header__icon">refresh</mat-icon>
</button>
}
<button class="ai-assistant-toggle" mat-icon-button (click)="close$.emit()" matTooltip="Close">
<button class="ai-assistant-toggle" mat-icon-button (click)="close()" matTooltip="Close">
<mat-icon class="char-header__icon">close</mat-icon>
</button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,9 @@ export class ChatHeaderComponent {
@Output() config$ = new EventEmitter();
@Input() isRefreshEnabled = true;
@Input() isConfigEnabled = true;

close(): void {
this.close$.emit();
parent.postMessage({ type: 'chatbot.close' }, '*');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ChatService } from '../../shared/chat.service';
import { environment } from '../../../../../environments/environment';
import { MarkdownComponent, MarkdownPipe } from 'ngx-markdown';
import { AsyncPipe } from '@angular/common';
import { AssistantIframe } from '@boldare/ai-embedded';

@Component({
selector: 'ai-chat-example',
Expand All @@ -19,12 +20,17 @@ export class ChatExampleComponent {
markdown = `\`\`\`html
<script
src="${environment.appUrl}/assets/js/ai-embedded.js"
data-chat-initial="true"
type="module"
defer
></script>
\`\`\``;

constructor(private readonly chatService: ChatService,) {
this.chatService.loadScript();
constructor(private readonly chatService: ChatService) {
if (environment.env === 'prod') {
this.chatService.loadScript();
} else {
new AssistantIframe({ url: `${environment.appUrl}/chat/iframe` }).init();
}
}
}
1 change: 1 addition & 0 deletions apps/spa/src/app/modules/+chat/shared/chat.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export class ChatService {
script.async = true;
script.defer = true;
script.type = 'module';
script.dataset['chatInitial'] = 'true';
body.appendChild(script);
}
}
1 change: 1 addition & 0 deletions apps/spa/src/environments/environment.development.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const environment = {
env: 'dev',
appUrl: 'http://localhost:4200',
apiUrl: 'http://localhost:3000/api',
websocketUrl: 'http://localhost:3000',
Expand Down
1 change: 1 addition & 0 deletions apps/spa/src/environments/environment.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const environment = {
env: 'prod',
appUrl: 'https://ai-assistant-c8b469d88808.herokuapp.com',
apiUrl: 'https://ai-assistant-c8b469d88808.herokuapp.com/api',
websocketUrl: 'https://ai-assistant-c8b469d88808.herokuapp.com',
Expand Down
5 changes: 5 additions & 0 deletions apps/spa/src/styles/_extends/_material.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
--mdc-filled-text-field-focus-label-text-color: var(--color-grey-500);
--mat-option-selected-state-label-text-color: var(--color-primary-500);
--mat-select-focused-arrow-color: var(--color-primary-500);
--mdc-filled-text-field-label-text-size: 14px;

.mat-primary {
--mat-minimal-pseudo-checkbox-selected-checkmark-color: var(--color-primary-500);
Expand Down Expand Up @@ -71,4 +72,8 @@
width: 100%;
min-height: 42px;
}

.mat-mdc-text-field-wrapper .mat-mdc-form-field-flex .mat-mdc-floating-label {
top: 28px;
}
}
3 changes: 2 additions & 1 deletion apps/spa/src/styles/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@

html,
body {
height: 100%;
min-height: 100vh;
}

body {
margin: 0;
background-color: var(--color-grey-300);
background-image: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
color: var(--color-grey-900);
font-size: 12px;
font-family: Roboto, 'Helvetica Neue', sans-serif;
Expand Down
19 changes: 18 additions & 1 deletion libs/ai-embedded/src/lib/assistant-iframe.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,18 @@ export const addIframeClass = (className: string) => `.${className} {
border: 0;
box-shadow: rgba(17, 17, 26, 0.1) 0 4px 16px, rgba(17, 17, 26, 0.1) 0 8px 32px;
z-index: 50;
}`;
}
@media (max-width: 460px) {
.${className} {
width: calc(100% - 20px);
left: 10px;
right: 10px;
bottom: 10px;
height: calc(100% - 20px);
}
}
`;

export const addTriggerClass = (className: string) => `
@keyframes trigger {
Expand Down Expand Up @@ -46,6 +57,12 @@ export const addTriggerClass = (className: string) => `
background-position: center;
transition: 0.2s all ease-in-out;
cursor: pointer;
@media (max-width: 460px) {
width: 40px;
height: 40px;
margin: 10px;
}
}
.${className}:hover {
Expand Down
50 changes: 30 additions & 20 deletions libs/ai-embedded/src/lib/assistant-iframe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@ export class AssistantIframe {
trigger!: HTMLElement;

constructor(config: Partial<AssistantIframeConfig> = {}) {
// @TODO: set URL as an env variable
const url = 'https://ai-assistant-c8b469d88808.herokuapp.com';
const url = 'https://ai-assistant-c8b469d88808.herokuapp.com/chat/iframe';

this.config = {
url: `${url}/chat/iframe`,
url: config.url || url,
elementId: config.elementId || '',
iframeId: config.elementId || 'ai-assistant-iframe',
iframeClass: 'ai-assistant-iframe',
toggleClass: 'ai-assistant-toggle',
bodyOpenClass: 'ai-assistant-open',
toggleIsAnimated: config.toggleIsAnimated || true,
};
this.init();

if (this.getChatInitialValue()) {
this.init();
}
}

addStyles(): void {
Expand All @@ -32,6 +34,14 @@ export class AssistantIframe {
);
}

getChatInitialValue(): boolean {
const dataChatInitialKey = 'data-chat-initial';
const element = document.querySelector(`[${dataChatInitialKey}]`);
const chatInitialData = element?.getAttribute(dataChatInitialKey);

return chatInitialData ? JSON.parse(chatInitialData) : false;
}

init(): void {
this.addStyles();
this.iframe = this.getIframe();
Expand Down Expand Up @@ -88,13 +98,14 @@ export class AssistantIframe {
this.config.bodyOpenClass,
);

this.toggleModal(!currentState);
this.changeModalState(!currentState);
this.watchToggleButton();
this.watchCloseButton();
});
}

toggleModal(state: boolean): void {
if (!state) {
changeModalState(currentState: boolean): void {
if (!currentState) {
document.body.classList.add(this.config.bodyOpenClass);
this.iframe.style.display = 'block';
} else {
Expand All @@ -104,20 +115,19 @@ export class AssistantIframe {
}

watchToggleButton(): void {
const iframeButtons = this.iframe?.contentDocument?.getElementsByClassName(
this.config.toggleClass,
);
const appButtons = document.getElementsByClassName(this.config.toggleClass);
const buttons = [iframeButtons, appButtons];

buttons.map(elements => {
if (elements?.length) {
elements[0].addEventListener('click', () => {
const isVisible = document.body.classList.contains(
this.config.bodyOpenClass,
);
this.toggleModal(isVisible);
});

appButtons[0].addEventListener('click', () => {
const isVisible = document.body.classList.contains(this.config.bodyOpenClass);
this.changeModalState(isVisible);
});
}

watchCloseButton(): void {
window.addEventListener('message', (message) => {
if (message.data.type === 'chatbot.close') {
const isVisible = document.body.classList.contains(this.config.bodyOpenClass);
this.changeModalState(isVisible);
}
});
}
Expand Down

0 comments on commit 74b2d98

Please sign in to comment.