Skip to content

Commit

Permalink
Merge branch 'master' into 7402-disable-edit-on-changing-the-chat
Browse files Browse the repository at this point in the history
  • Loading branch information
Mutugiii authored Jan 19, 2024
2 parents 56a2358 + 08518d9 commit 0d12649
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 82 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "planet",
"license": "AGPL-3.0",
"version": "0.14.6",
"version": "0.14.9",
"myplanet": {
"latest": "v0.12.59",
"latest": "v0.12.78",
"min": "v0.12.0"
},
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion src/app/chat/chat-sidebar/chat-sidebar.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<button class="icon-button" mat-icon-button (click)="drawer.toggle()"><i class="material-icons">chevron_left</i></button>
</div>
<mat-form-field class="font-size-1 margin-lr-3">
<input matInput i18n-placeholder placeholder="Search" [(ngModel)]="titleSearch" (input)="onSearchChange()">
<input matInput i18n-placeholder placeholder="Search" [(ngModel)]="titleSearch" (input)="onSearchChange($event.target.value)">
</mat-form-field>
<button mat-icon-button color="primary" (click)="resetFilter()" [disabled]="!titleSearch && !searchType"><mat-icon>delete</mat-icon></button><br>
<div>
Expand Down
56 changes: 33 additions & 23 deletions src/app/chat/chat-sidebar/chat-sidebar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

import { Conversation } from '../chat.model';
import { ChatService } from '../../shared/chat.service';
import { CouchService } from '../../shared/couchdb.service';
import { DeviceInfoService, DeviceType } from '../../shared/device-info.service';
Expand All @@ -25,9 +26,9 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
this.recordSearch();
this.filterConversations();
}
conversations: any;
filteredConversations: any;
selectedConversation: any;
conversations: Conversation[];
filteredConversations: Conversation[];
selectedConversation: Conversation;
lastRenderedConversation: number;
isEditing: boolean;
fullTextSearch = false;
Expand Down Expand Up @@ -83,7 +84,7 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
this.overlayOpen = !this.overlayOpen;
}

