diff --git a/aura/strike_lookup/strike_lookup.cmp b/aura/strike_lookup/strike_lookup.cmp index fecf404..1aa3fb7 100644 --- a/aura/strike_lookup/strike_lookup.cmp +++ b/aura/strike_lookup/strike_lookup.cmp @@ -1,212 +1,212 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - - - - - - - {!if(v.initCallsRunning > 0, v.loadingMessage, v.valueLabel)} - - -
-
-
- - -
- -
- -
-
-
-
-
    -
  • - -
    -
    {!v.searchingMessage}
    -
    -
    -
  • -
-
-
-
-
    -
  • - -
    -
    - {!format(v.noResultsMessage, '"' + v.lastSearchTerm + '"')} -
    -
    -
    -
  • -
-
-
    - - - - - - -
-
-
- - -
{!v.errorMessage}
-
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + {!if(v.initCallsRunning > 0, v.loadingMessage, v.valueLabel)} + + +
+
+
+ + +
+ +
+ +
+
+
+
+
    +
  • + +
    +
    {!v.searchingMessage}
    +
    +
    +
  • +
+
+
+
+
    +
  • + +
    +
    + {!format(v.noResultsMessage, '"' + v.lastSearchTerm + '"')} +
    +
    +
    +
  • +
+
+
    + + + + + + +
