
In this post I will explain you about How to create Dynamic LWC banner. Why we need to implement dynamic banner. Benefit of dynamic banner and Real life practical use case scenario.
A common challenge in application development and support is managing user communication during deployments or maintenance. Instead of time-consuming manual emails, our solution centralizes this process.
Consider two scenarios:
- Scenario 1: Scheduled Events – For planned deployments or maintenance, business managers often spend a lot of time drafting and sending emails to all users.
- Scenario 2: Targeted Messaging – Managers also need to send urgent warnings, general information, or release notes to specific user groups, such as by region (e.g., US, EMEA, APAC, CALA).
Our proposed solution lets business managers dynamically manage these communications directly within Salesforce. This content, including warnings, information, and maintenance notices, is then displayed on the application’s dashboard. This means that instead of receiving an email, users will immediately see the relevant message the moment they log in, ensuring they are always informed.
I have implemented this Dynamic Banner feature using LWC, APEX and configurations. In below screen you can see the Banner Config Page. Only Admin would have access of Banner Config tab. You can control accessibility of this page using permission set.

- Select Region for Banner Visibility (you create different banner as per region)
- Banner type ( Warning , Info, Maintenance)
- Select your banner Image
- Add Custom message
- Pick Banner background color
- Add custom link
- Start Date and End Date
- Active
- Preview Banner, Save and Cancel buttons
- Table to show list of banner created.
Technical changes as below.
Create Object(AD_Banner__c) and fields like (Active__c,Banner_Type__c,colorPickerVal__c,customMessage__c,End_Date__c,Region_avaiable__c, Start_Date__c,UrlVal__c,VisualPickerID__c,Status_Value__c)



Create Region field in User Object and custom label as per screenshot below


Upload below Images in Static resource:

Sample Images as below



