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

General: Fix scroll to section when clicking status bar in exercise update view #9243

Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
296a494
Fixing scroll so headline is displayed
florian-glombik Aug 22, 2024
8e0d6ee
Removing template test
florian-glombik Aug 22, 2024
5f89b1b
Adding e2e test for scrolling
florian-glombik Aug 22, 2024
c685882
Calculating header height differently
florian-glombik Aug 22, 2024
c8767e4
Fixing scroll for safari
florian-glombik Aug 22, 2024
dfc7149
Adjusting e2e test
florian-glombik Aug 22, 2024
c77cbab
Make e2e test more reliable
florian-glombik Aug 23, 2024
58dc138
Minor refactorings
florian-glombik Aug 23, 2024
6a4c643
Fixing typo in comment
florian-glombik Aug 23, 2024
019a2f2
Fixing client test
florian-glombik Aug 23, 2024
6b57ff6
Use a smarter way than a timeout to wait for the scroll to finish
florian-glombik Aug 23, 2024
e58c8f8
Adding timeout to custom function
florian-glombik Aug 23, 2024
b320b61
Removing unintended space
florian-glombik Aug 23, 2024
212be98
Improve documentation
florian-glombik Aug 23, 2024
7315efc
Improve naming of helper methods
florian-glombik Aug 23, 2024
9d7e027
Removing magic numbers
florian-glombik Aug 23, 2024
5115456
Addressing Ramonas feedback
florian-glombik Aug 23, 2024
f1ed7a4
Improving readability of form-status-bar.component
florian-glombik Aug 23, 2024
175896e
Re-adding fix for Safari
florian-glombik Aug 23, 2024
2260168
Fixing navbar distance for Safari
florian-glombik Aug 23, 2024
26bf89b
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Aug 23, 2024
3f3a9eb
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Aug 25, 2024
4ecbfd6
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Aug 26, 2024
b99ec38
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Aug 27, 2024
4d357b0
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Aug 27, 2024
33b5336
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Aug 28, 2024
a1d4751
Using more robust solution to retrieve scroll offset
florian-glombik Aug 29, 2024
2b6be15
Fix broken states for formStatusSections
florian-glombik Aug 29, 2024
495a83f
Fixing client tests by not using renderer2
florian-glombik Aug 30, 2024
fc4fd47
Not counding breadcrumb container twice
florian-glombik Aug 30, 2024
d15bf08
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Aug 30, 2024
009509d
Address Ramonas feedback
florian-glombik Aug 30, 2024
9d814b6
Fixing e2e test
florian-glombik Aug 30, 2024
83b46ce
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Aug 31, 2024
003a79f
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Sep 1, 2024
fad95f3
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Sep 2, 2024
6bd6400
Fixing change detection for modeling exercise
florian-glombik Sep 2, 2024
9e722a6
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Sep 2, 2024
07b372b
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Sep 3, 2024
dc2bc3f
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Sep 4, 2024
d434f42
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Sep 5, 2024
81077b7
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Sep 5, 2024
b974a06
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Sep 5, 2024
4ad749d
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Sep 6, 2024
44f0f21
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Sep 6, 2024
5689614
Merge branch 'develop' into bugfix/programming-exercises/scroll-to-he…
florian-glombik Sep 6, 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
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<div class="form-status-bar-container pt-2 pb-1">
<hr class="form-status-line" />
<div class="d-flex justify-content-between">
@for (formStatusSection of formStatusSections; track formStatusSection.title) {
<div class="d-flex flex-column align-items-center">
@for (formStatusSection of formStatusSections; track formStatusSection.title; let index = $index) {
<div class="d-flex flex-column align-items-center" id="status-bar-section-item-{{ index }}">
<div
class="d-flex align-items-center justify-content-center border rounded-circle border-secondary form-status-circle"
(click)="scrollToHeadline(formStatusSection.title)"
Expand All @@ -13,7 +13,7 @@
class="fa-sm"
/>
</div>
<a (click)="scrollToHeadline(formStatusSection.title)" class="d-none d-sm-inline link-primary">{{ formStatusSection.title | artemisTranslate }}</a>
<a (click)="scrollToHeadline(formStatusSection.title)" class="d-none d-sm-inline link-primary">{{ formStatusSection.title | artemisTranslate }} </a>
</div>
}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AfterViewInit, Component, HostListener, Input } from '@angular/core';
import { Component, Input } from '@angular/core';

