BugFix #87: neue Bild Gallery verwedet
This commit is contained in:
parent
f4f576d4a9
commit
c5577969c8
|
|
@ -42,6 +42,7 @@
|
||||||
"keycloak-angular": "^16.0.1",
|
"keycloak-angular": "^16.0.1",
|
||||||
"keycloak-js": "^25.0.1",
|
"keycloak-js": "^25.0.1",
|
||||||
"memoize-one": "^6.0.0",
|
"memoize-one": "^6.0.0",
|
||||||
|
"ng-gallery": "^11.0.0",
|
||||||
"ngx-currency": "^18.0.0",
|
"ngx-currency": "^18.0.0",
|
||||||
"ngx-image-cropper": "^8.0.0",
|
"ngx-image-cropper": "^8.0.0",
|
||||||
"ngx-mask": "^18.0.0",
|
"ngx-mask": "^18.0.0",
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { provideRouter, withEnabledBlockingInitialNavigation, withInMemoryScroll
|
||||||
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
||||||
import { provideAnimations } from '@angular/platform-browser/animations';
|
import { provideAnimations } from '@angular/platform-browser/animations';
|
||||||
import { KeycloakBearerInterceptor, KeycloakService } from 'keycloak-angular';
|
import { KeycloakBearerInterceptor, KeycloakService } from 'keycloak-angular';
|
||||||
|
import { GALLERY_CONFIG, GalleryConfig } from 'ng-gallery';
|
||||||
import { provideQuillConfig } from 'ngx-quill';
|
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';
|
||||||
|
|
@ -56,6 +57,13 @@ export const appConfig: ApplicationConfig = {
|
||||||
provide: 'TIMEOUT_DURATION',
|
provide: 'TIMEOUT_DURATION',
|
||||||
useValue: 5000, // Standard-Timeout von 5 Sekunden
|
useValue: 5000, // Standard-Timeout von 5 Sekunden
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: GALLERY_CONFIG,
|
||||||
|
useValue: {
|
||||||
|
autoHeight: true,
|
||||||
|
imageSize: 'cover',
|
||||||
|
} as GalleryConfig,
|
||||||
|
},
|
||||||
provideShareButtonsOptions(
|
provideShareButtonsOptions(
|
||||||
shareIcons(),
|
shareIcons(),
|
||||||
withConfig({
|
withConfig({
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,8 @@
|
||||||
|
|
||||||
<!-- Right column -->
|
<!-- Right column -->
|
||||||
<div class="w-full lg:w-1/2 mt-6 lg:mt-0 print:hidden">
|
<div class="w-full lg:w-1/2 mt-6 lg:mt-0 print:hidden">
|
||||||
<h3 class="text-lg font-semibold mb-4">Contact the Author of this Listing</h3>
|
<!-- <h2 class="text-lg font-semibold my-4">Contact the Author of this Listing</h2> -->
|
||||||
|
<div class="md:mt-8 mb-4 text-2xl font-bold mb-4">Contact the Author of this Listing</div>
|
||||||
<p class="text-sm mb-4">Please include your contact info below</p>
|
<p class="text-sm mb-4">Please include your contact info below</p>
|
||||||
<form class="space-y-4">
|
<form class="space-y-4">
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
|
|
||||||
|
|
@ -9,31 +9,6 @@
|
||||||
>
|
>
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-times"></i>
|
||||||
</button>
|
</button>
|
||||||
<div class="lg:hidden">
|
|
||||||
@if (listing && listing.imageOrder && listing.imageOrder.length > 0) {
|
|
||||||
<div id="gallery" class="relative w-full" data-carousel="slide">
|
|
||||||
<div class="relative h-56 overflow-hidden rounded-lg md:h-96">
|
|
||||||
@for (image of listing.imageOrder; track $index) {
|
|
||||||
<div class="hidden duration-700 ease-in-out" data-carousel-item>
|
|
||||||
<img src="{{ env.imageBaseUrl }}/pictures/property/{{ listing.imagePath }}/{{ listing.serialId }}/{{ image }}" class="absolute block max-w-full h-auto -translate-x-1/2 -translate-y-1/2 top-1/2 left-1/2" />
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div class="absolute z-30 flex space-x-3 -translate-x-1/2 bottom-5 left-1/2">
|
|
||||||
<button type="button" class="w-3 h-3 rounded-full bg-white dark:bg-gray-800" aria-current="true" aria-label="Slide 1" data-carousel-slide-to="0"></button>
|
|
||||||
@for (i of getImageIndices(); track i) {
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="w-3 h-3 rounded-full bg-white/50 dark:bg-gray-800/50 hover:bg-white dark:hover:bg-gray-800"
|
|
||||||
aria-current="false"
|
|
||||||
attr.aria-label="Slide {{ i }}"
|
|
||||||
attr.data-carousel-slide-to="{{ i }}"
|
|
||||||
></button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col lg:flex-row">
|
<div class="flex flex-col lg:flex-row">
|
||||||
<div class="w-full lg:w-1/2 pr-0 lg:pr-4">
|
<div class="w-full lg:w-1/2 pr-0 lg:pr-4">
|
||||||
<p class="mb-4" [innerHTML]="description"></p>
|
<p class="mb-4" [innerHTML]="description"></p>
|
||||||
|
|
@ -77,42 +52,20 @@
|
||||||
<share-button button="x" showText="true"></share-button>
|
<share-button button="x" showText="true"></share-button>
|
||||||
<share-button button="linkedin" showText="true"></share-button>
|
<share-button button="linkedin" showText="true"></share-button>
|
||||||
</div>
|
</div>
|
||||||
<!-- @if(listing && listingUser && (listingUser?.email===user?.email || isAdmin())){
|
|
||||||
<button class="mt-4 bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600" [routerLink]="['/editCommercialPropertyListing', listing.id]">Edit</button>
|
|
||||||
} -->
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full lg:w-1/2 mt-6 lg:mt-0">
|
<div class="w-full lg:w-1/2 mt-6 lg:mt-0">
|
||||||
<div class="hidden lg:block">
|
@if(this.images.length>0){
|
||||||
@if (listing && listing.imageOrder && listing.imageOrder.length > 0) {
|
<div class="block print:hidden">
|
||||||
<div id="gallery" class="relative w-full" data-carousel="slide">
|
<gallery [items]="images"></gallery>
|
||||||
<div class="relative h-56 overflow-hidden rounded-lg md:h-96">
|
|
||||||
@for (image of listing.imageOrder; track $index) {
|
|
||||||
<div class="hidden duration-700 ease-in-out" data-carousel-item>
|
|
||||||
<img
|
|
||||||
src="{{ env.imageBaseUrl }}/pictures/property/{{ listing.imagePath }}/{{ listing.serialId }}/{{ image }}"
|
|
||||||
class="absolute block max-w-full h-auto -translate-x-1/2 -translate-y-1/2 top-1/2 left-1/2"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
<div class="print:hidden" [ngClass]="{ 'mt-6': this.images.length > 0 }">
|
||||||
<div class="absolute z-30 flex space-x-3 -translate-x-1/2 bottom-5 left-1/2">
|
@if(this.images.length>0){
|
||||||
<button type="button" class="w-3 h-3 rounded-full bg-white dark:bg-gray-800" aria-current="true" aria-label="Slide 1" data-carousel-slide-to="0"></button>
|
<h2 class="text-xl font-semibold">Contact the Author of this Listing</h2>
|
||||||
@for (i of getImageIndices(); track i) {
|
}@else {
|
||||||
<button
|
<div class="md:mt-[-60px] text-2xl font-bold mb-4">Contact the Author of this Listing</div>
|
||||||
type="button"
|
|
||||||
class="w-3 h-3 rounded-full bg-white/50 dark:bg-gray-800/50 hover:bg-white dark:hover:bg-gray-800"
|
|
||||||
aria-current="false"
|
|
||||||
attr.aria-label="Slide {{ i }}"
|
|
||||||
attr.data-carousel-slide-to="{{ i }}"
|
|
||||||
></button>
|
|
||||||
}
|
}
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div class="mt-6 print:hidden">
|
|
||||||
<h2 class="text-xl font-semibold mb-4">Contact the Author of this Listing</h2>
|
|
||||||
<p class="text-sm text-gray-600 mb-4">Please include your contact info below</p>
|
<p class="text-sm text-gray-600 mb-4">Please include your contact info below</p>
|
||||||
<form class="space-y-4">
|
<form class="space-y-4">
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { faTimes } from '@fortawesome/free-solid-svg-icons';
|
import { faTimes } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { KeycloakService } from 'keycloak-angular';
|
import { KeycloakService } from 'keycloak-angular';
|
||||||
|
import { GalleryModule, ImageItem } from 'ng-gallery';
|
||||||
import { ShareButton } from 'ngx-sharebuttons/button';
|
import { ShareButton } from 'ngx-sharebuttons/button';
|
||||||
import { lastValueFrom } from 'rxjs';
|
import { lastValueFrom } from 'rxjs';
|
||||||
import { CommercialPropertyListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
import { CommercialPropertyListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||||
|
|
@ -27,7 +28,7 @@ import { createMailInfo, map2User } from '../../../utils/utils';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-details-commercial-property-listing',
|
selector: 'app-details-commercial-property-listing',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [SharedModule, ValidatedInputComponent, ValidatedTextareaComponent, ShareButton, ValidatedNgSelectComponent],
|
imports: [SharedModule, ValidatedInputComponent, ValidatedTextareaComponent, ShareButton, ValidatedNgSelectComponent, GalleryModule],
|
||||||
providers: [],
|
providers: [],
|
||||||
templateUrl: './details-commercial-property-listing.component.html',
|
templateUrl: './details-commercial-property-listing.component.html',
|
||||||
styleUrl: '../details.scss',
|
styleUrl: '../details.scss',
|
||||||
|
|
@ -64,7 +65,7 @@ export class DetailsCommercialPropertyListingComponent {
|
||||||
errorResponse: ErrorResponse;
|
errorResponse: ErrorResponse;
|
||||||
faTimes = faTimes;
|
faTimes = faTimes;
|
||||||
propertyDetails = [];
|
propertyDetails = [];
|
||||||
|
images: Array<ImageItem> = [];
|
||||||
constructor(
|
constructor(
|
||||||
private activatedRoute: ActivatedRoute,
|
private activatedRoute: ActivatedRoute,
|
||||||
private listingsService: ListingsService,
|
private listingsService: ListingsService,
|
||||||
|
|
@ -110,6 +111,10 @@ export class DetailsCommercialPropertyListingComponent {
|
||||||
if (this.listing.draft) {
|
if (this.listing.draft) {
|
||||||
this.propertyDetails.push({ label: 'Draft', value: this.listing.draft ? 'Yes' : 'No' });
|
this.propertyDetails.push({ label: 'Draft', value: this.listing.draft ? 'Yes' : 'No' });
|
||||||
}
|
}
|
||||||
|
this.listing.imageOrder.forEach(image => {
|
||||||
|
const imageURL = `${this.env.imageBaseUrl}/pictures/property/${this.listing.imagePath}/${this.listing.serialId}/${image}`;
|
||||||
|
this.images.push(new ImageItem({ src: imageURL, thumb: imageURL }));
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logService.log({ severity: 'error', text: error.error.message });
|
this.logService.log({ severity: 'error', text: error.error.message });
|
||||||
this.router.navigate(['notfound']);
|
this.router.navigate(['notfound']);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue