if (!URI_BASE) throw "Missing URI_BASE"; // => Request::getPathUri() if (!URI_WPS) throw "Missing URI_WPS"; if (!global.jQuery) throw "Missing jQuery" var $ = global.jQuery var DBG = DBG || false; var DBG1 = true; var createReactClass = global.p5VendorJs.createReactClass; var h = global.p5VendorJs.React.createElement; var ReactDOM = global.p5VendorJs.ReactDOM; var Redux = global.p5VendorJs.Redux; var ReduxThunk = global.p5VendorJs.ReduxThunk; var createStoreWithThunkMiddleware = Redux.applyMiddleware(ReduxThunk)(Redux.createStore); // TODO: to vendor.js var p5UI__FieldCheckboxSearch = global.p5VendorJs['p5UI__FieldCheckboxSearch']; var p5UI__FieldCheckboxLoading = global.p5VendorJs['p5UI__FieldCheckboxLoading']; if (!String.prototype.startsWith) { // TODO: to global js utils String.prototype.startsWith = function(search, pos) { return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; }; } p5WfsRefFilter = (function () { // convert GET param key ogc filter for ref return { parse: function (filterKey) { if (filterKey.startsWith('Ref_From_')) return { type: 'From', idInstance: filterKey.substr('Ref_From_'.length) }; if (filterKey.startsWith('Ref_To_')) return { type: 'To', idInstance: filterKey.substr('Ref_To_'.length) }; return null; } }; })(); var p5WPSUtils__createConvertToWpsDataInputFunction = function (identifier) { return function (value) { if (!value) return null; // WPS function require value, but for eg. featureQuery mey be empty return { // "wps:Input" identifier: identifier, // "ows:Identifier" // title: "...", // "ows:Title" data: { literalData: { value: value } }, // "wps:Data" // reference: "???", // "wps:Reference" // boundingBoxData: "???", // "wps:BoundingBoxData" }; } }; var p5WPSHelper_generateProcessSelectFeatureWithArgs = function (identifier, args) { var dataInputs = Object.keys(args).reduce(function (ret, argName) { var value = args[argName]; var convertValueToWpsDataInput = p5WPSUtils__createConvertToWpsDataInputFunction(argName); return (p5Utils__isArray(value)) ? ret.concat( value.map( convertValueToWpsDataInput ) ) : ret.concat([ convertValueToWpsDataInput(value) ]) ; }, []).filter(function (wpsTag) { return !! wpsTag; }) return { identifier: identifier, // "ows:Identifier" dataInputs: dataInputs, responseForm: { // "wps:ResponseForm" // rawDataOutput: "???", // "wps:RawDataOutput" // responseDocument: "???", // "wps:ResponseDocument" } } } var p5WPS_executeFeatureProcess = function(identifier) { return function (wpsArgs) { // TODO: ns, listPrimaryKeys return new Promise(function (resolve, reject) { var process = p5WPSHelper_generateProcessSelectFeatureWithArgs(identifier, wpsArgs); OpenLayers.Request.POST({ url: URI_WPS, data: new OpenLayers.Format.WPSExecute().write(process), callback: function (response) { try { var txt = response.responseText || '' if (!txt) throw "Empty response"; var responseJson = JSON.parse(txt) if ('success' != responseJson.type) throw "Error response type '" + responseJson.type + "'"; if (!responseJson.body || !responseJson.body.selected) throw "Brak danych"; var listSelectedPks = Object.keys(responseJson.body.selected).filter(function (pk) { return responseJson.body.selected[pk]; }) var totalSelected = responseJson.body.totalSelected; DBG && console.log('wps('+identifier+') response', {response, responseJson, selected: responseJson.body.selected, resolve: listSelectedPks}); resolve({ selected: listSelectedPks, totalSelected: totalSelected, }) } catch (e) { reject('' + e) return; } }, // success: function (response) { // }, // failure: function (response) { // } }); }); } }; var p5WPS__selecFeature = p5WPS_executeFeatureProcess('p5:selectFeature'); var p5WPS__unselectFeature = p5WPS_executeFeatureProcess('p5:unselectFeature'); var p5WPS__unselecAllFeatures = p5WPS_executeFeatureProcess('p5:unselectAllFeatures'); var p5WPS__getSelectedFeatures = p5WPS_executeFeatureProcess('p5:getSelectedFeatures'); var p5WPS__selectAllFeaturesMatchingFilter = p5WPS_executeFeatureProcess('p5:selectAllFeaturesMatchingFilter'); function p5Utils__arrayRemove(array, toRemoveItem) { return array.filter(function (item) { return ( item !== toRemoveItem ); }); } function p5Utils__mapToQuery(map, callback) { var mapCallback = ('function' === typeof callback) ? callback : function (key) { return '' + key + '=' + encodeURIComponent(map.get(key)); }; return Array.from(map.keys()).sort() .map(mapCallback) .join('&') } function p5Utils__mapToQueryWithKeyPrefix(map, keyPrefix, callback) { var mapCallback = ('function' === typeof callback) ? callback : function (key) { return '' + (keyPrefix || '') + key + '=' + encodeURIComponent(map.get(key)); }; return p5Utils__mapToQuery(map, mapCallback) } function p5Utils__objectToQueryWithKeyPrefix(obj, prefix, callback) { if (!obj) return ''; var mapCallback = ('function' === typeof callback) ? callback : function (key) { return '' + key + '=' + encodeURIComponent(obj[key]); }; return Object.keys(obj).sort() .map(mapCallback) .join('&') } function fixSelectAllInSelectedState(state) { var len = state.listPrimaryKeys.length; var selLen = state.selected.length; var isAllSelected = ( len > 0 && selLen >= len ); // selected array may contain 'select-all' for (var i = 0, pk = ''; i < len; i++) { pk = state.listPrimaryKeys[i]; if (-1 === state.selected.indexOf(pk)) { isAllSelected = false; break; } } // DBG && console.log('fixSelectAllInSelectedState', { isAllSelected, state }); var isSelectedSelectAll = ( -1 !== state.selected.indexOf('select-all') ); if (isAllSelected && !isSelectedSelectAll) return Object.assign(state, { selected: ['select-all'].concat(state.selected) }); if (!isAllSelected && isSelectedSelectAll) return Object.assign(state, { selected: p5Utils__arrayRemove(state.selected, 'select-all'), }); return state; } function selectedStore(state, action) { var prevState = state || { isLoading: false, selected: [], loading: [], listPrimaryKeys: [], totalSelected: 0 }; DBG && console.log('DBG::selectedStore', { prevState, action }); switch (action.type) { case 'SET_CHECKED': return fixSelectAllInSelectedState(Object.assign({}, prevState, { loading: p5Utils__arrayRemove(prevState.loading, action.primaryKey), selected: prevState.selected.concat(action.primaryKey), totalSelected: action.totalSelected, })); case 'SET_UNCHECKED': return fixSelectAllInSelectedState(Object.assign({}, prevState, { loading: p5Utils__arrayRemove(prevState.loading, action.primaryKey), selected: p5Utils__arrayRemove(prevState.selected, action.primaryKey), totalSelected: action.totalSelected, })); case 'SET_LIST_CHECKED': return fixSelectAllInSelectedState(Object.assign({}, prevState, { loading: [], // TODO: p5Utils__arrayExcept(prevState.loading, action.listPrimaryKeys), selected: [].concat(action.listPrimaryKeys), // TODO: p5Utils__arrayUniqueUnion(prevState.selected, action.listPrimaryKeys) totalSelected: action.totalSelected, })); case 'SET_LIST_UNCHECKED': return fixSelectAllInSelectedState(Object.assign({}, prevState, { loading: [], // TODO: p5Utils__arrayExcept(prevState.loading, action.listPrimaryKeys), selected: [], // TODO: p5Utils__arrayUniqueUnion(prevState.selected, action.listPrimaryKeys) totalSelected: action.totalSelected, })); case 'SET_LOADING': return Object.assign(prevState, { loading: prevState.loading.concat(action.primaryKey) }); case 'SET_LIST_LOADING': return Object.assign(prevState, { loading: [].concat(action.listPrimaryKeys) }); case 'SET_PRIMARY_KEYS': return fixSelectAllInSelectedState(Object.assign({}, prevState, { listPrimaryKeys: [].concat(action.listPrimaryKeys), loading: [].concat(action.listPrimaryKeys) })); // case 'SET_ERROR_MSG': return Object.assign(prevState, { // errorMsg: action.errorMsg // }); default: return prevState; } } function selectedActions(idContext) { var idContext = idContext || null; function setChecked(primaryKey, totalSelected) { return { type: 'SET_CHECKED', primaryKey: primaryKey, totalSelected: totalSelected } } function setUnchecked(primaryKey, totalSelected) { return { type: 'SET_UNCHECKED', primaryKey: primaryKey, totalSelected: totalSelected } } function setLoading(primaryKey) { return { type: 'SET_LOADING', primaryKey: primaryKey } } function setListChecked(listPrimaryKeys, totalSelected) { return { type: 'SET_LIST_CHECKED', listPrimaryKeys: listPrimaryKeys, totalSelected: totalSelected } } function setListUnchecked(listPrimaryKeys, totalSelected) { return { type: 'SET_LIST_UNCHECKED', listPrimaryKeys: listPrimaryKeys, totalSelected: totalSelected } } function setListLoading(listPrimaryKeys) { return { type: 'SET_LIST_LOADING', listPrimaryKeys: listPrimaryKeys } } function setErrorMsg(errorMsg) { return { type: 'SET_ERROR_MSG', errorMsg: errorMsg } } function toggle(namespace, primaryKey, checked) { if ('select-all' === primaryKey) return toggleAll(namespace, checked); return function(dispatch, getState) { // var state = getState(); dispatch(setLoading(primaryKey)); var reqArgs = { typeName: namespace, primaryKey: [ primaryKey ] }; if (idContext) reqArgs.idContext = idContext; var reqPromise = checked ? p5WPS__selecFeature(reqArgs) : p5WPS__unselectFeature(reqArgs); return reqPromise.then(function (response) { DBG && console.log('DBG::async toggle action: (pk:'+primaryKey+') dispatch...'); dispatch( checked ? setChecked(primaryKey, response.totalSelected) : setUnchecked(primaryKey, response.totalSelected) ); }).catch(function (e) { p5UI__notifyAjaxCallback({type: 'error', msg: 'Wystąpił błąd #TA1: ' + e}); DBG && console.warn('DBG::async toggle action: (pk:'+primaryKey+') ERROR', e); // dispatch( checked ? setUnchecked(primaryKey) : setChecked(primaryKey) ); // dispatch( setErrorMsg(e) ); // TODO: show error with msg and refresh button dispatch( setListLoading([]) ); }); } } function setPrimaryKeys(namespace, listPrimaryKeys) { // TODO: should set list primaryKeys, change checkboxes to loading and fetch its state, then update gui DBG && console.log('DBG::setPrimaryKeys action: (pks:['+listPrimaryKeys.join(',')+'])...'); return function(dispatch, getState) { dispatch({ type: 'SET_PRIMARY_KEYS', listPrimaryKeys: listPrimaryKeys }); // dispatch( setListLoading(listPrimaryKeys) ); if (!listPrimaryKeys.length) return; var reqArgs = { typeName: namespace, primaryKey: listPrimaryKeys }; if (idContext) reqArgs.idContext = idContext; return p5WPS__getSelectedFeatures(reqArgs).then(function (listSelected) { DBG && console.log('DBG::setPrimaryKeys action: (pks:['+listPrimaryKeys.join(',')+']) dispatch success'); dispatch( setListChecked(listSelected.selected, listSelected.totalSelected) ); }).catch(function (e) { p5UI__notifyAjaxCallback({type: 'error', msg: 'Wystąpił błąd #TA2: ' + e}); DBG && console.warn('DBG::setPrimaryKeys action: (pks:['+listPrimaryKeys.join(',')+']) ERROR dispatch error'); // var fullListPks = ['select-all'].concat(listPrimaryKeys); // dispatch( setListUnchecked(fullListPks) ); // dispatch( setErrorMsg(e) ); // TODO: show error with msg and refresh button dispatch( setListLoading([]) ); }); } } function toggleAll(namespace, checked) { var primaryKey = 'select-all'; return function(dispatch, getState) { // var state = getState(); dispatch(setLoading(primaryKey)); var state = getState(); var listPrimaryKeys = state.listPrimaryKeys; var reqArgs = { typeName: namespace, primaryKey: listPrimaryKeys }; if (idContext) reqArgs.idContext = idContext; var reqPromise = checked ? p5WPS__selecFeature(reqArgs) : p5WPS__unselectFeature(reqArgs); return reqPromise.then(function (response) { DBG && console.log('DBG::setPrimaryKeys action: (pks:['+listPrimaryKeys.join(',')+']) dispatch success'); dispatch( checked ? setListChecked(response.selected, response.totalSelected) : setListUnchecked(response.selected, response.totalSelected) ); }).catch(function (e) { p5UI__notifyAjaxCallback({type: 'error', msg: 'Wystąpił błąd #TA3: ' + e}); DBG && console.warn('DBG::setPrimaryKeys action: (pks:['+listPrimaryKeys.join(',')+']) ERROR dispatch error'); // var fullListPks = ['select-all'].concat(listPrimaryKeys) // dispatch( checked ? setListUnchecked(fullListPks) : setListChecked(fullListPks) ); // dispatch( setErrorMsg(e) ); // TODO: show error with msg and refresh button dispatch( setListLoading([]) ); }); } } function unselectAll(namespace) { // dispatch(setLoading()); return function(dispatch, getState) { var reqArgs = { typeName: namespace }; if (idContext) reqArgs.idContext = idContext; var reqPromise = p5WPS__unselecAllFeatures(reqArgs); return reqPromise.then(function (response) { DBG && console.log('DBG::setPrimaryKeys action: (pks:['+listPrimaryKeys.join(',')+']) dispatch success'); // dispatch( setListChecked(response.selected, response.totalSelected) ); dispatch( setListChecked([], 0) ); }).catch(function (e) { p5UI__notifyAjaxCallback({type: 'error', msg: 'Wystąpił błąd #TA4: ' + e}); DBG && console.warn('DBG::setPrimaryKeys action: (pks:['+listPrimaryKeys.join(',')+']) ERROR dispatch error'); // var fullListPks = ['select-all'].concat(listPrimaryKeys) // dispatch( checked ? setListUnchecked(fullListPks) : setListChecked(fullListPks) ); // dispatch( setErrorMsg(e) ); // TODO: show error with msg and refresh button // dispatch( setListLoading([]) ); }); }; } function selectAllMatchingFilter(namespace, filterQuery) { DBG && console.log('DBG::selectAllMatchingFilter', { filterQuery }); return function(dispatch, getState) { DBG && console.log('DBG::selectAllMatchingFilter state', state); var state = getState(); var listPrimaryKeys = state.listPrimaryKeys; var reqArgs = { typeName: namespace, primaryKey: listPrimaryKeys, filterQuery: filterQuery }; if (idContext) reqArgs.idContext = idContext; return p5WPS__selectAllFeaturesMatchingFilter(reqArgs).then(function (listSelected) { DBG && console.log('DBG::selectAllMatchingFilter dispatch success'); dispatch( setListChecked(listSelected.selected, listSelected.totalSelected) ); }).catch(function (e) { p5UI__notifyAjaxCallback({type: 'error', msg: 'Wystąpił błąd #TA5: ' + e}); DBG && console.warn('DBG::selectAllMatchingFilter ERROR dispatch error'); // var fullListPks = ['select-all'].concat(listPrimaryKeys); // dispatch( setListUnchecked(fullListPks) ); // dispatch( setErrorMsg(e) ); // TODO: show error with msg and refresh button dispatch( setListLoading([]) ); }); } } return { setPrimaryKeys: setPrimaryKeys, setChecked: setChecked, setUnchecked: setUnchecked, toggle: toggle, unselectAll: unselectAll, selectAllMatchingFilter: selectAllMatchingFilter, } } function createFilterStoreWithInitialData(initialFilter) { var initialState = { isLoading: false, isEmpty: true, filter: new Map(), specialFilter: new Map(), currSortCol: '', currSortFlip: false } Object.keys(initialFilter).forEach(function (key) { if ('currSortCol' === key) { initialState.currSortCol = initialFilter[key] } else if ('currSortFlip' === key) { initialState.currSortFlip = initialFilter[key] } else if ('f_' === key.substr(0, 2)) { initialState.filter.set(key.substr(2), initialFilter[key]) } else if ('sf_' === key.substr(0, 3)) { initialState.specialFilter.set(key.substr(3), initialFilter[key]) } }) return function filterStore(state, action) { var prevState = state || initialState; DBG && console.warn('DBG:filterStore:' + action.type, action); switch (action.type) { // case 'SET_FILTER': return fixFilterState(Object.assign({}, prevState, { // filter: Object.assign(prevState.filter, { // [action.fieldName]: action.value // }) // })); case 'TOGGLE_SORT': { return Object.assign(prevState, { currSortCol: action.fieldName, currSortFlip: !prevState.currSortFlip }) } case 'SET_FILTER': { if (action.value) { prevState.filter.set(action.fieldName, action.value); } else { prevState.filter.delete(action.fieldName); } return Object.assign(prevState, { isEmpty: (0 === prevState.specialFilter.size && 0 === prevState.filter.size) }) } case 'SET_SPECIAL_FILTER': { if (action.value) { prevState.specialFilter.set(action.fieldName, action.value); } else { prevState.specialFilter.delete(action.fieldName); } return Object.assign(prevState, { isEmpty: (0 === prevState.specialFilter.size && 0 === prevState.filter.size) }) } case 'CLEAR_ALL_FILTERS': { prevState.filter.clear(); prevState.specialFilter.clear(); return Object.assign(prevState, { isLoading: false, isEmpty: true }); } case 'SET_LOADING': return Object.assign(prevState, { // TODO: is loading for filter store or another store for rows? isLoading: true }); case 'UNSET_LOADING': return Object.assign(prevState, { isLoading: false }); default: return prevState; } } } function filterActions() { var delay = 450; var _filterTimeout = {}; var _clearTimer = function (fieldName) { if (_filterTimeout[fieldName]) { clearTimeout(_filterTimeout[fieldName]); } } var _clearAllTimers = function () { Object.keys(_filterTimeout).forEach(_clearTimer); } function clearAllFilters() { DBG && console.log('DBG:filterStore:clearAllFilters'); _clearAllTimers(); return { type: 'CLEAR_ALL_FILTERS' }; } function toggleSort(fieldName) { DBG && console.log('DBG:filterStore:toggleSort', { fieldName }); return { type: 'TOGGLE_SORT', fieldName: fieldName }; } function setFilter(fieldName, value) { DBG && console.log('DBG:filterStore:setFilter', { fieldName, value }); return { type: 'SET_FILTER', fieldName: fieldName, value: value }; } function setSpecialFilter(fieldName, value) { DBG && console.log('DBG:filterStore:setSpecialFilter', { fieldName, value }); return { type: 'SET_SPECIAL_FILTER', fieldName: fieldName, value: value }; } function delayFilter(fieldName, value) { DBG && console.log('DBG:filterStore:delayFilter', { fieldName, value }); return function(dispatch, getState) { // var state = getState(); // dispatch(setLoading(primaryKey)); return new Promise(function (resolve, reject) { DBG && console.log('DBG:filterStore:delayFilter::#1', { fieldName, value }); _clearTimer(fieldName); _filterTimeout[fieldName] = setTimeout(function () { // reject("Error"); resolve(value); }, delay); }).then(function (value) { DBG && console.log('DBG:filterStore:delayFilter::#3 resolve ', { fieldName, value }); dispatch( { type: 'SET_FILTER', fieldName: fieldName, value: value } ); }).catch(function (e) { p5UI__notifyAjaxCallback({type: 'error', msg: 'Wystąpił błąd #TA6: ' + e}); }) } } return { setFilter: setFilter, setSpecialFilter: setSpecialFilter, delayFilter: delayFilter, clearAllFilters: clearAllFilters, toggleSort: toggleSort, } } global['P5UI__TableAjaxRowCheckbox'] = createReactClass({ // props.namespace: PropTypes.string.isRequired // props.primaryKey: PropTypes.string.isRequired // props.store: Redux store with state: { isLoading bool, selected array of strings } // props.actions: Redux store actions getStateFromStore: function () { var state = this.props.store.getState(); return { disabled: this.props.disabled ? true : false, isLoading: (-1 !== state.loading.indexOf(this.props.primaryKey)), checked: (-1 !== state.selected.indexOf(this.props.primaryKey)) }; }, getInitialState: function () { return this.getStateFromStore(); }, componentDidMount: function () { DBG && console.log('DBG::P5UI__TableAjaxRowCheckbox::componentDidMount (pk:'+this.props.primaryKey+')'); this.unsubscribe = this.props.store.subscribe(this.storeUpdated) }, componentWillUnmount: function () { this.unsubscribe() }, storeUpdated: function () { DBG && console.log('DBG::P5UI__TableAjaxRowCheckbox::storeUpdated (pk:'+this.props.primaryKey+')'); this.setState(this.getStateFromStore()) }, shouldComponentUpdate: function (nextProps, nextState) { DBG && console.log('DBG::P5UI__TableAjaxRowCheckbox::shouldComponentUpdate (pk:'+this.props.primaryKey+')', { state: this.state, nextState}); return ( this.state.isLoading !== nextState.isLoading || this.state.checked !== nextState.checked ); }, handleChange: function (checked) { // handleChange: function (event) { DBG && console.log('DBG::P5UI__TableAjaxRowCheckbox::handleChange (pk:'+this.props.primaryKey+')', { checked: checked }); this.props.store.dispatch( this.props.actions.toggle( this.props.namespace, this.props.primaryKey, checked ) ) }, render: function () { DBG && console.log('DBG::P5UI__TableAjaxRowCheckbox::render (pk:'+this.props.primaryKey+')', { props: this.props, state: this.state }); return h(p5UI__FieldCheckboxLoading, { size: 20, color: '#999', checked: this.state.checked, disabled: this.state.disabled, isLoading: this.state.isLoading, onChange: this.handleChange }); } }); global['P5UI__TableAjaxSelectedInfo'] = createReactClass({ // props.namespace: PropTypes.string.isRequired // props.store: Redux store with state: { isLoading bool, selected array of strings } // props.actions: Redux store actions getStateFromStore: function () { var state = this.props.store.getState(); var wasAllSelected = (this.state) && this.state.isUpdatedAllSelected; var isAllSelected = ( -1 !== state.selected.indexOf('select-all') ); DBG && console.log('DBG: getStateFromStore (ns:'+this.props.namespace+')', { isAllSelected, state }); return { // isLoading: state.isLoading || 0, // add ? isUpdatedAllSelected: ( !wasAllSelected && isAllSelected ), totalSelected: state.totalSelected || 0, }; }, getInitialState: function () { return this.getStateFromStore(); }, componentDidMount: function () { DBG && console.log('DBG::P5UI__TableAjaxSelectedInfo::componentDidMount (ns:'+this.props.namespace+')'); this.unsubscribe = this.props.store.subscribe(this.storeUpdated) }, componentWillUnmount: function () { this.unsubscribe() }, storeUpdated: function () { DBG && console.log('DBG::P5UI__TableAjaxSelectedInfo::storeUpdated (ns:'+this.props.namespace+')'); this.setState(this.getStateFromStore()) }, shouldComponentUpdate: function (nextProps, nextState) { DBG && console.log('DBG::P5UI__TableAjaxSelectedInfo::shouldComponentUpdate (ns:'+this.props.namespace+')', { state: this.state, nextState}); return ( this.state.totalSelected !== nextState.totalSelected || this.state.isUpdatedAllSelected !== nextState.isUpdatedAllSelected ); }, handleUnselectAll: function (event) { DBG && console.log('DBG::P5UI__TableAjaxSelectedInfo::handleUnselectAll (ns:'+this.props.namespace+')'); this.props.store.dispatch( this.props.actions.unselectAll( this.props.namespace ) ) }, handleSelectAllByFilter: function (event) { DBG && console.log('DBG::P5UI__TableAjaxSelectedInfo::handleSelectAllByFilter (ns:'+this.props.namespace+')'); // this.props.store.dispatch( this.props.actions.unselectAll( this.props.namespace ) ) this.props.onSelectAllMatching() }, render: function () { DBG && console.log('DBG::P5UI__TableAjaxSelectedInfo::render (ns:'+this.props.namespace+')', { props: this.props, state: this.state }); return h('div', { style: { padding: '0 4px' } }, [ h('span', {}, "Wybrano " + this.state.totalSelected), (this.state.totalSelected > 0) ? h('i', { onClick: this.handleUnselectAll, className: "glyphicon glyphicon-remove", style: { marginLeft: '4px', cursor: 'pointer', color: 'red', opacity: '0.5' }, title: this.props.title || 'Usuń wszystkie zaznaczenia' }) : null, (this.state.isUpdatedAllSelected) && h('br'), (this.state.isUpdatedAllSelected) && h('a', { onClick: this.handleSelectAllByFilter, className: "btn btn-xs btn-link", style: { marginLeft: '4px', }, title: this.props.title || 'Zaznacz wszystkie pasujące do wyszukiwania' }, "+ wszystkie"), ]) } }); global['P5UI__TableAjaxSpecialFilter'] = createReactClass({ // props.store: Redux store with state: { isLoading bool, selected array of strings } // props.actions: Redux store actions // props.name: PropTypes.string.isRequired // props.values: PropTypes.array.isRequired // props.icon: PropTypes.string.isRequired // props.label: PropTypes.string getStateFromStore: function () { var state = this.props.store.getState(); DBG && console.log('DBG::P5UI__TableAjaxSpecialFilter::getStateFromStore (name:'+this.props.name+')', { store: state, name: this.props.name, selected: state.specialFilter.get(this.props.name) }); return { selected: state.specialFilter.get(this.props.name), }; }, getInitialState: function () { return this.getStateFromStore(); }, componentDidMount: function () { DBG && console.log('DBG::P5UI__TableAjaxSpecialFilter::componentDidMount (name:'+this.props.name+')'); this.unsubscribe = this.props.store.subscribe(this.storeUpdated) }, componentWillUnmount: function () { this.unsubscribe() }, storeUpdated: function () { DBG && console.log('DBG::P5UI__TableAjaxSpecialFilter::storeUpdated (name:'+this.props.name+')'); this.setState(this.getStateFromStore()) }, shouldComponentUpdate: function (nextProps, nextState) { DBG && console.log('DBG::P5UI__TableAjaxSpecialFilter::shouldComponentUpdate (name:'+this.props.name+')', { state: this.state, nextState}); return ( this.state.selected !== nextState.selected ); }, handleRemoveFilter: function (event) { this.props.store.dispatch( this.props.actions.setSpecialFilter(this.props.name, '') ); }, handleSetFilter: function (value) { this.props.store.dispatch( this.props.actions.setSpecialFilter(this.props.name, value) ); }, renderButton: function (buttonKey) { var option = buttonKey; var props = this.props.values[option]; var value = props.value || ''; var state = this.props.store.getState(); DBG && console.warn('DBG:renderButton state', { state, props, value }); var active = (value === this.state.selected); return h('button', { className: "btn btn-xs btn-default" + ( active ? " active" : "" ), onClick: function (event) { DBG && console.warn('DBG:renderButton click', { value }); this.handleSetFilter(value); }.bind(this), }, option); }, render: function () { DBG && console.log('DBG::P5UI__TableAjaxSpecialFilter::render (name:'+this.props.name+')', { state: this.state, props: this.props }); var label = this.props.label || this.props.name; return h('div', { className: "btn-group", style: { margin: '0 4px 0 0' } }, [ h('button', { className: "btn btn-xs btn-default", title: label, }, [ h('i', { className: this.props.icon }) ]) ].concat( Object.keys(this.props.values).map(this.renderButton) ).concat( [ h('button', { className: "btn btn-xs btn-default", title: "Kasuj filtr", disabled: !this.state.selected, onClick: this.handleRemoveFilter, style: { color: !this.state.selected ? '#bbb' : '#f00' } }, [ h('i', { className: "glyphicon glyphicon-remove" }) ]) ] ) ); } }); global['P5UI__TableAjaxSpecialFilterRelations'] = createReactClass({ // props.store: Redux store with state: { isLoading bool, selected array of strings } // props.actions: Redux store actions // props.name: PropTypes.string.isRequired // props.values: PropTypes.array.isRequired // props.icon: PropTypes.string.isRequired // props.label: PropTypes.string // props.availableBackRefs: PropTypes.array.isRequired // array of objects { id, namespace, label } // props.availableChildRefs: PropTypes.array.isRequired // array of objects { id, namespace, label } getStateFromStore: function () { var state = this.props.store.getState(); DBG && console.log('DBG::P5UI__TableAjaxSpecialFilterRelations::getStateFromStore (name:'+this.props.name+')', { store: state, name: this.props.name, selected: state.specialFilter.get(this.props.name) }); var selected = []; // Array of { idInstance, primaryKey } state.specialFilter.forEach(function (value, key) { var refInfo = p5WfsRefFilter.parse(key); // null | { type: 'From' | 'To', idInstance: int } if (refInfo) { selected.push(Object.assign(refInfo, { primaryKey: value, filterKey: key })) } }) DBG && console.log('TODO: DBG::P5UI__TableAjaxSpecialFilterRelations::getStateFromStore (name:'+this.props.name+')', { store: state, name: this.props.name, selected }); return { selected: selected, }; }, getInitialState: function () { return this.getStateFromStore(); }, componentDidMount: function () { DBG && console.log('DBG::P5UI__TableAjaxSpecialFilterRelations::componentDidMount (name:'+this.props.name+')'); this.unsubscribe = this.props.store.subscribe(this.storeUpdated) }, componentWillUnmount: function () { this.unsubscribe() }, storeUpdated: function () { DBG && console.log('DBG::P5UI__TableAjaxSpecialFilterRelations::storeUpdated (name:'+this.props.name+')'); this.setState(this.getStateFromStore()) }, shouldComponentUpdate: function (nextProps, nextState) { DBG && console.log('DBG::P5UI__TableAjaxSpecialFilterRelations::shouldComponentUpdate (name:'+this.props.name+')', { state: this.state, nextState}); return ( this.state.selected !== nextState.selected ); }, handleRemoveFilter: function (event) { this.props.store.dispatch( this.props.actions.setSpecialFilter(this.props.name, '') ); }, handleSetFilter: function (value) { this.props.store.dispatch( this.props.actions.setSpecialFilter(this.props.name, value) ); }, handleCreate: function () { // TODO: save swal reference to variable to avoid open twice? var inputOptions = {}; if (this.props.availableBackRefs) this.props.availableBackRefs.forEach(function (instanceInfo) { inputOptions[ 'From_' + instanceInfo.id ] = "z " + instanceInfo.label || instanceInfo.namespace; }); if (this.props.availableChildRefs) this.props.availableChildRefs.forEach(function (instanceInfo) { inputOptions[ 'To_' + instanceInfo.id ] = "do " + instanceInfo.label || instanceInfo.namespace; }); swal({ title: "Wybierz rodzaj relacji", input: 'select', inputOptions: inputOptions, inputPlaceholder: "Wybierz", showCancelButton: true, cancelButtonText: "Anuluj", animation: false, inputValidator: function (value) { DBG && console.log('DBG::P5UI__TableAjaxSpecialFilterRelations::inputValidator', value); return new Promise(function (resolve) { if (!value) { resolve('Nie wybrano obiektu'); } else { resolve(); } }); }, }).then(this.handleInstanceCreate) // args: { value: ... } }, handleInstanceCreate: function (result) { if (!result.value) return; // cancel when result = { dismiss: "cancel" } var idInstance = ''; var type = ''; var instanceLabel = ''; if ('From_' === result.value.substr(0, 'From_'.length)) { type = 'From'; idInstance = result.value.substr('From_'.length); if (this.props.availableBackRefs) this.props.availableBackRefs.forEach(function (instanceInfo) { if (idInstance == instanceInfo.id) instanceLabel = instanceInfo.label || instanceInfo.namespace; }); } else if ('To_' === result.value.substr(0, 'To_'.length)) { type = 'To'; idInstance = result.value.substr('To_'.length); if (this.props.availableChildRefs) this.props.availableChildRefs.forEach(function (instanceInfo) { if (idInstance == instanceInfo.id) instanceLabel = instanceInfo.label || instanceInfo.namespace; }); } DBG && console.log('DBG::P5UI__TableAjaxSpecialFilterRelations::handleInstanceCreate (name:'+this.props.name+') selected instance('+idInstance+')', { result: result, state: this.state, props: this.props, availableBackRefs: this.props.availableBackRefs }); swal({ title: "Wybierz obiekt", html: (instanceLabel) ? "typu: " + instanceLabel : "", input: 'text', inputPlaceholder: "Wybierz obiekt", showCancelButton: true, cancelButtonText: "Anuluj", animation: false, inputValidator: function (value) { DBG && console.log('DBG::P5UI__TableAjaxSpecialFilterRelations::inputValidator', value); return new Promise(function (resolve) { if (!value) { resolve('Nie podano obiektu'); } else { resolve(); } }); }, preConfirm: function (value) { return { type: type, idInstance: idInstance, primaryKey: value, } } }).then(this.handleInstancePrimaryKeySelected) // args: { value: { idInstance, primaryKey } } }, handleInstancePrimaryKeySelected: function (result) { if (!result.value) return; // cancel when result = { dismiss: "cancel" } var type = result.value.type; var idInstance = result.value.idInstance; var primaryKey = result.value.primaryKey; DBG && console.log('DBG::P5UI__TableAjaxSpecialFilterRelations::handleInstancePrimaryKeySelected (name:'+this.props.name+') selected featureID('+idInstance+'.'+primaryKey+')', { result: result, state: this.state, props: this.props, availableBackRefs: this.props.availableBackRefs }); this.props.store.dispatch( this.props.actions.setSpecialFilter('Ref_' + type + '_' + idInstance, primaryKey) ); }, renderButton: function (buttonKey) { var option = buttonKey; var props = this.props.values[option]; var value = props.value || ''; var state = this.props.store.getState(); DBG && console.warn('DBG:renderButton state', { state, props, value }); var active = (value === this.state.selected); return h('button', { className: "btn btn-xs btn-default" + ( active ? " active" : "" ), onClick: function (event) { DBG && console.warn('DBG:renderButton click', { value }); this.handleSetFilter(value); }.bind(this), }, option); }, renderLabel: function () { var label = this.props.label || this.props.name; return h('button', { className: "btn btn-xs btn-default", title: label, style: { color: '#31708f', backgroundColor: '#d9edf7', } }, [ h('i', { className: this.props.icon }), " Filtr relacji: ", ]); }, renderListSelected: function () { // @return array of react nodes DBG && console.log('DBG::P5UI__TableAjaxSpecialFilterRelations::this.props.availableBackRefs (name:'+this.props.name+')', { state: this.state, props: this.props, availableBackRefs: this.props.availableBackRefs }); return this.state.selected.map(this.renderSelected); }, renderSelected: function (selected) { // @selected: { type: 'From' | 'To', filterKey, idInstance, primaryKey }, @return react node var filterKey = selected.filterKey; var type = selected.type; // From | To - backRef | childRef var idInstance = selected.idInstance; var primaryKey = selected.primaryKey; var namespace = idInstance; var label = "" + idInstance + "." + primaryKey + ""; if ('From' === type) { var foundInstanceInfo = this.props.availableBackRefs.filter(function (instanceInfo) { return ( parseInt(idInstance) === parseInt(instanceInfo.id) ); }); if (foundInstanceInfo.length > 0) label = 'z ' + foundInstanceInfo[0].label + "." + primaryKey; if (foundInstanceInfo.length > 0) namespace = foundInstanceInfo[0].namespace; } else if ('To' === type) { var foundInstanceInfo = this.props.availableChildRefs.filter(function (instanceInfo) { return ( parseInt(idInstance) === parseInt(instanceInfo.id) ); }); if (foundInstanceInfo.length > 0) label = 'do ' + foundInstanceInfo[0].label + "." + primaryKey; if (foundInstanceInfo.length > 0) namespace = foundInstanceInfo[0].namespace; } return h(P5UI__TableAjaxSpecialFilterRelationFrom, { filterKey: filterKey, label: label, namespace: namespace, primaryKey: primaryKey, store: this.props.store, actions: this.props.actions, }); }, renderBackRef: function () { // @return react node - button with dropdown to select primaryKey from parent instance + remove button if selected return null; }, renderCreateButton: function () { return h('button', { className: "btn btn-xs btn-default", title: "Dodaj nowy filtr relacji", onClick: this.handleCreate, }, [ h('i', { className: 'glyphicon glyphicon-plus' }) ]); }, render: function () { DBG && console.log('DBG::P5UI__TableAjaxSpecialFilterRelations::render (name:'+this.props.name+')', { state: this.state, props: this.props }); return h('div', { className: "btn-group", style: { margin: '0 4px 0 0' } }, [ this.renderLabel(), ].concat( this.renderListSelected() ).concat([ this.renderCreateButton() ]) // Object.keys(this.props.values).map(this.renderButton) // ).concat( // [ // h('button', { // className: "btn btn-xs btn-default", // title: "Kasuj filtr", // disabled: !this.state.selected, // onClick: this.handleRemoveFilter, // style: { color: !this.state.selected ? '#bbb' : '#f00' } // }, [ // h('i', { className: "glyphicon glyphicon-remove" }) // ]) // ] ); } }); global['P5UI__TableAjaxSpecialFilterRelationFrom'] = createReactClass({ handleRemoveFilter: function (event) { this.props.store.dispatch( this.props.actions.setSpecialFilter(this.props.filterKey, '') ); }, render: function () { DBG1 && console.log('DBG::P5UI__TableAjaxSpecialFilterRelationFrom::render (filterKey:'+this.props.filterKey+')', { state: this.state, props: this.props }); var refInfo = p5WfsRefFilter.parse(this.props.filterKey); // null | { type: 'From' | 'To', idInstance: int } return h('button', { className: "btn btn-xs btn-default active", title: "Powiązane" + ( 'From' === refInfo.type ? " z " : " do " ) + this.props.namespace + " " + this.props.primaryKey, // onClick: this.handleUpdate, // TODO: paste param }, [ this.props.label, h('i', { className: 'glyphicon glyphicon-remove', style: { color: '#f00', opacity: 0.5, marginLeft: "3px", }, onClick: this.handleRemoveFilter, }) ]); } }); global['P5UI__TableAjaxSpecialFilters'] = createReactClass({ // props.store: Redux store with state: { isLoading bool, selected array of strings } // props.actions: Redux store actions // props.namespace: PropTypes.string.isRequired // props.specialFilters: PropTypes.object.isRequired // props.specialFilters: // [Msgs] => stdClass Object // [icon] => glyphicon glyphicon-envelope // [label] => Wiadomości // [btns] => Array: // [WIADOMOSCI] => stdClass Object // [value] => HAS_MSGS // [NOWE] => stdClass Object // [value] => NEW_MSGS // [BRAK_WIAD.] => stdClass Object // [value] => NO_MSGS // [Status] => stdClass Object // [icon] => glyphicon glyphicon-question-sign // [btns] => Array: // [OCZEKUJACY] => stdClass Object // [value] => WAITING // [AKTYWNI] => stdClass Object // [value] => AKTYWNI // handleClick: function (event) { // DBG && console.log('DBG::P5UI__TableAjaxSpecialFilters::handleChange (ns:'+this.props.namespace+')', { checked: checked }); // this.props.store.dispatch( this.props.actions.unselectAll( this.props.namespace ) ) // }, renderSpecialFilter: function (key) { var props = this.props.specialFilters[key]; DBG && console.log('DBG::P5UI__TableAjaxSpecialFilters::renderSpecialFilter (ns:'+this.props.namespace+')', { key: key, props, state: this.state }); if ('RELATIONS' === props.type) { DBG && console.warn('DBG::P5UI__TableAjaxSpecialFilters::renderSpecialFilter TODO render RELATIONS filter (ns:'+this.props.namespace+')', { props, state: this.state }); return h(P5UI__TableAjaxSpecialFilterRelations, { store: this.props.store, actions: this.props.actions, name: key, icon: props.icon, label: props.label, availableBackRefs: props.availableBackRefs, availableChildRefs: props.availableChildRefs, }); } return h(P5UI__TableAjaxSpecialFilter, { store: this.props.store, actions: this.props.actions, name: key, icon: props.icon, label: props.label, values: props.btns, }); }, render: function () { DBG && console.log('DBG::P5UI__TableAjaxSpecialFilters::render (ns:'+this.props.namespace+')', { props: this.props, state: this.state }); return h('div', {}, Object.keys(this.props.specialFilters).map(this.renderSpecialFilter)) } }); global['P5UI__TableAjaxFieldCheckboxSearch'] = createReactClass({ // props.namespace: PropTypes.string.isRequired // props.fieldName: PropTypes.string.isRequired // props.store: Redux store with state: { isLoading bool, selected array of strings } // props.actions: Redux store actions getStateFromStore: function () { var state = this.props.store.getState(); // selected = || 2 // 0 - unchecked, 1 - checked, 2 - indeterminate var selected = ''; if (state.filter.has(this.props.fieldName)) { selected = state.filter.get(this.props.fieldName) } return { disabled: this.props.disabled ? true : false, selected: selected, active: ('YES' === selected || 'NO' === selected), // isLoading: (-1 !== state.loading.indexOf(this.props.fieldName)), // checked: (-1 !== state.selected.indexOf(this.props.fieldName)) }; }, getInitialState: function() { return this.getStateFromStore(); }, componentDidMount: function () { DBG && console.log('DBG::P5UI__TableAjaxFieldCheckboxSearch::componentDidMount (f:'+this.props.fieldName+')'); this.unsubscribe = this.props.store.subscribe(this.storeUpdated) }, componentWillUnmount: function () { this.unsubscribe() }, storeUpdated: function () { DBG && console.log('DBG::P5UI__TableAjaxFieldCheckboxSearch::storeUpdated (f:'+this.props.fieldName+')', this.getStateFromStore()); this.setState(this.getStateFromStore()) }, shouldComponentUpdate: function (nextProps, nextState) { DBG && console.log('DBG::P5UI__TableAjaxFieldCheckboxSearch::shouldComponentUpdate (f:'+this.props.fieldName+')', { state: this.state, nextState}); return ( this.state.disabled !== nextState.disabled || this.state.selected !== nextState.selected ); }, handleChange: function (selected) { // selected: 0 - not checked, 1 - checked, 2 - indeterminate DBG && console.log('DBG::P5UI__TableAjaxFieldCheckboxSearch::handleChange (f:'+this.props.fieldName+')', { selected: selected, state: this.state }); if (0 === selected) { this.props.store.dispatch( this.props.actions.setFilter(this.props.fieldName, 'NO') ); } else if (1 === selected) { this.props.store.dispatch( this.props.actions.setFilter(this.props.fieldName, 'YES') ); } else if (2 === selected) { this.props.store.dispatch( this.props.actions.setFilter(this.props.fieldName, '') ); } }, mapSelectedToValue: function (selected) { switch (selected) { case 'YES': return 1; case 'NO': return 0; default: return 2; } }, render: function () { DBG && console.log('DBG::P5UI__TableAjaxFieldCheckboxSearch::render (f:'+this.props.fieldName+')', { props: this.props, state: this.state, state_sel: this.state.selected, sel: this.mapSelectedToValue(this.state.selected) }); return h('div', { style: { boxSizing: 'border-box', width: '100%', height: '21px', padding: '0 5px', borderTop: 0, borderBottom: '2px solid ' + ( this.state.active ? '#00ACCC' : 'transparent' ), }, }, [ h(p5UI__FieldCheckboxSearch, { size: 19, color: '#888', staticLabel: ["Pokaż:", "wszystkie,", "wybrane,", "niewybrane"].join("\n"), fieldName: this.props.fieldName, selected: this.mapSelectedToValue(this.state.selected), onChange: this.handleChange // checked: this.state.checked, // disabled: this.state.disabled, // isLoading: this.state.isLoading, }), ] ); } }); global['p5UI__FieldInputFilterSearch'] = createReactClass({ // props.fieldName: PropTypes.string.isRequired // props.type: PropTypes.string.isRequired // props.store: Redux store with state: { } // props.actions: Redux store actions // props.disabled: PropTypes.bool // props.lagacyProps: PropTypes.object getStateFromStore: function () { var storeState = this.props.store.getState(); return { value: storeState.filter.get(this.props.fieldName) || '', active: storeState.filter.has(this.props.fieldName) }; }, getInitialState: function() { return this.getStateFromStore(); }, componentDidMount: function () { DBG && console.log('DBG::p5UI__FieldInputFilterSearch::componentDidMount (f:'+this.props.fieldName+')'); this.unsubscribe = this.props.store.subscribe(this.storeUpdated) }, componentWillUnmount: function () { this.unsubscribe() }, storeUpdated: function () { DBG && console.log('DBG::p5UI__FieldInputFilterSearch::storeUpdated (f:'+this.props.fieldName+')', this.getStateFromStore()); this.setState(this.getStateFromStore()) }, shouldComponentUpdate: function (nextProps, nextState) { DBG && console.log('DBG::p5UI__FieldInputFilterSearch::shouldComponentUpdate (f:'+this.props.fieldName+')', { state: this.state, nextState}); return ( this.state.value !== nextState.value || this.state.active !== nextState.active ); }, handleChange: function (event) { // handleChange: function (event) { var value = event.target.value; DBG && console.log('DBG::p5UI__FieldInputFilterSearch::handleChange (f:'+this.props.fieldName+')', { value }); this.setState({ value: value }); this.props.onChange(this.props.fieldName, value); // this.props.store.dispatch( this.props.actions.toggle( this.props.namespace, this.props.primaryKey, checked ) ) }, render: function () { DBG && console.log('DBG::p5UI__FieldInputFilterSearch::render (f:'+this.props.fieldName+',v:'+this.state.value+')', { props: this.props, state: this.state }); switch (this.props.type) { case "number": case "date": case "bool": case "p5:price": case "p5:www_link": case "p5:string": case "string": return this.renderInput(); case "special": return this.renderEmpty(); case "simpleLink": return this.renderEmpty(); case "geom": return this.renderInput(); case "none": return this.renderEmpty(); case "ref": return this.renderEmpty(); default: return this.renderEmpty(); } }, renderEmpty: function () { return h('div', {}, " "); }, renderInput: function () { return h('input', { className: "filter", // + ( this.state.active ? " filter-active" : "" ), placeholder: !this.props.disabled ? "%" : "", type: "text", disabled: this.props.disabled || false, style: { boxSizing: 'border-box', width: '100%', height: '21px', borderTop: 0, borderBottom: '2px solid ' + ( this.state.active ? '#00ACCC' : 'transparent' ), }, value: this.state.value, onChange: this.handleChange }); } }); global['p5UI__TableAjaxClearAllFilters'] = createReactClass({ // props.store: Redux store with state: { } // props.actions: Redux store actions getStateFromStore: function () { var storeState = this.props.store.getState(); return { isFiltersEmpty: ( 0 === storeState.filter.size && 0 === storeState.specialFilter.size ) }; }, getInitialState: function() { return this.getStateFromStore(); }, componentDidMount: function () { DBG && console.log('DBG::p5UI__TableAjaxClearAllFilters::componentDidMount (f:'+this.props.fieldName+')'); this.unsubscribe = this.props.store.subscribe(this.storeUpdated) }, componentWillUnmount: function () { this.unsubscribe() }, storeUpdated: function () { DBG && console.log('DBG::p5UI__TableAjaxClearAllFilters::storeUpdated (f:'+this.props.fieldName+')', this.getStateFromStore()); this.setState(this.getStateFromStore()) }, // shouldComponentUpdate: function (nextProps, nextState) { // DBG && console.log('DBG::p5UI__TableAjaxClearAllFilters::shouldComponentUpdate (f:'+this.props.fieldName+')', { state: this.state, nextState}); // return ( // this.state.value !== nextState.value // || this.state.active !== nextState.active // ); // }, handleClick: function (event) { DBG && console.log('DBG::p5UI__TableAjaxClearAllFilters::handleClick (clearAllFilters)'); this.props.store.dispatch( this.props.actions.clearAllFilters() ) }, render: function () { DBG && console.log('DBG::p5UI__TableAjaxClearAllFilters::render (clearAllFilters)', { props: this.props, state: this.state }); return h('i', { title: this.props.title || "Kasuj wszystkie filtry", className: "glyphicon glyphicon-remove", style: Object.assign( { opacity: '0.5', lineHeight: '20px', padding: '0 3px', cursor: 'pointer', }, this.state.isFiltersEmpty ? { color: '#777' } : { color: '#f00' } ), onClick: this.handleClick }); } }); var TableAjax = function() { var priv = {}; //private api var publ = {}; //public api priv.options = {}; var defaults = { namespace: '', url: '', //webservice url urlPost: false, //use POST instead of GET selectAllByFilterUrl: '', getCsvTheGeomAjaxUrl: '', removeTheGeomAjaxUrl: '', moreFunctionsCellAjaxUrl: '', editInlineSaveUrl: '', theGeomSaveUrl: '', pageSizeSave: '', hiddenColsSaveUrl: '', editInlineUrl: '', addUserTableFilterAjaxUrl: '', rmUserTableFilterAjaxUrl: '', hasAdditionalLayers: 0, labelHtml: '', debug: false, //prints debug info to console filter: false, //show filter row filterInit: false,// init filters data forceFilterInit: false, columnPicker: false, //show columnpicker checkboxes: false, //show body checkboxes actions: '', //holds action links pageSize: 10, //current pagesize pageSizes: [10, 20, 30, 40, 50, 'All'], //available pagesizes hidePagerOnEmpty: false, //removes pager if no rows types: { //type specific options string: {}, number: {}, bool: {}, date: {} }, rowFunctions: false, tblFunctions: false, specialFilterFunctions: false, filtersClean: false, router: false, longDesc: false, exportFields: [], mapEditor: false, // mapEditor visible or not mapEditorContainer: 'window' // 'window' or 'dock' }; var _uiNodeCont; // container holding table var _uiNodeSelectedInfo; var _uiNodeSpecialFilters; var _uiNode$Table; // the table node var _head; // table header var _headSort; // table header sorting row var _headFilter; // table header columns filter row var _headSpecialFilter; // table header special filter row var _bodyNode; // table body var _body; // TODO: table body need render? var _foot; // table footer var _inlineEditBox; // inline edit box with form var _popoverCell; // inline popover cell var _popoverCellCurrent; // inline popover cell var _popoverCellAjaxXhr; var _mapEditor; // map editor node var _mapEditorWrap; // map editor wrapper node var _mapEditorDialog; // map editor jquery ui dialog node var _state = {};// state - to replace variables below (date, ...) var _data; //columns and rows var _totalPages; // total pages var _currDpOp; // clicked datetimepicker operator var _filterTimeout; // timer for delayed filtering var _checkToggleChecked = false; // check-all toggle state var _exportFieldsSelect = {}; var _tableWidth; var _fieldWidgets = {}; /* initialize the plugin. */ priv.init = function() { _uiNodeCont = priv.options.id; _state = {};// init state _state.page = 1; _state.specialFilters = {}; { // init events jQuery(_uiNodeCont).on('TableAjax:render', priv.onRender); jQuery(window).on('resize', priv.onWindowResize) } priv.initialRender();// set up _uiNode$... priv.options.types.string = ((priv.options.types || {}).string || {}); priv.options.types.number = ((priv.options.types || {}).number || {}); priv.options.types.bool = ((priv.options.types || {}).bool || {}); priv.options.types.date = ((priv.options.types || {}).date || {}); if (priv.options.mapEditorContainer != 'dock' && priv.options.mapEditorContainer != 'window') { priv.options.mapEditorContainer = 'window'; } if (priv.options.exportFields) { $.each(priv.options.exportFields, function(ind, col) { _exportFieldsSelect[col] = true; }); } _state._forceFilterQuery = p5Utils__objectToQueryWithKeyPrefix(priv.options.forceFilterInit, 'f_') var filterStore = createFilterStoreWithInitialData(priv.options.filterInit || {}); priv.options.filterStore = createStoreWithThunkMiddleware(filterStore) priv.options.filterActions = filterActions() // priv.options._filterState = Object.assign({}, priv.options.filterStore.getState()) var curFilterState = priv.options.filterStore.getState() _state._filterQuery = p5Utils__mapToQueryWithKeyPrefix(curFilterState.filter, 'f_') _state._specialFilterQuery = p5Utils__mapToQueryWithKeyPrefix(curFilterState.specialFilter, 'sf_') _state._currSortCol = curFilterState.currSortCol; _state._currSortFlip = curFilterState.currSortFlip; DBG && console.log('TODO:INIT: ', { _state }); priv.options.filterStore.subscribe(function () { curState = priv.options.filterStore.getState() var curFilterQuery = p5Utils__mapToQueryWithKeyPrefix(curState.filter, 'f_') var curSpecialFilterQuery = p5Utils__mapToQueryWithKeyPrefix(curState.specialFilter, 'sf_') var needFetchData = ( curFilterQuery !== _state._filterQuery || curSpecialFilterQuery !== _state._specialFilterQuery || curState.currSortCol !== _state._currSortCol || curState.currSortFlip !== _state._currSortFlip ); DBG && console.log('TODO:filtersUpdated - FETCH_DATA: ', { _state, curState }); _state._filterQuery = curFilterQuery; _state._specialFilterQuery = curSpecialFilterQuery; _state._currSortCol = curState.currSortCol; _state._currSortFlip = curState.currSortFlip; if (needFetchData) { DBG && console.log('TODO:filtersUpdated - FETCH_DATA: ', { curFilterQuery, curSpecialFilterQuery }); priv.loadPage(0) } }) if (priv.options.checkboxes) { priv.options.selectedStore = createStoreWithThunkMiddleware(selectedStore) priv.options.selectedActions = selectedActions(idContext = priv.options.checkboxIdContext) if (_uiNodeSelectedInfo) { // must run after priv.initialRender(); - _uiNodeSelectedInfo must exists ReactDOM.render( h(P5UI__TableAjaxSelectedInfo, { namespace: priv.options.namespace, store: priv.options.selectedStore, actions: priv.options.selectedActions, onSelectAllMatching: function () { var filterQuery = ''; filterQuery += (_state._filterQuery) ? "&" + _state._filterQuery : ""; filterQuery += (_state._specialFilterQuery) ? "&" + _state._specialFilterQuery : ""; filterQuery += (_state._forceFilterQuery) ? "&" + _state._forceFilterQuery : ""; priv.options.selectedStore.dispatch( priv.options.selectedActions.selectAllMatchingFilter(priv.options.namespace, filterQuery) ); } }), _uiNodeSelectedInfo ); } } else { if (_uiNodeSelectedInfo) { // jQuery('.').appendTo(_uiNodeSelectedInfo); jQuery('.').appendTo(_uiNodeSelectedInfo); } } if (location.hash) { priv.options.router() } else { priv.update(priv.options.router) } if (typeof priv.options.router == "function") { $(window).bind('hashchange', function() { priv.options.router.apply(this); }); } }; priv.onRender = function(e) { if (priv.options.debug || DBG) console.log('onRender.arguments:', arguments.length, arguments, 'e:', e); // console.log("priv.onRender arguments:", arguments); // console.trace(); if (arguments.length > 1) { for (var i=1; i