export type FormSectionStatus = {
title: string;
Expand All @@ -11,27 +11,21 @@ export type FormSectionStatus = {
templateUrl: './form-status-bar.component.html',
styleUrl: './form-status-bar.component.scss',
})
export class FormStatusBarComponent implements AfterViewInit {
export class FormStatusBarComponent {
@Input()
florian-glombik marked this conversation as resolved.
Show resolved Hide resolved
formStatusSections: FormSectionStatus[];

@HostListener('window:resize')
onResize() {
setTimeout(() => {
const headerHeight = (document.querySelector('jhi-navbar') as HTMLElement).offsetHeight;
document.documentElement.style.setProperty('--header-height', `${headerHeight}px`);
});
}

ngAfterViewInit() {
this.onResize();
}

scrollToHeadline(id: string) {
const element = document.getElementById(id);

if (element) {
element.style.scrollMarginTop = 'calc(2rem + 78px)';
element.scrollIntoView();
const headerHeight = (document.querySelector('jhi-navbar') as HTMLElement).offsetHeight;

const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
const offset = isSafari ? 8 : 4;

element.style.scrollMarginTop = `calc(${offset}rem + ${headerHeight}px)`;
element.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'start' });
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ describe('FormStatusBarComponent', () => {
jest.restoreAllMocks();
});

it('should initializes', () => {
expect(comp).toBeDefined();
});

it('should scroll to correct headline', () => {
const mockDOMElement = { scrollIntoView: jest.fn(), style: {} };
const getElementSpy = jest.spyOn(document, 'getElementById').mockReturnValue(mockDOMElement as any as HTMLElement);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,36 @@ test.describe('Programming Exercise Management', () => {
await expect(courseManagementExercises.getExerciseTitle(exerciseTitle)).toBeVisible();
await page.waitForURL(`**/programming-exercises/${exercise.id}**`);
});

test('FormStatusBar scrolls to the correct section with headline visible after scroll', async ({
login,
page,
navigationBar,
courseManagement,
courseManagementExercises,
programmingExerciseCreation,
}) => {
await login(admin, '/');
await navigationBar.openCourseManagement();
await courseManagement.openExercisesOfCourse(course.id!);
florian-glombik marked this conversation as resolved.
Show resolved Hide resolved
await courseManagementExercises.createProgrammingExercise();
await page.waitForURL('**/programming-exercises/new**');

const firstSectionHeadline = 'General';
const firstSectionStatusBarId = 0;
const fourthSectionHeadline = 'Problem';
const fourthSectionStatusBarId = 3;

// scroll down
await programmingExerciseCreation.clickFormStatusBarSection(fourthSectionStatusBarId);
await programmingExerciseCreation.checkIsHeadlineLocatorInViewport(firstSectionHeadline, false);
await programmingExerciseCreation.checkIsHeadlineLocatorInViewport(fourthSectionHeadline, true);

// scroll up
await programmingExerciseCreation.clickFormStatusBarSection(firstSectionStatusBarId);
await programmingExerciseCreation.checkIsHeadlineLocatorInViewport(firstSectionHeadline, true);
await programmingExerciseCreation.checkIsHeadlineLocatorInViewport(fourthSectionHeadline, false);
});
});

test.describe('Programming exercise deletion', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Page, expect } from '@playwright/test';
import { Locator, Page, expect } from '@playwright/test';
import { PROGRAMMING_EXERCISE_BASE, ProgrammingLanguage } from '../../../constants';
import { Dayjs } from 'dayjs';

Expand Down Expand Up @@ -73,4 +73,37 @@ export class ProgrammingExerciseCreationPage {
}
await expect(this.page.locator('.owl-dt-popup')).not.toBeVisible();
}

async clickFormStatusBarSection(sectionId: number) {
const searchedSectionId = `#status-bar-section-item-${sectionId}`;
const sectionStatusBarLocator: Locator = this.page.locator(searchedSectionId);
expect(await sectionStatusBarLocator.isVisible()).toBeTruthy();
await sectionStatusBarLocator.click();
await this.page.waitForTimeout(1000); // wait for scroll to finish
}

florian-glombik marked this conversation as resolved.
Show resolved Hide resolved
/**
* Verifies that the locator is visible in the viewport and not hidden by another element
*
* {@link toBeHidden} and {@link toBeVisible} do not solve this problem
* @param locator
*/
private async verifyLocatorIsVisible(locator: Locator) {
const initialPosition = await locator.boundingBox();
await locator.click(); // scrolls to the locator if needed (e.g. if hidden by another element)
const newPosition = await locator.boundingBox();
expect(initialPosition).toEqual(newPosition);
}

async checkIsHeadlineLocatorInViewport(searchedHeadlineDisplayText: string, expected: boolean) {
const headlineLocator = this.page.getByRole('heading', { name: searchedHeadlineDisplayText }).first();

if (expected) {
await expect(headlineLocator).toBeInViewport({ ratio: 1 });
/** additional check because {@link toBeInViewport} is too inaccurate */
await this.verifyLocatorIsVisible(headlineLocator);
} else {
await expect(headlineLocator).not.toBeInViewport();
}
}
}
Loading