From 8bf15b305bedb9e2a03c8853ee143dd5aae6a3ea Mon Sep 17 00:00:00 2001 From: Paul Rangger <48455539+PaRangger@users.noreply.github.com> Date: Fri, 25 Oct 2024 00:44:12 +0200 Subject: [PATCH] Communication: Fix clipping issues on mobile devices (#9460) --- src/main/webapp/app/core/core.module.ts | 4 + .../course-conversations.component.html | 15 +- .../course-conversations.component.scss | 70 ++++++ .../course-conversations.component.ts | 81 ++++++- .../course-wide-search.component.html | 199 +++++++++--------- .../course-wide-search.component.scss | 40 ++++ .../course-wide-search.component.ts | 11 +- .../conversation-header.component.html | 11 +- .../conversation-header.component.ts | 12 +- .../conversation-messages.component.html | 22 +- .../conversation-messages.component.scss | 14 +- .../conversation-messages.component.ts | 14 ++ ...conversation-thread-sidebar.component.scss | 13 ++ .../overview/course-overview.component.html | 9 +- .../overview/course-overview.component.scss | 16 ++ .../app/overview/course-overview.component.ts | 21 ++ .../app/overview/course-sidebar.service.ts | 24 +++ .../app/shared/breakpoints/layout.service.ts | 2 +- .../answer-post/answer-post.component.scss | 10 + .../app/shared/metis/metis.component.scss | 24 +++ .../answer-post-header.component.html | 14 +- .../post-header/post-header.component.html | 14 +- .../app/shared/sidebar/sidebar.component.scss | 2 + .../app/shared/sidebar/sidebar.component.ts | 45 ++-- src/main/webapp/content/scss/global.scss | 4 +- src/main/webapp/i18n/de/metis.json | 4 +- src/main/webapp/i18n/en/metis.json | 4 +- .../course/course-overview.component.spec.ts | 17 +- .../course-conversations.component.spec.ts | 78 +++++++ .../shared/sidebar/sidebar.component.spec.ts | 8 + .../overview/course-sidebar.service.spec.ts | 52 +++++ 31 files changed, 703 insertions(+), 151 deletions(-) create mode 100644 src/main/webapp/app/overview/course-sidebar.service.ts create mode 100644 src/test/javascript/spec/service/overview/course-sidebar.service.spec.ts diff --git a/src/main/webapp/app/core/core.module.ts b/src/main/webapp/app/core/core.module.ts index a371ea41e9b1..30c0442557b2 100644 --- a/src/main/webapp/app/core/core.module.ts +++ b/src/main/webapp/app/core/core.module.ts @@ -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: [ @@ -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; + } } } diff --git a/src/main/webapp/app/overview/course-conversations/course-conversations.component.html b/src/main/webapp/app/overview/course-conversations/course-conversations.component.html index fd62d2f7e57e..113ab1ca1cd8 100644 --- a/src/main/webapp/app/overview/course-conversations/course-conversations.component.html +++ b/src/main/webapp/app/overview/course-conversations/course-conversations.component.html @@ -10,7 +10,7 @@ (keyup.enter)="onSearch()" placeholder="{{ 'artemisApp.metis.overview.searchBarDefault' | artemisTranslate }}" /> - + @@ -22,7 +22,7 @@ } @if (isCodeOfConductAccepted && isServiceSetUp && course) {
-
+ @if (course && !activeConversation && isCodeOfConductPresented) { @@ -45,7 +46,10 @@
} -
+
@if (activeConversation) {
@if (!!postInThread) { (); + private closeSidebarEventSubscription: Subscription; + private openSidebarEventSubscription: Subscription; + private toggleSidebarEventSubscription: Subscription; + private breakpointSubscription: Subscription; course?: Course; isLoading = false; isServiceSetUp = false; @@ -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; @@ -130,6 +138,9 @@ export class CourseConversationsComponent implements OnInit, OnDestroy { createChannelFn?: (channel: ChannelDTO) => Observable; channelActions$ = new EventEmitter(); + private courseSidebarService: CourseSidebarService = inject(CourseSidebarService); + private layoutService: LayoutService = inject(LayoutService); + constructor( private router: Router, private activatedRoute: ActivatedRoute, @@ -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); + }); + + 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(); + }); + + if (!this.isMobile) { + if (this.courseOverviewService.getSidebarCollapseStateFromStorage('conversation')) { + this.courseSidebarService.openSidebar(); + } else { + this.courseSidebarService.closeSidebar(); + } + } else { + this.courseSidebarService.openSidebar(); + } + 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; @@ -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; } @@ -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(); } 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(); }); } @@ -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); + this.activeConversation = undefined; this.updateQueryParameters(); this.courseWideSearchConfig.searchTerm = this.courseWideSearchTerm; this.courseWideSearch?.onSearch(); @@ -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); } @@ -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(); diff --git a/src/main/webapp/app/overview/course-conversations/course-wide-search/course-wide-search.component.html b/src/main/webapp/app/overview/course-conversations/course-wide-search/course-wide-search.component.html index aa3b35159b88..1295be3edf63 100644 --- a/src/main/webapp/app/overview/course-conversations/course-wide-search/course-wide-search.component.html +++ b/src/main/webapp/app/overview/course-conversations/course-wide-search/course-wide-search.component.html @@ -1,114 +1,121 @@ -
-
+
+ + +
+
+

@if (!courseWideSearchConfig.searchTerm) { } @else { + }

-
- @if (formGroup) { -
-
- -
- -
-
- -
-
- - + @if (formGroup) { +
+ + +
+ +
+
+ +
+
+ + +
+
+ + +
+
+ + +
-
- - -
-
- - + +
+
+
+ +
- -
-
-
- + +
+ } +
+ -
-