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: Improve the user interface design on mobile devices #9460

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
346962a
Fix Clipping Issues
Pablosanqt Oct 12, 2024
44b8071
Merge develop into branch
Pablosanqt Oct 13, 2024
7371d42
Merge remote-tracking branch 'origin/develop' into bugfix/communicati…
Pablosanqt Oct 16, 2024
90ea773
Fix conflict and overflows caused by margins
Pablosanqt Oct 16, 2024
a2760ef
Change display of messages on small mobile devices
Pablosanqt Oct 16, 2024
927364b
Small improvements
Pablosanqt Oct 16, 2024
bf5f3ed
disable tooltips on mobile
Pablosanqt Oct 16, 2024
bb1e097
Fixed favoriting channel making sidebar dissapear
Pablosanqt Oct 17, 2024
8434bb5
Merge remote-tracking branch 'origin/develop' into bugfix/communicati…
Pablosanqt Oct 18, 2024
d5e6dd2
Merge remote-tracking branch 'origin/develop' into bugfix/communicati…
Pablosanqt Oct 19, 2024
3096916
Fix console errors from merging
Pablosanqt Oct 19, 2024
b573519
Cleanup tests
Pablosanqt Oct 19, 2024
90dc04f
Listened to breakpoints instead of user agent
Pablosanqt Oct 20, 2024
735c4d1
Merge remote-tracking branch 'origin/develop' into bugfix/communicati…
Pablosanqt Oct 20, 2024
38d49ab
Remove emoji media query
Pablosanqt Oct 21, 2024
95e2f24
Merge remote-tracking branch 'origin/develop' into bugfix/communicati…
Pablosanqt Oct 21, 2024
45b8386
Fix to make it possible to reselect channels
Pablosanqt Oct 22, 2024
ffba759
Merge remote-tracking branch 'origin/develop' into bugfix/communicati…
Pablosanqt Oct 23, 2024
a693dbc
Fix Scrolling Containers
Pablosanqt Oct 23, 2024
20575ec
Merge remote-tracking branch 'origin/develop' into bugfix/communicati…
Pablosanqt Oct 24, 2024
c520e33
Added additional tags for better browser support
Pablosanqt Oct 24, 2024
40175f2
Added return to sidebar button to search
Pablosanqt Oct 24, 2024
068c060
Feedback to use inject for services and wording change
Pablosanqt Oct 24, 2024
29e0745
Fix E2E test
Pablosanqt Oct 24, 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
4 changes: 4 additions & 0 deletions src/main/webapp/app/core/core.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { NgbDateDayjsAdapter } from 'app/core/config/datepicker-adapter';
import { JhiLanguageHelper } from 'app/core/language/language.helper';
import { TraceService } from '@sentry/angular';
import { Router } from '@angular/router';
import isMobile from 'ismobilejs-es5';