+
+
+ + +
{!v.errorMessage}
+
+
\ No newline at end of file diff --git a/aura/strike_lookup/strike_lookupController.js b/aura/strike_lookup/strike_lookupController.js index e1d9ca0..24e4999 100644 --- a/aura/strike_lookup/strike_lookupController.js +++ b/aura/strike_lookup/strike_lookupController.js @@ -1,242 +1,244 @@ /*Strike by Appiphony -Version: 1.0.0 -Website: http://www.lightningstrike.io -GitHub: https://github.com/appiphony/Strike-Components -License: BSD 3-Clause License*/ + Version: 1.0.0 + Website: http://www.lightningstrike.io + GitHub: https://github.com/appiphony/Strike-Components + License: BSD 3-Clause License +*/ ({ - onInit: function(component, event, helper) { - component.handleClick = $A.getCallback(function() { - if (!component.isValid()) { - window.removeEventListener('click', component.handleClick); - - return; - } - - helper.closeMenu(component, event, helper); - }); - - window.addEventListener('click', component.handleClick); - - component.set('v.initCallsRunning', 3); - - helper.getRecentRecords(component, event, helper); - helper.getRecordByValue(component, event, helper); - helper.getRecordLabel(component, event, helper); - - var randomNumber = Math.floor(1000 + Math.random() * 9000); - - component.set('v.idNumber', randomNumber); - - component.set('v.isMobile', $A.get('$Browser.formFactor') === 'DESKTOP' ? false : true); - }, - handleInputClick: function(component, event, helper) { - event.stopPropagation(); - }, - handleSearchingClick: function(component, event, helper) { - component.set('v.searching', false); - }, - handleInputFocus: function(component, event, helper) { - $A.util.addClass(component.find('lookup'), 'sl-lookup--open'); - - if (component.get('v.disabled')) { - return; - } - - helper.getRecordsBySearchTerm(component, event, helper); - }, - cancelLookup: function(component, event, helper) { - helper.closeMobileLookup(component, event, helper); - }, - handleInputKeyDown: function(component, event, helper) { - if (component.get('v.disabled')) { - return; - } - - var KEYCODE_TAB = 9; - - var keyCode = event.which || event.keyCode || 0; - - if (keyCode === KEYCODE_TAB) { - helper.closeMenu(component, event, helper); - } - }, - handleInputKeyPress: function(component, event, helper) { - if (component.get('v.disabled')) { - return; - } - }, - handleInputKeyUp: function(component, event, helper) { - if (component.get('v.disabled')) { - return; - } - - var KEYCODE_ENTER = 13; - var KEYCODE_UP = 38; - var KEYCODE_DOWN = 40; - - var keyCode = event.which || event.keyCode || 0; - - if (keyCode === KEYCODE_ENTER) { - helper.updateValueByFocusIndex(component, event, helper); - } else if (keyCode === KEYCODE_UP) { - helper.moveRecordFocusUp(component, event, helper); - } else if (keyCode === KEYCODE_DOWN) { - helper.moveRecordFocusDown(component, event, helper); - } else { - helper.getRecordsBySearchTerm(component, event, helper); - } - }, - - handleRecordClick: function(component, event, helper) { - event.preventDefault(); - event.stopPropagation(); - - var focusIndex = event.currentTarget.dataset.index; - - component.set('v.focusIndex', focusIndex); - - helper.updateValueByFocusIndex(component, event, helper); - }, - handleNewRecordClick: function(component, event, helper) { - event.preventDefault(); - event.stopPropagation(); - - helper.addNewRecord(component, event, helper); - }, - handlePillClick: function(component, event, helper) { - event.preventDefault(); - event.stopPropagation(); - - component.set('v.value', ''); - - helper.getRecordsBySearchTerm(component, event, helper); - - window.setTimeout($A.getCallback(function() { - component.find('lookupInput').getElement().focus(); - }), 1); - }, - - handleFocusIndexChange: function(component, event, helper) { - var focusIndex = component.get('v.focusIndex'); - var lookupMenu = component.find('lookupMenu').getElement(); - - if (!$A.util.isEmpty(lookupMenu)) { - var options = lookupMenu.getElementsByTagName('li'); - var focusScrollTop = 0; - var focusScrollBottom = 0; - - for (var i = 0; i < options.length; i++) { - var optionSpan = options[i].getElementsByTagName('span')[0]; - - if (i === focusIndex) { - $A.util.addClass(optionSpan, 'slds-has-focus'); - } else { - if (i < focusIndex) { - focusScrollTop += options[i].scrollHeight; - } - - $A.util.removeClass(optionSpan, 'slds-has-focus'); - } - } - - if (focusIndex !== null) { - focusScrollBottom = focusScrollTop + options[focusIndex].scrollHeight; - } - - if (focusScrollTop < lookupMenu.scrollTop) { - lookupMenu.scrollTop = focusScrollTop; - } else if (focusScrollBottom > lookupMenu.scrollTop + lookupMenu.clientHeight) { - lookupMenu.scrollTop = focusScrollBottom - lookupMenu.clientHeight; - } - } - }, - handleValueChange: function(component, event, helper) { - var value = component.get('v.value'); - - if ($A.util.isEmpty(value)) { - component.set('v.valueLabel', ''); - } else if ($A.util.isEmpty(component.get('v.valueLabel'))) { - helper.getRecordByValue(component, event, helper); - } - }, - - handleFilterChange: function(component, event, helper) { - component.set('v.initCallsRunning', 2); - - helper.getRecordByValue(component, event, helper); - helper.getRecentRecords(component, event, helper); - - component.find('lookupInput').getElement().value = ''; - helper.getRecordsBySearchTerm(component, event, helper); - }, - handleLimitChange: function(component, event, helper) { - component.find('lookupInput').getElement().value = ''; - helper.getRecordsBySearchTerm(component, event, helper); - }, - handleObjectChange: function(component, event, helper) { - component.set('v.initCallsRunning', 3); - - helper.getRecentRecords(component, event, helper); - helper.getRecordByValue(component, event, helper); - helper.getRecordLabel(component, event, helper); - - component.find('lookupInput').getElement().value = ''; - helper.getRecordsBySearchTerm(component, event, helper); - }, - handleOrderChange: function(component, event, helper) { - component.set('v.initCallsRunning', 1); - - helper.getRecentRecords(component, event, helper); - - component.find('lookupInput').getElement().value = ''; - helper.getRecordsBySearchTerm(component, event, helper); - }, - handleSearchfieldChange: function(component, event, helper) { - component.set('v.initCallsRunning', 2); - - helper.getRecentRecords(component, event, helper); - helper.getRecordByValue(component, event, helper); - - component.find('lookupInput').getElement().value = ''; - helper.getRecordsBySearchTerm(component, event, helper); - }, - handleSubtitlefieldChange: function(component, event, helper) { - component.set('v.initCallsRunning', 1); - - helper.getRecentRecords(component, event, helper); - - component.find('lookupInput').getElement().value = ''; - helper.getRecordsBySearchTerm(component, event, helper); - }, - - showError: function(component, event, helper) { - var errorMessage = event.getParam('arguments').errorMessage; - - component.set('v.errorMessage', errorMessage); - component.set('v.error', true); - }, - hideError: function(component, event, helper) { - component.set('v.errorMessage', null); - component.set('v.error', false); - } + onInit: function(component, event, helper) { + component.handleClick = $A.getCallback(function() { + if (!component.isValid()) { + window.removeEventListener('click', component.handleClick); + + return; + } + + helper.closeMenu(component, event, helper); + }); + + window.addEventListener('click', component.handleClick); + + component.set('v.initCallsRunning', 3); + + helper.getRecentRecords(component, event, helper); + helper.getRecordByValue(component, event, helper); + helper.getRecordLabel(component, event, helper); + + var randomNumber = Math.floor(1000 + Math.random() * 9000); + + component.set('v.idNumber', randomNumber); + + component.set('v.isMobile', $A.get('$Browser.formFactor') === 'DESKTOP' ? false : true); + }, + handleInputClick: function(component, event, helper) { + event.stopPropagation(); + }, + handleSearchingClick: function(component, event, helper) { + component.set('v.searching', false); + }, + handleInputFocus: function(component, event, helper) { + $A.util.addClass(component.find('lookup'), 'sl-lookup--open'); + + if (component.get('v.disabled')) { + return; + } + + helper.getRecordsBySearchTerm(component, event, helper); + }, + cancelLookup: function(component, event, helper) { + helper.closeMobileLookup(component, event, helper); + }, + handleInputKeyDown: function(component, event, helper) { + if (component.get('v.disabled')) { + return; + } + + var KEYCODE_TAB = 9; + + var keyCode = event.which || event.keyCode || 0; + + if (keyCode === KEYCODE_TAB) { + helper.closeMenu(component, event, helper); + } + }, + handleInputKeyPress: function(component, event, helper) { + if (component.get('v.disabled')) { + return; + } + }, + handleInputKeyUp: function(component, event, helper) { + if (component.get('v.disabled')) { + return; + } + + var KEYCODE_ENTER = 13; + var KEYCODE_UP = 38; + var KEYCODE_DOWN = 40; + + var keyCode = event.which || event.keyCode || 0; + + if (keyCode === KEYCODE_ENTER) { + helper.updateValueByFocusIndex(component, event, helper); + } else if (keyCode === KEYCODE_UP) { + helper.moveRecordFocusUp(component, event, helper); + } else if (keyCode === KEYCODE_DOWN) { + helper.moveRecordFocusDown(component, event, helper); + } else { + helper.getRecordsBySearchTerm(component, event, helper); + } + }, + + handleRecordClick: function(component, event, helper) { + event.preventDefault(); + event.stopPropagation(); + + var focusIndex = event.currentTarget.dataset.index; + + component.set('v.focusIndex', focusIndex); + + helper.updateValueByFocusIndex(component, event, helper); + }, + handleNewRecordClick: function(component, event, helper) { + event.preventDefault(); + event.stopPropagation(); + + helper.addNewRecord(component, event, helper); + }, + handlePillClick: function(component, event, helper) { + event.preventDefault(); + event.stopPropagation(); + + component.set('v.value', ''); + + helper.getRecordsBySearchTerm(component, event, helper); + + window.setTimeout($A.getCallback(function() { + component.find('lookupInput').getElement().focus(); + }), 1); + }, + + handleFocusIndexChange: function(component, event, helper) { + var focusIndex = component.get('v.focusIndex'); + var lookupMenu = component.find('lookupMenu').getElement(); + + if (!$A.util.isEmpty(lookupMenu)) { + var options = lookupMenu.getElementsByTagName('li'); + var focusScrollTop = 0; + var focusScrollBottom = 0; + + for (var i = 0; i < options.length; i++) { + var optionSpan = options[i].getElementsByTagName('span')[0]; + + if (i === focusIndex) { + $A.util.addClass(optionSpan, 'slds-has-focus'); + } else { + if (i < focusIndex) { + focusScrollTop += options[i].scrollHeight; + } + + $A.util.removeClass(optionSpan, 'slds-has-focus'); + } + } + + if (focusIndex !== null) { + focusScrollBottom = focusScrollTop + options[focusIndex].scrollHeight; + } + + if (focusScrollTop < lookupMenu.scrollTop) { + lookupMenu.scrollTop = focusScrollTop; + } else if (focusScrollBottom > lookupMenu.scrollTop + lookupMenu.clientHeight) { + lookupMenu.scrollTop = focusScrollBottom - lookupMenu.clientHeight; + } + } + }, + handleValueChange: function(component, event, helper) { + var value = component.get('v.value'); + + if ($A.util.isEmpty(value)) { + component.set('v.valueLabel', ''); + } else if ($A.util.isEmpty(component.get('v.valueLabel'))) { + helper.getRecordByValue(component, event, helper); + } + }, + + handleFilterChange: function(component, event, helper) { + component.set('v.initCallsRunning', 2); + + helper.getRecordByValue(component, event, helper); + helper.getRecentRecords(component, event, helper); + + component.find('lookupInput').getElement().value = ''; + helper.getRecordsBySearchTerm(component, event, helper); + }, + handleLimitChange: function(component, event, helper) { + component.find('lookupInput').getElement().value = ''; + helper.getRecordsBySearchTerm(component, event, helper); + }, + handleObjectChange: function(component, event, helper) { + component.set('v.initCallsRunning', 3); + + helper.getRecentRecords(component, event, helper); + helper.getRecordByValue(component, event, helper); + helper.getRecordLabel(component, event, helper); + + component.find('lookupInput').getElement().value = ''; + helper.getRecordsBySearchTerm(component, event, helper); + }, + handleOrderChange: function(component, event, helper) { + component.set('v.initCallsRunning', 1); + + helper.getRecentRecords(component, event, helper); + + component.find('lookupInput').getElement().value = ''; + helper.getRecordsBySearchTerm(component, event, helper); + }, + handleSearchfieldChange: function(component, event, helper) { + component.set('v.initCallsRunning', 2); + + helper.getRecentRecords(component, event, helper); + helper.getRecordByValue(component, event, helper); + + component.find('lookupInput').getElement().value = ''; + helper.getRecordsBySearchTerm(component, event, helper); + }, + handleSubtitlefieldChange: function(component, event, helper) { + component.set('v.initCallsRunning', 1); + + helper.getRecentRecords(component, event, helper); + + component.find('lookupInput').getElement().value = ''; + helper.getRecordsBySearchTerm(component, event, helper); + }, + + showError: function(component, event, helper) { + var errorMessage = event.getParam('arguments').errorMessage; + + component.set('v.errorMessage', errorMessage); + component.set('v.error', true); + }, + hideError: function(component, event, helper) { + component.set('v.errorMessage', null); + component.set('v.error', false); + } }) /*Copyright 2017 Appiphony, LLC -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following -disclaimer in the documentation and/or other materials provided with the distribution. -3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/ \ No newline at end of file + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following + disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ \ No newline at end of file diff --git a/aura/strike_lookup/strike_lookupHelper.js b/aura/strike_lookup/strike_lookupHelper.js index 02434da..b577ab9 100644 --- a/aura/strike_lookup/strike_lookupHelper.js +++ b/aura/strike_lookup/strike_lookupHelper.js @@ -1,308 +1,312 @@ /*Strike by Appiphony -Version: 1.0.0 -Website: http://www.lightningstrike.io -GitHub: https://github.com/appiphony/Strike-Components -License: BSD 3-Clause License*/ + Version: 1.0.0 + Website: http://www.lightningstrike.io + GitHub: https://github.com/appiphony/Strike-Components + License: BSD 3-Clause License +*/ ({ - checkIfInitialized: function(component, event, helper) { - var initCallsRunning = component.get('v.initCallsRunning'); - - if (--initCallsRunning < 0) { - initCallsRunning = 0; - } - - component.set('v.initCallsRunning', initCallsRunning); - }, - closeMenu: function(component, event, helper) { - component.set('v.focusIndex', null); - component.set('v.openMenu', false); - }, - getParams: function(component, event, helper) { - var filter = component.get('v.filter'); - var limit = component.get('v.limit'); - var object = component.get('v.object'); - var order = component.get('v.order'); - var searchField = component.get('v.searchField'); - var subtitleField = component.get('v.subtitleField'); - - return { - filter: filter, - limit: limit, - object: object, - order: order, - searchField: searchField, - subtitleField: subtitleField - }; - }, - getRecentRecords: function(component, event, helper) { - var returnedRecords = []; - - var getRecordsAction = component.get('c.getRecentRecords'); - - getRecordsAction.setParams({ - jsonString: JSON.stringify(helper.getParams(component, event, helper)) - }); - - getRecordsAction.setCallback(this, function(res) { - if (res.getState() === 'SUCCESS') { - var returnValue = JSON.parse(res.getReturnValue()); - - if (returnValue.isSuccess) { - returnValue.results.data.forEach(function(record) { - returnedRecords.push({ - label: record.label, - sublabel: record.sublabel, - value: record.value - }); - }); - } - } - component.set('v.recentRecords', returnedRecords); - - helper.checkIfInitialized(component, event, helper); - }); - - $A.enqueueAction(getRecordsAction); - }, - getRecordByValue: function(component, event, helper) { - var value = component.get('v.value'); - - if (!value) { - component.set('v.valueLabel', null); - component.set('v.valueSublabel', null); - helper.checkIfInitialized(component, event, helper); - - return; - } - - var getRecordsAction = component.get('c.getRecords'); - var params = helper.getParams(component, event, helper); - - if ($A.util.isEmpty(params.filter)) { - params.filter = 'Id = \'' + value + '\''; - } else { - params.filter = 'Id = \'' + value + '\' AND (' + params.filter + ')'; - } - - getRecordsAction.setParams({ - jsonString: JSON.stringify(params) - }); - - getRecordsAction.setCallback(this, function(res) { - if (res.getState() === 'SUCCESS') { - var returnValue = JSON.parse(res.getReturnValue()); - - if (returnValue.isSuccess) { - returnValue.results.data.forEach(function(record) { - component.set('v.valueLabel', record.label); - component.set('v.valueSublabel', record.sublabel); - }); - } - } - - helper.checkIfInitialized(component, event, helper); - }); - - $A.enqueueAction(getRecordsAction); - }, - getRecordLabel: function(component, event, helper) { - var getRecordLabelAction = component.get('c.getRecordLabel'); - - getRecordLabelAction.setParams({ - jsonString: JSON.stringify({ - object: component.get('v.object') - }) - }); - - getRecordLabelAction.setCallback(this, function(res) { - if (res.getState() === 'SUCCESS') { - var returnValue = JSON.parse(res.getReturnValue()); - - if (returnValue.isSuccess) { - component.set('v.objectLabel', returnValue.results.objectLabel); - } - } - - helper.checkIfInitialized(component, event, helper); - }); - - $A.enqueueAction(getRecordLabelAction); - }, - getRecordsBySearchTerm: function(component, event, helper) { - var searchTerm = component.find('lookupInput').getElement().value; - - var lastSearchTerm = component.get('v.lastSearchTerm'); - var searchTimeout = component.get('v.searchTimeout'); - var showRecentRecords = component.get('v.showRecentRecords'); - - clearTimeout(searchTimeout); - - if ($A.util.isEmpty(searchTerm)) { - if (showRecentRecords) { - helper.setRecords(component, event, helper, component.get('v.recentRecords')); - } else { - helper.setRecords(component, event, helper, []); - } - - return; - } else if (searchTerm === lastSearchTerm) { - component.set('v.searching', false); - helper.openMenu(component, event, helper); - - return; - } - - component.set('v.openMenu', true); - component.set('v.searching', true); - - component.set('v.searchTimeout', setTimeout($A.getCallback(function() { - if (!component.isValid()) { - return; - } - - var getRecordsAction = component.get('c.getRecords'); - var params = helper.getParams(component, event, helper); - - params.searchTerm = component.find('lookupInput').getElement().value; - - getRecordsAction.setParams({ - jsonString: JSON.stringify(params) - }); - - getRecordsAction.setCallback(this, function(res) { - if (res.getState() === 'SUCCESS') { - var returnValue = JSON.parse(res.getReturnValue()); - - if (returnValue.isSuccess && returnValue.results.searchTerm === component.find('lookupInput').getElement().value) { - var returnedRecords = []; - - returnValue.results.data.forEach(function(record) { - returnedRecords.push({ - label: record.label, - sublabel: record.sublabel, - value: record.value - }); - }); - - helper.setRecords(component, event, helper, returnedRecords); - } - } else { - helper.setRecords(component, event, helper, []); - } - }); - - $A.enqueueAction(getRecordsAction); - }), 200)); - }, - setRecords: function(component, event, helper, returnedRecords) { - component.set('v.focusIndex', null); - component.set('v.lastSearchTerm', component.find('lookupInput').getElement().value); - component.set('v.records', returnedRecords); - component.set('v.searching', false); - - helper.openMenu(component, event, helper); - }, - openMenu: function(component, event, helper) { - var showRecentRecords = component.get('v.showRecentRecords') && !$A.util.isEmpty(component.get('v.recentRecords')); - component.set('v.openMenu', !component.get('v.disabled') && (!$A.util.isEmpty(component.get('v.lastSearchTerm')) || showRecentRecords)); - }, - closeMobileLookup: function(component, event, helper) { - $A.util.removeClass(component.find('lookup'), 'sl-lookup--open'); - component.find('lookupInput').getElement().value = '' - }, - updateValueByFocusIndex: function(component, event, helper) { - var focusIndex = component.get('v.focusIndex'); - - if (focusIndex == null) { - focusIndex = 0; - } - - var records = component.get('v.records'); - - if (focusIndex < records.length) { - component.set('v.value', records[focusIndex].value); - component.set('v.valueLabel', records[focusIndex].label); - component.set('v.valueSublabel', records[focusIndex].sublabel); - component.find('lookupInput').getElement().value = ''; - - helper.closeMenu(component, event, helper); - } else if (focusIndex === records.length) { - helper.addNewRecord(component, event, helper); - } - - helper.closeMobileLookup(component, event, helper); - }, - addNewRecord: function(component, event, helper) { - if (!component.get('v.allowNewRecords')) { - return; - } - - var addRecordEvent; - var overrideNewEvent = component.get('v.overrideNewEvent'); - - if (overrideNewEvent) { - addRecordEvent = component.getEvent('strike_evt_addNewRecord'); - } else { - addRecordEvent = $A.get('e.force:createRecord'); - - addRecordEvent.setParams({ - entityApiName: component.get('v.object') - }); - } - addRecordEvent.fire(); - - helper.closeMenu(component, event, helper); - }, - moveRecordFocusUp: function(component, event, helper) { - var openMenu = component.get('v.openMenu'); - - if (openMenu) { - var focusIndex = component.get('v.focusIndex'); - var options = component.find('lookupMenu').getElement().getElementsByTagName('li'); - - if (focusIndex === null || focusIndex === 0) { - focusIndex = options.length - 1; - } else { - --focusIndex; - } - - component.set('v.focusIndex', focusIndex); - } - }, - moveRecordFocusDown: function(component, event, helper) { - var openMenu = component.get('v.openMenu'); - - if (openMenu) { - var focusIndex = component.get('v.focusIndex'); - var options = component.find('lookupMenu').getElement().getElementsByTagName('li'); - - if (focusIndex === null || focusIndex === options.length - 1) { - focusIndex = 0; - } else { - ++focusIndex; - } - - component.set('v.focusIndex', focusIndex); - } - } + checkIfInitialized: function(component, event, helper) { + var initCallsRunning = component.get('v.initCallsRunning'); + + if (--initCallsRunning < 0) { + initCallsRunning = 0; + } + + component.set('v.initCallsRunning', initCallsRunning); + }, + closeMenu: function(component, event, helper) { + component.set('v.focusIndex', null); + component.set('v.openMenu', false); + }, + getParams: function(component, event, helper) { + var filter = component.get('v.filter'); + var limit = component.get('v.limit'); + var object = component.get('v.object'); + var order = component.get('v.order'); + var searchField = component.get('v.searchField'); + var searchFields = component.get('v.searchFields'); + var subtitleField = component.get('v.subtitleField'); + + return { + filter: filter, + limit: limit, + object: object, + order: order, + searchField: searchField, + searchFields: searchFields, + subtitleField: subtitleField + }; + }, + getRecentRecords: function(component, event, helper) { + var returnedRecords = []; + + var getRecordsAction = component.get('c.getRecentRecords'); + + getRecordsAction.setParams({ + jsonString: JSON.stringify(helper.getParams(component, event, helper)) + }); + + getRecordsAction.setCallback(this, function(res) { + if (res.getState() === 'SUCCESS') { + var returnValue = JSON.parse(res.getReturnValue()); + + if (returnValue.isSuccess) { + returnValue.results.data.forEach(function(record) { + returnedRecords.push({ + label: record.label, + sublabel: record.sublabel, + value: record.value + }); + }); + } + } + component.set('v.recentRecords', returnedRecords); + + helper.checkIfInitialized(component, event, helper); + }); + + $A.enqueueAction(getRecordsAction); + }, + getRecordByValue: function(component, event, helper) { + var value = component.get('v.value'); + + if (!value) { + component.set('v.valueLabel', null); + component.set('v.valueSublabel', null); + helper.checkIfInitialized(component, event, helper); + + return; + } + + var getRecordsAction = component.get('c.getRecords'); + var params = helper.getParams(component, event, helper); + + if ($A.util.isEmpty(params.filter)) { + params.filter = 'Id = \'' + value + '\''; + } else { + params.filter = 'Id = \'' + value + '\' AND (' + params.filter + ')'; + } + + getRecordsAction.setParams({ + jsonString: JSON.stringify(params) + }); + + getRecordsAction.setCallback(this, function(res) { + if (res.getState() === 'SUCCESS') { + var returnValue = JSON.parse(res.getReturnValue()); + + if (returnValue.isSuccess) { + returnValue.results.data.forEach(function(record) { + component.set('v.valueLabel', record.label); + component.set('v.valueSublabel', record.sublabel); + }); + } + } + + helper.checkIfInitialized(component, event, helper); + }); + + $A.enqueueAction(getRecordsAction); + }, + getRecordLabel: function(component, event, helper) { + var getRecordLabelAction = component.get('c.getRecordLabel'); + + getRecordLabelAction.setParams({ + jsonString: JSON.stringify({ + object: component.get('v.object') + }) + }); + + getRecordLabelAction.setCallback(this, function(res) { + if (res.getState() === 'SUCCESS') { + var returnValue = JSON.parse(res.getReturnValue()); + + if (returnValue.isSuccess) { + component.set('v.objectLabel', returnValue.results.objectLabel); + } + } + + helper.checkIfInitialized(component, event, helper); + }); + + $A.enqueueAction(getRecordLabelAction); + }, + getRecordsBySearchTerm: function(component, event, helper) { + var searchTerm = component.find('lookupInput').getElement().value; + + var lastSearchTerm = component.get('v.lastSearchTerm'); + var searchTimeout = component.get('v.searchTimeout'); + var showRecentRecords = component.get('v.showRecentRecords'); + + clearTimeout(searchTimeout); + + if ($A.util.isEmpty(searchTerm)) { + if (showRecentRecords) { + helper.setRecords(component, event, helper, component.get('v.recentRecords')); + } else { + helper.setRecords(component, event, helper, []); + } + + return; + } else if (searchTerm === lastSearchTerm) { + component.set('v.searching', false); + helper.openMenu(component, event, helper); + + return; + } + + component.set('v.openMenu', true); + component.set('v.searching', true); + + component.set('v.searchTimeout', setTimeout($A.getCallback(function() { + if (!component.isValid()) { + return; + } + + var getRecordsAction = component.get('c.getRecords'); + var params = helper.getParams(component, event, helper); + + params.searchTerm = component.find('lookupInput').getElement().value; + + getRecordsAction.setParams({ + jsonString: JSON.stringify(params) + }); + + getRecordsAction.setCallback(this, function(res) { + if (res.getState() === 'SUCCESS') { + var returnValue = JSON.parse(res.getReturnValue()); + + if (returnValue.isSuccess && returnValue.results.searchTerm === component.find('lookupInput').getElement().value) { + var returnedRecords = []; + + returnValue.results.data.forEach(function(record) { + returnedRecords.push({ + label: record.label, + sublabel: record.sublabel, + value: record.value + }); + }); + + helper.setRecords(component, event, helper, returnedRecords); + } + } else { + helper.setRecords(component, event, helper, []); + } + }); + + $A.enqueueAction(getRecordsAction); + }), 200)); + }, + setRecords: function(component, event, helper, returnedRecords) { + component.set('v.focusIndex', null); + component.set('v.lastSearchTerm', component.find('lookupInput').getElement().value); + component.set('v.records', returnedRecords); + component.set('v.searching', false); + + helper.openMenu(component, event, helper); + }, + openMenu: function(component, event, helper) { + var showRecentRecords = component.get('v.showRecentRecords') && !$A.util.isEmpty(component.get('v.recentRecords')); + component.set('v.openMenu', !component.get('v.disabled') && (!$A.util.isEmpty(component.get('v.lastSearchTerm')) || showRecentRecords)); + }, + closeMobileLookup: function(component, event, helper) { + $A.util.removeClass(component.find('lookup'), 'sl-lookup--open'); + component.find('lookupInput').getElement().value = '' + }, + updateValueByFocusIndex: function(component, event, helper) { + var focusIndex = component.get('v.focusIndex'); + + if (focusIndex == null) { + focusIndex = 0; + } + + var records = component.get('v.records'); + + if (focusIndex < records.length) { + component.set('v.value', records[focusIndex].value); + component.set('v.valueLabel', records[focusIndex].label); + component.set('v.valueSublabel', records[focusIndex].sublabel); + component.find('lookupInput').getElement().value = ''; + + helper.closeMenu(component, event, helper); + } else if (focusIndex === records.length) { + helper.addNewRecord(component, event, helper); + } + + helper.closeMobileLookup(component, event, helper); + }, + addNewRecord: function(component, event, helper) { + if (!component.get('v.allowNewRecords')) { + return; + } + + var addRecordEvent; + var overrideNewEvent = component.get('v.overrideNewEvent'); + + if (overrideNewEvent) { + addRecordEvent = component.getEvent('strike_evt_addNewRecord'); + } else { + addRecordEvent = $A.get('e.force:createRecord'); + + addRecordEvent.setParams({ + entityApiName: component.get('v.object') + }); + } + addRecordEvent.fire(); + + helper.closeMenu(component, event, helper); + }, + moveRecordFocusUp: function(component, event, helper) { + var openMenu = component.get('v.openMenu'); + + if (openMenu) { + var focusIndex = component.get('v.focusIndex'); + var options = component.find('lookupMenu').getElement().getElementsByTagName('li'); + + if (focusIndex === null || focusIndex === 0) { + focusIndex = options.length - 1; + } else { + --focusIndex; + } + + component.set('v.focusIndex', focusIndex); + } + }, + moveRecordFocusDown: function(component, event, helper) { + var openMenu = component.get('v.openMenu'); + + if (openMenu) { + var focusIndex = component.get('v.focusIndex'); + var options = component.find('lookupMenu').getElement().getElementsByTagName('li'); + + if (focusIndex === null || focusIndex === options.length - 1) { + focusIndex = 0; + } else { + ++focusIndex; + } + + component.set('v.focusIndex', focusIndex); + } + } }) /*Copyright 2017 Appiphony, LLC -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following -disclaimer in the documentation and/or other materials provided with the distribution. -3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/ \ No newline at end of file + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following + disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ \ No newline at end of file diff --git a/classes/strike_lookupController.cls b/classes/strike_lookupController.cls index 60dbc3d..23539c0 100644 --- a/classes/strike_lookupController.cls +++ b/classes/strike_lookupController.cls @@ -1,247 +1,279 @@ /* -------------------------------------------------- -Strike by Appiphony + Strike by Appiphony -Version: 0.10.0 -Website: http://www.lightningstrike.io -GitHub: https://github.com/appiphony/Strike-Components -License: BSD 3-Clause License + Version: 0.10.0 + Website: http://www.lightningstrike.io + GitHub: https://github.com/appiphony/Strike-Components + License: BSD 3-Clause License -------------------------------------------------- */ public with sharing class strike_lookupController { - @AuraEnabled - public static String getRecentRecords(String jsonString) { - strike_responseData responseData = new strike_responseData(); - - try { - Map jsonMap = (Map)JSON.deserializeUntyped(jsonString); - Map recentlyViewedMap = new Map([SELECT Id - FROM RecentlyViewed - WHERE Type = :((String)jsonMap.get('object'))]); - List idList = new List(recentlyViewedMap.keySet()); - - if (idList.size() > 0) { - String filter = 'Id IN (\'' + String.join(idList, '\',\'') + '\')'; - - if (strike_lookupController.fieldNotEmpty(jsonMap, 'filter')) { - filter += ' AND (' + jsonMap.get('filter') + ')'; - } - - jsonMap.put('filter', filter); - - responseData.results = strike_lookupController.getData(jsonMap); - } else { - responseData.results = new Map{ - 'data' => new List(), - 'searchTerm' => '' - }; - } - } catch (Exception e) { - responseData.addError(e.getMessage()); - } - - return responseData.getJsonString(); - } - - @AuraEnabled - public static String getRecordLabel(String jsonString) { - strike_responseData responseData = new strike_responseData(); - - try { - Map jsonMap = (Map)JSON.deserializeUntyped(jsonString); - - String obj = (String)jsonMap.get('object'); - String objectLabel = Schema.describeSObjects(new List{obj})[0].getLabel(); - - responseData.results.put('objectLabel', objectLabel); - } catch (Exception e) { - responseData.addError(e.getMessage()); - } - - return responseData.getJsonString(); - } - - @AuraEnabled - public static String getRecords(String jsonString) { - strike_responseData responseData = new strike_responseData(); - - - try { - Map jsonMap = (Map)JSON.deserializeUntyped(jsonString); - responseData.results = strike_lookupController.getData(jsonMap); - } catch (Exception e) { - responseData.addError(e.getMessage()); - } - - return responseData.getJsonString(); - } - - private static Map getData(Map jsonMap) { - List> data = new List>(); - - String objType = String.escapeSingleQuotes((String)jsonMap.get('object')); - String query = strike_lookupController.getQuery(jsonMap); - String searchField = String.escapeSingleQuotes((String)jsonMap.get('searchField')); - String searchTerm = ''; - String subtitleField; - - if (strike_lookupController.fieldNotEmpty(jsonMap, 'subtitleField')) { - subtitleField = String.escapeSingleQuotes((String)jsonMap.get('subtitleField')); - } - - if (strike_lookupController.fieldNotEmpty(jsonMap, 'searchTerm')) { - searchTerm = String.escapeSingleQuotes((String)jsonMap.get('searchTerm')); - } - - if (String.isEmpty(subtitleField)) { - for (sObject obj : Database.query(query)) { - data.add(new Map{ - 'label' => strike_lookupController.getValue(obj, objType, searchField), - 'value' => obj.get('Id') - }); - } - } else { - for (sObject obj : Database.query(query)) { - data.add(new Map{ - 'label' => strike_lookupController.getValue(obj, objType, searchField), - 'sublabel' => strike_lookupController.getValue(obj, objType, subtitleField), - 'value' => obj.get('Id') - }); - } - } - - return new Map{ - 'data' => data, - 'searchTerm' => searchTerm - }; - } - - private static String getQuery(Map jsonMap) { - Set queryFields = new Set{'Id'}; - List filters = new List(); - List orders = new List(); - - String query; - String obj = String.escapeSingleQuotes((String)jsonMap.get('object')); - String subtitleField; - - if (strike_lookupController.fieldNotEmpty(jsonMap, 'subtitleField')) { - subtitleField = String.escapeSingleQuotes((String)jsonMap.get('subtitleField')); - queryFields.add(subtitleField); - } - - if (strike_lookupController.fieldNotEmpty(jsonMap, 'searchField')) { - queryFields.add(String.escapeSingleQuotes((String)jsonMap.get('searchField'))); - - if (strike_lookupController.fieldNotEmpty(jsonMap, 'searchTerm')) { - String searchField = String.escapeSingleQuotes((String)jsonMap.get('searchField')); - String searchTerm = String.escapeSingleQuotes((String)jsonMap.get('searchTerm')); - - filters.add(searchField + ' LIKE \'%' + searchTerm + '%\''); - } - } - - if (strike_lookupController.fieldNotEmpty(jsonMap, 'filter')) { - filters.add('(' + (String)jsonMap.get('filter') + ')'); - } - - if (strike_lookupController.fieldNotEmpty(jsonMap, 'order')) { - orders.add(String.escapeSingleQuotes((String)jsonMap.get('order'))); - } - - query = 'SELECT ' + String.join(new List(queryFields), ', '); - query += ' FROM ' + obj; - - if (filters.size() > 0) { - query += ' WHERE ' + String.join(filters, ' AND '); - } - - if (orders.size() > 0) { - query += ' ORDER BY ' + String.join(orders, ', '); - } - - if (strike_lookupController.fieldNotEmpty(jsonMap, 'limit')) { - query += ' LIMIT ' + String.escapeSingleQuotes((String)jsonMap.get('limit')); - } - - return query; - } - - private static Boolean fieldNotEmpty(Map jsonMap, String field) { - return jsonMap.containsKey(field) && !String.isEmpty((String)jsonMap.get(field)); - } - - private static String getValue(SObject obj, String objectType, String field) { - List fieldPath = field.split('[.]'); - Object label = strike_utilities.convertObjectToMap(obj); - Map fieldMap = Schema.getGlobalDescribe().get(objectType).getDescribe().fields.getMap(); - - for (String fieldName : fieldPath) { - fieldName = fieldName.replaceAll('__r$', '__c'); - - label = ((Map)label).get(fieldName); - - if (label == null) { - return ''; - } - - if (fieldMap.containsKey(fieldName + 'Id')) { - fieldName = fieldName + 'Id'; - } - - Schema.DescribeFieldResult fieldDescribe = fieldMap.get(fieldName).getDescribe(); - String fieldType = String.valueOf(fieldDescribe.getType()).toUpperCase(); - - if (fieldType == 'REFERENCE') { - fieldMap = Schema.getGlobalDescribe().get(String.valueOf(fieldDescribe.getReferenceTo().get(0))).getDescribe().fields.getMap(); - } else if (fieldType == 'ADDRESS') { - List addressComponents = new List(); - Map addr = (Map)label; - - if (addr.containsKey('street') && addr.get('street') != null) { - addressComponents.add((String)addr.get('street')); - } - - if (addr.containsKey('city') && addr.get('city') != null) { - addressComponents.add((String)addr.get('city')); - } - - if (addr.containsKey('state') && addr.get('state') != null) { - addressComponents.add((String)addr.get('state')); - } - - if (addr.containsKey('country') && addr.get('country') != null) { - addressComponents.add((String)addr.get('country')); - } - - if (addr.containsKey('postalCode') &&addr.get('postalCode') != null) { - addressComponents.add((String)addr.get('postalCode')); - } - - // change later for user formatting? - label = String.join(addressComponents, ', '); - } - } - - return String.valueOf(label); - } + @AuraEnabled + public static String getRecentRecords(String jsonString) { + strike_responseData responseData = new strike_responseData(); + + try { + Map jsonMap = (Map)JSON.deserializeUntyped(jsonString); + Map recentlyViewedMap = new Map( + [SELECT Id FROM RecentlyViewed WHERE Type = :((String)jsonMap.get('object'))]); + List idList = new List(recentlyViewedMap.keySet()); + + if (idList.size() > 0) { + String filter = 'Id IN (\'' + String.join(idList, '\',\'') + '\')'; + + if (strike_lookupController.fieldNotEmpty(jsonMap, 'filter')) { + filter += ' AND (' + jsonMap.get('filter') + ')'; + } + + jsonMap.put('filter', filter); + + responseData.results = strike_lookupController.getData(jsonMap); + } else { + responseData.results = new Map{ + 'data' => new List(), + 'searchTerm' => '' + }; + } + } catch (Exception e) { + responseData.addError(e.getMessage()); + } + + return responseData.getJsonString(); + } + + @AuraEnabled + public static String getRecordLabel(String jsonString) { + strike_responseData responseData = new strike_responseData(); + + try { + Map jsonMap = (Map)JSON.deserializeUntyped(jsonString); + + String obj = (String)jsonMap.get('object'); + String objectLabel = Schema.describeSObjects(new List{obj})[0].getLabel(); + + responseData.results.put('objectLabel', objectLabel); + } catch (Exception e) { + responseData.addError(e.getMessage()); + } + + return responseData.getJsonString(); + } + + @AuraEnabled + public static String getRecords(String jsonString) { + strike_responseData responseData = new strike_responseData(); + + try { + Map jsonMap = (Map)JSON.deserializeUntyped(jsonString); + responseData.results = strike_lookupController.getData(jsonMap); + } catch (Exception e) { + responseData.addError(e.getMessage()); + } + + return responseData.getJsonString(); + } + + private static Map getData(Map jsonMap) { + List> data = new List>(); + + String objType = String.escapeSingleQuotes((String)jsonMap.get('object')); + String query = strike_lookupController.getQuery(jsonMap); + String searchField = String.escapeSingleQuotes((String)jsonMap.get('searchField')); + String searchTerm = ''; + String subtitleField; + + if (strike_lookupController.fieldNotEmpty(jsonMap, 'subtitleField')) { + subtitleField = String.escapeSingleQuotes((String)jsonMap.get('subtitleField')); + } + + if (strike_lookupController.fieldNotEmpty(jsonMap, 'searchTerm')) { + searchTerm = String.escapeSingleQuotes((String)jsonMap.get('searchTerm')); + } + + if (String.isEmpty(subtitleField)) { + for (sObject obj : Database.query(query)) { + data.add(new Map{ + 'label' => strike_lookupController.getValue(obj, objType, searchField), + 'value' => obj.get('Id') + }); + } + } else { + for (sObject obj : Database.query(query)) { + data.add(new Map{ + 'label' => strike_lookupController.getValue(obj, objType, searchField), + 'sublabel' => strike_lookupController.getValue(obj, objType, subtitleField), + 'value' => obj.get('Id') + }); + } + } + + return new Map{ + 'data' => data, + 'searchTerm' => searchTerm + }; + } + + private static String getQuery(Map jsonMap) { + Set queryFields = new Set{'Id'}; + List filters = new List(); + List filtersORCondition = new List(); + List orders = new List(); + + String query; + String obj = String.escapeSingleQuotes((String)jsonMap.get('object')); + String subtitleField; + + if (strike_lookupController.fieldNotEmpty(jsonMap, 'subtitleField')) { + subtitleField = String.escapeSingleQuotes((String)jsonMap.get('subtitleField')); + queryFields.add(subtitleField); + } + + if (strike_lookupController.fieldNotEmpty(jsonMap, 'searchField')) { + queryFields.add(String.escapeSingleQuotes((String)jsonMap.get('searchField'))); + + if (strike_lookupController.fieldNotEmpty(jsonMap, 'searchTerm')) { + String searchField = String.escapeSingleQuotes((String)jsonMap.get('searchField')); + String searchTerm = String.escapeSingleQuotes((String)jsonMap.get('searchTerm')); + + if('Id'.equalsIgnoreCase(searchField)){ + if(searchTerm instanceOf Id){ + filtersORCondition.add(searchField + ' = \'' + searchTerm + '\''); + } + }else{ + filters.add(searchField + ' LIKE \'%' + searchTerm + '%\''); + } + } + } + + if (strike_lookupController.fieldNotEmpty(jsonMap, 'searchFields')) { + Set fieldstoAdd = new Set( String.escapeSingleQuotes((String)jsonMap.get('searchFields')).split(',') ); + queryFields.addAll(fieldstoAdd); + + if (strike_lookupController.fieldNotEmpty(jsonMap, 'searchTerm')) { + String searchFields = String.escapeSingleQuotes((String)jsonMap.get('searchFields')); + String searchTerm = String.escapeSingleQuotes((String)jsonMap.get('searchTerm')); + + List searchConditions = new List(); + for(String searchField : searchFields.split(',')){ + if('Id'.equalsIgnoreCase(searchField)){ + searchConditions.add(searchField + ' = \'' + searchTerm + '\''); + }else{ + searchConditions.add(searchField + ' LIKE \'%' + searchTerm + '%\''); + } + } + String searchCondition = '(' + String.join(searchConditions, ' OR ') + ')'; + filters.add(searchCondition); + } + } + + if (strike_lookupController.fieldNotEmpty(jsonMap, 'filter')) { + filters.add('(' + (String)jsonMap.get('filter') + ')'); + } + + if (strike_lookupController.fieldNotEmpty(jsonMap, 'order')) { + orders.add(String.escapeSingleQuotes((String)jsonMap.get('order'))); + } + + query = 'SELECT ' + String.join(new List(queryFields), ', '); + query += ' FROM ' + obj; + + if (filters.size() > 0) { + query += ' WHERE ' + String.join(filters, ' AND '); + } + + if(filtersORCondition.size() > 0){ + query += ' OR (' +String.join(filtersORCondition, ' OR ') + ')'; + } + + if (orders.size() > 0) { + query += ' ORDER BY ' + String.join(orders, ', '); + } + + if (strike_lookupController.fieldNotEmpty(jsonMap, 'limit')) { + query += ' LIMIT ' + String.escapeSingleQuotes((String)jsonMap.get('limit')); + } + System.debug(LoggingLevel.FINEST, String.join(filters, ' AND ')); + System.debug(LoggingLevel.FINEST, query); + return query; + } + + private static Boolean fieldNotEmpty(Map jsonMap, String field) { + return jsonMap.containsKey(field) && !String.isEmpty((String)jsonMap.get(field)); + } + + private static String getValue(SObject obj, String objectType, String field) { + List fieldPath = field.split('[.]'); + Object label = strike_utilities.convertObjectToMap(obj); + Map fieldMap = Schema.getGlobalDescribe().get(objectType).getDescribe().fields.getMap(); + + for (String fieldName : fieldPath) { + fieldName = fieldName.replaceAll('__r$', '__c'); + + label = ((Map)label).get(fieldName); + + if (label == null) { + return ''; + } + + if (fieldMap.containsKey(fieldName + 'Id')) { + fieldName = fieldName + 'Id'; + } + + Schema.DescribeFieldResult fieldDescribe = fieldMap.get(fieldName).getDescribe(); + String fieldType = String.valueOf(fieldDescribe.getType()).toUpperCase(); + + if (fieldType == 'REFERENCE') { + fieldMap = Schema.getGlobalDescribe().get(String.valueOf(fieldDescribe.getReferenceTo().get(0))).getDescribe().fields.getMap(); + } else if (fieldType == 'ADDRESS') { + List addressComponents = new List(); + Map addr = (Map)label; + + if (addr.containsKey('street') && addr.get('street') != null) { + addressComponents.add((String)addr.get('street')); + } + + if (addr.containsKey('city') && addr.get('city') != null) { + addressComponents.add((String)addr.get('city')); + } + + if (addr.containsKey('state') && addr.get('state') != null) { + addressComponents.add((String)addr.get('state')); + } + + if (addr.containsKey('country') && addr.get('country') != null) { + addressComponents.add((String)addr.get('country')); + } + + if (addr.containsKey('postalCode') &&addr.get('postalCode') != null) { + addressComponents.add((String)addr.get('postalCode')); + } + + // change later for user formatting? + label = String.join(addressComponents, ', '); + } + } + + return String.valueOf(label); + } } /* -------------------------------------------------- -Copyright 2017 Appiphony, LLC - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following -disclaimer in the documentation and/or other materials provided with the distribution. -3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------- */ \ No newline at end of file + Copyright 2017 Appiphony, LLC + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following + disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------- +*/ \ No newline at end of file