Skip to content

Commit b011a9d

Browse files
Merge pull request #20 from Evolveum/bug/GUI-fixing
bug/GUI-fixing
2 parents 7b4f226 + 3975c75 commit b011a9d

File tree

8 files changed

+123
-41
lines changed

8 files changed

+123
-41
lines changed

angular-frontend/src/app/components/application-detail/application-detail.html

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
-->
66

77
<div class="container-fluid p-0 page-container">
8+
<!-- Header -->
9+
<div class="w-100 text-white text-center py-2 page-header">
10+
(HEADER)
11+
</div>
812
@if (loading()) {
913
<div class="container py-5">
1014
<div class="d-flex justify-content-center align-items-center loading-container">
@@ -514,13 +518,6 @@ <h3 class="h5 mb-0">
514518
}
515519
</div>
516520

517-
<!-- Back Button -->
518-
<div class="mt-4 ps-4">
519-
<button class="btn btn-back d-flex align-items-center" (click)="goBack()">
520-
<i class="fa-solid fa-arrow-left icon-md me-2"></i>
521-
Back to Integration Catalog
522-
</button>
523-
</div>
524521
</div>
525522

526523
<!-- Right Panel - Sidebar -->
@@ -596,6 +593,14 @@ <h6 class="text-muted small mb-1">Installations</h6>
596593
</div>
597594
</div>
598595
</div>
596+
597+
<!-- Back Button -->
598+
<div class="mt-4 ps-4">
599+
<button class="btn btn-back d-flex align-items-center" (click)="goBack()">
600+
<i class="fa-solid fa-arrow-left icon-md me-2"></i>
601+
Back to Integration Catalog
602+
</button>
603+
</div>
599604
</div>
600605

601606
<!-- Fixed Position Filter Dropdowns -->

angular-frontend/src/app/components/application-detail/application-detail.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
.text-title {
6868
color: #1a202c;
6969
font-weight: 600;
70+
font-size: 2rem;
7071
}
7172

