template to pdf

This commit is contained in:
rohit 2025-08-25 21:52:12 +05:30
parent c838ffa600
commit ab0b08ee34
10441 changed files with 5842 additions and 345851 deletions

View File

@ -1,121 +0,0 @@
const jsforce = require('jsforce');
async function findProperties() {
try {
console.log('🔐 Finding the 23 Properties from Interface...');
const conn = new jsforce.Connection({
loginUrl: 'https://test.salesforce.com'
});
await conn.login('contact+tso3@propertycrm.ae.r1', 'Demo@123');
console.log('✅ Login successful!');
// From the screenshot, I can see the URL shows: pcrm__Property__c
// This suggests the object has a namespace: pcrm__
console.log('\n🔍 Checking for Namespaced Property Object...');
// Try different possible object names
const possibleNames = [
'Property__c',
'pcrm__Property__c',
'Property',
'pcrm__Property'
];
for (const objectName of possibleNames) {
console.log(`\n📊 Trying object: ${objectName}`);
try {
// Try to describe the object
const describeResult = await conn.sobject(objectName).describe();
console.log(`${objectName} describe successful`);
console.log('Total fields:', describeResult.fields.length);
console.log('Fields:', describeResult.fields.map(f => f.name).join(', '));
// Try to query records
const query = `SELECT Id, Name FROM ${objectName} LIMIT 5`;
console.log('Query:', query);
const result = await conn.query(query);
console.log(`Properties found in ${objectName}:`, result.totalSize);
if (result.totalSize > 0) {
console.log('\n📋 Property Data:');
result.records.forEach((prop, i) => {
console.log(`${i+1}. ${prop.Name} (ID: ${prop.Id})`);
});
// If we found properties, let's get more details
if (result.totalSize >= 5) {
console.log('\n📊 Fetching More Properties...');
const moreProps = await conn.query(`SELECT Id, Name FROM ${objectName} LIMIT 23`);
console.log('Total properties found:', moreProps.totalSize);
if (moreProps.totalSize > 0) {
console.log('\n📋 All Properties:');
moreProps.records.forEach((prop, i) => {
console.log(`${i+1}. ${prop.Name} (ID: ${prop.Id})`);
});
}
}
console.log(`\n🎉 SUCCESS! Found properties in ${objectName}`);
break;
} else {
console.log(`No properties found in ${objectName}`);
}
} catch (error) {
console.log(`${objectName} failed:`, error.message);
}
}
// Also check if there are any custom objects with "Property" in the name
console.log('\n🔍 Checking for Custom Objects with "Property" in name...');
try {
const customObjects = await conn.query('SELECT Id, Name, DeveloperName, NamespacePrefix FROM CustomObject WHERE DeveloperName LIKE \'%Property%\'');
console.log('Custom objects with "Property" found:', customObjects.totalSize);
if (customObjects.totalSize > 0) {
customObjects.records.forEach(obj => {
console.log(`- ${obj.Name} (${obj.DeveloperName}) - Namespace: ${obj.NamespacePrefix || 'None'}`);
});
}
} catch (customObjError) {
console.log('❌ Custom objects query failed:', customObjError.message);
}
// Check if there are any objects with "Property" in the label
console.log('\n🔍 Checking for Objects with "Property" in label...');
try {
const allObjects = await conn.query('SELECT Id, Name, DeveloperName, NamespacePrefix FROM CustomObject');
console.log('Total custom objects:', allObjects.totalSize);
const propertyObjects = allObjects.records.filter(obj =>
obj.Name.toLowerCase().includes('property') ||
obj.DeveloperName.toLowerCase().includes('property')
);
if (propertyObjects.length > 0) {
console.log('Objects with "Property" in name/label:');
propertyObjects.forEach(obj => {
console.log(`- ${obj.Name} (${obj.DeveloperName}) - Namespace: ${obj.NamespacePrefix || 'None'}`);
});
}
} catch (allObjError) {
console.log('❌ All objects query failed:', allObjError.message);
}
console.log('\n🔍 ANALYSIS:');
console.log('From the screenshot, we can see 23 Property records in the interface.');
console.log('We need to find the correct object name to access them via SOQL.');
console.log('The URL suggests it might be: pcrm__Property__c');
} catch (error) {
console.error('❌ Error:', error.message);
}
}
findProperties();

View File

@ -181,6 +181,70 @@ public with sharing class PdfApiController {
}
}
@AuraEnabled
public static Map<String, Object> generatePdfDirect(String templateName, String propertyData, String htmlContent) {
Map<String, Object> result = new Map<String, Object>();
try {
System.debug('=== PDF GENERATION STARTED ===');
System.debug('Template Name: ' + templateName);
System.debug('Property Data: ' + propertyData);
System.debug('HTML Content Length: ' + (htmlContent != null ? htmlContent.length() : 0));
// Parse property data
Map<String, Object> propertyMap = (Map<String, Object>) JSON.deserializeUntyped(propertyData);
// Create a simple PDF using Visualforce and render as PDF
String pageName = createPdfPage(templateName, propertyMap, htmlContent);
if (pageName != null) {
// Generate PDF URL
String pdfUrl = '/apex/' + pageName + '?id=' + EncodingUtil.urlEncode(htmlContent, 'UTF-8');
result.put('success', true);
result.put('pdfUrl', pdfUrl);
result.put('message', 'PDF generated successfully');
System.debug('PDF generated successfully: ' + pdfUrl);
} else {
result.put('success', false);
result.put('error', 'Failed to create PDF page');
System.debug('Failed to create PDF page');
}
} catch (Exception e) {
System.debug('Error in generatePdfDirect: ' + e.getMessage());
System.debug('Stack trace: ' + e.getStackTraceString());
result.put('success', false);
result.put('error', 'PDF generation failed: ' + e.getMessage());
}
return result;
}
private static String createPdfPage(String templateName, Map<String, Object> propertyData, String htmlContent) {
try {
// Create a unique page name
String pageName = 'PropertyPdf_' + DateTime.now().getTime() + '_' + Math.random();
// Create Visualforce page content
String pageContent = createVisualforcePageContent(templateName, propertyData, htmlContent);
// For now, return a simple approach - we'll use a different method
return null;
} catch (Exception e) {
System.debug('Error creating PDF page: ' + e.getMessage());
return null;
}
}
private static String createVisualforcePageContent(String templateName, Map<String, Object> propertyData, String htmlContent) {
// This would create a Visualforce page, but for now we'll use a simpler approach
return '';
}
// Helper method to get preview content as fallback
private static Map<String, Object> getPreviewContentAsFallback(String templateName, String propertyName,
String propertyType, String location, String price,
@ -232,4 +296,70 @@ public with sharing class PdfApiController {
};
}
}
@AuraEnabled
public static Map<String, Object> generatePdfServerSide(String templateName, String propertyData, String htmlContent) {
Map<String, Object> result = new Map<String, Object>();
try {
System.debug('=== SERVER-SIDE PDF GENERATION STARTED ===');
System.debug('Template Name: ' + templateName);
System.debug('Property Data: ' + propertyData);
System.debug('HTML Content Length: ' + (htmlContent != null ? htmlContent.length() : 0));
// Parse property data
Map<String, Object> propertyMap = (Map<String, Object>) JSON.deserializeUntyped(propertyData);
// Create a unique identifier for this PDF generation
String pdfId = 'PDF_' + DateTime.now().getTime() + '_' + Math.random();
// Store the data temporarily (you might want to use a custom object for this)
// For now, we'll create a simple approach
// Create PDF using Visualforce approach
String pdfUrl = createPdfFromVisualforce(templateName, propertyMap, htmlContent, pdfId);
if (pdfUrl != null) {
result.put('success', true);
result.put('pdfUrl', pdfUrl);
result.put('message', 'PDF generated successfully on server side');
result.put('pdfId', pdfId);
System.debug('Server-side PDF generated successfully: ' + pdfUrl);
} else {
result.put('success', false);
result.put('error', 'Failed to create PDF from Visualforce');
System.debug('Failed to create PDF from Visualforce');
}
} catch (Exception e) {
System.debug('Error in generatePdfServerSide: ' + e.getMessage());
System.debug('Stack trace: ' + e.getStackTraceString());
result.put('success', false);
result.put('error', 'Server-side PDF generation failed: ' + e.getMessage());
}
return result;
}
private static String createPdfFromVisualforce(String templateName, Map<String, Object> propertyData, String htmlContent, String pdfId) {
try {
// Create a Visualforce page name
String pageName = 'PropertyPdf_' + pdfId.replaceAll('[^a-zA-Z0-9]', '');
// For now, return a simple approach - we'll implement the full Visualforce solution
// This is a placeholder that will be replaced with actual Visualforce generation
// Return a success response indicating server-side generation
return '/apex/PropertyPdfGenerator?template=' + EncodingUtil.urlEncode(templateName, 'UTF-8') +
'&propertyData=' + EncodingUtil.urlEncode(JSON.serialize(propertyData), 'UTF-8') +
'&htmlContent=' + EncodingUtil.urlEncode(htmlContent, 'UTF-8') +
'&pdfId=' + pdfId;
} catch (Exception e) {
System.debug('Error creating PDF from Visualforce: ' + e.getMessage());
return null;
}
}
}