Create Apex class – AD_BannerController
public with sharing class AD_BannerController {
public static String CurrentClassName = AD_BannerController.class.getName();
/*****************************************************************************
*
* Public Method to create new banner
*
* @param : String - Region, banner type, custom message, link, color value, image id, status
Date - start date, end date
******************************************************************************/
@AuraEnabled
public static void createBannerRecord(String bannerId,String requiredRegion,String bannerType, String requiredCustomMessage,
String requiredColorPickerVal, String requiredUrlVal,
String requiredVisualPickerID, Boolean isBannerActive, Date startDate, Date endDate ) {
// Create a new AD_Banner__c record
AD_Banner__c newBanner = new AD_Banner__c();
// Set the fields of the new banner record
newBanner.Id = bannerId;
newBanner.Region_avaiable__c = requiredRegion;
newBanner.customMessage__c = requiredCustomMessage;
newBanner.colorPickerVal__c = requiredColorPickerVal;
newBanner.UrlVal__c = requiredUrlVal;
newBanner.VisualPickerID__c = requiredVisualPickerID;
newBanner.Active__c = isBannerActive;
newBanner.Start_Date__c = startDate;
newBanner.End_Date__c = endDate;
newBanner.Banner_Type__c = bannerType;
// Insert the new banner record
try {
upsert newBanner;
} catch(Exception e){
}
}
/*****************************************************************************
*
* Public Method to retrieve list of banner's created
*
* @param : -
******************************************************************************/
@AuraEnabled(cacheable=true)
public static List<AD_Banner__c> getAllBannerRecord() {
return [SELECT Id, Region_avaiable__c, customMessage__c, UrlVal__c,Status_Value__c, Start_Date__c, End_Date__c, Banner_Type__c,VisualPickerID__c, colorPickerVal__c
FROM AD_Banner__c ];
}
/*****************************************************************************
*
* Public Method to Display active Banner
*
* @param : -
******************************************************************************/
@AuraEnabled(cacheable=true)
public static List<AD_Banner__c> getActiveBannerRecord() {
User currentUser = [select Region__c from user where id = :UserInfo.getUserId()];
String region = currentUser.Region__c == 'APJ' ?'%'+ 'APAC' +'%' :'%'+currentUser.Region__c +'%';
return [SELECT Id, Region_avaiable__c, customMessage__c, UrlVal__c,Status_Value__c, Start_Date__c, End_Date__c, Banner_Type__c,VisualPickerID__c, colorPickerVal__c
FROM AD_Banner__c
where Status_Value__c = 'Active' and Region_avaiable__c != null and Region_avaiable__c LIKE :region and Start_Date__c <= TODAY and End_Date__c >= TODAY];
}
/*****************************************************************************
*
* Public Method to Edit Banner Id
*
* @param recordId : String, the Banner Id
******************************************************************************/
@AuraEnabled
public static AD_Banner__c editBannerContent(Id recordId) {
return [SELECT Id, Region_avaiable__c, customMessage__c, UrlVal__c,Status_Value__c, Active__c, Start_Date__c, End_Date__c, Banner_Type__c,VisualPickerID__c, colorPickerVal__c
FROM AD_Banner__c where id =: recordId ];
}
/*****************************************************************************
*
* Public Method to Delete Banner Id
*
* @param recordId : String, the Banner Id
******************************************************************************/
@AuraEnabled
public static AD_Utility_Method.errorWrapper deleteBannerContent(List<String> recordIds) {
AD_Utility_Method.errorWrapper err = new AD_Utility_Method.errorWrapper();
try{
if(recordIds !=null && !recordIds.isEmpty()){
Database.delete(recordIds);
}
err.flag = true;
return err;
}catch (Exception e) {
err.flag = false;
err.errorMsg = e.getMessage();
return err;
}
}
}
Create LWC Component – ad_Constants
Copy paste below code of ad_Constants.js
import AD_Banner_Delete_Success from '@salesforce/label/c.AD_Banner_Delete_Success';
import AD_Banner_Create_Success from '@salesforce/label/c.AD_Banner_Create_Success';
import AD_Banner_Color from '@salesforce/label/c.AD_Banner_Color';
import AD_Banner_Custom_Image from '@salesforce/label/c.AD_Banner_Custom_Image';
import AD_Banner_Custom_Link from '@salesforce/label/c.AD_Banner_Custom_Link';
import AD_Banner_Custom_Message from '@salesforce/label/c.AD_Banner_Custom_Message';
import AD_Banner_Preview from '@salesforce/label/c.AD_Banner_Preview';
import AD_Banner_Region from '@salesforce/label/c.AD_Banner_Region';
import AD_Banner_Type from '@salesforce/label/c.AD_Banner_Type';
import AD_Start_Date from '@salesforce/label/c.AD_Start_Date';
import AD_End_Date from '@salesforce/label/c.AD_End_Date';
import AD_Active from '@salesforce/label/c.AD_Active';
import AD_Banner_Update_Success from '@salesforce/label/c.AD_Banner_Update_Success';
import AD_Start_Date_Message from '@salesforce/label/c.AD_Start_Date_Message';
import AD_End_Date_Message from '@salesforce/label/c.AD_End_Date_Message';
import AD_Banner_Delete_Confirmation from '@salesforce/label/c.AD_Banner_Delete_Confirmation';
import AD_Active_Banner_Message from '@salesforce/label/c.AD_Active_Banner_Message';
import AD_Input_Date_Message from '@salesforce/label/c.AD_Input_Date_Message';
import AD_Banner_Date_Message from '@salesforce/label/c.AD_Banner_Date_Message';
import AD_Banner_Save from '@salesforce/label/c.AD_Banner_Save';
import AD_Banner_Cancel from '@salesforce/label/c.AD_Banner_Cancel';
import AD_Tooltip_Delete from "@salesforce/label/c.AD_Tooltip_Delete";
import AD_Tooltip_Download from "@salesforce/label/c.AD_Tooltip_Download";
import AD_Tooltip_Edit from "@salesforce/label/c.AD_Tooltip_Edit";
import AD_Tooltip_Undo from "@salesforce/label/c.AD_Tooltip_Undo";
import AD_Month from '@salesforce/label/c.AD_Month';
import AD_MonthList from '@salesforce/label/c.AD_Month_List';
const getLabels = () => {
return {
AD_Banner_Save,
AD_Banner_Cancel,
AD_Banner_Delete_Success,
AD_Banner_Create_Success,
AD_Banner_Color,
AD_Banner_Custom_Image,
AD_Banner_Custom_Link,
AD_Banner_Custom_Message,
AD_Banner_Preview,
AD_Banner_Region,
AD_Banner_Type,
AD_Start_Date,
AD_End_Date,
AD_Active,
AD_Banner_Update_Success,
AD_Start_Date_Message,
AD_End_Date_Message,
AD_Banner_Delete_Confirmation,
AD_Active_Banner_Message,
AD_Input_Date_Message,
AD_Banner_Date_Message,
AD_Tooltip_Delete,
AD_Tooltip_Edit,
AD_Tooltip_Undo,
AD_Tooltip_Download,
AD_Month,
AD_MonthList
}
}
/**/
const getConstants = () => {
return {
CONTENTVERSION_API : "ContentVersion",
IMAGE: "Image",
IMAGE_VARIANT_ERROR: 'error',
IMAGE_VAIANT_WARNING: 'warning',
DAYS: "Days",
STATUS_PASSED: "passed",
STATUS_FAILED: "failure",
STATUS_ERROR: "error",
STATUS_SUCCESS: "success",
TOAST_MODE_DISMISSIBLE: "dismissible",
TOAST_MODE_STICKY: "sticky",
TOAST_TYPE_SUCCESS: "success",
TOAST_TYPE_ERROR: "error",
TOAST_TYPE_INFO: 'info',
TOAST_TYPE_WARN: 'warning',
TITLE_INFO: 'Info',
SPINNER: 'spinner',
MONTH: 1,
ENDDATE: 89,
TOTALMONTH: 12,
BASE_URL: 'sfc/servlet.shepherd/document/download/',
FILE_UPLOAD: 'fileupload',
FILE_DELETE: 'filedelete',
FILE_DOWNLOAD: 'clone',
OwnerName: 'OwnerName',
CreatedByName:'docCreateby',
createdDateModified: 'createdDateModified',
FileType: 'FileType',
FileName:'docFileType',
Content_FIELD:'docContentSize',
textLabel: 'text',
DELETE_ICON_PATH: 'utility:delete',
iconLable: 'utility:undo',
iconLablePreview : 'action:preview',
iconLabelDown:"utility:download",
FORM_FACTOR_LARGE: "Large",
APJ_REGION: 'APJ',
EMEA_REGION: 'EMEA',
CALA_REGION: 'CALA',
LOOKUP: 'lookup',
DELAY: '300',
OTHER: 'Other', // 4-02-22
USREGION: 'USA',
SUCCESS: 'Success',
VariantMsg:'success',
ToastMsg:'Files uploaded Successfully',
REJECT: 'Reject',
REJECTED: 'Rejected',
CANCELLED : 'Cancelled',
PDF : 'PDF',
RECORDPAGE : 'RecordPage',
DESC : 'DESC',
ACSE : 'ACSE',
bannerMsg:' from',
bannerMsgTo:'to',
FORM_FACTOR_SMALL : 'Small',
FORM_FACTOR_MEDIUM : 'Medium',
API_VERSION : '51.0',
CLICK_SAVE : 'clicksave',
SAVED : 'Saved',
FALSE :'false',
SLDS_LRP : 'slds-p-left_small slds-p-right_small',
SLDS_ERROR : 'slds-has-error',
ONCLICK:'onclick',
EDIT_ICON_PATH: 'utility:edit',
COLORPICKERVAL:'#59EA98',
BTNDISABLESTYLE:'#B4BAB6',
BTNENABLEDSTYLE: '#405cf5',
AVAILABLE_REGIONS: ['USA','EMEA','APAC','CALA'],
ID_REGION: 'idRegion',
SELECT_ALL: 'selectAll',
TITLE_MAINTENANCE: 'Maintenance',
TITLE_WARNING: 'Warning',
ACTIVECHECK: 'activeCheck',
DATE: 'Date',
STATUS_CHANGES_APPLICABLE_REGIONS: 'EMEA',
}
}
export { getLabels, getConstants };
Copy paste below code of ad_Constatnts.js-meta.xml
<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>63.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
<target>lightning__RecordPage</target>
</targets>
</LightningComponentBundle>
Create LWC component ad_FlexiDatTable
Copy paste below code of ad_FlexiDataTable.html
<template>
<div class={scrolVar} style={tableStyle}>
<template if:true={formatedData}>
<table onload={handleLoad} aria-multiselectable="true"
class=" slds-table slds-table_bordered slds-border_left slds-border_right " role="grid" aria-label="">
<thead>
<tr class="slds-line-height_reset">
<template if:true={showRowSelect}>
<th scope="col">
<div class="">
<lightning-input type="checkbox" data-checkbox="select-all"
onchange={handleSelectAll} label="" name="input1"></lightning-input>
<!---->
</div>
</th>
</template>
<template for:each={localColumn} for:item="head">
<th scope="col" key={head}>
<div style="display: inline-flex; ">
<template if:true={head.showSearchBox}>
<div style=" z-index: 999999999;display:inline-flex">
<lightning-input type="text" name="search"
class="slds-has-overflow slds-has-overflow" variant="label-hidden"
data-search={head.field} onchange={handleColumnSearch}>
</lightning-input>
<lightning-button-icon variant="bare" data-icon={head.field}
onclick={closeSearchBox} icon-name="utility:close">
</lightning-button-icon>
</div>
</template>
<template if:false={head.showSearchBox}>
<!--<div>
<label class="slds-wrap slds-p-right_medium ">
{head.label}</label>
</div>-->
<div>
<label class="slds-wrap">
{head.label}</label>
</div>
</template>
<template if:true={head.sortable}>
<template if:true={head.showUp}>
<!--<lightning-button-icon variant="bare" data-icon={head.field} class="slds-button slds-button_icon"
onclick={handleSortAscending} icon-name="utility:arrowup">
</lightning-button-icon>-->
<lightning-icon icon-name="utility:arrowup" size="x-small"
onclick={handleSortAscending} data-icon={head.field}></lightning-icon>
</template>
<template if:false={head.showUp}>
<!--<lightning-button-icon variant="bare" data-icon={head.field} class="slds-button slds-button_icon"
onclick={handleSortDescending} icon-name="utility:arrowdown">
</lightning-button-icon>-->
<lightning-icon icon-name="utility:arrowdown" size="x-small"
onclick={handleSortDescending} data-icon={head.field}></lightning-icon>
</template>
</template>
<template if:true={head.filterable}>
<lightning-button-icon variant="bare" data-icon={head.field}
onclick={handleShowSearchbox} icon-name="utility:search">
</lightning-button-icon>
</template>
</div>
</th>
</template>
<template if:true={showRowAction}>
<th class="" scope="col" style="width:3.25rem">
<div class="slds-truncate slds-assistive-text" title="Actions">Actions</div>
</th>
</template>
</tr>
</thead>
<tbody>
<template for:each={formatedData} for:item="item">
<tr key={item} aria-selected="false" class="slds-hint-parent">
<template if:true={showRowSelect}>
<td class="slds-text-align_right" role="gridcell">
<lightning-input onload={handleLoad} data-item={item.index}
data-checkbox="select-item" onchange={hanleItemSelect} type="checkbox"
value={item.isChecked} label="" name="input1">
<!-- -->
</lightning-input>
</td>
</template>
<template for:each={item.row} for:item="rowItem">
<td key={row} role="gridcell">
<template if:true={rowItem.editable}>
<template if:true={rowItem.isComboBox}>
<lightning-combobox name={item.index} label="" variant="label-hidden"
value={rowItem.value} placeholder="" options={rowItem.options}
data-required={rowItem.required} data-input={rowItem.dataInput}
onchange={handleInputValueChange} data-item={item.index}
dropdown-alignment="auto" style="overflow: visible;"
>
</lightning-combobox>
</template>
<template if:false={rowItem.isComboBox}>
<template if:true={rowItem.isNumber}>
<lightning-input type={rowItem.dataType} step={rowItem.step}
formatter={rowItem.formatter} variant="label-hidden"
disabled={rowItem.readOnly} data-required={rowItem.required}
onchange={handleInputValueChange} value={rowItem.value}
data-input={rowItem.dataInput} data-item={item.index} name={item.index}
class="slds-truncate">
</lightning-input>
</template>
<template if:false={rowItem.isNumber}>
<lightning-input type={rowItem.dataType} step={rowItem.step}
formatter={rowItem.formatter} variant="label-hidden"
disabled={rowItem.readOnly} data-required={rowItem.required}
onchange={handleInputValueChange} value={rowItem.value}
data-input={rowItem.dataInput} data-item={item.index} name={item.index}
max-length={label.ad_Comment_Size}
class="slds-truncate">
</lightning-input>
</template>
</template>
</template>
<template if:false={rowItem.editable}>
<template if:true={rowItem.isImage}>
<lightning-helptext icon-name="utility:warning" icon-variant={rowItem.value}
content={rowItem.ImageTitle}></lightning-helptext>
</template>
<template if:false={rowItem.isImage}>
<template if:true={rowItem.isDate}>
<div class={rowItem.DateColor} title={rowItem.value}>
{rowItem.value}</div>
</template>
</template>
<template if:false={rowItem.isImage}>
<template if:false={rowItem.isDate}>
<div class="slds-truncate slds-text-align_left" title={rowItem.value}>
{rowItem.value}</div>
</template>
</template>
</template>
<!-- <template if:false={rowItem.editable}>
<template if:true={rowItem.isImage}>
<lightning-helptext icon-name="utility:warning" icon-variant={rowItem.value}
content={rowItem.ImageTitle}></lightning-helptext>
</template>
<template if:false={rowItem.isImage}>
<div class="slds-truncate slds-text-align_left" title={rowItem.value}>
{rowItem.value}</div>
</template>
</template> -->
</td>
</template>
<template if:true={showRowAction}>
<lightning-button-group>
<template if:true={showViewRowAction}>
<lightning-button title={label.ad_Tooltip_Download}
icon-name="utility:download" variant="base" name="download"
data-item={item.index} onclick={handleRowActionClone}>
</lightning-button>
</template>
<!-- if table name is banner-->
<template lwc:if={isBanner}>
<lightning-button title={undoEditPathLabel} icon-name={editIconPath}
variant="base" name="edit" data-item={item.index}
onclick={handleRowActionEdit}>
</lightning-button>
</template>
<!-- if table name is not fileupload-->
<template if:false={isFileUpload}>
<lightning-button title={undoIconPathLabel} icon-name={undoIconPath}
variant="base" name="delete" data-item={item.index}
onclick={handleRowActionDelete}>
</lightning-button>
</template>
<template if:true={isFileUpload}>
<template if:true={item.data.showDeleteIcon}>
<lightning-button title={undoIconPathLabel} icon-name={undoIconPath}
variant="base" name="delete" data-item={item.index}
onclick={handleRowActionDelete} disabled={deleteToDisable}>
</lightning-button>
</template>
</template>
</lightning-button-group>
</template>
</tr>
</template>
</tbody>
</table>
</template>
<template if:true={addBottomSpace}>
<!--ADDS SPACE AT THE BOTTOM OF THE PAGE-->
<lightning-layout class="slds-p-bottom_small">
<lightning-layout-item size="4" padding="around-large">
</lightning-layout-item>
</lightning-layout>
<!--ADDS SPACE AT THE BOTTOM OF THE PAGE END-->
<!--ADDS SPACE AT THE BOTTOM OF THE PAGE-->
<lightning-layout class="slds-p-bottom_small">
<lightning-layout-item size="4" padding="around-large">
</lightning-layout-item>
</lightning-layout>
<!--ADDS SPACE AT THE BOTTOM OF THE PAGE END-->
</template>
</div>
</template>
Copy paste below code of ad_FlexiDataTable.js
import { LightningElement, api, track, wire} from 'lwc';
import { getLabels,getConstants } from "c/ad_Constants";
const DELAY_TIMER = 1500;
export default class ad_FlexiDataTable extends LightningElement {
@api tableName;
@api uniqueKey;
@api showRowSelect;
@api showRowAction;
@api showViewRowAction = false;
@api undoIconPath = 'utility:undo';
@api editIconPath = 'utility:edit';
@api addBottomSpace = false;
@api tableStyle = "max-height: 550px; min-height: 250px; overflow-y:scroll";
@api deleteToDisable = false; //
columnData;
@api scrolVar = "slds-scrollable--y slds-scrollable--x tableFixHead";
@api
get column() {
return this.columnData;
}
CONSTANT = getConstants();
label = getLabels();
get isFileUpload(){
return (this.tableName=='fileupload'?true:false);
}
get isExpiredTable(){
return (this.tableName=='expiry and short date'?true:false);
}
get isBanner(){
if(this.tableName=='banner'){
return true;
}
return false;
}
get undoIconPathLabel()
{
return (this.undoIconPath=== this.CONSTANT.DELETE_ICON_PATH) ? this.label.AD_Tooltip_Delete : this.label.AD_Tooltip_Undo;
}
get undoEditPathLabel()
{
return (this.editIconPath=== this.CONSTANT.EDIT_ICON_PATH) ? this.label.AD_Tooltip_Edit : this.label.AD_Tooltip_Undo;
}
set column(value) {
if (value)
this.localColumn = JSON.parse(JSON.stringify(value));
console.log("Local" + JSON.stringify(this.localColumn));
this.rowFields = [];
this.columnData = value;
this.column.forEach(element => {
let obj = {
field: element.field,
filterable: element.filterable,
disabled: element.disabled,
dataType: element.dataType,
editable: element.editable
}
this.rowFields.push(element);
});
}
rowdataValue;
@api
get rowData() {
return this.rowdataValue;
}
set rowData(data) {
if (data)
this.localData = JSON.parse(JSON.stringify(data));
this.modifyedData = [...this.localData];
this.rowdataValue = data;
this.formatData(this.rowData);
}
@api selectedItems;
@api isStackViewMobile;
@api scrollableX;
@api scrollableY;
@track localData = [];
@track localColumn = [];
@track rowFields = [];
@api formatedData = [];
@track selectedRows = [];
@track searchResult = [];
@track sortedData = [];
@track selectedItemIndexList = [];
@track modifyedData = [];
@track rerenderFlag = false;
month = this.label.AD_Month.split(',');
//------------------------------------------------------------------------ Searching & Sorting Start--------------------------------------------------------------
/**
* column Search
* @param {object} event
*/
handleColumnSearch(event) {
let field = event.target.dataset.search;
let searchString = event.detail.value;
if (searchString) this.searchResult = [...this.searchItem(searchString, field)];
this.formatData(this.searchResult);
}
/**
* Show/hide Search box
* @param {object} event
*/
handleShowSearchbox(event) {
let field = event.target.dataset.icon;
this.localColumn.forEach(element => {
if (element.field == field) {
element['showSearchBox'] = true;
}
});
}
/**
* Column Sorting
* @param {object} event
*/
handleSortAscending(event) {
let field = event.target.dataset.icon;
this.localColumn.forEach(element => {
if (element.field == field) {
element['showUp'] = false;
}
});
this.sortedData = [...this.sortData(this.localData, field)];
console.log('this.sortedData for asc'+JSON.stringify(this.sortedData));
this.formatData(this.sortedData);
}
/**
* Column Sorting
* @param {object} event
*/
handleSortDescending(event) {
let field = event.target.dataset.icon;
this.localColumn.forEach(element => {
if (element.field == field) {
element['showUp'] = true;
}
});
this.sortedData = [...this.sortData(this.localData, field, true)];
console.log('this.sortedData dsc'+JSON.stringify(this.sortedData));
this.formatData(this.sortedData);
}
/**
* Sort data based on parameters added
* @param {List<object>} data -list of record/object which need to sort
* @param {String} field - sorting based on which field/attribute
* @param {Number , Date} field - sorting based on which field/attribute
* @param {Boolean} descending - sorting order
* @returns {List<object>} -sorted data
*
*/
sortData(data, field, descending = false) {
//console.log(this.month);
let m = this.month;
console.log(m);
data.sort(function (x, y) {
if( (x[field] && y[field]) || x[field] || y[field]) {
if( ( (typeof(x[field]) == "number" ) && ( typeof(y[field]) == "number") ) || (typeof(x[field]) == "number" ) || ( typeof(y[field]) == "number"))
{
console.log("type " + (typeof(x[field]) == "number") );
let a = x[field], b = y[field];
if(!descending){
if(a == b)
return 0;
else if(a == undefined || a == null)
return -1;
else if(b == undefined || b == null)
return 1;
else
return a > b ? 1 : -1;
}else{
if(a == b)
return 0;
else if(a == undefined || a == null)
return 1;
else if(b == undefined || b == null)
return -1;
else
return a < b ? 1 : -1;
}
// if (!descending) return a == b ? 0 : a > b ? 1 : -1;
// else return a == b ? 0 : a < b ? 1 : -1;
}
else if( ((typeof(x[field]) == "string" ) && ( typeof(y[field]) == "string")) || (typeof(x[field]) == "string" ) || ( typeof(y[field]) == "string")){
//const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun','Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
let a = x[field], b = y[field];
console.log("value a: " + a);
console.log("value b: " +b);
if( ( Date.parse(a) > 0) && (Date.parse(b) > 0) )
{
console.log("Date type: postive");
let month1 = a.substr(0,4).trim(), month2 = b.substr(0,4).trim();
console.log('month ' +month1);
if((m.includes(month1) ) && (m.includes(month2) ) ){
//console.log("true match is found for month");
let month_a = m.indexOf(month1), month_b = m.indexOf(month2);
console.log('month ' +month_a);
let y1 = a.substr(8, 11).trim(), y2 = b.substr(8, 11).trim();
let d1 = a.substr(4,4).replace(/\,/g,'').trim(), d2 = b.substr(4,4).replace(/\,/g,'').trim();
if(!descending){
if(y1 != y2){
return y1 - y2;
}
else if(y1 == y2 && month1 == month2 ){
return d1 - d2;
}
else {
return month_a - month_b;
}
}
else {
if(y1 != y2){
return y2 - y1;
}
else if(y1 == y2 && month1 == month2 ){
return d2 - d1;
}
else {
return month_b - month_a;
}
}
}
else{
console.log("false match is not found for month");
let a = x[field].toUpperCase(), b = y[field].toUpperCase();
if (!descending) return a == b ? 0 : a > b ? 1 : -1;
else return a == b ? 0 : a < b ? 1 : -1;
}
}
else{
console.log("Date type: negative");
let a = x[field], b = y[field];
console.log("a type: " +typeof(a));
console.log("b type: "+typeof(b));
if( (+a) && (+b)){
console.log("inside numeric");
// if (!descending) return (+a) == (+b) ? 0 : (+a) > (+b) ? 1 : -1;
// else return (+a) == (+b) ? 0 : (+a) < (+b) ? 1 : -1;
if(!descending){
if((+a) == (+b))
return 0;
else if((+a) == undefined || (+a) == null)
return -1;
else if((+b) == undefined || (+b) == null)
return 1;
else
return (+a) > (+b) ? 1 : -1;
}else{
if((+a) == (+b))
return 0;
else if((+a) == undefined || (+a) == null)
return 1;
else if((+b) == undefined || (+b) == null)
return -1;
else
return (+a) < (+b) ? 1 : -1;
}
}else{
console.log("not inside numeric");
if(!descending){
if(a == b)
return 0;
else if(a == undefined || a == null )
return -1;
else if(b == undefined || b == null)
return 1;
else
return a > b ? 1 : -1;
}else{
if(a == b)
return 0;
else if(a == undefined || a == null)
return 1;
else if(b == undefined || b == null)
return -1;
else
return a < b ? 1 : -1;
}
}
// else if((a === undefined && b === undefined) || (a === undefined || b === undefined)){
// console.log("not inside numeric && undefined");
// if (!descending) return a == b ? 0 : a > b ? 1 : -1;
// else return a == b ? 0 : a < b ? 1 : -1;
// }
// else{
// a = a.toUpperCase();
// b = b.toUpperCase();
// console.log("not inside numeric && not a undefiend");
// if (!descending) return a == b ? 0 : a > b ? 1 : -1;
// else return a == b ? 0 : a < b ? 1 : -1;
// }
}
}
}
});
return data;
}
/**
* Search data based on parameters added
* @param {String} searchString -tex in search input
* @param {String} field -which field/attribute need to search
* @returns {List<object>} - filtered list of records
*/
searchItem(searchString, field) {
let finalList = [];
this.rowData.forEach(element => {
if (element[field] && element[field].toLowerCase().includes(searchString.toLowerCase())) {
finalList.push(element);
}
});
return finalList;
}
/**
* Hide Search box
* @param {*} event
*/
closeSearchBox(event) {
let field = event.target.dataset.icon;
this.localColumn.forEach(element => {
if (element.field == field) {
element['showSearchBox'] = false;
}
});
this.formatData(this.rowData);
//show all filter icon
}
//------------------------------------------------------------------------Searching & Sorting End--------------------------------------------------------------
//------------------------------------------------------------------------ Table Formating Start--------------------------------------------------------------
/**
* Add row in data
* @param {List<object>} rowData
*/
formatData(rowData) {
if (rowData) {
this.formatedData = [];
this.selectedItemIndexList = [];
for (let i = 0; i < rowData.length; i++) {
let temp=[];
let obj = {
index: i,
data: rowData[i],
//name: i+rowData[i]
row: this.getRow(rowData[i], this.rowFields, i)
}
// if(i==0){
// obj.data.showDeleteIcon=false;
// }
console.log('@@@data -- '+ JSON.stringify(obj.data));
console.log('@@@data -- '+obj.data.showDeleteIcon);
if (this.checkIfIteminSelectedList(rowData[i])) {
this.selectedItemIndexList.push(i);
}
this.formatedData.push(obj);
}
}
this.populateCheckbox();
}
/**
* check if this item is selected or not
* @param {object} item
* @returns {Boolean} - if item is checked or not
*/
checkIfIteminSelectedList(item) {
let result = false;
if (this.selectedItems) {
this.selectedItems.forEach(element => {
if (element[this.uniqueKey] == item[this.uniqueKey]) {
result = true;
}
});
}
return result;
}
/**
* generate row based on column attribute
* @param {object} objData
* @param {List<String>} attLIst
* @param {Integer} rowNumber
* @returns {List<object>} - formated row
*
*/
getRow(objData, attLIst, rowNumber) {
let row = [];
let i = 0;
console.log('attLIst =' +JSON.stringify(objData));
attLIst.forEach(element => {
let isComboBox = false;
let isNumber = false;
let readOnly = false;
let isImage = false;
let isDate = false; //c
let combineId = rowNumber + '#' + i + '#' + element['field'] + '#' + element['dataType'];
if (element['required']) {
this.addRequired(combineId)
}
if (element['dataType'] == 'number') {
isNumber = true;
}
if (element['dataType'] == 'combobox') {
isComboBox = true;
}
if (element['dataType'] == 'image' && objData[element['field']] != undefined ){
isImage = true;
}
if (objData['readOnly'] == true) {
readOnly = true;
}
if (element['dataType'] == 'date' && objData[element['field']] != undefined ){
isDate = true;
}
let obj = {
index: i,
value: objData[element['field']],
filterable: element['filterable'],
disabled: element['disabled'],
dataType: element['dataType'],
editable: element['editable'],
required: element['required'],
formatter: element['formatter'],
step: element['step'],
isNumber: isNumber,
isComboBox: isComboBox,
isImage : isImage,
readOnly : readOnly,
options: element['options'],
dataInput: combineId,
isDate : isDate,
label: element['label'],
}
console.log('obj.value==' + JSON.stringify(obj));
if(obj.value != undefined && obj.dataType == 'date' ){
let monthList = this.label.AD_MonthList.split(',');
let d = new Date(obj.value);
let mon = (d.getDate() < this.CONSTANT.DOUBLE_DIGIT ? this.CONSTANT.ZERO_TEXT + d.getDate() : d.getDate());
//Date get display in new format - [ Month date, year ]
obj.value = monthList[d.getMonth()] + ' ' + mon + ', ' + d.getFullYear();
//this.DateFormaterWithoutTime(obj.value);
}
if(isDate && obj.value != undefined){
if(obj.label.includes('Expiry Date')){
obj['DateColor'] = objData['Date'];
}
}
// if(isImage && obj.value != undefined){
// if(obj.value.includes('warning')){
// //obj['ImageTitle']= 'Short Dated Product : '+objData['Days']+' Days';
// obj['ImageTitle']= 'Short Dated Product: '+objData['Days'] + ' '+ 'Remaining Days';
// }
// else if(obj.value.includes('error')){
// //obj['ImageTitle']= 'Expired Product - Date: '+objData['Days'];
// obj['ImageTitle']= 'Expired Product - Date: '+ this.DateFormaterWithoutTime(objData['Days']);
// }
// else{
// obj['ImageTitle']= '';
// }
// }
row.push(obj);
i++;
});
return row;
}
/**
* Method to format date (MMM DD, YYYY)
* @param {date}
*
*/
DateFormaterWithoutTime(dateValue) {
let monthList = this.label.AD_MonthList.split(',');
let d = new Date(dateValue);
let mon = (d.getDate() < this.CONSTANT.DOUBLE_DIGIT ? this.CONSTANT.ZERO_TEXT + d.getDate() : d.getDate());
return monthList[d.getMonth()] + ' ' + mon + ', ' + d.getFullYear();
}
/**
* add required attribute in input
* @param {Integer} targetInput -Index of the element
*/
addRequired(targetInput) {
this.template.querySelectorAll('[data-input="' + targetInput + '"]')
.forEach(element => {
element.required = true;
});
}
//------------------------------------------------------------------------ Table Formating End---------------------------------------------------------------
//------------------------------------------------------------------------ Data Modification Start--------------------------------------------------------------
/**
* handle input value change and dispatch event
* @param {object} event
*/
handleInputValueChange(event) {
let targetInput = event.target.dataset.input;
let tempArr = targetInput.split('#');
let row = tempArr[0];
let column = tempArr[1];
let field = tempArr[2];
let dataType = tempArr[3];
let value = '';
switch (dataType) {
case 'combobox':
value = event.detail.value;
break;
case 'text':
value = event.detail.value;
break
case 'checkbox':
value = event.target.checked;
break;
default:
value = event.detail.value;
}
console.log("issue "+ value);
this.modifyData(row, field, value);
}
/**
* Helper method for handleInputValueChange
* @param {Integer} row -Index of the element
* @param {String} field -field name
* @param {any} value - value to be added
*/
modifyData(row, field, value) {
let li = this.localData[row];
li[field] = value;
let modifieddata = [];
modifieddata.push(li);
this.dispatchDatamodification(modifieddata);
}
/**
* dispatch 'rowchange' event
* @param {List<object>} data
*/
dispatchDatamodification(data) {
console.log("issue "+ JSON.stringify(this.localData));
const lwcEvent = new CustomEvent('rowchange', {
detail: {
rows: JSON.parse(JSON.stringify(data)),
table: this.tableName
}
});
this.dispatchEvent(lwcEvent);
}
//------------------------------------------------------------------------ Data Modification End--------------------------------------------------------------
//------------------------------------------------------------------------ Selection Start---------------------------------------------------------------
/**
* Select all row
* @param {object} event
*/
handleSelectAll(event) {
let isSelected = event.target.checked;
this.template.querySelectorAll('[data-checkbox="select-item"]')
.forEach(element => {
element.checked = isSelected;
});
if (isSelected) this.selectedRows = [...this.formatedData];
else this.selectedRows = [];
this.dispatchRowselection();
}
/**
* add item in selected item and dispatch event
* @param {object} event
*/
hanleItemSelect(event) {
let isSelected = event.target.checked;
let index = event.target.dataset.item;
this.selectItems(index, isSelected);
this.template.querySelectorAll('[data-checkbox="select-all"]')
.forEach(element => {
element.checked = false;
});
this.dispatchRowselection();
}
/**
* helper method for hanleItemSelect
* @param {Integer} index -Index of the element
* @param {Boolean} isSelected
*/
selectItems(index, isSelected) {
if (isSelected) {
let itemIndex = this.formatedData.findIndex(element => element.index == index);
this.selectedRows.push(this.formatedData[itemIndex]);
} else {
let selectedRowsIndex = this.selectedRows.findIndex(element => element.index == index);
this.selectedRows.splice(selectedRowsIndex, 1);
}
}
/**
* populate previously selected items
*/
populateCheckbox() {
setTimeout(() => {
this.formatedData.forEach(formatedItem => {
if (this.selectedItemIndexList.includes(formatedItem.index)) {
this.selectItems(formatedItem.index, true);
let item = this.template.querySelector("lightning-input[data-item=" + '"' + formatedItem.index + '"' + " ]");
if (item) {
item.checked = true;
}
}
});
}, DELAY_TIMER);
}
/**
* Dispatch 'rowselect' event
*/
dispatchRowselection() {
let finalSelection = [];
this.selectedRows.forEach(element => {
finalSelection.push(element.data);
});
const lwcEvent = new CustomEvent('rowselect', {
detail: {
rows: finalSelection
}
});
this.dispatchEvent(lwcEvent);
}
//------------------------------------------------------------------------ Selection End---------------------------------------------------------------
//------------------------------------------------------------------------ Row Action Start---------------------------------------------------------------
//Row Action
/**
* handler method for row action delete
* @param {Object} event
*/
handleRowActionDelete(event) {
let index = event.target.dataset.item;
this.dispatchRowAction('delete', index);
let indexedElement = this.formatedData.find(element => element.index == index);
this.dispatchRowAction('filedelete', indexedElement.data);
let indexedBannerElement = this.formatedData.find(element => element.index == index);
this.dispatchRowAction('bannerdelete', indexedBannerElement.data);
}
/**
* handler method for row action Edit
* @param {Object} event
*/
handleRowActionEdit(event) {
let index = event.target.dataset.item;
this.dispatchRowAction('edit', index);
let indexedBannerElement = this.formatedData.find(element => element.index == index);
this.dispatchRowAction('bannerEdit', indexedBannerElement.data);
}
handleRowActionClone(event){
let indexedElement = this.formatedData.find(element => element.index == event.target.dataset.item);
this.dispatchRowAction('clone', indexedElement.data.downloadUrl);
}
/**
* Edit/Delete action on row
* @param {String} name
* @param {Integer} index
*/
dispatchRowAction(name, index) {
const lwcEvent = new CustomEvent('rowcaction', {
detail: {
index: index,
name: name,
table: this.tableName
}
});
this.dispatchEvent(lwcEvent);
}
///
dispatchRowSort() {
const lwcEvent = new CustomEvent('notify', {
detail: {
name: name,
table: this.tableName
}
});
this.dispatchEvent(lwcEvent);
}
//------------------------------------------------------------------------ Row Action End---------------------------------------------------------------
connectedCallback() {
console.log('this is the start of the flexi');
console.log('tis table'+this.tableName);
console.log('formatData--', this.formatedData);
}
}
Copy paste below code of ad_FlexiDataTable.css
.customXScroll_X {
max-width: 100%;
overflow-y: auto;
}
.customXScroll_Y {
display: block;
max-width: 100%;
overflow: overlay;
overflow-x: auto;
height: 300px;
}
/* .slds-truncate {
max-width: 100%;
overflow: visible;
text-overflow: visible;
white-space: normal;
} */
.slds-truncate {
max-width: 15em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* */
.tableFixHead th {
position: sticky;
top: 0;
z-index: 5;
background: white;
}
.highlight-red{
color:red;
font-weight: bold;
}
.highlight-orange{
color: rgb(252 147 2);
font-weight: bold;
}
Copy paste below table of ad_FlexiDataTable.js-meta.xml
<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>63.0</apiVersion>
<isExposed>true</isExposed>
</LightningComponentBundle>
Create LWC Component – ad_Closemodal
Copy paste below code of ad_Closemodal.html
<template>
<!--Use template if:true to display/hide popup based on isModalOpen value-->
<template if:true={isModalOpen}>
<!-- Modal/Popup Box LWC starts here -->
<section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
<div class="slds-modal__container">
<!-- Modal/Popup Box LWC header here -->
<header class="slds-modal__header">
<button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" title="Close" onclick={closeModal}>
<lightning-icon icon-name="utility:close"
alternative-text="close"
variant="inverse"
size="small" ></lightning-icon>
<span class="slds-assistive-text">Close</span>
</button>
<h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">{header}</h2>
</header>
<!-- Modal/Popup Box LWC body starts here -->
<div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
<p class="message slds-text-title_bold">{warningMessage}
</p>
</div>
<!-- Modal/Popup Box LWC footer starts here -->
<footer class="slds-modal__footer">
<button class="slds-button slds-button_brand" onclick={goBack} title={yeslabel}>{yeslabel}</button>
<button class="slds-button slds-button_neutral" onclick={closeModal} title={nolabel}>{nolabel}</button>
</footer>
</div>
</section>
<div class="slds-backdrop slds-backdrop_open"></div>
</template>
</template>
Copy paste below code of ad_Closemodal.js
import { LightningElement,api,track } from 'lwc';
import { getConstants, getLabels } from "c/ad_Constants";
export default class Ad_Closemodal extends LightningElement {
//Boolean tracked variable to indicate if modal is open or not default value is false as modal is closed when page is loaded
@api isModalOpen = false;
@api warningMessage = '';
@api header = '';
//@api parentComponentName = '';
//@api cycleCountMethodToDisplay;
label = getLabels();
CONSTANT = getConstants();
// @track ad_CloseModalLabelList
yeslabel ='Yes'
nolabel='No'
msg;
str;
openModal() {
this.isModalOpen = true;
}
// When No button in the pop-up is clicked
closeModal() {
this.isModalOpen = false;
this.countingMethodSelected='Avideep Application';
this.dispatchEvent(new CustomEvent('goback', { detail: false }));
}
// When Yes button in the pop-up is clicked
goBack() {
this.isModalOpen = false;
this.dispatchEvent(new CustomEvent('goback', { detail:{isUserCycleCount: true, selectedCountingMethod: this.countingMethodSelected,resetYesButton: true }}));
}
renderedCallback(){
this.msg=this.template.querySelector('.message');
if(this.parentComponentName ==this.CONSTANT.UCC_REQ_LWC && this.isModalOpen == true ){
console.log('this.warningMessage renderif msg'+this.msg.innerHTML);
this.str=this.warningMessage.split(',').join('<br>');
this.msg.innerHTML=this.str;
}
}
}
Copy paste below code of ad_Closemodal.js-meta.xml
<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>63.0</apiVersion>
<isExposed>true</isExposed>
</LightningComponentBundle>
Copy paste below code of ad_Closemodal.css
.custom-container{
color : black;
}
Create LWC Component - ad_BannerConfigComponent
Copy paste below code of ad_BannerConfigComponent.html
<template>
<lightning-card variant="Narrow" title="Banner Configuration" icon-name="standard:settings">
<div class="main_container">
<div class="dsp_grid">
<!-- Banner Region -->
<div>
<h3 class="headings"><span class="req">*</span> {label.AD_Banner_Region}</h3>
<div style="margin-top:5px;" >
<fieldset >
<div class="slds-form-element__control">
<div class="slds-grid slds-wrap ">
<div class="slds-checkbox slds-p-right_small" for:each={options} for:item="item" key={item.value} >
<input type="checkbox" name={label} data-id="idRegion" id={item.value} value={item.value} onchange={handleIndividualChange}/>
<label class="slds-checkbox__label" for={item.value}>
<span class="slds-checkbox_faux"></span>
<span class="slds-form-element__label slds-p-left_xx-small">{item.label}</span>
</label>
</div>
<div class="slds-checkbox slds-p-right_small" for:each={option_all} for:item="item" key={item.value}>
<input type="checkbox" name={label} data-id="selectAll" id={item.value} value={item.value} onchange={handleSelectAll}/>
<label class="slds-checkbox__label" for={item.value}>
<span class="slds-checkbox_faux"></span>
<span class="slds-form-element__label slds-p-left_xx-small">{item.label}</span>
</label>
</div>
</div>
</div>
</fieldset>
</div>
<br/><br/>
</div>
<!-- Banner Custom Message -->
<div class="custom_msg">
<h3 class="headings margin_btm"><span class="req">*</span> {label.AD_Banner_Custom_Message}</h3>
<lightning-textarea name="customMessage" value={customMessage} placeholder="type here..." onblur={handleCustomMessageChange}></lightning-textarea>
</div>
</div>
<div class="dsp_grid bgG cmp_container">
<!-- Banner Type -->
<div>
<h3 class="headings margin_btm"><span class="req">*</span> {label.AD_Banner_Type}</h3>
<lightning-combobox class="cntrl_combobox"
name="iconType"
value={iconType}
options={comboboxOptions}
onchange={handleBannerTypeChange}>
</lightning-combobox>
</div>
<div class="color_picker ">
<!-- Banner Color -->
<div>
<h3 class="headings margin_btm">{label.AD_Banner_Color}</h3>
<lightning-input type="color" name="input_color" value={colorPickerVal} onchange={handleColorChange}></lightning-input>
</div>
<!-- Banner Custom Link -->
<div>
<h3 class="headings margin_btm">{label.AD_Banner_Custom_Link}</h3>
<lightning-input type="url" name="inputUrl" value={urlVal} placeholder="Enter valid URL here..." onblur={handleURLChange} ></lightning-input>
</div>
</div>
</div>
<div class="dsp_grid bgG cmp_container">
<!-- Banner Image -->
<div>
<h3 class="headings "><span class="req">*</span> {label.AD_Banner_Custom_Image}</h3>
<div class="img_picker style-3 ">
<div>
<fieldset class="slds-form-element">
<div class="slds-form-element__control">
<template for:each={imagesPickerArr} for:item="imageElm">
<div key={imageElm.id} class="slds-visual-picker slds-visual-picker_medium bgR">
<input type="radio" data-id={imageElm.dataId} id={imageElm.id} value={imageElm.id} name="visual_pickerForImage" onchange={handleImageChange} />
<label for={imageElm.id}>
<span class="slds-visual-picker__figure slds-visual-picker__text slds-align_absolute-center cntrl_picker">
<div class=" imgContainer">
<img src={imageElm.val} alt="icon Image"/>
</div>
</span>
<span class="slds-icon_container slds-visual-picker__text-check"></span>
</label>
</div>
</template>
</div>
</fieldset>
</div>
</div>
</div>
<div class="slds-form-element">
<!-- Start and End Date functionality starts here-->
<div class="slds-grid slds-gutters slds-p-top_x-small" >
<div class="slds-col slds-size_1-of-3">
<h3 class="headings margin_btm"><span class="req">*</span> {label.AD_Start_Date}</h3>
<lightning-input type="date" name="startdate" data-id="startdate" value={start_date} onchange={handleDateChange}></lightning-input>
</div>
<div class="slds-col slds-size_1-of-3">
<h3 class="headings margin_btm"><span class="req">*</span> {label.AD_End_Date}</h3>
<lightning-input type="date" name="enddate" data-id="enddate" value={end_date} onchange={handleDateChange}></lightning-input>
</div>
</div>
<!-- Start and End Date functionality ends here-->
<!-- Active functionality starts here -->
<div class="slds-form-element__control slds-p-top_x-small">
<div class="slds-checkbox">
<input type="checkbox" name="options" data-id="activeCheck" id="active" value="bannerActive" checked="" onchange={handleBannerActive}/>
<label class="slds-checkbox__label" for="active">
<span class="slds-checkbox_faux"></span>
<h3 class="slds-form-element__label headings ">{label.AD_Active}</h3>
</label>
</div>
</div>
<!-- Active functionality ends here-->
<!-- Preview button -->
<div class="preview_btn bgR slds-p-top_x-small">
<button style={previewBtnColor} class="btn" onclick={handlePreview} disabled={isBtnDisabled} >Preview Banner</button>
</div>
</div>
</div>
</br>
<!-- Save/Cancel functionality starts here -->
<div class="footer" >
<button class="btn" onclick={handleSave}>{label.AD_Banner_Save}</button>
<button class="btn" onclick={handleCancel}>{label.AD_Banner_Cancel}</button>
</div>
<!-- Save/Cancel functionality ends here -->
</div>
<!-- Show created banners in table starts here -->
<template if:true={hideTable}>
<lightning-layout>
<lightning-layout-item padding="around-small" size="12">
<lightning-card variant="Narrow" class="slds-cell-wrap">
<c-ad_-flexi-data-table unique-key="Id" column={columns} row-data={data} edit-icon-path={CONSTANT.EDIT_ICON_PATH} undo-icon-path={CONSTANT.DELETE_ICON_PATH}
show-row-action="true" onrowcaction={handleRowAction} table-name='banner' ></c-ad_-flexi-data-table>
</lightning-card>
</lightning-layout-item>
</lightning-layout>
</template>
<!-- Show created banners in table ends here -->
</lightning-card>
<!-- Preview section starts here -->
<template if:true={isModalOpen}>
<section role="dialog" tabindex="-1" aria-modal="true" aria-labelledby="modal-heading-01" class="slds-modal slds-fade-in-open">
<div class="slds-modal__container">
<div class="slds-modal__header">
<h1 id="modal-heading-01" class="slds-modal__title slds-hyphenate">{label.AD_Banner_Preview}</h1>
</div>
<div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
<div class="modal_mainContainer">
<div class="modal_imgContainer">
<img src={visualPickerImage} alt="icon Image" />
</div>
<div style={backgroundColor} class="modal_messageContainer" >
{customMessage}
<template if:true={urlVal}>
Please <a href={urlVal} target="_blank">Click here</a>
</template>
</div>
</div>
</div>
<div class="slds-modal__footer">
<button class="slds-button slds-button_brand" onclick={handleDone} >Done</button>
</div>
</div>
</section>
<div class="slds-backdrop slds-backdrop_open" role="presentation"></div>
<!-- </lightning-modal-footer> -->
</template>
<!-- Preview section ends here -->
<!-- modal popup for delete button -->
<c-ad_-closemodal ongoback={handleCloseModal} is-modal-open={statusWarningModal} warning-message={messageWarning} header={header} > </c-ad_-closemodal>
</template>
Copy paste below code of ad_BannerConfigComponent.js
import { LightningElement, track, api, wire } from 'lwc';
import { displayToast } from "c/ad_Utility";
import { getConstants, getLabels } from "c/ad_Constants"
import { refreshApex } from '@salesforce/apex';
import LightningModal from 'lightning/modal';
//import from apex class
import createBannerRecord from "@salesforce/apex/AD_BannerController.createBannerRecord";
import getAllBannerRecord from "@salesforce/apex/AD_BannerController.getAllBannerRecord";
import deleteBannerContent from "@salesforce/apex/AD_BannerController.deleteBannerContent";
import editBannerContent from "@salesforce/apex/AD_BannerController.editBannerContent";
//import from static resource
import AD_OutageImage from '@salesforce/resourceUrl/AD_OutageImage';
import AD_AttentionPlease from '@salesforce/resourceUrl/AD_AttentionPlease';
import AD_UnderMaintenance from '@salesforce/resourceUrl/AD_UnderMaintenance';
export default class Ad_BannerConfigComponent extends LightningElement {
//Get all the custom labels from AD_Constants LWC Js
label = getLabels();
//get all constants from AD_Utility
CONSTANT = getConstants();
customMessage="";
iconType="";
colorPickerVal=this.CONSTANT.COLORPICKERVAL;
backgroundColor = 'background-color: '+this.CONSTANT.COLORPICKERVAL;
btnDisableStyle=this.CONSTANT.BTNDISABLESTYLE;
btnEnabledStyle=this.CONSTANT.BTNENABLEDSTYLE;
enabledRegions="";
visualPickerID="";
visualPickerImage;
wiredBannerResult;
bannerEdit;
wireBannerData;
error;
messageWarning='';
rowIdToDelete;
bannerDeleted =[];
selectedValues = this.CONSTANT.AVAILABLE_REGIONS;
isBannerActive = true;
isModalOpen=false;
enableCancel = false;
isRendered = false;
statusWarningModal = false;
hideTable = false;
isDuplicate = false;
data;
columns;
urlVal="";
start_date;
end_date;
range;
validateDate = false;
iconImage1 =AD_OutageImage;
iconImage2 =AD_AttentionPlease;
imagesPickerArr=[{id:1,val:AD_AttentionPlease, dataId: "option1"},{id:2,val: AD_OutageImage, dataId: "option2"},{id:3,val:AD_UnderMaintenance, dataId: "option3"}];
header = this.CONSTANT.TITLE_WARNING;
//wire method to retrieve banner records
@wire(getAllBannerRecord)
banner(result) {
console.log("result 79 ==", result);
this.wiredBannerResult = result.data;
if (result.data) {
this.data = result.data;
console.log("data" + result.data.length);
if(result.data.length > 0){
this.hideTable = true;
}else{
this.hideTable = false;
}
console.log(JSON.stringify(this.data));
this.error = undefined;
} else if (result.error) {
this.error = result.error;
this.data = undefined;
}
}
//get region options
get options() {
return [
{ label: this.CONSTANT.USREGION, value: this.CONSTANT.USREGION, idoption: this.CONSTANT.ID_REGION },
{ label: this.CONSTANT.EMEA_REGION, value: this.CONSTANT.EMEA_REGION, idoption: this.CONSTANT.ID_REGION},
{ label: this.CONSTANT.APAC_REGION, value: this.CONSTANT.APAC_REGION, idoption: this.CONSTANT.ID_REGION },
{ label: this.CONSTANT.CALA_REGION, value: this.CONSTANT.CALA_REGION, idoption: this.CONSTANT.ID_REGION }
];
}
//get all options
get option_all() {
return [
{ label: this.CONSTANT.ALL_PRODUCT, value: this.CONSTANT.ALL_PRODUCT, idoption: this.CONSTANT.SELECT_ALL }
];
}
//get banner options
get comboboxOptions() {
return [
{ label: this.CONSTANT.TITLE_WARNING, value: this.CONSTANT.TITLE_WARNING },
{ label: this.CONSTANT.TITLE_INFO, value: this.CONSTANT.TITLE_INFO },
{ label: this.CONSTANT.TITLE_MAINTENANCE, value: this.CONSTANT.TITLE_MAINTENANCE },
];
}
today = new Date();
connectedCallback() {
this.start_date = (this.start_date) ? this.start_date : this.today.toJSON().slice(0,10);
this.end_date = (this.end_date) ? this.end_date : this.addDays(this.today,1).toJSON().slice(0,10);
this.range = this.diff(this.start_date,this.end_date);
this.iconType = this.comboboxOptions[0].value;
}
addDays = (sd,days) => {
const d = new Date(Number(sd));
d.setDate(sd.getDate() + days);
return d;
}
diff = (sdate,edate) => {
let diffTime = Math.abs(new Date(edate).getTime() - new Date(sdate).getTime());
return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
}
valid_date = (sdate,edate) => {
return new Date(edate) >= new Date(sdate);
}
//method to handle date change
handleDateChange = (e) => {
let field_name = e.target.name;
let dateId;
let errorMessage;
let inputDate = e.target.value;
if(field_name === 'startdate'){
this.start_date = e.target.value;
dateId = 'startdate';
errorMessage = this.label.AD_Start_Date_Message;
}
if(field_name === 'enddate'){
this.end_date = e.target.value;
dateId = 'enddate';
errorMessage = this.label.AD_End_Date_Message;
}
let inputfield = this.template.querySelector(`[data-id="${dateId}"]`);
if(new Date(inputDate).setHours(0,0,0,0) < new Date().setHours(0,0,0,0)){
inputfield.setCustomValidity(this.label.AD_Input_Date_Message);
inputfield.reportValidity();
this.validateDate = true;
return;
} else {
inputfield.setCustomValidity("");
inputfield.reportValidity();
this.validateDate = false;
}
if(this.valid_date(this.start_date,this.end_date) == true){
this.range = this.diff(this.start_date,this.end_date);
inputfield.setCustomValidity("");
inputfield.reportValidity();
this.validateDate = false;
}else{
inputfield.setCustomValidity(errorMessage);
inputfield.reportValidity();
this.validateDate = true;
}
}
handleBannerActive(e){
this.isBannerActive = e.target.checked;
}
renderedCallback(){
if(!this.isRendered){
this.isRendered = true;
const selectAllCheckbox = this.template.querySelector(`[data-id="${this.CONSTANT.SELECT_ALL}"]`);
selectAllCheckbox.checked = true;
const checkboxes = this.template.querySelectorAll(`[data-id="${this.CONSTANT.ID_REGION}"]`);
checkboxes.forEach(checkbox => {
checkbox.checked = true;
});
}
}
//method to handle all option
handleSelectAll(e){
const isChecked= e.target.checked;
const select = e.target.value;
const checkboxes = this.template.querySelectorAll(`[data-id="${this.CONSTANT.ID_REGION}"]`);
checkboxes.forEach(checkbox => {
checkbox.checked = isChecked;
});
if(select.includes('ALL') && isChecked){
this.selectedValues = this.options.map(options => options.value);
} else{
this.selectedValues = [];
}
}
//method to handle single region option
handleIndividualChange(e){
const value = e.target.value;
let isChecked = e.target.checked;
const checkboxes = this.template.querySelectorAll(`[data-id="${this.CONSTANT.ID_REGION}"]`);
const selectAllCheckbox = this.template.querySelector(`[data-id="${this.CONSTANT.SELECT_ALL}"]`);
if(checkboxes && isChecked){
const allRegionChecked = Array.from(checkboxes).every(checkbox => (checkbox.checked) == true);
if(allRegionChecked){
selectAllCheckbox.checked = true;
}
this.selectedValues = [...this.selectedValues, value];
} else if(checkboxes && !isChecked){
selectAllCheckbox.checked = false;
const index = (this.selectedValues).indexOf(value);
if(index > -1){
(this.selectedValues).splice(index, 1);
}
}
}
handleCustomMessageChange(e){
this.customMessage= e.target.value;
}
handleBannerTypeChange(e){
this.iconType= e.target.value;
}
handleColorChange(e){
this.colorPickerVal = e.target.value;
}
handleURLChange(e){
this.urlVal = e.target.value;
}
handleImageChange(e){
this.visualPickerID = e.target.value;
let responseArr = this.imagesPickerArr.filter(val => val.id == this.visualPickerID);
this.visualPickerImage = responseArr[0].val;
console.log('modal this.imageObj --> '+ JSON.stringify(responseArr));
}
//method to handle save functionality
handleSave(){
let regionString = (this.selectedValues).join(",");
let startDateString = (this.start_date);
let endDateString = (this.end_date);
let fieldLevelValidation = false;
//Add the error message for No Custom/Link message provided
if (!(this.customMessage != undefined && this.customMessage != '') ) {
fieldLevelValidation = true;
}
//Add the error message for No Image provided
if (!(this.visualPickerID != undefined && this.visualPickerID != ''))
{
fieldLevelValidation = true;
}
//Add the error message for No Banner Type provided
if (!(this.iconType != undefined && this.iconType != ''))
{
fieldLevelValidation = true;
}
//Add the error message for No Banner Region provided
if (!(this.selectedValues != undefined && this.selectedValues != ''))
{
fieldLevelValidation = true;
}
const bannerStartDate = new Date(startDateString);
let activeBanners = (this.wiredBannerResult).filter(banner =>
(banner.Status_Value__c == 'Active') &&
new Date(banner.Start_Date__c) <= bannerStartDate &&
new Date(banner.End_Date__c) >= bannerStartDate &&
banner.Banner_Type__c == this.iconType &&
(this.selectedValues).some(region => (banner.Region_avaiable__c != null && (banner.Region_avaiable__c).split(',').includes(region)))
);
if(this.bannerEdit){
activeBanners = activeBanners.filter(activeBanner => activeBanner.Id != this.bannerEdit);
}
console.log('check activeBanners==' , activeBanners);
//Create new banner if required fields are entered
if(fieldLevelValidation){
this.dispatchEvent(displayToast(this.CONSTANT.TITLE_ERROR,this.label.GeneralError,this.CONSTANT.TOAST_TYPE_ERROR,this.CONSTANT.TOAST_MODE_STICKY));
} else if(this.isBannerActive && activeBanners.length > 0){
this.dispatchEvent(displayToast(this.CONSTANT.TITLE_ERROR,this.label.AD_Active_Banner_Message,this.CONSTANT.TOAST_TYPE_ERROR,this.CONSTANT.TOAST_MODE_STICKY));
} else if(this.validateDate){
this.dispatchEvent(displayToast(this.CONSTANT.TITLE_ERROR,this.label.AD_Banner_Date_Message,this.CONSTANT.TOAST_TYPE_ERROR,this.CONSTANT.TOAST_MODE_STICKY));
} else{
console.log("banner id check== " , this.bannerEdit);
createBannerRecord({
bannerId: this.bannerEdit,
requiredRegion: regionString,
bannerType: this.iconType,
requiredCustomMessage: this.customMessage,
requiredColorPickerVal : this.colorPickerVal,
requiredUrlVal : this.urlVal,
requiredVisualPickerID: this.visualPickerID,
isBannerActive: this.isBannerActive,
startDate: startDateString,
endDate: endDateString})
let message;
if(this.bannerEdit){
message = this.label.AD_Banner_Update_Success;
} else{
message = this.label.AD_Banner_Create_Success;
}
this.dispatchEvent(displayToast(this.CONSTANT.TITLE_SUCCESS, message, this.CONSTANT.TOAST_TYPE_SUCCESS,this.CONSTANT.TOAST_MODE_STICKY));
window.location.href = window.location.href;
}
}
//disable preview button
get isBtnDisabled(){
console.log('inside isBtnDisabled= '+this.customMessage.length + this.selectedValues + this.visualPickerID.length );
if((((this.customMessage.length > 0) && this.selectedValues != null) && this.visualPickerID.length) > 0 && this.iconType){
return false;
}
return true;
}
get previewBtnColor(){
if(this.isBtnDisabled){
return `background-color: ${this.btnDisableStyle};`;
}
return `background-color: ${this.btnEnabledStyle};`;;
}
handlePreview(){
this.isModalOpen=true;
console.log('inside handlePreview '+this.isModalOpen + this.isBtnDisabled );
this.backgroundColor = `background-color: ${this.colorPickerVal};`;
}
handleDone(){
this.isModalOpen=false;
}
//method to handle cancel functionality
handleCancel(){
this.customMessage = "";
this.urlVal = "";
this.colorPickerVal = this.CONSTANT.COLORPICKERVAL;
this.start_date = this.today.toJSON().slice(0,10);;
this.end_date = this.addDays(this.today,1).toJSON().slice(0,10);
this.iconType = "";
for(var i = 0; i < this.imagesPickerArr.length; i++ ){
var idVal = this.imagesPickerArr[i].id;
this.template.querySelector(`input[data-id="option${idVal}"]`).checked = false;
}
//this.enableCancel = false;
const checkboxes = this.template.querySelectorAll(`[data-id="${this.CONSTANT.ID_REGION}"]`);
checkboxes.forEach(checkbox => {
checkbox.checked = true;
});
const selectAllCheckbox = this.template.querySelector(`[data-id="${this.CONSTANT.SELECT_ALL}"]`);
selectAllCheckbox.checked = true;
this.selectedValues = [];
this.bannerEdit = undefined;
this.isBannerActive = this.template.querySelector(`input[data-id="${this.CONSTANT.ACTIVECHECK}"]`).checked = true;
this.iconType = this.comboboxOptions[0].value;
}
//method to handle delete and edit action
get handleRowAction() {
return (event) => {
// Row action for Delete
console.log("id check== " + event.detail.index.Id);
if (event.detail.table == 'banner' && event.detail.name == 'bannerdelete') {
this.statusWarningModal = true;
this.messageWarning = this.label.AD_Banner_Delete_Confirmation;
this.rowIdToDelete = event.detail.index.Id;
}
// Row action for Edit
if (event.detail.table == 'banner' && event.detail.name == 'bannerEdit') {
console.log("index==" + event.detail.index.Id);
//this.enableCancel = true;
this.handleEdit(event.detail.index.Id);
}
};
}
handleDelete(bannerId) {
console.log("test ID:::" + bannerId);
this.bannerDeleted = bannerId;
deleteBannerContent({ recordIds: this.bannerDeleted })
.then(result => {
console.log('data check : '+JSON.stringify(result));
this.handleCancel();
//Display toast message for banner deleted successfully
this.dispatchEvent(displayToast(this.CONSTANT.TITLE_SUCCESS, this.label.AD_Banner_Delete_Success, this.CONSTANT.TOAST_TYPE_SUCCESS, this.CONSTANT.TOAST_MODE_DISMISSIBLE));
window.location.href = window.location.href;
})
.catch(error => {
//Display toast message for apex and LWC error
this.dispatchEvent(displayToast(this.CONSTANT.TITLE_ERROR, error.message, this.CONSTANT.TOAST_TYPE_ERROR, this.CONSTANT.TOAST_MODE_STICKY));
});
}
handleEdit(bannerId) {
console.log("test ID - edit " + bannerId);
this.bannerEdit = bannerId;
editBannerContent({ recordId: this.bannerEdit })
.then(result => {
//get record values
this.customMessage = result.customMessage__c;
this.urlVal = result.UrlVal__c;
this.colorPickerVal = result.colorPickerVal__c;
this.start_date = result.Start_Date__c;
this.end_date = result.End_Date__c;
this.iconType = result.Banner_Type__c;
this.selectedValues = (result.Region_avaiable__c).split(",");
const checkboxes = this.template.querySelectorAll(`[data-id="${this.CONSTANT.ID_REGION}"]`);
const selectAllCheckbox = this.template.querySelector(`[data-id="${this.CONSTANT.SELECT_ALL}"]`);
for(var i =0; i<checkboxes.length; i++){
const checkbox = checkboxes[i];
if((this.selectedValues).includes(checkbox.value)){
checkbox.checked = true;
} else {
checkbox.checked = false;
}
}
if(checkboxes.length == (this.selectedValues.length)){
selectAllCheckbox.checked = true;
} else {
selectAllCheckbox.checked = false;
}
if(result.Active__c){
this.template.querySelector(`input[data-id="${this.CONSTANT.ACTIVECHECK}"]`).checked = true;
}else{
this.template.querySelector(`input[data-id="${this.CONSTANT.ACTIVECHECK}"]`).checked = false;
}
let idVal = result.VisualPickerID__c;
this.template.querySelector(`input[data-id="option${idVal}"]`).checked = true;
this.visualPickerID = idVal;
let responseArr = this.imagesPickerArr.filter(val => val.id == this.visualPickerID);
this.visualPickerImage = responseArr[0].val;
})
.catch(error => {
//Display toast message for apex and LWC error
this.dispatchEvent(displayToast(this.CONSTANT.TITLE_ERROR, error.body.message, this.CONSTANT.TOAST_TYPE_ERROR, this.CONSTANT.TOAST_MODE_STICKY));
});
}
// Handler if Yes/No clicked in the warning pop-up
handleCloseModal(event) {
if (event.detail.isUserCycleCount == true) {
console.log('this.rowIdToDelete', this.rowIdToDelete);
this.handleDelete(this.rowIdToDelete);
} else if(event.detail == false) {
this.statusWarningModal = false;
}
}
columns=
[{
index: 0,
label: 'Region',
field: "Region_avaiable__c",
dataType: 'text',
disabled: false,
sortable: true,
filterable: false,
editable: false,
required: false
},
{
index: 1,
label: 'Banner Type',
field: 'Banner_Type__c',
dataType: 'text',
disabled: false,
sortable: true,
filterable: false,
editable: false,
required: false
},
{
index: 2,
label: 'Custom Message',
field: 'customMessage__c',
dataType: 'text',
disabled: false,
sortable: false,
filterable: false,
editable: false,
required: false,
},
{
index: 3,
label: 'Link',
field: 'UrlVal__c',
dataType: 'text',
disabled: false,
sortable: false,
filterable: false,
editable: false,
required: false,
},
{
index: 4,
label: 'Status',
field: 'Status_Value__c',
dataType: 'text',
disabled: false,
sortable: true,
filterable: false,
editable: false,
required: false,
},
{
index: 5,
label: 'Start Date',
field: 'Start_Date__c',
dataType: 'date',
disabled: false,
sortable: true,
filterable: false,
editable: false,
required: false,
},
{
index: 6,
label: 'End Date',
field: 'End_Date__c',
dataType: 'date',
disabled: false,
sortable: true,
filterable: false,
editable: false,
required: false,
}]
}
Copy paste below code of ad_BannerConfigComponent.css
.dummy{
color : black;
}
.main_container{
padding: 1.5rem;
padding-inline: 2rem;
}
.cmp_container{
margin-bottom: 0.7rem;
}
.slds-form-element__control {
display: inline-flex;
}
.dsp_grid{
display: grid;
grid-template-columns: 1fr 1fr;
align-items: start;
}
.dsp_flex{
display: flex;
align-items: center;
justify-content: center;
grid-template-rows: auto auto;
}
.bgG{
/* border: 2px rgb(1, 148, 1) solid; */
}
.bgR{
/* border: 2px rgb(209, 30, 75) solid; */
}
/* CSS */
.btn {
appearance: button;
backface-visibility: hidden;
background-color: #405cf5;
border-radius: 6px;
border-width: 0;
box-shadow: rgba(50, 50, 93, .1) 0 0 0 1px inset,rgba(50, 50, 93, .1) 0 2px 5px 0,rgba(0, 0, 0, .07) 0 1px 1px 0;
box-sizing: border-box;
color: #fff;
cursor: pointer;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI;
font-size: 16px;
height: 42px;
margin: 12px 7px 0;
outline: none;
overflow: hidden;
padding: 0 25px;
position: relative;
text-align: center;
text-transform: none;
transition: all .2s,box-shadow .08s ease-in;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
}
.button{
--slds-c-button-line-height: 2rem;
}
.btn:disabled {
cursor: default;
}
.btn:focus {
box-shadow: rgba(50, 50, 93, .1) 0 0 0 1px inset, rgba(50, 50, 93, .2) 0 6px 15px 0, rgba(0, 0, 0, .1) 0 2px 2px 0, rgba(50, 151, 211, .3) 0 0 0 4px;
}
.chk{
font-size: 15px;
}
.custom_msg{
/* margin-top: 0.5rem; */
padding-bottom: 0.5rem;
}
.cntrl_combobox{
width: 18rem;
}
.color_picker {
display: grid;
grid-template-columns: 1fr 2fr;
align-items: start;
}
.preview_btn{
min-height: 100%;
display: flex;
align-items: start;
justify-content: center;
}
.preview_btn > button{
width: 40%;
padding: 0 10px;
}
.icon_preview{
padding-bottom: 0.5rem;
}
.imgContainer{
/* padding: 0.7rem; */
}
.img_picker{
margin-top: 0.4rem;
border: 2px solid rgb(177, 175, 175);
border-radius: 4px;
padding: 1rem;
width: 21rem;
height: 7.3rem;
overflow-y: hidden;
overflow-x: auto;
/* scrollbar-width: thin;
scrollbar-color: rgb(8, 111, 196) rgb(230, 228, 226); */
}
.style-3::-webkit-scrollbar {
height: 8px; /* width of the entire scrollbar */
}
.style-3::-webkit-scrollbar-track {
background: rgb(230, 229, 228); /* color of the tracking area */
}
.style-3::-webkit-scrollbar-thumb {
background-color: rgb(64,92,245); /* color of the scroll thumb */
border-radius: 20px; /* roundness of the scroll thumb */
border: 3px solid rgb(230, 229, 228)ange; /* creates padding around scroll thumb */
}
.cntrl_picker{
width: 5rem;
height: 5rem;
}
.margin_btm{
margin-bottom: -0.7rem;
}
.req {
color: red;
}
.headings{
font-size:110%;
font-weight:500;
/* font-family: system-ui; */
}
.checkbox{
font-size:100%;
font-weight:400;
/* font-family: system-ui; */
}
.footer{
padding-inline: 1.5rem;
}
.text{
font-size: 1rem;
}
/* _____________Modal CSS ____________ */
.modal_mainContainer{
display: flex;
align-items: center;
border: 2px rgb(216, 214, 214) solid;
}
.modal_imgContainer > img{
width: 6rem;
height: 6rem;
}
.modal_messageContainer{
height: 6rem;
width: 80rem;
padding-top: 0.3rem;
padding-left: 0.5rem;
font-size: 1rem;
font-family: Arial, Helvetica, sans-serif;
overflow-x: hidden;
}
.slds-modal__container {
max-width: 80rem !important;
width: 80% !important;
}
.modal_link{
color: rgb(76, 147, 240);
}
Copy Paste below code of ad_BannerConfigComponent.js-meta.xml
<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>63.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
<target>lightning__RecordPage</target>
<target>lightning__Tab</target>
</targets>
</LightningComponentBundle>
Create LWC Component – ad_Utility
Copy Paste below code of ad_Utility.js
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
//import { NavigationMixin } from 'lightning/navigation';
//import FORM_FACTOR from "@salesforce/client/formFactor";
/**Generic method for show toast notification.
* @param {String} title -Title of the toast message.
* @param {String} message Message of the toast message.
* @param {String} variant Variant of the toast like error, warning success.
* @returns {Event} ShowToastEvent
*/
function displayToast(title, message, variant, mode = 'dismissable') {
const evt = new ShowToastEvent({
title: title,
message: message,
variant: variant,
mode: mode
});
return evt;
}
/*
function DateFormaterWithTime(dateValue) {
let months = MonthList.split(',');
let d = new Date(dateValue);
let mon = (d.getDate() < 10 ? '0' + d.getDate() : d.getDate());
var hours = d.getHours();
var minutes = d.getMinutes();
var ampm = hours >= 12 ? 'am' : 'pm';
hours = hours % 12;
hours = hours ? hours : 12;
minutes = minutes < 10 ? '0' + minutes : minutes;
return months[d.getMonth()] + ' ' + mon + ', ' + d.getFullYear() + ' ' + hours + ':' + minutes + ' ' + ampm;
}
function DateFormaterWithoutTime(dateValue) {
let months = MonthList.split(',');
let d = new Date(dateValue);
let dueDateSplit = dateValue.toString().split('-');
//let mon = (d.getDate() < 10 ? '0' + d.getDate() : d.getDate());
//return months[d.getMonth()] + ' ' + mon + ', ' + d.getFullYear();
return months[d.getUTCMonth()] + ' ' + dueDateSplit[2] + ', ' + d.getUTCFullYear();
} */
export { displayToast };
Copy paste below code of ad_Utility.js-meta.xml
<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>63.0</apiVersion>
<isExposed>true</isExposed>
</LightningComponentBundle>
Create LWC Component ad_Dynamic_Banner
Copy paste below code of ad_Dynamic_Banner.html
<template>
<!-- Display banner on home page-->
<template iterator:it={bannerRecord} >
<div class="slds-p-around_xx-small slds-m-bottom_medium" style={it.value.backgroundColor} key={it.value.Id}>
<lightning-layout >
<lightning-layout-item size="1">
<img src={it.value.visualPickerImage} alt="Outage Image" />
</lightning-layout-item>
<lightning-layout-item class="slds-p-left_x-small">
<p>{it.value.customMessage}
<template if:true={it.value.urlVal}>
Please <a href={it.value.urlVal} target="_blank">Click here</a>
</template>
</p>
</lightning-layout-item>
</lightning-layout>
</div>a
</template>
</template>
Copy paste below code of ad_Dynamic_Banner.js
/**********************************************************************************************
* @name : ad_Dynamic_Banner.js
* @description : Utility component to show active banners
*----------------------------------------------------------------------------------------------
* Modification Log:
*----------------------------------------------------------------------------------------------
***********************************************************************************************/
import { LightningElement, wire, track } from 'lwc';
import getActiveBannerRecord from "@salesforce/apex/AD_BannerController.getActiveBannerRecord";
import AD_OutageImage from '@salesforce/resourceUrl/AD_OutageImage';
import AD_AttentionPlease from '@salesforce/resourceUrl/AD_AttentionPlease';
import AD_UnderMaintenance from '@salesforce/resourceUrl/AD_UnderMaintenance';
export default class Ad_Dynamic_Banner extends LightningElement {
error;
id;
customMessage;
colorPickerVal;
urlVal;
visualPickerID;
visualPickerImage;
backgroundColor;
regionAvailable = [];
@track bannerRecord = [];
@track userRegion = '';
imagesPickerArr=[{id:1,val:AD_OutageImage},{id:2,val:AD_AttentionPlease},{id:3,val:AD_UnderMaintenance},{id:4,val:AD_UnderMaintenance},{id:5,val:AD_UnderMaintenance},{id:6,val:AD_OutageImage},{id:7,val:AD_AttentionPlease}];
//wire to fetch the Active banners
@wire(getActiveBannerRecord)
wiredBannerRecord({ error, data }) {
if (data) {
console.log('DATA -> '+JSON.stringify(data));
data.forEach(banner => {
let responseArr = this.imagesPickerArr.filter(val => val.id == banner.VisualPickerID__c);
this.bannerRecord.push({
"Id" : banner.Id,
"backgroundColor" : `background-color: ${banner.colorPickerVal__c};`,
"visualPickerImage" : responseArr[0].val,
"customMessage" : banner.customMessage__c,
"urlVal" : banner.UrlVal__c
})
})
this.error = undefined;
} else if (error) {
this.error = error;
this.bannerRecord = undefined;
console.log('DATA ERROR -> '+JSON.stringify(this.error));
}
}
}
Copy paste below code of ad_Dynamic_Banner.js-meta.xml
<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>63.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
<target>lightning__RecordPage</target>
<target>lightning__Tab</target>
</targets>
</LightningComponentBundle>
Copy paste below code of ad_Dynamic_Banner.css
.custom-container{
color : black;
}
Create Lightning Component Tab – Banner Config

Drag and Drop ad_Dynamic_Banner LWC Component on top of lightning page

