${propertyName}
${location}
@@ -2194,7 +2071,7 @@ export default class PropertyTemplateSelector extends LightningElement {
-
Basic Information
+
Basic Information
Property Type: ${propertyType}
Status: ${status}
@@ -2207,7 +2084,7 @@ export default class PropertyTemplateSelector extends LightningElement {
-
Contact Details
+
Contact Details
Name: ${data.contactName || 'N/A'}
Email: ${data.contactEmail || 'N/A'}
@@ -2217,7 +2094,7 @@ export default class PropertyTemplateSelector extends LightningElement {
-
Location Details
+
Location Details
City (Bayut): ${data.cityBayut || 'N/A'}
City (Propertyfinder): ${data.cityPropertyfinder || 'N/A'}
@@ -2232,7 +2109,7 @@ export default class PropertyTemplateSelector extends LightningElement {
-
Specifications
+
Specifications
Bedrooms: ${bedrooms}
Bathrooms: ${bathrooms}
@@ -2242,10 +2119,9 @@ export default class PropertyTemplateSelector extends LightningElement {
Floor: ${data.floor || 'N/A'}
-
-
Pricing Information
+
Pricing Information
Rent Price: ${rentPriceMin}
Sale Price: ${salePriceMin}
@@ -2256,7 +2132,7 @@ export default class PropertyTemplateSelector extends LightningElement {
-
Rent Availability
+
Rent Availability
Rent Available From: ${data.rentAvailableFrom || 'N/A'}
Rent Available To: ${data.rentAvailableTo || 'N/A'}
@@ -2265,7 +2141,7 @@ export default class PropertyTemplateSelector extends LightningElement {
-
Property Description
+
Property Description
${titleEnglish}
@@ -2274,17 +2150,17 @@ export default class PropertyTemplateSelector extends LightningElement {
-
Property Type: ${propertyType}
-
Status: ${status}
-
Furnished: ${furnished}
-
Build Year: ${buildYear}
+
Property Type: ${propertyType}
+
Status: ${status}
+
Furnished: ${furnished}
+
Build Year: ${buildYear}
-
Amenities & Features
+
Amenities & Features
Parking Spaces: ${data.parkingSpaces || 'N/A'}
Furnished: ${data.furnished || 'N/A'}
@@ -2293,21 +2169,14 @@ export default class PropertyTemplateSelector extends LightningElement {
-
-
Property Gallery
+
Property Gallery
- ${this.generatePropertyGalleryHTML()}
+ ${firstChunk.length > 0 ? this.generatePropertyGalleryHTMLForImages(firstChunk) : this.generatePropertyGalleryHTML()}
-
-
-
-
Custom Content Area
-
This is a blank template that you can customize with your own content.
-
Add images, text, and styling to create your perfect property brochure.
-
+ ${additionalGalleryPagesHTML}
`;
}
@@ -2334,26 +2203,6 @@ export default class PropertyTemplateSelector extends LightningElement {
const allGalleryImages = this.realPropertyImages || [];
const firstGalleryCount = Math.min(4, allGalleryImages.length);
const firstPageImages = allGalleryImages.slice(0, firstGalleryCount);
- let additionalGalleryPagesHTML = '';
- if (allGalleryImages.length > firstGalleryCount) {
- const remainingImages = allGalleryImages.slice(firstGalleryCount);
- const imagesPerPage = 8;
- for (let start = 0; start < remainingImages.length; start += imagesPerPage) {
- const chunk = remainingImages.slice(start, start + imagesPerPage);
- additionalGalleryPagesHTML += `
-
-
-
-
-
- ${this.generatePropertyGalleryHTMLForImages(chunk)}
-
-
-
-
-
`;
- }
- }
const propertyGallery = this.generatePropertyGalleryHTML();
const interiorImage = this.getSmartImageForSection('interior', 'https://images.unsplash.com/photo-1616486338812-3dadae4b4ace?ixlib=rb-4.0.3&q=85&fm=jpg&crop=entropy&cs=srgb&w=1200');
const kitchenImage = this.getSmartImageForSection('kitchen', 'https://images.unsplash.com/photo-1556909114-f6e7ad7d3136?ixlib=rb-4.0.3&q=85&fm=jpg&crop=entropy&cs=srgb&w=1200');
@@ -2443,7 +2292,6 @@ export default class PropertyTemplateSelector extends LightningElement {
createCoreshiftTemplate() {
return `
Commercial PropertiesCommercial Properties Template
Unlock Your Business Potential
`;
}
-
createModernHomeTemplate() {
const data = this.propertyData || {};
@@ -2638,7 +2486,6 @@ export default class PropertyTemplateSelector extends LightningElement {
const ownerName = data.Owner_Name__c || data.ownerName || "John & Jane Doe";
const ownerPhone = data.Owner_Phone__c || data.ownerPhone || "(555) 111-2222";
const ownerEmail = data.Owner_Email__c || data.ownerEmail || "owner@email.com";
-
// Get smart images
const exteriorImage = this.getExteriorImageUrl();
const interiorImage1 = this.getSmartImageForSection('interior', 'https://images.unsplash.com/photo-1616486338812-3dadae4b4ace?ixlib=rb-4.0.3&q=85&fm=jpg&crop=entropy&cs=srgb&w=1200');
@@ -2838,7 +2685,6 @@ export default class PropertyTemplateSelector extends LightningElement {
content: ''; position: absolute; bottom: 0; left: 0;
width: 50px; height: 3px; background-color: var(--color-accent-gold);
}
-
.main-content { flex-grow: 1; }
.page-footer {
@@ -3004,7 +2850,6 @@ export default class PropertyTemplateSelector extends LightningElement {
-
@@ -3155,7 +3000,6 @@ export default class PropertyTemplateSelector extends LightningElement {
`;
}
-
createLuxuryMansionTemplate() {
const data = this.propertyData || {};
@@ -3351,7 +3195,6 @@ export default class PropertyTemplateSelector extends LightningElement {
color: var(--color-text-primary);
margin: 20px 0;
}
-
.p1-address {
font-size: 1rem;
color: var(--color-text-secondary);
@@ -3551,7 +3394,6 @@ export default class PropertyTemplateSelector extends LightningElement {
column-count: 2;
column-gap: 40px;
}
-
.amenities-list li {
margin-bottom: 12px;
color: var(--color-text-secondary);
@@ -3688,7 +3530,7 @@ export default class PropertyTemplateSelector extends LightningElement {
${propertyName}
A Sanctuary of Modern Design
-
${description}
+ ${description}
@@ -3719,7 +3561,6 @@ export default class PropertyTemplateSelector extends LightningElement {
Acres
-
Property Details
@@ -3839,10 +3680,7 @@ export default class PropertyTemplateSelector extends LightningElement {
${propertyName} - Property Gallery
-
-
-
-
+ ${propertyGallery}
@@ -3923,7 +3761,6 @@ export default class PropertyTemplateSelector extends LightningElement {
this.showSuccess('Template saved successfully');
}
}
-
handleReset() {
// Reload the template
this.loadTemplateInStep3();
@@ -4043,73 +3880,162 @@ export default class PropertyTemplateSelector extends LightningElement {
return true;
}
- // NEW CLEAN BULLET FUNCTION
+ // ENHANCED BULLET FUNCTION
handleBulletList() {
const editorContent = this.template.querySelector('.enhanced-editor-content');
- if (!editorContent) { this.showError('Editor not found'); return; }
+ if (!editorContent) {
+ this.showError('Editor not found');
+ return;
+ }
+
editorContent.focus();
- const ok = document.execCommand('insertUnorderedList', false, null);
- if (!ok) {
+
const selection = window.getSelection();
- if (selection.rangeCount) {
+ if (!selection.rangeCount) {
+ // No selection, create a new list at the end
+ const ul = document.createElement('ul');
+ const li = document.createElement('li');
+ li.innerHTML = ' ';
+ ul.appendChild(li);
+ editorContent.appendChild(ul);
+
+ // Place cursor in the new list item
+ const newRange = document.createRange();
+ newRange.selectNodeContents(li);
+ newRange.collapse(true);
+ selection.removeAllRanges();
+ selection.addRange(newRange);
+ } else {
const range = selection.getRangeAt(0);
+
+ // Check if we're already in a list
+ const listItem = range.commonAncestorContainer.closest('li');
+ if (listItem) {
+ // Already in a list, create new list item
+ const newLi = document.createElement('li');
+ newLi.innerHTML = ' ';
+ listItem.parentNode.insertBefore(newLi, listItem.nextSibling);
+
+ // Place cursor in new list item
+ const newRange = document.createRange();
+ newRange.selectNodeContents(newLi);
+ newRange.collapse(true);
+ selection.removeAllRanges();
+ selection.addRange(newRange);
+ } else {
+ // Not in a list, create new list
if (range.collapsed) {
- // Wrap current block
+ // No text selected, create new list
const ul = document.createElement('ul');
const li = document.createElement('li');
li.innerHTML = ' ';
ul.appendChild(li);
range.insertNode(ul);
- // place caret inside LI
+
+ // Place cursor in list item
const newRange = document.createRange();
newRange.selectNodeContents(li);
newRange.collapse(true);
selection.removeAllRanges();
selection.addRange(newRange);
- } else {
- const li = document.createElement('li');
- li.appendChild(range.extractContents());
+ } else {
+ // Text selected, wrap in list
+ const selectedContent = range.extractContents();
const ul = document.createElement('ul');
+ const li = document.createElement('li');
+ li.appendChild(selectedContent);
ul.appendChild(li);
range.insertNode(ul);
+
+ // Place cursor after the list
+ const newRange = document.createRange();
+ newRange.setStartAfter(ul);
+ newRange.collapse(true);
selection.removeAllRanges();
+ selection.addRange(newRange);
}
}
}
+
editorContent.dispatchEvent(new Event('input', { bubbles: true }));
}
-
- // NEW CLEAN NUMBER FUNCTION
+ // ENHANCED NUMBERED LIST FUNCTION
handleNumberedList() {
const editorContent = this.template.querySelector('.enhanced-editor-content');
- if (!editorContent) { this.showError('Editor not found'); return; }
+ if (!editorContent) {
+ this.showError('Editor not found');
+ return;
+ }
+
editorContent.focus();
- const ok = document.execCommand('insertOrderedList', false, null);
- if (!ok) {
+
const selection = window.getSelection();
- if (selection.rangeCount) {
+ if (!selection.rangeCount) {
+ // No selection, create a new list at the end
+ const ol = document.createElement('ol');
+ const li = document.createElement('li');
+ li.innerHTML = ' ';
+ ol.appendChild(li);
+ editorContent.appendChild(ol);
+
+ // Place cursor in the new list item
+ const newRange = document.createRange();
+ newRange.selectNodeContents(li);
+ newRange.collapse(true);
+ selection.removeAllRanges();
+ selection.addRange(newRange);
+ } else {
const range = selection.getRangeAt(0);
+
+ // Check if we're already in a list
+ const listItem = range.commonAncestorContainer.closest('li');
+ if (listItem) {
+ // Already in a list, create new list item
+ const newLi = document.createElement('li');
+ newLi.innerHTML = ' ';
+ listItem.parentNode.insertBefore(newLi, listItem.nextSibling);
+
+ // Place cursor in new list item
+ const newRange = document.createRange();
+ newRange.selectNodeContents(newLi);
+ newRange.collapse(true);
+ selection.removeAllRanges();
+ selection.addRange(newRange);
+ } else {
+ // Not in a list, create new list
if (range.collapsed) {
+ // No text selected, create new list
const ol = document.createElement('ol');
const li = document.createElement('li');
li.innerHTML = ' ';
ol.appendChild(li);
range.insertNode(ol);
+
+ // Place cursor in list item
const newRange = document.createRange();
newRange.selectNodeContents(li);
newRange.collapse(true);
selection.removeAllRanges();
selection.addRange(newRange);
- } else {
- const li = document.createElement('li');
- li.appendChild(range.extractContents());
+ } else {
+ // Text selected, wrap in list
+ const selectedContent = range.extractContents();
const ol = document.createElement('ol');
+ const li = document.createElement('li');
+ li.appendChild(selectedContent);
ol.appendChild(li);
range.insertNode(ol);
+
+ // Place cursor after the list
+ const newRange = document.createRange();
+ newRange.setStartAfter(ol);
+ newRange.collapse(true);
selection.removeAllRanges();
+ selection.addRange(newRange);
}
}
}
+
editorContent.dispatchEvent(new Event('input', { bubbles: true }));
}
@@ -4194,7 +4120,6 @@ export default class PropertyTemplateSelector extends LightningElement {
}
// Don't hide floating panel since we're not using it
}
-
// Show selector options
showSelectorOptions(element) {
// Create or update selector options panel
@@ -4382,7 +4307,6 @@ export default class PropertyTemplateSelector extends LightningElement {
`;
}
-
// Select property image
selectPropertyImage(imageUrl) {
if (this.selectedElement) {
@@ -4574,7 +4498,6 @@ export default class PropertyTemplateSelector extends LightningElement {
e.stopPropagation();
this.deleteTableRow(table);
};
-
// Delete Column button
const delColBtn = document.createElement('button');
delColBtn.innerHTML = '- Col';
@@ -4700,6 +4623,7 @@ export default class PropertyTemplateSelector extends LightningElement {
this.dragStartX = e.clientX;
this.dragStartY = e.clientY;
this.dragElement = e.target;
+ this.dragInitiated = false; // will flip to true only after threshold is exceeded
// Store initial position
const rect = this.dragElement.getBoundingClientRect();
@@ -4711,7 +4635,6 @@ export default class PropertyTemplateSelector extends LightningElement {
// Add dragging class for visual feedback
this.dragElement.style.cursor = 'grabbing';
- this.dragElement.style.opacity = '0.8';
// Prevent text selection during drag
document.body.style.userSelect = 'none';
@@ -4724,11 +4647,19 @@ export default class PropertyTemplateSelector extends LightningElement {
const deltaX = e.clientX - this.dragStartX;
const deltaY = e.clientY - this.dragStartY;
+ const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
- // Update position smoothly
+ // Only start moving the image if the cursor moved beyond a small threshold
+ if (!this.dragInitiated && distance > 5) {
+ this.dragInitiated = true;
+ this.dragElement.style.opacity = '0.85';
+ this.dragElement.style.position = 'absolute';
+ }
+ if (!this.dragInitiated) return;
+
+ // Update position smoothly after drag actually begins
this.dragElement.style.left = (this.initialLeft + deltaX) + 'px';
this.dragElement.style.top = (this.initialTop + deltaY) + 'px';
- this.dragElement.style.position = 'absolute';
}
handleImageMouseUp(e) {
@@ -4738,17 +4669,19 @@ export default class PropertyTemplateSelector extends LightningElement {
// Restore cursor and opacity
this.dragElement.style.cursor = 'grab';
- this.dragElement.style.opacity = '1';
+ this.dragElement.style.opacity = '';
// Re-enable text selection
document.body.style.userSelect = '';
// Save undo state after drag
- this.saveUndoState();
+ if (this.dragInitiated) {
+ this.saveUndoState();
+ }
this.dragElement = null;
+ this.dragInitiated = false;
}
-
// Add resize handles to image
addResizeHandles(img) {
const handles = ['nw', 'ne', 'sw', 'se'];
@@ -4944,7 +4877,6 @@ export default class PropertyTemplateSelector extends LightningElement {
this.showError('Please select text first');
}
}
-
handleContentChange() {
// Update the HTML content when user types in the editor
const editorContent = this.template.querySelector('.enhanced-editor-content');
@@ -5107,7 +5039,6 @@ export default class PropertyTemplateSelector extends LightningElement {
currentElement = currentElement.parentElement;
}
}
-
// Method 4: Check for background images in the element hierarchy (enhanced for property cards)
if (!clickedImage) {
let currentElement = e.target;
@@ -5309,7 +5240,6 @@ export default class PropertyTemplateSelector extends LightningElement {
// Reset upload area
this.resetUploadArea();
}
-
// Set image source (property or local)
setImageSource(event) {
const source = event.target.dataset.source;
@@ -5510,7 +5440,6 @@ export default class PropertyTemplateSelector extends LightningElement {
this.logCurrentState();
this.insertSelectedImage();
}
-
// Insert selected image
insertSelectedImage() {
@@ -5692,7 +5621,6 @@ export default class PropertyTemplateSelector extends LightningElement {
// Prevent scrolling while dragging
document.body.style.overflow = 'hidden';
};
-
const handleMouseMove = (e) => {
if (!isDragging) return;
@@ -5883,7 +5811,6 @@ export default class PropertyTemplateSelector extends LightningElement {
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
}
-
handleBringForward() {
const selection = window.getSelection();
if (selection.rangeCount > 0) {
@@ -6083,7 +6010,6 @@ export default class PropertyTemplateSelector extends LightningElement {
selection.addRange(range);
}
}
-
insertImage() {
// Create file input for local image upload
const fileInput = document.createElement('input');
@@ -6284,7 +6210,6 @@ export default class PropertyTemplateSelector extends LightningElement {
element.appendChild(handleElement);
});
}
-
addShape() {
}
@@ -6482,7 +6407,6 @@ export default class PropertyTemplateSelector extends LightningElement {
if (templateImages && templateImages.length > 0) {
return templateImages;
}
-
// No images found
return [];
}
@@ -6677,7 +6601,6 @@ export default class PropertyTemplateSelector extends LightningElement {
this._resizeHandler = () => { if (this.currentStep === 3 && this.fitToWidth) this.fitToWidth(); };
window.addEventListener('resize', this._resizeHandler);
}
-
// Called after template loads
renderedCallback() {
this.ensureEditorEditable();
@@ -6845,7 +6768,6 @@ export default class PropertyTemplateSelector extends LightningElement {
return null;
}
-
// Triple click handler for image replacement
handleImageClick(clickedImage, event) {
// Clear any existing timeout
@@ -7045,7 +6967,6 @@ export default class PropertyTemplateSelector extends LightningElement {
this.replaceImageSrc(imageUrl);
this.closeImageReplacement();
}
-
triggerImageReplacementFileUpload() {
// Try to find the image upload input in the replacement modal
@@ -7246,7 +7167,6 @@ export default class PropertyTemplateSelector extends LightningElement {
this.saveTemplateName = '';
document.body.style.overflow = 'hidden';
}
-
closeSaveDialog() {
this.showSaveDialog = false;
document.body.style.overflow = '';
@@ -7617,7 +7537,6 @@ export default class PropertyTemplateSelector extends LightningElement {
return updatedHTML;
}
-
// Method to dynamically update CSS background-image rules after template loads
updateCSSBackgroundImages() {
const editor = this.template.querySelector('.enhanced-editor-content');
@@ -7814,9 +7733,6 @@ export default class PropertyTemplateSelector extends LightningElement {
this.showSuccess('Table inserted via drag and drop!');
}
-
-
-
// Insert table at specific position
insertTableAtPosition(editor, tableData, event) {
// Get cursor position relative to editor
@@ -8011,7 +7927,6 @@ export default class PropertyTemplateSelector extends LightningElement {
tbody.appendChild(newRow);
this.showSuccess('Row added successfully!');
}
-
// Add column to table
addTableColumn(event) {
const tableId = event.currentTarget.dataset.tableId;
@@ -8183,7 +8098,6 @@ export default class PropertyTemplateSelector extends LightningElement {
});
});
}
-
// Improved text insertion that's draggable anywhere
insertDraggableText() {
const editor = this.template.querySelector('.enhanced-editor-content');
@@ -8385,7 +8299,6 @@ export default class PropertyTemplateSelector extends LightningElement {
}, 500);
}
}
-
// Enhanced image manipulation methods
addResizeHandles(container) {
const handles = ['nw', 'ne', 'sw', 'se', 'n', 's', 'w', 'e'];
@@ -8581,7 +8494,6 @@ export default class PropertyTemplateSelector extends LightningElement {
document.removeEventListener('mouseup', stopDrag);
};
}
-
// Select draggable element
selectDraggableElement(element) {
// Remove selection from all draggable elements
@@ -8777,7 +8689,6 @@ export default class PropertyTemplateSelector extends LightningElement {
connectedCallback() {
this.loadSavedTemplates();
}
-
// Helper method for generating amenities HTML
generateAmenitiesHTML(data) {
const amenities = [
@@ -8804,24 +8715,30 @@ export default class PropertyTemplateSelector extends LightningElement {
const images = this.realPropertyImages || [];
if (images.length === 0) {
const exteriorImage = this.getExteriorImageUrl();
+ const interiorImage = this.getSmartImageForSection('interior', 'https://images.unsplash.com/photo-1616486338812-3dadae4b4ace?ixlib=rb-4.0.3&q=85&fm=jpg&crop=entropy&cs=srgb&w=1200');
+ const bedroomImage = this.getSmartImageForSection('bedroom', 'https://images.unsplash.com/photo-1586023492125-27b2c045efd7?ixlib=rb-4.0.3&q=85&fm=jpg&crop=entropy&cs=srgb&w=1200');
+ const kitchenImage = this.getSmartImageForSection('kitchen', 'https://images.unsplash.com/photo-1556909114-f6e7ad7d3136?ixlib=rb-4.0.3&q=85&fm=jpg&crop=entropy&cs=srgb&w=1200');
+
return `
-
-

-
-
-

-
-
-

-
+
+
+
+
`;
}
- return images.slice(0, 6).map(image => `
-
-

-
- `).join('');
+ // Generate gallery items with proper grid positioning
+ const galleryItems = images.slice(0, 4).map((image, index) => {
+ if (index === 0) {
+ // First image spans full width
+ return `
`;
+ } else {
+ // Other images in grid columns
+ return `
`;
+ }
+ }).join('');
+
+ return galleryItems;
}
// Helper method for getting smart images for sections