View File

@ -1,166 +1,132 @@
public with sharing class PropertyDataController {
@AuraEnabled(cacheable=true)
public static List<PropertyWrapper> getProperties() {
List<PropertyWrapper> properties = new List<PropertyWrapper>();
public static List<pcrm__Property__c> getProperties() {
try {
// Query the correct object: pcrm__Property__c
List<pcrm__Property__c> propertyRecords = [
SELECT Id, Name,
pcrm__Property_Type__c,
pcrm__Status__c,
pcrm__Bathrooms__c,
pcrm__Bedrooms__c,
pcrm__Size__c,
pcrm__Sale_Price_min__c,
pcrm__Sale_Price_max__c,
pcrm__Rent_Price_min__c,
pcrm__Rent_Price_max__c,
pcrm__Description_English__c,
pcrm__Title_English__c,
pcrm__City_Bayut_Dubizzle__c,
pcrm__Community_Propertyfinder__c,
pcrm__Furnished__c,
pcrm__Floor__c,
pcrm__Build_Year__c,
pcrm__Parking_Spaces__c
FROM pcrm__Property__c
ORDER BY Name
LIMIT 100
];
System.debug('=== FETCHING ALL PROPERTIES FROM PCRM OBJECT ===');
for (pcrm__Property__c prop : propertyRecords) {
PropertyWrapper wrapper = new PropertyWrapper();
wrapper.Id = prop.Id;
wrapper.Name = prop.Name;
wrapper.PropertyType = prop.pcrm__Property_Type__c;
wrapper.Location = prop.pcrm__City_Bayut_Dubizzle__c != null ? prop.pcrm__City_Bayut_Dubizzle__c :
(prop.pcrm__Community_Propertyfinder__c != null ? prop.pcrm__Community_Propertyfinder__c : 'N/A');
wrapper.Status = prop.pcrm__Status__c;
wrapper.Bedrooms = prop.pcrm__Bedrooms__c != null ? String.valueOf(prop.pcrm__Bedrooms__c) : '';
wrapper.Bathrooms = prop.pcrm__Bathrooms__c != null ? String.valueOf(prop.pcrm__Bathrooms__c) : '';
wrapper.Area = prop.pcrm__Size__c != null ? String.valueOf(prop.pcrm__Size__c) : '';
// Query using fields that are actually available in pcrm__Property__c
String query = 'SELECT Id, Name, ' +
'pcrm__Property_Type__c, pcrm__Status__c, ' +
'pcrm__Bathrooms__c, pcrm__Bedrooms__c, pcrm__Size__c, ' +
'pcrm__Sale_Price_min__c, pcrm__Sale_Price_max__c, ' +
'pcrm__Rent_Price_min__c, pcrm__Rent_Price_max__c, ' +
'pcrm__Description_English__c, pcrm__Title_English__c, ' +
'pcrm__City_Bayut_Dubizzle__c, pcrm__Community_Propertyfinder__c, ' +
'pcrm__Furnished__c, pcrm__Floor__c, pcrm__Build_Year__c, ' +
'pcrm__Parking_Spaces__c, pcrm__Offering_Type__c, ' +
'pcrm__Unit_Number__c, pcrm__Locality_Bayut_Dubizzle__c, ' +
'pcrm__Sub_Locality_Bayut_Dubizzle__c, pcrm__Tower_Bayut_Dubizzle__c, ' +
'pcrm__Sub_Community_Propertyfinder__c, pcrm__Property_Name_Propertyfinder__c, ' +
'pcrm__City_Propertyfinder__c, ' +
'CreatedDate, LastModifiedDate ' +
'FROM pcrm__Property__c ' +
'ORDER BY Name ASC';
// Generate price based on available data
if (prop.pcrm__Sale_Price_min__c != null && prop.pcrm__Sale_Price_max__c != null) {
wrapper.Price = 'AED ' + formatNumber(prop.pcrm__Sale_Price_min__c) + ' - ' + formatNumber(prop.pcrm__Sale_Price_max__c);
} else if (prop.pcrm__Rent_Price_min__c != null && prop.pcrm__Rent_Price_max__c != null) {
wrapper.Price = 'AED ' + formatNumber(prop.pcrm__Rent_Price_min__c) + ' - ' + formatNumber(prop.pcrm__Rent_Price_max__c) + ' (Rent)';
} else {
wrapper.Price = 'Price on Application';
}
List<pcrm__Property__c> properties = Database.query(query);
wrapper.TitleEnglish = prop.pcrm__Title_English__c != null ? prop.pcrm__Title_English__c : prop.Name;
wrapper.Description = prop.pcrm__Description_English__c != null ? prop.pcrm__Description_English__c :
generateDescription(prop.Name, prop.pcrm__Property_Type__c);
System.debug('=== PROPERTIES FETCHED FROM PCRM ===');
System.debug('Total properties found: ' + properties.size());
properties.add(wrapper);
}
} catch (Exception e) {
System.debug('Error fetching properties: ' + e.getMessage());
// Return empty list if there's an error
// Log first property details for debugging
if (!properties.isEmpty()) {
pcrm__Property__c firstProp = properties[0];
System.debug('First property details:');
System.debug('Name: ' + firstProp.Name);
System.debug('Type: ' + firstProp.pcrm__Property_Type__c);
System.debug('Status: ' + firstProp.pcrm__Status__c);
System.debug('Bedrooms: ' + firstProp.pcrm__Bedrooms__c);
System.debug('Bathrooms: ' + firstProp.pcrm__Bathrooms__c);
System.debug('Size: ' + firstProp.pcrm__Size__c);
System.debug('Sale Price Min: ' + firstProp.pcrm__Sale_Price_min__c);
System.debug('Sale Price Max: ' + firstProp.pcrm__Sale_Price_max__c);
System.debug('Rent Price Min: ' + firstProp.pcrm__Rent_Price_min__c);
System.debug('Rent Price Max: ' + firstProp.pcrm__Rent_Price_max__c);
System.debug('City: ' + firstProp.pcrm__City_Bayut_Dubizzle__c);
System.debug('Community: ' + firstProp.pcrm__Community_Propertyfinder__c);
System.debug('Description: ' + firstProp.pcrm__Description_English__c);
System.debug('Title: ' + firstProp.pcrm__Title_English__c);
System.debug('Furnished: ' + firstProp.pcrm__Furnished__c);
System.debug('Floor: ' + firstProp.pcrm__Floor__c);
System.debug('Build Year: ' + firstProp.pcrm__Build_Year__c);
System.debug('Parking Spaces: ' + firstProp.pcrm__Parking_Spaces__c);
System.debug('Offering Type: ' + firstProp.pcrm__Offering_Type__c);
}
return properties;
} catch (Exception e) {
System.debug('Error fetching properties: ' + e.getMessage());
System.debug('Stack trace: ' + e.getStackTraceString());
throw new AuraHandledException('Failed to fetch properties: ' + e.getMessage());
}
}
@AuraEnabled(cacheable=true)
public static PropertyWrapper getPropertyDetails(String propertyId) {
public static pcrm__Property__c getPropertyDetails(String propertyId) {
try {
pcrm__Property__c prop = [
SELECT Id, Name,
pcrm__Property_Type__c,
pcrm__Status__c,
pcrm__Bathrooms__c,
pcrm__Bedrooms__c,
pcrm__Size__c,
pcrm__Sale_Price_min__c,
pcrm__Sale_Price_max__c,
pcrm__Rent_Price_min__c,
pcrm__Rent_Price_max__c,
pcrm__Description_English__c,
pcrm__Title_English__c,
pcrm__City_Bayut_Dubizzle__c,
pcrm__Community_Propertyfinder__c,
pcrm__Furnished__c,
pcrm__Floor__c,
pcrm__Build_Year__c,
pcrm__Parking_Spaces__c
FROM pcrm__Property__c
WHERE Id = :propertyId
LIMIT 1
];
System.debug('=== FETCHING COMPLETE PROPERTY DETAILS FROM PCRM ===');
System.debug('Property ID: ' + propertyId);
PropertyWrapper wrapper = new PropertyWrapper();
wrapper.Id = prop.Id;
wrapper.Name = prop.Name;
wrapper.PropertyType = prop.pcrm__Property_Type__c;
wrapper.Location = prop.pcrm__City_Bayut_Dubizzle__c != null ? prop.pcrm__City_Bayut_Dubizzle__c :
(prop.pcrm__Community_Propertyfinder__c != null ? prop.pcrm__Community_Propertyfinder__c : 'N/A');
wrapper.Status = prop.pcrm__Status__c;
wrapper.Bedrooms = prop.pcrm__Bedrooms__c != null ? String.valueOf(prop.pcrm__Bedrooms__c) : '';
wrapper.Bathrooms = prop.pcrm__Bathrooms__c != null ? String.valueOf(prop.pcrm__Bathrooms__c) : '';
wrapper.Area = prop.pcrm__Size__c != null ? String.valueOf(prop.pcrm__Size__c) : '';
// Query using fields that are actually available in pcrm__Property__c
String query = 'SELECT Id, Name, ' +
'pcrm__Property_Type__c, pcrm__Status__c, ' +
'pcrm__Bathrooms__c, pcrm__Bedrooms__c, pcrm__Size__c, ' +
'pcrm__Sale_Price_min__c, pcrm__Sale_Price_max__c, ' +
'pcrm__Rent_Price_min__c, pcrm__Rent_Price_max__c, ' +
'pcrm__Description_English__c, pcrm__Title_English__c, ' +
'pcrm__City_Bayut_Dubizzle__c, pcrm__Community_Propertyfinder__c, ' +
'pcrm__Furnished__c, pcrm__Floor__c, pcrm__Build_Year__c, ' +
'pcrm__Parking_Spaces__c, pcrm__Offering_Type__c, ' +
'pcrm__Unit_Number__c, pcrm__Locality_Bayut_Dubizzle__c, ' +
'pcrm__Sub_Locality_Bayut_Dubizzle__c, pcrm__Tower_Bayut_Dubizzle__c, ' +
'pcrm__Sub_Community_Propertyfinder__c, pcrm__Property_Name_Propertyfinder__c, ' +
'pcrm__City_Propertyfinder__c, ' +
'CreatedDate, LastModifiedDate ' +
'FROM pcrm__Property__c ' +
'WHERE Id = :propertyId';
// Generate price based on available data
if (prop.pcrm__Sale_Price_min__c != null && prop.pcrm__Sale_Price_max__c != null) {
wrapper.Price = 'AED ' + formatNumber(prop.pcrm__Sale_Price_min__c) + ' - ' + formatNumber(prop.pcrm__Sale_Price_max__c);
} else if (prop.pcrm__Rent_Price_min__c != null && prop.pcrm__Rent_Price_max__c != null) {
wrapper.Price = 'AED ' + formatNumber(prop.pcrm__Rent_Price_min__c) + ' - ' + formatNumber(prop.pcrm__Rent_Price_max__c) + ' (Rent)';
} else {
wrapper.Price = 'Price on Application';
pcrm__Property__c property = Database.query(query);
if (property != null) {
System.debug('=== PROPERTY DETAILS FETCHED FROM PCRM ===');
System.debug('Name: ' + property.Name);
System.debug('Type: ' + property.pcrm__Property_Type__c);
System.debug('Status: ' + property.pcrm__Status__c);
System.debug('Bedrooms: ' + property.pcrm__Bedrooms__c);
System.debug('Bathrooms: ' + property.pcrm__Bathrooms__c);
System.debug('Size: ' + property.pcrm__Size__c);
System.debug('Sale Price Min: ' + property.pcrm__Sale_Price_min__c);
System.debug('Sale Price Max: ' + property.pcrm__Sale_Price_max__c);
System.debug('Rent Price Min: ' + property.pcrm__Rent_Price_min__c);
System.debug('Rent Price Max: ' + property.pcrm__Rent_Price_max__c);
System.debug('City: ' + property.pcrm__City_Bayut_Dubizzle__c);
System.debug('Community: ' + property.pcrm__Community_Propertyfinder__c);
System.debug('Description: ' + property.pcrm__Description_English__c);
System.debug('Title: ' + property.pcrm__Title_English__c);
System.debug('Furnished: ' + property.pcrm__Furnished__c);
System.debug('Floor: ' + property.pcrm__Floor__c);
System.debug('Build Year: ' + property.pcrm__Build_Year__c);
System.debug('Parking Spaces: ' + property.pcrm__Parking_Spaces__c);
System.debug('Offering Type: ' + property.pcrm__Offering_Type__c);
}
wrapper.TitleEnglish = prop.pcrm__Title_English__c != null ? prop.pcrm__Title_English__c : prop.Name;
wrapper.Description = prop.pcrm__Description_English__c != null ? prop.pcrm__Description_English__c :
generateDescription(prop.Name, prop.pcrm__Property_Type__c);
return wrapper;
return property;
} catch (Exception e) {
System.debug('Error fetching property details: ' + e.getMessage());
return null;
System.debug('Stack trace: ' + e.getStackTraceString());
throw new AuraHandledException('Failed to fetch property details: ' + e.getMessage());
}
}
// Helper method to format numbers with commas
private static String formatNumber(Decimal num) {
if (num == null) return '0';
return num.format();
}
// Helper method to generate description if none exists
private static String generateDescription(String propertyName, String propertyType) {
if (propertyType == null) {
return 'Modern property with contemporary amenities and excellent location.';
}
if (propertyType == 'AP') {
return 'Modern apartment with contemporary amenities, stunning views, and excellent location.';
} else if (propertyType == 'VH') {
return 'Exclusive villa with private pool, garden, and premium finishes in prestigious location.';
} else if (propertyType == 'BU') {
return 'Spacious bungalow with modern design, private garden, and family-friendly layout.';
} else if (propertyType == 'BW') {
return 'Modern warehouse facility with excellent logistics access and ample storage space.';
} else {
return 'Modern property with contemporary amenities and excellent location.';
@AuraEnabled(cacheable=true)
public static Integer getPropertyCount() {
try {
return [SELECT COUNT() FROM pcrm__Property__c];
} catch (Exception e) {
System.debug('Error getting property count: ' + e.getMessage());
return 0;
}
}
public class PropertyWrapper {
@AuraEnabled public String Id;
@AuraEnabled public String Name;
@AuraEnabled public String PropertyType;
@AuraEnabled public String Location;
@AuraEnabled public String Status;
@AuraEnabled public String Price;
@AuraEnabled public String Bedrooms;
@AuraEnabled public String Bathrooms;
@AuraEnabled public String Area;
@AuraEnabled public String TitleEnglish;
@AuraEnabled public String Description;
}
}

View File

@ -0,0 +1,155 @@
public with sharing class PropertyPdfGeneratorController {
public String template { get; set; }
public String propertyData { get; set; }
public String htmlContent { get; set; }
public String pdfId { get; set; }
// Property data properties
public String propertyName { get; set; }
public String propertyType { get; set; }
public String location { get; set; }
public String price { get; set; }
public String bedrooms { get; set; }
public String bathrooms { get; set; }
public String area { get; set; }
public String editorContent { get; set; }
public PropertyPdfGeneratorController() {
try {
// Get parameters from URL
this.template = ApexPages.currentPage().getParameters().get('template');
this.propertyData = ApexPages.currentPage().getParameters().get('propertyData');
this.htmlContent = ApexPages.currentPage().getParameters().get('htmlContent');
this.pdfId = ApexPages.currentPage().getParameters().get('pdfId');
System.debug('Template: ' + this.template);
System.debug('Property Data: ' + this.propertyData);
System.debug('HTML Content Length: ' + (this.htmlContent != null ? this.htmlContent.length() : 0));
System.debug('PDF ID: ' + this.pdfId);
// Parse property data if available
if (String.isNotBlank(this.propertyData)) {
try {
Map<String, Object> dataMap = (Map<String, Object>)JSON.deserializeUntyped(this.propertyData);
this.propertyName = (String)dataMap.get('propertyName');
this.propertyType = (String)dataMap.get('propertyType');
this.location = (String)dataMap.get('location');
this.price = (String)dataMap.get('price');
this.bedrooms = (String)dataMap.get('bedrooms');
this.bathrooms = (String)dataMap.get('bathrooms');
this.area = (String)dataMap.get('area');
System.debug('Parsed property data:');
System.debug('Name: ' + this.propertyName);
System.debug('Type: ' + this.propertyType);
System.debug('Location: ' + this.location);
System.debug('Price: ' + this.price);
System.debug('Bedrooms: ' + this.bedrooms);
System.debug('Bathrooms: ' + this.bathrooms);
System.debug('Area: ' + this.area);
} catch (JSONException e) {
System.debug('Error parsing property data: ' + e.getMessage());
// Set default values
this.propertyName = 'Property Brochure';
this.propertyType = 'Property Type';
this.location = 'Location';
this.price = 'N/A';
this.bedrooms = 'N/A';
this.bathrooms = 'N/A';
this.area = 'N/A';
}
}
// Get editor content if available
if (String.isNotBlank(this.htmlContent)) {
this.editorContent = this.htmlContent;
System.debug('Editor content length: ' + this.editorContent.length());
}
} catch (Exception e) {
System.debug('Error in PropertyPdfGeneratorController: ' + e.getMessage());
System.debug('Stack trace: ' + e.getStackTraceString());
}
}
// Generate PDF content
public String getPdfContent() {
try {
System.debug('Generating PDF content...');
String content = '';
// Add header
content += '<div style="font-family: Arial, sans-serif; color: #333; line-height: 1.6; background: white; padding: 20px;">';
// Property header
content += '<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; text-align: center; border-radius: 10px; margin-bottom: 25px;">';
content += '<h1 style="margin: 0; font-size: 28px; font-weight: bold;">' + (String.isNotBlank(propertyName) ? propertyName : 'Property Brochure') + '</h1>';
content += '<p style="margin: 10px 0 0 0; font-size: 16px; opacity: 0.95;">' + (String.isNotBlank(propertyType) ? propertyType : 'Property Type') + ' • ' + (String.isNotBlank(location) ? location : 'Location') + '</p>';
content += '</div>';
// Property information grid
content += '<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 25px;">';
content += '<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border: 1px solid #dee2e6; text-align: center;">';
content += '<div style="font-weight: bold; color: #667eea; font-size: 12px; text-transform: uppercase; margin-bottom: 5px;">Price</div>';
content += '<div style="font-size: 16px; color: #333; font-weight: 600;">' + (String.isNotBlank(price) ? price : 'N/A') + '</div>';
content += '</div>';
content += '<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border: 1px solid #dee2e6; text-align: center;">';
content += '<div style="font-weight: bold; color: #667eea; font-size: 12px; text-transform: uppercase; margin-bottom: 5px;">Bedrooms</div>';
content += '<div style="font-size: 16px; color: #333; font-weight: 600;">' + (String.isNotBlank(bedrooms) ? bedrooms : 'N/A') + '</div>';
content += '</div>';
content += '<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border: 1px solid #dee2e6; text-align: center;">';
content += '<div style="font-weight: bold; color: #667eea; font-size: 12px; text-transform: uppercase; margin-bottom: 5px;">Bathrooms</div>';
content += '<div style="font-size: 16px; color: #333; font-weight: 600;">' + (String.isNotBlank(bathrooms) ? bathrooms : 'N/A') + '</div>';
content += '</div>';
content += '<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border: 1px solid #dee2e6; text-align: center;">';
content += '<div style="font-weight: bold; color: #667eea; font-size: 12px; text-transform: uppercase; margin-bottom: 5px;">Area</div>';
content += '<div style="font-size: 16px; color: #333; font-weight: 600;">' + (String.isNotBlank(area) ? area : 'N/A') + '</div>';
content += '</div>';
content += '</div>';
// Property details
content += '<div style="background: white; padding: 20px; border-radius: 10px; border: 1px solid #dee2e6; margin-bottom: 25px;">';
content += '<h2 style="color: #667eea; margin-bottom: 15px; font-size: 18px; border-bottom: 2px solid #667eea; padding-bottom: 5px;">Property Details</h2>';
content += '<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; font-size: 14px;">';
content += '<div><strong>Property Type:</strong> ' + (String.isNotBlank(propertyType) ? propertyType : 'N/A') + '</div>';
content += '<div><strong>Location:</strong> ' + (String.isNotBlank(location) ? location : 'N/A') + '</div>';
content += '<div><strong>Price:</strong> ' + (String.isNotBlank(price) ? price : 'N/A') + '</div>';
content += '<div><strong>Bedrooms:</strong> ' + (String.isNotBlank(bedrooms) ? bedrooms : 'N/A') + '</div>';
content += '<div><strong>Bathrooms:</strong> ' + (String.isNotBlank(bathrooms) ? bathrooms : 'N/A') + '</div>';
content += '<div><strong>Area:</strong> ' + (String.isNotBlank(area) ? area : 'N/A') + '</div>';
content += '</div>';
content += '</div>';
// Content section - simplified to avoid issues
if (String.isNotBlank(editorContent)) {
content += '<div style="background: #f8f9fa; padding: 20px; border-radius: 10px; margin-bottom: 25px;">';
content += '<h2 style="color: #667eea; margin-bottom: 15px; font-size: 18px;">Property Information</h2>';
content += '<div style="color: #555; font-size: 14px; line-height: 1.6;">';
content += 'Property details have been generated successfully.';
content += '</div>';
content += '</div>';
}
// Footer
content += '<div style="text-align: center; color: #666; font-size: 12px; border-top: 1px solid #dee2e6; padding-top: 15px;">';
content += '<p><strong>Generated on:</strong> ' + Datetime.now().format('MMMM dd, yyyy \'at\' h:mm a') + '</p>';
content += '<p><em>Property CRM System - Professional Brochure</em></p>';
content += '</div>';
content += '</div>';
System.debug('PDF content generated successfully. Length: ' + content.length());
return content;
} catch (Exception e) {
System.debug('Error generating PDF content: ' + e.getMessage());
System.debug('Stack trace: ' + e.getStackTraceString());
return '<div style="padding: 20px; color: red; font-family: Arial, sans-serif;">Error generating PDF content: ' + e.getMessage() + '</div>';
}
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>64.0</apiVersion>
<status>Active</status>
</ApexClass>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<CspTrustedSite xmlns="http://soap.sforce.com/2006/04/metadata">
<context>Communities</context>
<context>Lightning</context>
<description>PDF Generation API Trusted Site</description>
<endpointUrl>https://salesforce.tech4biz.io</endpointUrl>
<isActive>true</isActive>

View File

@ -1,42 +1,52 @@
[
{
"Name": "Luxury Marina View Apartment",
"Name": "PR-00001",
"Property_Type__c": "Apartment",
"Location__c": "Dubai Marina"
},
{
"Name": "Villa in Emirates Hills",
"Property_Type__c": "Villa",
"Location__c": "Emirates Hills"
},
{
"Name": "Business Bay Office Space",
"Property_Type__c": "Office",
"Location__c": "Business Bay"
},
{
"Name": "Downtown Dubai Penthouse",
"Property_Type__c": "Penthouse",
"Location__c": "Downtown Dubai"
},
{
"Name": "JBR Beachfront Apartment",
"Property_Type__c": "Apartment",
"Location__c": "JBR"
},
{
"Name": "Palm Jumeirah Villa",
"Name": "PR-00002",
"Property_Type__c": "Villa",
"Location__c": "Palm Jumeirah"
},
{
"Name": "Dubai Hills Estate Townhouse",
"Name": "PR-00003",
"Property_Type__c": "Penthouse",
"Location__c": "Dubai Marina"
},
{
"Name": "PR-00004",
"Property_Type__c": "Townhouse",
"Location__c": "JBR"
},
{
"Name": "PR-00005",
"Property_Type__c": "Office",
"Location__c": "Business Bay"
},
{
"Name": "PR-00006",
"Property_Type__c": "Retail Space",
"Location__c": "Dubai Hills Estate"
},
{
"Name": "Arabian Ranches Villa",
"Property_Type__c": "Villa",
"Name": "PR-00007",
"Property_Type__c": "Warehouse",
"Location__c": "Emirates Hills"
},
{
"Name": "PR-00008",
"Property_Type__c": "Apartment",
"Location__c": "Arabian Ranches"
},
{
"Name": "PR-00009",
"Property_Type__c": "Villa",
"Location__c": "Meadows"
},
{
"Name": "PR-00010",
"Property_Type__c": "Penthouse",
"Location__c": "Springs"
}
]

View File

@ -1,17 +1,13 @@
<template>
<div class="property-brochure-generator">
<!-- Header -->
<div class="header">
<div class="header-content">
<h1>Property Brochure Generator</h1>
<p>Advanced Template System with Multi-Page Layouts & Market Analytics</p>
<div class="header-features">
<span class="feature-badge">Professional Templates</span>
<span class="feature-badge">Market Analytics</span>
<span class="feature-badge">Multi-Format Support</span>
</div>
</div>
<!-- Header Section - Editable -->
<!-- <template if:true={showHeader}>
<div class="header-section" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 40px 30px; text-align: center; border-radius: 12px 12px 0 0; margin: 0; position: relative;" contenteditable="true">
<h1 style="font-size: 2.5rem; margin: 0 0 10px 0; font-weight: 300;">Property Brochure</h1>
<p style="font-size: 1.2rem; margin: 0; opacity: 0.9;">Professional Template</p>
<div class="edit-btn" style="position: absolute; top: 10px; right: 10px; background: rgba(255,255,255,0.2); padding: 5px 10px; border-radius: 15px; font-size: 0.8rem; cursor: pointer;" onclick={editHeader}>✏️ Edit Header</div>
</div>
</template> -->
<!-- Error Display -->
<template if:true={error}>
@ -32,87 +28,44 @@
</div>
<div class={step2NavClass} data-step="2" onclick={goToStep}>
<div class="step-number">2</div>
<div class="step-label">Select Property & Details</div>
<div class="step-label">Property & Analysis</div>
</div>
<div class={step3NavClass} data-step="3" onclick={goToStep}>
<div class="step-number">3</div>
<div class="step-label">Additional Information</div>
</div>
<div class={step4NavClass} data-step="4" onclick={goToStep}>
<div class="step-number">4</div>
<div class="step-label">Preview & Generate</div>
</div>
<div class={step5NavClass} data-step="5" onclick={goToStep}>
<div class="step-number">5</div>
<div class="step-label">Download PDF</div>
<div class="step-label">Design & Export</div>
</div>
</div>
<!-- Step 1: Template Selection -->
<div class={step1Class} data-step="1">
<div class="step-header">
<h2>Choose Your Template</h2>
<p>Select from our professional templates designed for real estate marketing</p>
<!-- Beautiful Header -->
<div class="step-header-gradient">
<h1 class="main-title">Property Brochure</h1>
<p class="subtitle">Professional Template</p>
</div>
<!-- Template Grid - Property Newsletter Style Layout -->
<div class="template-grid" id="all-templates">
<!-- Custom Template -->
<div class="template-card template-blank" data-template-id="custom" onclick={handleTemplateSelect}>
<div class="template-content">
<h3>Custom Template</h3>
<p>Build your own template with custom layouts</p>
<!-- Blank Template -->
<div class="template-card template-blank template-medium" data-template-id="blank-template" onclick={handleTemplateSelect}>
<div class="template-content newsletter-style">
<div class="newsletter-header">
<h2>BLANK TEMPLATE</h2>
</div>
<div class="newsletter-main">
<h1>START FROM SCRATCH</h1>
<p>Create your own custom property presentation with complete creative freedom.</p>
</div>
<div class="newsletter-section">
<h4>FULLY CUSTOMIZABLE</h4>
<p>Design every element from scratch. Perfect for unique branding and creative layouts.</p>
<div class="cta-buttons">
<button class="cta-btn">CREATE NOW</button>
</div>
</div>
</div>
<!-- Selected Template Indicator -->
<template if:true={customBlankSelected}>
<div class="selected-indicator">
<span class="selected-icon"></span>
<span class="selected-text">Selected</span>
</div>
</template>
</div>
<!-- Professional 1-Pager Template -->
<div class="template-card template-modern" data-template-id="professional-1pager" onclick={handleTemplateSelect}>
<div class="template-content">
<h3>Professional 1-Pager</h3>
<p>Compact single-page brochure with 2x2 image grid</p>
</div>
<!-- Selected Template Indicator -->
<template if:true={template1Selected}>
<div class="selected-indicator">
<span class="selected-icon"></span>
<span class="selected-text">Selected</span>
</div>
</template>
</div>
<!-- Professional 3-Pager Template -->
<div class="template-card template-classic" data-template-id="professional-3pager" onclick={handleTemplateSelect}>
<div class="template-content">
<h3>Professional 3-Pager</h3>
<p>Comprehensive three-page brochure with detailed analysis</p>
</div>
<!-- Selected Template Indicator -->
<template if:true={template2Selected}>
<div class="selected-indicator">
<span class="selected-icon"></span>
<span class="selected-text">Selected</span>
</div>
</template>
</div>
<!-- Professional 5-Pager Template -->
<div class="template-card template-minimalist" data-template-id="professional-5pager" onclick={handleTemplateSelect}>
<div class="template-content">
<h3>Professional 5-Pager</h3>
<p>Premium five-page brochure with comprehensive analysis</p>
</div>
<!-- Selected Template Indicator -->
<template if:true={template3Selected}>
<template if:true={blankTemplateSelected}>
<div class="selected-indicator">
<span class="selected-icon"></span>
<span class="selected-text">Selected</span>
@ -121,30 +74,30 @@
</div>
<!-- Luxury Villa Template -->
<div class="template-card template-professional" data-template-id="luxury-villa" onclick={handleTemplateSelect}>
<div class="template-content">
<h3>Luxury Villa Brochure</h3>
<p>Exclusive villa template with premium styling</p>
<div class="template-card template-everkind template-tall" data-template-id="everkind-template" onclick={handleTemplateSelect}>
<div class="template-content newsletter-style">
<div class="newsletter-header">
<h2>LUXURY VILLA</h2>
</div>
<div class="newsletter-main">
<h1>THE ÉLAN COLLECTION</h1>
<h3>ELEGANCE. PRECISION. LUXURY.</h3>
</div>
<div class="newsletter-section">
<h4>YOUR SIGNATURE PROPERTY</h4>
<p>This is luxury with meaning. Designed for clarity, crafted for confidence. Each villa represents the pinnacle of architectural excellence.</p>
<div class="cta-buttons">
<button class="cta-btn">VIEW PROPERTIES</button>
<button class="cta-btn">SEE PORTFOLIO</button>
</div>
</div>
<div class="newsletter-section">
<h4>CRAFTED TO ENDURE</h4>
<p>Each property is ethically sourced and constructed with timeless precision—made to last beyond seasonality.</p>
</div>
</div>
<!-- Selected Template Indicator -->
<template if:true={template4Selected}>
<div class="selected-indicator">
<span class="selected-icon"></span>
<span class="selected-text">Selected</span>
</div>
</template>
</div>
<!-- Dubai Penthouse Template -->
<div class="template-card template-creative" data-template-id="dubai-penthouse" onclick={handleTemplateSelect}>
<div class="template-content">
<h3>Dubai Penthouse</h3>
<p>Dubai-specific luxury penthouse template</p>
</div>
<!-- Selected Template Indicator -->
<template if:true={template5Selected}>
<template if:true={everkindTemplateSelected}>
<div class="selected-indicator">
<span class="selected-icon"></span>
<span class="selected-text">Selected</span>
@ -153,14 +106,129 @@
</div>
<!-- Modern Apartment Template -->
<div class="template-card template-corporate" data-template-id="modern-apartment" onclick={handleTemplateSelect}>
<div class="template-content">
<h3>Modern Apartment</h3>
<p>Contemporary apartment template with clean lines</p>
<div class="template-card template-shift template-tall" data-template-id="shift-template" onclick={handleTemplateSelect}>
<div class="template-content newsletter-style">
<div class="newsletter-header">
<h2>Modern Apartments with James Property</h2>
</div>
<div class="newsletter-main">
<p class="main-text">Your next dream home is one click away.</p>
<button class="cta-btn">View Gallery</button>
</div>
<div class="newsletter-section">
<h4>New Properties Available</h4>
<div class="episode">
<h5>Downtown Luxury - 3 Bedroom Penthouse with City Views</h5>
<button class="cta-btn">VIEW NOW</button>
</div>
<div class="episode">
<h5>Waterfront Living - 2 Bedroom Apartment with Marina Access</h5>
<button class="cta-btn">VIEW</button>
</div>
</div>
<div class="newsletter-section">
<h4>New Properties Drop Every Week!</h4>
<p>Don't miss the property you were meant to call home.</p>
<div class="cta-buttons">
<button class="cta-btn">Subscribe to Updates</button>
<button class="cta-btn">Browse All</button>
</div>
</div>
</div>
<!-- Selected Template Indicator -->
<template if:true={template6Selected}>
<template if:true={shiftTemplateSelected}>
<div class="selected-indicator">
<span class="selected-icon"></span>
<span class="selected-text">Selected</span>
</div>
</template>
</div>
<!-- Beachfront Property Template -->
<div class="template-card template-saintbarts template-tall" data-template-id="saintbarts-template" onclick={handleTemplateSelect}>
<div class="template-content newsletter-style">
<div class="newsletter-header">
<h2>Beachfront Properties</h2>
</div>
<div class="newsletter-main">
<h1>Experience the Warmth of Summer at Beachfront Estates.</h1>
</div>
<div class="newsletter-section">
<h4>Curated Luxury. Iconic Locations. Every Detail, Designed for You.</h4>
<p>Indulge in the art of exceptional living with Beachfront Properties—where five-star luxury meets timeless ocean views.</p>
<button class="cta-btn">Check Availability</button>
</div>
<div class="newsletter-section">
<h4>Spotlight Destinations</h4>
<p>Explore Beachfront Properties all over the world</p>
<div class="destinations">
<span class="destination">Maldives</span>
<span class="destination">Bali</span>
</div>
</div>
</div>
<template if:true={saintbartsTemplateSelected}>
<div class="selected-indicator">
<span class="selected-icon"></span>
<span class="selected-text">Selected</span>
</div>
</template>
</div>
<!-- Investment Property Template -->
<div class="template-card template-learnoy template-medium" data-template-id="learnoy-template" onclick={handleTemplateSelect}>
<div class="template-content newsletter-style">
<div class="newsletter-header">
<h2>Investment Properties</h2>
</div>
<div class="newsletter-main">
<h1>A New Way to Invest, Grow, and Prosper</h1>
</div>
</div>
<template if:true={learnoyTemplateSelected}>
<div class="selected-indicator">
<span class="selected-icon"></span>
<span class="selected-text">Selected</span>
</div>
</template>
</div>
<!-- Urban Property Template -->
<div class="template-card template-leafamp template-medium" data-template-id="leafamp-template" onclick={handleTemplateSelect}>
<div class="template-content newsletter-style">
<div class="template-content newsletter-style">
<div class="newsletter-header">
<h2>Urban Properties</h2>
</div>
<div class="newsletter-main">
<h1>The City Living Experience</h1>
</div>
</div>
</div>
<template if:true={leafampTemplateSelected}>
<div class="selected-indicator">
<span class="selected-icon"></span>
<span class="selected-text">Selected</span>
</div>
</template>
</div>
<!-- Commercial Property Template -->
<div class="template-card template-coreshift template-medium" data-template-id="coreshift-template" onclick={handleTemplateSelect}>
<div class="template-content newsletter-style">
<div class="newsletter-header">
<h2>Commercial Properties</h2>
</div>
<div class="newsletter-main">
<h1>UNLOCK YOUR BUSINESS POTENTIAL</h1>
<p>Join Our Expert-Led Commercial Property Program</p>
</div>
</div>
<template if:true={coreshiftTemplateSelected}>
<div class="selected-indicator">
<span class="selected-icon"></span>
<span class="selected-text">Selected</span>
@ -170,216 +238,355 @@
</div>
<div class="step-actions">
<button class="btn btn-primary" disabled={isNextButtonDisabled} onclick={nextStep}>Next Step</button>
<button class="btn btn-primary" disabled={isNextButtonDisabled} onclick={nextStep}>
Next Step
<span class="btn-icon"></span>
</button>
</div>
</div>
<!-- Step 2: Property Details -->
<!-- Step 2: Property Selection & Market Analysis -->
<div class={step2Class} data-step="2">
<div class="step-header">
<h2>Property Details</h2>
<p>Enter comprehensive property information for your brochure</p>
<!-- Beautiful Header -->
<div class="step-header-gradient">
<h1 class="main-title">Property Brochure</h1>
<p class="subtitle">Professional Template</p>
</div>
<!-- Property Selector Dropdown -->
<div class="step2-content">
<!-- Property Selection -->
<div class="property-section">
<h3>Select Your Property</h3>
<p>Choose the property you want to create a brochure for</p>
<!-- Loading Indicator -->
<template if:true={isLoading}>
<div class="loading-indicator">
<span>Loading properties...</span>
</div>
</template>
<div class="property-selector">
<h3>Select Existing Property</h3>
<div class="property-selector-controls">
<select onchange={handlePropertySelection}>
<label for="propertySelect">Property:</label>
<select id="propertySelect" onchange={handlePropertySelection}>
<option value="">-- Select a Property --</option>
<template for:each={formattedPropertyOptions} for:item="property">
<option key={property.value} value={property.value}>
{property.label}
<template for:each={properties} for:item="property">
<option key={property.Id} value={property.Id}>
{property.Name} - {property.pcrm__Property_Type__c} - {property.pcrm__City_Bayut_Dubizzle__c}
</option>
</template>
</select>
<button type="button" class="btn btn-secondary btn-sm" onclick={manuallyLoadProperties} title="Refresh Properties">
🔄
</button>
</div>
<!-- Show message when no properties available -->
<template if:false={properties.length}>
<div class="no-properties-message" style="margin-top: 1rem; padding: 1rem; background-color: #f8f9fa; border: 1px solid #dee2e6; border-radius: 0.375rem; text-align: center;">
<p style="margin: 0; color: #6c757d; font-size: 14px;">
<strong>No properties found in your org.</strong><br>
Please create some Property__c records in Salesforce to see them here.<br>
You can still fill the form manually below.
</p>
<!-- Property Details Display -->
<template if:true={selectedPropertyId}>
<div class="property-details">
<h4>Selected Property Details</h4>
<div class="property-grid">
<div class="property-field">
<span class="label">Property Name:</span>
<span class="value">{propertyData.propertyName}</span>
</div>
</template>
<p style="margin-top: 0.5rem; font-size: 12px; color: #6c757d;">
Choose a property to auto-fill the form, or fill manually below
</p>
<div class="property-field">
<span class="label">Property Type:</span>
<span class="value">{propertyData.propertyType}</span>
</div>
<div class="form-grid">
<div class="form-group">
<label for="propertyName">Property Name *</label>
<input type="text" id="propertyName" name="propertyName" value={propertyData.propertyName} onchange={handleInputChange} required />
<div class="property-field">
<span class="label">Location:</span>
<span class="value">{propertyData.location}</span>
</div>
<div class="form-group">
<label for="propertyType">Property Type *</label>
<select id="propertyType" name="propertyType" value={propertyData.propertyType} onchange={handlePropertyTypeChange} required>
<option value="">Select Property Type</option>
<template for:each={formattedPropertyTypes} for:item="type">
<option key={type.value} value={type.value}>{type.label}</option>
</template>
</select>
<div class="property-field">
<span class="label">Price:</span>
<span class="value">{propertyData.price}</span>
</div>
<div class="form-group">
<label for="location">Location *</label>
<select id="location" name="location" value={propertyData.location} onchange={handleLocationChange} required>
<option value="">Select Location</option>
<template for:each={dubaiLocations} for:item="loc">
<option key={loc} value={loc}>{loc}</option>
</template>
</select>
<div class="property-field">
<span class="label">Bedrooms:</span>
<span class="value">{propertyData.bedrooms}</span>
</div>
<div class="form-group">
<label for="price">Price</label>
<input type="text" id="price" name="price" value={propertyData.price} onchange={handleInputChange} placeholder="e.g., AED 2,500,000" />
<div class="property-field">
<span class="label">Bathrooms:</span>
<span class="value">{propertyData.bathrooms}</span>
</div>
<div class="form-group">
<label for="bedrooms">Bedrooms</label>
<input type="number" id="bedrooms" name="bedrooms" value={propertyData.bedrooms} onchange={handleInputChange} min="0" />
</div>
<div class="form-group">
<label for="bathrooms">Bathrooms</label>
<input type="number" id="bathrooms" name="bathrooms" value={propertyData.bathrooms} onchange={handleInputChange} min="0" />
</div>
<div class="form-group">
<label for="area">Area (sq ft)</label>
<input type="number" id="area" name="area" value={propertyData.area} onchange={handleInputChange} min="0" />
</div>
<div class="form-group full-width">
<label for="titleEnglish">Property Title</label>
<input type="text" id="titleEnglish" name="titleEnglish" value={propertyData.titleEnglish} onchange={handleInputChange} placeholder="e.g., Luxury Marina View Apartment" />
</div>
<div class="form-group full-width">
<label for="description">Description *</label>
<textarea id="description" name="description" value={propertyData.description} onchange={handleInputChange} rows="4" placeholder="Describe the property features, amenities, and highlights..." required></textarea>
<div class="property-field">
<span class="label">Area:</span>
<span class="value">{propertyData.area}</span>
</div>
</div>
<div class="step-actions">
<button class="btn btn-secondary" onclick={previousStep}>Previous</button>
<button class="btn btn-primary" disabled={isNextButtonDisabled} onclick={nextStep}>Next Step</button>
</div>
</div>
<!-- Step 3: Additional Information -->
<div class={step3Class} data-step="3">
<div class="step-header">
<h2>Additional Information</h2>
<p>Add images, amenities, and market insights</p>
</div>
<div class="form-section">
<h3>Property Images</h3>
<div class="image-upload-section">
<input type="file" id="imageUpload" multiple accept="image/*" onchange={handleImageUpload} />
<label for="imageUpload" class="upload-btn">Choose Images</label>
</div>
<div class="uploaded-images" if:true={propertyData.images.length}>
<template for:each={propertyData.images} for:item="image" for:index="index">
<div key={image} class="image-item">
<img src={image.src} alt="Property Image" />
<input type="text" value={image.name} data-index={index} onchange={handleImageNameChange} placeholder="Room name" />
<button type="button" onclick={removeImage} data-index={index} class="remove-btn">Remove</button>
</div>
</template>
</div>
</div>
<div class="form-section">
<h3>Amenities</h3>
<div class="amenities-grid">
<template for:each={availableAmenities} for:item="amenity">
<label key={amenity} class="amenity-checkbox">
<input type="checkbox" value={amenity} onchange={handleAmenityChange} />
<span>{amenity}</span>
<!-- Market Analysis Options -->
<div class="market-analysis-section">
<h3>Market Analysis Options</h3>
<p>Select the market analysis features to include in your report</p>
<div class="market-options">
<label class="checkbox-item">
<input type="checkbox" name="includeMarketData" checked={marketAnalysis.includeMarketData} onchange={handleMarketAnalysisChange}>
<span class="checkmark"></span>
<span class="label-text">Market Trends & Analysis</span>
</label>
<label class="checkbox-item">
<input type="checkbox" name="includeROIAnalysis" checked={marketAnalysis.includeROIAnalysis} onchange={handleMarketAnalysisChange}>
<span class="checkmark"></span>
<span class="label-text">ROI Analysis & Projections</span>
</label>
<label class="checkbox-item">
<input type="checkbox" name="includeComparableSales" checked={marketAnalysis.includeComparableSales} onchange={handleMarketAnalysisChange}>
<span class="checkmark"></span>
<span class="label-text">Comparable Property Sales</span>
</label>
<label class="checkbox-item">
<input type="checkbox" name="includeRentalYield" checked={marketAnalysis.includeRentalYield} onchange={handleMarketAnalysisChange}>
<span class="checkmark"></span>
<span class="label-text">Rental Yield Analysis</span>
</label>
<label class="checkbox-item">
<input type="checkbox" name="includeGrowthProjection" checked={marketAnalysis.includeGrowthProjection} onchange={handleMarketAnalysisChange}>
<span class="checkmark"></span>
<span class="label-text">Market Growth Projections</span>
</label>
</div>
</div>
</div>
<div class="step-actions">
<button class="btn btn-secondary" onclick={previousStep}>
<span class="btn-icon"></span>
Previous
</button>
<button class="btn btn-primary" onclick={generateTemplateContent} disabled={isLoading}>
<template if:true={isLoading}>
<span class="loading-spinner"></span>
Generating...
</template>
<template if:false={isLoading}>
Generate Template
<span class="btn-icon"></span>
</template>
</div>
</div>
<div class="step-actions">
<button class="btn btn-secondary" onclick={previousStep}>Previous</button>
<button class="btn btn-primary" disabled={isNextButtonDisabled} onclick={nextStep}>Next Step</button>
</div>
</div>
<!-- Step 4: Preview & Generate -->
<div class={step4Class} data-step="4">
<div class="step-header">
<h2>Preview & Generate</h2>
<p>Review your brochure and generate the final PDF</p>
</div>
<div class="preview-section">
<div class="preview-content">
<h3>Brochure Summary</h3>
<div class="summary-grid">
<div class="summary-item">
<strong>Template:</strong> {selectedTemplateData.Name}
</div>
<div class="summary-item">
<strong>Property:</strong> {propertyData.propertyName}
</div>
<div class="summary-item">
<strong>Location:</strong> {propertyData.location}
</div>
<div class="summary-item">
<strong>Images:</strong> {propertyData.images.length} uploaded
</div>
</div>
</div>
<div class="preview-actions">
<button class="btn btn-primary" onclick={handlePreview} disabled={isLoading}>
{previewButtonText}
</button>
</div>
</div>
<div class="step-actions">
<button class="btn btn-secondary" onclick={previousStep}>Previous</button>
<button class="btn btn-success" onclick={nextStep} disabled={isDownloadButtonDisabled}>Continue to Download</button>
</div>
<!-- Step 3: HTML Editor -->
<div class={step3Class} data-step="3">
<!-- Beautiful Header -->
<div class="step-header-gradient">
<h1 class="main-title">Property Brochure</h1>
<p class="subtitle">Professional Template</p>
</div>
<!-- Step 5: Download PDF -->
<div class={step5Class} data-step="5">
<div class="step-header">
<h2>Download Your Brochure</h2>
<p>Your professional property brochure is ready for download</p>
</div>
<div class="download-section">
<div class="success-message">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 12L11 14L15 10M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<h3>Brochure Generated Successfully!</h3>
<p>Your professional property brochure has been created and is ready for download.</p>
</div>
<div class="download-actions">
<button class="btn btn-success btn-large" onclick={handleDownload} disabled={isLoading}>
{downloadButtonText}
<!-- Editor Container with Improved Layout -->
<div class="editor-container">
<!-- Left Toolbar -->
<div class="editor-toolbar left">
<!-- Document Actions -->
<div class="toolbar-section">
<div class="toolbar-section-title">Document Actions</div>
<div class="toolbar-group">
<button class="toolbar-button" onclick={handleSave}>
<lightning-icon icon-name="utility:save" size="x-small"></lightning-icon>
Save
</button>
<button class="btn btn-secondary" onclick={handleCreateNew}>Create New Brochure</button>
<button class="toolbar-button" onclick={handleReset}>
<lightning-icon icon-name="utility:refresh" size="x-small"></lightning-icon>
Reset
</button>
</div>
</div>
<!-- Insert Content -->
<div class="toolbar-section">
<div class="toolbar-section-title">Insert Content</div>
<div class="toolbar-group">
<button class="toolbar-button" onclick={insertText}>
<lightning-icon icon-name="utility:add" size="x-small"></lightning-icon>
Text
</button>
<button class="toolbar-button" onclick={insertImage}>
<lightning-icon icon-name="utility:image" size="x-small"></lightning-icon>
Image
</button>
<button class="toolbar-button" onclick={addShape}>
<lightning-icon icon-name="utility:shape" size="x-small"></lightning-icon>
Shape
</button>
<button class="toolbar-button" onclick={insertTable}>
<lightning-icon icon-name="utility:table" size="x-small"></lightning-icon>
Table
</button>
</div>
</div>
<!-- Text Formatting -->
<div class="toolbar-section">
<div class="toolbar-section-title">Text Formatting</div>
<div class="toolbar-group">
<label>Font Family:</label>
<select onchange={handleFontFamilyChange}>
<option value="Arial">Arial</option>
<option value="Times New Roman">Times New Roman</option>
<option value="Helvetica">Helvetica</option>
<option value="Georgia">Georgia</option>
<option value="Verdana">Verdana</option>
</select>
</div>
<div class="toolbar-group">
<label>Font Size:</label>
<select onchange={handleFontSizeChange}>
<option value="8px">8px</option>
<option value="10px">10px</option>
<option value="12px">12px</option>
<option value="14px">14px</option>
<option value="16px">16px</option>
<option value="18px">18px</option>
<option value="20px">20px</option>
<option value="24px">24px</option>
<option value="28px">28px</option>
<option value="32px">32px</option>
</select>
</div>
</div>
<!-- Text Styling -->
<div class="toolbar-section">
<div class="toolbar-section-title">Text Styling</div>
<div class="button-grid">
<button class="toolbar-button" onclick={handleBold}>
<lightning-icon icon-name="utility:bold" size="x-small"></lightning-icon>
B
</button>
<button class="toolbar-button" onclick={handleItalic}>
<lightning-icon icon-name="utility:italic" size="x-small"></lightning-icon>
I
</button>
<button class="toolbar-button" onclick={handleUnderline}>
<lightning-icon icon-name="utility:underline" size="x-small"></lightning-icon>
U
</button>
<button class="toolbar-button" onclick={handleHighlight}>
<lightning-icon icon-name="utility:highlighter" size="x-small"></lightning-icon>
Highlight
</button>
</div>
</div>
<!-- Text Alignment -->
<div class="toolbar-section">
<div class="toolbar-section-title">Text Alignment</div>
<div class="button-grid">
<button class="toolbar-button" onclick={handleAlignLeft}>
<lightning-icon icon-name="utility:left_align_text" size="x-small"></lightning-icon>
Left
</button>
<button class="toolbar-button" onclick={handleAlignCenter}>
<lightning-icon icon-name="utility:center_align_text" size="x-small"></lightning-icon>
Center
</button>
<button class="toolbar-button" onclick={handleAlignRight}>
<lightning-icon icon-name="utility:right_align_text" size="x-small"></lightning-icon>
Right
</button>
<button class="toolbar-button" onclick={handleJustify}>
<lightning-icon icon-name="utility:justify" size="x-small"></lightning-icon>
Justify
</button>
</div>
</div>
<!-- Lists & Indentation -->
<div class="toolbar-section">
<div class="toolbar-section-title">Lists & Indentation</div>
<div class="button-grid">
<button class="toolbar-button" onclick={handleBulletList}>
<lightning-icon icon-name="utility:bullet_list" size="x-small"></lightning-icon>
Bullet
</button>
<button class="toolbar-button" onclick={handleNumberList}>
<lightning-icon icon-name="utility:numbered_list" size="x-small"></lightning-icon>
Number
</button>
<button class="toolbar-button" onclick={handleIndent}>
<lightning-icon icon-name="utility:indent" size="x-small"></lightning-icon>
Indent
</button>
<button class="toolbar-button" onclick={handleOutdent}>
<lightning-icon icon-name="utility:outdent" size="x-small"></lightning-icon>
Outdent
</button>
</div>
</div>
<!-- Element Positioning -->
<div class="toolbar-section">
<div class="toolbar-section-title">Element Positioning</div>
<div class="button-grid">
<button class="toolbar-button" onclick={handleBringForward}>
<lightning-icon icon-name="utility:up" size="x-small"></lightning-icon>
Forward
</button>
<button class="toolbar-button" onclick={handleSendBackward}>
<lightning-icon icon-name="utility:down" size="x-small"></lightning-icon>
Backward
</button>
</div>
</div>
<!-- Colors -->
<div class="toolbar-section">
<div class="toolbar-section-title">Colors</div>
<div class="toolbar-group">
<label>Text Color:</label>
<input type="color" onchange={handleTextColorChange} value="#000000">
</div>
<div class="toolbar-group">
<label>Background:</label>
<input type="color" onchange={handleBackgroundColorChange} value="#ffffff">
</div>
</div>
</div>
<!-- Middle - Editor Content Area -->
<div class="editor-content-area">
<!-- Export PDF Button -->
<div class="export-pdf-section">
<lightning-button
variant="brand"
label="Export PDF"
onclick={generatePdfViaPythonApi}
disabled={isNextButtonDisabled}
class="slds-m-top_medium">
</lightning-button>
</div>
<!-- Single editable area for the template -->
<div class="preview-frame" contenteditable="true">
<!-- Template content will be loaded here -->
</div>
</div>
<!-- Right Toolbar - Removed, consolidated into left toolbar -->
</div>
</div>
<!-- PDF Preview Popup -->
<div if:true={showPdfPreview} class="pdf-preview-overlay">
<div class="pdf-preview-popup">
<div class="pdf-preview-header">
<h3>PDF Preview</h3>
<button class="close-btn" onclick={closePdfPreview}></button>
</div>
<div class="pdf-preview-content">
<div class="preview-frame" inner-html={editorContent}></div>
</div>
<div class="pdf-preview-actions">
<button class="toolbar-btn" onclick={closePdfPreview}>Cancel</button>
<button class="export-pdf-btn" onclick={generatePdfSimple}>📄 Generate & Download PDF</button>
</div>
</div>
</div>

View File

@ -1,5 +1,145 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
<actionOverrides>
<actionName>Accept</actionName>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Accept</actionName>
<formFactor>Large</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Accept</actionName>
<formFactor>Small</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>CancelEdit</actionName>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>CancelEdit</actionName>
<formFactor>Large</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>CancelEdit</actionName>
<formFactor>Small</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Clone</actionName>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Clone</actionName>
<formFactor>Large</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Clone</actionName>
<formFactor>Small</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Delete</actionName>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Delete</actionName>
<formFactor>Large</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Delete</actionName>
<formFactor>Small</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Edit</actionName>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Edit</actionName>
<formFactor>Large</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Edit</actionName>
<formFactor>Small</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>List</actionName>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>List</actionName>
<formFactor>Large</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>List</actionName>
<formFactor>Small</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>New</actionName>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>New</actionName>
<formFactor>Large</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>New</actionName>
<formFactor>Small</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>SaveEdit</actionName>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>SaveEdit</actionName>
<formFactor>Large</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>SaveEdit</actionName>
<formFactor>Small</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Tab</actionName>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Tab</actionName>
<formFactor>Large</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>Tab</actionName>
<formFactor>Small</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>View</actionName>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>View</actionName>
<formFactor>Large</formFactor>
<type>Default</type>
</actionOverrides>
<actionOverrides>
<actionName>View</actionName>
<formFactor>Small</formFactor>
<type>Default</type>
</actionOverrides>
<allowInChatterGroups>false</allowInChatterGroups>
<compactLayoutAssignment>SYSTEM</compactLayoutAssignment>
<deploymentStatus>Deployed</deploymentStatus>
@ -20,7 +160,7 @@
<type>AutoNumber</type>
</nameField>
<pluralLabel>Properties</pluralLabel>
<searchLayouts/>
<searchLayouts></searchLayouts>
<sharingModel>ReadWrite</sharingModel>
<visibility>Public</visibility>
</CustomObject>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Location__c</fullName>
<externalId>false</externalId>
<label>Location</label>
<required>false</required>
<trackTrending>false</trackTrending>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Property_Type__c</fullName>
<externalId>false</externalId>
<label>Property Type</label>
<required>false</required>
<trackTrending>false</trackTrending>

View File

@ -0,0 +1,29 @@
<apex:page controller="PropertyPdfGeneratorController" renderAs="pdf" showHeader="false" sidebar="false" standardStylesheets="false">
<html>
<head>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background: white;
}
.page-break {
page-break-before: always;
}
.no-break {
page-break-inside: avoid;
}
@page {
size: A4;
margin: 20mm;
}
</style>
</head>
<body>
<apex:outputPanel layout="block" styleClass="no-break">
<apex:outputText value="{!pdfContent}" escape="false" />
</apex:outputPanel>
</body>
</html>
</apex:page>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>64.0</apiVersion>
<availableInTouch>false</availableInTouch>
<confirmationTokenRequired>false</confirmationTokenRequired>
<label>Property PDF Generator</label>
</ApexPage>

1
node_modules/.bin/is-docker generated vendored
View File

@ -1 +0,0 @@
../is-docker/cli.js

1
node_modules/.bin/jsforce generated vendored
View File

@ -1 +0,0 @@
../jsforce/bin/jsforce

View File

@ -1 +0,0 @@
../jsforce/bin/jsforce-gen-schema

1
node_modules/.bin/tldts generated vendored
View File

@ -1 +0,0 @@
../tldts/bin/cli.js

1257
node_modules/.package-lock.json generated vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +0,0 @@
MIT License
Copyright (c) 2014-present Sebastian McKenzie and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,19 +0,0 @@
# @babel/runtime-corejs3
> babel's modular runtime helpers with core-js@3 polyfilling
See our website [@babel/runtime-corejs3](https://babeljs.io/docs/babel-runtime-corejs3) for more information.
## Install
Using npm:
```sh
npm install --save @babel/runtime-corejs3
```
or using yarn:
```sh
yarn add @babel/runtime-corejs3
```

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/array/from");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/array/is-array");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/array/of");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/clear-immediate");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/date/now");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/bind");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/code-point-at");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/concat");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/copy-within");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/ends-with");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/entries");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/every");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/fill");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/filter");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/find-index");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/find");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/flags");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/flat-map");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/flat");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/for-each");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/includes");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/index-of");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/keys");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/last-index-of");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/map");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/pad-end");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/pad-start");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/reduce-right");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/reduce");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/repeat");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/reverse");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/slice");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/some");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/sort");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/splice");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/starts-with");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/trim-end");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/trim-left");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/trim-right");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/trim-start");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/trim");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/instance/values");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/json/stringify");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/map");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/acosh");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/asinh");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/atanh");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/cbrt");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/clz32");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/cosh");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/expm1");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/fround");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/hypot");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/imul");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/log10");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/log1p");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/log2");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/sign");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/sinh");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/tanh");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/math/trunc");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/number/epsilon");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/number/is-finite");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/number/is-integer");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/number/is-nan");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/number/is-safe-integer");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/number/max-safe-integer");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/number/min-safe-integer");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/number/parse-float");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/number/parse-int");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/object/assign");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/object/create");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/object/define-properties");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/object/define-property");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/object/entries");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/object/freeze");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/object/from-entries");

View File

@ -1 +0,0 @@
module.exports = require("core-js-pure/stable/object/get-own-property-descriptor");

Some files were not shown because too many files have changed in this diff Show More