updateConversation(conversation, title) {
updateConversation(conversation: Conversation, title) {
this.couchService.updateDocument(
this.dbName, { ...conversation, title: title, updatedDate: this.couchService.datePlaceholder }
).subscribe((data) => {
Expand All @@ -92,7 +93,7 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
});
}

submitTitle(conversation) {
submitTitle(conversation: Conversation) {
if (this.titleForm[conversation._id].valid) {
const title = this.titleForm[conversation._id].get('title').value;
this.updateConversation(conversation, title);
Expand All @@ -103,7 +104,7 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
}

initializeFormGroups() {
this.conversations.forEach((conversation) => {
this.conversations.forEach((conversation: Conversation) => {
this.titleForm[conversation._id] = this.formBuilder.group({
title: [ conversation?.title, Validators.required ]
});
Expand Down Expand Up @@ -142,8 +143,8 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
this.lastRenderedConversation = index;
}

onSearchChange() {
this.titleSearch = this.titleSearch;
onSearchChange(searchValue: string) {
this.titleSearch = searchValue;
}

resetFilter() {
Expand All @@ -163,28 +164,37 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
this.filterConversations();
}

matchesSearchTerm(value: string, searchTerm: string): boolean {
return value?.toLowerCase().includes(searchTerm.toLowerCase());
}

filterByTitle(conversation: Conversation): boolean {
return this.matchesSearchTerm(conversation.title, this.titleSearch);
}

filterByFullText(conversation: Conversation): boolean {
return conversation.conversations.some(chat => {
const queryMatch = this.matchesSearchTerm(chat.query, this.titleSearch);
const responseMatch = this.matchesSearchTerm(chat.response, this.titleSearch);
if (this.searchType === 'questions') {
return queryMatch;
} else if (this.searchType === 'responses') {
return responseMatch;
} else {
return queryMatch || responseMatch;
}
});
}

filterConversations() {
if (this.titleSearch.trim() === '' ) {
this.getChatHistory();
}

this.filteredConversations = this.conversations?.filter(conversation => {
if (this.fullTextSearch) {
const conversationMatches = conversation.conversations.some(chat => {
const queryMatch = chat.query?.toLowerCase().includes(this.titleSearch.toLowerCase());
const responseMatch = chat.response?.toLowerCase().includes(this.titleSearch.toLowerCase());
if (this.searchType === 'questions') {
return queryMatch;
} else if (this.searchType === 'responses') {
return responseMatch;
} else {
return queryMatch || responseMatch;
}
});
return conversationMatches;
return this.filterByFullText(conversation);
}

return conversation.title?.toLowerCase().includes(this.titleSearch.toLowerCase());
return this.filterByTitle(conversation);
});
}
}
46 changes: 29 additions & 17 deletions src/app/chat/chat-window/chat-window.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

import { CustomValidators } from '../../validators/custom-validators';
import { ConversationForm } from '../chat.model';
import { ChatService } from '../../shared/chat.service';
import { showFormErrors } from '../../shared/table-helpers';
import { UserService } from '../../shared/user.service';
Expand All @@ -19,11 +20,11 @@ export class ChatWindowComponent implements OnInit, OnDestroy {
conversations: any[] = [];
selectedConversationId: any;
promptForm: FormGroup;
data = {
user: this.userService.get().name,
content: '',
data: ConversationForm = {
_id: '',
_rev: ''
_rev: '',
user: this.userService.get().name,
content: ''
};

@ViewChild('chat') chatContainer: ElementRef;
Expand Down Expand Up @@ -52,6 +53,8 @@ export class ChatWindowComponent implements OnInit, OnDestroy {
.subscribe(() => {
this.selectedConversationId = null;
this.conversations = [];
}, error => {
console.error('Error subscribing to newChatSelected$', error);
});
}

Expand All @@ -61,6 +64,8 @@ export class ChatWindowComponent implements OnInit, OnDestroy {
.subscribe((conversationId) => {
this.selectedConversationId = conversationId;
this.fetchConversation(this.selectedConversationId?._id);
}, error => {
console.error('Error subscribing to selectedConversationId$', error);
});
}

Expand All @@ -72,27 +77,34 @@ export class ChatWindowComponent implements OnInit, OnDestroy {

fetchConversation(id) {
if (id) {
this.chatService.findConversations([ id ]).subscribe(
(conversation: Object) => {
const messages = conversation[0]?.conversations;

this.conversations = messages;
}
);
try {
this.chatService.findConversations([ id ]).subscribe(
(conversation: Object) => {
const messages = conversation[0]?.conversations;
this.conversations = messages;
}
);
} catch (error) {
console.error('Error fetching conversation: ', error);
}
}
}

scrollToBottom(): void {
scrollTo(position: 'top' | 'bottom'): void {
const target = position === 'top' ? 0 : this.chatContainer.nativeElement.scrollHeight;
this.chatContainer.nativeElement.scrollTo({
top: this.chatContainer.nativeElement.scrollHeight,
top: target,
behavior: 'smooth',
});
}

setSelectedConversation() {
setSelectedConversation(): void {
if (this.selectedConversationId) {
this.data._id = this.selectedConversationId._id;
this.data._rev = this.selectedConversationId._rev;
this.data = {
...this.data,
_id: this.selectedConversationId._id,
_rev: this.selectedConversationId._rev,
};
} else {
delete this.data._id;
delete this.data._rev;
Expand All @@ -102,7 +114,7 @@ export class ChatWindowComponent implements OnInit, OnDestroy {
postSubmit() {
this.changeDetectorRef.detectChanges();
this.spinnerOn = true;
this.scrollToBottom();
this.scrollTo('bottom');
this.promptForm.controls['prompt'].setValue('');
}

Expand Down
2 changes: 1 addition & 1 deletion src/app/chat/chat.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class ChatComponent {
private router: Router,
) {}

goBack() {
goBack(): void {
this.router.navigate([ '/' ], { relativeTo: this.route });
}

Expand Down
21 changes: 21 additions & 0 deletions src/app/chat/chat.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export interface ConversationForm {
_id: string;
_rev: string;
user: string;
content: string;
}

export interface Conversation {
_id: string;
_rev: string;
user: string;
conversations: Message[];
title: string;
createdDate: number;
updatedDate: number;
}

export interface Message {
query: string;
response: string;
}
4 changes: 2 additions & 2 deletions src/app/courses/add-courses/courses-add.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@
</mat-autocomplete>
</mat-form-field>
<mat-form-field>
<mat-select i18n-placeholder placeholder="Grade Level" formControlName="gradeLevel">
<mat-select i18n-placeholder placeholder="Grade Level" formControlName="gradeLevel" required>
<mat-option *ngFor="let grade of gradeLevels" [value]="grade.value">{{grade.label}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select i18n-placeholder placeholder="Subject Level" formControlName="subjectLevel">
<mat-select i18n-placeholder placeholder="Subject Level" formControlName="subjectLevel" required>
<mat-option *ngFor="let sub of subjectLevels" [value]="sub.value">{{sub.label}}</mat-option>
</mat-select>
</mat-form-field>
Expand Down
4 changes: 2 additions & 2 deletions src/app/courses/add-courses/courses-add.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ export class CoursesAddComponent implements OnInit, OnDestroy {
],
description: [ '', CustomValidators.requiredMarkdown ],
languageOfInstruction: '',
gradeLevel: this.gradeLevels[0],
subjectLevel: this.subjectLevels[0],
gradeLevel: '',
subjectLevel: '',
createdDate: this.couchService.datePlaceholder,
creator: this.userService.get().name + '@' + configuration.code,
sourcePlanet: configuration.code,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<planet-rating [rating]="courseDetail?.rating" [item]="courseDetail" [parent]="false" [ratingType]="'course'"></planet-rating>
<p><b i18n>Subject Level:</b> <planet-language-label [options]="subjectOptions" [label]="courseDetail?.subjectLevel"></planet-language-label></p>
<p><b i18n>Grade Level:</b> <planet-language-label [options]="gradeOptions" [label]="courseDetail?.gradeLevel"></planet-language-label></p>
<p><b i18n>Language of Instruction:</b> <planet-language-label [options]="languageOptions" [label]="courseDetail?.languageOfInstruction || 'N/A'"></planet-language-label></p>
<p *ngIf="courseDetail?.languageOfInstruction"><b i18n>Language of Instruction:</b> <planet-language-label [options]="languageOptions" [label]="courseDetail?.languageOfInstruction || 'N/A'"></planet-language-label></p>
<p *ngIf="courseDetail?.creatorDoc"><b i18n>Creator:</b> {{courseDetail?.creatorDoc?.fullName}} </p>
<p *ngIf="courseDetail?.sourcePlanet !== planetConfiguration.code && courseDetail?.sourcePlanet"><b i18n>Source:</b> {{courseDetail?.sourcePlanet}}</p>
<p><b i18n>Description:</b></p>
Expand Down
63 changes: 37 additions & 26 deletions src/app/login/login-form.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,39 +141,50 @@ export class LoginFormComponent {
{ withCredentials: true, domain: this.stateService.configuration.parentDomain });
}

checkArchiveStatus(name) {
this.couchService.get('_users/org.couchdb.user:' + name).subscribe((userData) => {
async checkArchiveStatus(name) {
try {
const userData = await this.couchService.get('_users/org.couchdb.user:' + name).toPromise();

if (userData?.isArchived) {
this.errorHandler($localize`Member ${name} is not registered`)();
this.errorHandler($localize`Member ${name} is not registered.`)();
return true;
}
});
return true;
return false;
} catch (error) {
this.errorHandler($localize`There was an error connecting to Planet`)();
return false;
}
}

login({ name, password }: { name: string, password: string }, isCreate: boolean) {
async login({ name, password }: { name: string, password: string }, isCreate: boolean) {
const configuration = this.stateService.configuration;
const userId = `org.couchdb.user:${name}`;
if (this.checkArchiveStatus(name)) {
return;

try {
if (await this.checkArchiveStatus(name)) {
return;
}
this.pouchAuthService.login(name, password).pipe(
switchMap(() => isCreate ? from(this.router.navigate([ 'users/update/' + name ])) : from(this.reRoute())),
switchMap(() => forkJoin(this.pouchService.replicateFromRemoteDBs())),
switchMap(this.createSession(name, password)),
switchMap((sessionData) => {
const adminName = configuration.adminName.split('@')[0];
return isCreate ? this.sendNotifications(adminName, name) : of(sessionData);
}),
switchMap(() => this.submissionsService.getSubmissions(findDocuments({ type: 'survey', status: 'pending', 'user.name': name }))),
map((surveys) => {
const uniqueSurveys = dedupeObjectArray(surveys, [ 'parentId' ]);
if (uniqueSurveys.length > 0) {
this.openNotificationsDialog(uniqueSurveys);
}
}),
switchMap(() => this.healthService.userHealthSecurity(this.healthService.userDatabaseName(userId))),
catchError(error => error.status === 404 ? of({}) : throwError(error))
).subscribe(() => {}, this.loginError.bind(this));
} catch (error) {
console.error('Error during login:', error);
}
this.pouchAuthService.login(name, password).pipe(
switchMap(() => isCreate ? from(this.router.navigate([ 'users/update/' + name ])) : from(this.reRoute())),
switchMap(() => forkJoin(this.pouchService.replicateFromRemoteDBs())),
switchMap(this.createSession(name, password)),
switchMap((sessionData) => {
const adminName = configuration.adminName.split('@')[0];
return isCreate ? this.sendNotifications(adminName, name) : of(sessionData);
}),
switchMap(() => this.submissionsService.getSubmissions(findDocuments({ type: 'survey', status: 'pending', 'user.name': name }))),
map((surveys) => {
const uniqueSurveys = dedupeObjectArray(surveys, [ 'parentId' ]);
if (uniqueSurveys.length > 0) {
this.openNotificationsDialog(uniqueSurveys);
}
}),
switchMap(() => this.healthService.userHealthSecurity(this.healthService.userDatabaseName(userId))),
catchError(error => error.status === 404 ? of({}) : throwError(error))
).subscribe(() => {}, this.loginError.bind(this));
}

loginError() {
Expand Down
Loading

0 comments on commit 0d12649

Please sign in to comment.