template to pdf
This commit is contained in:
parent
c838ffa600
commit
ab0b08ee34
@ -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();
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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) : '';
|
||||
|
||||
// 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';
|
||||
// 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';
|
||||
|
||||
List<pcrm__Property__c> properties = Database.query(query);
|
||||
|
||||
System.debug('=== PROPERTIES FETCHED FROM PCRM ===');
|
||||
System.debug('Total properties found: ' + properties.size());
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
properties.add(wrapper);
|
||||
}
|
||||
return properties;
|
||||
|
||||
} catch (Exception e) {
|
||||
System.debug('Error fetching properties: ' + e.getMessage());
|
||||
// Return empty list if there's an error
|
||||
System.debug('Stack trace: ' + e.getStackTraceString());
|
||||
throw new AuraHandledException('Failed to fetch properties: ' + e.getMessage());
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
@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
|
||||
];
|
||||
|
||||
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) : '';
|
||||
System.debug('=== FETCHING COMPLETE PROPERTY DETAILS FROM PCRM ===');
|
||||
System.debug('Property 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';
|
||||
// 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';
|
||||
|
||||
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.';
|
||||
@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;
|
||||
}
|
||||
|
||||
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.';
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -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>';
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
@ -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>
|
||||
|
||||
@ -1,42 +1,52 @@
|
||||
[
|
||||
{
|
||||
"Name": "Luxury Marina View Apartment",
|
||||
"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",
|
||||
"Property_Type__c": "Villa",
|
||||
"Location__c": "Palm Jumeirah"
|
||||
},
|
||||
{
|
||||
"Name": "Dubai Hills Estate Townhouse",
|
||||
"Property_Type__c": "Townhouse",
|
||||
"Location__c": "Dubai Hills Estate"
|
||||
},
|
||||
{
|
||||
"Name": "Arabian Ranches Villa",
|
||||
"Property_Type__c": "Villa",
|
||||
"Location__c": "Arabian Ranches"
|
||||
}
|
||||
{
|
||||
"Name": "PR-00001",
|
||||
"Property_Type__c": "Apartment",
|
||||
"Location__c": "Downtown Dubai"
|
||||
},
|
||||
{
|
||||
"Name": "PR-00002",
|
||||
"Property_Type__c": "Villa",
|
||||
"Location__c": "Palm Jumeirah"
|
||||
},
|
||||
{
|
||||
"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": "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"
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
@ -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>
|
||||
<!-- 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>
|
||||
</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>
|
||||
</div>
|
||||
|
||||
<!-- Selected Template Indicator -->
|
||||
<template if:true={customBlankSelected}>
|
||||
<div class="selected-indicator">
|
||||
<span class="selected-icon">✓</span>
|
||||
<span class="selected-text">Selected</span>
|
||||
<!-- 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>
|
||||
</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 class="newsletter-main">
|
||||
<h1>START FROM SCRATCH</h1>
|
||||
<p>Create your own custom property presentation with complete creative freedom.</p>
|
||||
</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 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>
|
||||
</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,265 +74,519 @@
|
||||
</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}>
|
||||
<template if:true={everkindTemplateSelected}>
|
||||
<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}>
|
||||
<div class="selected-indicator">
|
||||
<span class="selected-icon">✓</span>
|
||||
<span class="selected-text">Selected</span>
|
||||
</div>
|
||||
</template>
|
||||
</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>
|
||||
|
||||
<!-- Selected Template Indicator -->
|
||||
<template if:true={template6Selected}>
|
||||
<div class="selected-indicator">
|
||||
<span class="selected-icon">✓</span>
|
||||
<span class="selected-text">Selected</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step-actions">
|
||||
<button class="btn btn-primary" disabled={isNextButtonDisabled} onclick={nextStep}>Next Step</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 2: Property Details -->
|
||||
<div class={step2Class} data-step="2">
|
||||
<div class="step-header">
|
||||
<h2>Property Details</h2>
|
||||
<p>Enter comprehensive property information for your brochure</p>
|
||||
</div>
|
||||
|
||||
<!-- Property Selector Dropdown -->
|
||||
<div class="property-selector">
|
||||
<h3>Select Existing Property</h3>
|
||||
<div class="property-selector-controls">
|
||||
<select onchange={handlePropertySelection}>
|
||||
<option value="">-- Select a Property --</option>
|
||||
<template for:each={formattedPropertyOptions} for:item="property">
|
||||
<option key={property.value} value={property.value}>
|
||||
{property.label}
|
||||
</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>
|
||||
<!-- Modern Apartment Template -->
|
||||
<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>
|
||||
|
||||
<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>
|
||||
</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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
</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>
|
||||
<button class="btn btn-primary" disabled={isNextButtonDisabled} onclick={nextStep}>
|
||||
Next Step
|
||||
<span class="btn-icon">→</span>
|
||||
</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>
|
||||
<!-- Step 2: Property Selection & Market Analysis -->
|
||||
<div class={step2Class} data-step="2">
|
||||
<!-- Beautiful Header -->
|
||||
<div class="step-header-gradient">
|
||||
<h1 class="main-title">Property Brochure</h1>
|
||||
<p class="subtitle">Professional Template</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 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">
|
||||
<label for="propertySelect">Property:</label>
|
||||
<select id="propertySelect" onchange={handlePropertySelection}>
|
||||
<option value="">-- Select a Property --</option>
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<!-- 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>
|
||||
<div class="property-field">
|
||||
<span class="label">Property Type:</span>
|
||||
<span class="value">{propertyData.propertyType}</span>
|
||||
</div>
|
||||
<div class="property-field">
|
||||
<span class="label">Location:</span>
|
||||
<span class="value">{propertyData.location}</span>
|
||||
</div>
|
||||
<div class="property-field">
|
||||
<span class="label">Price:</span>
|
||||
<span class="value">{propertyData.price}</span>
|
||||
</div>
|
||||
<div class="property-field">
|
||||
<span class="label">Bedrooms:</span>
|
||||
<span class="value">{propertyData.bedrooms}</span>
|
||||
</div>
|
||||
<div class="property-field">
|
||||
<span class="label">Bathrooms:</span>
|
||||
<span class="value">{propertyData.bathrooms}</span>
|
||||
</div>
|
||||
<div class="property-field">
|
||||
<span class="label">Area:</span>
|
||||
<span class="value">{propertyData.area}</span>
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
</template>
|
||||
|
||||
<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}>Previous</button>
|
||||
<button class="btn btn-primary" disabled={isNextButtonDisabled} onclick={nextStep}>Next Step</button>
|
||||
<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>
|
||||
</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>
|
||||
<!-- 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>
|
||||
|
||||
<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}
|
||||
<!-- 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="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 class="summary-item">
|
||||
<strong>Property:</strong> {propertyData.propertyName}
|
||||
</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 class="summary-item">
|
||||
<strong>Location:</strong> {propertyData.location}
|
||||
</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 class="summary-item">
|
||||
<strong>Images:</strong> {propertyData.images.length} uploaded
|
||||
</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>
|
||||
|
||||
<div class="preview-actions">
|
||||
<button class="btn btn-primary" onclick={handlePreview} disabled={isLoading}>
|
||||
{previewButtonText}
|
||||
</button>
|
||||
<!-- 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>
|
||||
|
||||
<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>
|
||||
|
||||
<!-- Right Toolbar - Removed, consolidated into left toolbar -->
|
||||
</div>
|
||||
</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>
|
||||
<!-- 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="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 class="pdf-preview-content">
|
||||
<div class="preview-frame" inner-html={editorContent}></div>
|
||||
</div>
|
||||
|
||||
<div class="download-actions">
|
||||
<button class="btn btn-success btn-large" onclick={handleDownload} disabled={isLoading}>
|
||||
{downloadButtonText}
|
||||
</button>
|
||||
<button class="btn btn-secondary" onclick={handleCreateNew}>Create New Brochure</button>
|
||||
<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>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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>
|
||||
</CustomObject>
|
||||
|
||||
@ -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>
|
||||
@ -62,4 +61,4 @@
|
||||
</value>
|
||||
</valueSetDefinition>
|
||||
</valueSet>
|
||||
</CustomField>
|
||||
</CustomField>
|
||||
|
||||
@ -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>
|
||||
@ -47,4 +46,4 @@
|
||||
</value>
|
||||
</valueSetDefinition>
|
||||
</valueSet>
|
||||
</CustomField>
|
||||
</CustomField>
|
||||
|
||||
29
force-app/main/default/pages/PropertyPdfGenerator.page
Normal file
29
force-app/main/default/pages/PropertyPdfGenerator.page
Normal 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>
|
||||
@ -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
1
node_modules/.bin/is-docker
generated
vendored
@ -1 +0,0 @@
|
||||
../is-docker/cli.js
|
||||
1
node_modules/.bin/jsforce
generated
vendored
1
node_modules/.bin/jsforce
generated
vendored
@ -1 +0,0 @@
|
||||
../jsforce/bin/jsforce
|
||||
1
node_modules/.bin/jsforce-gen-schema
generated
vendored
1
node_modules/.bin/jsforce-gen-schema
generated
vendored
@ -1 +0,0 @@
|
||||
../jsforce/bin/jsforce-gen-schema
|
||||
1
node_modules/.bin/tldts
generated
vendored
1
node_modules/.bin/tldts
generated
vendored
@ -1 +0,0 @@
|
||||
../tldts/bin/cli.js
|
||||
1257
node_modules/.package-lock.json
generated
vendored
1257
node_modules/.package-lock.json
generated
vendored
File diff suppressed because it is too large
Load Diff
22
node_modules/@babel/runtime-corejs3/LICENSE
generated
vendored
22
node_modules/@babel/runtime-corejs3/LICENSE
generated
vendored
@ -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.
|
||||
19
node_modules/@babel/runtime-corejs3/README.md
generated
vendored
19
node_modules/@babel/runtime-corejs3/README.md
generated
vendored
@ -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
|
||||
```
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/array/from.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/array/from.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/array/from");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/array/is-array.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/array/is-array.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/array/is-array");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/array/of.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/array/of.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/array/of");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/clear-immediate.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/clear-immediate.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/clear-immediate");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/date/now.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/date/now.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/date/now");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/bind.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/bind.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/bind");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/code-point-at.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/code-point-at.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/code-point-at");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/concat.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/concat.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/concat");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/copy-within.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/copy-within.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/copy-within");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/ends-with.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/ends-with.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/ends-with");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/entries.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/entries.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/entries");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/every.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/every.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/every");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/fill.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/fill.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/fill");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/filter.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/filter.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/filter");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/find-index.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/find-index.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/find-index");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/find.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/find.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/find");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/flags.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/flags.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/flags");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/flat-map.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/flat-map.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/flat-map");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/flat.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/flat.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/flat");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/for-each.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/for-each.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/for-each");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/includes.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/includes.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/includes");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/index-of.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/index-of.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/index-of");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/keys.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/keys.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/keys");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/last-index-of.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/last-index-of.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/last-index-of");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/map.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/map.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/map");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/pad-end.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/pad-end.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/pad-end");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/pad-start.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/pad-start.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/pad-start");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/reduce-right.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/reduce-right.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/reduce-right");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/reduce.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/reduce.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/reduce");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/repeat.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/repeat.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/repeat");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/reverse.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/reverse.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/reverse");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/slice.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/slice.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/slice");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/some.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/some.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/some");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/sort.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/sort.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/sort");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/splice.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/splice.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/splice");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/starts-with.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/starts-with.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/starts-with");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/trim-end.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/trim-end.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/trim-end");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/trim-left.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/trim-left.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/trim-left");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/trim-right.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/trim-right.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/trim-right");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/trim-start.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/trim-start.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/trim-start");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/trim.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/trim.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/trim");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/values.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/instance/values.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/instance/values");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/json/stringify.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/json/stringify.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/json/stringify");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/map.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/map.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/map");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/acosh.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/acosh.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/acosh");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/asinh.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/asinh.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/asinh");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/atanh.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/atanh.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/atanh");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/cbrt.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/cbrt.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/cbrt");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/clz32.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/clz32.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/clz32");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/cosh.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/cosh.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/cosh");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/expm1.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/expm1.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/expm1");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/fround.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/fround.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/fround");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/hypot.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/hypot.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/hypot");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/imul.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/imul.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/imul");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/log10.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/log10.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/log10");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/log1p.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/log1p.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/log1p");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/log2.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/log2.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/log2");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/sign.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/sign.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/sign");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/sinh.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/sinh.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/sinh");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/tanh.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/tanh.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/tanh");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/trunc.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/math/trunc.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/math/trunc");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/epsilon.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/epsilon.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/number/epsilon");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/is-finite.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/is-finite.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/number/is-finite");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/is-integer.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/is-integer.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/number/is-integer");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/is-nan.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/is-nan.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/number/is-nan");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/is-safe-integer.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/is-safe-integer.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/number/is-safe-integer");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/max-safe-integer.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/max-safe-integer.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/number/max-safe-integer");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/min-safe-integer.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/min-safe-integer.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/number/min-safe-integer");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/parse-float.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/parse-float.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/number/parse-float");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/parse-int.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/number/parse-int.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/number/parse-int");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/object/assign.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/object/assign.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/object/assign");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/object/create.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/object/create.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/object/create");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/object/define-properties.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/object/define-properties.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/object/define-properties");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/object/define-property.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/object/define-property.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/object/define-property");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/object/entries.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/object/entries.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/object/entries");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/object/freeze.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/object/freeze.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/object/freeze");
|
||||
1
node_modules/@babel/runtime-corejs3/core-js-stable/object/from-entries.js
generated
vendored
1
node_modules/@babel/runtime-corejs3/core-js-stable/object/from-entries.js
generated
vendored
@ -1 +0,0 @@
|
||||
module.exports = require("core-js-pure/stable/object/from-entries");
|
||||
@ -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
Loading…
Reference in New Issue
Block a user