diff --git a/bizmatch-server/src/file/file.service.ts b/bizmatch-server/src/file/file.service.ts index 47c3e83..3024122 100644 --- a/bizmatch-server/src/file/file.service.ts +++ b/bizmatch-server/src/file/file.service.ts @@ -1,13 +1,12 @@ import { Inject, Injectable } from '@nestjs/common'; -import { fstat, readFileSync } from 'fs'; -import { join } from 'path'; -import { fileURLToPath } from 'url'; -import path from 'path'; +import { readFileSync } from 'fs'; import fs from 'fs-extra'; -import { ImageProperty } from '../models/main.model.js'; -import sharp from 'sharp'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; +import path, { join } from 'path'; +import sharp from 'sharp'; +import { fileURLToPath } from 'url'; import { Logger } from 'winston'; +import { ImageProperty } from '../models/main.model.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -27,66 +26,66 @@ export class FileService { this.subscriptions = JSON.parse(rawData); } getSubscriptions() { - return this.subscriptions + return this.subscriptions; } async storeProfilePicture(file: Express.Multer.File, userId: string) { - let quality = 50; + let quality = 50; const output = await sharp(file.buffer) - .resize({ width: 300 }) - .avif({ quality }) // Verwende AVIF - //.webp({ quality }) // Verwende Webp - .toBuffer(); - await sharp(output).toFile(`./pictures/profile/${userId}.avif`); + .resize({ width: 300 }) + .avif({ quality }) // Verwende AVIF + //.webp({ quality }) // Verwende Webp + .toBuffer(); + await sharp(output).toFile(`./pictures/profile/${userId}.avif`); } - hasProfile(userId: string){ - return fs.existsSync(`./pictures/profile/${userId}.avif`) + hasProfile(userId: string) { + return fs.existsSync(`./pictures/profile/${userId}.avif`); } async storeCompanyLogo(file: Express.Multer.File, userId: string) { - let quality = 50; + let quality = 50; const output = await sharp(file.buffer) - .resize({ width: 300 }) - .avif({ quality }) // Verwende AVIF - //.webp({ quality }) // Verwende Webp - .toBuffer(); + .resize({ width: 300 }) + .avif({ quality }) // Verwende AVIF + //.webp({ quality }) // Verwende Webp + .toBuffer(); await sharp(output).toFile(`./pictures/logo/${userId}.avif`); // Ersetze Dateierweiterung // await fs.outputFile(`./pictures/logo/${userId}`, file.buffer); } - hasCompanyLogo(userId: string){ - return fs.existsSync(`./pictures/logo/${userId}.avif`)?true:false + hasCompanyLogo(userId: string) { + return fs.existsSync(`./pictures/logo/${userId}.avif`) ? true : false; } - + async getPropertyImages(listingId: string): Promise { - const result: string[] = [] - const directory = `./pictures/property/${listingId}` + const result: string[] = []; + const directory = `./pictures/property/${listingId}`; if (fs.existsSync(directory)) { const files = await fs.readdir(directory); files.forEach(f => { - result.push(f) - }) + result.push(f); + }); return result; } else { - return [] + return []; } } async hasPropertyImages(listingId: string): Promise { - const result: ImageProperty[] = [] - const directory = `./pictures/property/${listingId}` + const result: ImageProperty[] = []; + const directory = `./pictures/property/${listingId}`; if (fs.existsSync(directory)) { const files = await fs.readdir(directory); - return files.length>0 + return files.length > 0; } else { - return false + return false; } } - async storePropertyPicture(file: Express.Multer.File, listingId: string) : Promise { - const suffix = file.mimetype.includes('png') ? 'png' : 'jpg' - const directory = `./pictures/property/${listingId}` + async storePropertyPicture(file: Express.Multer.File, listingId: string): Promise { + const suffix = file.mimetype.includes('png') ? 'png' : 'jpg'; + const directory = `./pictures/property/${listingId}`; fs.ensureDirSync(`${directory}`); const imageName = await this.getNextImageName(directory); //await fs.outputFile(`${directory}/${imageName}`, file.buffer); - await this.resizeImageToAVIF(file.buffer,150 * 1024,imageName,directory); - return `${imageName}.avif` + await this.resizeImageToAVIF(file.buffer, 150 * 1024, imageName, directory); + return `${imageName}.avif`; } async getNextImageName(directory) { try { @@ -103,37 +102,51 @@ export class FileService { return null; } } - async resizeImageToAVIF(buffer: Buffer, maxSize: number,imageName:string,directory:string) { + async resizeImageToAVIF(buffer: Buffer, maxSize: number, imageName: string, directory: string) { let quality = 50; // AVIF kann mit niedrigeren Qualitätsstufen gute Ergebnisse erzielen let output; let start = Date.now(); - output = await sharp(buffer) - .resize({ width: 1500 }) - .avif({ quality }) // Verwende AVIF - //.webp({ quality }) // Verwende Webp - .toBuffer(); + output = await sharp(buffer) + .resize({ width: 1500 }) + .avif({ quality }) // Verwende AVIF + //.webp({ quality }) // Verwende Webp + .toBuffer(); await sharp(output).toFile(`${directory}/${imageName}.avif`); // Ersetze Dateierweiterung let timeTaken = Date.now() - start; - this.logger.info(`Quality: ${quality} - Time: ${timeTaken} milliseconds`) + this.logger.info(`Quality: ${quality} - Time: ${timeTaken} milliseconds`); } - getProfileImagesForUsers(userids:string){ + getProfileImagesForUsers(userids: string) { const ids = userids.split(','); let result = {}; - for (const id of ids){ - result = {...result,[id]:fs.existsSync(`./pictures/profile/${id}.avif`)} + for (const id of ids) { + result = { ...result, [id]: fs.existsSync(`./pictures/profile/${id}.avif`) }; } return result; } - getCompanyLogosForUsers(userids:string){ + getCompanyLogosForUsers(userids: string) { const ids = userids.split(','); let result = {}; - for (const id of ids){ - result = {...result,[id]:fs.existsSync(`./pictures/logo/${id}.avif`)} + for (const id of ids) { + result = { ...result, [id]: fs.existsSync(`./pictures/logo/${id}.avif`) }; } return result; } - deleteImage(path:string){ + deleteImage(path: string) { fs.unlinkSync(path); } + deleteDirectoryIfExists(imagePath) { + const dirPath = `pictures/property/${imagePath}`; + try { + const exists = fs.pathExistsSync(); + if (exists) { + fs.removeSync(dirPath); + console.log(`Directory ${dirPath} was deleted.`); + } else { + console.log(`Directory ${dirPath} does not exist.`); + } + } catch (error) { + console.error(`Error while deleting ${dirPath}:`, error); + } + } } diff --git a/bizmatch-server/src/listings/commercial-property-listings.controller.ts b/bizmatch-server/src/listings/commercial-property-listings.controller.ts index a1d4256..5641a8e 100644 --- a/bizmatch-server/src/listings/commercial-property-listings.controller.ts +++ b/bizmatch-server/src/listings/commercial-property-listings.controller.ts @@ -40,9 +40,10 @@ export class CommercialPropertyListingsController { this.logger.info(`Save Listing`); return await this.listingsService.updateListing(listing.id, listing, commercials); } - @Delete(':id') - deleteById(@Param('id') id: string) { + @Delete(':id/:imagePath') + deleteById(@Param('id') id: string, @Param('imagePath') imagePath: string) { this.listingsService.deleteListing(id, commercials); + this.fileService.deleteDirectoryIfExists(imagePath); } @Put('imageOrder/:id') diff --git a/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.html b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.html index 3194d89..258c348 100644 --- a/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.html +++ b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.html @@ -60,7 +60,7 @@
{{ listing.brokerLicencing }}
- @if(listing && listingUser && (listingUser.id===listing?.userId || isAdmin())){ + @if(listing && listingUser && (listingUser?.email===user?.email || isAdmin())){ } diff --git a/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html b/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html index 48e1c38..97ce16c 100644 --- a/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html +++ b/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html @@ -43,7 +43,7 @@ - @if(listing && listingUser && (listingUser.id===listing?.userId || isAdmin())){ + @if(listing && listingUser && (listingUser?.email===user?.email || isAdmin())){ } diff --git a/bizmatch/src/app/pages/details/details-user/details-user.component.html b/bizmatch/src/app/pages/details/details-user/details-user.component.html index f159e48..8081de7 100644 --- a/bizmatch/src/app/pages/details/details-user/details-user.component.html +++ b/bizmatch/src/app/pages/details/details-user/details-user.component.html @@ -138,7 +138,7 @@ - @if( user?.id===(user$| async)?.id || isAdmin()){ + @if( user?.email===(user$| async)?.email || isAdmin()){ } diff --git a/bizmatch/src/app/pages/details/details-user/details-user.component.ts b/bizmatch/src/app/pages/details/details-user/details-user.component.ts index 7f3d27e..4765fef 100644 --- a/bizmatch/src/app/pages/details/details-user/details-user.component.ts +++ b/bizmatch/src/app/pages/details/details-user/details-user.component.ts @@ -48,7 +48,7 @@ export class DetailsUserComponent { async ngOnInit() { this.user = await this.userService.getById(this.id); - + this.user.email; const results = await Promise.all([await this.listingsService.getListingByUserId(this.id, 'business'), await this.listingsService.getListingByUserId(this.id, 'commercialProperty')]); // Zuweisen der Ergebnisse zu den Member-Variablen der Klasse this.businessListings = results[0]; diff --git a/bizmatch/src/app/pages/subscription/my-listing/my-listing.component.ts b/bizmatch/src/app/pages/subscription/my-listing/my-listing.component.ts index 5b32c8b..8459067 100644 --- a/bizmatch/src/app/pages/subscription/my-listing/my-listing.component.ts +++ b/bizmatch/src/app/pages/subscription/my-listing/my-listing.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectorRef, Component } from '@angular/core'; import { ConfirmationService, MessageService } from 'primeng/api'; -import { User } from '../../../../../../bizmatch-server/src/models/db.model'; +import { CommercialPropertyListing, User } from '../../../../../../bizmatch-server/src/models/db.model'; import { ListingType } from '../../../../../../bizmatch-server/src/models/main.model'; import { ListingsService } from '../../../services/listings.service'; import { SelectOptionsService } from '../../../services/select-options.service'; @@ -36,7 +36,11 @@ export class MyListingComponent { } async deleteListing(listing: ListingType) { - await this.listingsService.deleteListing(listing.id, listing.listingsCategory); + if (listing.listingsCategory === 'business') { + await this.listingsService.deleteBusinessListing(listing.id); + } else { + await this.listingsService.deleteCommercialPropertyListing(listing.id, (listing).imagePath); + } const result = await Promise.all([await this.listingsService.getListingByUserId(this.user.id, 'business'), await this.listingsService.getListingByUserId(this.user.id, 'commercialProperty')]); this.myListings = [...result[0], ...result[1]]; } diff --git a/bizmatch/src/app/services/history.service.ts b/bizmatch/src/app/services/history.service.ts index 52c3b8d..297bc16 100644 --- a/bizmatch/src/app/services/history.service.ts +++ b/bizmatch/src/app/services/history.service.ts @@ -22,7 +22,7 @@ export class HistoryService { } get canGoBack(): boolean { - return !!this.previousUrl; + return !!this.previousUrl || window.history.length > 2; } goBack(): void { diff --git a/bizmatch/src/app/services/listings.service.ts b/bizmatch/src/app/services/listings.service.ts index 2dfdb14..85696ec 100644 --- a/bizmatch/src/app/services/listings.service.ts +++ b/bizmatch/src/app/services/listings.service.ts @@ -31,12 +31,16 @@ export class ListingsService { } } async getAllStates(listingsCategory?: 'business' | 'commercialProperty'): Promise { - const result = lastValueFrom(this.http.get(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/states/all`)); + const result = lastValueFrom(this.http.get(`${this.apiBaseUrl}/bizmatch/listings/business/states/all`)); return result; } - async deleteListing(id: string, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty') { - await lastValueFrom(this.http.delete(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`)); + async deleteBusinessListing(id: string) { + await lastValueFrom(this.http.delete(`${this.apiBaseUrl}/bizmatch/listings/business/${id}`)); } + async deleteCommercialPropertyListing(id: string, imagePath: string) { + await lastValueFrom(this.http.delete(`${this.apiBaseUrl}/bizmatch/listings/commercialProperty/${id}/${imagePath}`)); + } + async getPropertyImages(id: string): Promise { return await lastValueFrom(this.http.get(`${this.apiBaseUrl}/bizmatch/image/${id}`)); } diff --git a/bizmatch/src/build.ts b/bizmatch/src/build.ts index 354cebd..a06d4d1 100644 --- a/bizmatch/src/build.ts +++ b/bizmatch/src/build.ts @@ -1,6 +1,6 @@ // Build information, automatically generated by `the_build_script` :zwinkern: const build = { - timestamp: 'NA', + timestamp: "GER: 16.05.2024 22:55 | TX: 05/16/2024 3:55 PM" }; -export default build; +export default build; \ No newline at end of file diff --git a/bizmatch/src/styles.scss b/bizmatch/src/styles.scss index ace6ce8..a8040be 100644 --- a/bizmatch/src/styles.scss +++ b/bizmatch/src/styles.scss @@ -1,29 +1,29 @@ -@import "primeng/resources/primeng.css"; +@import 'primeng/resources/primeng.css'; @import 'primeicons/primeicons.css'; // @import 'primeflex/primeflex.scss'; -@import "primeflex/primeflex.css"; +@import 'primeflex/primeflex.css'; @import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap'); -@import "primeng/resources/themes/lara-light-blue/theme.css"; -@import "@fortawesome/fontawesome-free/css/all.min.css"; +@import 'primeng/resources/themes/lara-light-blue/theme.css'; +@import '@fortawesome/fontawesome-free/css/all.min.css'; :root { - --text-color-secondary:rgba(255, 255, 255); - --wrapper-width:1491px; - // --secondary-color: #ffffff; /* Setzt die secondary Farbe auf weiß */ + --text-color-secondary: rgba(255, 255, 255); + --wrapper-width: 1491px; + // --secondary-color: #ffffff; /* Setzt die secondary Farbe auf weiß */ } -.p-button.p-button-secondary.p-button-outlined{ - color: #ffffff;; +.p-button.p-button-secondary.p-button-outlined { + color: #ffffff; } html, body, app-root { - margin: 0; - height: 100%; + margin: 0; + height: 100%; } app-root { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } h1, @@ -32,47 +32,54 @@ h3, h4, h5, h6 { - margin: 0; + margin: 0; } -body, input, button, select, textarea { - // font-family: 'Open Sans', sans-serif; - font-family: var(--font-family); - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; +body, +input, +button, +select, +textarea { + // font-family: 'Open Sans', sans-serif; + font-family: var(--font-family); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } *:focus, .p-focus { - box-shadow: none !important; + box-shadow: none !important; } p-menubarsub ul { - gap: 4px; + gap: 4px; } ::-webkit-scrollbar { - width: 3px; + width: 3px; } ::-webkit-scrollbar-track { - background: transparent; + background: transparent; } ::-webkit-scrollbar-thumb { - background-color: rgba(155, 155, 155, 0.5); - border-radius: 20px; - border: transparent; + background-color: rgba(155, 155, 155, 0.5); + border-radius: 20px; + border: transparent; } .wrapper { - width: var(--wrapper-width); - max-width: 100%; - height: 100%; - margin: auto; + width: var(--wrapper-width); + max-width: 100%; + height: 100%; + margin: auto; +} +.p-editor-container .ql-toolbar { + background: #f9fafb; + border-top-right-radius: 6px; + border-top-left-radius: 6px; +} +.p-dropdown-panel .p-dropdown-header .p-dropdown-filter { + margin-right: 0 !important; } -.p-editor-container .ql-toolbar{ - background: #f9fafb; - border-top-right-radius: 6px; - border-top-left-radius: 6px; -} \ No newline at end of file diff --git a/bizmatch/version.js b/bizmatch/version.js index e29f63a..9fd9c49 100644 --- a/bizmatch/version.js +++ b/bizmatch/version.js @@ -3,9 +3,11 @@ const fs = require('fs'); const dayjs = require('dayjs'); const timezone = require('dayjs/plugin/timezone'); const utc = require('dayjs/plugin/utc'); +var localizedFormat = require('dayjs/plugin/localizedFormat'); dayjs.extend(utc); dayjs.extend(timezone); +dayjs.extend(localizedFormat); const write = (content, path) => { const writePath = path || `${process.cwd()}/src/build.ts`; @@ -23,7 +25,10 @@ const package = require(`${process.cwd()}/package.json`); console.log('start build.js script ...'); // Generate `build` object const build = {}; - build.timestamp = dayjs(new Date()).utc().format('DD.MM.YYYY HH:mm') + ' UTC'; + const acDate = new Date(); + const german = dayjs(acDate).tz('Europe/Berlin').format('DD.MM.YYYY HH:mm'); + const texan = dayjs(acDate).tz('America/Chicago').format('L LT'); + build.timestamp = `GER: ${german} | TX: ${texan}`; // Write Build information to file write(build); console.log('build.js script finished ...');