Fehlerbehebung & Start Vector Search

This commit is contained in:
2024-07-11 17:09:35 +02:00
parent 7bd5e1aaf8
commit b4644ea295
20 changed files with 381 additions and 245 deletions

View File

@@ -41,19 +41,21 @@
</div>
<ul class="py-2" aria-labelledby="user-menu-button">
<li>
<a routerLink="/account" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Account</a>
<a routerLink="/account" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Account</a>
</li>
<li>
<a routerLink="/createBusinessListing" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Create Listing</a>
<a routerLink="/createBusinessListing" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
>Create Listing</a
>
</li>
<li>
<a routerLink="/myListings" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">My Listings</a>
<a routerLink="/myListings" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">My Listings</a>
</li>
<li>
<a routerLink="/emailUs" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">EMail Us</a>
<a routerLink="/emailUs" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">EMail Us</a>
</li>
<li>
<a routerLink="/logout" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Logout</a>
<a routerLink="/logout" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Logout</a>
</li>
</ul>
</div>
@@ -93,6 +95,7 @@
[ngClass]="{ 'bg-blue-700 text-white md:text-blue-700 md:bg-transparent md:dark:text-blue-500': isActive('/businessListings') }"
class="block py-2 px-3 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700"
aria-current="page"
(click)="closeMenus()"
>Businesses</a
>
</li>
@@ -102,6 +105,7 @@
routerLink="/commercialPropertyListings"
[ngClass]="{ 'bg-blue-700 text-white md:text-blue-700 md:bg-transparent md:dark:text-blue-500': isActive('/commercialPropertyListings') }"
class="block py-2 px-3 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700"
(click)="closeMenus()"
>Properties</a
>
</li>
@@ -111,6 +115,7 @@
routerLink="/brokerListings"
[ngClass]="{ 'bg-blue-700 text-white md:text-blue-700 md:bg-transparent md:dark:text-blue-500': isActive('/brokerListings') }"
class="block py-2 px-3 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700"
(click)="closeMenus()"
>Professionals</a
>
</li>

View File

@@ -2,7 +2,7 @@ import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { Router, RouterModule } from '@angular/router';
import { faUserGear } from '@fortawesome/free-solid-svg-icons';
import { initFlowbite } from 'flowbite';
import { Collapse, Dropdown, initFlowbite } from 'flowbite';
import { KeycloakService } from 'keycloak-angular';
import { Observable } from 'rxjs';
import { User } from '../../../../../bizmatch-server/src/models/db.model';
@@ -60,4 +60,26 @@ export class HeaderComponent {
isActive(route: string): boolean {
return this.router.url === route;
}
closeDropdown() {
const dropdownButton = document.getElementById('user-menu-button');
const dropdownMenu = this.user ? document.getElementById('user-login') : document.getElementById('user-unknown');
if (dropdownButton && dropdownMenu) {
const dropdown = new Dropdown(dropdownMenu, dropdownButton);
dropdown.hide();
}
}
closeMobileMenu() {
const targetElement = document.getElementById('navbar-user');
const triggerElement = document.querySelector('[data-collapse-toggle="navbar-user"]');
if (targetElement instanceof HTMLElement && triggerElement instanceof HTMLElement) {
const collapse = new Collapse(targetElement, triggerElement);
collapse.collapse();
}
}
closeMenus() {
this.closeDropdown();
this.closeMobileMenu();
}
}

View File

@@ -0,0 +1,30 @@
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { MessageComponent } from './message.component';
import { Message, MessageService } from './message.service';
@Component({
selector: 'app-message-container',
standalone: true,
imports: [CommonModule, MessageComponent],
template: `
<div class="fixed top-5 right-5 z-50 flex flex-col items-end">
<app-message *ngFor="let message of messages" [message]="message" (close)="removeMessage(message)"> </app-message>
</div>
`,
})
export class MessageContainerComponent implements OnInit {
messages: Message[] = [];
constructor(private messageService: MessageService) {}
ngOnInit(): void {
this.messageService.messages$.subscribe(messages => {
this.messages = messages;
});
}
removeMessage(message: Message): void {
this.messageService.removeMessage(message);
}
}

View File

