Skip to content

Commit 1783096

Browse files
Mutugiiidogi
andauthored
chat: initial commit (fixes #7184) (#7189)
Co-authored-by: dogi <dogi@users.noreply.github.com>
1 parent 29c344d commit 1783096

12 files changed

Lines changed: 191 additions & 6 deletions

File tree

chatapi/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
},
2828
"homepage": "https://github.com/open-learning-exchange/planet#readme",
2929
"dependencies": {
30+
"@types/cors": "^2.8.13",
3031
"@types/express": "^4.17.17",
32+
"cors": "^2.8.5",
3133
"express": "^4.18.2",
3234
"nano": "^10.1.2",
3335
"openai": "^3.3.0"

chatapi/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import express from 'express';
22
import { chatWithGpt } from './services/gpt-prompt.service';
33
import dotenv from 'dotenv';
4+
import cors from 'cors';
45

56
dotenv.config();
67

78
const app = express();
89

10+
app.use(cors());
911
// Parse JSON bodies (as sent by API clients)
1012
app.use(express.json());
1113

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
PLANET_VERSION=$(cat package.json | jq -r .version)
2-
LATEST_APK_VERSION="v0.9.50"
3-
LATEST_APK_VER_CODE="950"
2+
LATEST_APK_VERSION="v0.9.55"
43
MIN_APK_VERSION="v0.9.30"
5-
MIN_APK_VER_CODE="930"
6-
APK_PATH="https://github.com/open-learning-exchange/myplanet/releases/download/v0.9.41/myPlanet.apk"
4+
LATEST_APK_VER_CODE=$(echo $LATEST_APK_VERSION | awk -F'[v.]' '{printf "%d%02d%02d\n", $2, $3, $4}' | sed 's#^0*##')
5+
MIN_APK_VER_CODE=$(echo $MIN_APK_VERSION | awk -F'[v.]' '{printf "%d%02d%02d\n", $2, $3, $4}' | sed 's#^0*##')
6+
APK_PATH="https://github.com/open-learning-exchange/myplanet/releases/download/"$LATEST_APK_VERSION"/myPlanet.apk"
77
LOCAL_APK_PATH="/fs/myPlanet.apk"
88

99
echo '{"appname":"planet","planetVersion":"'$PLANET_VERSION'","latestapk":"'$LATEST_APK_VERSION'","latestapkcode":'$LATEST_APK_VER_CODE',"minapk":"'$MIN_APK_VERSION'","minapkcode":'$MIN_APK_VER_CODE',"apkpath":"'$APK_PATH'","localapkpath":"'$LOCAL_APK_PATH'"}' > /usr/share/nginx/html/versions

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "planet-app",
3-
"version": "0.13.23",
3+
"version": "0.13.24",
44
"license": "AGPL-3.0",
55
"scripts": {
66
"ng": "ng",

src/app/chat/chat.component.html

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<mat-toolbar>
2+
<button mat-icon-button (click)="goBack()"><mat-icon>arrow_back</mat-icon></button>
3+
<span i18n>Chat Prompts</span>
4+
<span class="toolbar-fill"></span>
5+
</mat-toolbar>
6+
7+
<div class="space-container">
8+
<div>
9+
<div class="chat-container" #chat>
10+
<div *ngFor="let conversation of conversations">
11+
<p class="conversation-query">{{conversation.query}}</p>
12+
<p [ngClass]="{'conversation-error': conversation.error}" class="conversation-err">{{conversation.response}}</p>
13+
</div>
14+
</div>
15+
16+
<div class="form-container">
17+
<form [formGroup]="promptForm" class="form-spacing" (ngSubmit)="onSubmit()">
18+
<mat-form-field class="full-width mat-form-field-type-no-underline">
19+
<planet-markdown-textbox class="full-width" required="true" i18n-placeholder placeholder="Prompt" [formControl]="promptForm.controls.prompt"></planet-markdown-textbox>
20+
<mat-error><planet-form-error-messages [control]="promptForm.controls.prompt"></planet-form-error-messages></mat-error>
21+
</mat-form-field>
22+
<button type="submit" mat-raised-button [planetSubmit]="spinnerOn" color="primary" i18n>Chat</button>
23+
</form>
24+
</div>
25+
26+
27+
</div>
28+
</div>

src/app/chat/chat.component.scss

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
@import '../variables.scss';
2+
3+
.form-container {
4+
width: auto;
5+
height: calc(1 / 4 * #{$view-container-height});
6+
margin-top: 30px;
7+
display: flex;
8+
justify-content: center;
9+
}
10+
11+
.chat-container {
12+
height: calc(1 / 2 * #{$view-container-height});
13+
overflow-y: auto;
14+
border: 1px solid #{$primary};
15+
padding: 10px;
16+
margin-bottom: 10px;
17+
display: flex;
18+
flex-direction: column;
19+
}
20+
21+
.conversation-query {
22+
align-self: flex-start;
23+
background-color: #{$primary};
24+
color: white;
25+
border-radius: 10px;
26+
padding: 10px;
27+
margin: 5px;
28+
}
29+
30+
.converstaion-response {
31+
align-self: flex-end;
32+
border-radius: 10px;
33+
padding: 5px;
34+
margin: 5px;
35+
}
36+
37+
.conversation-error {
38+
background-color: red;
39+
border-radius: 10px;
40+
padding: 10px;
41+
}

src/app/chat/chat.component.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { Component, OnInit, ViewChild, ElementRef, ChangeDetectorRef } from '@angular/core';
2+
import { FormBuilder, FormGroup } from '@angular/forms';
3+
import { ActivatedRoute, Router } from '@angular/router';
4+
5+
import { CustomValidators } from '../validators/custom-validators';
6+
import { showFormErrors } from '../shared/table-helpers';
7+
import { ChatService } from '../shared/chat.service';
8+
9+
@Component({
10+
selector: 'planet-chat',
11+
templateUrl: './chat.component.html',
12+
styleUrls: [ './chat.component.scss' ],
13+
})
14+
export class ChatComponent implements OnInit {
15+
spinnerOn = true;
16+
promptForm: FormGroup;
17+
messages: any[] = [];
18+
conversations: any[] = [];
19+
20+
@ViewChild('chat') chatContainer: ElementRef;
21+
22+
constructor(
23+
private formBuilder: FormBuilder,
24+
private route: ActivatedRoute,
25+
private router: Router,
26+
private changeDetectorRef: ChangeDetectorRef,
27+
private chatService: ChatService
28+
) {}
29+
30+
ngOnInit() {
31+
this.createForm();
32+
}
33+
34+
scrollToBottom(): void {
35+
this.chatContainer.nativeElement.scrollTo({
36+
top: this.chatContainer.nativeElement.scrollHeight,
37+
behavior: 'smooth',
38+
});
39+
}
40+
41+
createForm() {
42+
this.promptForm = this.formBuilder.group({
43+
prompt: [ '', CustomValidators.requiredMarkdown ],
44+
});
45+
}
46+
47+
goBack() {
48+
this.router.navigate([ '/' ], { relativeTo: this.route });
49+
}
50+
51+
onSubmit() {
52+
if (!this.promptForm.valid) {
53+
showFormErrors(this.promptForm.controls);
54+
return;
55+
}
56+
57+
this.submitPrompt();
58+
}
59+
60+
submitPrompt() {
61+
const content = this.promptForm.get('prompt').value;
62+
this.messages.push({ role: 'user', content });
63+
64+
this.chatService.getPrompt(content).subscribe(
65+
(completion: any) => {
66+
this.conversations.push({
67+
query: content,
68+
response: completion?.chat,
69+
});
70+
this.spinnerOn = false;
71+
this.changeDetectorRef.detectChanges();
72+
this.scrollToBottom();
73+
this.spinnerOn = true;
74+
},
75+
(error: any) => {
76+
console.log(error);
77+
this.conversations.push({
78+
query: content,
79+
response: 'Error: ' + error.message,
80+
error: true,
81+
});
82+
}
83+
);
84+
}
85+
}

src/app/home/home-router.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { CommunityComponent } from '../community/community.component';
1313
import { myDashboardRoute } from './router-constants';
1414
import { CoursesProgressLearnerComponent } from '../courses/progress-courses/courses-progress-learner.component';
1515
import { LandingComponent } from '../landing/landing.component';
16+
import { ChatComponent } from '../chat/chat.component';
1617

1718
export function dashboardPath(route): string {
1819
return `${myDashboardRoute}/${route}`;
@@ -36,6 +37,7 @@ const routes: Routes = [
3637
{ path: 'enterprises', loadChildren: () => import('../teams/teams.module').then(m => m.TeamsModule), data: { mode: 'enterprise' } },
3738
{ path: 'logs/myplanet', component: LogsMyPlanetComponent },
3839
{ path: 'health', component: HealthListComponent },
40+
{ path: 'chat', component: ChatComponent },
3941
{ path: 'health/profile/:id', loadChildren: () => import('../health/health.module').then(m => m.HealthModule) },
4042
{ path: 'nation', component: TeamsViewComponent, data: { mode: 'services' } },
4143
{ path: 'earth', component: TeamsViewComponent, data: { mode: 'services' } },

src/app/home/home.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ <h1><ng-container>Planet</ng-container> {{planetName}}</h1>
4242
<ng-container *ngIf="planetType === 'community'">
4343
<button mat-icon-button *planetAuthorizedRoles="'only,health'" i18n-title title="Health" routerLink="/health"><mat-icon>local_hospital</mat-icon></button>
4444
</ng-container>
45+
<button mat-icon-button routerLink="/chat" i18n-title title="Chat"><mat-icon>chat_bubble_outline</mat-icon></button>
4546
<button mat-icon-button planetFeedback i18n-title title="Feedback" *ngIf="layout === 'classic' && !forceModern"><mat-icon>feedback_outline</mat-icon></button>
4647
<button mat-icon-button routerLink="/feedback" i18n-title title="Messages"><mat-icon>mail_outline</mat-icon></button>
4748
<ng-container *planetAuthorizedRoles>

src/app/home/home.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { HealthListComponent } from '../health/health-list.component';
2626
import { UsersModule } from '../users/users.module';
2727
import { PlanetComponent } from './planet.component';
2828
import { CoursesViewDetailModule } from '../courses/view-courses/courses-view-detail.module';
29+
import { ChatComponent } from '../chat/chat.component';
2930

3031
@NgModule({
3132
imports: [
@@ -59,6 +60,7 @@ import { CoursesViewDetailModule } from '../courses/view-courses/courses-view-de
5960
CommunityLinkDialogComponent,
6061
PlanetComponent,
6162
HealthListComponent,
63+
ChatComponent
6264
]
6365
})
6466
export class HomeModule {}

0 commit comments

Comments
 (0)