parent
8a7e26d2b6
commit
60866473f7
|
|
@ -1,6 +1,7 @@
|
||||||
import { Controller, Delete, Inject, Param, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
|
import { Controller, Delete, Inject, Param, Post, UploadedFile, UseGuards, UseInterceptors } from '@nestjs/common';
|
||||||
import { FileInterceptor } from '@nestjs/platform-express';
|
import { FileInterceptor } from '@nestjs/platform-express';
|
||||||
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
||||||
|
import { JwtAuthGuard } from 'src/jwt-auth/jwt-auth.guard';
|
||||||
import { Logger } from 'winston';
|
import { Logger } from 'winston';
|
||||||
import { FileService } from '../file/file.service';
|
import { FileService } from '../file/file.service';
|
||||||
import { CommercialPropertyService } from '../listings/commercial-property.service';
|
import { CommercialPropertyService } from '../listings/commercial-property.service';
|
||||||
|
|
@ -17,12 +18,14 @@ export class ImageController {
|
||||||
// ############
|
// ############
|
||||||
// Property
|
// Property
|
||||||
// ############
|
// ############
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
@Post('uploadPropertyPicture/:imagePath/:serial')
|
@Post('uploadPropertyPicture/:imagePath/:serial')
|
||||||
@UseInterceptors(FileInterceptor('file'))
|
@UseInterceptors(FileInterceptor('file'))
|
||||||
async uploadPropertyPicture(@UploadedFile() file: Express.Multer.File, @Param('imagePath') imagePath: string, @Param('serial') serial: string) {
|
async uploadPropertyPicture(@UploadedFile() file: Express.Multer.File, @Param('imagePath') imagePath: string, @Param('serial') serial: string) {
|
||||||
const imagename = await this.fileService.storePropertyPicture(file, imagePath, serial);
|
const imagename = await this.fileService.storePropertyPicture(file, imagePath, serial);
|
||||||
await this.listingService.addImage(imagePath, serial, imagename);
|
await this.listingService.addImage(imagePath, serial, imagename);
|
||||||
}
|
}
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
@Delete('propertyPicture/:imagePath/:serial/:imagename')
|
@Delete('propertyPicture/:imagePath/:serial/:imagename')
|
||||||
async deletePropertyImagesById(@Param('imagePath') imagePath: string, @Param('serial') serial: string, @Param('imagename') imagename: string): Promise<any> {
|
async deletePropertyImagesById(@Param('imagePath') imagePath: string, @Param('serial') serial: string, @Param('imagename') imagename: string): Promise<any> {
|
||||||
this.fileService.deleteImage(`pictures/property/${imagePath}/${serial}/${imagename}`);
|
this.fileService.deleteImage(`pictures/property/${imagePath}/${serial}/${imagename}`);
|
||||||
|
|
@ -31,11 +34,13 @@ export class ImageController {
|
||||||
// ############
|
// ############
|
||||||
// Profile
|
// Profile
|
||||||
// ############
|
// ############
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
@Post('uploadProfile/:email')
|
@Post('uploadProfile/:email')
|
||||||
@UseInterceptors(FileInterceptor('file'))
|
@UseInterceptors(FileInterceptor('file'))
|
||||||
async uploadProfile(@UploadedFile() file: Express.Multer.File, @Param('email') adjustedEmail: string) {
|
async uploadProfile(@UploadedFile() file: Express.Multer.File, @Param('email') adjustedEmail: string) {
|
||||||
await this.fileService.storeProfilePicture(file, adjustedEmail);
|
await this.fileService.storeProfilePicture(file, adjustedEmail);
|
||||||
}
|
}
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
@Delete('profile/:email/')
|
@Delete('profile/:email/')
|
||||||
async deleteProfileImagesById(@Param('email') email: string): Promise<any> {
|
async deleteProfileImagesById(@Param('email') email: string): Promise<any> {
|
||||||
this.fileService.deleteImage(`pictures/profile/${email}.avif`);
|
this.fileService.deleteImage(`pictures/profile/${email}.avif`);
|
||||||
|
|
@ -43,11 +48,13 @@ export class ImageController {
|
||||||
// ############
|
// ############
|
||||||
// Logo
|
// Logo
|
||||||
// ############
|
// ############
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
@Post('uploadCompanyLogo/:email')
|
@Post('uploadCompanyLogo/:email')
|
||||||
@UseInterceptors(FileInterceptor('file'))
|
@UseInterceptors(FileInterceptor('file'))
|
||||||
async uploadCompanyLogo(@UploadedFile() file: Express.Multer.File, @Param('email') adjustedEmail: string) {
|
async uploadCompanyLogo(@UploadedFile() file: Express.Multer.File, @Param('email') adjustedEmail: string) {
|
||||||
await this.fileService.storeCompanyLogo(file, adjustedEmail);
|
await this.fileService.storeCompanyLogo(file, adjustedEmail);
|
||||||
}
|
}
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
@Delete('logo/:email/')
|
@Delete('logo/:email/')
|
||||||
async deleteLogoImagesById(@Param('email') adjustedEmail: string): Promise<any> {
|
async deleteLogoImagesById(@Param('email') adjustedEmail: string): Promise<any> {
|
||||||
this.fileService.deleteImage(`pictures/logo/${adjustedEmail}.avif`);
|
this.fileService.deleteImage(`pictures/logo/${adjustedEmail}.avif`);
|
||||||
|
|
|
||||||
|
|
@ -103,9 +103,6 @@ export class BusinessListingService {
|
||||||
whereConditions.push(and(ilike(schema.users.firstname, `%${firstname}%`), ilike(schema.users.lastname, `%${lastname}%`)));
|
whereConditions.push(and(ilike(schema.users.firstname, `%${firstname}%`), ilike(schema.users.lastname, `%${lastname}%`)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if (criteria.brokerName) {
|
|
||||||
// whereConditions.push(or(ilike(schema.users.firstname, `%${criteria.brokerName}%`), ilike(schema.users.lastname, `%${criteria.brokerName}%`)));
|
|
||||||
// }
|
|
||||||
if (!user?.roles?.includes('ADMIN') ?? false) {
|
if (!user?.roles?.includes('ADMIN') ?? false) {
|
||||||
whereConditions.push(or(eq(businesses.email, user?.username), ne(businesses.draft, true)));
|
whereConditions.push(or(eq(businesses.email, user?.username), ne(businesses.draft, true)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,16 +51,12 @@ export class BusinessListingsController {
|
||||||
this.logger.info(`Save Listing`);
|
this.logger.info(`Save Listing`);
|
||||||
return this.listingsService.updateBusinessListing(listing.id, listing);
|
return this.listingsService.updateBusinessListing(listing.id, listing);
|
||||||
}
|
}
|
||||||
@Delete(':id')
|
@Delete('listing/:id')
|
||||||
deleteById(@Param('id') id: string) {
|
deleteById(@Param('id') id: string) {
|
||||||
this.listingsService.deleteListing(id);
|
this.listingsService.deleteListing(id);
|
||||||
}
|
}
|
||||||
// @Get('states/all')
|
|
||||||
// getStates(): any {
|
|
||||||
// return this.listingsService.getStates();
|
|
||||||
// }
|
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Delete('favorites/:id')
|
@Delete('favorite/:id')
|
||||||
deleteFavorite(@Request() req, @Param('id') id: string) {
|
deleteFavorite(@Request() req, @Param('id') id: string) {
|
||||||
this.listingsService.deleteFavorite(id, req.user as JwtUser);
|
this.listingsService.deleteFavorite(id, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,6 @@ export class CommercialPropertyListingsController {
|
||||||
findTotal(@Request() req, @Body() criteria: CommercialPropertyListingCriteria): Promise<number> {
|
findTotal(@Request() req, @Body() criteria: CommercialPropertyListingCriteria): Promise<number> {
|
||||||
return this.listingsService.getCommercialPropertiesCount(criteria, req.user as JwtUser);
|
return this.listingsService.getCommercialPropertiesCount(criteria, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
// @Get('states/all')
|
|
||||||
// getStates(): any {
|
|
||||||
// return this.listingsService.getStates();
|
|
||||||
// }
|
|
||||||
@Post()
|
@Post()
|
||||||
async create(@Body() listing: any) {
|
async create(@Body() listing: any) {
|
||||||
this.logger.info(`Save Listing`);
|
this.logger.info(`Save Listing`);
|
||||||
|
|
@ -55,13 +51,13 @@ export class CommercialPropertyListingsController {
|
||||||
this.logger.info(`Save Listing`);
|
this.logger.info(`Save Listing`);
|
||||||
return await this.listingsService.updateCommercialPropertyListing(listing.id, listing);
|
return await this.listingsService.updateCommercialPropertyListing(listing.id, listing);
|
||||||
}
|
}
|
||||||
@Delete(':id/:imagePath')
|
@Delete('listing/:id/:imagePath')
|
||||||
deleteById(@Param('id') id: string, @Param('imagePath') imagePath: string) {
|
deleteById(@Param('id') id: string, @Param('imagePath') imagePath: string) {
|
||||||
this.listingsService.deleteListing(id);
|
this.listingsService.deleteListing(id);
|
||||||
this.fileService.deleteDirectoryIfExists(imagePath);
|
this.fileService.deleteDirectoryIfExists(imagePath);
|
||||||
}
|
}
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Delete('favorites/:id')
|
@Delete('favorite/:id')
|
||||||
deleteFavorite(@Request() req, @Param('id') id: string) {
|
deleteFavorite(@Request() req, @Param('id') id: string) {
|
||||||
this.listingsService.deleteFavorite(id, req.user as JwtUser);
|
this.listingsService.deleteFavorite(id, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,8 +115,8 @@ export class MailService {
|
||||||
//template: './inquiry', // `.hbs` extension is appended automatically
|
//template: './inquiry', // `.hbs` extension is appended automatically
|
||||||
template: join(__dirname, '../..', 'mail/templates/send2Friend.hbs'),
|
template: join(__dirname, '../..', 'mail/templates/send2Friend.hbs'),
|
||||||
context: {
|
context: {
|
||||||
name: shareByEMail.name,
|
name: shareByEMail.yourName,
|
||||||
email: shareByEMail.email,
|
email: shareByEMail.yourEmail,
|
||||||
listingTitle: shareByEMail.listingTitle,
|
listingTitle: shareByEMail.listingTitle,
|
||||||
url: shareByEMail.url,
|
url: shareByEMail.url,
|
||||||
id: shareByEMail.id,
|
id: shareByEMail.id,
|
||||||
|
|
|
||||||
|
|
@ -307,9 +307,9 @@ export const SenderSchema = z.object({
|
||||||
});
|
});
|
||||||
export type Sender = z.infer<typeof SenderSchema>;
|
export type Sender = z.infer<typeof SenderSchema>;
|
||||||
export const ShareByEMailSchema = z.object({
|
export const ShareByEMailSchema = z.object({
|
||||||
name: z.string().min(6, { message: 'Name must be at least 6 characters long' }),
|
yourName: z.string().min(6, { message: 'Name must be at least 6 characters long' }),
|
||||||
recipientEmail: z.string().email({ message: 'Invalid email address' }),
|
recipientEmail: z.string().email({ message: 'Invalid email address' }),
|
||||||
email: z.string().email({ message: 'Invalid email address' }),
|
yourEmail: z.string().email({ message: 'Invalid email address' }),
|
||||||
listingTitle: z.string().optional().nullable(),
|
listingTitle: z.string().optional().nullable(),
|
||||||
url: z.string().url({ message: 'Invalid URL format' }).optional().nullable(),
|
url: z.string().url({ message: 'Invalid URL format' }).optional().nullable(),
|
||||||
id: z.string().optional().nullable(),
|
id: z.string().optional().nullable(),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { Component, HostListener } from '@angular/core';
|
import { Component, HostListener } from '@angular/core';
|
||||||
import { ActivatedRoute, NavigationEnd, Router, RouterOutlet } from '@angular/router';
|
import { ActivatedRoute, NavigationEnd, Router, RouterOutlet } from '@angular/router';
|
||||||
import { KeycloakService } from 'keycloak-angular';
|
import { KeycloakEventType, KeycloakService } from 'keycloak-angular';
|
||||||
|
|
||||||
import { filter } from 'rxjs/operators';
|
import { filter } from 'rxjs/operators';
|
||||||
import build from '../build';
|
import build from '../build';
|
||||||
|
|
@ -45,14 +45,38 @@ export class AppComponent {
|
||||||
this.actualRoute = currentRoute.snapshot.url[0].path;
|
this.actualRoute = currentRoute.snapshot.url[0].path;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ngOnInit() {}
|
ngOnInit() {
|
||||||
|
// Überwache Keycloak-Events, um den Token-Refresh zu kontrollieren
|
||||||
|
this.keycloakService.keycloakEvents$.subscribe({
|
||||||
|
next: event => {
|
||||||
|
if (event.type === KeycloakEventType.OnTokenExpired) {
|
||||||
|
// Wenn der Token abgelaufen ist, versuchen wir einen Refresh
|
||||||
|
this.handleTokenExpiration();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private async handleTokenExpiration(): Promise<void> {
|
||||||
|
try {
|
||||||
|
// Versuche, den Token zu erneuern
|
||||||
|
const refreshed = await this.keycloakService.updateToken();
|
||||||
|
if (!refreshed) {
|
||||||
|
// Wenn der Token nicht erneuert werden kann, leite zur Login-Seite weiter
|
||||||
|
this.keycloakService.login({
|
||||||
|
redirectUri: window.location.href, // oder eine andere Seite
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.error === 'invalid_grant' && error.error_description === 'Token is not active') {
|
||||||
|
// Hier wird der Fehler "invalid_grant" abgefangen
|
||||||
|
this.keycloakService.login({
|
||||||
|
redirectUri: window.location.href,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@HostListener('window:keydown', ['$event'])
|
@HostListener('window:keydown', ['$event'])
|
||||||
handleKeyboardEvent(event: KeyboardEvent) {
|
handleKeyboardEvent(event: KeyboardEvent) {
|
||||||
// this.router.events.subscribe(event => {
|
|
||||||
// if (event instanceof NavigationEnd) {
|
|
||||||
// initFlowbite();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
if (event.shiftKey && event.ctrlKey && event.key === 'V') {
|
if (event.shiftKey && event.ctrlKey && event.key === 'V') {
|
||||||
this.showVersionDialog();
|
this.showVersionDialog();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { APP_INITIALIZER, ApplicationConfig } from '@angular/core';
|
import { APP_INITIALIZER, ApplicationConfig, ErrorHandler } from '@angular/core';
|
||||||
import { provideRouter, withEnabledBlockingInitialNavigation, withInMemoryScrolling } from '@angular/router';
|
import { provideRouter, withEnabledBlockingInitialNavigation, withInMemoryScrolling } from '@angular/router';
|
||||||
|
|
||||||
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
||||||
|
|
@ -9,11 +9,10 @@ import { provideQuillConfig } from 'ngx-quill';
|
||||||
import { provideShareButtonsOptions, SharerMethods, withConfig } from 'ngx-sharebuttons';
|
import { provideShareButtonsOptions, SharerMethods, withConfig } from 'ngx-sharebuttons';
|
||||||
import { shareIcons } from 'ngx-sharebuttons/icons';
|
import { shareIcons } from 'ngx-sharebuttons/icons';
|
||||||
import { provideNgxStripe } from 'ngx-stripe';
|
import { provideNgxStripe } from 'ngx-stripe';
|
||||||
import { environment } from '../environments/environment';
|
|
||||||
import { customKeycloakAdapter } from '../keycloak';
|
|
||||||
import { routes } from './app.routes';
|
import { routes } from './app.routes';
|
||||||
import { LoadingInterceptor } from './interceptors/loading.interceptor';
|
import { LoadingInterceptor } from './interceptors/loading.interceptor';
|
||||||
import { TimeoutInterceptor } from './interceptors/timeout.interceptor';
|
import { TimeoutInterceptor } from './interceptors/timeout.interceptor';
|
||||||
|
import { GlobalErrorHandler } from './services/globalErrorHandler';
|
||||||
import { KeycloakInitializerService } from './services/keycloak-initializer.service';
|
import { KeycloakInitializerService } from './services/keycloak-initializer.service';
|
||||||
import { SelectOptionsService } from './services/select-options.service';
|
import { SelectOptionsService } from './services/select-options.service';
|
||||||
import { createLogger } from './utils/utils';
|
import { createLogger } from './utils/utils';
|
||||||
|
|
@ -25,9 +24,9 @@ export const appConfig: ApplicationConfig = {
|
||||||
{ provide: KeycloakService },
|
{ provide: KeycloakService },
|
||||||
{
|
{
|
||||||
provide: APP_INITIALIZER,
|
provide: APP_INITIALIZER,
|
||||||
// useFactory: initializeKeycloak,
|
// useFactory: initializeKeycloak1,
|
||||||
//useFactory: initializeKeycloak,
|
//useFactory: initializeKeycloak2,
|
||||||
useFactory: initializeKeycloak3,
|
useFactory: initializeKeycloak,
|
||||||
multi: true,
|
multi: true,
|
||||||
//deps: [KeycloakService],
|
//deps: [KeycloakService],
|
||||||
deps: [KeycloakInitializerService],
|
deps: [KeycloakInitializerService],
|
||||||
|
|
@ -64,6 +63,7 @@ export const appConfig: ApplicationConfig = {
|
||||||
imageSize: 'cover',
|
imageSize: 'cover',
|
||||||
} as GalleryConfig,
|
} as GalleryConfig,
|
||||||
},
|
},
|
||||||
|
{ provide: ErrorHandler, useClass: GlobalErrorHandler }, // Registriere den globalen ErrorHandler
|
||||||
provideShareButtonsOptions(
|
provideShareButtonsOptions(
|
||||||
shareIcons(),
|
shareIcons(),
|
||||||
withConfig({
|
withConfig({
|
||||||
|
|
@ -100,47 +100,47 @@ function initServices(selectOptions: SelectOptionsService) {
|
||||||
await selectOptions.init();
|
await selectOptions.init();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
export function initializeKeycloak3(keycloak: KeycloakInitializerService) {
|
export function initializeKeycloak(keycloak: KeycloakInitializerService) {
|
||||||
return () => keycloak.initialize();
|
return () => keycloak.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initializeKeycloak2(keycloak: KeycloakService): () => Promise<void> {
|
// export function initializeKeycloak1(keycloak: KeycloakService): () => Promise<void> {
|
||||||
return async () => {
|
// return async () => {
|
||||||
const { url, realm, clientId } = environment.keycloak;
|
// const { url, realm, clientId } = environment.keycloak;
|
||||||
const adapter = customKeycloakAdapter(() => keycloak.getKeycloakInstance(), {});
|
// const adapter = customKeycloakAdapter(() => keycloak.getKeycloakInstance(), {});
|
||||||
if (window.location.search.length > 0) {
|
// if (window.location.search.length > 0) {
|
||||||
sessionStorage.setItem('SEARCH', window.location.search);
|
// sessionStorage.setItem('SEARCH', window.location.search);
|
||||||
}
|
// }
|
||||||
const { host, hostname, href, origin, pathname, port, protocol, search } = window.location;
|
// const { host, hostname, href, origin, pathname, port, protocol, search } = window.location;
|
||||||
await keycloak.init({
|
// await keycloak.init({
|
||||||
config: { url, realm, clientId },
|
// config: { url, realm, clientId },
|
||||||
initOptions: {
|
// initOptions: {
|
||||||
onLoad: 'check-sso',
|
// onLoad: 'check-sso',
|
||||||
silentCheckSsoRedirectUri: window.location.hostname === 'localhost' ? `${window.location.origin}/assets/silent-check-sso.html` : `${window.location.origin}/dealerweb/assets/silent-check-sso.html`,
|
// silentCheckSsoRedirectUri: window.location.hostname === 'localhost' ? `${window.location.origin}/assets/silent-check-sso.html` : `${window.location.origin}/dealerweb/assets/silent-check-sso.html`,
|
||||||
adapter,
|
// adapter,
|
||||||
redirectUri: `${origin}${pathname}`,
|
// redirectUri: `${origin}${pathname}`,
|
||||||
},
|
// },
|
||||||
});
|
// });
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
function initializeKeycloak(keycloak: KeycloakService) {
|
// function initializeKeycloak2(keycloak: KeycloakService) {
|
||||||
return async () => {
|
// return async () => {
|
||||||
logger.info(`###>calling keycloakService init ...`);
|
// logger.info(`###>calling keycloakService init ...`);
|
||||||
const authenticated = await keycloak.init({
|
// const authenticated = await keycloak.init({
|
||||||
config: {
|
// config: {
|
||||||
url: environment.keycloak.url,
|
// url: environment.keycloak.url,
|
||||||
realm: environment.keycloak.realm,
|
// realm: environment.keycloak.realm,
|
||||||
clientId: environment.keycloak.clientId,
|
// clientId: environment.keycloak.clientId,
|
||||||
},
|
// },
|
||||||
initOptions: {
|
// initOptions: {
|
||||||
onLoad: 'check-sso',
|
// onLoad: 'check-sso',
|
||||||
silentCheckSsoRedirectUri: (<any>window).location.origin + '/assets/silent-check-sso.html',
|
// silentCheckSsoRedirectUri: (<any>window).location.origin + '/assets/silent-check-sso.html',
|
||||||
},
|
// },
|
||||||
bearerExcludedUrls: ['/assets'],
|
// bearerExcludedUrls: ['/assets'],
|
||||||
shouldUpdateToken(request) {
|
// shouldUpdateToken(request) {
|
||||||
return !request.headers.get('token-update') === false;
|
// return !request.headers.get('token-update') === false;
|
||||||
},
|
// },
|
||||||
});
|
// });
|
||||||
logger.info(`+++>${authenticated}`);
|
// logger.info(`+++>${authenticated}`);
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,10 @@
|
||||||
<div class="p-4 md:p-5">
|
<div class="p-4 md:p-5">
|
||||||
<form class="space-y-4" action="#">
|
<form class="space-y-4" action="#">
|
||||||
<div>
|
<div>
|
||||||
<app-validated-input label="Your Email" name="email" [(ngModel)]="shareByEMail.email"></app-validated-input>
|
<app-validated-input label="Your Email" name="yourEmail" [(ngModel)]="shareByEMail.yourEmail"></app-validated-input>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<app-validated-input label="Your Name" name="name" [(ngModel)]="shareByEMail.name"></app-validated-input>
|
<app-validated-input label="Your Name" name="yourName" [(ngModel)]="shareByEMail.yourName"></app-validated-input>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<app-validated-input label="Your Friend's EMail" name="recipientEmail" [(ngModel)]="shareByEMail.recipientEmail"></app-validated-input>
|
<app-validated-input label="Your Friend's EMail" name="recipientEmail" [(ngModel)]="shareByEMail.recipientEmail"></app-validated-input>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<div
|
<div
|
||||||
[id]="id"
|
[id]="id"
|
||||||
role="tooltip"
|
role="tooltip"
|
||||||
class="max-w-72 w-max absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700"
|
class="max-w-72 w-max absolute z-50 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700"
|
||||||
>
|
>
|
||||||
{{ text }}
|
{{ text }}
|
||||||
<div class="tooltip-arrow" data-popper-arrow></div>
|
<div class="tooltip-arrow" data-popper-arrow></div>
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,6 @@ export class DetailsBusinessListingComponent {
|
||||||
this.mailinfo.listing = this.listing;
|
this.mailinfo.listing = this.listing;
|
||||||
await this.mailService.mail(this.mailinfo);
|
await this.mailService.mail(this.mailinfo);
|
||||||
this.messageService.addMessage({ severity: 'success', text: 'Your message has been sent to the creator of the listing', duration: 3000 });
|
this.messageService.addMessage({ severity: 'success', text: 'Your message has been sent to the creator of the listing', duration: 3000 });
|
||||||
this.mailinfo = createMailInfo(this.user);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.messageService.addMessage({
|
this.messageService.addMessage({
|
||||||
severity: 'danger',
|
severity: 'danger',
|
||||||
|
|
@ -121,6 +120,9 @@ export class DetailsBusinessListingComponent {
|
||||||
this.validationMessagesService.updateMessages(error.error.message);
|
this.validationMessagesService.updateMessages(error.error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.user) {
|
||||||
|
this.mailinfo = createMailInfo(this.user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
get listingDetails() {
|
get listingDetails() {
|
||||||
let typeOfRealEstate = '';
|
let typeOfRealEstate = '';
|
||||||
|
|
@ -158,8 +160,8 @@ export class DetailsBusinessListingComponent {
|
||||||
}
|
}
|
||||||
async showShareByEMail() {
|
async showShareByEMail() {
|
||||||
const result = await this.emailService.showShareByEMail({
|
const result = await this.emailService.showShareByEMail({
|
||||||
email: this.user.email,
|
yourEmail: this.user ? this.user.email : null,
|
||||||
name: `${this.user.firstname} ${this.user.lastname}`,
|
yourName: this.user ? `${this.user.firstname} ${this.user.lastname}` : null,
|
||||||
url: environment.mailinfoUrl,
|
url: environment.mailinfoUrl,
|
||||||
listingTitle: this.listing.title,
|
listingTitle: this.listing.title,
|
||||||
id: this.listing.id,
|
id: this.listing.id,
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,6 @@ export class DetailsCommercialPropertyListingComponent {
|
||||||
this.mailinfo.listing = this.listing;
|
this.mailinfo.listing = this.listing;
|
||||||
await this.mailService.mail(this.mailinfo);
|
await this.mailService.mail(this.mailinfo);
|
||||||
this.messageService.addMessage({ severity: 'success', text: 'Your message has been sent to the creator of the listing', duration: 3000 });
|
this.messageService.addMessage({ severity: 'success', text: 'Your message has been sent to the creator of the listing', duration: 3000 });
|
||||||
this.mailinfo = createMailInfo(this.user);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.messageService.addMessage({
|
this.messageService.addMessage({
|
||||||
severity: 'danger',
|
severity: 'danger',
|
||||||
|
|
@ -154,6 +153,9 @@ export class DetailsCommercialPropertyListingComponent {
|
||||||
this.validationMessagesService.updateMessages(error.error.message);
|
this.validationMessagesService.updateMessages(error.error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.user) {
|
||||||
|
this.mailinfo = createMailInfo(this.user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
containsError(fieldname: string) {
|
containsError(fieldname: string) {
|
||||||
return this.errorResponse?.fields.map(f => f.fieldname).includes(fieldname);
|
return this.errorResponse?.fields.map(f => f.fieldname).includes(fieldname);
|
||||||
|
|
@ -170,8 +172,8 @@ export class DetailsCommercialPropertyListingComponent {
|
||||||
}
|
}
|
||||||
async showShareByEMail() {
|
async showShareByEMail() {
|
||||||
const result = await this.emailService.showShareByEMail({
|
const result = await this.emailService.showShareByEMail({
|
||||||
email: this.user.email,
|
yourEmail: this.user.email,
|
||||||
name: `${this.user.firstname} ${this.user.lastname}`,
|
yourName: `${this.user.firstname} ${this.user.lastname}`,
|
||||||
url: environment.mailinfoUrl,
|
url: environment.mailinfoUrl,
|
||||||
listingTitle: this.listing.title,
|
listingTitle: this.listing.title,
|
||||||
id: this.listing.id,
|
id: this.listing.id,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { HttpErrorResponse } from '@angular/common/http';
|
||||||
|
import { ErrorHandler, Injectable } from '@angular/core';
|
||||||
|
import { KeycloakService } from 'keycloak-angular';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class GlobalErrorHandler implements ErrorHandler {
|
||||||
|
constructor(private keycloakService: KeycloakService) {}
|
||||||
|
|
||||||
|
handleError(error: any): void {
|
||||||
|
// Prüfe, ob es sich um einen HttpErrorResponse handelt
|
||||||
|
if (error instanceof HttpErrorResponse) {
|
||||||
|
// Prüfe, ob es ein 401 Unauthorized Fehler ist
|
||||||
|
if (error.status === 401) {
|
||||||
|
// Führe den Login-Prozess über Keycloak aus
|
||||||
|
this.keycloakService.login({
|
||||||
|
redirectUri: window.location.href, // oder eine benutzerdefinierte URL
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Weiterhin normale Fehlerbehandlung
|
||||||
|
console.error('Ein Fehler ist aufgetreten:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -21,8 +21,8 @@ export class KeycloakInitializerService {
|
||||||
initOptions: {
|
initOptions: {
|
||||||
onLoad: 'check-sso',
|
onLoad: 'check-sso',
|
||||||
silentCheckSsoRedirectUri: (<any>window).location.origin + '/assets/silent-check-sso.html',
|
silentCheckSsoRedirectUri: (<any>window).location.origin + '/assets/silent-check-sso.html',
|
||||||
// flow: 'implicit',
|
|
||||||
},
|
},
|
||||||
|
bearerExcludedUrls: ['/assets'],
|
||||||
});
|
});
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
resolve(true);
|
resolve(true);
|
||||||
|
|
@ -30,35 +30,5 @@ export class KeycloakInitializerService {
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if (this.initialized) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// logger.info(`###>calling keycloakService init ...`);
|
|
||||||
// const authenticated = await this.keycloakService.init({
|
|
||||||
// config: {
|
|
||||||
// url: environment.keycloak.url,
|
|
||||||
// realm: environment.keycloak.realm,
|
|
||||||
// clientId: environment.keycloak.clientId,
|
|
||||||
// },
|
|
||||||
// initOptions: {
|
|
||||||
// onLoad: 'check-sso',
|
|
||||||
// silentCheckSsoRedirectUri: (<any>window).location.origin + '/assets/silent-check-sso.html',
|
|
||||||
// // flow: 'implicit',
|
|
||||||
// },
|
|
||||||
// // initOptions: {
|
|
||||||
// // pkceMethod: 'S256',
|
|
||||||
// // redirectUri: environment.keycloak.redirectUri,
|
|
||||||
// // checkLoginIframe: false,
|
|
||||||
// // },
|
|
||||||
// });
|
|
||||||
// logger.info(`+++>authenticated: ${authenticated}`);
|
|
||||||
// const token = await this.keycloakService.getToken();
|
|
||||||
// logger.info(`--->${token}`);
|
|
||||||
|
|
||||||
// this.initialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// isInitialized(): boolean {
|
|
||||||
// return this.initialized;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,12 +44,12 @@ export class ListingsService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async deleteBusinessListing(id: string) {
|
async deleteBusinessListing(id: string) {
|
||||||
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/business/${id}`));
|
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/business/listing/${id}`));
|
||||||
}
|
}
|
||||||
async deleteCommercialPropertyListing(id: string, imagePath: string) {
|
async deleteCommercialPropertyListing(id: string, imagePath: string) {
|
||||||
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/commercialProperty/${id}/${imagePath}`));
|
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/commercialProperty/listing/${id}/${imagePath}`));
|
||||||
}
|
}
|
||||||
async removeFavorite(id: string, listingsCategory?: 'business' | 'commercialProperty') {
|
async removeFavorite(id: string, listingsCategory?: 'business' | 'commercialProperty') {
|
||||||
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/favorites/${id}`));
|
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/favorite/${id}`));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue