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

Communication: Add profile picture to sidebar element and conversation header #9719

Merged
merged 3 commits into from
Nov 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ export class OneToOneChatDTO extends ConversationDTO {
export function isOneToOneChatDTO(conversation: ConversationDTO): conversation is OneToOneChatDTO {
return conversation.type === ConversationType.ONE_TO_ONE;
}

export function getAsOneToOneChatDTO(conversation: ConversationDTO | undefined): OneToOneChatDTO | undefined {
if (!conversation) {
return undefined;
}
return isOneToOneChatDTO(conversation) ? conversation : undefined;
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import { GenericConfirmationDialogComponent } from './dialogs/generic-confirmati
import { ConversationSettingsComponent } from './dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component';
import { OneToOneChatCreateDialogComponent } from './dialogs/one-to-one-chat-create-dialog/one-to-one-chat-create-dialog.component';
import { GroupChatCreateDialogComponent } from './dialogs/group-chat-create-dialog/group-chat-create-dialog.component';
import { GroupChatIconComponent } from './other/group-chat-icon/group-chat-icon.component';
import { ArtemisMarkdownModule } from 'app/shared/markdown.module';
import { CourseConversationsCodeOfConductComponent } from 'app/overview/course-conversations/code-of-conduct/course-conversations-code-of-conduct.component';
import { CourseWideSearchComponent } from 'app/overview/course-conversations/course-wide-search/course-wide-search.component';
Expand Down Expand Up @@ -79,7 +78,6 @@ const routes: Routes = [
ConversationSettingsComponent,
OneToOneChatCreateDialogComponent,
GroupChatCreateDialogComponent,
GroupChatIconComponent,
CourseWideSearchComponent,
],
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ <h4 class="modal-title">
@if (getAsChannel(activeConversation); as channel) {
<jhi-channel-icon [isPublic]="channel.isPublic!" [isArchived]="channel.isArchived!" [isAnnouncementChannel]="channel.isAnnouncementChannel!" />
}
@if (getAsGroupChat(activeConversation); as groupChat) {
<jhi-group-chat-icon />
@if (getAsGroupChat(activeConversation)) {
<fa-icon [icon]="faPeopleGroup" size="xs" />
}
{{ conversationService.getConversationName(activeConversation, true) }}
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ConversationService } from 'app/shared/metis/conversations/conversation
import { isOneToOneChatDTO } from 'app/entities/metis/conversation/one-to-one-chat.model';
import { getAsGroupChatDTO } from 'app/entities/metis/conversation/group-chat.model';
import { AbstractDialogComponent } from 'app/overview/course-conversations/dialogs/abstract-dialog.component';
import { faPeopleGroup } from '@fortawesome/free-solid-svg-icons';

export enum ConversationDetailTabs {
MEMBERS = 'members',
Expand All @@ -24,6 +25,7 @@ export class ConversationDetailDialogComponent extends AbstractDialogComponent {
@Input() selectedTab: ConversationDetailTabs = ConversationDetailTabs.MEMBERS;

isInitialized = false;
readonly faPeopleGroup = faPeopleGroup;

initialize() {
super.initialize(['course', 'activeConversation', 'selectedTab']);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,23 @@ <h4 class="pointer d-inline-block rounded py-2 info mb-0" (click)="openConversat
[isAnnouncementChannel]="activeConversationAsChannel.isAnnouncementChannel!"
/>
}
@if (getAsGroupChat(activeConversation); as groupChat) {
<jhi-group-chat-icon />
@if (getAsGroupChat(activeConversation)) {
<fa-icon [icon]="faPeopleGroup" size="xs" />
}
@if (getAsOneToOneChat(activeConversation) && otherUser) {
<jhi-profile-picture
[imageSizeInRem]="'2'"
[fontSizeInRem]="'0.9'"
[imageId]="'sidebar-profile-picture'"
[defaultPictureId]="'sidebar-default-profile-picture'"
[isGray]="false"
[authorId]="otherUser.id"
[authorName]="otherUser.name"
class="me-2"
[imageUrl]="otherUser.imageUrl"
[isEditable]="false"
>
</jhi-profile-picture>
}
{{ conversationService.getConversationName(activeConversation, true) }}
</h4>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, EventEmitter, OnDestroy, OnInit, Output, inject } from '@angular/core';
import { faChevronLeft, faSearch, faUserGroup, faUserPlus } from '@fortawesome/free-solid-svg-icons';
import { faChevronLeft, faPeopleGroup, faSearch, faUserGroup, faUserPlus } from '@fortawesome/free-solid-svg-icons';
import { ConversationDTO } from 'app/entities/metis/conversation/conversation.model';
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { Course } from 'app/entities/course.model';
Expand All @@ -18,6 +18,8 @@ import { defaultFirstLayerDialogOptions, getChannelSubTypeReferenceTranslationKe
import { catchError } from 'rxjs/operators';
import { MetisService } from 'app/shared/metis/metis.service';
import { CourseSidebarService } from 'app/overview/course-sidebar.service';
import { getAsOneToOneChatDTO } from 'app/entities/metis/conversation/one-to-one-chat.model';
import { ConversationUserDTO } from 'app/entities/metis/conversation/conversation-user-dto.model';

@Component({
selector: 'jhi-conversation-header',
Expand All @@ -39,11 +41,13 @@ export class ConversationHeaderComponent implements OnInit, OnDestroy {
activeConversationAsChannel?: ChannelDTO;
channelSubTypeReferenceTranslationKey?: string;
channelSubTypeReferenceRouterLink?: string;
otherUser?: ConversationUserDTO;

faUserPlus = faUserPlus;
faUserGroup = faUserGroup;
faSearch = faSearch;
faChevronLeft = faChevronLeft;
readonly faPeopleGroup = faPeopleGroup;

private courseSidebarService: CourseSidebarService = inject(CourseSidebarService);

Expand All @@ -56,6 +60,7 @@ export class ConversationHeaderComponent implements OnInit, OnDestroy {
) {}

getAsGroupChat = getAsGroupChatDTO;
getAsOneToOneChat = getAsOneToOneChatDTO;
krusche marked this conversation as resolved.
Show resolved Hide resolved

canAddUsers = canAddUsersToConversation;

Expand All @@ -64,6 +69,13 @@ export class ConversationHeaderComponent implements OnInit, OnDestroy {
this.subscribeToActiveConversation();
}

getOtherUser() {
const conversation = getAsOneToOneChatDTO(this.activeConversation);
if (conversation) {
this.otherUser = conversation.members?.find((user) => !user.isRequestingUser);
}
}

ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
Expand All @@ -79,6 +91,7 @@ export class ConversationHeaderComponent implements OnInit, OnDestroy {
this.activeConversationAsChannel = getAsChannelDTO(conversation);
this.channelSubTypeReferenceTranslationKey = getChannelSubTypeReferenceTranslationKey(this.activeConversationAsChannel?.subType);
this.channelSubTypeReferenceRouterLink = this.metisService.getLinkForChannelSubType(this.activeConversationAsChannel);
this.getOtherUser();
});
}

Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,20 @@
[class.muted]="sidebarItem.conversation?.isMuted"
[ngClass]="unreadCount() > 0 ? 'fw-bold' : 'fw-normal'"
>
@if (sidebarItem.icon) {
@if (otherUser) {
<jhi-profile-picture
[imageSizeInRem]="'1.1'"
[fontSizeInRem]="'0.5'"
[imageId]="'sidebar-profile-picture'"
[defaultPictureId]="'sidebar-default-profile-picture'"
[isGray]="false"
[authorId]="otherUser.id"
[authorName]="otherUser.name"
[imageUrl]="otherUser.imageUrl"
[isEditable]="false"
>
</jhi-profile-picture>
} @else if (sidebarItem.icon) {
<fa-icon [fixedWidth]="true" [icon]="sidebarItem.icon" />
}
{{ sidebarItem.title }}</span
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Component, Input, OnChanges, OnInit, SimpleChanges, input } from '@angular/core';
import { SidebarCardElement, SidebarTypes } from 'app/types/sidebar';
import { OneToOneChatDTO } from 'app/entities/metis/conversation/one-to-one-chat.model';
import { faPeopleGroup } from '@fortawesome/free-solid-svg-icons';

@Component({
selector: 'jhi-sidebar-card-item',
Expand All @@ -11,11 +13,15 @@ export class SidebarCardItemComponent implements OnInit, OnChanges {
@Input() sidebarType?: SidebarTypes;
@Input() groupKey?: string;
unreadCount = input<number>(0);
otherUser: any;

readonly faPeopleGroup = faPeopleGroup;
krusche marked this conversation as resolved.
Show resolved Hide resolved

formattedUnreadCount: string = '';

ngOnInit(): void {
this.formattedUnreadCount = this.getFormattedUnreadCount();
this.extractMessageUser();
krusche marked this conversation as resolved.
Show resolved Hide resolved
}

ngOnChanges(changes: SimpleChanges): void {
Expand All @@ -30,4 +36,16 @@ export class SidebarCardItemComponent implements OnInit, OnChanges {
}
return this.unreadCount().toString() || '';
}

extractMessageUser(): void {
if (this.sidebarItem.type === 'oneToOneChat' && (this.sidebarItem.conversation as OneToOneChatDTO)?.members) {
this.otherUser = (this.sidebarItem.conversation as OneToOneChatDTO).members!.find((user) => !user.isRequestingUser);
} else {
this.otherUser = null;
}

if (this.sidebarItem.type === 'groupChat') {
this.sidebarItem.icon = this.faPeopleGroup;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<span jhiTranslate="artemisApp.courseOverview.sidebar.createDirectChat"></span>
</button>
<button (click)="createGroupChat()" class="p-2" ngbDropdownItem>
<fa-icon [icon]="faUsers" class="item-icon" [fixedWidth]="true"></fa-icon>
<fa-icon [icon]="faPeopleGroup" class="item-icon" [fixedWidth]="true"></fa-icon>
<span jhiTranslate="artemisApp.courseOverview.sidebar.createGroupChat"></span>
</button>
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/webapp/app/shared/sidebar/sidebar.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, effect, input, output } from '@angular/core';
import { faFilter, faFilterCircleXmark, faHashtag, faPlusCircle, faSearch, faUser, faUsers } from '@fortawesome/free-solid-svg-icons';
import { faFilter, faFilterCircleXmark, faHashtag, faPeopleGroup, faPlusCircle, faSearch, faUser } from '@fortawesome/free-solid-svg-icons';
import { ActivatedRoute, Params } from '@angular/router';
import { Subscription, distinctUntilChanged } from 'rxjs';
import { ProfileService } from '../layouts/profiles/profile.service';
Expand Down Expand Up @@ -57,7 +57,7 @@ export class SidebarComponent implements OnDestroy, OnChanges, OnInit {
readonly faFilter = faFilter;
readonly faFilterCurrentlyApplied = faFilterCircleXmark;
readonly faUser = faUser;
readonly faUsers = faUsers;
readonly faPeopleGroup = faPeopleGroup;
readonly faPlusCircle = faPlusCircle;
readonly faSearch = faSearch;
readonly faHashtag = faHashtag;
Expand Down
2 changes: 2 additions & 0 deletions src/main/webapp/app/shared/sidebar/sidebar.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { SidebarCardDirective } from 'app/shared/sidebar/sidebar-card.directive'
import { ConversationOptionsComponent } from 'app/shared/sidebar/conversation-options/conversation-options.component';
import { ArtemisExamSharedModule } from 'app/exam/shared/exam-shared.module';
import { SearchFilterComponent } from 'app/shared/search-filter/search-filter.component';
import { ProfilePictureComponent } from 'app/shared/profile-picture/profile-picture.component';

@NgModule({
imports: [
Expand All @@ -29,6 +30,7 @@ import { SearchFilterComponent } from 'app/shared/search-filter/search-filter.co
SidebarCardDirective,
ArtemisExamSharedModule,
SearchFilterComponent,
ProfilePictureComponent,
krusche marked this conversation as resolved.
Show resolved Hide resolved
],
declarations: [
SidebarAccordionComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { AddUsersFormData } from 'app/overview/course-conversations/dialogs/conv
import { initializeDialog } from '../dialog-test-helpers';
import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe';
import { ChannelIconComponent } from 'app/overview/course-conversations/other/channel-icon/channel-icon.component';
import { GroupChatIconComponent } from 'app/overview/course-conversations/other/group-chat-icon/group-chat-icon.component';
import { UserPublicInfoDTO } from 'app/core/user/user.model';
import { By } from '@angular/platform-browser';
import { isChannelDTO } from 'app/entities/metis/conversation/channel.model';
Expand Down Expand Up @@ -42,13 +41,7 @@ examples.forEach((activeConversation) => {

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [
ConversationAddUsersDialogComponent,
ConversationAddUsersFormStubComponent,
MockPipe(ArtemisTranslatePipe),
MockComponent(ChannelIconComponent),
MockComponent(GroupChatIconComponent),
],
declarations: [ConversationAddUsersDialogComponent, ConversationAddUsersFormStubComponent, MockPipe(ArtemisTranslatePipe), MockComponent(ChannelIconComponent)],
providers: [
MockProvider(AlertService),
MockProvider(NgbActiveModal),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Course } from 'app/entities/course.model';
import { ConversationDTO } from 'app/entities/metis/conversation/conversation.model';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import {
ConversationDetailDialogComponent,
ConversationDetailTabs,
Expand All @@ -9,7 +10,6 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe';
import { MockComponent, MockPipe, MockProvider } from 'ng-mocks';
import { ChannelIconComponent } from 'app/overview/course-conversations/other/channel-icon/channel-icon.component';
import { GroupChatIconComponent } from 'app/overview/course-conversations/other/group-chat-icon/group-chat-icon.component';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { ConversationService } from 'app/shared/metis/conversations/conversation.service';
import { generateExampleChannelDTO, generateExampleGroupChatDTO, generateOneToOneChatDTO } from '../../helpers/conversationExampleModels';
Expand Down Expand Up @@ -82,8 +82,8 @@ examples.forEach((activeConversation) => {
ConversationInfoStubComponent,
MockPipe(ArtemisTranslatePipe),
MockComponent(ChannelIconComponent),
MockComponent(GroupChatIconComponent),
],
imports: [FontAwesomeModule],
providers: [MockProvider(NgbActiveModal), MockProvider(ConversationService)],
}).compileComponents();
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { ConversationHeaderComponent } from 'app/overview/course-conversations/l
import { Location } from '@angular/common';
import { MockComponent, MockPipe, MockProvider } from 'ng-mocks';
import { ChannelIconComponent } from 'app/overview/course-conversations/other/channel-icon/channel-icon.component';
import { GroupChatIconComponent } from 'app/overview/course-conversations/other/group-chat-icon/group-chat-icon.component';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe';
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
Expand All @@ -28,6 +27,7 @@ import { MetisModule } from 'app/shared/metis/metis.module';
import { MockTranslateService } from '../../../../../helpers/mocks/service/mock-translate.service';
import { TranslateService } from '@ngx-translate/core';
import { provideRouter } from '@angular/router';
import { ProfilePictureComponent } from '../../../../../../../../main/webapp/app/shared/profile-picture/profile-picture.component';

const examples: ConversationDTO[] = [
generateOneToOneChatDTO({}),
Expand All @@ -51,7 +51,7 @@ examples.forEach((activeConversation) => {
declarations: [
ConversationHeaderComponent,
MockComponent(ChannelIconComponent),
MockComponent(GroupChatIconComponent),
MockComponent(ProfilePictureComponent),
MockComponent(FaIconComponent),
MockPipe(ArtemisTranslatePipe),
],
Expand Down Expand Up @@ -138,6 +138,19 @@ examples.forEach((activeConversation) => {
});
}));

it('should set otherUser to the non-requesting user in a one-to-one conversation', () => {
const oneToOneChat = generateOneToOneChatDTO({});
oneToOneChat.members = [
{ id: 1, isRequestingUser: true },
{ id: 2, isRequestingUser: false },
];

component.activeConversation = oneToOneChat;
component.getOtherUser();

expect(component.otherUser).toEqual(oneToOneChat.members[1]);
});
krusche marked this conversation as resolved.
Show resolved Hide resolved

if (activeConversation instanceof ChannelDTO && activeConversation.subType !== ChannelSubType.GENERAL) {
it(
'should navigate to ' + activeConversation.subType,
Expand Down

This file was deleted.

Loading
Loading