@NgModule({
imports: [
Expand Down Expand Up @@ -109,5 +110,8 @@ export class ArtemisCoreModule {
const languageKey = sessionStorageService.retrieve('locale') || languageHelper.determinePreferredLanguage();
translateService.use(languageKey);
tooltipConfig.container = 'body';
if (isMobile(window.navigator.userAgent).any ?? false) {
tooltipConfig.disableTooltip = true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
(keyup.enter)="onSearch()"
placeholder="{{ 'artemisApp.metis.overview.searchBarDefault' | artemisTranslate }}"
/>
<jhi-button [btnType]="ButtonType.SECONDARY" [icon]="faTimes" (onClick)="courseWideSearchTerm = ''" />
<jhi-button [btnType]="ButtonType.SECONDARY" [icon]="faTimes" (onClick)="hideSearchTerm()" />
<jhi-button id="search-submit" class="ms-1" [icon]="faSearch" (onClick)="onSearch()" />
</div>
<!-- only display after isCodeOfConductAccepted is loaded and set to false -->
Expand All @@ -22,7 +22,7 @@
}
@if (isCodeOfConductAccepted && isServiceSetUp && course) {
<div class="d-flex justify-content-between">
<div [ngClass]="{ 'sidebar-collapsed': isCollapsed }">
<div class="communication-content-sidebar" [ngClass]="{ 'sidebar-collapsed': isCollapsed, 'is-not-in-active-conversation': !activeConversation }">
<jhi-sidebar
(onSelectConversation)="onConversationSelected($event)"
(onUpdateSidebar)="prepareSidebarData()"
Expand All @@ -38,14 +38,18 @@
[sidebarItemAlwaysShow]="DEFAULT_SHOW_ALWAYS"
[collapseState]="DEFAULT_COLLAPSE_STATE"
[inCommunication]="true"
[reEmitNonDistinctSidebarEvents]="isMobile"
/>
</div>
@if (course && !activeConversation && isCodeOfConductPresented) {
<div class="col pe-0 flex-grow-1">
<jhi-course-conversations-code-of-conduct [course]="course!" />
</div>
}
<div class="col flex-grow-1 module-bg rounded-3 scrollable-content" [ngClass]="{ 'content-height-dev': !isProduction || isTestServer }" style="min-width: 200px">
<div
class="communication-message-wrap col flex-grow-1 module-bg rounded-3 scrollable-content"
[ngClass]="{ 'content-height-dev': !isProduction || isTestServer, 'is-answer-thread-open': !!postInThread }"
>
@if (activeConversation) {
<jhi-conversation-header (collapseSearch)="toggleChannelSearch()" (onUpdateSidebar)="prepareSidebarData()" />
<jhi-conversation-messages
Expand All @@ -59,9 +63,8 @@
}
</div>
<div
class="col d-flex flex-grow-1 justify-end px-0 scrollable-content"
[ngClass]="{ 'content-height-dev': !isProduction || isTestServer }"
style="max-width: min-content"
class="communication-answer-message-wrap col flex-grow-1 justify-end px-0 scrollable-content"
[ngClass]="{ 'content-height-dev': !isProduction || isTestServer, 'is-answer-thread-open': !!postInThread }"
>
@if (!!postInThread) {
<jhi-conversation-thread-sidebar
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
@import 'bootstrap/scss/functions';
@import 'bootstrap/scss/variables';
@import 'bootstrap/scss/mixins';

.second-layer-modal-bg {
background-color: var(--secondary);
}
Expand Down Expand Up @@ -28,10 +32,76 @@

@media (max-width: 768px) {
max-height: calc(100vh - var(--header-height) - var(--message-input-height-prod)) !important;
max-height: calc(100dvh - var(--header-height) - var(--message-input-height-prod)) !important;
}
}

.message-input {
border-top: 1px solid;
border-color: var(--bs-card-border-color);
}

.communication-message-wrap {
min-width: 200px;
}

.communication-answer-message-wrap {
max-width: min-content;
display: flex;
}

@include media-breakpoint-down(sm) {
.communication-content-sidebar {
position: absolute;
width: 100%;
z-index: 2;
pointer-events: none;

& .sidebar-wrap,
.communication-content-sidebar .sidebar-width {
max-width: 0;
}

&.sidebar-collapsed {
pointer-events: all;
}

&.sidebar-collapsed .sidebar-wrap,
&.sidebar-collapsed .sidebar-width {
max-width: 100%;
}

&.sidebar-collapsed .sidebar-width {
width: 100%;
}

.sidebar-content {
opacity: 0;
}

&.sidebar-collapsed .sidebar-content {
opacity: 1;
}

.sidebar-wrap {
margin-right: 0;
}
}

.communication-message-wrap.is-answer-thread-open {
display: none;
}

.communication-answer-message-wrap {
max-width: 100%;
display: none;
}

.communication-answer-message-wrap.is-answer-thread-open {
display: flex;
}

.communication-message-wrap {
max-width: 100%;
}
}
PaRangger marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, ElementRef, EventEmitter, HostListener, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { Component, ElementRef, EventEmitter, HostListener, OnDestroy, OnInit, ViewChild, ViewEncapsulation, inject } from '@angular/core';
import { ConversationDTO } from 'app/entities/metis/conversation/conversation.model';
import { Post } from 'app/entities/metis/post.model';
import { ActivatedRoute, Router } from '@angular/router';
Expand All @@ -22,6 +22,9 @@ import { OneToOneChatCreateDialogComponent } from 'app/overview/course-conversat
import { ChannelAction, ChannelsOverviewDialogComponent } from 'app/overview/course-conversations/dialogs/channels-overview-dialog/channels-overview-dialog.component';
import { ProfileService } from 'app/shared/layouts/profiles/profile.service';
import { ChannelsCreateDialogComponent } from 'app/overview/course-conversations/dialogs/channels-create-dialog/channels-create-dialog.component';
import { CourseSidebarService } from 'app/overview/course-sidebar.service';
import { LayoutService } from 'app/shared/breakpoints/layout.service';
import { CustomBreakpointNames } from 'app/shared/breakpoints/breakpoints.service';

const DEFAULT_CHANNEL_GROUPS: AccordionGroups = {
favoriteChannels: { entityData: [] },
Expand Down Expand Up @@ -85,6 +88,10 @@ const DEFAULT_SHOW_ALWAYS: SidebarItemShowAlways = {
})
export class CourseConversationsComponent implements OnInit, OnDestroy {
private ngUnsubscribe = new Subject<void>();
private closeSidebarEventSubscription: Subscription;
private openSidebarEventSubscription: Subscription;
private toggleSidebarEventSubscription: Subscription;
private breakpointSubscription: Subscription;
course?: Course;
isLoading = false;
isServiceSetUp = false;
Expand All @@ -102,6 +109,7 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
isCollapsed = false;
isProduction = true;
isTestServer = false;
isMobile = false;

readonly CHANNEL_TYPE_SHOW_ADD_OPTION = CHANNEL_TYPE_SHOW_ADD_OPTION;
readonly CHANNEL_TYPE_ICON = CHANNEL_TYPE_ICON;
Expand Down Expand Up @@ -130,6 +138,9 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
createChannelFn?: (channel: ChannelDTO) => Observable<never>;
channelActions$ = new EventEmitter<ChannelAction>();

private courseSidebarService: CourseSidebarService = inject(CourseSidebarService);
private layoutService: LayoutService = inject(LayoutService);

constructor(
private router: Router,
private activatedRoute: ActivatedRoute,
Expand All @@ -156,8 +167,35 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
}

ngOnInit(): void {
this.isMobile = this.layoutService.isBreakpointActive(CustomBreakpointNames.extraSmall);

this.breakpointSubscription = this.layoutService.subscribeToLayoutChanges().subscribe(() => {
this.isMobile = this.layoutService.isBreakpointActive(CustomBreakpointNames.extraSmall);
});

PaRangger marked this conversation as resolved.
Show resolved Hide resolved
this.openSidebarEventSubscription = this.courseSidebarService.openSidebar$.subscribe(() => {
this.setIsCollapsed(true);
});

this.closeSidebarEventSubscription = this.courseSidebarService.closeSidebar$.subscribe(() => {
this.setIsCollapsed(false);
});

this.toggleSidebarEventSubscription = this.courseSidebarService.toggleSidebar$.subscribe(() => {
this.toggleSidebar();
});

PaRangger marked this conversation as resolved.
Show resolved Hide resolved
if (!this.isMobile) {
if (this.courseOverviewService.getSidebarCollapseStateFromStorage('conversation')) {
this.courseSidebarService.openSidebar();
} else {
this.courseSidebarService.closeSidebar();
}
} else {
this.courseSidebarService.openSidebar();
}

PaRangger marked this conversation as resolved.
Show resolved Hide resolved
this.isLoading = true;
this.isCollapsed = this.courseOverviewService.getSidebarCollapseStateFromStorage('conversation');
this.metisConversationService.isServiceSetup$.pipe(takeUntil(this.ngUnsubscribe)).subscribe((isServiceSetUp: boolean) => {
if (isServiceSetUp) {
this.course = this.metisConversationService.course;
Expand Down Expand Up @@ -214,9 +252,13 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
this.activatedRoute.queryParams.pipe(take(1), takeUntil(this.ngUnsubscribe)).subscribe((queryParams) => {
if (queryParams.conversationId) {
this.metisConversationService.setActiveConversation(Number(queryParams.conversationId));

this.closeSidebarOnMobile();
}
if (queryParams.messageId) {
this.postInThread = { id: Number(queryParams.messageId) } as Post;

this.closeSidebarOnMobile();
} else {
this.postInThread = undefined;
}
Expand All @@ -236,12 +278,20 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
this.openSidebarEventSubscription?.unsubscribe();
this.closeSidebarEventSubscription?.unsubscribe();
this.toggleSidebarEventSubscription?.unsubscribe();
this.profileSubscription?.unsubscribe();
this.breakpointSubscription?.unsubscribe();
}
PaRangger marked this conversation as resolved.
Show resolved Hide resolved

private subscribeToActiveConversation() {
this.metisConversationService.activeConversation$.pipe(takeUntil(this.ngUnsubscribe)).subscribe((conversation: ConversationDTO) => {
const previousConversation = this.activeConversation;
this.activeConversation = conversation;
if (this.isMobile && conversation && previousConversation?.id !== conversation.id) {
this.courseSidebarService.closeSidebar();
}
this.updateQueryParameters();
PaRangger marked this conversation as resolved.
Show resolved Hide resolved
PaRangger marked this conversation as resolved.
Show resolved Hide resolved
});
}
Expand Down Expand Up @@ -286,8 +336,20 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
: DEFAULT_CHANNEL_GROUPS;
}

hideSearchTerm() {
this.courseWideSearchTerm = '';
}

onSearch() {
if (this.isMobile) {
if (this.courseWideSearchTerm) {
this.courseSidebarService.closeSidebar();
} else {
this.courseSidebarService.openSidebar();
}
}
this.metisConversationService.setActiveConversation(undefined);
PaRangger marked this conversation as resolved.
Show resolved Hide resolved
PaRangger marked this conversation as resolved.
Show resolved Hide resolved
PaRangger marked this conversation as resolved.
Show resolved Hide resolved
this.activeConversation = undefined;
this.updateQueryParameters();
this.courseWideSearchConfig.searchTerm = this.courseWideSearchTerm;
PaRangger marked this conversation as resolved.
Show resolved Hide resolved
this.courseWideSearch?.onSearch();
Expand Down Expand Up @@ -316,11 +378,22 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
}

onConversationSelected(conversationId: number) {
this.closeSidebarOnMobile();
this.metisConversationService.setActiveConversation(conversationId);
}

toggleSidebar() {
this.isCollapsed = !this.isCollapsed;
this.setIsCollapsed(!this.isCollapsed);
}

closeSidebarOnMobile() {
if (this.isMobile) {
this.courseSidebarService.closeSidebar();
}
}

setIsCollapsed(value: boolean) {
this.isCollapsed = value;
this.courseOverviewService.setSidebarCollapseState('conversation', this.isCollapsed);
}

Expand Down Expand Up @@ -395,12 +468,14 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
complete: () => {
if (newActiveConversation) {
this.metisConversationService.setActiveConversation(newActiveConversation);
this.closeSidebarOnMobile();
}
},
});
} else {
if (newActiveConversation) {
this.metisConversationService.setActiveConversation(newActiveConversation);
this.closeSidebarOnMobile();
}
}
this.prepareSidebarData();
Expand Down
Loading
Loading