scripts/apps/contacts/directives/ContactsSearchPanelDirective.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import _ from 'lodash';
import {getUrlParameters} from '../constants';
import {SelectFieldSearchInput} from '../../contacts/components/Form';
import {gettext} from 'core/utils';
class LinkFunction {
scope: any;
elem: any;
orgField: any;
contacts: any;
$location: any;
constructor(contacts, $location, scope, elem) {
this.scope = scope;
this.elem = elem;
this.orgField = document.getElementById('org-field');
this.contacts = contacts;
this.$location = $location;
this.scope.searchItems = this.search.bind(this);
this.scope.clear = this.clear.bind(this);
this.setQueryString = this.setQueryString.bind(this);
this.scope.toggle = {all: true};
this.scope.keyPressed = this.keyPressed.bind(this);
this.scope.searchField = this.searchField.bind(this);
this.scope.isSearchDifferent = this.isSearchDifferent.bind(this);
this.handleOnChange = this.handleOnChange.bind(this);
this.init();
this.scope.$on('$locationChangeSuccess', () => {
if (this.scope.query !== this.$location.search().q || this.scope.isSearchDifferent()) {
this.init();
}
});
this.scope.$on('$destroy', () => {
elem.off();
ReactDOM.unmountComponentAtNode(this.orgField);
});
}
/*
* init function to setup the directive initial state and called by $locationChangeSuccess event
*/
init() {
var params = this.$location.search();
this.scope.query = params.q;
this.scope.flags = false;
let meta = {};
_.forEach(getUrlParameters(), (value, key) => {
if (_.get(params, key)) {
meta[key] = params[key];
}
});
this.scope.meta = meta;
this.scope.filteredList = {};
if (!params.organisation) {
this.scope.filteredList['organisation'] = [];
}
this.renderSearchField('organisation', true);
this.scope.selectedItem = '';
}
isSearchDifferent() {
let params = this.$location.search();
return _.some(_.keys(getUrlParameters()), (key) => _.get(this.scope.meta, key) !== _.get(params, key));
}
handleOnChange(field, value) {
this.scope.meta[field] = value;
this.renderSearchField(field, false);
}
renderSearchField(field, initValue?) {
let fieldElement;
let fieldLabel;
let querySearch = false;
switch (field) {
case 'organisation':
fieldElement = this.orgField;
fieldLabel = gettext('Organisation');
querySearch = true;
break;
}
ReactDOM.render(
<SelectFieldSearchInput
field={field}
label={fieldLabel}
onChange={this.handleOnChange}
value={_.get(this.scope.meta, field, '')}
querySearch={querySearch}
onQuerySearch={((searchText) => this.scope.searchField(field, searchText))}
dataList={this.scope.filteredList[field]}
initValue={initValue}
/>
, fieldElement,
);
}
/**
* @ngdoc method
* @name sdContactsSearchPanel#setQueryString
* @description function to set query string.
*/
setQueryString() {
let pattern = /[()]/g;
let params = this.$location.search();
const booleanToBinaryString = function(bool) {
return Number(bool).toString();
};
_.forEach(this.scope.meta, (val, key) => {
let v = val;
if (typeof val === 'boolean') {
v = booleanToBinaryString(val);
}
if (typeof val === 'string') {
v = val.replace(pattern, '');
}
if (v) {
this.$location.search(key, val);
} else if (_.get(params, key)) {
this.$location.search(key, null);
}
});
this.$location.search('q', this.scope.query || null);
}
/**
* @ngdoc method
* @name sdContactsSearchPanel#search
* @description function to perform search.
*/
search() {
this.setQueryString();
}
/*
* Get search input from field while typed and query the text input.
*/
searchField(field, text) {
if (text) {
this.contacts.queryField(field, text).then((items) => {
this.scope.filteredList[field] = _.map(items._items, field);
this.scope.meta[field] = text;
this.renderSearchField(field);
});
}
}
keyPressed(event) {
const ENTER = 13;
if (event.keyCode === ENTER) {
this.search();
event.preventDefault();
}
}
/**
* @ngdoc method
* @name sdContactsSearchPanel#clear
* @description clear all search and refresh the results.
*/
clear() {
const fields = [..._.keys(getUrlParameters()), 'q'];
this.$location.search(_.omit(this.$location.search(), fields));
this.scope.$broadcast('tag:removed');
}
}
/**
* @ngdoc directive
* @module superdesk.apps.contacts
* @name sdContactsSearchPanel
* @requires https://docs.angularjs.org/api/ng/service/$location $location
* @description sd-contacts-search-panel operates the search panel that appears
* to the left of the contacts search page
*/
export function ContactsSearchPanelDirective(contacts, $location) {
return {
template: require('scripts/apps/contacts/views/search-panel.html'),
link: (scope, elem) => new LinkFunction(contacts, $location, scope, elem),
};
}
ContactsSearchPanelDirective.$inject = ['contacts', '$location'];