Fehlerbehebung & Start Vector Search
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user