@rolatech/angular-property 20.0.2-beta.2 → 20.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/rolatech-angular-property-property-filter-icon.component-_P3G8E-x.mjs +126 -0
- package/fesm2022/rolatech-angular-property-property-filter-icon.component-_P3G8E-x.mjs.map +1 -0
- package/fesm2022/rolatech-angular-property-property-index.component-CbbxIQ8w.mjs +92 -0
- package/fesm2022/rolatech-angular-property-property-index.component-CbbxIQ8w.mjs.map +1 -0
- package/fesm2022/{rolatech-angular-property-property-manage-viewings-index.component-gVG8HPPp.mjs → rolatech-angular-property-property-manage-viewings-index.component-Bk02i8QS.mjs} +2 -2
- package/fesm2022/{rolatech-angular-property-property-manage-viewings-index.component-gVG8HPPp.mjs.map → rolatech-angular-property-property-manage-viewings-index.component-Bk02i8QS.mjs.map} +1 -1
- package/fesm2022/{rolatech-angular-property-rolatech-angular-property-B4w7sAFv.mjs → rolatech-angular-property-rolatech-angular-property-nGHNbG8j.mjs} +580 -168
- package/fesm2022/rolatech-angular-property-rolatech-angular-property-nGHNbG8j.mjs.map +1 -0
- package/fesm2022/rolatech-angular-property.mjs +1 -1
- package/index.d.ts +25 -17
- package/package.json +5 -5
- package/themes/_default.scss +1 -1
- package/fesm2022/rolatech-angular-property-property-filter-icon.component-CO2B-Na5.mjs +0 -93
- package/fesm2022/rolatech-angular-property-property-filter-icon.component-CO2B-Na5.mjs.map +0 -1
- package/fesm2022/rolatech-angular-property-property-index.component-Birv1xyB.mjs +0 -43
- package/fesm2022/rolatech-angular-property-property-index.component-Birv1xyB.mjs.map +0 -1
- package/fesm2022/rolatech-angular-property-rolatech-angular-property-B4w7sAFv.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, ElementRef, input, booleanAttribute, effect, HostBinding, ViewEncapsulation, Component, viewChild, PLATFORM_ID, output, computed,
|
|
2
|
+
import { inject, ElementRef, input, booleanAttribute, effect, HostBinding, ViewEncapsulation, Component, viewChild, PLATFORM_ID, output, computed, EventEmitter, Injectable, signal, Pipe, model, ViewChild } from '@angular/core';
|
|
3
3
|
import * as i1$4 from '@angular/material/button';
|
|
4
4
|
import { MatButtonModule } from '@angular/material/button';
|
|
5
5
|
import * as i4 from '@angular/material/menu';
|
|
@@ -10,11 +10,11 @@ import { MatSnackBar } from '@angular/material/snack-bar';
|
|
|
10
10
|
import { MatTableModule } from '@angular/material/table';
|
|
11
11
|
import * as i1$1 from '@angular/router';
|
|
12
12
|
import { RouterLink, RouterModule, Router, ActivatedRoute, RouterLinkActive, RouterOutlet } from '@angular/router';
|
|
13
|
-
import { ThumbnailComponent, ImagePlaceholderComponent, ToolbarComponent, SpinnerComponent, ImagePreviewDialogComponent, BaseComponent, AcceptDialogComponent, RejectDialogComponent, RichLabelComponent, AngularComponentsModule, ConfirmationDialogComponent, TabsComponent, TabComponent, EmptyComponent, ContainerComponent, ListComponent, MediaListComponent, MediaListItemComponent,
|
|
14
|
-
import { PropertyService, FeatureService } from '@rolatech/angular-services';
|
|
13
|
+
import { ThumbnailComponent, ImagePlaceholderComponent, ToolbarComponent, SpinnerComponent, ImagePreviewDialogComponent, BaseComponent, AcceptDialogComponent, RejectDialogComponent, RichLabelComponent, AngularComponentsModule, ConfirmationDialogComponent, TabsComponent, TabComponent, EmptyComponent, ContainerComponent, SearchBar, ListComponent, MediaListComponent, MediaListItemComponent, InputComponent } from '@rolatech/angular-components';
|
|
14
|
+
import { PropertyService, FeatureService, PropertySearchService, DialogService } from '@rolatech/angular-services';
|
|
15
15
|
import * as i1 from '@angular/common';
|
|
16
16
|
import { CommonModule, NgClass, isPlatformBrowser, ViewportScroller, KeyValuePipe, Location } from '@angular/common';
|
|
17
|
-
import { FixedPipe, AngularCommonModule, OptionsFormatPipe, APP_CONFIG, DecimalDirective } from '@rolatech/angular-common';
|
|
17
|
+
import { FixedPipe, AngularCommonModule, OptionsFormatPipe, APP_CONFIG, DecimalDirective, DurationPipe } from '@rolatech/angular-common';
|
|
18
18
|
import * as i2 from '@angular/material/icon';
|
|
19
19
|
import { MatIconModule, MatIcon } from '@angular/material/icon';
|
|
20
20
|
import { MatDialog } from '@angular/material/dialog';
|
|
@@ -38,9 +38,6 @@ import { MatOptionModule, MAT_DATE_LOCALE, DateAdapter, MAT_DATE_FORMATS } from
|
|
|
38
38
|
import _, { findIndex, findLastIndex, first, remove } from 'lodash';
|
|
39
39
|
import * as i2$1 from '@angular/material/divider';
|
|
40
40
|
import { MatDividerModule, MatDivider } from '@angular/material/divider';
|
|
41
|
-
import * as i7 from '@angular/material/datepicker';
|
|
42
|
-
import { MatDatepickerModule } from '@angular/material/datepicker';
|
|
43
|
-
import { trigger, state, transition, style, animate } from '@angular/animations';
|
|
44
41
|
import { CommentsComponent } from '@rolatech/angular-comment';
|
|
45
42
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
46
43
|
import * as i4$1 from '@angular/cdk/text-field';
|
|
@@ -48,8 +45,11 @@ import { TextFieldModule } from '@angular/cdk/text-field';
|
|
|
48
45
|
import * as i7$1 from '@angular/material/radio';
|
|
49
46
|
import { MatRadioModule } from '@angular/material/radio';
|
|
50
47
|
import { MomentDateAdapter } from '@angular/material-moment-adapter';
|
|
48
|
+
import * as i7 from '@angular/material/datepicker';
|
|
49
|
+
import { MatDatepickerModule } from '@angular/material/datepicker';
|
|
51
50
|
import * as i3$1 from '@angular/material/progress-spinner';
|
|
52
51
|
import { MatProgressSpinner, MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
52
|
+
import { trigger, state, transition, style, animate } from '@angular/animations';
|
|
53
53
|
import * as i8 from '@angular/material/progress-bar';
|
|
54
54
|
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
55
55
|
import * as i1$6 from '@angular/material/checkbox';
|
|
@@ -61,13 +61,13 @@ var PropertyPriceType;
|
|
|
61
61
|
PropertyPriceType["PARTIAL"] = "\u652F\u4ED8\u5B9A\u91D1";
|
|
62
62
|
PropertyPriceType["VARIED"] = "\u591A\u53D8\u7684";
|
|
63
63
|
})(PropertyPriceType || (PropertyPriceType = {}));
|
|
64
|
-
var
|
|
65
|
-
(function (
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
})(
|
|
64
|
+
var PropertyVideoProvider;
|
|
65
|
+
(function (PropertyVideoProvider) {
|
|
66
|
+
PropertyVideoProvider["YOUTUBE"] = "YOUTUBE";
|
|
67
|
+
PropertyVideoProvider["S3"] = "AWS S3";
|
|
68
|
+
PropertyVideoProvider["LOCAL"] = "Local server";
|
|
69
|
+
PropertyVideoProvider["COS"] = "COS";
|
|
70
|
+
})(PropertyVideoProvider || (PropertyVideoProvider = {}));
|
|
71
71
|
var PropertyStatus;
|
|
72
72
|
(function (PropertyStatus) {
|
|
73
73
|
PropertyStatus[PropertyStatus["DRAFT"] = 'Draft'] = "DRAFT";
|
|
@@ -1067,83 +1067,78 @@ const propertyManageOffersRoutes = [
|
|
|
1067
1067
|
},
|
|
1068
1068
|
];
|
|
1069
1069
|
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
};
|
|
1080
|
-
reset() { }
|
|
1081
|
-
search() { }
|
|
1082
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1083
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyFilterComponent, isStandalone: true, selector: "rolatech-property-filter", inputs: { filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filter: "filterChange" }, ngImport: i0, template: "<!-- <div class=\"p-3\">\n <div class=\"bg-white p-3 flex items-center justify-between rounded-md\">\n <div class=\"flex items-center\">\n <mat-form-field subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Town\" i18n-placeholder [(ngModel)]=\"searchOptions.town\">\n @for (Town of towns; track Town) {\n <mat-option [value]=\"Town\">\n {{ Town }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"flex gap-3\">\n <a mat-stroked-button class=\"w-[128px]\" (click)=\"reset()\" i18n>Reset</a>\n <ng-container *ngComponentOutlet=\"propertyFilterIconComponent | async\"></ng-container>\n <a mat-flat-button class=\"w-full\" (click)=\"search()\" i18n>Search</a>\n </div>\n </div>\n</div> -->\n<div\n [ngClass]=\"filter() ? 'transition-height duration-500 ease-in-out' : 'md:h-14 h-0 transition-height duration-500 ease-in-out'\"\n>\n <div\n class=\"min-w-[256px] md:min-w-[320px] h-full m-3 flex flex-row md:flex-col md:h-full items-center md:items-start shadow-inner shadow-light-400 md:shadow-none overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <div class=\"w-full h-full\">\n <div class=\"flex flex-col md:flex-row h-in justify-center items-center gap-3\">\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Town\" [(ngModel)]=\"searchOptions.city\">\n @for (town of towns; track town) {\n <mat-option [value]=\"town\">\n {{ town }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <input\n matInput\n placeholder=\"Available\"\n [matDatepicker]=\"startDatePicker\"\n [min]=\"minDate\"\n (focus)=\"startDatePicker.open()\"\n name=\"available\"\n [(ngModel)]=\"searchOptions.available\"\n (dateInput)=\"searchOptions.available = $event.value.format('YYYY-MM-DD')\"\n readonly\n />\n <mat-datepicker-toggle matIconPrefix [for]=\"startDatePicker\"></mat-datepicker-toggle>\n <mat-datepicker #startDatePicker></mat-datepicker>\n </mat-form-field>\n <div class=\"flex w-full gap-3\">\n <a mat-stroked-button class=\"w-[128px]\" (click)=\"reset()\">Reset</a>\n <ng-container *ngComponentOutlet=\"propertyFilterIconComponent | async\"></ng-container>\n <a mat-flat-button class=\"w-full\" (click)=\"search()\">Search</a>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i7.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i7.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i7.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], animations: [
|
|
1084
|
-
trigger('filter', [
|
|
1085
|
-
state('collapsed', style({ height: '0px', minHeight: '0' })),
|
|
1086
|
-
state('expanded', style({ height: '*' })),
|
|
1087
|
-
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
|
|
1088
|
-
]),
|
|
1089
|
-
] });
|
|
1070
|
+
var PropertyViewType;
|
|
1071
|
+
(function (PropertyViewType) {
|
|
1072
|
+
PropertyViewType[PropertyViewType["GRID"] = 0] = "GRID";
|
|
1073
|
+
PropertyViewType[PropertyViewType["LIST"] = 1] = "LIST";
|
|
1074
|
+
})(PropertyViewType || (PropertyViewType = {}));
|
|
1075
|
+
class PropertyUtil {
|
|
1076
|
+
viewEvent = new EventEmitter();
|
|
1077
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyUtil, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1078
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyUtil, providedIn: 'root' });
|
|
1090
1079
|
}
|
|
1091
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type:
|
|
1092
|
-
type:
|
|
1093
|
-
args: [{
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
MatFormFieldModule,
|
|
1097
|
-
MatInputModule,
|
|
1098
|
-
MatSelectModule,
|
|
1099
|
-
MatOptionModule,
|
|
1100
|
-
FormsModule,
|
|
1101
|
-
MatDatepickerModule,
|
|
1102
|
-
], animations: [
|
|
1103
|
-
trigger('filter', [
|
|
1104
|
-
state('collapsed', style({ height: '0px', minHeight: '0' })),
|
|
1105
|
-
state('expanded', style({ height: '*' })),
|
|
1106
|
-
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
|
|
1107
|
-
]),
|
|
1108
|
-
], template: "<!-- <div class=\"p-3\">\n <div class=\"bg-white p-3 flex items-center justify-between rounded-md\">\n <div class=\"flex items-center\">\n <mat-form-field subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Town\" i18n-placeholder [(ngModel)]=\"searchOptions.town\">\n @for (Town of towns; track Town) {\n <mat-option [value]=\"Town\">\n {{ Town }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"flex gap-3\">\n <a mat-stroked-button class=\"w-[128px]\" (click)=\"reset()\" i18n>Reset</a>\n <ng-container *ngComponentOutlet=\"propertyFilterIconComponent | async\"></ng-container>\n <a mat-flat-button class=\"w-full\" (click)=\"search()\" i18n>Search</a>\n </div>\n </div>\n</div> -->\n<div\n [ngClass]=\"filter() ? 'transition-height duration-500 ease-in-out' : 'md:h-14 h-0 transition-height duration-500 ease-in-out'\"\n>\n <div\n class=\"min-w-[256px] md:min-w-[320px] h-full m-3 flex flex-row md:flex-col md:h-full items-center md:items-start shadow-inner shadow-light-400 md:shadow-none overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <div class=\"w-full h-full\">\n <div class=\"flex flex-col md:flex-row h-in justify-center items-center gap-3\">\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Town\" [(ngModel)]=\"searchOptions.city\">\n @for (town of towns; track town) {\n <mat-option [value]=\"town\">\n {{ town }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <input\n matInput\n placeholder=\"Available\"\n [matDatepicker]=\"startDatePicker\"\n [min]=\"minDate\"\n (focus)=\"startDatePicker.open()\"\n name=\"available\"\n [(ngModel)]=\"searchOptions.available\"\n (dateInput)=\"searchOptions.available = $event.value.format('YYYY-MM-DD')\"\n readonly\n />\n <mat-datepicker-toggle matIconPrefix [for]=\"startDatePicker\"></mat-datepicker-toggle>\n <mat-datepicker #startDatePicker></mat-datepicker>\n </mat-form-field>\n <div class=\"flex w-full gap-3\">\n <a mat-stroked-button class=\"w-[128px]\" (click)=\"reset()\">Reset</a>\n <ng-container *ngComponentOutlet=\"propertyFilterIconComponent | async\"></ng-container>\n <a mat-flat-button class=\"w-full\" (click)=\"search()\">Search</a>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: ["mat-form-field{width:100%}\n"] }]
|
|
1080
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyUtil, decorators: [{
|
|
1081
|
+
type: Injectable,
|
|
1082
|
+
args: [{
|
|
1083
|
+
providedIn: 'root',
|
|
1084
|
+
}]
|
|
1109
1085
|
}] });
|
|
1110
1086
|
|
|
1111
1087
|
class PropertyLayoutComponent extends BaseComponent {
|
|
1112
1088
|
propertyService = inject(PropertyService);
|
|
1089
|
+
util = inject(PropertyUtil);
|
|
1090
|
+
open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
|
|
1091
|
+
model = {};
|
|
1092
|
+
gridView = true;
|
|
1093
|
+
searchBar = viewChild('searchBar', ...(ngDevMode ? [{ debugName: "searchBar" }] : []));
|
|
1113
1094
|
selectIndex = 0;
|
|
1114
1095
|
filter = false;
|
|
1096
|
+
propertyFilterIconComponent = defer(() => import('./rolatech-angular-property-property-filter-icon.component-_P3G8E-x.mjs').then((m) => m.PropertyFilterIconComponent));
|
|
1115
1097
|
ngOnInit() {
|
|
1116
|
-
this.findCategories();
|
|
1117
|
-
}
|
|
1118
|
-
findCategories() {
|
|
1119
|
-
// this.categoryService.find({}, false).subscribe({
|
|
1120
|
-
// next: (res: any) => {
|
|
1121
|
-
// this.categories = res.data;
|
|
1122
|
-
// },
|
|
1123
|
-
// });
|
|
1124
|
-
}
|
|
1125
|
-
loadPropertyByCategoryIndex(index) {
|
|
1126
|
-
// this.selectIndex = index;
|
|
1127
|
-
// const id = this.categories[index].id;
|
|
1128
|
-
// if (index === 0) {
|
|
1129
|
-
// this.router.navigate([`./`]);
|
|
1130
|
-
// // this.propertyService.find({}).subscribe({
|
|
1131
|
-
// // next: res => {
|
|
1132
|
-
// // }
|
|
1133
|
-
// // })
|
|
1134
|
-
// } else {
|
|
1135
|
-
// this.router.navigate([`../categories/${id}`], {
|
|
1136
|
-
// relativeTo: this.route,
|
|
1137
|
-
// });
|
|
1138
|
-
// }
|
|
1139
1098
|
}
|
|
1140
|
-
|
|
1099
|
+
toggleSearch() {
|
|
1100
|
+
this.open.update(v => !v);
|
|
1101
|
+
}
|
|
1102
|
+
onCloseSearch() {
|
|
1103
|
+
// this.open.set(false);
|
|
1104
|
+
// this.router.navigate([], { queryParams: {}, queryParamsHandling: 'merge' });
|
|
1105
|
+
this.router.navigate(["/properties"]);
|
|
1106
|
+
}
|
|
1107
|
+
toggleView() {
|
|
1108
|
+
if (this.gridView) {
|
|
1109
|
+
this.gridView = false;
|
|
1110
|
+
this.util.viewEvent.emit(PropertyViewType.LIST);
|
|
1111
|
+
}
|
|
1112
|
+
else {
|
|
1113
|
+
this.gridView = true;
|
|
1114
|
+
this.util.viewEvent.emit(PropertyViewType.GRID);
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
onSearch(event) {
|
|
1118
|
+
const qp = Object.fromEntries(Object.entries(event).filter(([_, v]) => v !== undefined && v !== null && !(Array.isArray(v) && v.length === 0) && v !== ''));
|
|
1119
|
+
this.router.navigate([], {
|
|
1120
|
+
queryParams: qp,
|
|
1121
|
+
queryParamsHandling: 'merge', // keep other params like sort, etc.
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
searchByText(event) {
|
|
1125
|
+
this.router.navigate([], {
|
|
1126
|
+
queryParams: { q: event, page: 1, limit: 15 },
|
|
1127
|
+
queryParamsHandling: 'merge', // keep other params like sort, etc.
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
onReset(event) {
|
|
1131
|
+
this.router.navigate([], {
|
|
1132
|
+
queryParams: {}, // empty
|
|
1133
|
+
// omit queryParamsHandling so it REPLACES (not merges) → clears everything
|
|
1134
|
+
});
|
|
1135
|
+
}
|
|
1141
1136
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyLayoutComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1142
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
1137
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.2.0", type: PropertyLayoutComponent, isStandalone: true, selector: "rolatech-property-layout", viewQueries: [{ propertyName: "searchBar", first: true, predicate: ["searchBar"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <div class=\"flex flex-col min-w-[320px] max-w-[1280px] m-auto\">\n <div class=\"flex justify-between items-center h-16\">\n <div class=\"flex justify-between items-center w-full\">\n <div class=\"p-3 text-2xl font-medium\" i18n>Properties</div>\n <div class=\"flex flex-row\">\n <button mat-icon-button (click)=\"toggleSearch()\">\n <mat-icon>search</mat-icon>\n </button>\n <button mat-icon-button (click)=\"toggleView()\">\n <mat-icon>{{ gridView ? 'view_list' : 'grid_on' }}</mat-icon>\n </button>\n <ng-container *ngComponentOutlet=\"propertyFilterIconComponent | async\"></ng-container>\n </div>\n </div>\n </div>\n <rolatech-search-bar\n [(show)]=\"open\"\n #searchBar\n (search)=\"searchByText($event)\"\n (close)=\"onCloseSearch()\"\n ></rolatech-search-bar>\n <div class=\"w-full\">\n <router-outlet></router-outlet>\n </div>\n </div>\n</rolatech-container>\n", styles: [".property-layout-active{border-radius:var(--rt-rounded-base, 8px);background-color:var(-rt-base-background, #fff);color:var(--rt-brand-color, #000)}@media (max-width: 768px){.property-layout-active{background-color:var(--rt-text-primary, #000);color:var(--rt-text-primary-inverse, #000)}}.scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: i1$1.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: i1$4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: SearchBar, selector: "rolatech-search-bar", inputs: ["show"], outputs: ["showChange", "search", "close"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }] });
|
|
1143
1138
|
}
|
|
1144
1139
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyLayoutComponent, decorators: [{
|
|
1145
1140
|
type: Component,
|
|
1146
|
-
args: [{ selector: 'rolatech-property-layout', imports: [AngularCommonModule, AngularComponentsModule, ContainerComponent,
|
|
1141
|
+
args: [{ selector: 'rolatech-property-layout', imports: [AngularCommonModule, AngularComponentsModule, ContainerComponent, SearchBar], template: "<rolatech-container>\n <div class=\"flex flex-col min-w-[320px] max-w-[1280px] m-auto\">\n <div class=\"flex justify-between items-center h-16\">\n <div class=\"flex justify-between items-center w-full\">\n <div class=\"p-3 text-2xl font-medium\" i18n>Properties</div>\n <div class=\"flex flex-row\">\n <button mat-icon-button (click)=\"toggleSearch()\">\n <mat-icon>search</mat-icon>\n </button>\n <button mat-icon-button (click)=\"toggleView()\">\n <mat-icon>{{ gridView ? 'view_list' : 'grid_on' }}</mat-icon>\n </button>\n <ng-container *ngComponentOutlet=\"propertyFilterIconComponent | async\"></ng-container>\n </div>\n </div>\n </div>\n <rolatech-search-bar\n [(show)]=\"open\"\n #searchBar\n (search)=\"searchByText($event)\"\n (close)=\"onCloseSearch()\"\n ></rolatech-search-bar>\n <div class=\"w-full\">\n <router-outlet></router-outlet>\n </div>\n </div>\n</rolatech-container>\n", styles: [".property-layout-active{border-radius:var(--rt-rounded-base, 8px);background-color:var(-rt-base-background, #fff);color:var(--rt-brand-color, #000)}@media (max-width: 768px){.property-layout-active{background-color:var(--rt-text-primary, #000);color:var(--rt-text-primary-inverse, #000)}}.scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"] }]
|
|
1147
1142
|
}] });
|
|
1148
1143
|
|
|
1149
1144
|
class PropertyActionsComponent {
|
|
@@ -1240,22 +1235,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImpor
|
|
|
1240
1235
|
args: [{ selector: 'rolatech-property-section', imports: [CommonModule, ThumbnailComponent], encapsulation: ViewEncapsulation.None, template: "@if (section(); as section) {\n <div>\n @if (section.title) {\n <div class=\"py-3 flex items-center gap-3\">\n <span class=\"h-4 w-1 bg-[--rt-brand-color] inline-block\"></span>\n <span class=\"text-lg font-medium py-1\"> {{ section.title }}</span>\n </div>\n }\n @if (section.description) {\n <div>\n {{ section.description }}\n </div>\n }\n @if (section.media) {\n <div class=\"w-80%\">\n @for (item of section.media; track item) {\n <div class=\"py-3\">\n <rolatech-thumbnail\n [src]=\"item.url\"\n size=\"small\"\n mode=\"full\"\n [width]=\"item.width\"\n [height]=\"item.height\"\n ></rolatech-thumbnail>\n </div>\n }\n </div>\n }\n </div>\n}\n" }]
|
|
1241
1236
|
}] });
|
|
1242
1237
|
|
|
1243
|
-
class
|
|
1238
|
+
class PropertyVideoComponent {
|
|
1244
1239
|
sanitizer = inject(DomSanitizer);
|
|
1245
|
-
|
|
1240
|
+
video = input.required(...(ngDevMode ? [{ debugName: "video" }] : []));
|
|
1246
1241
|
videoUrl = computed(() => {
|
|
1247
|
-
const match = this.
|
|
1242
|
+
const match = this.video().url.match(/(?:youtu\.be\/|youtube\.com\/watch\?v=)([\w-]+)/);
|
|
1248
1243
|
if (match && match[1]) {
|
|
1249
1244
|
return this.sanitizer.bypassSecurityTrustResourceUrl(`https://www.youtube.com/embed/${match[1]}`);
|
|
1250
1245
|
}
|
|
1251
1246
|
return null; // Not a valid YouTube URL
|
|
1252
1247
|
}, ...(ngDevMode ? [{ debugName: "videoUrl" }] : []));
|
|
1253
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type:
|
|
1254
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.2.0", type:
|
|
1248
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyVideoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1249
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.2.0", type: PropertyVideoComponent, isStandalone: true, selector: "rolatech-property-video", inputs: { video: { classPropertyName: "video", publicName: "video", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"\">\n <div class=\"text-2xl font-bold py-4\" i18n>Videos</div>\n <iframe [src]=\"videoUrl()\" frameborder=\"0\" allowfullscreen class=\"w-full aspect-video\"></iframe>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
1255
1250
|
}
|
|
1256
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type:
|
|
1251
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyVideoComponent, decorators: [{
|
|
1257
1252
|
type: Component,
|
|
1258
|
-
args: [{ selector: 'rolatech-property-video
|
|
1253
|
+
args: [{ selector: 'rolatech-property-video', imports: [CommonModule], template: "<div class=\"\">\n <div class=\"text-2xl font-bold py-4\" i18n>Videos</div>\n <iframe [src]=\"videoUrl()\" frameborder=\"0\" allowfullscreen class=\"w-full aspect-video\"></iframe>\n</div>\n" }]
|
|
1259
1254
|
}] });
|
|
1260
1255
|
|
|
1261
1256
|
class PropertyActionContactComponent {
|
|
@@ -1289,6 +1284,153 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImpor
|
|
|
1289
1284
|
args: [{ selector: 'rolatech-property-agent-renderer', imports: [AngularCommonModule, MatIconModule], template: "<div class=\"flex flex-col\">\n <div class=\"flex flex-row items-center py-3\">\n <div class=\"flex mr-3 gap-2 items-center\">\n @if (avatar()) {\n <div class=\"cursor-pointer\" [routerLink]=\"['/', '@' + username()]\">\n <img [src]=\"avatar()\" class=\"w-14 h-14 rounded-full\" alt />\n </div>\n } @else {\n <div class=\"w-14 h-14 rounded-full bg-[--rt-brand-color]\"></div>\n }\n <div class=\"flex flex-col\">\n <div class=\"flex items-center text-lg font-bold cursor-pointer\">\n <a [routerLink]=\"['/', '@' + username()]\">\n <span>{{ name() }}</span>\n </a>\n <mat-icon class=\"verified-icon\">verified</mat-icon>\n </div>\n <div class=\"text-lg font-bold text-[--rt-brand-color]\">{{ subtitle() }}</div>\n </div>\n </div>\n </div>\n <div class=\"text-sm opacity-70\">This listing is verified and managed by an Primecase agent</div>\n</div>\n" }]
|
|
1290
1285
|
}] });
|
|
1291
1286
|
|
|
1287
|
+
class PropertyHighlights {
|
|
1288
|
+
highlights = input.required(...(ngDevMode ? [{ debugName: "highlights" }] : []));
|
|
1289
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyHighlights, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1290
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyHighlights, isStandalone: true, selector: "rolatech-property-highlights", inputs: { highlights: { classPropertyName: "highlights", publicName: "highlights", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"\">\n <div class=\"text-2xl font-bold py-3\" i18n>Highlights</div>\n <div class=\"flex flex-col flex-wrap\">\n @for (item of highlights(); track $index) {\n <div class=\"flex items-center py-1\">\n <!-- <mat-icon>check</mat-icon> -->\n <span>{{ item }}</span>\n </div>\n }\n </div>\n</div>\n", styles: [""] });
|
|
1291
|
+
}
|
|
1292
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyHighlights, decorators: [{
|
|
1293
|
+
type: Component,
|
|
1294
|
+
args: [{ selector: 'rolatech-property-highlights', template: "<div class=\"\">\n <div class=\"text-2xl font-bold py-3\" i18n>Highlights</div>\n <div class=\"flex flex-col flex-wrap\">\n @for (item of highlights(); track $index) {\n <div class=\"flex items-center py-1\">\n <!-- <mat-icon>check</mat-icon> -->\n <span>{{ item }}</span>\n </div>\n }\n </div>\n</div>\n" }]
|
|
1295
|
+
}] });
|
|
1296
|
+
|
|
1297
|
+
const BANDS = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
|
|
1298
|
+
const RANGES = {
|
|
1299
|
+
A: '(92+)', B: '(81-91)', C: '(69-80)', D: '(55-68)',
|
|
1300
|
+
E: '(39-54)', F: '(21-38)', G: '(1-20)',
|
|
1301
|
+
};
|
|
1302
|
+
const COLORS = {
|
|
1303
|
+
A: '#0E9F6E', // green
|
|
1304
|
+
B: '#10B981',
|
|
1305
|
+
C: '#84CC16',
|
|
1306
|
+
D: '#F59E0B',
|
|
1307
|
+
E: '#F97316',
|
|
1308
|
+
F: '#FB7185',
|
|
1309
|
+
G: '#DC2626'
|
|
1310
|
+
};
|
|
1311
|
+
function bandFromScore(s) {
|
|
1312
|
+
const v = s ?? 0;
|
|
1313
|
+
if (v >= 92)
|
|
1314
|
+
return 'A';
|
|
1315
|
+
if (v >= 81)
|
|
1316
|
+
return 'B';
|
|
1317
|
+
if (v >= 69)
|
|
1318
|
+
return 'C';
|
|
1319
|
+
if (v >= 55)
|
|
1320
|
+
return 'D';
|
|
1321
|
+
if (v >= 39)
|
|
1322
|
+
return 'E';
|
|
1323
|
+
if (v >= 21)
|
|
1324
|
+
return 'F';
|
|
1325
|
+
return 'G';
|
|
1326
|
+
}
|
|
1327
|
+
class EpcChart {
|
|
1328
|
+
// --- inputs (signals) ---
|
|
1329
|
+
currentScore = input(null, ...(ngDevMode ? [{ debugName: "currentScore" }] : [])); // 1..100
|
|
1330
|
+
potentialScore = input(null, ...(ngDevMode ? [{ debugName: "potentialScore" }] : [])); // 1..100
|
|
1331
|
+
showCaptions = input(true, ...(ngDevMode ? [{ debugName: "showCaptions" }] : []));
|
|
1332
|
+
// --- layout ---
|
|
1333
|
+
width = 920;
|
|
1334
|
+
leftPadding = 24;
|
|
1335
|
+
headerY = 40;
|
|
1336
|
+
rangeColW = 90;
|
|
1337
|
+
gapY = 10;
|
|
1338
|
+
topY = 110; // top of first row area
|
|
1339
|
+
rowH = 48; // height of each wedge row
|
|
1340
|
+
rows = 7;
|
|
1341
|
+
// wedge geometry
|
|
1342
|
+
wedgeMaxW = 420; // width of 'A' row
|
|
1343
|
+
wedgeMinW = 220;
|
|
1344
|
+
wedgeDelta = 44; // decrement per row
|
|
1345
|
+
cut = 24; // right slant depth
|
|
1346
|
+
// arrow columns
|
|
1347
|
+
arrowW = 104;
|
|
1348
|
+
arrowH = 44;
|
|
1349
|
+
colGap = 130;
|
|
1350
|
+
wedgeAreaRight = this.leftPadding + this.rangeColW + 12 + this.wedgeMaxW + 20;
|
|
1351
|
+
currentColX = this.wedgeAreaRight + 80;
|
|
1352
|
+
potentialColX = this.currentColX + this.colGap;
|
|
1353
|
+
// captions
|
|
1354
|
+
topCaptionY = this.topY - 22;
|
|
1355
|
+
get bottomCaptionY() { return this.topY + this.rows * (this.rowH + this.gapY) + 22; }
|
|
1356
|
+
// overall height
|
|
1357
|
+
get height() {
|
|
1358
|
+
return this.bottomCaptionY + 56;
|
|
1359
|
+
}
|
|
1360
|
+
// expose constants to template
|
|
1361
|
+
bands = BANDS;
|
|
1362
|
+
RANGES = RANGES;
|
|
1363
|
+
COLORS = COLORS;
|
|
1364
|
+
get rangeX() { return this.leftPadding; }
|
|
1365
|
+
get maxW() { return this.wedgeMinW + 6 * this.wedgeDelta; } // width of G (widest)
|
|
1366
|
+
// helpers
|
|
1367
|
+
wedgeX(i) { return this.leftPadding + this.rangeColW + 12; }
|
|
1368
|
+
// private wedgeW(i: number) { return this.wedgeMaxW - (i * this.wedgeDelta); }
|
|
1369
|
+
wedgeW(i) {
|
|
1370
|
+
// A..G => 0..6 → widths increase downward
|
|
1371
|
+
return this.wedgeMinW + i * this.wedgeDelta;
|
|
1372
|
+
}
|
|
1373
|
+
rowY(i) { return this.topY + i * (this.rowH + this.gapY); }
|
|
1374
|
+
wedgePoints1(i) {
|
|
1375
|
+
const x = this.wedgeX(i), y = this.rowY(i), w = this.wedgeW(i), h = this.rowH, c = this.cut;
|
|
1376
|
+
// rectangle with right chevron tip
|
|
1377
|
+
// (x,y) → (x+w-c,y) → (x+w,y+h/2) → (x+w-c,y+h) → (x,y+h)
|
|
1378
|
+
return `${x},${y} ${x + w - c},${y} ${x + w},${y + h / 2} ${x + w - c},${y + h} ${x},${y + h}`;
|
|
1379
|
+
}
|
|
1380
|
+
wedgePoints(i) {
|
|
1381
|
+
const x = this.wedgeX(i), y = this.rowY(i), w = this.wedgeW(i), h = this.rowH;
|
|
1382
|
+
// rectangle: (x,y) → (x+w,y) → (x+w,y+h) → (x,y+h)
|
|
1383
|
+
return `${x},${y} ${x + w},${y} ${x + w},${y + h} ${x},${y + h}`;
|
|
1384
|
+
}
|
|
1385
|
+
wedgeLetterX(i) {
|
|
1386
|
+
// place on the trailing (right) end of wedge, just before chevron tip
|
|
1387
|
+
return this.wedgeX(i) + this.wedgeW(i) - this.cut - 10;
|
|
1388
|
+
}
|
|
1389
|
+
// arrow badge (left-pointing)
|
|
1390
|
+
arrowPoints() {
|
|
1391
|
+
const w = this.arrowW, h = this.arrowH, tip = 18; // tip depth
|
|
1392
|
+
// (w,0) → (tip,0) → (0,h/2) → (tip,h) → (w,h) → close
|
|
1393
|
+
return `${w},0 ${tip},0 0,${h / 2} ${tip},${h} ${w},${h}`;
|
|
1394
|
+
}
|
|
1395
|
+
// vertical placement: center the arrow in the band row for the given score
|
|
1396
|
+
arrowY(score) {
|
|
1397
|
+
const b = bandFromScore(score);
|
|
1398
|
+
const rowIndex = this.bands.indexOf(b);
|
|
1399
|
+
const y = this.rowY(rowIndex) + (this.rowH - this.arrowH) / 2;
|
|
1400
|
+
return Math.max(y, this.topY); // safety
|
|
1401
|
+
}
|
|
1402
|
+
clampScore(s) { return Math.max(1, Math.min(100, Math.round(s))); }
|
|
1403
|
+
// add below COLORS, bandFromScore...
|
|
1404
|
+
colorForBand(b) { return COLORS[b]; }
|
|
1405
|
+
colorForScore(s) { return this.colorForBand(bandFromScore(s)); }
|
|
1406
|
+
// simple contrast so numbers stay readable
|
|
1407
|
+
textColorForBand(b) {
|
|
1408
|
+
const hex = this.colorForBand(b).replace('#', '');
|
|
1409
|
+
const r = parseInt(hex.slice(0, 2), 16);
|
|
1410
|
+
const g = parseInt(hex.slice(2, 4), 16);
|
|
1411
|
+
const bl = parseInt(hex.slice(4, 6), 16);
|
|
1412
|
+
const yiq = (r * 299 + g * 587 + bl * 114) / 1000;
|
|
1413
|
+
return yiq >= 170 ? '#111' : '#fff'; // light bg → dark text, else white
|
|
1414
|
+
}
|
|
1415
|
+
textColorForScore(s) { return this.textColorForBand(bandFromScore(s)); }
|
|
1416
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: EpcChart, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1417
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: EpcChart, isStandalone: true, selector: "rolatech-epc-chart", inputs: { currentScore: { classPropertyName: "currentScore", publicName: "currentScore", isSignal: true, isRequired: false, transformFunction: null }, potentialScore: { classPropertyName: "potentialScore", publicName: "potentialScore", isSignal: true, isRequired: false, transformFunction: null }, showCaptions: { classPropertyName: "showCaptions", publicName: "showCaptions", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "w-full" }, ngImport: i0, template: "<svg [attr.viewBox]=\"'0 0 ' + width + ' ' + height\" class=\"w-full h-auto\">\n <!-- outer border -->\n <rect x=\"8\" y=\"8\" [attr.width]=\"width-16\" [attr.height]=\"height-16\" fill=\"none\" stroke=\"#111\" stroke-width=\"2\" />\n\n <!-- header row -->\n <text [attr.x]=\"leftPadding\" [attr.y]=\"headerY\" font-weight=\"700\" font-size=\"16\">Energy Rating</text>\n <text [attr.x]=\"currentColX + arrowW/2\" [attr.y]=\"headerY\" text-anchor=\"middle\" font-weight=\"700\" font-size=\"16\">\n Current\n </text>\n <text [attr.x]=\"potentialColX + arrowW/2\" [attr.y]=\"headerY\" text-anchor=\"middle\" font-weight=\"700\" font-size=\"16\">\n Potential\n </text>\n <line x1=\"8\" [attr.y1]=\"headerY+10\" [attr.x2]=\"width-8\" [attr.y2]=\"headerY+10\" stroke=\"#111\" stroke-width=\"2\" />\n\n <!-- top/bottom captions -->\n @if (showCaptions()) {\n <text [attr.x]=\"leftPadding\" [attr.y]=\"topCaptionY\" fill=\"#9CA3AF\" font-size=\"20\">\n very energy efficient - lower running costs\n </text>\n <text [attr.x]=\"leftPadding\" [attr.y]=\"bottomCaptionY\" fill=\"#9CA3AF\" font-size=\"20\">\n not energy efficient - higher running costs\n </text>\n }\n\n <!-- Wedges (A..G) -->\n @for (b of bands; track b; let i = $index) {\n <!-- range text column -->\n <text [attr.x]=\"rangeX\" [attr.y]=\"rowY(i) + rowH/2 + 5\" fill=\"#6B7280\" font-size=\"16\">{{ RANGES[b] }}</text>\n\n <!-- colored wedge -->\n <polygon [attr.points]=\"wedgePoints(i)\" [attr.fill]=\"COLORS[b]\" stroke=\"none\" />\n\n <!-- band letter -->\n <text\n [attr.x]=\"wedgeLetterX(i)\"\n [attr.y]=\"rowY(i) + rowH/2 + 8\"\n fill=\"white\"\n font-size=\"28\"\n font-weight=\"700\"\n text-anchor=\"end\"\n >\n {{ b }}\n </text>\n }\n\n <!-- Current arrow badge -->\n @if (currentScore() !== null) {\n <g [attr.transform]=\"'translate(' + currentColX + ',' + arrowY(currentScore()!) + ')'\">\n <polygon [attr.points]=\"arrowPoints()\" [attr.fill]=\"colorForScore(currentScore()!)\"></polygon>\n <text\n [attr.x]=\"arrowW/2 + 6\"\n [attr.y]=\"arrowH/2 + 9\"\n text-anchor=\"middle\"\n font-size=\"24\"\n font-weight=\"800\"\n [attr.fill]=\"textColorForScore(currentScore()!)\"\n >\n {{ clampScore(currentScore()!) }}\n </text>\n <!-- underline (optional) -->\n <rect\n [attr.x]=\"arrowW/2 - 12\"\n [attr.y]=\"arrowH/2 + 12\"\n width=\"36\"\n height=\"3\"\n [attr.fill]=\"textColorForScore(currentScore()!)\"\n opacity=\"0.8\"\n />\n </g>\n }\n\n <!-- Potential arrow badge -->\n @if (potentialScore() !== null) {\n <g [attr.transform]=\"'translate(' + potentialColX + ',' + arrowY(potentialScore()!) + ')'\">\n <polygon [attr.points]=\"arrowPoints()\" [attr.fill]=\"colorForScore(potentialScore()!)\"></polygon>\n <text\n [attr.x]=\"arrowW/2 + 6\"\n [attr.y]=\"arrowH/2 + 9\"\n text-anchor=\"middle\"\n font-size=\"24\"\n font-weight=\"800\"\n [attr.fill]=\"textColorForScore(potentialScore()!)\"\n >\n {{ clampScore(potentialScore()!) }}\n </text>\n </g>\n }\n</svg>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
1418
|
+
}
|
|
1419
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: EpcChart, decorators: [{
|
|
1420
|
+
type: Component,
|
|
1421
|
+
args: [{ selector: 'rolatech-epc-chart', imports: [CommonModule], host: { class: 'w-full' }, template: "<svg [attr.viewBox]=\"'0 0 ' + width + ' ' + height\" class=\"w-full h-auto\">\n <!-- outer border -->\n <rect x=\"8\" y=\"8\" [attr.width]=\"width-16\" [attr.height]=\"height-16\" fill=\"none\" stroke=\"#111\" stroke-width=\"2\" />\n\n <!-- header row -->\n <text [attr.x]=\"leftPadding\" [attr.y]=\"headerY\" font-weight=\"700\" font-size=\"16\">Energy Rating</text>\n <text [attr.x]=\"currentColX + arrowW/2\" [attr.y]=\"headerY\" text-anchor=\"middle\" font-weight=\"700\" font-size=\"16\">\n Current\n </text>\n <text [attr.x]=\"potentialColX + arrowW/2\" [attr.y]=\"headerY\" text-anchor=\"middle\" font-weight=\"700\" font-size=\"16\">\n Potential\n </text>\n <line x1=\"8\" [attr.y1]=\"headerY+10\" [attr.x2]=\"width-8\" [attr.y2]=\"headerY+10\" stroke=\"#111\" stroke-width=\"2\" />\n\n <!-- top/bottom captions -->\n @if (showCaptions()) {\n <text [attr.x]=\"leftPadding\" [attr.y]=\"topCaptionY\" fill=\"#9CA3AF\" font-size=\"20\">\n very energy efficient - lower running costs\n </text>\n <text [attr.x]=\"leftPadding\" [attr.y]=\"bottomCaptionY\" fill=\"#9CA3AF\" font-size=\"20\">\n not energy efficient - higher running costs\n </text>\n }\n\n <!-- Wedges (A..G) -->\n @for (b of bands; track b; let i = $index) {\n <!-- range text column -->\n <text [attr.x]=\"rangeX\" [attr.y]=\"rowY(i) + rowH/2 + 5\" fill=\"#6B7280\" font-size=\"16\">{{ RANGES[b] }}</text>\n\n <!-- colored wedge -->\n <polygon [attr.points]=\"wedgePoints(i)\" [attr.fill]=\"COLORS[b]\" stroke=\"none\" />\n\n <!-- band letter -->\n <text\n [attr.x]=\"wedgeLetterX(i)\"\n [attr.y]=\"rowY(i) + rowH/2 + 8\"\n fill=\"white\"\n font-size=\"28\"\n font-weight=\"700\"\n text-anchor=\"end\"\n >\n {{ b }}\n </text>\n }\n\n <!-- Current arrow badge -->\n @if (currentScore() !== null) {\n <g [attr.transform]=\"'translate(' + currentColX + ',' + arrowY(currentScore()!) + ')'\">\n <polygon [attr.points]=\"arrowPoints()\" [attr.fill]=\"colorForScore(currentScore()!)\"></polygon>\n <text\n [attr.x]=\"arrowW/2 + 6\"\n [attr.y]=\"arrowH/2 + 9\"\n text-anchor=\"middle\"\n font-size=\"24\"\n font-weight=\"800\"\n [attr.fill]=\"textColorForScore(currentScore()!)\"\n >\n {{ clampScore(currentScore()!) }}\n </text>\n <!-- underline (optional) -->\n <rect\n [attr.x]=\"arrowW/2 - 12\"\n [attr.y]=\"arrowH/2 + 12\"\n width=\"36\"\n height=\"3\"\n [attr.fill]=\"textColorForScore(currentScore()!)\"\n opacity=\"0.8\"\n />\n </g>\n }\n\n <!-- Potential arrow badge -->\n @if (potentialScore() !== null) {\n <g [attr.transform]=\"'translate(' + potentialColX + ',' + arrowY(potentialScore()!) + ')'\">\n <polygon [attr.points]=\"arrowPoints()\" [attr.fill]=\"colorForScore(potentialScore()!)\"></polygon>\n <text\n [attr.x]=\"arrowW/2 + 6\"\n [attr.y]=\"arrowH/2 + 9\"\n text-anchor=\"middle\"\n font-size=\"24\"\n font-weight=\"800\"\n [attr.fill]=\"textColorForScore(potentialScore()!)\"\n >\n {{ clampScore(potentialScore()!) }}\n </text>\n </g>\n }\n</svg>\n" }]
|
|
1422
|
+
}] });
|
|
1423
|
+
|
|
1424
|
+
class PropertyEpc {
|
|
1425
|
+
epc = input.required(...(ngDevMode ? [{ debugName: "epc" }] : []));
|
|
1426
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyEpc, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1427
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.2.0", type: PropertyEpc, isStandalone: true, selector: "rolatech-property-epc", inputs: { epc: { classPropertyName: "epc", publicName: "epc", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"w-full\">\n <div class=\"text-2xl font-bold py-3\" i18n>EPC</div>\n <div class=\"flex flex-row items-center font-thin text-sm\">\n <rolatech-epc-chart\n [currentScore]=\"epc().currentScore\"\n [potentialScore]=\"epc().potentialScore\"\n [showCaptions]=\"true\"\n ></rolatech-epc-chart>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: EpcChart, selector: "rolatech-epc-chart", inputs: ["currentScore", "potentialScore", "showCaptions"] }] });
|
|
1428
|
+
}
|
|
1429
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyEpc, decorators: [{
|
|
1430
|
+
type: Component,
|
|
1431
|
+
args: [{ selector: 'rolatech-property-epc', imports: [EpcChart], template: "<div class=\"w-full\">\n <div class=\"text-2xl font-bold py-3\" i18n>EPC</div>\n <div class=\"flex flex-row items-center font-thin text-sm\">\n <rolatech-epc-chart\n [currentScore]=\"epc().currentScore\"\n [potentialScore]=\"epc().potentialScore\"\n [showCaptions]=\"true\"\n ></rolatech-epc-chart>\n </div>\n</div>\n" }]
|
|
1432
|
+
}] });
|
|
1433
|
+
|
|
1292
1434
|
class PropertyDetailsComponent extends BaseComponent {
|
|
1293
1435
|
authService = inject(AuthService);
|
|
1294
1436
|
authUserService = inject(AuthUserService);
|
|
@@ -1303,6 +1445,8 @@ class PropertyDetailsComponent extends BaseComponent {
|
|
|
1303
1445
|
selectedOption;
|
|
1304
1446
|
variants = [];
|
|
1305
1447
|
features = [];
|
|
1448
|
+
highlights = [];
|
|
1449
|
+
epc;
|
|
1306
1450
|
selectedVariant;
|
|
1307
1451
|
variantOption = signal(undefined, ...(ngDevMode ? [{ debugName: "variantOption" }] : []));
|
|
1308
1452
|
variantOptionChanged = computed(() => {
|
|
@@ -1320,6 +1464,8 @@ class PropertyDetailsComponent extends BaseComponent {
|
|
|
1320
1464
|
ngOnInit() {
|
|
1321
1465
|
this.getProperty();
|
|
1322
1466
|
this.findFeatures();
|
|
1467
|
+
this.findHighlights();
|
|
1468
|
+
this.getEpc();
|
|
1323
1469
|
}
|
|
1324
1470
|
getProperty() {
|
|
1325
1471
|
this.propertyService.get(this.id).subscribe({
|
|
@@ -1356,10 +1502,23 @@ class PropertyDetailsComponent extends BaseComponent {
|
|
|
1356
1502
|
});
|
|
1357
1503
|
}
|
|
1358
1504
|
findFeatures() {
|
|
1359
|
-
console.log(this.id);
|
|
1360
1505
|
this.propertyService.findFeatures(this.id).subscribe({
|
|
1361
1506
|
next: (res) => {
|
|
1362
|
-
this.features = res.data;
|
|
1507
|
+
this.features = res.data || [];
|
|
1508
|
+
}
|
|
1509
|
+
});
|
|
1510
|
+
}
|
|
1511
|
+
findHighlights() {
|
|
1512
|
+
this.propertyService.getHighlights(this.id).subscribe({
|
|
1513
|
+
next: (res) => {
|
|
1514
|
+
this.highlights = res.data || [];
|
|
1515
|
+
}
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
getEpc() {
|
|
1519
|
+
this.propertyService.getEpc(this.id).subscribe({
|
|
1520
|
+
next: (res) => {
|
|
1521
|
+
this.epc = res.data;
|
|
1363
1522
|
}
|
|
1364
1523
|
});
|
|
1365
1524
|
}
|
|
@@ -1441,7 +1600,7 @@ class PropertyDetailsComponent extends BaseComponent {
|
|
|
1441
1600
|
// const updatedCriteria = matchingVariant ? updateCriteriaFromVariant(matchingVariant) : [];
|
|
1442
1601
|
}
|
|
1443
1602
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1444
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyDetailsComponent, isStandalone: true, selector: "rolatech-property-details", usesInheritance: true, ngImport: i0, template: "@if (property) {\n <rolatech-container>\n <div class=\"flex flex-col w-full\">\n <div class=\"py-3\">\n <rolatech-property-media [media]=\"property.media\"></rolatech-property-media>\n </div>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <!-- <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer> -->\n <mat-divider></mat-divider>\n <rolatech-property-features [features]=\"features\"></rolatech-property-features>\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n @if (property.
|
|
1603
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyDetailsComponent, isStandalone: true, selector: "rolatech-property-details", usesInheritance: true, ngImport: i0, template: "@if (property) {\n <rolatech-container>\n <div class=\"flex flex-col w-full\">\n <div class=\"py-3\">\n <rolatech-property-media [media]=\"property.media\"></rolatech-property-media>\n </div>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <!-- <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer> -->\n <mat-divider></mat-divider>\n\n @if (features.length > 0) {\n <rolatech-property-features [features]=\"features\"></rolatech-property-features>\n }\n @if (highlights.length > 0) {\n <rolatech-property-highlights [highlights]=\"highlights\"></rolatech-property-highlights>\n }\n <!-- <rolatech-property-epc [epc]=\"epc\"></rolatech-property-epc> -->\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n @if (property.videos) {\n @for (item of property.videos; track $index) {\n <rolatech-property-video [video]=\"item\"></rolatech-property-video>\n }\n }\n @if (epc && epc.currentScore) {\n <rolatech-property-epc [epc]=\"epc\"></rolatech-property-epc>\n }\n <div class=\"flex flex-col\">\n <div class=\"text-2xl font-bold pt-3\" i18n>Sections</div>\n @for (section of property.sections; track $index) {\n <rolatech-property-section [section]=\"section\"></rolatech-property-section>\n }\n <rolatech-comments [itemId]=\"property.id\"></rolatech-comments>\n </div>\n </div>\n <div class=\"w-full md:w-1/3\">\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-pricing (wish)=\"onWish($event)\" [property]=\"property\"></rolatech-property-pricing>\n <rolatech-property-actions\n [property]=\"property\"\n (offer)=\"onOffer($event)\"\n (deposit)=\"onOffer($event)\"\n (requestViewing)=\"onRequestViewing($event)\"\n >\n @if (user) {\n <rolatech-property-action-contact [email]=\"user.email\" [phone]=\"user.phone\"></rolatech-property-action-contact>\n }\n </rolatech-property-actions>\n </div>\n </div>\n </div>\n </rolatech-container>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: i2$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: PropertyInfoComponent, selector: "rolatech-property-info", inputs: ["property", "inWishList"], outputs: ["wish"] }, { kind: "component", type: PropertyMediaComponent, selector: "rolatech-property-media", inputs: ["media", "min"] }, { kind: "component", type: PropertyPricingComponent, selector: "rolatech-property-pricing", inputs: ["property", "price"] }, { kind: "component", type: PropertySectionComponent, selector: "rolatech-property-section", inputs: ["section", "user", "username"] }, { kind: "component", type: PropertyActionsComponent, selector: "rolatech-property-actions", inputs: ["property"], outputs: ["requestViewing", "offer", "deposit"] }, { kind: "component", type: CommentsComponent, selector: "rolatech-comments", inputs: ["itemId"] }, { kind: "component", type: PropertyAgentRenderer, selector: "rolatech-property-agent-renderer", inputs: ["name", "avatar", "username", "subtitle"] }, { kind: "component", type: PropertyLocationComponent, selector: "rolatech-property-location", inputs: ["location"] }, { kind: "component", type: PropertyFeaturesComponent, selector: "rolatech-property-features", inputs: ["features"] }, { kind: "component", type: PropertyVideoComponent, selector: "rolatech-property-video", inputs: ["video"] }, { kind: "component", type: PropertyActionContactComponent, selector: "rolatech-property-action-contact", inputs: ["email", "phone"], outputs: ["callAgent", "emailAgent"] }, { kind: "component", type: PropertyHighlights, selector: "rolatech-property-highlights", inputs: ["highlights"] }, { kind: "component", type: PropertyEpc, selector: "rolatech-property-epc", inputs: ["epc"] }] });
|
|
1445
1604
|
}
|
|
1446
1605
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyDetailsComponent, decorators: [{
|
|
1447
1606
|
type: Component,
|
|
@@ -1458,9 +1617,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImpor
|
|
|
1458
1617
|
PropertyAgentRenderer,
|
|
1459
1618
|
PropertyLocationComponent,
|
|
1460
1619
|
PropertyFeaturesComponent,
|
|
1461
|
-
|
|
1620
|
+
PropertyVideoComponent,
|
|
1462
1621
|
PropertyActionContactComponent,
|
|
1463
|
-
|
|
1622
|
+
PropertyHighlights,
|
|
1623
|
+
PropertyEpc,
|
|
1624
|
+
], template: "@if (property) {\n <rolatech-container>\n <div class=\"flex flex-col w-full\">\n <div class=\"py-3\">\n <rolatech-property-media [media]=\"property.media\"></rolatech-property-media>\n </div>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <!-- <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer> -->\n <mat-divider></mat-divider>\n\n @if (features.length > 0) {\n <rolatech-property-features [features]=\"features\"></rolatech-property-features>\n }\n @if (highlights.length > 0) {\n <rolatech-property-highlights [highlights]=\"highlights\"></rolatech-property-highlights>\n }\n <!-- <rolatech-property-epc [epc]=\"epc\"></rolatech-property-epc> -->\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n @if (property.videos) {\n @for (item of property.videos; track $index) {\n <rolatech-property-video [video]=\"item\"></rolatech-property-video>\n }\n }\n @if (epc && epc.currentScore) {\n <rolatech-property-epc [epc]=\"epc\"></rolatech-property-epc>\n }\n <div class=\"flex flex-col\">\n <div class=\"text-2xl font-bold pt-3\" i18n>Sections</div>\n @for (section of property.sections; track $index) {\n <rolatech-property-section [section]=\"section\"></rolatech-property-section>\n }\n <rolatech-comments [itemId]=\"property.id\"></rolatech-comments>\n </div>\n </div>\n <div class=\"w-full md:w-1/3\">\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-pricing (wish)=\"onWish($event)\" [property]=\"property\"></rolatech-property-pricing>\n <rolatech-property-actions\n [property]=\"property\"\n (offer)=\"onOffer($event)\"\n (deposit)=\"onOffer($event)\"\n (requestViewing)=\"onRequestViewing($event)\"\n >\n @if (user) {\n <rolatech-property-action-contact [email]=\"user.email\" [phone]=\"user.phone\"></rolatech-property-action-contact>\n }\n </rolatech-property-actions>\n </div>\n </div>\n </div>\n </rolatech-container>\n}\n" }]
|
|
1464
1625
|
}], ctorParameters: () => [] });
|
|
1465
1626
|
|
|
1466
1627
|
const MY_FORMATS$5 = {
|
|
@@ -2270,7 +2431,7 @@ const propertyRoutes = [
|
|
|
2270
2431
|
children: [
|
|
2271
2432
|
{
|
|
2272
2433
|
path: '',
|
|
2273
|
-
loadComponent: () => import('./rolatech-angular-property-property-index.component-
|
|
2434
|
+
loadComponent: () => import('./rolatech-angular-property-property-index.component-CbbxIQ8w.mjs').then((x) => x.PropertyIndexComponent),
|
|
2274
2435
|
},
|
|
2275
2436
|
],
|
|
2276
2437
|
},
|
|
@@ -2339,6 +2500,7 @@ class PropertyManageIndexComponent {
|
|
|
2339
2500
|
dialog = inject(MatDialog);
|
|
2340
2501
|
snackBar = inject(MatSnackBar);
|
|
2341
2502
|
propertyService = inject(PropertyService);
|
|
2503
|
+
propertySearchService = inject(PropertySearchService);
|
|
2342
2504
|
isLoading = false;
|
|
2343
2505
|
isSearch = false;
|
|
2344
2506
|
properties = [];
|
|
@@ -2492,11 +2654,11 @@ class PropertyManageLayoutComponent extends BaseComponent {
|
|
|
2492
2654
|
});
|
|
2493
2655
|
}
|
|
2494
2656
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageLayoutComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2495
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyManageLayoutComponent, isStandalone: true, selector: "rolatech-property-manage-layout", usesInheritance: true, ngImport: i0, template: "<div class=\"flex flex-col md:flex-row m-auto\">\n <div\n class=\"min-w-[256px] px-3 md:px-0 flex flex-row md:flex-col md:h-full items-center md:items-start h-16 overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <div class=\"flex flex-row md:flex-col md:w-full\">\n <div class=\"hidden md:flex text-xl font-bold h-14 items-center px-1\" i18n>Property</div>\n <a routerLink=\"./info\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Basic info</a>\n <a routerLink=\"./media\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Media</a>\n <a routerLink=\"./
|
|
2657
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyManageLayoutComponent, isStandalone: true, selector: "rolatech-property-manage-layout", usesInheritance: true, ngImport: i0, template: "<div class=\"flex flex-col md:flex-row m-auto\">\n <div\n class=\"min-w-[256px] px-3 md:px-0 flex flex-row md:flex-col md:h-full items-center md:items-start h-16 overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <div class=\"flex flex-row md:flex-col md:w-full\">\n <div class=\"hidden md:flex text-xl font-bold h-14 items-center px-1\" i18n>Property</div>\n <a routerLink=\"./info\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Basic info</a>\n <a routerLink=\"./media\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Media</a>\n <a routerLink=\"./videos\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Videos</a>\n <a routerLink=\"./sections\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Details</a>\n <a routerLink=\"./location\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Location</a>\n <a routerLink=\"./features\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Features</a>\n <a routerLink=\"./highlights\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Highlights</a>\n <a routerLink=\"./epc\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>EPC</a>\n <a routerLink=\"./translation\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Translation</a>\n <!-- <a routerLink=\"./amenities\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Amenities</a> -->\n <!-- <a routerLink=\"./tags\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Tags</a> -->\n <!-- <a routerLink=\"./options\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Options</a> -->\n </div>\n <div class=\"flex flex-row md:flex-col md:w-full\">\n <div class=\"hidden md:flex text-xl font-bold h-14 items-center px-2\" i18n>Settings</div>\n <!-- <a routerLink=\"./variants\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Variants</a> -->\n <a routerLink=\"./schedule\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Schedule</a>\n <a routerLink=\"./pricing\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Pricing</a>\n </div>\n <!-- <div class=\"flex flex-row md:flex-col md:w-full\">\n <div class=\"hidden md:flex text-xl font-bold h-14 items-center px-2\" i18n>Others</div>\n </div> -->\n @if (property) {\n @if (property.status.toString() === 'DRAFT') {\n <div class=\"md:mt-6 md:ml-2 flex items-center\">\n <button mat-flat-button (click)=\"submit()\" i18n>Submit for review</button>\n </div>\n }\n @if (property.status.toString() === 'PENDING') {\n <div class=\"md:mt-6 md:ml-2 flex items-center\">\n <button mat-flat-button disabled i18n>Pending</button>\n </div>\n }\n @if (property.status.toString() === 'APPROVED') {\n <div class=\"md:mt-6 md:ml-2 flex items-center\">\n <button mat-flat-button (click)=\"publish()\" i18n>Publish</button>\n </div>\n }\n }\n </div>\n <div class=\"w-full\">\n <router-outlet></router-outlet>\n </div>\n</div>\n", styles: [".manage-active{background-color:var(--rt-10-percent-layer, rgba(0, 0, 0, .05));box-shadow:4px 0 var(--rt-base-background-inverse, #000) inset;font-weight:600}@media (max-width: 768px){.manage-active{box-shadow:inset 0 -4px 0 0 var(--rt-base-background-inverse, #000)}}.scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
2496
2658
|
}
|
|
2497
2659
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageLayoutComponent, decorators: [{
|
|
2498
2660
|
type: Component,
|
|
2499
|
-
args: [{ selector: 'rolatech-property-manage-layout', imports: [RouterLink, RouterLinkActive, MatButtonModule, RouterOutlet], encapsulation: ViewEncapsulation.None, template: "<div class=\"flex flex-col md:flex-row m-auto\">\n <div\n class=\"min-w-[256px] px-3 md:px-0 flex flex-row md:flex-col md:h-full items-center md:items-start h-16 overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <div class=\"flex flex-row md:flex-col md:w-full\">\n <div class=\"hidden md:flex text-xl font-bold h-14 items-center px-1\" i18n>Property</div>\n <a routerLink=\"./info\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Basic info</a>\n <a routerLink=\"./media\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Media</a>\n <a routerLink=\"./
|
|
2661
|
+
args: [{ selector: 'rolatech-property-manage-layout', imports: [RouterLink, RouterLinkActive, MatButtonModule, RouterOutlet], encapsulation: ViewEncapsulation.None, template: "<div class=\"flex flex-col md:flex-row m-auto\">\n <div\n class=\"min-w-[256px] px-3 md:px-0 flex flex-row md:flex-col md:h-full items-center md:items-start h-16 overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <div class=\"flex flex-row md:flex-col md:w-full\">\n <div class=\"hidden md:flex text-xl font-bold h-14 items-center px-1\" i18n>Property</div>\n <a routerLink=\"./info\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Basic info</a>\n <a routerLink=\"./media\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Media</a>\n <a routerLink=\"./videos\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Videos</a>\n <a routerLink=\"./sections\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Details</a>\n <a routerLink=\"./location\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Location</a>\n <a routerLink=\"./features\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Features</a>\n <a routerLink=\"./highlights\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Highlights</a>\n <a routerLink=\"./epc\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>EPC</a>\n <a routerLink=\"./translation\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Translation</a>\n <!-- <a routerLink=\"./amenities\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Amenities</a> -->\n <!-- <a routerLink=\"./tags\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Tags</a> -->\n <!-- <a routerLink=\"./options\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Options</a> -->\n </div>\n <div class=\"flex flex-row md:flex-col md:w-full\">\n <div class=\"hidden md:flex text-xl font-bold h-14 items-center px-2\" i18n>Settings</div>\n <!-- <a routerLink=\"./variants\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Variants</a> -->\n <a routerLink=\"./schedule\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Schedule</a>\n <a routerLink=\"./pricing\" routerLinkActive=\"manage-active\" class=\"p-2\" i18n>Pricing</a>\n </div>\n <!-- <div class=\"flex flex-row md:flex-col md:w-full\">\n <div class=\"hidden md:flex text-xl font-bold h-14 items-center px-2\" i18n>Others</div>\n </div> -->\n @if (property) {\n @if (property.status.toString() === 'DRAFT') {\n <div class=\"md:mt-6 md:ml-2 flex items-center\">\n <button mat-flat-button (click)=\"submit()\" i18n>Submit for review</button>\n </div>\n }\n @if (property.status.toString() === 'PENDING') {\n <div class=\"md:mt-6 md:ml-2 flex items-center\">\n <button mat-flat-button disabled i18n>Pending</button>\n </div>\n }\n @if (property.status.toString() === 'APPROVED') {\n <div class=\"md:mt-6 md:ml-2 flex items-center\">\n <button mat-flat-button (click)=\"publish()\" i18n>Publish</button>\n </div>\n }\n }\n </div>\n <div class=\"w-full\">\n <router-outlet></router-outlet>\n </div>\n</div>\n", styles: [".manage-active{background-color:var(--rt-10-percent-layer, rgba(0, 0, 0, .05));box-shadow:4px 0 var(--rt-base-background-inverse, #000) inset;font-weight:600}@media (max-width: 768px){.manage-active{box-shadow:inset 0 -4px 0 0 var(--rt-base-background-inverse, #000)}}.scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"] }]
|
|
2500
2662
|
}] });
|
|
2501
2663
|
|
|
2502
2664
|
class PropertyManageContentComponent {
|
|
@@ -3069,7 +3231,6 @@ class PropertyManageFeaturesComponent extends BaseComponent {
|
|
|
3069
3231
|
features: this.featureService.find({}),
|
|
3070
3232
|
options: this.propertyService.findFeatures(this.id),
|
|
3071
3233
|
}).subscribe(({ features, options }) => {
|
|
3072
|
-
console.log(options);
|
|
3073
3234
|
this.features = features.data;
|
|
3074
3235
|
if (options.data) {
|
|
3075
3236
|
this.selected = this.convertToBinding(options.data);
|
|
@@ -3167,13 +3328,12 @@ class PropertyManageLocationComponent extends BaseComponent {
|
|
|
3167
3328
|
longitude: '',
|
|
3168
3329
|
latitude: '',
|
|
3169
3330
|
}, ...(ngDevMode ? [{ debugName: "location" }] : []));
|
|
3170
|
-
platformId = inject(PLATFORM_ID);
|
|
3171
3331
|
placeAutocompleteElement;
|
|
3172
3332
|
autocompleteInput;
|
|
3173
3333
|
ngOnInit() {
|
|
3174
3334
|
this.id = this.route.parent?.snapshot.paramMap.get('id');
|
|
3175
3335
|
this.find();
|
|
3176
|
-
if (
|
|
3336
|
+
if (this.isBrowser) {
|
|
3177
3337
|
// this.autocompleteService = new google.maps.places.AutocompleteService();
|
|
3178
3338
|
}
|
|
3179
3339
|
}
|
|
@@ -3334,9 +3494,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImpor
|
|
|
3334
3494
|
args: ['autocompleteInput', { static: false }]
|
|
3335
3495
|
}] } });
|
|
3336
3496
|
|
|
3337
|
-
class
|
|
3338
|
-
|
|
3339
|
-
videoId = '';
|
|
3497
|
+
class PropertyVideoYoutubeAddComponent {
|
|
3498
|
+
url = '';
|
|
3340
3499
|
output = output();
|
|
3341
3500
|
getYouTubeVideoId(url) {
|
|
3342
3501
|
const regex = /(?:youtube\.com\/(?:watch\?v=|embed\/|v\/|shorts\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/;
|
|
@@ -3344,40 +3503,141 @@ class PropertyVideoTourAddComponent {
|
|
|
3344
3503
|
return match ? match[1] : null;
|
|
3345
3504
|
}
|
|
3346
3505
|
ngDoCheck() {
|
|
3347
|
-
this.
|
|
3348
|
-
this.output.emit(this.videoId);
|
|
3506
|
+
this.output.emit(this.url);
|
|
3349
3507
|
}
|
|
3350
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type:
|
|
3351
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.0", type:
|
|
3508
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyVideoYoutubeAddComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3509
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.0", type: PropertyVideoYoutubeAddComponent, isStandalone: true, selector: "rolatech-property-video-youtube-add", outputs: { output: "output" }, ngImport: i0, template: "<mat-form-field appearance=\"fill\">\n <mat-label>Youtube Video URL</mat-label>\n <input matInput placeholder=\"Youtube Video URL\" type=\"text\" [(ngModel)]=\"url\" i18n />\n</mat-form-field>\n", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
3352
3510
|
}
|
|
3353
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type:
|
|
3511
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyVideoYoutubeAddComponent, decorators: [{
|
|
3354
3512
|
type: Component,
|
|
3355
|
-
args: [{ selector: 'rolatech-property-video-
|
|
3513
|
+
args: [{ selector: 'rolatech-property-video-youtube-add', imports: [CommonModule, MatFormFieldModule, MatInputModule, FormsModule], template: "<mat-form-field appearance=\"fill\">\n <mat-label>Youtube Video URL</mat-label>\n <input matInput placeholder=\"Youtube Video URL\" type=\"text\" [(ngModel)]=\"url\" i18n />\n</mat-form-field>\n", styles: ["mat-form-field{width:100%}\n"] }]
|
|
3356
3514
|
}] });
|
|
3357
3515
|
|
|
3358
|
-
class
|
|
3359
|
-
propertyService = inject(PropertyService);
|
|
3516
|
+
class SafeUrlPipe {
|
|
3360
3517
|
sanitizer = inject(DomSanitizer);
|
|
3361
|
-
|
|
3518
|
+
transform(url) {
|
|
3519
|
+
if (!url) {
|
|
3520
|
+
return null;
|
|
3521
|
+
}
|
|
3522
|
+
// If you want to allow in [href], [src], [poster], [srcdoc], etc.
|
|
3523
|
+
return this.sanitizer.bypassSecurityTrustResourceUrl(url);
|
|
3524
|
+
}
|
|
3525
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: SafeUrlPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
3526
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.0", ngImport: i0, type: SafeUrlPipe, isStandalone: true, name: "safeUrl" });
|
|
3527
|
+
}
|
|
3528
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: SafeUrlPipe, decorators: [{
|
|
3529
|
+
type: Pipe,
|
|
3530
|
+
args: [{
|
|
3531
|
+
name: 'safeUrl',
|
|
3532
|
+
standalone: true
|
|
3533
|
+
}]
|
|
3534
|
+
}] });
|
|
3535
|
+
|
|
3536
|
+
class PropertyVideoItem {
|
|
3537
|
+
platformId = inject(PLATFORM_ID);
|
|
3538
|
+
el = inject(ElementRef);
|
|
3539
|
+
dialogService = inject(DialogService);
|
|
3540
|
+
myVideo = viewChild('video', ...(ngDevMode ? [{ debugName: "myVideo" }] : []));
|
|
3541
|
+
progress = input(0, ...(ngDevMode ? [{ debugName: "progress" }] : []));
|
|
3542
|
+
video = input.required(...(ngDevMode ? [{ debugName: "video" }] : []));
|
|
3543
|
+
actions = input(true, ...(ngDevMode ? [{ debugName: "actions" }] : []));
|
|
3544
|
+
hasUnsaved = input(false, ...(ngDevMode ? [{ debugName: "hasUnsaved" }] : []));
|
|
3545
|
+
editId = model(...(ngDevMode ? [undefined, { debugName: "editId" }] : []));
|
|
3546
|
+
save = output();
|
|
3547
|
+
cancel = output();
|
|
3548
|
+
delete = output();
|
|
3549
|
+
edit = output();
|
|
3550
|
+
upload = output();
|
|
3551
|
+
editTitle = false;
|
|
3552
|
+
editing = false;
|
|
3553
|
+
onSave(video) {
|
|
3554
|
+
this.editTitle = false;
|
|
3555
|
+
this.editId.set(null);
|
|
3556
|
+
this.save.emit(video);
|
|
3557
|
+
}
|
|
3558
|
+
onCancel(video) {
|
|
3559
|
+
this.editTitle = false;
|
|
3560
|
+
this.editId.set(null);
|
|
3561
|
+
this.cancel.emit(video);
|
|
3562
|
+
}
|
|
3563
|
+
onDelete(video) {
|
|
3564
|
+
this.delete.emit(video);
|
|
3565
|
+
}
|
|
3566
|
+
onEdit(video) {
|
|
3567
|
+
this.editId.set(video.id);
|
|
3568
|
+
this.editTitle = true;
|
|
3569
|
+
this.edit.emit(video);
|
|
3570
|
+
}
|
|
3571
|
+
onMediaEdit(video) {
|
|
3572
|
+
this.editId.set(video.id);
|
|
3573
|
+
this.editing = true;
|
|
3574
|
+
}
|
|
3575
|
+
onUpload(id, data) {
|
|
3576
|
+
this.video().uploading = true;
|
|
3577
|
+
this.upload.emit({ id, data });
|
|
3578
|
+
}
|
|
3579
|
+
onLoadedMetadata(event) {
|
|
3580
|
+
if (this.video().duration) {
|
|
3581
|
+
return;
|
|
3582
|
+
}
|
|
3583
|
+
const videoElement = event.target;
|
|
3584
|
+
this.video().duration = videoElement.duration;
|
|
3585
|
+
}
|
|
3586
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyVideoItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3587
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyVideoItem, isStandalone: true, selector: "rolatech-property-video-item", inputs: { progress: { classPropertyName: "progress", publicName: "progress", isSignal: true, isRequired: false, transformFunction: null }, video: { classPropertyName: "video", publicName: "video", isSignal: true, isRequired: true, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, hasUnsaved: { classPropertyName: "hasUnsaved", publicName: "hasUnsaved", isSignal: true, isRequired: false, transformFunction: null }, editId: { classPropertyName: "editId", publicName: "editId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { editId: "editIdChange", save: "save", cancel: "cancel", delete: "delete", edit: "edit", upload: "upload" }, viewQueries: [{ propertyName: "myVideo", first: true, predicate: ["video"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"flex flex-col grow p-2\">\n @if (!editTitle) {\n <div class=\"w-full flex gap-3 p-3 items-center\">\n <span>{{ video().title }}</span>\n <button mat-icon-button (click)=\"onEdit(video()); $event.stopPropagation()\" class=\"max-w-8 max-h-8 !p-1\">\n <mat-icon>edit</mat-icon>\n </button>\n <button mat-icon-button (click)=\"onDelete(video()); $event.stopPropagation()\" class=\"max-w-8 max-h-8 !p-1\">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n } @else {\n <div class=\"flex flex-col justify-between items-center\">\n <rolatech-input [(title)]=\"video().title\" placeholder=\"Title\"></rolatech-input>\n <div class=\"w-full flex flex-row justify-end p-3 gap-3\">\n <button mat-button class=\"max-h-8\" (click)=\"onCancel(video())\" i18n>Cancel</button>\n <button mat-flat-button class=\"max-h-8\" (click)=\"onSave(video())\" i18n>Save</button>\n </div>\n </div>\n }\n\n <div>\n @if (video().url) {\n <div class=\"flex flex-col p-2 gap-3\">\n <div class=\"bg-black h-fit\">\n <video\n controls\n #videoContainer\n [src]=\"video().url\"\n class=\"w-full aspect-video\"\n (loadedmetadata)=\"onLoadedMetadata($event)\"\n [poster]=\"video().thumbnail\"\n >\n <!-- <source [src]=\"video().url\" type=\"video/mp4\" /> -->\n </video>\n </div>\n <div class=\"flex flex-col justify-between w-full\">\n <div class=\"flex justify-between items-center w-full\">\n @if (video().uploading) {\n <div>\n <span> {{ video().progress }}%</span>\n </div>\n }\n </div>\n <div class=\"flex justify-between items-center\">\n <div>\n <span>{{ video().duration | duration }}</span>\n </div>\n </div>\n </div>\n </div>\n @if (video().uploading) {\n <div class=\"p-2\">\n <mat-progress-bar mode=\"determinate\" [value]=\"video().progress\"> </mat-progress-bar>\n </div>\n } } @else {\n <div class=\"px-3\">\n <input\n class=\"ud-sr-only\"\n type=\"file\"\n accept=\".avi,.mpg,.mpeg,.flv,.mov,.m2v,.m4v,.mp4,.rm,.ram,.vob,.ogv,.webm,.wmv\"\n (change)=\"onUpload(video().id, $event)\"\n #fileInput\n />\n <div class=\"flex justify-between items-center\">\n <div i18n>No videos</div>\n <button mat-flat-button class=\"max-h-8\" (click)=\"fileInput.click()\" i18n>Upload</button>\n </div>\n </div>\n }\n </div>\n @if (!hasUnsaved) {\n <ng-content></ng-content>\n }\n</div>\n", styles: [".ud-sr-only{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: AngularCommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1$4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: i8.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: InputComponent, selector: "rolatech-input", inputs: ["title", "placeholder"], outputs: ["titleChange"] }, { kind: "pipe", type: DurationPipe, name: "duration" }] });
|
|
3588
|
+
}
|
|
3589
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyVideoItem, decorators: [{
|
|
3590
|
+
type: Component,
|
|
3591
|
+
args: [{ selector: 'rolatech-property-video-item', imports: [
|
|
3592
|
+
MatIconModule,
|
|
3593
|
+
AngularCommonModule,
|
|
3594
|
+
FormsModule,
|
|
3595
|
+
MatButtonModule,
|
|
3596
|
+
MatDividerModule,
|
|
3597
|
+
AngularComponentsModule,
|
|
3598
|
+
DurationPipe,
|
|
3599
|
+
InputComponent
|
|
3600
|
+
], template: "<div class=\"flex flex-col grow p-2\">\n @if (!editTitle) {\n <div class=\"w-full flex gap-3 p-3 items-center\">\n <span>{{ video().title }}</span>\n <button mat-icon-button (click)=\"onEdit(video()); $event.stopPropagation()\" class=\"max-w-8 max-h-8 !p-1\">\n <mat-icon>edit</mat-icon>\n </button>\n <button mat-icon-button (click)=\"onDelete(video()); $event.stopPropagation()\" class=\"max-w-8 max-h-8 !p-1\">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n } @else {\n <div class=\"flex flex-col justify-between items-center\">\n <rolatech-input [(title)]=\"video().title\" placeholder=\"Title\"></rolatech-input>\n <div class=\"w-full flex flex-row justify-end p-3 gap-3\">\n <button mat-button class=\"max-h-8\" (click)=\"onCancel(video())\" i18n>Cancel</button>\n <button mat-flat-button class=\"max-h-8\" (click)=\"onSave(video())\" i18n>Save</button>\n </div>\n </div>\n }\n\n <div>\n @if (video().url) {\n <div class=\"flex flex-col p-2 gap-3\">\n <div class=\"bg-black h-fit\">\n <video\n controls\n #videoContainer\n [src]=\"video().url\"\n class=\"w-full aspect-video\"\n (loadedmetadata)=\"onLoadedMetadata($event)\"\n [poster]=\"video().thumbnail\"\n >\n <!-- <source [src]=\"video().url\" type=\"video/mp4\" /> -->\n </video>\n </div>\n <div class=\"flex flex-col justify-between w-full\">\n <div class=\"flex justify-between items-center w-full\">\n @if (video().uploading) {\n <div>\n <span> {{ video().progress }}%</span>\n </div>\n }\n </div>\n <div class=\"flex justify-between items-center\">\n <div>\n <span>{{ video().duration | duration }}</span>\n </div>\n </div>\n </div>\n </div>\n @if (video().uploading) {\n <div class=\"p-2\">\n <mat-progress-bar mode=\"determinate\" [value]=\"video().progress\"> </mat-progress-bar>\n </div>\n } } @else {\n <div class=\"px-3\">\n <input\n class=\"ud-sr-only\"\n type=\"file\"\n accept=\".avi,.mpg,.mpeg,.flv,.mov,.m2v,.m4v,.mp4,.rm,.ram,.vob,.ogv,.webm,.wmv\"\n (change)=\"onUpload(video().id, $event)\"\n #fileInput\n />\n <div class=\"flex justify-between items-center\">\n <div i18n>No videos</div>\n <button mat-flat-button class=\"max-h-8\" (click)=\"fileInput.click()\" i18n>Upload</button>\n </div>\n </div>\n }\n </div>\n @if (!hasUnsaved) {\n <ng-content></ng-content>\n }\n</div>\n", styles: [".ud-sr-only{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}\n"] }]
|
|
3601
|
+
}] });
|
|
3602
|
+
|
|
3603
|
+
class PropertyManageVideoComponent extends BaseComponent {
|
|
3604
|
+
propertyService = inject(PropertyService);
|
|
3605
|
+
tabIndex = signal(0, ...(ngDevMode ? [{ debugName: "tabIndex" }] : []));
|
|
3606
|
+
videos = [];
|
|
3362
3607
|
data;
|
|
3363
3608
|
iframeVisible = false;
|
|
3364
3609
|
iframeLoaded = false;
|
|
3365
|
-
safeURL = this.sanitizer.bypassSecurityTrustResourceUrl('');
|
|
3366
3610
|
thumbnailUrl;
|
|
3367
|
-
|
|
3611
|
+
provider = PropertyVideoProvider;
|
|
3368
3612
|
chunkSize = 5 * 1024 * 1024; // 切片大小
|
|
3613
|
+
selectProvider = '';
|
|
3614
|
+
videoEditId = '';
|
|
3615
|
+
get youtubeVideos() {
|
|
3616
|
+
return this.videos.filter(v => v.provider === PropertyVideoProvider.YOUTUBE);
|
|
3617
|
+
}
|
|
3618
|
+
get cosVideos() {
|
|
3619
|
+
return this.videos.filter(v => v.provider === PropertyVideoProvider.COS);
|
|
3620
|
+
}
|
|
3621
|
+
constructor() {
|
|
3622
|
+
super();
|
|
3623
|
+
effect(() => {
|
|
3624
|
+
const index = this.tabIndex();
|
|
3625
|
+
if (index === 0) {
|
|
3626
|
+
this.selectProvider = 'YOUTUBE';
|
|
3627
|
+
}
|
|
3628
|
+
if (index === 1) {
|
|
3629
|
+
this.selectProvider = 'COS';
|
|
3630
|
+
}
|
|
3631
|
+
});
|
|
3632
|
+
}
|
|
3369
3633
|
ngOnInit() {
|
|
3370
3634
|
this.id = this.route.parent?.snapshot.paramMap.get('id');
|
|
3371
|
-
this.
|
|
3635
|
+
this.getVideos();
|
|
3372
3636
|
}
|
|
3373
|
-
|
|
3374
|
-
this.propertyService.
|
|
3637
|
+
getVideos() {
|
|
3638
|
+
this.propertyService.getVideos(this.id).subscribe({
|
|
3375
3639
|
next: (res) => {
|
|
3376
|
-
this.
|
|
3377
|
-
// this.safeURL = this.sanitizer.bypassSecurityTrustResourceUrl(
|
|
3378
|
-
// `https://www.youtube.com/embed/${this.propertyVideoTour.videoId}`,
|
|
3379
|
-
// );
|
|
3380
|
-
// this.thumbnailUrl = `https://i.ytimg.com/vi/${this.propertyVideoTour.videoId}/hqdefault.jpg`;
|
|
3640
|
+
this.videos = Array.isArray(res.data) ? res.data : [];
|
|
3381
3641
|
},
|
|
3382
3642
|
});
|
|
3383
3643
|
}
|
|
@@ -3387,68 +3647,129 @@ class PropertyManageVideoTourComponent extends BaseComponent {
|
|
|
3387
3647
|
onIframeLoad() {
|
|
3388
3648
|
this.iframeLoaded = true;
|
|
3389
3649
|
}
|
|
3390
|
-
|
|
3391
|
-
const
|
|
3392
|
-
title: 'Add
|
|
3650
|
+
addYoutubeUrl() {
|
|
3651
|
+
const options = {
|
|
3652
|
+
title: 'Add Youtube url',
|
|
3393
3653
|
cancelText: 'Cancel',
|
|
3394
3654
|
confirmText: 'Confirm',
|
|
3395
3655
|
data: {
|
|
3396
|
-
|
|
3656
|
+
url: '',
|
|
3397
3657
|
},
|
|
3398
|
-
component:
|
|
3658
|
+
component: PropertyVideoYoutubeAddComponent,
|
|
3399
3659
|
};
|
|
3400
|
-
this.dialogService.open(
|
|
3660
|
+
this.dialogService.open(options);
|
|
3401
3661
|
this.dialogService.confirmed().subscribe({
|
|
3402
3662
|
next: (res) => {
|
|
3403
3663
|
if (res) {
|
|
3404
3664
|
const data = {
|
|
3405
|
-
|
|
3665
|
+
url: res,
|
|
3666
|
+
title: 'Youtube',
|
|
3667
|
+
provider: PropertyVideoProvider.YOUTUBE
|
|
3406
3668
|
};
|
|
3407
|
-
this.propertyService.
|
|
3669
|
+
this.propertyService.addVideo(this.id, data).subscribe({
|
|
3408
3670
|
next: (res) => {
|
|
3409
|
-
this.
|
|
3410
|
-
this.snackBarService.open('Video
|
|
3671
|
+
this.videos.push(res.data);
|
|
3672
|
+
this.snackBarService.open('Video added');
|
|
3411
3673
|
},
|
|
3412
3674
|
});
|
|
3413
3675
|
}
|
|
3414
3676
|
},
|
|
3415
3677
|
});
|
|
3416
3678
|
}
|
|
3417
|
-
|
|
3418
|
-
const
|
|
3419
|
-
title: 'Update
|
|
3679
|
+
updateYoutubeUrl(video) {
|
|
3680
|
+
const options = {
|
|
3681
|
+
title: 'Update Youtube url',
|
|
3420
3682
|
cancelText: 'Cancel',
|
|
3421
3683
|
confirmText: 'Confirm',
|
|
3422
3684
|
data: {
|
|
3423
|
-
|
|
3685
|
+
url: video?.url || '',
|
|
3424
3686
|
},
|
|
3425
|
-
component:
|
|
3687
|
+
component: PropertyVideoYoutubeAddComponent,
|
|
3426
3688
|
};
|
|
3427
|
-
this.dialogService.open(
|
|
3689
|
+
this.dialogService.open(options);
|
|
3428
3690
|
this.dialogService.confirmed().subscribe({
|
|
3429
3691
|
next: (res) => {
|
|
3430
3692
|
if (res) {
|
|
3431
3693
|
const data = {
|
|
3432
|
-
|
|
3694
|
+
url: res,
|
|
3695
|
+
title: video.title
|
|
3433
3696
|
};
|
|
3434
|
-
this.propertyService.
|
|
3697
|
+
this.propertyService.updateVideo(this.id, video.id, data).subscribe({
|
|
3435
3698
|
next: (res) => {
|
|
3436
|
-
|
|
3437
|
-
|
|
3699
|
+
video.url = res.data.url;
|
|
3700
|
+
// Force reload
|
|
3701
|
+
this.iframeLoaded = false;
|
|
3702
|
+
this.snackBarService.open('Youtube url updated');
|
|
3703
|
+
},
|
|
3704
|
+
});
|
|
3705
|
+
}
|
|
3706
|
+
},
|
|
3707
|
+
});
|
|
3708
|
+
}
|
|
3709
|
+
toYoutubeEmbed(urlOrId) {
|
|
3710
|
+
const m = urlOrId.match(/(?:v=|\/embed\/|\.be\/)([A-Za-z0-9_-]{6,})/);
|
|
3711
|
+
const id = m ? m[1] : urlOrId;
|
|
3712
|
+
return `https://www.youtube-nocookie.com/embed/${id}`;
|
|
3713
|
+
}
|
|
3714
|
+
addCOSVideo() {
|
|
3715
|
+
const video = {
|
|
3716
|
+
provider: PropertyVideoProvider.COS
|
|
3717
|
+
};
|
|
3718
|
+
this.propertyService.addVideo(this.id, video).subscribe({
|
|
3719
|
+
next: (res) => {
|
|
3720
|
+
this.videoEditId = res.data.id;
|
|
3721
|
+
this.videos.push(res.data);
|
|
3722
|
+
},
|
|
3723
|
+
});
|
|
3724
|
+
}
|
|
3725
|
+
onCOSVideoSave(event) {
|
|
3726
|
+
const { id, title, url } = event;
|
|
3727
|
+
const data = {
|
|
3728
|
+
title, url
|
|
3729
|
+
};
|
|
3730
|
+
this.propertyService.updateVideo(this.id, id, data).subscribe({
|
|
3731
|
+
next: (res) => {
|
|
3732
|
+
this.snackBarService.open('Youtube url updated');
|
|
3733
|
+
},
|
|
3734
|
+
});
|
|
3735
|
+
}
|
|
3736
|
+
onCOSVideoDelete(video, event) {
|
|
3737
|
+
if (!video.id) {
|
|
3738
|
+
return;
|
|
3739
|
+
}
|
|
3740
|
+
const options = {
|
|
3741
|
+
title: 'Confirm delete',
|
|
3742
|
+
message: 'Are you sure?',
|
|
3743
|
+
cancelText: 'Cancel',
|
|
3744
|
+
confirmText: 'Ok',
|
|
3745
|
+
};
|
|
3746
|
+
this.dialogService.open(options);
|
|
3747
|
+
this.dialogService.confirmed().subscribe({
|
|
3748
|
+
next: (res) => {
|
|
3749
|
+
if (res) {
|
|
3750
|
+
this.propertyService.deleteVideo(this.id, video.id).subscribe({
|
|
3751
|
+
next: res => {
|
|
3752
|
+
this.videos = this.videos.filter(v => v.id !== video.id);
|
|
3753
|
+
this.snackBarService.open("Video deleted");
|
|
3754
|
+
},
|
|
3755
|
+
error: (error) => {
|
|
3756
|
+
this.snackBarService.open(error.message);
|
|
3438
3757
|
},
|
|
3439
3758
|
});
|
|
3440
3759
|
}
|
|
3441
3760
|
},
|
|
3442
3761
|
});
|
|
3443
3762
|
}
|
|
3444
|
-
|
|
3763
|
+
onVideoEdit(event) { }
|
|
3764
|
+
onMediaDelete(video, event) { }
|
|
3765
|
+
onCOSVideoUpload(video, event) {
|
|
3445
3766
|
const file = event.data.target.files[0];
|
|
3446
3767
|
if (!file) {
|
|
3447
3768
|
return;
|
|
3448
3769
|
}
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3770
|
+
video.url = URL.createObjectURL(file);
|
|
3771
|
+
video.progress = 0;
|
|
3772
|
+
video.uploading = true;
|
|
3452
3773
|
const reader = new FileReader();
|
|
3453
3774
|
if (reader.readyState === FileReader.EMPTY) {
|
|
3454
3775
|
reader.onload = async (e) => {
|
|
@@ -3456,10 +3777,10 @@ class PropertyManageVideoTourComponent extends BaseComponent {
|
|
|
3456
3777
|
crypto.subtle.digest('SHA-256', fileBuffer).then((res) => {
|
|
3457
3778
|
const hashArray = Array.from(new Uint8Array(res));
|
|
3458
3779
|
const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
3459
|
-
const data = { hash: hashHex, filename: file.name, fileType: file.type };
|
|
3460
|
-
this.propertyService.
|
|
3780
|
+
const data = { hash: hashHex, filename: file.name, fileType: file.type, type: 'COS' };
|
|
3781
|
+
this.propertyService.uploadVideosInit(this.id, data).subscribe({
|
|
3461
3782
|
next: (res) => {
|
|
3462
|
-
this.uploadPart(
|
|
3783
|
+
this.uploadPart(video, res.data.uploadId, file);
|
|
3463
3784
|
},
|
|
3464
3785
|
error: (e) => { },
|
|
3465
3786
|
});
|
|
@@ -3469,34 +3790,33 @@ class PropertyManageVideoTourComponent extends BaseComponent {
|
|
|
3469
3790
|
reader.readAsArrayBuffer(file);
|
|
3470
3791
|
}
|
|
3471
3792
|
}
|
|
3472
|
-
uploadPart(
|
|
3793
|
+
uploadPart(video, uploadId, file) {
|
|
3473
3794
|
let uploadedCount = 0;
|
|
3474
3795
|
const fileChunkList = this.createFileChunk(file);
|
|
3475
3796
|
const numberOfChunks = fileChunkList.length;
|
|
3476
3797
|
from(fileChunkList)
|
|
3477
|
-
.pipe(concatMap((val, index) => this.uploadFile(
|
|
3798
|
+
.pipe(concatMap((val, index) => this.uploadFile(video, val.file, index, uploadId)), take(numberOfChunks))
|
|
3478
3799
|
.subscribe((res) => {
|
|
3479
3800
|
uploadedCount++;
|
|
3480
3801
|
const p = ((uploadedCount / numberOfChunks) * 100).toFixed(0);
|
|
3481
|
-
|
|
3802
|
+
video.progress = parseFloat(p);
|
|
3482
3803
|
if (uploadedCount === numberOfChunks) {
|
|
3483
|
-
this.completePartUpload(
|
|
3804
|
+
this.completePartUpload(video, { uploadId });
|
|
3484
3805
|
}
|
|
3485
3806
|
});
|
|
3486
3807
|
}
|
|
3487
|
-
completePartUpload(
|
|
3488
|
-
data.duration =
|
|
3489
|
-
this.propertyService.completePartUpload(
|
|
3808
|
+
completePartUpload(video, data) {
|
|
3809
|
+
data.duration = video.duration;
|
|
3810
|
+
this.propertyService.completePartUpload(video.id || '', data).subscribe({
|
|
3490
3811
|
next: (res) => {
|
|
3491
|
-
|
|
3492
|
-
lecture.item.id = res.data.id;
|
|
3812
|
+
video.uploading = false;
|
|
3493
3813
|
},
|
|
3494
3814
|
error: (e) => {
|
|
3495
3815
|
this.snackBarService.open('Upload failed: ' + e.message);
|
|
3496
3816
|
},
|
|
3497
3817
|
});
|
|
3498
3818
|
}
|
|
3499
|
-
uploadFile(
|
|
3819
|
+
uploadFile(property, file, index, uploadId) {
|
|
3500
3820
|
const reader = new FileReader();
|
|
3501
3821
|
return new Observable((observer) => {
|
|
3502
3822
|
reader.readAsArrayBuffer(file);
|
|
@@ -3510,7 +3830,8 @@ class PropertyManageVideoTourComponent extends BaseComponent {
|
|
|
3510
3830
|
formData.append('uploadId', uploadId);
|
|
3511
3831
|
formData.append('number', index + 1);
|
|
3512
3832
|
formData.append('hash', hashHex);
|
|
3513
|
-
|
|
3833
|
+
formData.append('type', 'COS');
|
|
3834
|
+
this.propertyService.uploadVideosPartsToProperty(property.id, formData).subscribe({
|
|
3514
3835
|
next: (res) => {
|
|
3515
3836
|
observer.next(res);
|
|
3516
3837
|
observer.complete();
|
|
@@ -3537,12 +3858,91 @@ class PropertyManageVideoTourComponent extends BaseComponent {
|
|
|
3537
3858
|
}
|
|
3538
3859
|
return fileChunkList;
|
|
3539
3860
|
}
|
|
3540
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type:
|
|
3541
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type:
|
|
3861
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageVideoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3862
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyManageVideoComponent, isStandalone: true, selector: "rolatech-property-manage-video", usesInheritance: true, ngImport: i0, template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"Videos\" class=\"hidden md:block\" divider> </rolatech-toolbar>\n <rolatech-tabs [(select)]=\"tabIndex\">\n <rolatech-tab label=\"Youtube\"></rolatech-tab>\n <rolatech-tab label=\"COS\"></rolatech-tab>\n </rolatech-tabs>\n <div class=\"py-2\">\n @if (tabIndex() === 0) {\n @if (youtubeVideos.length > 0 && youtubeVideos[0].url) {\n <div class=\"relative w-full aspect-video\">\n @if (!iframeLoaded) {\n <div class=\"absolute inset-0 flex items-center justify-center bg-black/10 border bg-white\">\n <span>Loading...</span>\n </div>\n }\n <iframe\n [src]=\"toYoutubeEmbed(youtubeVideos[0].url) | safeUrl\"\n frameborder=\"0\"\n allowfullscreen\n class=\"w-full h-full\"\n (load)=\"iframeLoaded = true\"\n ></iframe>\n </div>\n <button mat-flat-button (click)=\"updateYoutubeUrl(youtubeVideos[0])\" class=\"mt-3\">Update Youtube url</button>\n } @else {\n <button mat-flat-button (click)=\"addYoutubeUrl()\" class=\"mt-3\">Add Youtube url</button>\n }\n }\n @if (tabIndex() === 1) {\n @for (video of cosVideos; track $index) {\n <rolatech-property-video-item\n [video]=\"video\"\n (save)=\"onCOSVideoSave($event)\"\n (delete)=\"onCOSVideoDelete(video, $event)\"\n (edit)=\"onVideoEdit($event)\"\n (upload)=\"onCOSVideoUpload(video, $event)\"\n [editId]=\"videoEditId\"\n ></rolatech-property-video-item>\n }\n\n <div class=\"p-3\">\n <button mat-flat-button class=\"max-h-8\" (click)=\"addCOSVideo()\">\n <mat-icon>add</mat-icon>\n <span>Add video</span>\n </button>\n </div>\n <!-- <rolatech-video-upload (upload)=\"onMediaUploadInit($event)\"></rolatech-video-upload> -->\n }\n </div>\n</rolatech-property-manage-content>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: PropertyManageContentComponent, selector: "rolatech-property-manage-content" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: TabsComponent, selector: "rolatech-tabs", inputs: ["select", "loading"], outputs: ["selectChange"] }, { kind: "component", type: TabComponent, selector: "rolatech-tab", inputs: ["label"] }, { kind: "component", type: PropertyVideoItem, selector: "rolatech-property-video-item", inputs: ["progress", "video", "actions", "hasUnsaved", "editId"], outputs: ["editIdChange", "save", "cancel", "delete", "edit", "upload"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: SafeUrlPipe, name: "safeUrl" }] });
|
|
3542
3863
|
}
|
|
3543
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type:
|
|
3864
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageVideoComponent, decorators: [{
|
|
3544
3865
|
type: Component,
|
|
3545
|
-
args: [{ selector: 'rolatech-property-manage-video
|
|
3866
|
+
args: [{ selector: 'rolatech-property-manage-video', imports: [CommonModule, ToolbarComponent, PropertyManageContentComponent, MatButtonModule, TabsComponent, TabComponent, SafeUrlPipe, PropertyVideoItem, MatIcon], template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"Videos\" class=\"hidden md:block\" divider> </rolatech-toolbar>\n <rolatech-tabs [(select)]=\"tabIndex\">\n <rolatech-tab label=\"Youtube\"></rolatech-tab>\n <rolatech-tab label=\"COS\"></rolatech-tab>\n </rolatech-tabs>\n <div class=\"py-2\">\n @if (tabIndex() === 0) {\n @if (youtubeVideos.length > 0 && youtubeVideos[0].url) {\n <div class=\"relative w-full aspect-video\">\n @if (!iframeLoaded) {\n <div class=\"absolute inset-0 flex items-center justify-center bg-black/10 border bg-white\">\n <span>Loading...</span>\n </div>\n }\n <iframe\n [src]=\"toYoutubeEmbed(youtubeVideos[0].url) | safeUrl\"\n frameborder=\"0\"\n allowfullscreen\n class=\"w-full h-full\"\n (load)=\"iframeLoaded = true\"\n ></iframe>\n </div>\n <button mat-flat-button (click)=\"updateYoutubeUrl(youtubeVideos[0])\" class=\"mt-3\">Update Youtube url</button>\n } @else {\n <button mat-flat-button (click)=\"addYoutubeUrl()\" class=\"mt-3\">Add Youtube url</button>\n }\n }\n @if (tabIndex() === 1) {\n @for (video of cosVideos; track $index) {\n <rolatech-property-video-item\n [video]=\"video\"\n (save)=\"onCOSVideoSave($event)\"\n (delete)=\"onCOSVideoDelete(video, $event)\"\n (edit)=\"onVideoEdit($event)\"\n (upload)=\"onCOSVideoUpload(video, $event)\"\n [editId]=\"videoEditId\"\n ></rolatech-property-video-item>\n }\n\n <div class=\"p-3\">\n <button mat-flat-button class=\"max-h-8\" (click)=\"addCOSVideo()\">\n <mat-icon>add</mat-icon>\n <span>Add video</span>\n </button>\n </div>\n <!-- <rolatech-video-upload (upload)=\"onMediaUploadInit($event)\"></rolatech-video-upload> -->\n }\n </div>\n</rolatech-property-manage-content>\n" }]
|
|
3867
|
+
}], ctorParameters: () => [] });
|
|
3868
|
+
|
|
3869
|
+
class PropertyManageHighlights extends BaseComponent {
|
|
3870
|
+
propertyService = inject(PropertyService);
|
|
3871
|
+
highlights = [];
|
|
3872
|
+
ngOnInit() {
|
|
3873
|
+
this.id = this.route.parent?.snapshot.paramMap.get('id');
|
|
3874
|
+
this.find();
|
|
3875
|
+
}
|
|
3876
|
+
find() {
|
|
3877
|
+
this.propertyService.getHighlights(this.id).subscribe({
|
|
3878
|
+
next: (res) => {
|
|
3879
|
+
this.highlights = res.data;
|
|
3880
|
+
}
|
|
3881
|
+
});
|
|
3882
|
+
}
|
|
3883
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageHighlights, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3884
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyManageHighlights, isStandalone: true, selector: "rolatech-property-manage-highlights", usesInheritance: true, ngImport: i0, template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"Highlights\" class=\"hidden md:block\" divider></rolatech-toolbar>\n <div>\n @for (item of highlights; track $index) {\n <div class=\"font-bold p-1\">{{item}}</div>\n }\n </div>\n</rolatech-property-manage-content>\n", styles: [""], dependencies: [{ kind: "component", type: PropertyManageContentComponent, selector: "rolatech-property-manage-content" }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }] });
|
|
3885
|
+
}
|
|
3886
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageHighlights, decorators: [{
|
|
3887
|
+
type: Component,
|
|
3888
|
+
args: [{ selector: 'rolatech-property-manage-highlights', imports: [PropertyManageContentComponent, ToolbarComponent], template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"Highlights\" class=\"hidden md:block\" divider></rolatech-toolbar>\n <div>\n @for (item of highlights; track $index) {\n <div class=\"font-bold p-1\">{{item}}</div>\n }\n </div>\n</rolatech-property-manage-content>\n" }]
|
|
3889
|
+
}] });
|
|
3890
|
+
|
|
3891
|
+
class PropertyManageEpc extends BaseComponent {
|
|
3892
|
+
propertyService = inject(PropertyService);
|
|
3893
|
+
currentRating = '';
|
|
3894
|
+
potentialRating = '';
|
|
3895
|
+
currentScore = 0;
|
|
3896
|
+
potentialScore = 0;
|
|
3897
|
+
ngOnInit() {
|
|
3898
|
+
this.id = this.route.parent?.snapshot.paramMap.get('id');
|
|
3899
|
+
this.get();
|
|
3900
|
+
}
|
|
3901
|
+
get() {
|
|
3902
|
+
this.propertyService.getEpc(this.id).subscribe({
|
|
3903
|
+
next: (res) => {
|
|
3904
|
+
this.currentScore = res.data.currentScore || 0;
|
|
3905
|
+
this.potentialScore = res.data.potentialScore || 0;
|
|
3906
|
+
}
|
|
3907
|
+
});
|
|
3908
|
+
}
|
|
3909
|
+
add() {
|
|
3910
|
+
const data = {
|
|
3911
|
+
currentScore: this.currentScore,
|
|
3912
|
+
potentialScore: this.potentialScore
|
|
3913
|
+
};
|
|
3914
|
+
this.propertyService.addEpc(this.id, data).subscribe({
|
|
3915
|
+
next: res => {
|
|
3916
|
+
this.snackBarService.open("EPC Added");
|
|
3917
|
+
}
|
|
3918
|
+
});
|
|
3919
|
+
}
|
|
3920
|
+
update() {
|
|
3921
|
+
const data = {
|
|
3922
|
+
currentScore: this.currentScore,
|
|
3923
|
+
potentialScore: this.potentialScore
|
|
3924
|
+
};
|
|
3925
|
+
this.propertyService.updateEpc(this.id, data).subscribe({
|
|
3926
|
+
next: res => {
|
|
3927
|
+
this.snackBarService.open("EPC Updated");
|
|
3928
|
+
}
|
|
3929
|
+
});
|
|
3930
|
+
}
|
|
3931
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageEpc, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3932
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.0", type: PropertyManageEpc, isStandalone: true, selector: "rolatech-property-manage-epc", usesInheritance: true, ngImport: i0, template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"EPC\" class=\"hidden md:block\" divider></rolatech-toolbar>\n <div class=\"w-full md:max-w-[70%]\">\n <div class=\"p-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label>Current Score</mat-label>\n <input matInput [(ngModel)]=\"currentScore\" placeholder=\"Current Score\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>Potential Score</mat-label>\n <input matInput [(ngModel)]=\"potentialScore\" placeholder=\"Potential Score\" />\n </mat-form-field>\n <button mat-flat-button (click)=\"add()\">Save</button>\n </div>\n <div>\n <div class=\"font-bold text-lg p-2\">Domestic EPC</div>\n <rolatech-epc-chart\n [currentScore]=\"currentScore\"\n [potentialScore]=\"potentialScore\"\n [showCaptions]=\"true\"\n ></rolatech-epc-chart>\n </div>\n </div>\n</rolatech-property-manage-content>\n", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "component", type: PropertyManageContentComponent, selector: "rolatech-property-manage-content" }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: EpcChart, selector: "rolatech-epc-chart", inputs: ["currentScore", "potentialScore", "showCaptions"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }] });
|
|
3933
|
+
}
|
|
3934
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageEpc, decorators: [{
|
|
3935
|
+
type: Component,
|
|
3936
|
+
args: [{ selector: 'rolatech-property-manage-epc', imports: [PropertyManageContentComponent, ToolbarComponent, EpcChart, MatFormFieldModule, FormsModule, MatInputModule, MatButtonModule], template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"EPC\" class=\"hidden md:block\" divider></rolatech-toolbar>\n <div class=\"w-full md:max-w-[70%]\">\n <div class=\"p-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label>Current Score</mat-label>\n <input matInput [(ngModel)]=\"currentScore\" placeholder=\"Current Score\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>Potential Score</mat-label>\n <input matInput [(ngModel)]=\"potentialScore\" placeholder=\"Potential Score\" />\n </mat-form-field>\n <button mat-flat-button (click)=\"add()\">Save</button>\n </div>\n <div>\n <div class=\"font-bold text-lg p-2\">Domestic EPC</div>\n <rolatech-epc-chart\n [currentScore]=\"currentScore\"\n [potentialScore]=\"potentialScore\"\n [showCaptions]=\"true\"\n ></rolatech-epc-chart>\n </div>\n </div>\n</rolatech-property-manage-content>\n", styles: ["mat-form-field{width:100%}\n"] }]
|
|
3937
|
+
}] });
|
|
3938
|
+
|
|
3939
|
+
class PropertyManageTranslation {
|
|
3940
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageTranslation, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3941
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.0", type: PropertyManageTranslation, isStandalone: true, selector: "rolatech-property-manage-translation", ngImport: i0, template: "<p>property-manage-translation works!</p>\n", styles: [""] });
|
|
3942
|
+
}
|
|
3943
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageTranslation, decorators: [{
|
|
3944
|
+
type: Component,
|
|
3945
|
+
args: [{ selector: 'rolatech-property-manage-translation', imports: [], template: "<p>property-manage-translation works!</p>\n" }]
|
|
3546
3946
|
}] });
|
|
3547
3947
|
|
|
3548
3948
|
const propertyManageRoutes = [
|
|
@@ -3567,8 +3967,8 @@ const propertyManageRoutes = [
|
|
|
3567
3967
|
component: PropertyManageMediaComponent,
|
|
3568
3968
|
},
|
|
3569
3969
|
{
|
|
3570
|
-
path: '
|
|
3571
|
-
component:
|
|
3970
|
+
path: 'videos',
|
|
3971
|
+
component: PropertyManageVideoComponent,
|
|
3572
3972
|
},
|
|
3573
3973
|
{
|
|
3574
3974
|
path: 'sections',
|
|
@@ -3582,6 +3982,18 @@ const propertyManageRoutes = [
|
|
|
3582
3982
|
path: 'features',
|
|
3583
3983
|
component: PropertyManageFeaturesComponent,
|
|
3584
3984
|
},
|
|
3985
|
+
{
|
|
3986
|
+
path: 'highlights',
|
|
3987
|
+
component: PropertyManageHighlights,
|
|
3988
|
+
},
|
|
3989
|
+
{
|
|
3990
|
+
path: 'epc',
|
|
3991
|
+
component: PropertyManageEpc,
|
|
3992
|
+
},
|
|
3993
|
+
{
|
|
3994
|
+
path: 'translation',
|
|
3995
|
+
component: PropertyManageTranslation,
|
|
3996
|
+
},
|
|
3585
3997
|
// {
|
|
3586
3998
|
// path: 'amenities',
|
|
3587
3999
|
// component: PropertyManageAmenitiesComponent,
|
|
@@ -3696,7 +4108,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImpor
|
|
|
3696
4108
|
const propertyManageViewingsRoutes = [
|
|
3697
4109
|
{
|
|
3698
4110
|
path: '',
|
|
3699
|
-
loadComponent: () => import('./rolatech-angular-property-property-manage-viewings-index.component-
|
|
4111
|
+
loadComponent: () => import('./rolatech-angular-property-property-manage-viewings-index.component-Bk02i8QS.mjs').then((x) => x.PropertyManageViewingsIndexComponent),
|
|
3700
4112
|
},
|
|
3701
4113
|
{
|
|
3702
4114
|
path: ':id',
|
|
@@ -3942,7 +4354,7 @@ class LettingManageDetail extends BaseComponent {
|
|
|
3942
4354
|
// const updatedCriteria = matchingVariant ? updateCriteriaFromVariant(matchingVariant) : [];
|
|
3943
4355
|
}
|
|
3944
4356
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: LettingManageDetail, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3945
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: LettingManageDetail, isStandalone: true, selector: "rolatech-letting-manage-detail", usesInheritance: true, ngImport: i0, template: "@if (property) {\n<rolatech-container>\n <div class=\"flex flex-col w-full\">\n <div class=\"py-3\">\n <rolatech-property-media [media]=\"property.media\"></rolatech-property-media>\n </div>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-features [features]=\"property.features\"></rolatech-property-features>\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n @if (property.
|
|
4357
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: LettingManageDetail, isStandalone: true, selector: "rolatech-letting-manage-detail", usesInheritance: true, ngImport: i0, template: "@if (property) {\n<rolatech-container>\n <div class=\"flex flex-col w-full\">\n <div class=\"py-3\">\n <rolatech-property-media [media]=\"property.media\"></rolatech-property-media>\n </div>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-features [features]=\"property.features\"></rolatech-property-features>\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n @if (property.videos) {\n <rolatech-property-video [video]=\"property.videos[0]\"></rolatech-property-video>\n }\n <div class=\"flex flex-col\">\n <div class=\"text-2xl font-bold pt-3\" i18n>Sections</div>\n @for (section of property.sections; track $index) {\n <rolatech-property-section [section]=\"section\"></rolatech-property-section>\n }\n </div>\n </div>\n <div class=\"w-full h-fit md:w-1/3 rounded-md border shadow p-3\">\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n subtitle=\"PrimeCase Agent\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-pricing (wish)=\"onWish($event)\" [property]=\"property\"></rolatech-property-pricing>\n <rolatech-letting-actions\n [letting]=\"property\"\n (offer)=\"onOffer($event)\"\n (deposit)=\"onOffer($event)\"\n (requestViewing)=\"onRequestViewing($event)\"\n >\n @if (user) {\n <rolatech-letting-action-contact [phone]=\"user.phone\"></rolatech-letting-action-contact>\n }\n </rolatech-letting-actions>\n </div>\n </div>\n </div>\n</rolatech-container>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: PropertyInfoComponent, selector: "rolatech-property-info", inputs: ["property", "inWishList"], outputs: ["wish"] }, { kind: "component", type: PropertyMediaComponent, selector: "rolatech-property-media", inputs: ["media", "min"] }, { kind: "component", type: PropertyPricingComponent, selector: "rolatech-property-pricing", inputs: ["property", "price"] }, { kind: "component", type: PropertySectionComponent, selector: "rolatech-property-section", inputs: ["section", "user", "username"] }, { kind: "component", type: LettingActions, selector: "rolatech-letting-actions", inputs: ["letting"], outputs: ["requestViewing", "offer", "deposit"] }, { kind: "component", type: LettingActionContact, selector: "rolatech-letting-action-contact", inputs: ["phone"], outputs: ["callAgent", "emailAgent"] }, { kind: "component", type: PropertyLocationComponent, selector: "rolatech-property-location", inputs: ["location"] }, { kind: "component", type: PropertyFeaturesComponent, selector: "rolatech-property-features", inputs: ["features"] }, { kind: "component", type: PropertyVideoComponent, selector: "rolatech-property-video", inputs: ["video"] }, { kind: "component", type: PropertyAgentRenderer, selector: "rolatech-property-agent-renderer", inputs: ["name", "avatar", "username", "subtitle"] }] });
|
|
3946
4358
|
}
|
|
3947
4359
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: LettingManageDetail, decorators: [{
|
|
3948
4360
|
type: Component,
|
|
@@ -3958,9 +4370,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImpor
|
|
|
3958
4370
|
LettingActionContact,
|
|
3959
4371
|
PropertyLocationComponent,
|
|
3960
4372
|
PropertyFeaturesComponent,
|
|
3961
|
-
|
|
4373
|
+
PropertyVideoComponent,
|
|
3962
4374
|
PropertyAgentRenderer
|
|
3963
|
-
], template: "@if (property) {\n<rolatech-container>\n <div class=\"flex flex-col w-full\">\n <div class=\"py-3\">\n <rolatech-property-media [media]=\"property.media\"></rolatech-property-media>\n </div>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-features [features]=\"property.features\"></rolatech-property-features>\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n @if (property.
|
|
4375
|
+
], template: "@if (property) {\n<rolatech-container>\n <div class=\"flex flex-col w-full\">\n <div class=\"py-3\">\n <rolatech-property-media [media]=\"property.media\"></rolatech-property-media>\n </div>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-features [features]=\"property.features\"></rolatech-property-features>\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n @if (property.videos) {\n <rolatech-property-video [video]=\"property.videos[0]\"></rolatech-property-video>\n }\n <div class=\"flex flex-col\">\n <div class=\"text-2xl font-bold pt-3\" i18n>Sections</div>\n @for (section of property.sections; track $index) {\n <rolatech-property-section [section]=\"section\"></rolatech-property-section>\n }\n </div>\n </div>\n <div class=\"w-full h-fit md:w-1/3 rounded-md border shadow p-3\">\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n subtitle=\"PrimeCase Agent\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-pricing (wish)=\"onWish($event)\" [property]=\"property\"></rolatech-property-pricing>\n <rolatech-letting-actions\n [letting]=\"property\"\n (offer)=\"onOffer($event)\"\n (deposit)=\"onOffer($event)\"\n (requestViewing)=\"onRequestViewing($event)\"\n >\n @if (user) {\n <rolatech-letting-action-contact [phone]=\"user.phone\"></rolatech-letting-action-contact>\n }\n </rolatech-letting-actions>\n </div>\n </div>\n </div>\n</rolatech-container>\n}\n" }]
|
|
3964
4376
|
}], ctorParameters: () => [] });
|
|
3965
4377
|
|
|
3966
4378
|
const MY_FORMATS$1 = {
|
|
@@ -4309,5 +4721,5 @@ const tenantManageRoutes = [
|
|
|
4309
4721
|
* Generated bundle index. Do not edit.
|
|
4310
4722
|
*/
|
|
4311
4723
|
|
|
4312
|
-
export { AdverseCreditStatus as A, EmploymentStatus as E,
|
|
4313
|
-
//# sourceMappingURL=rolatech-angular-property-rolatech-angular-property-
|
|
4724
|
+
export { AdverseCreditStatus as A, EmploymentStatus as E, PropertyUtil as P, ResidencyStatus as R, ViewingTime as V, PropertyViewType as a, PropertyViewingItemComponent as b, propertyManageOffersRoutes as c, propertyRoutes as d, propertyManageRoutes as e, featureManageRoutes as f, propertyManageViewingsRoutes as g, PropertyActionsComponent as h, PropertyItemComponent as i, PropertyPricingComponent as j, PropertyPriceType as k, lettingManageRoutes as l, PropertyVideoProvider as m, PropertyStatus as n, PropertyType as o, propertyReviewRoutes as p, PropertyInventoryStatus as q, PropertyScope as r, PropertyViewingStatus as s, tenantManageRoutes as t, PropertyViewerCategory as u, PropertyOfferTimelineStatus as v, PropertyOfferType as w, PropertyOfferStatus as x, PropertyApplicantType as y };
|
|
4725
|
+
//# sourceMappingURL=rolatech-angular-property-rolatech-angular-property-nGHNbG8j.mjs.map
|