UNPKG

@stratusjs/idx

Version:

AngularJS idx/property Service and Components bundle to be used as an add on to StratusJS

570 lines (568 loc) 33.9 kB
System.register(["./search.component.less", "./search.compact.component.less", "./search.classic.component.less", "lodash", "@stratusjs/runtime/stratus", "angular", "angular-material", "@stratusjs/core/misc", "@stratusjs/core/environment", "@stratusjs/angularjs-extras"], function (exports_1, context_1) { "use strict"; var lodash_1, stratus_1, angular_1, misc_1, environment_1, min, packageName, moduleName, componentName, localDir, localDistStyle; var __moduleName = context_1 && context_1.id; return { setters: [ function (_1) { }, function (_2) { }, function (_3) { }, function (lodash_1_1) { lodash_1 = lodash_1_1; }, function (stratus_1_1) { stratus_1 = stratus_1_1; }, function (angular_1_1) { angular_1 = angular_1_1; }, function (_4) { }, function (misc_1_1) { misc_1 = misc_1_1; }, function (environment_1_1) { environment_1 = environment_1_1; }, function (_5) { } ], execute: function () { min = !environment_1.cookie('env') ? '.min' : ''; packageName = 'idx'; moduleName = 'property'; componentName = 'search'; localDir = `${stratus_1.Stratus.BaseUrl}${stratus_1.Stratus.DeploymentPath}@stratusjs/${packageName}/src/${moduleName}/`; localDistStyle = `${stratus_1.Stratus.BaseUrl}${stratus_1.Stratus.DeploymentPath}@stratusjs/${packageName}/dist/${packageName}.bundle.min.css`; stratus_1.Stratus.Components.IdxPropertySearch = { bindings: { elementId: '@', initNow: '=', tokenUrl: '@', tokenOnLoad: '@', listId: '@', listLinkUrl: '@', listLinkTarget: '@', searchType: '@', advancedSearchUrl: '@', advancedSearchLinkName: '@', template: '@', options: '@', optionsAgentGroups: '@', optionsOfficeGroups: '@', displayFilterFullHeight: '@', variableSync: '@', widgetName: '@' }, controller($attrs, $element, $q, $mdConstant, $mdDialog, $mdPanel, $sce, $scope, $timeout, $window, Idx) { $scope.uid = misc_1.safeUniqueId(packageName, moduleName, componentName); $scope.elementId = $attrs.elementId || $scope.uid; $scope._ = lodash_1.default; stratus_1.Stratus.Instances[$scope.elementId] = $scope; $scope.localDir = localDir; $scope.initialized = false; if ($attrs.tokenUrl) { Idx.setTokenURL($attrs.tokenUrl); } stratus_1.Stratus.Internals.CssLoader(localDistStyle).then(); let defaultQuery; let lastQuery; let mlsVariables; $scope.openPrice = false; $scope.advancedFiltersStatus = false; $scope.advancedSearchUrl = ''; $scope.advancedSearchLinkName = 'Advanced Search'; $scope.presetLocationText = ''; $scope.$mdConstant = $mdConstant; const init = async () => { $scope.widgetName = $attrs.widgetName || ''; $scope.listId = $attrs.listId || null; $scope.listInitialized = false; $scope.listLinkUrl = $attrs.listLinkUrl || $attrs.advancedSearchUrl || '/property/list'; $scope.listLinkTarget = $attrs.listLinkTarget || '_self'; $scope.searchType = $attrs.searchType || 'advanced'; $scope.advancedSearchUrl = $attrs.advancedSearchUrl || $scope.advancedSearchUrl; $scope.advancedSearchLinkName = $attrs.advancedSearchLinkName || $scope.advancedSearchLinkName; $scope.options = $attrs.options && misc_1.isJSON($attrs.options) ? JSON.parse($attrs.options) : {}; $scope.displayFilterFullHeight = $attrs.displayFilterFullHeight && misc_1.isJSON($attrs.displayFilterFullHeight) ? JSON.parse($attrs.displayFilterFullHeight) : false; $scope.filterMenu = null; $scope.options.forRent ||= false; $scope.options.agentGroups ??= []; $scope.options.officeGroups = ($scope.options.officeGroups && lodash_1.isString($scope.options.officeGroups) && misc_1.isJSON($scope.options.officeGroups) ? JSON.parse($scope.options.officeGroups) : ($attrs.optionsOfficeGroups && misc_1.isJSON($attrs.optionsOfficeGroups) ? JSON.parse($attrs.optionsOfficeGroups) : $scope.options.officeGroups)) || []; $scope.options.query ??= {}; $scope.options.query.where ??= {}; $scope.options.query.service ??= []; $scope.setWhere($scope.options.query.where); defaultQuery = JSON.parse(JSON.stringify(lodash_1.cloneDeep($scope.options.query.where))); if ($scope.options.query.order) { defaultQuery.Order = $scope.options.query.order; } $timeout(async () => { await $scope.variableSync(); }, 1000); $scope.options.selection ??= {}; $scope.options.selection.Bedrooms ??= [ { name: '1+', value: 1 }, { name: '2+', value: 2 }, { name: '3+', value: 3 }, { name: '4+', value: 4 }, { name: '5+', value: 5 } ]; $scope.options.selection.Bathrooms ??= [ { name: '1+', value: 1 }, { name: '2+', value: 2 }, { name: '3+', value: 3 }, { name: '4+', value: 4 }, { name: '5+', value: 5 } ]; $scope.options.selection.order ??= [ { name: 'Highest Price', value: '-BestPrice' }, { name: 'Lowest Price', value: 'BestPrice' }, { name: 'Recently Updated', value: '-ModificationTimestamp' }, { name: 'Recently Sold', value: '-CloseDate' }, { name: 'Status + Price', value: ['Status', '-BestPrice'] }, { name: 'Status + Recent', value: ['Status', '-ModificationTimestamp'] } ]; $scope.options.selection.Status ??= {}; $scope.options.selection.Status.default ??= { Sale: ['Active', 'Contract'], Lease: ['Active'] }; $scope.options.selection.ListingType ??= {}; $scope.options.selection.ListingType.group ??= { Residential: true, Commercial: false }; $scope.options.selection.ListingType.list ??= { Residential: ['House', 'Condo', 'Townhouse', 'MultiFamily', 'Manufactured', 'Land', 'LeaseHouse', 'LeaseCondo', 'LeaseTownhouse', 'LeaseOther'], Commercial: ['Commercial', 'CommercialBusinessOp', 'CommercialResidential', 'CommercialLand', 'LeaseCommercial'], Lease: ['LeaseHouse', 'LeaseCondo', 'LeaseTownhouse', 'LeaseOther', 'LeaseCommercial'] }; $scope.options.selection.ListingType.default ??= { Sale: { Residential: ['House', 'Condo', 'Townhouse'], Commercial: ['Commercial', 'CommercialBusinessOp'] }, Lease: { Residential: ['LeaseHouse', 'LeaseCondo', 'LeaseTownhouse'], Commercial: ['LeaseCommercial'] } }; $scope.options.selection.ListingType.All ??= [ { name: 'House', value: 'House', group: 'Residential', lease: false }, { name: 'Condo', value: 'Condo', group: 'Residential', lease: false }, { name: 'Townhouse', value: 'Townhouse', group: 'Residential', lease: false }, { name: 'Multi-Family', value: 'MultiFamily', group: 'Residential', lease: false }, { name: 'Manufactured', value: 'Manufactured', group: 'Residential', lease: false }, { name: 'Land', value: 'Land', group: 'Residential', lease: false }, { name: 'Other', value: 'Other', group: 'Residential', lease: false }, { name: 'Commercial', value: 'Commercial', group: 'Commercial', lease: false }, { name: 'Commercial Business Op', value: 'CommercialBusinessOp', group: 'Commercial', lease: false }, { name: 'Commercial Residential', value: 'CommercialResidential', group: 'Commercial', lease: false }, { name: 'Commercial Land', value: 'CommercialLand', group: 'Commercial', lease: false }, { name: 'House', value: 'LeaseHouse', group: 'Residential', lease: true }, { name: 'Condo', value: 'LeaseCondo', group: 'Residential', lease: true }, { name: 'Townhouse', value: 'LeaseTownhouse', group: 'Residential', lease: true }, { name: 'Other', value: 'LeaseOther', group: 'Residential', lease: true }, { name: 'Commercial', value: 'LeaseCommercial', group: 'Commercial', lease: true } ]; $scope.setWhereDefaults(); Idx.registerSearchInstance($scope.elementId, moduleName, $scope, $scope.listId); if ($scope.listId) { Idx.on($scope.listId, 'init', $scope.refreshSearchWidgetOptions); Idx.on($scope.listId, 'searching', $scope.refreshSearchWidgetOptions); } if ($attrs.tokenOnLoad) { try { await Idx.tokenKeepAuth(); $scope.getMLSVariables(true); } catch (e) { console.error('Search is unable to load in token data', e); } } $scope.$applyAsync(() => { $scope.initialized = true; }); Idx.emit('init', $scope); }; this.$onInit = () => { $scope.Idx = Idx; let initNow = true; if (Object.prototype.hasOwnProperty.call($attrs.$attr, 'initNow')) { initNow = misc_1.isJSON($attrs.initNow) ? JSON.parse($attrs.initNow) : false; } if (initNow) { init().then(); return; } const stopWatchingInitNow = $scope.$watch('$ctrl.initNow', (initNowCtrl) => { if (initNowCtrl !== true) { return; } if (!$scope.initialized) { init().then(); } stopWatchingInitNow(); }); }; $scope.$watch('options.query.where.ListingType', () => { if ($scope.options?.query?.where && $scope.options?.selection?.ListingType?.list) { if (!$scope.options?.query?.where?.ListingType) { $scope.options.query.where.ListingType = []; } if (!lodash_1.isArray($scope.options.query.where.ListingType)) { $scope.options.query.where.ListingType = [$scope.options.query.where.ListingType]; } $scope.options.selection.ListingType.group.Residential = $scope.isIntersecting($scope.options.selection.ListingType.list.Residential, $scope.options.query.where.ListingType); $scope.options.selection.ListingType.group.Commercial = $scope.isIntersecting($scope.options.selection.ListingType.list.Commercial, $scope.options.query.where.ListingType); $scope.options.forRent = $scope.isIntersecting($scope.options.selection.ListingType.list.Lease, $scope.options.query.where.ListingType); } }); $scope.resetLocationQuery = () => { $scope.options.query.where.Location = ''; $scope.options.query.where.eLocation = ''; $scope.options.query.where.UnparsedAddress = []; $scope.options.query.where.StreetAddress = []; $scope.options.query.where.eStreetAddress = []; $scope.options.query.where.City = []; $scope.options.query.where.eCity = []; $scope.options.query.where.CountyOrParish = []; $scope.options.query.where.eCountyOrParish = []; $scope.options.query.where.MLSAreaMajor = []; $scope.options.query.where.eMLSAreaMajor = []; $scope.options.query.where.Neighborhood = []; $scope.options.query.where.eNeighborhood = []; $scope.options.query.where.PostalCode = []; $scope.options.query.where.ListingId = []; $scope.options.query.where.AgentLicense = []; $scope.options.query.where.OfficeNumber = []; $scope.options.officeGroups = []; $scope.parsePresetLocationText(); }; $scope.getPresetLocations = () => { const currentWhere = $scope.options.query.where; return lodash_1.compact(lodash_1.union(currentWhere.UnparsedAddress, currentWhere.StreetAddress, currentWhere.eStreetAddress, currentWhere.City, currentWhere.eCity, currentWhere.CountyOrParish, currentWhere.eCountyOrParish, currentWhere.MLSAreaMajor, currentWhere.eMLSAreaMajor, currentWhere.Neighborhood, currentWhere.eNeighborhood, currentWhere.PostalCode)); }; $scope.getOtherPresetFilterCount = () => { const currentWhere = $scope.options.query.where; let filterCounts = lodash_1.compact(lodash_1.union(currentWhere.OfficeNumber, currentWhere.AgentLicense, currentWhere.ListingId)).length; if (currentWhere.OpenHouseOnly) { filterCounts++; } return filterCounts; }; $scope.isPresetLocationSet = () => { return $scope.getPresetLocations().length > 0; }; $scope.parsePresetLocationText = () => { const locations = $scope.getPresetLocations(); $scope.presetLocationText = locations.join(', '); if (!lodash_1.isEmpty($scope.presetLocationText)) { const html = `<span>${locations.join('</span><span>')}</span>`; $scope.presetLocationHTML = $sce.trustAsHtml(html); } else { $scope.presetLocationHTML = null; } $scope.presetLocationsCountText = null; $scope.presetLocationsRemainingCountText = null; if (locations.length > 0) { $scope.presetLocationsCountText = `+${locations.length}`; if (locations.length > 2) { $scope.presetLocationsRemainingCountText = `+${locations.length - 2}`; } } $scope.presetOtherFiltersCountText = null; const filterCounts = $scope.getOtherPresetFilterCount(); if (filterCounts > 0) { $scope.presetOtherFiltersCountText = `+${filterCounts} Filter${filterCounts > 1 ? 's' : ''}`; } }; $scope.focusElement = (selector) => { if (!lodash_1.isEmpty(selector)) { $timeout(() => { const elementThis = $element[0]; const elementSelected = elementThis.querySelector(selector); if (!elementSelected) { console.warn('unable to find focusable element of', selector); return; } elementSelected.focus(); }, 100); } }; $scope.variableSync = async () => { $scope.variableSyncing = $attrs.variableSync && misc_1.isJSON($attrs.variableSync) ? JSON.parse($attrs.variableSync) : {}; const promises = []; Object.keys($scope.variableSyncing).forEach((elementId) => { promises.push($q(async (resolve) => { const varElement = Idx.getInput(elementId); if (varElement) { const scopeVarPath = $scope.variableSyncing[elementId]; await Idx.updateScopeValuePath($scope, scopeVarPath, varElement.val()); $scope.setWhere($scope.options.query.where); $scope.$watch(scopeVarPath, (value) => { if (lodash_1.isString(value) || lodash_1.isNumber(value) || lodash_1.isUndefined(value) || value == null) { if (lodash_1.isUndefined(value)) { value = null; } varElement.val(value); } else { varElement.val(JSON.stringify(value)); } varElement[0].dispatchEvent(new Event('change')); }, true); } resolve(); })); }); await $q.all(promises); }; $scope.canDisplayListingTypeButton = (listType) => { return $scope.options.forRent === listType.lease && $scope.options.selection.ListingType.group[listType.group]; }; $scope.inArray = (item, array) => lodash_1.includes(array, item); $scope.isIntersecting = (itemArray, array) => { if (!lodash_1.isArray(array) || !lodash_1.isArray(itemArray)) { console.warn('Array undefined, cannot search for', itemArray, 'in', array); return false; } return lodash_1.intersection(itemArray, array).length > 0; }; $scope.toggleArrayElement = (item, array) => { array ??= []; const arrayIndex = array.indexOf(item); if (arrayIndex >= 0) { array.splice(arrayIndex, 1); } else { array.push(item); } }; $scope.showInlinePopup = (ev, menuElement) => { if (!$scope.filterMenu) { const position = $mdPanel.newPanelPosition() .relativeTo(ev.srcElement) .addPanelPosition($mdPanel.xPosition.CENTER, $mdPanel.yPosition.BELOW); const animation = $mdPanel.newPanelAnimation(); animation.openFrom(position); animation.closeTo(position); animation.withAnimation($mdPanel.animation.FADE); const config = { animation, attachTo: angular_1.element(document.body), contentElement: menuElement, position, openFrom: ev, clickOutsideToClose: true, escapeToClose: true, focusOnOpen: false, zIndex: 2 }; $scope.filterMenu = $mdPanel.create(config); $scope.filterMenu.reposition = function reposition() { $timeout(() => { $scope.filterMenu.updatePosition(position); }, 100); }; } $scope.filterMenu.open(); }; $scope.getMLSVariables = (reset) => { if (!mlsVariables || reset) { mlsVariables = {}; Idx.getMLSVariables().forEach((service) => { mlsVariables[service.id] = service; }); } return Object.values(mlsVariables); }; $scope.setQuery = (newQuery) => { newQuery ??= {}; newQuery.where ??= {}; $scope.options.query = lodash_1.cloneDeep(newQuery); $scope.setWhere($scope.options.query.where); }; $scope.setWhere = (newWhere) => { newWhere ??= {}; $scope.options.query.where = lodash_1.extend(Idx.getDefaultWhereOptions(), newWhere); lodash_1.map(Idx.getDefaultWhereOptions(), (value, key) => { if (lodash_1.isArray(value) && Object.prototype.hasOwnProperty.call($scope.options.query.where, key) && !lodash_1.isArray($scope.options.query.where[key])) { $scope.options.query.where[key] = [$scope.options.query.where[key]]; } }); $scope.parsePresetLocationText(); }; $scope.setWhereDefaults = () => { $scope.$applyAsync(() => { if ($scope.options.query.where.ListingType.length < 1) { $scope.options.query.where.ListingType = $scope.options.selection.ListingType.default.Sale.Residential; $scope.selectDefaultListingType(); } lastQuery = lodash_1.cloneDeep($scope.options.query); $scope.parsePresetLocationText(); }); }; $scope.selectDefaultListingType = (listingGroup) => { if (!listingGroup) { listingGroup = 'Commercial'; if (!$scope.options.selection.ListingType.group.Commercial) { listingGroup = 'Residential'; } } $scope.options.query.where.ListingType = $scope.options.forRent ? $scope.options.selection.ListingType.default.Lease[listingGroup] : $scope.options.selection.ListingType.default.Sale[listingGroup]; if ($scope.filterMenu) { $scope.filterMenu.reposition(); } if ($scope.options.forRent) { $scope.options.query.where.Status = $scope.options.selection.Status.default.Lease; } else { $scope.options.query.where.Status = ($scope.options.query.where.Status && $scope.options.query.where.Status.length > 0) ? $scope.options.query.where.Status : $scope.options.selection.Status.default.Lease; } }; $scope.search = (force) => { if (!$scope.initialized) { console.warn($scope.uid, 'has not initialized and may not search yet'); return; } let listScope; if ($scope.listId) { listScope = Idx.getListInstance($scope.listId); } if (listScope) { if (!$scope.throttledSearch) { $scope.throttledSearch = lodash_1.throttle(() => { listScope.search($scope.options.query, true); }, 600, { trailing: false }); } $scope.throttledSearch(); } else { if ($scope.hasQueryChanged() || force) { lastQuery = lodash_1.cloneDeep($scope.options.query); Idx.setUrlOptions('Search', $scope.options.query.where); $window.open($scope.listLinkUrl + '#!' + Idx.getUrlOptionsPath(defaultQuery), $scope.listLinkTarget); } } }; $scope.displayOfficeGroupSelector = (searchTerm, editIndex, ev) => { if (ev) { ev.preventDefault(); } let searchOnLoad = false; const options = { query: { perPage: 100 } }; if (!lodash_1.isEmpty(searchTerm) && lodash_1.isString(searchTerm)) { options.query.where = { OfficeName: searchTerm }; searchOnLoad = true; } if (!lodash_1.isNumber(editIndex)) { editIndex = $scope.options.officeGroups.length; } const template = '<md-dialog aria-label="Property Office Group Selector" class="transparent">' + '<md-button style="text-align: center" data-ng-click="close()">Close and Accept</md-button>' + '<stratus-idx-office-search' + ' data-template="search.group-selector"' + ` data-list-id="office-group-selector-${$scope.elementId}"` + ` data-options='${JSON.stringify(options)}'` + ` data-sync-instance="${$scope.elementId}"` + ` data-sync-instance-variable="options.officeGroups"` + ` data-sync-instance-variable-index="${editIndex}"` + '></stratus-idx-office-search>' + '<stratus-idx-office-list' + ` data-element-id="office-group-selector-${$scope.elementId}"` + ' data-template="list.empty"' + ` data-search-on-load="${searchOnLoad}"` + ` data-query='${JSON.stringify(options.query)}'` + ` data-query-service="${$scope.options.query.service}"` + '></stratus-idx-office-list>' + '</md-dialog>'; $mdDialog.show({ template, parent: angular_1.element(document.body), targetEvent: ev, clickOutsideToClose: true, fullscreen: true, controllerAs: 'ctrl', controller: ($scope, $mdDialog) => { const dc = this; dc.$onInit = () => { dc.close = close; }; function close() { if ($mdDialog) { $mdDialog.hide(); } } $scope.close = close; } }) .then(() => { $scope.validateOfficeGroups(); }, () => { $scope.validateOfficeGroups(); }); }; $scope.validateOfficeGroups = (search) => { $scope.options.officeGroups = $scope.options.officeGroups.filter((selection) => { return (!lodash_1.isEmpty(selection.name) && !lodash_1.isEmpty(selection.group)); }); const officeNumbers = []; $scope.options.query.where.OfficeNumber = []; $scope.options.officeGroups.forEach((selection) => { officeNumbers.push(...selection.group); }); $scope.options.query.where.OfficeNumber = officeNumbers; if (search) { $scope.search(); } }; $scope.refreshSearchWidgetOptions = async (listScope) => { if (!listScope && $scope.listId) { listScope = Idx.getListInstance($scope.listId); } if (listScope) { $scope.setQuery(listScope.query); lastQuery = lodash_1.cloneDeep($scope.options.query); $scope.listInitialized = true; } }; $scope.on = (emitterName, callback) => Idx.on($scope.elementId, emitterName, callback); $scope.hasQueryChanged = () => !lodash_1.isEqual(lodash_1.clone(lastQuery), lodash_1.clone($scope.options.query)); $scope.remove = () => { }; }, templateUrl: ($attrs) => `${localDir}${$attrs.template || componentName}.component${min}.html` }; } }; }); //# sourceMappingURL=search.component.js.map