@@ -1,32 +1,25 @@
import { Component } from '@angular/core';
import { AsyncPipe, NgIf } from '@angular/common';
import { MessageService } from './message.service';
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Message } from './message.service';
@Component({
selector: 'app-message',
standalone: true,
imports: [AsyncPipe, NgIf],
imports: [CommonModule],
template: `
<div
*ngIf="messageService.modalVisible$ | async"
id="toast-success"
class="fixed top-[0.5rem] right-[1rem] flex items-center w-full max-w-xs p-4 mb-4 text-gray-500 bg-slate-200 rounded-lg shadow dark:text-gray-400 dark:bg-gray-800"
role="alert"
>
<div class="inline-flex items-center justify-center flex-shrink-0 w-8 h-8 text-green-500 bg-green-100 rounded-lg dark:bg-green-800 dark:text-green-200">
<div [ngClass]="getClasses()" role="alert">
<div [ngClass]="getIconClasses()">
<svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 8.207-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L9 10.586l3.293-3.293a1 1 0 0 1 1.414 1.414Z" />
<path [attr.d]="getIconPath()" />
</svg>
<span class="sr-only">Check icon</span>
<span class="sr-only">{{ getSrText() }}</span>
</div>
<div class="ms-3 text-sm font-normal">{{ messageService.message$ | async }}</div>
<div class="ms-3 text-sm font-normal">{{ message.text }}</div>
<button
type="button"
(click)="onClose()"
class="ms-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex items-center justify-center h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700"
data-dismiss-target="#toast-success"
aria-label="Close"
(click)="messageService.reject()"
>
<span class="sr-only">Close</span>
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
@@ -37,5 +30,59 @@ import { MessageService } from './message.service';
`,
})
export class MessageComponent {
constructor(public messageService: MessageService) {}
@Input() message!: Message;
@Output() close = new EventEmitter<void>();
onClose(): void {
this.close.emit();
}
getClasses(): string {
return `flex items-center w-full max-w-xs p-4 mb-4 text-gray-500 bg-white rounded-lg shadow dark:text-gray-400 dark:bg-gray-800 ${this.getSeverityClasses()}`;
}
getIconClasses(): string {
const baseClasses = 'inline-flex items-center justify-center flex-shrink-0 w-8 h-8 rounded-lg';
switch (this.message.severity) {
case 'success':
return `${baseClasses} text-green-500 bg-green-100 dark:bg-green-800 dark:text-green-200`;
case 'danger':
return `${baseClasses} text-red-500 bg-red-100 dark:bg-red-800 dark:text-red-200`;
case 'warning':
return `${baseClasses} text-orange-500 bg-orange-100 dark:bg-orange-700 dark:text-orange-200`;
}
}
getIconPath(): string {
switch (this.message.severity) {
case 'success':
return 'M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 8.207-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L9 10.586l3.293-3.293a1 1 0 0 1 1.414 1.414Z';
case 'danger':
return 'M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 11.793a1 1 0 1 1-1.414 1.414L10 11.414l-2.293 2.293a1 1 0 0 1-1.414-1.414L8.586 10 6.293 7.707a1 1 0 0 1 1.414-1.414L10 8.586l2.293-2.293a1 1 0 0 1 1.414 1.414L11.414 10l2.293 2.293Z';
case 'warning':
return 'M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM10 15a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm1-4a1 1 0 0 1-2 0V6a1 1 0 0 1 2 0v5Z';
}
}
getSrText(): string {
switch (this.message.severity) {
case 'success':
return 'Check icon';
case 'danger':
return 'Error icon';
case 'warning':
return 'Warning icon';
}
}
private getSeverityClasses(): string {
switch (this.message.severity) {
case 'success':
return 'border-green-500';
case 'danger':
return 'border-red-500';
case 'warning':
return 'border-orange-500';
}
}
}

View File

@@ -1,32 +1,30 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
export interface Message {
severity: 'success' | 'danger' | 'warning';
text: string;
duration: number;
}
@Injectable({
providedIn: 'root',
})
export class MessageService {
private modalVisibleSubject = new BehaviorSubject<boolean>(false);
private messageSubject = new BehaviorSubject<string>('');
private resolvePromise!: (value: boolean) => void;
private messagesSubject = new BehaviorSubject<Message[]>([]);
messages$: Observable<Message[]> = this.messagesSubject.asObservable();
modalVisible$: Observable<boolean> = this.modalVisibleSubject.asObservable();
message$: Observable<string> = this.messageSubject.asObservable();
addMessage(message: Message): void {
const currentMessages = this.messagesSubject.value;
this.messagesSubject.next([...currentMessages, message]);
showMessage(message: string): Promise<boolean> {
this.messageSubject.next(message);
this.modalVisibleSubject.next(true);
return new Promise<boolean>(resolve => {
this.resolvePromise = resolve;
});
if (message.duration > 0) {
setTimeout(() => this.removeMessage(message), message.duration);
}
}
accept(): void {
this.modalVisibleSubject.next(false);
this.resolvePromise(true);
}
reject(): void {
this.modalVisibleSubject.next(false);
this.resolvePromise(false);
removeMessage(messageToRemove: Message): void {
const currentMessages = this.messagesSubject.value;
this.messagesSubject.next(currentMessages.filter(msg => msg !== messageToRemove));
}
}