7273
.text-body {

angular-frontend/src/app/components/applications-list/applications-list.html

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
-->
66

77
<div class="container-fluid p-0 position-relative page-bg">
8+
<!-- Header -->
9+
<div class="w-100 text-white text-center py-2 page-header">
10+
(HEADER)
11+
</div>
812
<!-- Login Required Toast Notification -->
913
@if (showLoginRequiredMessage()) {
1014
<div class="position-fixed top-0 end-0 p-3 toast-container">
@@ -27,7 +31,7 @@
2731

2832
<div class="container-fluid p-0 page-bg">
2933
<!-- Hero Banner -->
30-
<div class="bg-primary text-white py-5 hero-gradient">
34+
<div class="bg-primary text-white py-5 hero-gradient position-relative">
3135
<!-- Login/Logout Button (Top Right) -->
3236
<div class="position-absolute top-0 end-0 p-3 z-index-10">
3337
@if (currentUser()) {
@@ -40,7 +44,7 @@
4044
}
4145
</div>
4246

43-
<div class="container">
47+
<div class="mx-auto content-width position-relative">
4448
<!-- title -->
4549
<div class="row">
4650
<div class="col-12 text-center">
@@ -57,9 +61,9 @@ <h1 class="display-6 fw-bold mb-3 hero-title">Integration Catalog</h1>
5761
</div>
5862
</div>
5963

60-
<!-- Row 3: 2 columns (left numbers, right image) -->
64+
<!-- Row 3: 2 columns (left numbers, right image overlapping into gray below) -->
6165
<div class="row mt-4">
62-
<div class="col-lg-6 d-flex justify-content-center">
66+
<div class="col-6 d-flex justify-content-center">
6367
<div class="d-flex gap-5">
6468
<div class="text-center">
6569
<div class="display-4 fw-bold mb-2 hero-stat-value">{{ activeIntegrationsCount() }}</div>
@@ -71,30 +75,29 @@ <h1 class="display-6 fw-bold mb-3 hero-title">Integration Catalog</h1>
7175
</div>
7276
</div>
7377
</div>
74-
<div class="col-lg-6"><!-- empty, reserved for overlay image alignment --></div>
78+
<div class="col-6 position-relative">
79+
<div class="overlay-image-container">
80+
<img
81+
src="installation-nobg.png"
82+
alt="Integration illustration"
83+
class="overlay-image" />
84+
</div>
85+
</div>
7586
</div>
7687
</div>
7788
</div>
7889

79-
<!-- Overlay image across blue + gray -->
80-
<div class="d-none d-md-block overlay-image-container">
81-
<img
82-
src="installation-nobg.png"
83-
alt="Integration illustration"
84-
class="img-fluid overlay-image" />
85-
</div>
86-
8790
<!-- Description + filter section (gray background) -->
8891
<div class="pt-5 pb-4">
8992
<div class="row mb-3 mx-auto content-width">
90-
<div class="col-lg-6">
93+
<div class="col-6">
9194
<p class="mb-0 description-text">
9295
Explore available integrations to jump-start your workflow, build your own with AI-guided assistance,
9396
or upload an existing configuration to get started in just minutes. The process is fast, flexible, and
9497
user-friendly.
9598
</p>
9699
</div>
97-
<div class="col-lg-6"></div>
100+
<div class="col-6"></div>
98101
</div>
99102
</div>
100103

@@ -254,7 +257,7 @@ <h1 class="display-6 fw-bold mb-3 hero-title">Integration Catalog</h1>
254257
}
255258

256259
@if (!loading() && !error() && featuredApplications().length > 0) {
257-
<h2 class="h3 mb-4 text-center">Featured integration apps</h2>
260+
<h2 class="h3 mb-4 text-center section-title">Featured integration apps</h2>
258261

259262
<div class="position-relative mb-5 mx-auto content-width">
260263
<button class="btn rounded-circle position-absolute top-50 start-0 translate-middle-y d-flex align-items-center justify-content-center scroll-btn"
@@ -364,7 +367,7 @@ <h5 class="card-title card-title-truncate">{{ app.displayName }}</h5>
364367
@if (!(filterState().trending || filterState().categories.length > 0 || filterState().capabilities.length > 0 || filterState().appStatus.length > 0 || filterState().midpointVersions.length > 0 || filterState().integrationMethods.length > 0 || filterState().maintainers.length > 0)) {
365368
<div class="position-relative mb-5">
366369
<div class="text-center">
367-
<h2 class="h3 mb-0">More apps</h2>
370+
<h2 class="h3 mb-0 section-title">More apps</h2>
368371
</div>
369372
</div>
370373

@@ -388,7 +391,7 @@ <h2 class="h3 mb-0">More apps</h2>
388391
}
389392
</div>
390393

391-
<div class="d-flex flex-wrap gap-4 mb-4 mx-auto content-width">
394+
<div class="apps-grid mb-4 mx-auto content-width">
392395
@for (app of moreApplications(); track app.id) {
393396
<div>
394397
<div class="card shadow-sm position-relative app-card">

angular-frontend/src/app/components/applications-list/applications-list.scss

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
======================================== */
1010
.page-bg {
1111
background-color: #e9ecef;
12+
min-width: 1080px;
1213
}
1314

1415
.content-width {
15-
width: 1080px;
16+
max-width: 1080px;
17+
width: 100%;
1618
}
1719

1820
/* ========================================
@@ -32,6 +34,7 @@
3234

3335
.hero-stat-value {
3436
color: #A3CDCC;
37+
font-size: 3.5rem;
3538
}
3639

3740
.hero-stat-label {
@@ -67,16 +70,24 @@
6770
======================================== */
6871
.overlay-image-container {
6972
position: absolute;
70-
right: 28%;
71-
top: 150px;
73+
top: -35px;
74+
left: 45%;
75+
transform: translateX(-50%);
7276
z-index: 5;
7377
}
7478

7579
.overlay-image {
76-
max-width: 450px;
80+
width: 450px;
7781
height: auto;
7882
}
7983

84+
/* ========================================
85+
SECTION TITLES
86+
======================================== */
87+
.section-title {
88+
font-size: 1.75rem;
89+
}
90+
8091
/* ========================================
8192
DESCRIPTION TEXT
8293
======================================== */
@@ -235,6 +246,20 @@
235246
transition: opacity 0.3s ease;
236247
}
237248

249+
/* ========================================
250+
MORE APPS RESPONSIVE GRID
251+
======================================== */
252+
.apps-grid {
253+
display: grid;
254+
grid-template-columns: repeat(auto-fill, minmax(252px, 1fr));
255+
gap: 1.5rem;
256+
}
257+
258+
.apps-grid .app-card {
259+
width: 100%;
260+
min-width: unset;
261+
}
262+
238263
/* ========================================
239264
STATUS BADGES
240265
======================================== */
@@ -410,7 +435,8 @@
410435
border: 0;
411436
border-top: 1px solid #6c757d;
412437
margin: 3rem auto;
413-
width: 1080px;
438+
max-width: 1080px;
439+
width: 100%;
414440
}
415441

416442
/* ========================================

angular-frontend/src/app/components/applications-list/applications-list.ts

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Licensed under the EUPL-1.2 or later.
55
*/
66

7-
import { Component, OnInit, signal, computed, ViewChild, ViewChildren, ElementRef, AfterViewInit, QueryList } from '@angular/core';
7+
import { Component, OnInit, OnDestroy, signal, computed, ViewChild, ViewChildren, ElementRef, AfterViewInit, QueryList } from '@angular/core';
88
import { CommonModule } from '@angular/common';
99
import { FormsModule } from '@angular/forms';
1010
import { Router } from '@angular/router';
@@ -23,7 +23,7 @@ import { AuthService } from '../../services/auth.service';
2323
templateUrl: './applications-list.html',
2424
styleUrls: ['./applications-list.scss']
2525
})
26-
export class ApplicationsList implements OnInit, AfterViewInit {
26+
export class ApplicationsList implements OnInit, AfterViewInit, OnDestroy {
2727
@ViewChild('scrollContainer') scrollContainer!: ElementRef<HTMLDivElement>;
2828
@ViewChild('scrollContainerMore') scrollContainerMore!: ElementRef<HTMLDivElement>;
2929
@ViewChildren('featuredCard') featuredCards!: QueryList<ElementRef<HTMLDivElement>>;
@@ -75,6 +75,9 @@ export class ApplicationsList implements OnInit, AfterViewInit {
7575
protected showLoginRequiredMessage = signal<boolean>(false);
7676
protected dropdownPosition = signal<{ top: number; left: number } | null>(null);
7777

78+
private activeChipElement: HTMLElement | null = null;
79+
private scrollListener: (() => void) | null = null;
80+
7881
protected filterState = signal<FilterState>({
7982
trending: false,
8083
categories: [],
@@ -255,17 +258,15 @@ export class ApplicationsList implements OnInit, AfterViewInit {
255258

256259
protected toggleDropdown(filterType: string, event: MouseEvent): void {
257260
if (this.openDropdown() === filterType) {
258-
this.openDropdown.set(null);
259-
this.dropdownPosition.set(null);
261+
this.closeDropdown();
260262
} else {
261263
const target = event.currentTarget as HTMLElement;
262-
const rect = target.closest('.filter-chip')?.getBoundingClientRect();
264+
const chip = target.closest('.filter-chip') as HTMLElement | null;
263265

264-
if (rect) {
265-
this.dropdownPosition.set({
266-
top: rect.bottom + 8,
267-
left: rect.left
268-
});
266+
if (chip) {
267+
this.activeChipElement = chip;
268+
this.updateDropdownPosition();
269+
this.attachScrollListener();
269270
}
270271
this.openDropdown.set(filterType);
271272
}
@@ -274,6 +275,34 @@ export class ApplicationsList implements OnInit, AfterViewInit {
274275
protected closeDropdown(): void {
275276
this.openDropdown.set(null);
276277
this.dropdownPosition.set(null);
278+
this.activeChipElement = null;
279+
this.detachScrollListener();
280+
}
281+
282+
private updateDropdownPosition(): void {
283+
if (!this.activeChipElement) return;
284+
const rect = this.activeChipElement.getBoundingClientRect();
285+
this.dropdownPosition.set({
286+
top: rect.bottom + 8,
287+
left: rect.left
288+
});
289+
}
290+
291+
private attachScrollListener(): void {
292+
this.detachScrollListener();
293+
this.scrollListener = () => this.updateDropdownPosition();
294+
window.addEventListener('scroll', this.scrollListener, true);
295+
}
296+
297+
private detachScrollListener(): void {
298+
if (this.scrollListener) {
299+
window.removeEventListener('scroll', this.scrollListener, true);
300+
this.scrollListener = null;
301+
}
302+
}
303+
304+
ngOnDestroy(): void {
305+
this.detachScrollListener();
277306
}
278307

279308
protected clearTrendingFilter(): void {

angular-frontend/src/app/components/filter-modal/filter-modal.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ export class FilterModal implements OnInit {
123123

124124
protected toggleTrending(): void {
125125
this.trending.set(!this.trending());
126+
this.closeModal();
126127
}
127128

128129
protected toggleCategory(categoryName: string): void {
@@ -133,6 +134,7 @@ export class FilterModal implements OnInit {
133134
current.add(categoryName);
134135
}
135136
this.selectedCategories.set(current);
137+
this.closeModal();
136138
}
137139

138140
protected toggleCapability(capability: string): void {
@@ -143,6 +145,7 @@ export class FilterModal implements OnInit {
143145
current.add(capability);
144146
}
145147
this.selectedCapabilities.set(current);
148+
this.closeModal();
146149
}
147150

148151
protected toggleAppStatus(status: string): void {
@@ -153,6 +156,7 @@ export class FilterModal implements OnInit {
153156
current.add(status);
154157
}
155158
this.selectedAppStatus.set(current);
159+
this.closeModal();
156160
}
157161

158162
protected isCategorySelected(categoryName: string): boolean {
@@ -175,6 +179,7 @@ export class FilterModal implements OnInit {
175179
current.add(version);
176180
}
177181
this.selectedMidpointVersions.set(current);
182+
this.closeModal();
178183
}
179184

180185
protected isMidpointVersionSelected(version: string): boolean {
@@ -189,6 +194,7 @@ export class FilterModal implements OnInit {
189194
current.add(method);
190195
}
191196
this.selectedIntegrationMethods.set(current);
197+
this.closeModal();
192198
}
193199

194200
protected isIntegrationMethodSelected(method: string): boolean {
@@ -203,6 +209,7 @@ export class FilterModal implements OnInit {
203209
current.add(maintainer);
204210
}
205211
this.selectedMaintainers.set(current);
212+
this.closeModal();
206213
}
207214

208215
protected isMaintainerSelected(maintainer: string): boolean {

0 commit comments

Comments
 (0)