This commit is contained in:
Christophe Coenraets 2018-05-08 09:46:59 +02:00
Родитель a5aa340f5f
Коммит e672ee6ea1
15 изменённых файлов: 13 добавлений и 407 удалений

Просмотреть файл

@ -43,9 +43,12 @@ Dreamhouse is a sample application for the real estate business built on the Sal
### Lightning Components
DreamHouse features a large number of Lightning Components to enhance the user experience. Lightning Components are used on the Property record page, on an app pages (**Property Finder** and **Property Explorer**), in the utility bar, and as quick actions.
Installing a Lightning component as a quick action can be a great alternative to adding the component directly to the page layout because the component instantiation is deferred until the action button is clicked (lazy instantiation). Installing less frequently used components as quick or global actions can contribute to a faster page loading time, and a streamlined user interface. In DreamHouse, the [SmartHome](force-app/main/default/aura/SmartHome) component is installed as a quick action on the Property record page.
Installing a Lightning component as a **quick action)) can be a great alternative to adding the component directly to the page layout because the component instantiation is deferred until the action button is clicked (lazy instantiation). Installing less frequently used components as quick or global actions can contribute to a faster page loading time, and a streamlined user interface. In DreamHouse, the [SmartHome](force-app/main/default/aura/SmartHome) component is installed as a quick action on the Property record page.
The utility bar is a great place to host components you always want at your fingertips. [MortgageCalculator](force-app/main/default/aura/MortgageCalculator) is a great example.
The **utility bar** is a great place to host components you always want at your fingertips. [MortgageCalculator](force-app/main/default/aura/MortgageCalculator) is a great example.
### Base Lightning Components
Base Lightning Components are a set of powerful UI components available in the Lightning Component Framework. The DreamHouse custom components use many Base Lightning Components as building blocks. For example, [PropertyCarousel](force-app/main/default/aura/PropertyCarousel/PropertyCarousel.cmp), which allows you to navigate through the pictures of a property and upload new pictures, is built using **lightning:carousel** and **lightning:fileUpload**. [PropertySummary](force-app/main/default/aura/PropertySummary/PropertySummary.cmp) leverages **lightning:formattedAddress** and **lightning:formattedNumber**.
### Lightning Data Service
Lightning Data Service allows you to manipulate (retrieve, create, update, delete) Salesforce records without writing server-side code (Apex). In DreamHouse, all the Lightning components that work with a single Property record use Lightning Data Service. Check out [PropertySummary](force-app/main/default/aura/PropertySummary) for an example.
@ -53,13 +56,7 @@ Lightning Data Service allows you to manipulate (retrieve, create, update, delet
### Third-Party JavaScript Libraries
You can use third-party JavaScript libraries in Lightning Components using **ltng:require**. For example:
- [Map](force-app/main/default/aura/Map) and [PropertyListMap](force-app/main/default/aura/PropertyListMap) use the [Leaflet](https://leafletjs.com/) library.
- [PriceRange](force-app/main/default/aura/PropertyListMap) uses [nouislider](https://refreshless.com/nouislider/)'s double slider.
### Custom Page Templates
Custom Page Templates allow you to create ad hoc page layouts that admins can use in App Builder to create new pages. Custom Page Templates are implemented as Lightning Components. There are two custom page templates in Dreamhouse: [PageTemplate_2_6_4](force-app/main/default/aura/PageTemplate_2_6_4/PageTemplate_2_6_4.cmp) (used by the **Property Finder** page) and [PageTemplate_2_7_3](force-app/main/default/aura/PageTemplate_2_7_3/PageTemplate_2_7_3.cmp) (used by the **Property Explorer** page). They provide custom three column layouts using different relative widths for each column.
### Base Lightning Components
Base Lightning Components are a set of powerful UI components available in the Lightning Component Framework. The DreamHouse custom components use many Base Lightning Components as building blocks. For example, [PropertyCarousel](force-app/main/default/aura/PropertyCarousel/PropertyCarousel.cmp) which allows you to navigate through the pictures of a property and upload new pictures is built using **lightning:carousel** and **lightning:fileUpload**. [PropertySummary](force-app/main/default/aura/PropertySummary/PropertySummary.cmp) leverages **lightning:formattedAddress** and **lightning:formattedNumber**.
- [PriceRange](force-app/main/default/aura/PropertyListMap) uses the [nouislider](https://refreshless.com/nouislider/) library for its double slider.
### Standard Application Events
Standard application events are available by default in the framework and are used to trigger high level actions. For example, in [PropertySummary](force-app/main/default/aura/PropertySummary/PropertySummaryController.js), **force:navigateToSObject** is used to navigate to a record, and **force:editRecord** is used to edit a record "in place."
@ -70,6 +67,9 @@ Application events are used for communication between components in App Builder.
### Component Events
Component events are used for finer-grained communication between components. For example, the [PropertyPaginator](force-app/main/default/aura/PropertyProperty) component fires the **pageNext** and **pagePrevious** events to notify its parent ([PropetyTileList](force-app/main/default/aura/PropertyTileList)) that the user requested the next or previous page.
### Custom Page Templates
Custom Page Templates allow you to create ad hoc page layouts that admins can use in App Builder to create new pages. Custom Page Templates are implemented as Lightning Components. There are two custom page templates in Dreamhouse: [PageTemplate_2_6_4](force-app/main/default/aura/PageTemplate_2_6_4/PageTemplate_2_6_4.cmp) (used by the **Property Finder** page) and [PageTemplate_2_7_3](force-app/main/default/aura/PageTemplate_2_7_3/PageTemplate_2_7_3.cmp) (used by the **Property Explorer** page). They provide custom three column layouts using different relative widths for each column.
### Reports and Dashboards
Reports and dashboards are easy to create and look great in Lightning. Just to get things started, the DreamHouse app includes a few reports in the DreamHouse Reports folder (**Days on Market**, **Properties by Broker**, and **Portfolio Health**).

Просмотреть файл

@ -1,7 +1,7 @@
<aura:component access="global">
<ltng:require styles="{!$Resource.leaflet1 + '/leaflet.css'}"
scripts="{!$Resource.leaflet1 + '/leaflet.js'}"
<ltng:require styles="{!$Resource.leaflet + '/leaflet.css'}"
scripts="{!$Resource.leaflet + '/leaflet.js'}"
afterScriptsLoaded="{!c.jsLoaded}" />
<aura:attribute name="location" type="SObject"/>

Просмотреть файл

@ -1,31 +0,0 @@
<aura:component controller="PropertyController" implements="flexipage:availableForAllPageTypes" access="global">
<aura:attribute name="properties" type="Property__c[]" />
<aura:attribute name="chartModel" type="Object[]" />
<aura:attribute name="maxDaysOnMarket" type="Integer" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<lightning:card title="Properties by days on the market" iconName="custom:custom85">
<table>
<aura:iteration items="{!v.chartModel}" var="item" indexVar="index">
<tr>
<td class="col-address">
<div class="slds-truncate">
<a data-id="{#item.id}" onclick="{!c.navigateToRecord}">{#item.address}, {#item.city}</a>
</div>
</td>
<td class="col-days">
<div class="slds-truncate">{#item.daysOnMarket} days</div>
</td>
<td>
<div class="{# 'bar ' + item.status}" data-id="{#item.id}" onclick="{!c.barClickHandler}" style="{# 'width:' + (item.daysOnMarket / v.maxDaysOnMarket * 100) + '%'}"></div>
</td>
</tr>
</aura:iteration>
</table>
</lightning:card>
</aura:component>

Просмотреть файл

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<AuraDefinitionBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>42.0</apiVersion>
<description>A Lightning Component Bundle</description>
</AuraDefinitionBundle>

Просмотреть файл

@ -1,62 +0,0 @@
.THIS {
box-sizing: border-box;
padding-right: 8px;
}
.THIS h3 {
display: inline;
margin-left: 8px;
}
.THIS .title {
margin: 8px 0 16px 0;
}
.THIS .bar {
box-sizing: border-box;
display: inline-block;
height: 24px;
margin: 2px 0 -2px 0;
}
.THIS .bar.green {
background-color: #00716B;
}
.THIS .bar.orange {
background-color: #FFB75D;
}
.THIS .bar.red {
background-color: #C23934;
}
.THIS table {
box-sizing: border-box;
}
.THIS tr {
box-sizing: border-box;
border-bottom: solid 1px rgb(216, 221, 230);
padding: 2px 0;
}
.THIS .col-address {
width: 180px;
}
.THIS .col-days {
width: 60px;
text-align: right;
padding-right: 8px;
}
.THIS .col-date {
width: 80px;
text-align: right;
padding-right: 6px;
}
.THIS .slds-card__body {
margin: 16px;
}

Просмотреть файл

@ -1,3 +0,0 @@
<design:component label="Days on the Market Chart">
</design:component>

Просмотреть файл

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="100px" height="100px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 39.1 (31720) - http://www.bohemiancoding.com/sketch -->
<title>Slice</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="Rectangle" fill="#699BE1" x="0" y="0" width="100" height="100" rx="8"></rect>
<path d="M79.5333333,17 L21.4666667,17 C19.01,17 17,19.01 17,21.4666667 L17,30.4 C17,32.8566667 19.01,34.8666667 21.4666667,34.8666667 L79.5333333,34.8666667 C81.99,34.8666667 84,32.8566667 84,30.4 L84,21.4666667 C84,19.01 81.99,17 79.5333333,17 L79.5333333,17 Z M51.6166667,30.4 L51.6166667,21.4666667 L79.5333333,21.4666667 L79.5333333,30.4 L51.6166667,30.4 L51.6166667,30.4 Z M79.5333333,41.5666667 L21.4666667,41.5666667 C19.01,41.5666667 17,43.5766667 17,46.0333333 L17,54.9666667 C17,57.4233333 19.01,59.4333333 21.4666667,59.4333333 L79.5333333,59.4333333 C81.99,59.4333333 84,57.4233333 84,54.9666667 L84,46.0333333 C84,43.5766667 81.99,41.5666667 79.5333333,41.5666667 L79.5333333,41.5666667 Z M41.5666667,54.9666667 L41.5666667,46.0333333 L79.5333333,46.0333333 L79.5333333,54.9666667 L41.5666667,54.9666667 L41.5666667,54.9666667 Z M79.5333333,66.1333333 L21.4666667,66.1333333 C19.01,66.1333333 17,68.1433333 17,70.6 L17,79.5333333 C17,81.99 19.01,84 21.4666667,84 L79.5333333,84 C81.99,84 84,81.99 84,79.5333333 L84,70.6 C84,68.1433333 81.99,66.1333333 79.5333333,66.1333333 L79.5333333,66.1333333 Z M61.6666667,79.5333333 L61.6666667,70.6 L79.5333333,70.6 L79.5333333,79.5333333 L61.6666667,79.5333333 L61.6666667,79.5333333 Z" id="Shape" fill="#FFFFFF"></path>
</g>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Просмотреть файл

@ -1,56 +0,0 @@
({
doInit : function(component) {
var action = component.get("c.getAvailableProperties");
action.setStorable();
action.setCallback(this, function(response) {
var result = response.getReturnValue();
var chartModel = [];
for (var i=0; i<result.length; i=i+1) {
var property = result[i],
status;
if (property.Date_Listed__c && !property.Date_Agreement__c) {
var dateListed = new Date(property.Date_Listed__c);
var daysOnMarket = property.Days_On_Market__c;
if (daysOnMarket>60) {
status="red";
} else if (daysOnMarket>30) {
status="orange";
} else {
status="green";
}
chartModel.push({
id: property.Id,
address: property.Address__c,
city: property.City__c,
dateListed: property.Date_Listed__c,
daysOnMarket: daysOnMarket,
status: status
});
}
}
var maxDaysOnMarket = 0;
chartModel.forEach(function(house) {
if (house.daysOnMarket > maxDaysOnMarket) {
maxDaysOnMarket = house.daysOnMarket;
}
});
component.set("v.chartModel", chartModel);
component.set("v.properties", result);
component.set("v.maxDaysOnMarket", maxDaysOnMarket);
});
$A.enqueueAction(action);
},
barClickHandler : function(component, event) {
var myEvent = $A.get("e.ltng:selectSObject");
myEvent.setParams({"recordId": event.target.dataset.id, channel: "Properties"});
myEvent.fire();
},
navigateToRecord : function(component, event) {
var myEvent = $A.get("e.force:navigateToSObject");
myEvent.setParams({"recordId": event.target.dataset.id, slideDevName: "detail"});
myEvent.fire();
}
})

Просмотреть файл

@ -1,5 +0,0 @@
({
helperMethod : function() {
}
})

Просмотреть файл

@ -1,7 +1,7 @@
<aura:component implements="flexipage:availableForAllPageTypes" controller="PropertyController" access="global">
<ltng:require styles="{!$Resource.leaflet1 + '/leaflet.css'}"
scripts="{!$Resource.leaflet1 + '/leaflet.js'}"
<ltng:require styles="{!$Resource.leaflet + '/leaflet.css'}"
scripts="{!$Resource.leaflet + '/leaflet.js'}"
afterScriptsLoaded="{!c.onJSLoaded}" />
<aura:attribute name="searchKey" type="String" default=""/>

Просмотреть файл

@ -1,211 +0,0 @@
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
define(factory);
} else if (typeof exports === 'object') {
module.exports = factory(require, exports, module);
} else {
root.CountUp = factory();
}
}(this, function(require, exports, module) {
/*
countUp.js
by @inorganik
*/
// target = id of html element or var of previously selected html element where counting occurs
// startVal = the value you want to begin at
// endVal = the value you want to arrive at
// decimals = number of decimal places, default 0
// duration = duration of animation in seconds, default 2
// options = optional object of options (see below)
var CountUp = function(target, startVal, endVal, decimals, duration, options) {
// make sure requestAnimationFrame and cancelAnimationFrame are defined
// polyfill for browsers without native support
// by Opera engineer Erik Möller
var lastTime = 0;
var vendors = ['webkit', 'moz', 'ms', 'o'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame =
window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
timeToCall);
lastTime = currTime + timeToCall;
return id;
};
}
if (!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}
var self = this;
// default options
self.options = {
useEasing : true, // toggle easing
useGrouping : true, // 1,000,000 vs 1000000
separator : ',', // character to use as a separator
decimal : '.', // character to use as a decimal
easingFn: null, // optional custom easing closure function, default is Robert Penner's easeOutExpo
formattingFn: null // optional custom formatting function, default is self.formatNumber below
};
// extend default options with passed options object
for (var key in options) {
if (options.hasOwnProperty(key)) {
self.options[key] = options[key];
}
}
if (self.options.separator === '') { self.options.useGrouping = false; }
if (!self.options.prefix) self.options.prefix = '';
if (!self.options.suffix) self.options.suffix = '';
self.d = (typeof target === 'string') ? document.getElementById(target) : target;
self.startVal = Number(startVal);
self.endVal = Number(endVal);
self.countDown = (self.startVal > self.endVal);
self.frameVal = self.startVal;
self.decimals = Math.max(0, decimals || 0);
self.dec = Math.pow(10, self.decimals);
self.duration = Number(duration) * 1000 || 2000;
self.formatNumber = function(nStr) {
nStr = nStr.toFixed(self.decimals);
nStr += '';
var x, x1, x2, rgx;
x = nStr.split('.');
x1 = x[0];
x2 = x.length > 1 ? self.options.decimal + x[1] : '';
rgx = /(\d+)(\d{3})/;
if (self.options.useGrouping) {
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + self.options.separator + '$2');
}
}
return self.options.prefix + x1 + x2 + self.options.suffix;
};
// Robert Penner's easeOutExpo
self.easeOutExpo = function(t, b, c, d) {
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
};
self.easingFn = self.options.easingFn ? self.options.easingFn : self.easeOutExpo;
self.formattingFn = self.options.formattingFn ? self.options.formattingFn : self.formatNumber;
self.version = function () { return '1.7.1'; };
// Print value to target
self.printValue = function(value) {
var result = self.formattingFn(value);
if (self.d.tagName === 'INPUT') {
this.d.value = result;
}
else if (self.d.tagName === 'text' || self.d.tagName === 'tspan') {
this.d.textContent = result;
}
else {
this.d.innerHTML = result;
}
};
self.count = function(timestamp) {
if (!self.startTime) { self.startTime = timestamp; }
self.timestamp = timestamp;
var progress = timestamp - self.startTime;
self.remaining = self.duration - progress;
// to ease or not to ease
if (self.options.useEasing) {
if (self.countDown) {
self.frameVal = self.startVal - self.easingFn(progress, 0, self.startVal - self.endVal, self.duration);
} else {
self.frameVal = self.easingFn(progress, self.startVal, self.endVal - self.startVal, self.duration);
}
} else {
if (self.countDown) {
self.frameVal = self.startVal - ((self.startVal - self.endVal) * (progress / self.duration));
} else {
self.frameVal = self.startVal + (self.endVal - self.startVal) * (progress / self.duration);
}
}
// don't go past endVal since progress can exceed duration in the last frame
if (self.countDown) {
self.frameVal = (self.frameVal < self.endVal) ? self.endVal : self.frameVal;
} else {
self.frameVal = (self.frameVal > self.endVal) ? self.endVal : self.frameVal;
}
// decimal
self.frameVal = Math.round(self.frameVal*self.dec)/self.dec;
// format and print value
self.printValue(self.frameVal);
// whether to continue
if (progress < self.duration) {
self.rAF = requestAnimationFrame(self.count);
} else {
if (self.callback) { self.callback(); }
}
};
// start your animation
self.start = function(callback) {
self.callback = callback;
self.rAF = requestAnimationFrame(self.count);
return false;
};
// toggles pause/resume animation
self.pauseResume = function() {
if (!self.paused) {
self.paused = true;
cancelAnimationFrame(self.rAF);
} else {
self.paused = false;
delete self.startTime;
self.duration = self.remaining;
self.startVal = self.frameVal;
requestAnimationFrame(self.count);
}
};
// reset to startVal so animation can be run again
self.reset = function() {
self.paused = false;
delete self.startTime;
self.startVal = startVal;
cancelAnimationFrame(self.rAF);
self.printValue(self.startVal);
};
// pass a new endVal and start animation
self.update = function (newEndVal) {
cancelAnimationFrame(self.rAF);
self.paused = false;
delete self.startTime;
self.startVal = self.frameVal;
self.endVal = Number(newEndVal);
self.countDown = (self.startVal > self.endVal);
self.rAF = requestAnimationFrame(self.count);
};
// format startVal on initialization
self.printValue(self.startVal);
};
return CountUp;
}));

Просмотреть файл

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<StaticResource xmlns="http://soap.sforce.com/2006/04/metadata">
<cacheControl>Private</cacheControl>
<contentType>application/javascript</contentType>
</StaticResource>

Двоичный файл не отображается.

Двоичный файл не отображается.

Просмотреть файл

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<StaticResource xmlns="http://soap.sforce.com/2006/04/metadata">
<cacheControl>Private</cacheControl>
<contentType>application/zip</contentType>
</StaticResource>